summaryrefslogtreecommitdiff
path: root/ACE/ace
diff options
context:
space:
mode:
authorWilliam R. Otte <wotte@dre.vanderbilt.edu>2008-03-04 14:51:23 +0000
committerWilliam R. Otte <wotte@dre.vanderbilt.edu>2008-03-04 14:51:23 +0000
commit99aa8c60282c7b8072eb35eb9ac815702f5bf586 (patch)
treebda96bf8c3a4c2875a083d7b16720533c8ffeaf4 /ACE/ace
parentc4078c377d74290ebe4e66da0b4975da91732376 (diff)
downloadATCD-99aa8c60282c7b8072eb35eb9ac815702f5bf586.tar.gz
undoing accidental deletion
Diffstat (limited to 'ACE/ace')
-rw-r--r--ACE/ace/ACE.cpp3409
-rw-r--r--ACE/ace/ACE.h825
-rw-r--r--ACE/ace/ACE.inl350
-rw-r--r--ACE/ace/ACE.pc.in10
-rw-r--r--ACE/ace/ACE_crc32.cpp161
-rw-r--r--ACE/ace/ACE_crc_ccitt.cpp128
-rw-r--r--ACE/ace/ACE_export.h76
-rw-r--r--ACE/ace/ARGV.cpp359
-rw-r--r--ACE/ace/ARGV.h306
-rw-r--r--ACE/ace/ARGV.inl104
-rw-r--r--ACE/ace/ATM_Acceptor.cpp309
-rw-r--r--ACE/ace/ATM_Acceptor.h123
-rw-r--r--ACE/ace/ATM_Acceptor.inl43
-rw-r--r--ACE/ace/ATM_Addr.cpp522
-rw-r--r--ACE/ace/ATM_Addr.h197
-rw-r--r--ACE/ace/ATM_Addr.inl37
-rw-r--r--ACE/ace/ATM_Connector.cpp138
-rw-r--r--ACE/ace/ATM_Connector.h164
-rw-r--r--ACE/ace/ATM_Connector.inl132
-rw-r--r--ACE/ace/ATM_Params.cpp20
-rw-r--r--ACE/ace/ATM_Params.h214
-rw-r--r--ACE/ace/ATM_Params.inl235
-rw-r--r--ACE/ace/ATM_QoS.cpp631
-rw-r--r--ACE/ace/ATM_QoS.h115
-rw-r--r--ACE/ace/ATM_QoS.inl29
-rw-r--r--ACE/ace/ATM_Stream.cpp290
-rw-r--r--ACE/ace/ATM_Stream.h107
-rw-r--r--ACE/ace/ATM_Stream.inl133
-rw-r--r--ACE/ace/Acceptor.cpp1226
-rw-r--r--ACE/ace/Acceptor.h684
-rw-r--r--ACE/ace/Activation_Queue.cpp138
-rw-r--r--ACE/ace/Activation_Queue.h173
-rw-r--r--ACE/ace/Activation_Queue.inl31
-rw-r--r--ACE/ace/Active_Map_Manager.cpp9
-rw-r--r--ACE/ace/Active_Map_Manager.h116
-rw-r--r--ACE/ace/Active_Map_Manager.inl95
-rw-r--r--ACE/ace/Active_Map_Manager_T.cpp22
-rw-r--r--ACE/ace/Active_Map_Manager_T.h211
-rw-r--r--ACE/ace/Active_Map_Manager_T.inl311
-rw-r--r--ACE/ace/Addr.cpp73
-rw-r--r--ACE/ace/Addr.h104
-rw-r--r--ACE/ace/Addr.inl61
-rw-r--r--ACE/ace/Arg_Shifter.cpp230
-rw-r--r--ACE/ace/Arg_Shifter.h221
-rw-r--r--ACE/ace/Argv_Type_Converter.cpp204
-rw-r--r--ACE/ace/Argv_Type_Converter.h119
-rw-r--r--ACE/ace/Argv_Type_Converter.inl44
-rw-r--r--ACE/ace/Array.h29
-rw-r--r--ACE/ace/Array_Base.cpp235
-rw-r--r--ACE/ace/Array_Base.h256
-rw-r--r--ACE/ace/Array_Base.inl146
-rw-r--r--ACE/ace/Array_Map.cpp299
-rw-r--r--ACE/ace/Array_Map.h300
-rw-r--r--ACE/ace/Array_Map.inl133
-rw-r--r--ACE/ace/Assert.cpp24
-rw-r--r--ACE/ace/Assert.h38
-rw-r--r--ACE/ace/Asynch_Acceptor.cpp516
-rw-r--r--ACE/ace/Asynch_Acceptor.h281
-rw-r--r--ACE/ace/Asynch_Connector.cpp296
-rw-r--r--ACE/ace/Asynch_Connector.h171
-rw-r--r--ACE/ace/Asynch_IO.cpp1411
-rw-r--r--ACE/ace/Asynch_IO.h1690
-rw-r--r--ACE/ace/Asynch_IO_Impl.cpp117
-rw-r--r--ACE/ace/Asynch_IO_Impl.h816
-rw-r--r--ACE/ace/Asynch_IO_Impl.inl106
-rw-r--r--ACE/ace/Asynch_Pseudo_Task.cpp130
-rw-r--r--ACE/ace/Asynch_Pseudo_Task.h73
-rw-r--r--ACE/ace/Atomic_Op.cpp310
-rw-r--r--ACE/ace/Atomic_Op.h260
-rw-r--r--ACE/ace/Atomic_Op.inl335
-rw-r--r--ACE/ace/Atomic_Op_Sparc.c187
-rw-r--r--ACE/ace/Atomic_Op_Sparc.h14
-rw-r--r--ACE/ace/Atomic_Op_T.cpp82
-rw-r--r--ACE/ace/Atomic_Op_T.h369
-rw-r--r--ACE/ace/Atomic_Op_T.inl340
-rw-r--r--ACE/ace/Auto_Event.cpp49
-rw-r--r--ACE/ace/Auto_Event.h73
-rw-r--r--ACE/ace/Auto_Event.inl12
-rw-r--r--ACE/ace/Auto_Functor.cpp39
-rw-r--r--ACE/ace/Auto_Functor.h127
-rw-r--r--ACE/ace/Auto_Functor.inl134
-rw-r--r--ACE/ace/Auto_IncDec_T.cpp34
-rw-r--r--ACE/ace/Auto_IncDec_T.h91
-rw-r--r--ACE/ace/Auto_IncDec_T.inl25
-rw-r--r--ACE/ace/Auto_Ptr.cpp21
-rw-r--r--ACE/ace/Auto_Ptr.h242
-rw-r--r--ACE/ace/Auto_Ptr.inl171
-rw-r--r--ACE/ace/Barrier.cpp197
-rw-r--r--ACE/ace/Barrier.h215
-rw-r--r--ACE/ace/Barrier.inl22
-rw-r--r--ACE/ace/Base_Thread_Adapter.cpp120
-rw-r--r--ACE/ace/Base_Thread_Adapter.h186
-rw-r--r--ACE/ace/Base_Thread_Adapter.inl48
-rw-r--r--ACE/ace/Based_Pointer_Repository.cpp119
-rw-r--r--ACE/ace/Based_Pointer_Repository.h91
-rw-r--r--ACE/ace/Based_Pointer_T.cpp121
-rw-r--r--ACE/ace/Based_Pointer_T.h205
-rw-r--r--ACE/ace/Based_Pointer_T.inl139
-rw-r--r--ACE/ace/Basic_Stats.cpp78
-rw-r--r--ACE/ace/Basic_Stats.h87
-rw-r--r--ACE/ace/Basic_Stats.inl53
-rw-r--r--ACE/ace/Basic_Types.cpp139
-rw-r--r--ACE/ace/Basic_Types.h890
-rw-r--r--ACE/ace/Basic_Types.inl954
-rw-r--r--ACE/ace/Bound_Ptr.h388
-rw-r--r--ACE/ace/Bound_Ptr.inl494
-rw-r--r--ACE/ace/CDR_Base.cpp799
-rw-r--r--ACE/ace/CDR_Base.h353
-rw-r--r--ACE/ace/CDR_Base.inl255
-rw-r--r--ACE/ace/CDR_Size.cpp244
-rw-r--r--ACE/ace/CDR_Size.h241
-rw-r--r--ACE/ace/CDR_Size.inl424
-rw-r--r--ACE/ace/CDR_Stream.cpp1892
-rw-r--r--ACE/ace/CDR_Stream.h1364
-rw-r--r--ACE/ace/CDR_Stream.inl1700
-rw-r--r--ACE/ace/CE_Screen_Output.cpp158
-rw-r--r--ACE/ace/CE_Screen_Output.h109
-rw-r--r--ACE/ace/CORBA_macros.h575
-rw-r--r--ACE/ace/Cache_Map_Manager_T.cpp420
-rw-r--r--ACE/ace/Cache_Map_Manager_T.h405
-rw-r--r--ACE/ace/Cache_Map_Manager_T.inl245
-rw-r--r--ACE/ace/Cached_Connect_Strategy_T.cpp734
-rw-r--r--ACE/ace/Cached_Connect_Strategy_T.h262
-rw-r--r--ACE/ace/Caching_Strategies_T.cpp59
-rw-r--r--ACE/ace/Caching_Strategies_T.h552
-rw-r--r--ACE/ace/Caching_Strategies_T.inl456
-rw-r--r--ACE/ace/Caching_Utility_T.cpp499
-rw-r--r--ACE/ace/Caching_Utility_T.h347
-rw-r--r--ACE/ace/Capabilities.cpp355
-rw-r--r--ACE/ace/Capabilities.h221
-rw-r--r--ACE/ace/Capabilities.inl52
-rw-r--r--ACE/ace/Cleanup.cpp192
-rw-r--r--ACE/ace/Cleanup.h137
-rw-r--r--ACE/ace/Cleanup.inl12
-rw-r--r--ACE/ace/Cleanup_Strategies_T.cpp95
-rw-r--r--ACE/ace/Cleanup_Strategies_T.h155
-rw-r--r--ACE/ace/Codecs.cpp234
-rw-r--r--ACE/ace/Codecs.h121
-rw-r--r--ACE/ace/Codeset_IBM1047.cpp312
-rw-r--r--ACE/ace/Codeset_IBM1047.h128
-rw-r--r--ACE/ace/Codeset_Registry.cpp111
-rw-r--r--ACE/ace/Codeset_Registry.h104
-rw-r--r--ACE/ace/Codeset_Registry.inl102
-rw-r--r--ACE/ace/Codeset_Registry_db.cpp29
-rw-r--r--ACE/ace/Codeset_Symbols.h220
-rw-r--r--ACE/ace/Condition_Recursive_Thread_Mutex.cpp129
-rw-r--r--ACE/ace/Condition_Recursive_Thread_Mutex.h118
-rw-r--r--ACE/ace/Condition_T.cpp123
-rw-r--r--ACE/ace/Condition_T.h167
-rw-r--r--ACE/ace/Condition_T.inl51
-rw-r--r--ACE/ace/Condition_Thread_Mutex.cpp126
-rw-r--r--ACE/ace/Condition_Thread_Mutex.h190
-rw-r--r--ACE/ace/Condition_Thread_Mutex.inl74
-rw-r--r--ACE/ace/Configuration.cpp2148
-rw-r--r--ACE/ace/Configuration.h896
-rw-r--r--ACE/ace/Configuration.inl13
-rw-r--r--ACE/ace/Configuration_Import_Export.cpp670
-rw-r--r--ACE/ace/Configuration_Import_Export.h215
-rw-r--r--ACE/ace/Connection_Recycling_Strategy.cpp13
-rw-r--r--ACE/ace/Connection_Recycling_Strategy.h63
-rw-r--r--ACE/ace/Connector.cpp964
-rw-r--r--ACE/ace/Connector.h563
-rw-r--r--ACE/ace/Containers.cpp12
-rw-r--r--ACE/ace/Containers.h71
-rw-r--r--ACE/ace/Containers.inl25
-rw-r--r--ACE/ace/Containers_T.cpp1930
-rw-r--r--ACE/ace/Containers_T.h2024
-rw-r--r--ACE/ace/Containers_T.inl479
-rw-r--r--ACE/ace/Copy_Disabled.cpp23
-rw-r--r--ACE/ace/Copy_Disabled.h65
-rw-r--r--ACE/ace/Countdown_Time.cpp66
-rw-r--r--ACE/ace/Countdown_Time.h80
-rw-r--r--ACE/ace/DEV.cpp43
-rw-r--r--ACE/ace/DEV.h78
-rw-r--r--ACE/ace/DEV.inl18
-rw-r--r--ACE/ace/DEV_Addr.cpp108
-rw-r--r--ACE/ace/DEV_Addr.h90
-rw-r--r--ACE/ace/DEV_Addr.inl51
-rw-r--r--ACE/ace/DEV_Connector.cpp53
-rw-r--r--ACE/ace/DEV_Connector.h110
-rw-r--r--ACE/ace/DEV_Connector.inl34
-rw-r--r--ACE/ace/DEV_IO.cpp131
-rw-r--r--ACE/ace/DEV_IO.h185
-rw-r--r--ACE/ace/DEV_IO.inl126
-rw-r--r--ACE/ace/DLL.cpp267
-rw-r--r--ACE/ace/DLL.h196
-rw-r--r--ACE/ace/DLL_Manager.cpp787
-rw-r--r--ACE/ace/DLL_Manager.h269
-rw-r--r--ACE/ace/Date_Time.cpp10
-rw-r--r--ACE/ace/Date_Time.h125
-rw-r--r--ACE/ace/Date_Time.inl219
-rw-r--r--ACE/ace/Default_Constants.h573
-rw-r--r--ACE/ace/Dev_Poll_Reactor.cpp2513
-rw-r--r--ACE/ace/Dev_Poll_Reactor.h1252
-rw-r--r--ACE/ace/Dev_Poll_Reactor.inl228
-rw-r--r--ACE/ace/Dirent.cpp7
-rw-r--r--ACE/ace/Dirent.h122
-rw-r--r--ACE/ace/Dirent.inl99
-rw-r--r--ACE/ace/Dirent_Selector.cpp59
-rw-r--r--ACE/ace/Dirent_Selector.h75
-rw-r--r--ACE/ace/Dirent_Selector.inl19
-rw-r--r--ACE/ace/Dump.cpp141
-rw-r--r--ACE/ace/Dump.h172
-rw-r--r--ACE/ace/Dump_T.cpp48
-rw-r--r--ACE/ace/Dump_T.h82
-rw-r--r--ACE/ace/Dynamic.cpp34
-rw-r--r--ACE/ace/Dynamic.h75
-rw-r--r--ACE/ace/Dynamic.inl34
-rw-r--r--ACE/ace/Dynamic_Message_Strategy.cpp205
-rw-r--r--ACE/ace/Dynamic_Message_Strategy.h217
-rw-r--r--ACE/ace/Dynamic_Message_Strategy.inl75
-rw-r--r--ACE/ace/Dynamic_Service.cpp63
-rw-r--r--ACE/ace/Dynamic_Service.h89
-rw-r--r--ACE/ace/Dynamic_Service.inl40
-rw-r--r--ACE/ace/Dynamic_Service_Base.cpp101
-rw-r--r--ACE/ace/Dynamic_Service_Base.h74
-rw-r--r--ACE/ace/Dynamic_Service_Dependency.cpp51
-rw-r--r--ACE/ace/Dynamic_Service_Dependency.h70
-rw-r--r--ACE/ace/Encoding_Converter.cpp12
-rw-r--r--ACE/ace/Encoding_Converter.h70
-rw-r--r--ACE/ace/Encoding_Converter_Factory.cpp74
-rw-r--r--ACE/ace/Encoding_Converter_Factory.h54
-rw-r--r--ACE/ace/Env_Value_T.cpp12
-rw-r--r--ACE/ace/Env_Value_T.h166
-rw-r--r--ACE/ace/Env_Value_T.inl60
-rw-r--r--ACE/ace/Event.cpp93
-rw-r--r--ACE/ace/Event.h143
-rw-r--r--ACE/ace/Event.inl18
-rw-r--r--ACE/ace/Event_Handler.cpp396
-rw-r--r--ACE/ace/Event_Handler.h388
-rw-r--r--ACE/ace/Event_Handler.inl12
-rw-r--r--ACE/ace/Event_Handler_T.cpp125
-rw-r--r--ACE/ace/Event_Handler_T.h191
-rw-r--r--ACE/ace/Event_Handler_T.inl135
-rw-r--r--ACE/ace/Exception_Macros.h55
-rw-r--r--ACE/ace/FIFO.cpp78
-rw-r--r--ACE/ace/FIFO.h85
-rw-r--r--ACE/ace/FIFO.inl25
-rw-r--r--ACE/ace/FIFO_Recv.cpp88
-rw-r--r--ACE/ace/FIFO_Recv.h85
-rw-r--r--ACE/ace/FIFO_Recv.inl24
-rw-r--r--ACE/ace/FIFO_Recv_Msg.cpp67
-rw-r--r--ACE/ace/FIFO_Recv_Msg.h138
-rw-r--r--ACE/ace/FIFO_Recv_Msg.inl111
-rw-r--r--ACE/ace/FIFO_Send.cpp58
-rw-r--r--ACE/ace/FIFO_Send.h75
-rw-r--r--ACE/ace/FIFO_Send.inl24
-rw-r--r--ACE/ace/FIFO_Send_Msg.cpp80
-rw-r--r--ACE/ace/FIFO_Send_Msg.h91
-rw-r--r--ACE/ace/FIFO_Send_Msg.inl53
-rw-r--r--ACE/ace/FILE.cpp147
-rw-r--r--ACE/ace/FILE.h139
-rw-r--r--ACE/ace/FILE.inl18
-rw-r--r--ACE/ace/FILE_Addr.cpp124
-rw-r--r--ACE/ace/FILE_Addr.h89
-rw-r--r--ACE/ace/FILE_Addr.inl34
-rw-r--r--ACE/ace/FILE_Connector.cpp84
-rw-r--r--ACE/ace/FILE_Connector.h113
-rw-r--r--ACE/ace/FILE_Connector.inl36
-rw-r--r--ACE/ace/FILE_IO.cpp142
-rw-r--r--ACE/ace/FILE_IO.h170
-rw-r--r--ACE/ace/FILE_IO.inl152
-rw-r--r--ACE/ace/File_Lock.cpp72
-rw-r--r--ACE/ace/File_Lock.h170
-rw-r--r--ACE/ace/File_Lock.inl96
-rw-r--r--ACE/ace/Filecache.cpp754
-rw-r--r--ACE/ace/Filecache.h353
-rw-r--r--ACE/ace/FlReactor/ACE_FlReactor.pc.in11
-rw-r--r--ACE/ace/FlReactor/ACE_FlReactor_export.h58
-rw-r--r--ACE/ace/FlReactor/FlReactor.cpp330
-rw-r--r--ACE/ace/FlReactor/FlReactor.h110
-rw-r--r--ACE/ace/Flag_Manip.cpp95
-rw-r--r--ACE/ace/Flag_Manip.h58
-rw-r--r--ACE/ace/Flag_Manip.inl26
-rw-r--r--ACE/ace/FoxReactor/ACE_FoxReactor.pc.in11
-rw-r--r--ACE/ace/FoxReactor/ACE_FoxReactor_export.h58
-rw-r--r--ACE/ace/FoxReactor/FoxReactor.cpp337
-rw-r--r--ACE/ace/FoxReactor/FoxReactor.h115
-rw-r--r--ACE/ace/Framework_Component.cpp280
-rw-r--r--ACE/ace/Framework_Component.h210
-rw-r--r--ACE/ace/Framework_Component.inl39
-rw-r--r--ACE/ace/Framework_Component_T.cpp33
-rw-r--r--ACE/ace/Framework_Component_T.h71
-rw-r--r--ACE/ace/Free_List.cpp157
-rw-r--r--ACE/ace/Free_List.h150
-rw-r--r--ACE/ace/Functor.cpp43
-rw-r--r--ACE/ace/Functor.h593
-rw-r--r--ACE/ace/Functor.inl284
-rw-r--r--ACE/ace/Functor_String.cpp7
-rw-r--r--ACE/ace/Functor_String.h141
-rw-r--r--ACE/ace/Functor_String.inl56
-rw-r--r--ACE/ace/Functor_T.cpp49
-rw-r--r--ACE/ace/Functor_T.h158
-rw-r--r--ACE/ace/Functor_T.inl42
-rw-r--r--ACE/ace/Future.cpp436
-rw-r--r--ACE/ace/Future.h387
-rw-r--r--ACE/ace/Future_Set.cpp136
-rw-r--r--ACE/ace/Future_Set.h146
-rw-r--r--ACE/ace/Get_Opt.cpp730
-rw-r--r--ACE/ace/Get_Opt.h474
-rw-r--r--ACE/ace/Get_Opt.inl43
-rw-r--r--ACE/ace/Global_Macros.h1133
-rw-r--r--ACE/ace/Guard_T.cpp61
-rw-r--r--ACE/ace/Guard_T.h365
-rw-r--r--ACE/ace/Guard_T.inl170
-rw-r--r--ACE/ace/Handle_Gobbler.h68
-rw-r--r--ACE/ace/Handle_Gobbler.inl78
-rw-r--r--ACE/ace/Handle_Ops.cpp48
-rw-r--r--ACE/ace/Handle_Ops.h50
-rw-r--r--ACE/ace/Handle_Set.cpp570
-rw-r--r--ACE/ace/Handle_Set.h240
-rw-r--r--ACE/ace/Handle_Set.inl193
-rw-r--r--ACE/ace/Hash_Cache_Map_Manager_T.cpp232
-rw-r--r--ACE/ace/Hash_Cache_Map_Manager_T.h214
-rw-r--r--ACE/ace/Hash_Cache_Map_Manager_T.inl73
-rw-r--r--ACE/ace/Hash_Map_Manager.h31
-rw-r--r--ACE/ace/Hash_Map_Manager_T.cpp530
-rw-r--r--ACE/ace/Hash_Map_Manager_T.h1274
-rw-r--r--ACE/ace/Hash_Map_Manager_T.inl1253
-rw-r--r--ACE/ace/Hash_Map_With_Allocator_T.cpp35
-rw-r--r--ACE/ace/Hash_Map_With_Allocator_T.h112
-rw-r--r--ACE/ace/Hash_Map_With_Allocator_T.inl82
-rw-r--r--ACE/ace/Hash_Multi_Map_Manager_T.cpp605
-rw-r--r--ACE/ace/Hash_Multi_Map_Manager_T.h967
-rw-r--r--ACE/ace/Hash_Multi_Map_Manager_T.inl994
-rw-r--r--ACE/ace/Hashable.cpp36
-rw-r--r--ACE/ace/Hashable.h65
-rw-r--r--ACE/ace/Hashable.inl14
-rw-r--r--ACE/ace/High_Res_Timer.cpp537
-rw-r--r--ACE/ace/High_Res_Timer.h315
-rw-r--r--ACE/ace/High_Res_Timer.inl154
-rw-r--r--ACE/ace/ICMP_Socket.cpp186
-rw-r--r--ACE/ace/ICMP_Socket.h110
-rw-r--r--ACE/ace/INET_Addr.cpp1168
-rw-r--r--ACE/ace/INET_Addr.h399
-rw-r--r--ACE/ace/INET_Addr.inl257
-rw-r--r--ACE/ace/IOStream.cpp665
-rw-r--r--ACE/ace/IOStream.h512
-rw-r--r--ACE/ace/IOStream_T.cpp247
-rw-r--r--ACE/ace/IOStream_T.h297
-rw-r--r--ACE/ace/IOStream_T.inl123
-rw-r--r--ACE/ace/IO_Cntl_Msg.cpp51
-rw-r--r--ACE/ace/IO_Cntl_Msg.h112
-rw-r--r--ACE/ace/IO_Cntl_Msg.inl61
-rw-r--r--ACE/ace/IO_SAP.cpp142
-rw-r--r--ACE/ace/IO_SAP.h96
-rw-r--r--ACE/ace/IO_SAP.inl42
-rw-r--r--ACE/ace/IPC_SAP.cpp193
-rw-r--r--ACE/ace/IPC_SAP.h96
-rw-r--r--ACE/ace/IPC_SAP.inl40
-rw-r--r--ACE/ace/If_Then_Else.h89
-rw-r--r--ACE/ace/Init_ACE.cpp45
-rw-r--r--ACE/ace/Init_ACE.h62
-rw-r--r--ACE/ace/Intrusive_List.cpp153
-rw-r--r--ACE/ace/Intrusive_List.h144
-rw-r--r--ACE/ace/Intrusive_List.inl40
-rw-r--r--ACE/ace/Intrusive_List_Node.cpp27
-rw-r--r--ACE/ace/Intrusive_List_Node.h85
-rw-r--r--ACE/ace/Intrusive_List_Node.inl31
-rw-r--r--ACE/ace/LOCK_SOCK_Acceptor.cpp35
-rw-r--r--ACE/ace/LOCK_SOCK_Acceptor.h67
-rw-r--r--ACE/ace/LSOCK.cpp181
-rw-r--r--ACE/ace/LSOCK.h84
-rw-r--r--ACE/ace/LSOCK.inl43
-rw-r--r--ACE/ace/LSOCK_Acceptor.cpp143
-rw-r--r--ACE/ace/LSOCK_Acceptor.h95
-rw-r--r--ACE/ace/LSOCK_CODgram.cpp62
-rw-r--r--ACE/ace/LSOCK_CODgram.h78
-rw-r--r--ACE/ace/LSOCK_CODgram.inl30
-rw-r--r--ACE/ace/LSOCK_Connector.cpp59
-rw-r--r--ACE/ace/LSOCK_Connector.h91
-rw-r--r--ACE/ace/LSOCK_Connector.inl27
-rw-r--r--ACE/ace/LSOCK_Dgram.cpp71
-rw-r--r--ACE/ace/LSOCK_Dgram.h74
-rw-r--r--ACE/ace/LSOCK_Dgram.inl22
-rw-r--r--ACE/ace/LSOCK_Stream.cpp137
-rw-r--r--ACE/ace/LSOCK_Stream.h82
-rw-r--r--ACE/ace/LSOCK_Stream.inl25
-rw-r--r--ACE/ace/Lib_Find.cpp769
-rw-r--r--ACE/ace/Lib_Find.h131
-rw-r--r--ACE/ace/Local_Memory_Pool.cpp144
-rw-r--r--ACE/ace/Local_Memory_Pool.h133
-rw-r--r--ACE/ace/Local_Name_Space.cpp169
-rw-r--r--ACE/ace/Local_Name_Space.h132
-rw-r--r--ACE/ace/Local_Name_Space_T.cpp966
-rw-r--r--ACE/ace/Local_Name_Space_T.h280
-rw-r--r--ACE/ace/Local_Tokens.cpp1623
-rw-r--r--ACE/ace/Local_Tokens.h1121
-rw-r--r--ACE/ace/Local_Tokens.inl289
-rw-r--r--ACE/ace/Lock.cpp88
-rw-r--r--ACE/ace/Lock.h161
-rw-r--r--ACE/ace/Lock.inl12
-rw-r--r--ACE/ace/Lock_Adapter_T.cpp117
-rw-r--r--ACE/ace/Lock_Adapter_T.h123
-rw-r--r--ACE/ace/Lock_Adapter_T.inl16
-rw-r--r--ACE/ace/Log_Msg.cpp2510
-rw-r--r--ACE/ace/Log_Msg.h746
-rw-r--r--ACE/ace/Log_Msg.inl235
-rw-r--r--ACE/ace/Log_Msg_Backend.cpp14
-rw-r--r--ACE/ace/Log_Msg_Backend.h88
-rw-r--r--ACE/ace/Log_Msg_Callback.cpp13
-rw-r--r--ACE/ace/Log_Msg_Callback.h69
-rw-r--r--ACE/ace/Log_Msg_IPC.cpp111
-rw-r--r--ACE/ace/Log_Msg_IPC.h79
-rw-r--r--ACE/ace/Log_Msg_NT_Event_Log.cpp162
-rw-r--r--ACE/ace/Log_Msg_NT_Event_Log.h72
-rw-r--r--ACE/ace/Log_Msg_UNIX_Syslog.cpp207
-rw-r--r--ACE/ace/Log_Msg_UNIX_Syslog.h76
-rw-r--r--ACE/ace/Log_Priority.h85
-rw-r--r--ACE/ace/Log_Record.cpp412
-rw-r--r--ACE/ace/Log_Record.h223
-rw-r--r--ACE/ace/Log_Record.inl123
-rw-r--r--ACE/ace/Logging_Strategy.cpp566
-rw-r--r--ACE/ace/Logging_Strategy.h195
-rw-r--r--ACE/ace/MEM_Acceptor.cpp265
-rw-r--r--ACE/ace/MEM_Acceptor.h192
-rw-r--r--ACE/ace/MEM_Acceptor.inl103
-rw-r--r--ACE/ace/MEM_Addr.cpp170
-rw-r--r--ACE/ace/MEM_Addr.h155
-rw-r--r--ACE/ace/MEM_Addr.inl111
-rw-r--r--ACE/ace/MEM_Connector.cpp149
-rw-r--r--ACE/ace/MEM_Connector.h179
-rw-r--r--ACE/ace/MEM_Connector.inl30
-rw-r--r--ACE/ace/MEM_IO.cpp541
-rw-r--r--ACE/ace/MEM_IO.h310
-rw-r--r--ACE/ace/MEM_IO.inl233
-rw-r--r--ACE/ace/MEM_SAP.cpp97
-rw-r--r--ACE/ace/MEM_SAP.h169
-rw-r--r--ACE/ace/MEM_SAP.inl64
-rw-r--r--ACE/ace/MEM_Stream.cpp47
-rw-r--r--ACE/ace/MEM_Stream.h158
-rw-r--r--ACE/ace/MEM_Stream.inl180
-rw-r--r--ACE/ace/MMAP_Memory_Pool.cpp578
-rw-r--r--ACE/ace/MMAP_Memory_Pool.h327
-rw-r--r--ACE/ace/MMAP_Memory_Pool.inl21
-rw-r--r--ACE/ace/Makefile.am1419
-rw-r--r--ACE/ace/Malloc.cpp187
-rw-r--r--ACE/ace/Malloc.h396
-rw-r--r--ACE/ace/Malloc.inl26
-rw-r--r--ACE/ace/Malloc_Allocator.cpp361
-rw-r--r--ACE/ace/Malloc_Allocator.h146
-rw-r--r--ACE/ace/Malloc_Allocator.inl16
-rw-r--r--ACE/ace/Malloc_Base.h168
-rw-r--r--ACE/ace/Malloc_T.cpp1262
-rw-r--r--ACE/ace/Malloc_T.h931
-rw-r--r--ACE/ace/Malloc_T.inl184
-rw-r--r--ACE/ace/Managed_Object.cpp25
-rw-r--r--ACE/ace/Managed_Object.h168
-rw-r--r--ACE/ace/Managed_Object.inl23
-rw-r--r--ACE/ace/Manual_Event.cpp48
-rw-r--r--ACE/ace/Manual_Event.h74
-rw-r--r--ACE/ace/Manual_Event.inl12
-rw-r--r--ACE/ace/Map.h32
-rw-r--r--ACE/ace/Map_Manager.cpp701
-rw-r--r--ACE/ace/Map_Manager.h719
-rw-r--r--ACE/ace/Map_Manager.inl729
-rw-r--r--ACE/ace/Map_T.cpp1343
-rw-r--r--ACE/ace/Map_T.h1611
-rw-r--r--ACE/ace/Map_T.inl415
-rw-r--r--ACE/ace/Mem_Map.cpp310
-rw-r--r--ACE/ace/Mem_Map.h235
-rw-r--r--ACE/ace/Mem_Map.inl238
-rw-r--r--ACE/ace/Memory_Pool.h31
-rw-r--r--ACE/ace/Message_Block.cpp1273
-rw-r--r--ACE/ace/Message_Block.h871
-rw-r--r--ACE/ace/Message_Block.inl508
-rw-r--r--ACE/ace/Message_Block_T.cpp54
-rw-r--r--ACE/ace/Message_Block_T.h88
-rw-r--r--ACE/ace/Message_Block_T.inl31
-rw-r--r--ACE/ace/Message_Queue.cpp28
-rw-r--r--ACE/ace/Message_Queue.h237
-rw-r--r--ACE/ace/Message_Queue.inl12
-rw-r--r--ACE/ace/Message_Queue_NT.cpp237
-rw-r--r--ACE/ace/Message_Queue_NT.h231
-rw-r--r--ACE/ace/Message_Queue_NT.inl131
-rw-r--r--ACE/ace/Message_Queue_T.cpp2814
-rw-r--r--ACE/ace/Message_Queue_T.h1476
-rw-r--r--ACE/ace/Message_Queue_Vx.cpp368
-rw-r--r--ACE/ace/Message_Queue_Vx.h227
-rw-r--r--ACE/ace/Message_Queue_Vx.inl19
-rw-r--r--ACE/ace/Method_Object.h38
-rw-r--r--ACE/ace/Method_Request.cpp30
-rw-r--r--ACE/ace/Method_Request.h100
-rw-r--r--ACE/ace/Metrics_Cache.h140
-rw-r--r--ACE/ace/Metrics_Cache_T.cpp237
-rw-r--r--ACE/ace/Metrics_Cache_T.h243
-rw-r--r--ACE/ace/Metrics_Cache_T.inl240
-rw-r--r--ACE/ace/Min_Max.h70
-rw-r--r--ACE/ace/Module.cpp273
-rw-r--r--ACE/ace/Module.h215
-rw-r--r--ACE/ace/Module.inl65
-rw-r--r--ACE/ace/Msg_WFMO_Reactor.cpp85
-rw-r--r--ACE/ace/Msg_WFMO_Reactor.h120
-rw-r--r--ACE/ace/Msg_WFMO_Reactor.inl35
-rw-r--r--ACE/ace/Multihomed_INET_Addr.cpp300
-rw-r--r--ACE/ace/Multihomed_INET_Addr.h198
-rw-r--r--ACE/ace/Multihomed_INET_Addr.inl15
-rw-r--r--ACE/ace/Mutex.cpp125
-rw-r--r--ACE/ace/Mutex.h192
-rw-r--r--ACE/ace/Mutex.inl175
-rw-r--r--ACE/ace/NT_Service.cpp618
-rw-r--r--ACE/ace/NT_Service.h439
-rw-r--r--ACE/ace/NT_Service.inl85
-rw-r--r--ACE/ace/Name_Proxy.cpp209
-rw-r--r--ACE/ace/Name_Proxy.h101
-rw-r--r--ACE/ace/Name_Request_Reply.cpp577
-rw-r--r--ACE/ace/Name_Request_Reply.h265
-rw-r--r--ACE/ace/Name_Space.cpp73
-rw-r--r--ACE/ace/Name_Space.h165
-rw-r--r--ACE/ace/Naming_Context.cpp647
-rw-r--r--ACE/ace/Naming_Context.h387
-rw-r--r--ACE/ace/Naming_Context.inl44
-rw-r--r--ACE/ace/Netlink_Addr.cpp68
-rw-r--r--ACE/ace/Netlink_Addr.h120
-rw-r--r--ACE/ace/Netlink_Addr.inl51
-rw-r--r--ACE/ace/Node.cpp46
-rw-r--r--ACE/ace/Node.h85
-rw-r--r--ACE/ace/Notification_Queue.cpp222
-rw-r--r--ACE/ace/Notification_Queue.h156
-rw-r--r--ACE/ace/Notification_Queue.inl47
-rw-r--r--ACE/ace/Notification_Strategy.cpp22
-rw-r--r--ACE/ace/Notification_Strategy.h75
-rw-r--r--ACE/ace/Notification_Strategy.inl31
-rw-r--r--ACE/ace/Null_Barrier.h59
-rw-r--r--ACE/ace/Null_Condition.h85
-rw-r--r--ACE/ace/Null_Mutex.h232
-rw-r--r--ACE/ace/Null_Semaphore.h105
-rw-r--r--ACE/ace/Numeric_Limits.h270
-rw-r--r--ACE/ace/OS.cpp53
-rw-r--r--ACE/ace/OS.h329
-rw-r--r--ACE/ace/OS.inl93
-rw-r--r--ACE/ace/OS_Dirent.h32
-rw-r--r--ACE/ace/OS_Errno.cpp47
-rw-r--r--ACE/ace/OS_Errno.h101
-rw-r--r--ACE/ace/OS_Errno.inl67
-rw-r--r--ACE/ace/OS_Log_Msg_Attributes.cpp9
-rw-r--r--ACE/ace/OS_Log_Msg_Attributes.h90
-rw-r--r--ACE/ace/OS_Log_Msg_Attributes.inl12
-rw-r--r--ACE/ace/OS_Memory.h338
-rw-r--r--ACE/ace/OS_NS_Thread.cpp5328
-rw-r--r--ACE/ace/OS_NS_Thread.h2026
-rw-r--r--ACE/ace/OS_NS_Thread.inl3636
-rw-r--r--ACE/ace/OS_NS_arpa_inet.cpp53
-rw-r--r--ACE/ace/OS_NS_arpa_inet.h74
-rw-r--r--ACE/ace/OS_NS_arpa_inet.inl98
-rw-r--r--ACE/ace/OS_NS_ctype.cpp11
-rw-r--r--ACE/ace/OS_NS_ctype.h130
-rw-r--r--ACE/ace/OS_NS_ctype.inl163
-rw-r--r--ACE/ace/OS_NS_dirent.cpp274
-rw-r--r--ACE/ace/OS_NS_dirent.h153
-rw-r--r--ACE/ace/OS_NS_dirent.inl184
-rw-r--r--ACE/ace/OS_NS_dlfcn.cpp10
-rw-r--r--ACE/ace/OS_NS_dlfcn.h69
-rw-r--r--ACE/ace/OS_NS_dlfcn.inl286
-rw-r--r--ACE/ace/OS_NS_errno.cpp11
-rw-r--r--ACE/ace/OS_NS_errno.h100
-rw-r--r--ACE/ace/OS_NS_errno.inl83
-rw-r--r--ACE/ace/OS_NS_fcntl.cpp245
-rw-r--r--ACE/ace/OS_NS_fcntl.h83
-rw-r--r--ACE/ace/OS_NS_fcntl.inl23
-rw-r--r--ACE/ace/OS_NS_macros.h114
-rw-r--r--ACE/ace/OS_NS_math.cpp10
-rw-r--r--ACE/ace/OS_NS_math.h115
-rw-r--r--ACE/ace/OS_NS_math.inl41
-rw-r--r--ACE/ace/OS_NS_netdb.cpp421
-rw-r--r--ACE/ace/OS_NS_netdb.h146
-rw-r--r--ACE/ace/OS_NS_netdb.inl750
-rw-r--r--ACE/ace/OS_NS_poll.cpp10
-rw-r--r--ACE/ace/OS_NS_poll.h66
-rw-r--r--ACE/ace/OS_NS_poll.inl45
-rw-r--r--ACE/ace/OS_NS_pwd.cpp10
-rw-r--r--ACE/ace/OS_NS_pwd.h81
-rw-r--r--ACE/ace/OS_NS_pwd.inl120
-rw-r--r--ACE/ace/OS_NS_regex.cpp10
-rw-r--r--ACE/ace/OS_NS_regex.h65
-rw-r--r--ACE/ace/OS_NS_regex.inl39
-rw-r--r--ACE/ace/OS_NS_signal.cpp26
-rw-r--r--ACE/ace/OS_NS_signal.h153
-rw-r--r--ACE/ace/OS_NS_signal.inl232
-rw-r--r--ACE/ace/OS_NS_stdio.cpp456
-rw-r--r--ACE/ace/OS_NS_stdio.h530
-rw-r--r--ACE/ace/OS_NS_stdio.inl1224
-rw-r--r--ACE/ace/OS_NS_stdlib.cpp801
-rw-r--r--ACE/ace/OS_NS_stdlib.h313
-rw-r--r--ACE/ace/OS_NS_stdlib.inl499
-rw-r--r--ACE/ace/OS_NS_string.cpp377
-rw-r--r--ACE/ace/OS_NS_string.h471
-rw-r--r--ACE/ace/OS_NS_string.inl560
-rw-r--r--ACE/ace/OS_NS_strings.cpp84
-rw-r--r--ACE/ace/OS_NS_strings.h86
-rw-r--r--ACE/ace/OS_NS_strings.inl59
-rw-r--r--ACE/ace/OS_NS_stropts.cpp195
-rw-r--r--ACE/ace/OS_NS_stropts.h172
-rw-r--r--ACE/ace/OS_NS_stropts.inl201
-rw-r--r--ACE/ace/OS_NS_sys_mman.cpp10
-rw-r--r--ACE/ace/OS_NS_sys_mman.h97
-rw-r--r--ACE/ace/OS_NS_sys_mman.inl302
-rw-r--r--ACE/ace/OS_NS_sys_msg.cpp10
-rw-r--r--ACE/ace/OS_NS_sys_msg.h77
-rw-r--r--ACE/ace/OS_NS_sys_msg.inl78
-rw-r--r--ACE/ace/OS_NS_sys_resource.cpp10
-rw-r--r--ACE/ace/OS_NS_sys_resource.h67
-rw-r--r--ACE/ace/OS_NS_sys_resource.inl98
-rw-r--r--ACE/ace/OS_NS_sys_select.cpp10
-rw-r--r--ACE/ace/OS_NS_sys_select.h77
-rw-r--r--ACE/ace/OS_NS_sys_select.inl80
-rw-r--r--ACE/ace/OS_NS_sys_sendfile.cpp53
-rw-r--r--ACE/ace/OS_NS_sys_sendfile.h65
-rw-r--r--ACE/ace/OS_NS_sys_sendfile.inl24
-rw-r--r--ACE/ace/OS_NS_sys_shm.cpp10
-rw-r--r--ACE/ace/OS_NS_sys_shm.h74
-rw-r--r--ACE/ace/OS_NS_sys_shm.inl76
-rw-r--r--ACE/ace/OS_NS_sys_socket.cpp161
-rw-r--r--ACE/ace/OS_NS_sys_socket.h302
-rw-r--r--ACE/ace/OS_NS_sys_socket.inl993
-rw-r--r--ACE/ace/OS_NS_sys_stat.cpp10
-rw-r--r--ACE/ace/OS_NS_sys_stat.h149
-rw-r--r--ACE/ace/OS_NS_sys_stat.inl292
-rw-r--r--ACE/ace/OS_NS_sys_time.cpp10
-rw-r--r--ACE/ace/OS_NS_sys_time.h69
-rw-r--r--ACE/ace/OS_NS_sys_time.inl96
-rw-r--r--ACE/ace/OS_NS_sys_uio.cpp130
-rw-r--r--ACE/ace/OS_NS_sys_uio.h80
-rw-r--r--ACE/ace/OS_NS_sys_uio.inl55
-rw-r--r--ACE/ace/OS_NS_sys_utsname.cpp237
-rw-r--r--ACE/ace/OS_NS_sys_utsname.h71
-rw-r--r--ACE/ace/OS_NS_sys_wait.cpp9
-rw-r--r--ACE/ace/OS_NS_sys_wait.h87
-rw-r--r--ACE/ace/OS_NS_sys_wait.inl105
-rw-r--r--ACE/ace/OS_NS_time.cpp634
-rw-r--r--ACE/ace/OS_NS_time.h288
-rw-r--r--ACE/ace/OS_NS_time.inl505
-rw-r--r--ACE/ace/OS_NS_unistd.cpp859
-rw-r--r--ACE/ace/OS_NS_unistd.h375
-rw-r--r--ACE/ace/OS_NS_unistd.inl1193
-rw-r--r--ACE/ace/OS_NS_wchar.cpp377
-rw-r--r--ACE/ace/OS_NS_wchar.h199
-rw-r--r--ACE/ace/OS_NS_wchar.inl87
-rw-r--r--ACE/ace/OS_QoS.cpp476
-rw-r--r--ACE/ace/OS_QoS.h449
-rw-r--r--ACE/ace/OS_String.h32
-rw-r--r--ACE/ace/OS_TLI.cpp9
-rw-r--r--ACE/ace/OS_TLI.h285
-rw-r--r--ACE/ace/OS_TLI.inl390
-rw-r--r--ACE/ace/OS_Thread_Adapter.cpp153
-rw-r--r--ACE/ace/OS_Thread_Adapter.h72
-rw-r--r--ACE/ace/OS_main.cpp127
-rw-r--r--ACE/ace/OS_main.h303
-rw-r--r--ACE/ace/Obchunk.cpp36
-rw-r--r--ACE/ace/Obchunk.h77
-rw-r--r--ACE/ace/Obchunk.inl12
-rw-r--r--ACE/ace/Object_Manager.cpp888
-rw-r--r--ACE/ace/Object_Manager.h466
-rw-r--r--ACE/ace/Object_Manager.inl40
-rw-r--r--ACE/ace/Object_Manager_Base.cpp506
-rw-r--r--ACE/ace/Object_Manager_Base.h248
-rw-r--r--ACE/ace/Obstack.h31
-rw-r--r--ACE/ace/Obstack_T.cpp226
-rw-r--r--ACE/ace/Obstack_T.h134
-rw-r--r--ACE/ace/Obstack_T.inl19
-rw-r--r--ACE/ace/PI_Malloc.cpp165
-rw-r--r--ACE/ace/PI_Malloc.h213
-rw-r--r--ACE/ace/PI_Malloc.inl33
-rw-r--r--ACE/ace/POSIX_Asynch_IO.cpp2416
-rw-r--r--ACE/ace/POSIX_Asynch_IO.h1302
-rw-r--r--ACE/ace/POSIX_CB_Proactor.cpp185
-rw-r--r--ACE/ace/POSIX_CB_Proactor.h97
-rw-r--r--ACE/ace/POSIX_Proactor.cpp2064
-rw-r--r--ACE/ace/POSIX_Proactor.h659
-rw-r--r--ACE/ace/POSIX_Proactor.inl13
-rw-r--r--ACE/ace/Pagefile_Memory_Pool.cpp384
-rw-r--r--ACE/ace/Pagefile_Memory_Pool.h201
-rw-r--r--ACE/ace/Pagefile_Memory_Pool.inl54
-rw-r--r--ACE/ace/Pair.h32
-rw-r--r--ACE/ace/Pair_T.cpp16
-rw-r--r--ACE/ace/Pair_T.h129
-rw-r--r--ACE/ace/Pair_T.inl90
-rw-r--r--ACE/ace/Parse_Node.cpp838
-rw-r--r--ACE/ace/Parse_Node.h522
-rw-r--r--ACE/ace/Ping_Socket.cpp377
-rw-r--r--ACE/ace/Ping_Socket.h119
-rw-r--r--ACE/ace/Ping_Socket.inl13
-rw-r--r--ACE/ace/Pipe.cpp360
-rw-r--r--ACE/ace/Pipe.h165
-rw-r--r--ACE/ace/Pipe.inl188
-rw-r--r--ACE/ace/Priority_Reactor.cpp188
-rw-r--r--ACE/ace/Priority_Reactor.h100
-rw-r--r--ACE/ace/Proactor.cpp1177
-rw-r--r--ACE/ace/Proactor.h691
-rw-r--r--ACE/ace/Proactor.inl80
-rw-r--r--ACE/ace/Proactor_Impl.cpp21
-rw-r--r--ACE/ace/Proactor_Impl.h265
-rw-r--r--ACE/ace/Process.cpp1275
-rw-r--r--ACE/ace/Process.h617
-rw-r--r--ACE/ace/Process.inl412
-rw-r--r--ACE/ace/Process_Manager.cpp1015
-rw-r--r--ACE/ace/Process_Manager.h478
-rw-r--r--ACE/ace/Process_Manager.inl13
-rw-r--r--ACE/ace/Process_Mutex.cpp90
-rw-r--r--ACE/ace/Process_Mutex.h216
-rw-r--r--ACE/ace/Process_Mutex.inl118
-rw-r--r--ACE/ace/Process_Semaphore.cpp111
-rw-r--r--ACE/ace/Process_Semaphore.h161
-rw-r--r--ACE/ace/Process_Semaphore.inl66
-rw-r--r--ACE/ace/Profile_Timer.cpp438
-rw-r--r--ACE/ace/Profile_Timer.h139
-rw-r--r--ACE/ace/Profile_Timer.inl129
-rw-r--r--ACE/ace/QoS/ACE_QoS.pc.in11
-rw-r--r--ACE/ace/QoS/ACE_QoS_Export.h46
-rw-r--r--ACE/ace/QoS/Makefile.am74
-rw-r--r--ACE/ace/QoS/QoS_Decorator.cpp165
-rw-r--r--ACE/ace/QoS/QoS_Decorator.h179
-rw-r--r--ACE/ace/QoS/QoS_Manager.cpp41
-rw-r--r--ACE/ace/QoS/QoS_Manager.h74
-rw-r--r--ACE/ace/QoS/QoS_Session.h183
-rw-r--r--ACE/ace/QoS/QoS_Session_Factory.cpp105
-rw-r--r--ACE/ace/QoS/QoS_Session_Factory.h96
-rw-r--r--ACE/ace/QoS/QoS_Session_Impl.cpp718
-rw-r--r--ACE/ace/QoS/QoS_Session_Impl.h265
-rw-r--r--ACE/ace/QoS/QoS_Session_Impl.inl229
-rw-r--r--ACE/ace/QoS/README55
-rw-r--r--ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.cpp258
-rw-r--r--ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.h142
-rw-r--r--ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.inl57
-rw-r--r--ACE/ace/QoS/qos.mpc17
-rw-r--r--ACE/ace/QtReactor/ACE_QtReactor.pc.in11
-rw-r--r--ACE/ace/QtReactor/ACE_QtReactor_export.h58
-rw-r--r--ACE/ace/QtReactor/QtReactor.cpp644
-rw-r--r--ACE/ace/QtReactor/QtReactor.h231
-rw-r--r--ACE/ace/RB_Tree.cpp1204
-rw-r--r--ACE/ace/RB_Tree.h904
-rw-r--r--ACE/ace/RB_Tree.inl1169
-rw-r--r--ACE/ace/README1876
-rw-r--r--ACE/ace/RW_Mutex.cpp55
-rw-r--r--ACE/ace/RW_Mutex.h141
-rw-r--r--ACE/ace/RW_Mutex.inl83
-rw-r--r--ACE/ace/RW_Process_Mutex.cpp54
-rw-r--r--ACE/ace/RW_Process_Mutex.h133
-rw-r--r--ACE/ace/RW_Process_Mutex.inl77
-rw-r--r--ACE/ace/RW_Thread_Mutex.cpp45
-rw-r--r--ACE/ace/RW_Thread_Mutex.h74
-rw-r--r--ACE/ace/RW_Thread_Mutex.inl19
-rw-r--r--ACE/ace/Reactor.cpp512
-rw-r--r--ACE/ace/Reactor.h875
-rw-r--r--ACE/ace/Reactor.inl498
-rw-r--r--ACE/ace/Reactor_Impl.cpp15
-rw-r--r--ACE/ace/Reactor_Impl.h569
-rw-r--r--ACE/ace/Reactor_Notification_Strategy.cpp38
-rw-r--r--ACE/ace/Reactor_Notification_Strategy.h66
-rw-r--r--ACE/ace/Reactor_Notification_Strategy.inl19
-rw-r--r--ACE/ace/Reactor_Timer_Interface.cpp16
-rw-r--r--ACE/ace/Reactor_Timer_Interface.h60
-rw-r--r--ACE/ace/Reactor_Token_T.cpp70
-rw-r--r--ACE/ace/Reactor_Token_T.h93
-rw-r--r--ACE/ace/Read_Buffer.cpp176
-rw-r--r--ACE/ace/Read_Buffer.h129
-rw-r--r--ACE/ace/Read_Buffer.inl32
-rw-r--r--ACE/ace/Recursive_Thread_Mutex.cpp125
-rw-r--r--ACE/ace/Recursive_Thread_Mutex.h194
-rw-r--r--ACE/ace/Recursive_Thread_Mutex.inl95
-rw-r--r--ACE/ace/Recyclable.cpp22
-rw-r--r--ACE/ace/Recyclable.h79
-rw-r--r--ACE/ace/Recyclable.inl20
-rw-r--r--ACE/ace/Refcountable.cpp20
-rw-r--r--ACE/ace/Refcountable.h58
-rw-r--r--ACE/ace/Refcountable.inl31
-rw-r--r--ACE/ace/Refcounted_Auto_Ptr.cpp18
-rw-r--r--ACE/ace/Refcounted_Auto_Ptr.h199
-rw-r--r--ACE/ace/Refcounted_Auto_Ptr.inl190
-rw-r--r--ACE/ace/Registry.cpp1127
-rw-r--r--ACE/ace/Registry.h559
-rw-r--r--ACE/ace/Registry_Name_Space.cpp293
-rw-r--r--ACE/ace/Registry_Name_Space.h140
-rw-r--r--ACE/ace/Remote_Name_Space.cpp380
-rw-r--r--ACE/ace/Remote_Name_Space.h147
-rw-r--r--ACE/ace/Remote_Tokens.cpp527
-rw-r--r--ACE/ace/Remote_Tokens.h322
-rw-r--r--ACE/ace/Remote_Tokens.inl48
-rw-r--r--ACE/ace/Reverse_Lock_T.cpp93
-rw-r--r--ACE/ace/Reverse_Lock_T.h139
-rw-r--r--ACE/ace/Reverse_Lock_T.inl19
-rw-r--r--ACE/ace/Rtems_init.c219
-rw-r--r--ACE/ace/SOCK.cpp185
-rw-r--r--ACE/ace/SOCK.h138
-rw-r--r--ACE/ace/SOCK.inl39
-rw-r--r--ACE/ace/SOCK_Acceptor.cpp406
-rw-r--r--ACE/ace/SOCK_Acceptor.h178
-rw-r--r--ACE/ace/SOCK_Acceptor.inl13
-rw-r--r--ACE/ace/SOCK_CODgram.cpp112
-rw-r--r--ACE/ace/SOCK_CODgram.h78
-rw-r--r--ACE/ace/SOCK_CODgram.inl19
-rw-r--r--ACE/ace/SOCK_Connector.cpp359
-rw-r--r--ACE/ace/SOCK_Connector.h321
-rw-r--r--ACE/ace/SOCK_Connector.inl38
-rw-r--r--ACE/ace/SOCK_Dgram.cpp750
-rw-r--r--ACE/ace/SOCK_Dgram.h239
-rw-r--r--ACE/ace/SOCK_Dgram.inl167
-rw-r--r--ACE/ace/SOCK_Dgram_Bcast.cpp380
-rw-r--r--ACE/ace/SOCK_Dgram_Bcast.h140
-rw-r--r--ACE/ace/SOCK_Dgram_Bcast.inl37
-rw-r--r--ACE/ace/SOCK_Dgram_Mcast.cpp928
-rw-r--r--ACE/ace/SOCK_Dgram_Mcast.h384
-rw-r--r--ACE/ace/SOCK_Dgram_Mcast.inl52
-rw-r--r--ACE/ace/SOCK_IO.cpp181
-rw-r--r--ACE/ace/SOCK_IO.h136
-rw-r--r--ACE/ace/SOCK_IO.inl123
-rw-r--r--ACE/ace/SOCK_Netlink.cpp113
-rw-r--r--ACE/ace/SOCK_Netlink.h106
-rw-r--r--ACE/ace/SOCK_Netlink.inl37
-rw-r--r--ACE/ace/SOCK_SEQPACK_Acceptor.cpp596
-rw-r--r--ACE/ace/SOCK_SEQPACK_Acceptor.h190
-rw-r--r--ACE/ace/SOCK_SEQPACK_Acceptor.inl13
-rw-r--r--ACE/ace/SOCK_SEQPACK_Association.cpp339
-rw-r--r--ACE/ace/SOCK_SEQPACK_Association.h202
-rw-r--r--ACE/ace/SOCK_SEQPACK_Association.inl177
-rw-r--r--ACE/ace/SOCK_SEQPACK_Connector.cpp443
-rw-r--r--ACE/ace/SOCK_SEQPACK_Connector.h331
-rw-r--r--ACE/ace/SOCK_SEQPACK_Connector.inl38
-rw-r--r--ACE/ace/SOCK_Stream.cpp40
-rw-r--r--ACE/ace/SOCK_Stream.h184
-rw-r--r--ACE/ace/SOCK_Stream.inl177
-rw-r--r--ACE/ace/SPIPE.cpp82
-rw-r--r--ACE/ace/SPIPE.h116
-rw-r--r--ACE/ace/SPIPE.inl18
-rw-r--r--ACE/ace/SPIPE_Acceptor.cpp337
-rw-r--r--ACE/ace/SPIPE_Acceptor.h168
-rw-r--r--ACE/ace/SPIPE_Addr.cpp167
-rw-r--r--ACE/ace/SPIPE_Addr.h122
-rw-r--r--ACE/ace/SPIPE_Addr.inl59
-rw-r--r--ACE/ace/SPIPE_Connector.cpp160
-rw-r--r--ACE/ace/SPIPE_Connector.h118
-rw-r--r--ACE/ace/SPIPE_Connector.inl15
-rw-r--r--ACE/ace/SPIPE_Stream.cpp104
-rw-r--r--ACE/ace/SPIPE_Stream.h171
-rw-r--r--ACE/ace/SPIPE_Stream.inl275
-rw-r--r--ACE/ace/SSL/ACE_SSL.pc.in11
-rw-r--r--ACE/ace/SSL/Makefile.am85
-rw-r--r--ACE/ace/SSL/SSL_Asynch_BIO.cpp252
-rw-r--r--ACE/ace/SSL/SSL_Asynch_BIO.h42
-rw-r--r--ACE/ace/SSL/SSL_Asynch_Stream.cpp1042
-rw-r--r--ACE/ace/SSL/SSL_Asynch_Stream.h425
-rw-r--r--ACE/ace/SSL/SSL_Context.cpp636
-rw-r--r--ACE/ace/SSL/SSL_Context.h384
-rw-r--r--ACE/ace/SSL/SSL_Context.inl113
-rw-r--r--ACE/ace/SSL/SSL_Export.h44
-rw-r--r--ACE/ace/SSL/SSL_SOCK.cpp72
-rw-r--r--ACE/ace/SSL/SSL_SOCK.h103
-rw-r--r--ACE/ace/SSL/SSL_SOCK.inl71
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Acceptor.cpp249
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Acceptor.h198
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Acceptor.inl85
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Connector.cpp411
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Connector.h318
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Connector.inl28
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Stream.cpp583
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Stream.h321
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Stream.inl323
-rw-r--r--ACE/ace/SSL/ssl.mpc13
-rw-r--r--ACE/ace/SSL/ssl_for_tao.mpc42
-rw-r--r--ACE/ace/SSL/sslconf.h55
-rw-r--r--ACE/ace/SString.cpp550
-rw-r--r--ACE/ace/SString.h499
-rw-r--r--ACE/ace/SString.inl299
-rw-r--r--ACE/ace/SStringfwd.h55
-rw-r--r--ACE/ace/SUN_Proactor.cpp324
-rw-r--r--ACE/ace/SUN_Proactor.h126
-rw-r--r--ACE/ace/SV_Message.cpp24
-rw-r--r--ACE/ace/SV_Message.h67
-rw-r--r--ACE/ace/SV_Message.inl37
-rw-r--r--ACE/ace/SV_Message_Queue.cpp44
-rw-r--r--ACE/ace/SV_Message_Queue.h105
-rw-r--r--ACE/ace/SV_Message_Queue.inl81
-rw-r--r--ACE/ace/SV_Semaphore_Complex.cpp259
-rw-r--r--ACE/ace/SV_Semaphore_Complex.h159
-rw-r--r--ACE/ace/SV_Semaphore_Complex.inl84
-rw-r--r--ACE/ace/SV_Semaphore_Simple.cpp237
-rw-r--r--ACE/ace/SV_Semaphore_Simple.h197
-rw-r--r--ACE/ace/SV_Semaphore_Simple.inl128
-rw-r--r--ACE/ace/SV_Shared_Memory.cpp88
-rw-r--r--ACE/ace/SV_Shared_Memory.h121
-rw-r--r--ACE/ace/SV_Shared_Memory.inl118
-rw-r--r--ACE/ace/Sample_History.cpp73
-rw-r--r--ACE/ace/Sample_History.h91
-rw-r--r--ACE/ace/Sample_History.inl26
-rw-r--r--ACE/ace/Sbrk_Memory_Pool.cpp124
-rw-r--r--ACE/ace/Sbrk_Memory_Pool.h118
-rw-r--r--ACE/ace/Sched_Params.cpp332
-rw-r--r--ACE/ace/Sched_Params.h232
-rw-r--r--ACE/ace/Sched_Params.inl134
-rw-r--r--ACE/ace/Select_Reactor.h69
-rw-r--r--ACE/ace/Select_Reactor_Base.cpp1104
-rw-r--r--ACE/ace/Select_Reactor_Base.h611
-rw-r--r--ACE/ace/Select_Reactor_Base.inl152
-rw-r--r--ACE/ace/Select_Reactor_T.cpp1594
-rw-r--r--ACE/ace/Select_Reactor_T.h718
-rw-r--r--ACE/ace/Select_Reactor_T.inl236
-rw-r--r--ACE/ace/Semaphore.cpp62
-rw-r--r--ACE/ace/Semaphore.h183
-rw-r--r--ACE/ace/Semaphore.inl119
-rw-r--r--ACE/ace/Service_Config.cpp586
-rw-r--r--ACE/ace/Service_Config.h610
-rw-r--r--ACE/ace/Service_Config.inl190
-rw-r--r--ACE/ace/Service_Gestalt.cpp1281
-rw-r--r--ACE/ace/Service_Gestalt.h502
-rw-r--r--ACE/ace/Service_Gestalt.inl74
-rw-r--r--ACE/ace/Service_Manager.cpp387
-rw-r--r--ACE/ace/Service_Manager.h120
-rw-r--r--ACE/ace/Service_Object.cpp173
-rw-r--r--ACE/ace/Service_Object.h207
-rw-r--r--ACE/ace/Service_Object.inl79
-rw-r--r--ACE/ace/Service_Repository.cpp577
-rw-r--r--ACE/ace/Service_Repository.h281
-rw-r--r--ACE/ace/Service_Repository.inl51
-rw-r--r--ACE/ace/Service_Templates.h29
-rw-r--r--ACE/ace/Service_Types.cpp458
-rw-r--r--ACE/ace/Service_Types.h206
-rw-r--r--ACE/ace/Service_Types.inl32
-rw-r--r--ACE/ace/Shared_Memory.cpp13
-rw-r--r--ACE/ace/Shared_Memory.h58
-rw-r--r--ACE/ace/Shared_Memory_MM.cpp111
-rw-r--r--ACE/ace/Shared_Memory_MM.h120
-rw-r--r--ACE/ace/Shared_Memory_MM.inl42
-rw-r--r--ACE/ace/Shared_Memory_Pool.cpp461
-rw-r--r--ACE/ace/Shared_Memory_Pool.h210
-rw-r--r--ACE/ace/Shared_Memory_SV.cpp88
-rw-r--r--ACE/ace/Shared_Memory_SV.h101
-rw-r--r--ACE/ace/Shared_Memory_SV.inl30
-rw-r--r--ACE/ace/Shared_Object.cpp54
-rw-r--r--ACE/ace/Shared_Object.h59
-rw-r--r--ACE/ace/Shared_Object.inl12
-rw-r--r--ACE/ace/Sig_Adapter.cpp80
-rw-r--r--ACE/ace/Sig_Adapter.h81
-rw-r--r--ACE/ace/Sig_Handler.cpp614
-rw-r--r--ACE/ace/Sig_Handler.h236
-rw-r--r--ACE/ace/Sig_Handler.inl15
-rw-r--r--ACE/ace/Signal.cpp221
-rw-r--r--ACE/ace/Signal.h267
-rw-r--r--ACE/ace/Signal.inl265
-rw-r--r--ACE/ace/Singleton.cpp534
-rw-r--r--ACE/ace/Singleton.h327
-rw-r--r--ACE/ace/Singleton.inl42
-rw-r--r--ACE/ace/Sock_Connect.cpp1642
-rw-r--r--ACE/ace/Sock_Connect.h107
-rw-r--r--ACE/ace/Static_Object_Lock.h78
-rw-r--r--ACE/ace/Stats.cpp426
-rw-r--r--ACE/ace/Stats.h222
-rw-r--r--ACE/ace/Stats.inl104
-rw-r--r--ACE/ace/Strategies.h33
-rw-r--r--ACE/ace/Strategies_T.cpp1498
-rw-r--r--ACE/ace/Strategies_T.h1076
-rw-r--r--ACE/ace/Strategies_T.inl230
-rw-r--r--ACE/ace/Stream.cpp619
-rw-r--r--ACE/ace/Stream.h241
-rw-r--r--ACE/ace/Stream.inl51
-rw-r--r--ACE/ace/Stream_Modules.cpp380
-rw-r--r--ACE/ace/Stream_Modules.h166
-rw-r--r--ACE/ace/String_Base.cpp563
-rw-r--r--ACE/ace/String_Base.h612
-rw-r--r--ACE/ace/String_Base.inl159
-rw-r--r--ACE/ace/String_Base_Const.cpp20
-rw-r--r--ACE/ace/String_Base_Const.h52
-rw-r--r--ACE/ace/Svc_Conf.h100
-rw-r--r--ACE/ace/Svc_Conf.y425
-rw-r--r--ACE/ace/Svc_Conf_Lexer.cpp676
-rw-r--r--ACE/ace/Svc_Conf_Lexer.h70
-rw-r--r--ACE/ace/Svc_Conf_Param.h142
-rw-r--r--ACE/ace/Svc_Conf_Tokens.h81
-rw-r--r--ACE/ace/Svc_Conf_y.cpp1759
-rw-r--r--ACE/ace/Svc_Handler.cpp525
-rw-r--r--ACE/ace/Svc_Handler.h339
-rw-r--r--ACE/ace/Synch.h65
-rw-r--r--ACE/ace/Synch_Options.cpp110
-rw-r--r--ACE/ace/Synch_Options.h163
-rw-r--r--ACE/ace/Synch_T.cpp22
-rw-r--r--ACE/ace/Synch_T.h42
-rw-r--r--ACE/ace/Synch_Traits.h152
-rw-r--r--ACE/ace/System_Time.cpp140
-rw-r--r--ACE/ace/System_Time.h99
-rw-r--r--ACE/ace/TLI.cpp273
-rw-r--r--ACE/ace/TLI.h116
-rw-r--r--ACE/ace/TLI.inl50
-rw-r--r--ACE/ace/TLI_Acceptor.cpp553
-rw-r--r--ACE/ace/TLI_Acceptor.h123
-rw-r--r--ACE/ace/TLI_Connector.cpp256
-rw-r--r--ACE/ace/TLI_Connector.h130
-rw-r--r--ACE/ace/TLI_Connector.inl49
-rw-r--r--ACE/ace/TLI_Stream.cpp229
-rw-r--r--ACE/ace/TLI_Stream.h141
-rw-r--r--ACE/ace/TLI_Stream.inl25
-rw-r--r--ACE/ace/TP_Reactor.cpp686
-rw-r--r--ACE/ace/TP_Reactor.h320
-rw-r--r--ACE/ace/TP_Reactor.inl119
-rw-r--r--ACE/ace/TSS_Adapter.cpp45
-rw-r--r--ACE/ace/TSS_Adapter.h61
-rw-r--r--ACE/ace/TSS_T.cpp725
-rw-r--r--ACE/ace/TSS_T.h253
-rw-r--r--ACE/ace/TSS_T.inl42
-rw-r--r--ACE/ace/TTY_IO.cpp583
-rw-r--r--ACE/ace/TTY_IO.h122
-rw-r--r--ACE/ace/Task.cpp299
-rw-r--r--ACE/ace/Task.h307
-rw-r--r--ACE/ace/Task.inl77
-rw-r--r--ACE/ace/Task_Ex_T.cpp114
-rw-r--r--ACE/ace/Task_Ex_T.h205
-rw-r--r--ACE/ace/Task_Ex_T.inl109
-rw-r--r--ACE/ace/Task_T.cpp108
-rw-r--r--ACE/ace/Task_T.h198
-rw-r--r--ACE/ace/Task_T.inl105
-rw-r--r--ACE/ace/Test_and_Set.cpp51
-rw-r--r--ACE/ace/Test_and_Set.h75
-rw-r--r--ACE/ace/Thread.cpp99
-rw-r--r--ACE/ace/Thread.h282
-rw-r--r--ACE/ace/Thread.inl286
-rw-r--r--ACE/ace/Thread_Adapter.cpp225
-rw-r--r--ACE/ace/Thread_Adapter.h100
-rw-r--r--ACE/ace/Thread_Adapter.inl13
-rw-r--r--ACE/ace/Thread_Control.cpp96
-rw-r--r--ACE/ace/Thread_Control.h102
-rw-r--r--ACE/ace/Thread_Control.inl46
-rw-r--r--ACE/ace/Thread_Exit.cpp123
-rw-r--r--ACE/ace/Thread_Exit.h111
-rw-r--r--ACE/ace/Thread_Hook.cpp33
-rw-r--r--ACE/ace/Thread_Hook.h65
-rw-r--r--ACE/ace/Thread_Manager.cpp2163
-rw-r--r--ACE/ace/Thread_Manager.h1136
-rw-r--r--ACE/ace/Thread_Manager.inl308
-rw-r--r--ACE/ace/Thread_Mutex.cpp62
-rw-r--r--ACE/ace/Thread_Mutex.h175
-rw-r--r--ACE/ace/Thread_Mutex.inl97
-rw-r--r--ACE/ace/Thread_Semaphore.cpp62
-rw-r--r--ACE/ace/Thread_Semaphore.h89
-rw-r--r--ACE/ace/Thread_Semaphore.inl12
-rw-r--r--ACE/ace/Throughput_Stats.cpp202
-rw-r--r--ACE/ace/Throughput_Stats.h86
-rw-r--r--ACE/ace/Time_Value.cpp264
-rw-r--r--ACE/ace/Time_Value.h360
-rw-r--r--ACE/ace/Time_Value.inl407
-rw-r--r--ACE/ace/Timeprobe.cpp15
-rw-r--r--ACE/ace/Timeprobe.h201
-rw-r--r--ACE/ace/Timeprobe.inl14
-rw-r--r--ACE/ace/Timeprobe_T.cpp427
-rw-r--r--ACE/ace/Timeprobe_T.h220
-rw-r--r--ACE/ace/Timer_Hash.h75
-rw-r--r--ACE/ace/Timer_Hash_T.cpp873
-rw-r--r--ACE/ace/Timer_Hash_T.h342
-rw-r--r--ACE/ace/Timer_Heap.h41
-rw-r--r--ACE/ace/Timer_Heap_T.cpp889
-rw-r--r--ACE/ace/Timer_Heap_T.h338
-rw-r--r--ACE/ace/Timer_List.h42
-rw-r--r--ACE/ace/Timer_List_T.cpp418
-rw-r--r--ACE/ace/Timer_List_T.h226
-rw-r--r--ACE/ace/Timer_Queue.h52
-rw-r--r--ACE/ace/Timer_Queue_Adapters.cpp361
-rw-r--r--ACE/ace/Timer_Queue_Adapters.h261
-rw-r--r--ACE/ace/Timer_Queue_Adapters.inl29
-rw-r--r--ACE/ace/Timer_Queue_T.cpp481
-rw-r--r--ACE/ace/Timer_Queue_T.h562
-rw-r--r--ACE/ace/Timer_Queue_T.inl222
-rw-r--r--ACE/ace/Timer_Queuefwd.h38
-rw-r--r--ACE/ace/Timer_Wheel.h42
-rw-r--r--ACE/ace/Timer_Wheel_T.cpp967
-rw-r--r--ACE/ace/Timer_Wheel_T.h226
-rw-r--r--ACE/ace/TkReactor/ACE_TkReactor.pc.in11
-rw-r--r--ACE/ace/TkReactor/ACE_TkReactor_export.h58
-rw-r--r--ACE/ace/TkReactor/TkReactor.cpp439
-rw-r--r--ACE/ace/TkReactor/TkReactor.h136
-rw-r--r--ACE/ace/Token.cpp545
-rw-r--r--ACE/ace/Token.h376
-rw-r--r--ACE/ace/Token.inl176
-rw-r--r--ACE/ace/Token_Collection.cpp294
-rw-r--r--ACE/ace/Token_Collection.h243
-rw-r--r--ACE/ace/Token_Collection.inl17
-rw-r--r--ACE/ace/Token_Invariants.cpp355
-rw-r--r--ACE/ace/Token_Invariants.h245
-rw-r--r--ACE/ace/Token_Manager.cpp273
-rw-r--r--ACE/ace/Token_Manager.h150
-rw-r--r--ACE/ace/Token_Manager.inl25
-rw-r--r--ACE/ace/Token_Request_Reply.cpp186
-rw-r--r--ACE/ace/Token_Request_Reply.h270
-rw-r--r--ACE/ace/Token_Request_Reply.inl205
-rw-r--r--ACE/ace/Trace.cpp137
-rw-r--r--ACE/ace/Trace.h96
-rw-r--r--ACE/ace/Truncate.h1016
-rw-r--r--ACE/ace/Typed_SV_Message.cpp30
-rw-r--r--ACE/ace/Typed_SV_Message.h107
-rw-r--r--ACE/ace/Typed_SV_Message.inl96
-rw-r--r--ACE/ace/Typed_SV_Message_Queue.cpp56
-rw-r--r--ACE/ace/Typed_SV_Message_Queue.h92
-rw-r--r--ACE/ace/Typed_SV_Message_Queue.inl80
-rw-r--r--ACE/ace/UNIX_Addr.cpp151
-rw-r--r--ACE/ace/UNIX_Addr.h117
-rw-r--r--ACE/ace/UNIX_Addr.inl57
-rw-r--r--ACE/ace/UPIPE_Acceptor.cpp129
-rw-r--r--ACE/ace/UPIPE_Acceptor.h99
-rw-r--r--ACE/ace/UPIPE_Acceptor.inl14
-rw-r--r--ACE/ace/UPIPE_Addr.h33
-rw-r--r--ACE/ace/UPIPE_Connector.cpp101
-rw-r--r--ACE/ace/UPIPE_Connector.h115
-rw-r--r--ACE/ace/UPIPE_Connector.inl34
-rw-r--r--ACE/ace/UPIPE_Stream.cpp231
-rw-r--r--ACE/ace/UPIPE_Stream.h140
-rw-r--r--ACE/ace/UPIPE_Stream.inl14
-rw-r--r--ACE/ace/UTF16_Encoding_Converter.cpp364
-rw-r--r--ACE/ace/UTF16_Encoding_Converter.h86
-rw-r--r--ACE/ace/UTF16_Encoding_Converter.inl76
-rw-r--r--ACE/ace/UTF32_Encoding_Converter.cpp254
-rw-r--r--ACE/ace/UTF32_Encoding_Converter.h67
-rw-r--r--ACE/ace/UTF8_Encoding_Converter.cpp92
-rw-r--r--ACE/ace/UTF8_Encoding_Converter.h72
-rw-r--r--ACE/ace/UUID.cpp554
-rw-r--r--ACE/ace/UUID.h239
-rw-r--r--ACE/ace/UUID.inl200
-rw-r--r--ACE/ace/Unbounded_Queue.cpp434
-rw-r--r--ACE/ace/Unbounded_Queue.h297
-rw-r--r--ACE/ace/Unbounded_Queue.inl27
-rw-r--r--ACE/ace/Unbounded_Set.cpp478
-rw-r--r--ACE/ace/Unbounded_Set.h322
-rw-r--r--ACE/ace/Unbounded_Set.inl23
-rw-r--r--ACE/ace/Value_Ptr.h167
-rw-r--r--ACE/ace/Vector_T.cpp154
-rw-r--r--ACE/ace/Vector_T.h316
-rw-r--r--ACE/ace/Vector_T.inl107
-rw-r--r--ACE/ace/Version.h9
-rw-r--r--ACE/ace/Versioned_Namespace.h51
-rw-r--r--ACE/ace/WFMO_Reactor.cpp2754
-rw-r--r--ACE/ace/WFMO_Reactor.h1368
-rw-r--r--ACE/ace/WFMO_Reactor.inl1173
-rw-r--r--ACE/ace/WIN32_Asynch_IO.cpp3767
-rw-r--r--ACE/ace/WIN32_Asynch_IO.h1937
-rw-r--r--ACE/ace/WIN32_Proactor.cpp804
-rw-r--r--ACE/ace/WIN32_Proactor.h325
-rw-r--r--ACE/ace/XML_Svc_Conf.cpp15
-rw-r--r--ACE/ace/XML_Svc_Conf.h65
-rw-r--r--ACE/ace/XTI_ATM_Mcast.cpp70
-rw-r--r--ACE/ace/XTI_ATM_Mcast.h137
-rw-r--r--ACE/ace/XTI_ATM_Mcast.inl65
-rw-r--r--ACE/ace/XtReactor/ACE_XtReactor.pc.in11
-rw-r--r--ACE/ace/XtReactor/ACE_XtReactor_export.h58
-rw-r--r--ACE/ace/XtReactor/XtReactor.cpp450
-rw-r--r--ACE/ace/XtReactor/XtReactor.h138
-rw-r--r--ACE/ace/ace.mpc464
-rw-r--r--ACE/ace/ace.mwc14
-rw-r--r--ACE/ace/ace.rc38
-rw-r--r--ACE/ace/ace_ce_dll.cfg1
-rw-r--r--ACE/ace/ace_flreactor.mpc32
-rw-r--r--ACE/ace/ace_for_tao.mpc377
-rw-r--r--ACE/ace/ace_foxreactor.mpc32
-rw-r--r--ACE/ace/ace_message_table.binbin0 -> 28 bytes
-rw-r--r--ACE/ace/ace_qtreactor.mpc38
-rw-r--r--ACE/ace/ace_tkreactor.mpc32
-rw-r--r--ACE/ace/ace_wchar.cpp17
-rw-r--r--ACE/ace/ace_wchar.h377
-rw-r--r--ACE/ace/ace_wchar.inl183
-rw-r--r--ACE/ace/ace_xtreactor.mpc32
-rw-r--r--ACE/ace/checked_iterator.h58
-rw-r--r--ACE/ace/codecs.mpb8
-rw-r--r--ACE/ace/config-WinCE.h238
-rw-r--r--ACE/ace/config-aix-5.x.h333
-rw-r--r--ACE/ace/config-all.h81
-rw-r--r--ACE/ace/config-borland-common.h75
-rw-r--r--ACE/ace/config-cray.h215
-rw-r--r--ACE/ace/config-cxx-common.h87
-rw-r--r--ACE/ace/config-cygwin32.h204
-rw-r--r--ACE/ace/config-doxygen.h120
-rw-r--r--ACE/ace/config-freebsd.h284
-rw-r--r--ACE/ace/config-g++-common.h137
-rw-r--r--ACE/ace/config-ghs-common.h43
-rw-r--r--ACE/ace/config-hpux-11.00.h446
-rw-r--r--ACE/ace/config-icc-common.h114
-rw-r--r--ACE/ace/config-integritySCA.h234
-rw-r--r--ACE/ace/config-irix6.5.x-sgic++.h18
-rw-r--r--ACE/ace/config-irix6.x-common.h256
-rw-r--r--ACE/ace/config-irix6.x-g++.h23
-rw-r--r--ACE/ace/config-irix6.x-sgic++.h38
-rw-r--r--ACE/ace/config-linux-common.h442
-rw-r--r--ACE/ace/config-linux.h75
-rw-r--r--ACE/ace/config-lite.h164
-rw-r--r--ACE/ace/config-lynxos.h159
-rw-r--r--ACE/ace/config-macosx-leopard.h224
-rw-r--r--ACE/ace/config-macosx-panther.h191
-rw-r--r--ACE/ace/config-macosx-tiger.h219
-rw-r--r--ACE/ace/config-macosx.h191
-rw-r--r--ACE/ace/config-macros.h639
-rw-r--r--ACE/ace/config-minimal.h39
-rw-r--r--ACE/ace/config-mvs.h130
-rw-r--r--ACE/ace/config-netbsd.h167
-rw-r--r--ACE/ace/config-openbsd.h235
-rw-r--r--ACE/ace/config-openvms.h198
-rw-r--r--ACE/ace/config-pharlap.h86
-rw-r--r--ACE/ace/config-posix-nonetworking.h86
-rw-r--r--ACE/ace/config-posix.h72
-rw-r--r--ACE/ace/config-qnx-neutrino.h137
-rw-r--r--ACE/ace/config-qnx-rtp-62x.h129
-rw-r--r--ACE/ace/config-qnx-rtp-common.h46
-rw-r--r--ACE/ace/config-qnx-rtp-pre62x.h151
-rw-r--r--ACE/ace/config-qnx-rtp.h25
-rw-r--r--ACE/ace/config-rtems.h165
-rw-r--r--ACE/ace/config-sco-5.0.0-nothread.h14
-rw-r--r--ACE/ace/config-sco-5.0.0.h97
-rw-r--r--ACE/ace/config-suncc-common.h68
-rw-r--r--ACE/ace/config-sunos5.10.h46
-rw-r--r--ACE/ace/config-sunos5.11.h15
-rw-r--r--ACE/ace/config-sunos5.4-g++.h180
-rw-r--r--ACE/ace/config-sunos5.4-sunc++-4.x.h191
-rw-r--r--ACE/ace/config-sunos5.5.h414
-rw-r--r--ACE/ace/config-sunos5.6.h129
-rw-r--r--ACE/ace/config-sunos5.7.h78
-rw-r--r--ACE/ace/config-sunos5.8.h39
-rw-r--r--ACE/ace/config-sunos5.9.h18
-rw-r--r--ACE/ace/config-tandem-nsk-mips-v2.h404
-rw-r--r--ACE/ace/config-tandem-nsk-mips-v3.h474
-rw-r--r--ACE/ace/config-tandem.h192
-rw-r--r--ACE/ace/config-tru64.h155
-rw-r--r--ACE/ace/config-unixware-7.1.0.h414
-rw-r--r--ACE/ace/config-unixware-7.1.0.udk.h465
-rw-r--r--ACE/ace/config-visualage.h20
-rw-r--r--ACE/ace/config-vxworks.h33
-rw-r--r--ACE/ace/config-vxworks5.x.h334
-rw-r--r--ACE/ace/config-vxworks6.2.h332
-rw-r--r--ACE/ace/config-vxworks6.3.h322
-rw-r--r--ACE/ace/config-vxworks6.4.h345
-rw-r--r--ACE/ace/config-vxworks6.5.h25
-rw-r--r--ACE/ace/config-vxworks6.6.h29
-rw-r--r--ACE/ace/config-win32-borland.h121
-rw-r--r--ACE/ace/config-win32-common.h660
-rw-r--r--ACE/ace/config-win32-dmc.h109
-rw-r--r--ACE/ace/config-win32-ghs.h95
-rw-r--r--ACE/ace/config-win32-interix.h100
-rw-r--r--ACE/ace/config-win32-mingw.h98
-rw-r--r--ACE/ace/config-win32-msvc-7.h126
-rw-r--r--ACE/ace/config-win32-msvc-8.h149
-rw-r--r--ACE/ace/config-win32-msvc-9.h141
-rw-r--r--ACE/ace/config-win32-msvc.h164
-rw-r--r--ACE/ace/config-win32.h53
-rw-r--r--ACE/ace/filecache.mpb8
-rw-r--r--ACE/ace/gethrtime.cpp60
-rw-r--r--ACE/ace/iosfwd.h99
-rw-r--r--ACE/ace/os_include/arpa/os_inet.h74
-rw-r--r--ACE/ace/os_include/net/os_if.h119
-rw-r--r--ACE/ace/os_include/netinet/os_in.h185
-rw-r--r--ACE/ace/os_include/netinet/os_tcp.h46
-rw-r--r--ACE/ace/os_include/os_aio.h47
-rw-r--r--ACE/ace/os_include/os_assert.h46
-rw-r--r--ACE/ace/os_include/os_byteswap.h41
-rw-r--r--ACE/ace/os_include/os_complex.h42
-rw-r--r--ACE/ace/os_include/os_cpio.h42
-rw-r--r--ACE/ace/os_include/os_ctype.h45
-rw-r--r--ACE/ace/os_include/os_dirent.h108
-rw-r--r--ACE/ace/os_include/os_dlfcn.h107
-rw-r--r--ACE/ace/os_include/os_errno.h153
-rw-r--r--ACE/ace/os_include/os_fcntl.h106
-rw-r--r--ACE/ace/os_include/os_fenv.h42
-rw-r--r--ACE/ace/os_include/os_float.h42
-rw-r--r--ACE/ace/os_include/os_fmtmsg.h42
-rw-r--r--ACE/ace/os_include/os_fnmatch.h42
-rw-r--r--ACE/ace/os_include/os_ftw.h44
-rw-r--r--ACE/ace/os_include/os_glob.h44
-rw-r--r--ACE/ace/os_include/os_grp.h44
-rw-r--r--ACE/ace/os_include/os_iconv.h44
-rw-r--r--ACE/ace/os_include/os_intrin.h57
-rw-r--r--ACE/ace/os_include/os_inttypes.h46
-rw-r--r--ACE/ace/os_include/os_iso646.h42
-rw-r--r--ACE/ace/os_include/os_langinfo.h44
-rw-r--r--ACE/ace/os_include/os_libgen.h42
-rw-r--r--ACE/ace/os_include/os_limits.h143
-rw-r--r--ACE/ace/os_include/os_local.h44
-rw-r--r--ACE/ace/os_include/os_math.h44
-rw-r--r--ACE/ace/os_include/os_monetary.h44
-rw-r--r--ACE/ace/os_include/os_mqueue.h44
-rw-r--r--ACE/ace/os_include/os_ndbm.h44
-rw-r--r--ACE/ace/os_include/os_netdb.h108
-rw-r--r--ACE/ace/os_include/os_nl_types.h42
-rw-r--r--ACE/ace/os_include/os_poll.h42
-rw-r--r--ACE/ace/os_include/os_pthread.h424
-rw-r--r--ACE/ace/os_include/os_pwd.h58
-rw-r--r--ACE/ace/os_include/os_regex.h48
-rw-r--r--ACE/ace/os_include/os_sched.h52
-rw-r--r--ACE/ace/os_include/os_search.h44
-rw-r--r--ACE/ace/os_include/os_semaphore.h77
-rw-r--r--ACE/ace/os_include/os_setjmp.h42
-rw-r--r--ACE/ace/os_include/os_signal.h253
-rw-r--r--ACE/ace/os_include/os_spawn.h46
-rw-r--r--ACE/ace/os_include/os_stdarg.h50
-rw-r--r--ACE/ace/os_include/os_stdbool.h42
-rw-r--r--ACE/ace/os_include/os_stddef.h97
-rw-r--r--ACE/ace/os_include/os_stdint.h141
-rw-r--r--ACE/ace/os_include/os_stdio.h87
-rw-r--r--ACE/ace/os_include/os_stdlib.h77
-rw-r--r--ACE/ace/os_include/os_string.h76
-rw-r--r--ACE/ace/os_include/os_strings.h52
-rw-r--r--ACE/ace/os_include/os_stropts.h120
-rw-r--r--ACE/ace/os_include/os_syslog.h42
-rw-r--r--ACE/ace/os_include/os_tar.h42
-rw-r--r--ACE/ace/os_include/os_termios.h46
-rw-r--r--ACE/ace/os_include/os_tgmath.h45
-rw-r--r--ACE/ace/os_include/os_time.h123
-rw-r--r--ACE/ace/os_include/os_trace.h44
-rw-r--r--ACE/ace/os_include/os_ucontext.h48
-rw-r--r--ACE/ace/os_include/os_ulimit.h42
-rw-r--r--ACE/ace/os_include/os_unistd.h203
-rw-r--r--ACE/ace/os_include/os_utime.h44
-rw-r--r--ACE/ace/os_include/os_utmpx.h44
-rw-r--r--ACE/ace/os_include/os_wchar.h49
-rw-r--r--ACE/ace/os_include/os_wctype.h45
-rw-r--r--ACE/ace/os_include/os_wordexp.h44
-rw-r--r--ACE/ace/os_include/sys/os_ipc.h74
-rw-r--r--ACE/ace/os_include/sys/os_loadavg.h41
-rw-r--r--ACE/ace/os_include/sys/os_mman.h122
-rw-r--r--ACE/ace/os_include/sys/os_msg.h55
-rw-r--r--ACE/ace/os_include/sys/os_pstat.h42
-rw-r--r--ACE/ace/os_include/sys/os_resource.h104
-rw-r--r--ACE/ace/os_include/sys/os_select.h59
-rw-r--r--ACE/ace/os_include/sys/os_sem.h90
-rw-r--r--ACE/ace/os_include/sys/os_shm.h48
-rw-r--r--ACE/ace/os_include/sys/os_socket.h307
-rw-r--r--ACE/ace/os_include/sys/os_stat.h127
-rw-r--r--ACE/ace/os_include/sys/os_statvfs.h44
-rw-r--r--ACE/ace/os_include/sys/os_sysctl.h41
-rw-r--r--ACE/ace/os_include/sys/os_time.h60
-rw-r--r--ACE/ace/os_include/sys/os_timeb.h49
-rw-r--r--ACE/ace/os_include/sys/os_times.h44
-rw-r--r--ACE/ace/os_include/sys/os_types.h158
-rw-r--r--ACE/ace/os_include/sys/os_uio.h77
-rw-r--r--ACE/ace/os_include/sys/os_un.h52
-rw-r--r--ACE/ace/os_include/sys/os_utsname.h42
-rw-r--r--ACE/ace/os_include/sys/os_wait.h97
-rw-r--r--ACE/ace/other.mpb15
-rw-r--r--ACE/ace/post.h22
-rw-r--r--ACE/ace/pre.h24
-rw-r--r--ACE/ace/streams.h141
-rw-r--r--ACE/ace/svc_export.h44
-rw-r--r--ACE/ace/svcconf.mpb64
-rw-r--r--ACE/ace/token.mpb15
-rw-r--r--ACE/ace/uuid.mpb8
1334 files changed, 326233 insertions, 0 deletions
diff --git a/ACE/ace/ACE.cpp b/ACE/ace/ACE.cpp
new file mode 100644
index 00000000000..233ef720f4c
--- /dev/null
+++ b/ACE/ace/ACE.cpp
@@ -0,0 +1,3409 @@
+// $Id$
+
+#include "ace/ACE.h"
+
+#include "ace/Basic_Types.h"
+#include "ace/Handle_Set.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/SString.h"
+#include "ace/Version.h"
+#include "ace/Message_Block.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_strings.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_sys_resource.h"
+#include "ace/OS_NS_sys_wait.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_sys_uio.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_TLI.h"
+#include "ace/Truncate.h"
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x620)
+extern "C" int maxFiles;
+#endif /* ACE_VXWORKS */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/ACE.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT)
+# include "ace/OS_NS_poll.h"
+#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */
+
+
+ACE_RCSID (ace,
+ ACE,
+ "$Id$")
+
+
+// Open versioned namespace, if enabled by the user.
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE
+{
+ // private:
+ // Used internally so not exported.
+
+ // Size of allocation granularity.
+ size_t allocation_granularity_ = 0;
+
+ // Size of a VM page.
+ size_t pagesize_ = 0;
+
+ // Are we debugging ACE?
+ // Keeps track of whether we're in some global debug mode.
+ char debug_;
+}
+
+
+int
+ACE::out_of_handles (int error)
+{
+ // EMFILE is common to all platforms.
+ if (error == EMFILE ||
+#if defined (ACE_WIN32)
+ // On Win32, we need to check for ENOBUFS also.
+ error == ENOBUFS ||
+#elif defined (HPUX)
+ // On HPUX, we need to check for EADDRNOTAVAIL also.
+ error == EADDRNOTAVAIL ||
+#elif defined (linux)
+ // On linux, we need to check for ENOENT also.
+ error == ENOENT ||
+ // For RedHat5.2, need to check for EINVAL too.
+ error == EINVAL ||
+ // Without threads check for EOPNOTSUPP
+ error == EOPNOTSUPP ||
+#elif defined (sun)
+ // On sun, we need to check for ENOSR also.
+ error == ENOSR ||
+ // Without threads check for ENOTSUP
+ error == ENOTSUP ||
+#elif defined (__FreeBSD__)
+ // On FreeBSD we need to check for EOPNOTSUPP (LinuxThreads) or
+ // ENOSYS (libc_r threads) also.
+ error == EOPNOTSUPP ||
+ error == ENOSYS ||
+#elif defined (__OpenBSD__)
+ // OpenBSD appears to return EBADF.
+ error == EBADF ||
+#elif defined (__sgi) // irix
+ error == ENOTSUP ||
+#elif defined (DIGITAL_UNIX) // osf1
+ error == ENOTSUP ||
+#endif /* ACE_WIN32 */
+ error == ENFILE)
+ return 1;
+ else
+ return 0;
+}
+
+u_int
+ACE::major_version (void)
+{
+ return ACE_MAJOR_VERSION;
+}
+
+u_int
+ACE::minor_version (void)
+{
+ return ACE_MINOR_VERSION;
+}
+
+u_int
+ACE::beta_version (void)
+{
+ return ACE_BETA_VERSION;
+}
+
+const ACE_TCHAR *
+ACE::compiler_name (void)
+{
+#ifdef ACE_CC_NAME
+ return ACE_CC_NAME;
+#else
+ return ACE_TEXT ("");
+#endif
+}
+
+u_int
+ACE::compiler_major_version (void)
+{
+#ifdef ACE_CC_MAJOR_VERSION
+ return ACE_CC_MAJOR_VERSION;
+#else
+ return 0;
+#endif
+}
+
+u_int
+ACE::compiler_minor_version (void)
+{
+#ifdef ACE_CC_MINOR_VERSION
+ return ACE_CC_MINOR_VERSION;
+#else
+ return 0;
+#endif
+}
+
+u_int
+ACE::compiler_beta_version (void)
+{
+#ifdef ACE_CC_BETA_VERSION
+ return ACE_CC_BETA_VERSION;
+#else
+ return 0;
+#endif
+}
+
+bool
+ACE::debug (void)
+{
+ static const char* debug = ACE_OS::getenv ("ACE_DEBUG");
+ return (ACE::debug_ != 0) ? ACE::debug_ : (debug != 0 ? (*debug != '0'): false);
+}
+
+void
+ACE::debug (bool onoff)
+{
+ ACE::debug_ = onoff;
+}
+
+int
+ACE::select (int width,
+ ACE_Handle_Set *readfds,
+ ACE_Handle_Set *writefds,
+ ACE_Handle_Set *exceptfds,
+ const ACE_Time_Value *timeout)
+{
+ int result = ACE_OS::select (width,
+ readfds ? readfds->fdset () : 0,
+ writefds ? writefds->fdset () : 0,
+ exceptfds ? exceptfds->fdset () : 0,
+ timeout);
+ if (result > 0)
+ {
+# if !defined (ACE_WIN32)
+ // This isn't needed for Windows... it's a no-op anyway.
+ if (readfds)
+ readfds->sync ((ACE_HANDLE) width);
+ if (writefds)
+ writefds->sync ((ACE_HANDLE) width);
+ if (exceptfds)
+ exceptfds->sync ((ACE_HANDLE) width);
+#endif /* ACE_WIN32 */
+ }
+ return result;
+}
+
+int
+ACE::select (int width,
+ ACE_Handle_Set &readfds,
+ const ACE_Time_Value *timeout)
+{
+ int result = ACE_OS::select (width,
+ readfds.fdset (),
+ 0,
+ 0,
+ timeout);
+
+#if !defined (ACE_WIN32)
+ if (result > 0)
+ readfds.sync ((ACE_HANDLE) width);
+#endif /* ACE_WIN32 */
+ return result;
+}
+
+int
+ACE::terminate_process (pid_t pid)
+{
+#if defined (ACE_HAS_PHARLAP)
+ ACE_UNUSED_ARG (pid);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+ // Create a handle for the given process id.
+ ACE_HANDLE process_handle =
+ ::OpenProcess (PROCESS_TERMINATE,
+ FALSE, // New handle is not inheritable.
+ pid);
+
+ if (process_handle == ACE_INVALID_HANDLE
+ || process_handle == 0)
+ return -1;
+ else
+ {
+ // Kill the process associated with process_handle.
+ BOOL terminate_result =
+ ::TerminateProcess (process_handle, 0);
+ // Free up the kernel resources.
+ ACE_OS::close (process_handle);
+ return terminate_result ? 0 : -1;
+ }
+#else
+ return ACE_OS::kill (pid, 9);
+#endif /* ACE_HAS_PHARLAP */
+}
+
+int
+ACE::process_active (pid_t pid)
+{
+#if !defined(ACE_WIN32)
+ int retval = ACE_OS::kill (pid, 0);
+
+ if (retval == 0)
+ return 1;
+ else if (errno == ESRCH)
+ return 0;
+ else
+ return -1;
+#else
+ // Create a handle for the given process id.
+ ACE_HANDLE process_handle =
+ ::OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid);
+ if (process_handle == ACE_INVALID_HANDLE
+ || process_handle == 0)
+ return 0;
+ else
+ {
+ DWORD status;
+ int result = 1;
+ if (::GetExitCodeProcess (process_handle,
+ &status) == 0
+ || status != STILL_ACTIVE)
+ result = 0;
+
+ ::CloseHandle (process_handle);
+ return result;
+ }
+#endif /* !ACE_WIN32 */
+}
+
+const ACE_TCHAR *
+ACE::execname (const ACE_TCHAR *old_name)
+{
+#if defined (ACE_WIN32)
+ const ACE_TCHAR *suffix = ACE_OS::strrchr (old_name, ACE_TEXT ('.'));
+ if (suffix == 0 || ACE_OS::strcasecmp (suffix, ACE_TEXT (".exe")) != 0)
+ {
+ ACE_TCHAR *new_name;
+
+ size_t size =
+ ACE_OS::strlen (old_name)
+ + ACE_OS::strlen (ACE_TEXT (".exe"))
+ + 1;
+
+ ACE_NEW_RETURN (new_name,
+ ACE_TCHAR[size],
+ 0);
+ ACE_TCHAR *end = new_name;
+
+ end = ACE_OS::strecpy (new_name, old_name);
+
+ // Concatenate the .exe suffix onto the end of the executable.
+ // end points _after_ the terminating nul.
+ ACE_OS::strcpy (end - 1, ACE_TEXT (".exe"));
+
+ return new_name;
+ }
+#endif /* ACE_WIN32 */
+ return old_name;
+}
+
+u_long
+ACE::hash_pjw (const char *str, size_t len)
+{
+ u_long hash = 0;
+
+ for (size_t i = 0; i < len; i++)
+ {
+ const char temp = str[i];
+ hash = (hash << 4) + (temp * 13);
+
+ u_long g = hash & 0xf0000000;
+
+ if (g)
+ {
+ hash ^= (g >> 24);
+ hash ^= g;
+ }
+ }
+
+ return hash;
+}
+
+u_long
+ACE::hash_pjw (const char *str)
+{
+ return ACE::hash_pjw (str, ACE_OS::strlen (str));
+}
+
+#if defined (ACE_HAS_WCHAR)
+u_long
+ACE::hash_pjw (const wchar_t *str, size_t len)
+{
+ u_long hash = 0;
+
+ for (size_t i = 0; i < len; i++)
+ {
+ // @@ UNICODE: Does this function do the correct thing with wchar's?
+
+ const wchar_t temp = str[i];
+ hash = (hash << 4) + (temp * 13);
+
+ u_long g = hash & 0xf0000000;
+
+ if (g)
+ {
+ hash ^= (g >> 24);
+ hash ^= g;
+ }
+ }
+
+ return hash;
+}
+
+u_long
+ACE::hash_pjw (const wchar_t *str)
+{
+ return ACE::hash_pjw (str, ACE_OS::strlen (str));
+}
+#endif /* ACE_HAS_WCHAR */
+
+#if !defined (ACE_HAS_WINCE)
+ACE_TCHAR *
+ACE::strenvdup (const ACE_TCHAR *str)
+{
+ ACE_TRACE ("ACE::strenvdup");
+
+ return ACE_OS::strenvdup (str);
+}
+#endif /* ACE_HAS_WINCE */
+
+/*
+
+Examples:
+
+Source NT UNIX
+==================================================================
+netsvc netsvc.dll libnetsvc.so
+(PATH will be (LD_LIBRARY_PATH
+evaluated) evaluated)
+
+libnetsvc.dll libnetsvc.dll libnetsvc.dll + warning
+netsvc.so netsvc.so + warning libnetsvc.so
+
+..\../libs/netsvc ..\..\libs\netsvc.dll ../../libs/netsvc.so
+(absolute path used) (absolute path used)
+
+*/
+
+const ACE_TCHAR *
+ACE::basename (const ACE_TCHAR *pathname, ACE_TCHAR delim)
+{
+ ACE_TRACE ("ACE::basename");
+ const ACE_TCHAR *temp = ACE_OS::strrchr (pathname, delim);
+
+ if (temp == 0)
+ return pathname;
+ else
+ return temp + 1;
+}
+
+const ACE_TCHAR *
+ACE::dirname (const ACE_TCHAR *pathname, ACE_TCHAR delim)
+{
+ ACE_TRACE ("ACE::dirname");
+ static ACE_TCHAR return_dirname[MAXPATHLEN + 1];
+
+ const ACE_TCHAR *temp = ACE_OS::strrchr (pathname, delim);
+
+ if (temp == 0)
+ {
+ return_dirname[0] = '.';
+ return_dirname[1] = '\0';
+
+ return return_dirname;
+ }
+ else
+ {
+ // When the len is truncated, there are problems! This should
+ // not happen in normal circomstances
+ size_t len = temp - pathname + 1;
+ if (len > (sizeof return_dirname / sizeof (ACE_TCHAR)))
+ len = sizeof return_dirname / sizeof (ACE_TCHAR);
+
+ ACE_OS::strsncpy (return_dirname,
+ pathname,
+ len);
+ return return_dirname;
+ }
+}
+
+ssize_t
+ACE::recv (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::recv (handle, (char *) buf, len, flags);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_recv_timedwait (handle, timeout, val) ==-1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred =
+ ACE_OS::recv (handle, (char *) buf, len, flags);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+#if defined (ACE_HAS_TLI)
+
+ssize_t
+ACE::t_rcv (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int *flags,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::t_rcv (handle, (char *) buf, len, flags);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_recv_timedwait (handle, timeout, val) ==-1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred =
+ ACE_OS::t_rcv (handle, (char *) buf, len, flags);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+#endif /* ACE_HAS_TLI */
+
+ssize_t
+ACE::recv (ACE_HANDLE handle,
+ void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE::recv_i (handle, buf, n);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_recv_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred = ACE::recv_i (handle, buf, n);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+ssize_t
+ACE::recvmsg (ACE_HANDLE handle,
+ struct msghdr *msg,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::recvmsg (handle, msg, flags);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_recv_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred = ACE_OS::recvmsg (handle, msg, flags);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+ssize_t
+ACE::recvfrom (ACE_HANDLE handle,
+ char *buf,
+ int len,
+ int flags,
+ struct sockaddr *addr,
+ int *addrlen,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::recvfrom (handle, buf, len, flags, addr, addrlen);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_recv_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred =
+ ACE_OS::recvfrom (handle, buf, len, flags, addr, addrlen);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+ssize_t
+ACE::recv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int flags,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ n = ACE_OS::recv (handle,
+ static_cast <char *> (buf) + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+ // Check EOF.
+ if (n == 0)
+ return 0;
+
+ // Check for other errors.
+ if (n == -1)
+ {
+ // Check for possible blocking.
+ if (errno == EWOULDBLOCK)
+ {
+ // Wait for the blocking to subside.
+ int result = ACE::handle_read_ready (handle,
+ 0);
+
+ // Did select() succeed?
+ if (result != -1)
+ {
+ // Blocking subsided. Continue data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Other data transfer or select() failures.
+ return -1;
+ }
+ }
+
+ return static_cast<ssize_t> (bytes_transferred);
+}
+
+ssize_t
+ACE::recv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+ ssize_t result = 0;
+ int error = 0;
+
+ int val = 0;
+ ACE::record_and_set_non_blocking_mode (handle, val);
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ // Since the socket is in non-blocking mode, this call will not
+ // block.
+ n = ACE_OS::recv (handle,
+ static_cast <char *> (buf) + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+
+ // Check for errors.
+ if (n == 0 ||
+ n == -1)
+ {
+ // Check for possible blocking.
+ if (n == -1 &&
+ errno == EWOULDBLOCK)
+ {
+ // Wait upto <timeout> for the blocking to subside.
+ int rtn = ACE::handle_read_ready (handle,
+ timeout);
+
+ // Did select() succeed?
+ if (rtn != -1)
+ {
+ // Blocking subsided in <timeout> period. Continue
+ // data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Wait in select() timed out or other data transfer or
+ // select() failures.
+ error = 1;
+ result = n;
+ break;
+ }
+ }
+
+ ACE::restore_non_blocking_mode (handle, val);
+
+ if (error)
+ return result;
+ else
+ return static_cast<ssize_t> (bytes_transferred);
+}
+
+#if defined (ACE_HAS_TLI)
+
+ssize_t
+ACE::t_rcv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int *flags,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ n = ACE_OS::t_rcv (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+ // Check EOF.
+ if (n == 0)
+ return 0;
+
+ // Check for other errors.
+ if (n == -1)
+ {
+ // Check for possible blocking.
+ if (errno == EWOULDBLOCK)
+ {
+ // Wait for the blocking to subside.
+ int result = ACE::handle_read_ready (handle,
+ 0);
+
+ // Did select() succeed?
+ if (result != -1)
+ {
+ // Blocking subsided. Continue data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Other data transfer or select() failures.
+ return -1;
+ }
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::t_rcv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int *flags,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+ ssize_t result = 0;
+ int error = 0;
+
+ int val = 0;
+ ACE::record_and_set_non_blocking_mode (handle, val);
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ // Since the socket is in non-blocking mode, this call will not
+ // block.
+ n = ACE_OS::t_rcv (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+
+ // Check for errors.
+ if (n == 0 ||
+ n == -1)
+ {
+ // Check for possible blocking.
+ if (n == -1 &&
+ errno == EWOULDBLOCK)
+ {
+ // Wait upto <timeout> for the blocking to subside.
+ int rtn = ACE::handle_read_ready (handle,
+ timeout);
+
+ // Did select() succeed?
+ if (rtn != -1)
+ {
+ // Blocking subsided in <timeout> period. Continue
+ // data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Wait in select() timed out or other data transfer or
+ // select() failures.
+ error = 1;
+ result = n;
+ break;
+ }
+ }
+
+ ACE::restore_non_blocking_mode (handle, val);
+
+ if (error)
+ return result;
+ else
+ return bytes_transferred;
+}
+
+#endif /* ACE_HAS_TLI */
+
+ssize_t
+ACE::recv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ n = ACE::recv_i (handle,
+ static_cast <char *> (buf) + bytes_transferred,
+ len - bytes_transferred);
+ // Check EOF.
+ if (n == 0)
+ {
+ return 0;
+ }
+ // Check for other errors.
+ if (n == -1)
+ {
+ // Check for possible blocking.
+ if (errno == EWOULDBLOCK)
+ {
+ // Wait for the blocking to subside.
+ int result = ACE::handle_read_ready (handle,
+ 0);
+
+ // Did select() succeed?
+ if (result != -1)
+ {
+ // Blocking subsided. Continue data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Other data transfer or select() failures.
+ return -1;
+ }
+ }
+
+ return static_cast<ssize_t> (bytes_transferred);
+}
+
+ssize_t
+ACE::recv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+ ssize_t result = 0;
+ int error = 0;
+
+ int val = 0;
+ ACE::record_and_set_non_blocking_mode (handle, val);
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ // Since the socket is in non-blocking mode, this call will not
+ // block.
+ n = ACE::recv_i (handle,
+ static_cast <char *> (buf) + bytes_transferred,
+ len - bytes_transferred);
+
+ // Check for errors.
+ if (n == 0 ||
+ n == -1)
+ {
+ // Check for possible blocking.
+ if (n == -1 &&
+ errno == EWOULDBLOCK)
+ {
+ // Wait upto <timeout> for the blocking to subside.
+ int rtn = ACE::handle_read_ready (handle,
+ timeout);
+
+ // Did select() succeed?
+ if (rtn != -1)
+ {
+ // Blocking subsided in <timeout> period. Continue
+ // data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Wait in select() timed out or other data transfer or
+ // select() failures.
+ error = 1;
+ result = n;
+ break;
+ }
+ }
+
+ ACE::restore_non_blocking_mode (handle, val);
+
+ if (error)
+ return result;
+ else
+ return static_cast<ssize_t> (bytes_transferred);
+}
+
+// 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::recv (ACE_HANDLE handle, size_t n, ...)
+{
+ va_list argp;
+ int total_tuples = static_cast<int> (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 (int 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::recvv (handle, iovp, total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+ssize_t
+ACE::recvv (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::recvv (handle, iov, iovcnt);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_recv_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred = ACE_OS::recvv (handle, iov, iovcnt);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+ssize_t
+ACE::recvv_n_i (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+
+ for (int s = 0;
+ s < iovcnt;
+ )
+ {
+ // Try to transfer as much of the remaining data as possible.
+ ssize_t n = ACE_OS::recvv (handle,
+ iov + s,
+ iovcnt - s);
+ // Check EOF.
+ if (n == 0)
+ return 0;
+
+ // Check for other errors.
+ if (n == -1)
+ {
+ // Check for possible blocking.
+ if (errno == EWOULDBLOCK)
+ {
+ // Wait for the blocking to subside.
+ int result = ACE::handle_read_ready (handle,
+ 0);
+
+ // Did select() succeed?
+ if (result != -1)
+ {
+ // Blocking subsided. Continue data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Other data transfer or select() failures.
+ return -1;
+ }
+
+ for (bytes_transferred += n;
+ s < iovcnt
+ && n >= static_cast<ssize_t> (iov[s].iov_len);
+ s++)
+ n -= iov[s].iov_len;
+
+ if (n != 0)
+ {
+ char *base = static_cast<char *> (iov[s].iov_base);
+ iov[s].iov_base = base + n;
+ iov[s].iov_len = iov[s].iov_len - n;
+ }
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::recvv_n_i (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+ ssize_t result = 0;
+ int error = 0;
+
+ int val = 0;
+ ACE::record_and_set_non_blocking_mode (handle, val);
+
+ for (int s = 0;
+ s < iovcnt;
+ )
+ {
+ // Try to transfer as much of the remaining data as possible.
+ // Since the socket is in non-blocking mode, this call will not
+ // block.
+ ssize_t n = ACE_OS::recvv (handle,
+ iov + s,
+ iovcnt - s);
+
+ // Check for errors.
+ if (n == 0 ||
+ n == -1)
+ {
+ // Check for possible blocking.
+ if (n == -1 &&
+ errno == EWOULDBLOCK)
+ {
+ // Wait upto <timeout> for the blocking to subside.
+ int rtn = ACE::handle_read_ready (handle,
+ timeout);
+
+ // Did select() succeed?
+ if (rtn != -1)
+ {
+ // Blocking subsided in <timeout> period. Continue
+ // data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Wait in select() timed out or other data transfer or
+ // select() failures.
+ error = 1;
+ result = n;
+ break;
+ }
+
+ for (bytes_transferred += n;
+ s < iovcnt
+ && n >= static_cast<ssize_t> (iov[s].iov_len);
+ s++)
+ n -= iov[s].iov_len;
+
+ if (n != 0)
+ {
+ char *base = reinterpret_cast<char *> (iov[s].iov_base);
+ iov[s].iov_base = base + n;
+ iov[s].iov_len = iov[s].iov_len - n;
+ }
+ }
+
+ ACE::restore_non_blocking_mode (handle, val);
+
+ if (error)
+ return result;
+ else
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::recv_n (ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+
+ while (message_block != 0)
+ {
+ // Our current message block chain.
+ const ACE_Message_Block *current_message_block = message_block;
+
+ while (current_message_block != 0)
+ {
+ size_t current_message_block_length =
+ current_message_block->length ();
+ char *this_rd_ptr = current_message_block->rd_ptr ();
+
+ // Check if this block has any space for incoming data.
+ while (current_message_block_length > 0)
+ {
+ u_long const this_chunk_length =
+ ACE_Utils::truncate_cast<u_long> (
+ current_message_block_length);
+
+ // Collect the data in the iovec.
+ iov[iovcnt].iov_base = this_rd_ptr;
+ iov[iovcnt].iov_len = this_chunk_length;
+ current_message_block_length -= this_chunk_length;
+ this_rd_ptr += this_chunk_length;
+
+ // Increment iovec counter.
+ ++iovcnt;
+
+ // The buffer is full make a OS call. @@ TODO find a way to
+ // find ACE_IOV_MAX for platforms that do not define it rather
+ // than simply setting ACE_IOV_MAX to some arbitrary value such
+ // as 16.
+ if (iovcnt == ACE_IOV_MAX)
+ {
+ size_t current_transfer = 0;
+
+ ssize_t const result = ACE::recvv_n (handle,
+ iov,
+ iovcnt,
+ timeout,
+ &current_transfer);
+
+ // Add to total bytes transferred.
+ bytes_transferred += current_transfer;
+
+ // Errors.
+ if (result == -1 || result == 0)
+ return result;
+
+ // Reset iovec counter.
+ iovcnt = 0;
+ }
+ }
+
+ // Select the next message block in the chain.
+ current_message_block = current_message_block->cont ();
+ }
+
+ // Selection of the next message block chain.
+ message_block = message_block->next ();
+ }
+
+ // Check for remaining buffers to be sent. This will happen when
+ // ACE_IOV_MAX is not a multiple of the number of message blocks.
+ if (iovcnt != 0)
+ {
+ size_t current_transfer = 0;
+
+ ssize_t const result = ACE::recvv_n (handle,
+ iov,
+ iovcnt,
+ timeout,
+ &current_transfer);
+
+ // Add to total bytes transferred.
+ bytes_transferred += current_transfer;
+
+ // Errors.
+ if (result == -1 || result == 0)
+ return result;
+ }
+
+ // Return total bytes transferred.
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::send (ACE_HANDLE handle,
+ const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::send (handle, (const char *) buf, n, flags);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_send_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred = ACE_OS::send (handle, (const char *) buf, n, flags);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+#if defined (ACE_HAS_TLI)
+
+ssize_t
+ACE::t_snd (ACE_HANDLE handle,
+ const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::t_snd (handle, (const char *) buf, n, flags);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_send_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred = ACE_OS::t_snd (handle, (const char *) buf, n, flags);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+#endif /* ACE_HAS_TLI */
+
+ssize_t
+ACE::send (ACE_HANDLE handle,
+ const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE::send_i (handle, buf, n);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_send_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred = ACE::send_i (handle, buf, n);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+ssize_t
+ACE::sendmsg (ACE_HANDLE handle,
+ const struct msghdr *msg,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::sendmsg (handle, msg, flags);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_send_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred = ACE_OS::sendmsg (handle, msg, flags);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+ssize_t
+ACE::sendto (ACE_HANDLE handle,
+ const char *buf,
+ int len,
+ int flags,
+ const struct sockaddr *addr,
+ int addrlen,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::sendto (handle, buf, len, flags, addr, addrlen);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_send_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred =
+ ACE_OS::sendto (handle, buf, len, flags, addr, addrlen);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+ssize_t
+ACE::send_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ n = ACE_OS::send (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+ // Check EOF.
+ if (n == 0)
+ return 0;
+
+ // Check for other errors.
+ if (n == -1)
+ {
+ // Check for possible blocking.
+#if defined (ACE_WIN32)
+ if (errno == EWOULDBLOCK) // If enobufs no need to loop
+#else
+ if (errno == EWOULDBLOCK || errno == ENOBUFS)
+#endif /* ACE_WIN32 */
+ {
+ // Wait for the blocking to subside.
+ int result = ACE::handle_write_ready (handle,
+ 0);
+
+ // Did select() succeed?
+ if (result != -1)
+ {
+ // Blocking subsided. Continue data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Other data transfer or select() failures.
+ return -1;
+ }
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::send_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+ ssize_t result = 0;
+ int error = 0;
+
+ int val = 0;
+ ACE::record_and_set_non_blocking_mode (handle, val);
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ // Since the socket is in non-blocking mode, this call will not
+ // block.
+ n = ACE_OS::send (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+
+ // Check for errors.
+ if (n == 0 ||
+ n == -1)
+ {
+ // Check for possible blocking.
+ if (n == -1 &&
+ errno == EWOULDBLOCK || errno == ENOBUFS)
+ {
+ // Wait upto <timeout> for the blocking to subside.
+ int rtn = ACE::handle_write_ready (handle,
+ timeout);
+
+ // Did select() succeed?
+ if (rtn != -1)
+ {
+ // Blocking subsided in <timeout> period. Continue
+ // data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Wait in select() timed out or other data transfer or
+ // select() failures.
+ error = 1;
+ result = n;
+ break;
+ }
+ }
+
+ ACE::restore_non_blocking_mode (handle, val);
+
+ if (error)
+ return result;
+ else
+ return bytes_transferred;
+}
+
+#if defined (ACE_HAS_TLI)
+
+ssize_t
+ACE::t_snd_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ n = ACE_OS::t_snd (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+ // Check EOF.
+ if (n == 0)
+ return 0;
+
+ // Check for other errors.
+ if (n == -1)
+ {
+ // Check for possible blocking.
+ if (errno == EWOULDBLOCK || errno == ENOBUFS)
+ {
+ // Wait for the blocking to subside.
+ int result = ACE::handle_write_ready (handle,
+ 0);
+
+ // Did select() succeed?
+ if (result != -1)
+ {
+ // Blocking subsided. Continue data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Other data transfer or select() failures.
+ return -1;
+ }
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::t_snd_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+ ssize_t result = 0;
+ int error = 0;
+
+ int val = 0;
+ ACE::record_and_set_non_blocking_mode (handle, val);
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ // Since the socket is in non-blocking mode, this call will not
+ // block.
+ n = ACE_OS::t_snd (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+
+ // Check for errors.
+ if (n == 0 ||
+ n == -1)
+ {
+ // Check for possible blocking.
+ if (n == -1 &&
+ errno == EWOULDBLOCK || errno == ENOBUFS)
+ {
+ // Wait upto <timeout> for the blocking to subside.
+ int rtn = ACE::handle_write_ready (handle,
+ timeout);
+
+ // Did select() succeed?
+ if (rtn != -1)
+ {
+ // Blocking subsided in <timeout> period. Continue
+ // data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Wait in select() timed out or other data transfer or
+ // select() failures.
+ error = 1;
+ result = n;
+ break;
+ }
+ }
+
+ ACE::restore_non_blocking_mode (handle, val);
+
+ if (error)
+ return result;
+ else
+ return bytes_transferred;
+}
+
+#endif /* ACE_HAS_TLI */
+
+ssize_t
+ACE::send_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ n = ACE::send_i (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred);
+ // Check EOF.
+ if (n == 0)
+ return 0;
+
+ // Check for other errors.
+ if (n == -1)
+ {
+ // Check for possible blocking.
+ if (errno == EWOULDBLOCK || errno == ENOBUFS)
+ {
+ // Wait for the blocking to subside.
+ int result = ACE::handle_write_ready (handle,
+ 0);
+
+ // Did select() succeed?
+ if (result != -1)
+ {
+ // Blocking subsided. Continue data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Other data transfer or select() failures.
+ return -1;
+ }
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::send_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+ ssize_t result = 0;
+ int error = 0;
+
+ int val = 0;
+ ACE::record_and_set_non_blocking_mode (handle, val);
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ // Try to transfer as much of the remaining data as possible.
+ // Since the socket is in non-blocking mode, this call will not
+ // block.
+ n = ACE::send_i (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred);
+
+ // Check for errors.
+ if (n == 0 ||
+ n == -1)
+ {
+ // Check for possible blocking.
+ if (n == -1 &&
+ errno == EWOULDBLOCK || errno == ENOBUFS)
+ {
+ // Wait upto <timeout> for the blocking to subside.
+ int rtn = ACE::handle_write_ready (handle,
+ timeout);
+
+ // Did select() succeed?
+ if (rtn != -1)
+ {
+ // Blocking subsided in <timeout> period. Continue
+ // data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Wait in select() timed out or other data transfer or
+ // select() failures.
+ error = 1;
+ result = n;
+ break;
+ }
+ }
+
+ ACE::restore_non_blocking_mode (handle, val);
+
+ if (error)
+ return result;
+ else
+ return bytes_transferred;
+}
+
+// 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::send (ACE_HANDLE handle, size_t n, ...)
+{
+ va_list argp;
+ int total_tuples = static_cast<int> (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 (int 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::sendv (handle, iovp, total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+ssize_t
+ACE::sendv (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout)
+{
+ if (timeout == 0)
+ return ACE_OS::sendv (handle, iov, iovcnt);
+ else
+ {
+ int val = 0;
+ if (ACE::enter_send_timedwait (handle, timeout, val) == -1)
+ return -1;
+ else
+ {
+ ssize_t bytes_transferred = ACE_OS::sendv (handle, iov, iovcnt);
+ ACE::restore_non_blocking_mode (handle, val);
+ return bytes_transferred;
+ }
+ }
+}
+
+ssize_t
+ACE::sendv_n_i (ACE_HANDLE handle,
+ const iovec *i,
+ int iovcnt,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+
+ iovec *iov = const_cast<iovec *> (i);
+
+ for (int s = 0;
+ s < iovcnt;
+ )
+ {
+ // Try to transfer as much of the remaining data as possible.
+ ssize_t n = ACE_OS::sendv (handle,
+ iov + s,
+ iovcnt - s);
+ // Check EOF.
+ if (n == 0)
+ return 0;
+
+ // Check for other errors.
+ if (n == -1)
+ {
+ // Check for possible blocking.
+ if (errno == EWOULDBLOCK || errno == ENOBUFS)
+ {
+ // Wait for the blocking to subside.
+ int result = ACE::handle_write_ready (handle,
+ 0);
+
+ // Did select() succeed?
+ if (result != -1)
+ {
+ // Blocking subsided. Continue data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Other data transfer or select() failures.
+ return -1;
+ }
+
+ for (bytes_transferred += n;
+ s < iovcnt
+ && n >= static_cast<ssize_t> (iov[s].iov_len);
+ s++)
+ n -= iov[s].iov_len;
+
+ if (n != 0)
+ {
+ char *base = reinterpret_cast<char *> (iov[s].iov_base);
+ iov[s].iov_base = base + n;
+ iov[s].iov_len = iov[s].iov_len - n;
+ }
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::sendv_n_i (ACE_HANDLE handle,
+ const iovec *i,
+ int iovcnt,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+ ssize_t result = 0;
+ int error = 0;
+
+ int val = 0;
+ ACE::record_and_set_non_blocking_mode (handle, val);
+
+ iovec *iov = const_cast<iovec *> (i);
+
+ for (int s = 0;
+ s < iovcnt;
+ )
+ {
+ // Try to transfer as much of the remaining data as possible.
+ // Since the socket is in non-blocking mode, this call will not
+ // block.
+ ssize_t n = ACE_OS::sendv (handle,
+ iov + s,
+ iovcnt - s);
+
+ // Check for errors.
+ if (n == 0 ||
+ n == -1)
+ {
+ // Check for possible blocking.
+ if (n == -1 &&
+ errno == EWOULDBLOCK || errno == ENOBUFS)
+ {
+ // Wait upto <timeout> for the blocking to subside.
+ int rtn = ACE::handle_write_ready (handle,
+ timeout);
+
+ // Did select() succeed?
+ if (rtn != -1)
+ {
+ // Blocking subsided in <timeout> period. Continue
+ // data transfer.
+ n = 0;
+ continue;
+ }
+ }
+
+ // Wait in select() timed out or other data transfer or
+ // select() failures.
+ error = 1;
+ result = n;
+ break;
+ }
+
+ for (bytes_transferred += n;
+ s < iovcnt
+ && n >= static_cast<ssize_t> (iov[s].iov_len);
+ s++)
+ n -= iov[s].iov_len;
+
+ if (n != 0)
+ {
+ char *base = reinterpret_cast<char *> (iov[s].iov_base);
+ iov[s].iov_base = base + n;
+ iov[s].iov_len = iov[s].iov_len - n;
+ }
+ }
+
+ ACE::restore_non_blocking_mode (handle, val);
+
+ if (error)
+ return result;
+ else
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::write_n (ACE_HANDLE handle,
+ const ACE_Message_Block *message_block,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+
+ while (message_block != 0)
+ {
+ // Our current message block chain.
+ const ACE_Message_Block *current_message_block = message_block;
+
+ while (current_message_block != 0)
+ {
+ size_t current_message_block_length =
+ current_message_block->length ();
+ char *this_block_ptr = current_message_block->rd_ptr ();
+
+ // Check if this block has any data to be sent.
+ while (current_message_block_length > 0)
+ {
+ u_long const this_chunk_length =
+ ACE_Utils::truncate_cast<u_long> (
+ current_message_block_length);
+
+ // Collect the data in the iovec.
+ iov[iovcnt].iov_base = this_block_ptr;
+ iov[iovcnt].iov_len = this_chunk_length;
+ current_message_block_length -= this_chunk_length;
+ this_block_ptr += this_chunk_length;
+
+ // Increment iovec counter.
+ ++iovcnt;
+
+ // The buffer is full make a OS call. @@ TODO find a way to
+ // find ACE_IOV_MAX for platforms that do not define it rather
+ // than simply setting ACE_IOV_MAX to some arbitrary value such
+ // as 16.
+ if (iovcnt == ACE_IOV_MAX)
+ {
+ size_t current_transfer = 0;
+
+ ssize_t const result = ACE::writev_n (handle,
+ iov,
+ iovcnt,
+ &current_transfer);
+
+ // Add to total bytes transferred.
+ bytes_transferred += current_transfer;
+
+ // Errors.
+ if (result == -1 || result == 0)
+ return result;
+
+ // Reset iovec counter.
+ iovcnt = 0;
+ }
+ }
+
+ // Select the next message block in the chain.
+ current_message_block = current_message_block->cont ();
+ }
+
+ // Selection of the next message block chain.
+ message_block = message_block->next ();
+ }
+
+ // Check for remaining buffers to be sent. This will happen when
+ // ACE_IOV_MAX is not a multiple of the number of message blocks.
+ if (iovcnt != 0)
+ {
+ size_t current_transfer = 0;
+
+ ssize_t const result = ACE::writev_n (handle,
+ iov,
+ iovcnt,
+ &current_transfer);
+
+ // Add to total bytes transferred.
+ bytes_transferred += current_transfer;
+
+ // Errors.
+ if (result == -1 || result == 0)
+ return result;
+ }
+
+ // Return total bytes transferred.
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::send_n (ACE_HANDLE handle,
+ const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+
+ while (message_block != 0)
+ {
+ // Our current message block chain.
+ const ACE_Message_Block *current_message_block = message_block;
+
+ while (current_message_block != 0)
+ {
+ char *this_block_ptr = current_message_block->rd_ptr ();
+ size_t current_message_block_length =
+ current_message_block->length ();
+
+ // Check if this block has any data to be sent.
+ while (current_message_block_length > 0)
+ {
+ u_long const this_chunk_length =
+ ACE_Utils::truncate_cast<u_long> (
+ current_message_block_length);
+
+ // Collect the data in the iovec.
+ iov[iovcnt].iov_base = this_block_ptr;
+ iov[iovcnt].iov_len = this_chunk_length;
+ current_message_block_length -= this_chunk_length;
+ this_block_ptr += this_chunk_length;
+
+ // Increment iovec counter.
+ ++iovcnt;
+
+ // The buffer is full make a OS call. @@ TODO find a way to
+ // find ACE_IOV_MAX for platforms that do not define it rather
+ // than simply setting ACE_IOV_MAX to some arbitrary value such
+ // as 16.
+ if (iovcnt == ACE_IOV_MAX)
+ {
+ size_t current_transfer = 0;
+
+ ssize_t const result = ACE::sendv_n (handle,
+ iov,
+ iovcnt,
+ timeout,
+ &current_transfer);
+
+ // Add to total bytes transferred.
+ bytes_transferred += current_transfer;
+
+ // Errors.
+ if (result == -1 || result == 0)
+ return result;
+
+ // Reset iovec counter.
+ iovcnt = 0;
+ }
+ }
+
+ // Select the next message block in the chain.
+ current_message_block = current_message_block->cont ();
+ }
+
+ // Selection of the next message block chain.
+ message_block = message_block->next ();
+ }
+
+ // Check for remaining buffers to be sent. This will happen when
+ // ACE_IOV_MAX is not a multiple of the number of message blocks.
+ if (iovcnt != 0)
+ {
+ size_t current_transfer = 0;
+
+ ssize_t const result = ACE::sendv_n (handle,
+ iov,
+ iovcnt,
+ timeout,
+ &current_transfer);
+
+ // Add to total bytes transferred.
+ bytes_transferred += current_transfer;
+
+ // Errors.
+ if (result == -1 || result == 0)
+ return result;
+ }
+
+ // Return total bytes transferred.
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::readv_n (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+
+ for (int s = 0;
+ s < iovcnt;
+ )
+ {
+ ssize_t n = ACE_OS::readv (handle,
+ iov + s,
+ iovcnt - s);
+
+ if (n == -1 || n == 0)
+ return n;
+
+ for (bytes_transferred += n;
+ s < iovcnt
+ && n >= static_cast<ssize_t> (iov[s].iov_len);
+ s++)
+ n -= iov[s].iov_len;
+
+ if (n != 0)
+ {
+ char *base = reinterpret_cast<char *> (iov[s].iov_base);
+ iov[s].iov_base = base + n;
+ iov[s].iov_len = iov[s].iov_len - n;
+ }
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE::writev_n (ACE_HANDLE handle,
+ const iovec *i,
+ int iovcnt,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ bytes_transferred = 0;
+
+ iovec *iov = const_cast<iovec *> (i);
+
+ for (int s = 0;
+ s < iovcnt;
+ )
+ {
+ ssize_t n = ACE_OS::writev (handle,
+ iov + s,
+ iovcnt - s);
+ if (n == -1 || n == 0)
+ return n;
+
+ for (bytes_transferred += n;
+ s < iovcnt
+ && n >= static_cast<ssize_t> (iov[s].iov_len);
+ s++)
+ n -= iov[s].iov_len;
+
+ if (n != 0)
+ {
+ char *base = reinterpret_cast<char *> (iov[s].iov_base);
+ iov[s].iov_base = base + n;
+ iov[s].iov_len = iov[s].iov_len - n;
+ }
+ }
+
+ return bytes_transferred;
+}
+
+int
+ACE::handle_ready (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout,
+ int read_ready,
+ int write_ready,
+ int exception_ready)
+{
+#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT)
+ ACE_UNUSED_ARG (write_ready);
+ ACE_UNUSED_ARG (exception_ready);
+
+ struct pollfd fds;
+
+ fds.fd = handle;
+ fds.events = read_ready ? POLLIN : POLLOUT;
+ fds.revents = 0;
+
+ int result = ACE_OS::poll (&fds, 1, timeout);
+#else
+ ACE_Handle_Set handle_set;
+ handle_set.set_bit (handle);
+
+ // Wait for data or for the timeout to elapse.
+ int select_width;
+# if defined (ACE_WIN32)
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles.
+ select_width = 0;
+# else
+ select_width = int (handle) + 1;
+# endif /* ACE_WIN64 */
+ int result = ACE_OS::select (select_width,
+ read_ready ? handle_set.fdset () : 0, // read_fds.
+ write_ready ? handle_set.fdset () : 0, // write_fds.
+ exception_ready ? handle_set.fdset () : 0, // exception_fds.
+ timeout);
+
+#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */
+
+ switch (result)
+ {
+ case 0: // Timer expired.
+ errno = ETIME;
+ /* FALLTHRU */
+ case -1: // we got here directly - select() returned -1.
+ return -1;
+ case 1: // Handle has data.
+ /* FALLTHRU */
+ default: // default is case result > 0; return a
+ // ACE_ASSERT (result == 1);
+ return result;
+ }
+}
+
+int
+ACE::enter_recv_timedwait (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout,
+ int &val)
+{
+ int result = ACE::handle_read_ready (handle,
+ timeout);
+
+ if (result == -1)
+ return -1;
+
+ ACE::record_and_set_non_blocking_mode (handle,
+ val);
+
+ return result;
+}
+
+int
+ACE::enter_send_timedwait (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout,
+ int &val)
+{
+ int result = ACE::handle_write_ready (handle,
+ timeout);
+
+ if (result == -1)
+ return -1;
+
+ ACE::record_and_set_non_blocking_mode (handle,
+ val);
+
+ return result;
+}
+
+void
+ACE::record_and_set_non_blocking_mode (ACE_HANDLE handle,
+ int &val)
+{
+ // We need to record whether we are already *in* nonblocking mode,
+ // so that we can correctly reset the state when we're done.
+ val = ACE::get_flags (handle);
+
+ if (ACE_BIT_DISABLED (val, ACE_NONBLOCK))
+ // Set the handle into non-blocking mode if it's not already in
+ // it.
+ ACE::set_flags (handle, ACE_NONBLOCK);
+}
+
+void
+ACE::restore_non_blocking_mode (ACE_HANDLE handle,
+ int val)
+{
+ if (ACE_BIT_DISABLED (val,
+ ACE_NONBLOCK))
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ // Only disable ACE_NONBLOCK if we weren't in non-blocking mode
+ // originally.
+ ACE::clr_flags (handle, ACE_NONBLOCK);
+ }
+}
+
+
+// Format buffer into printable format. This is useful for debugging.
+// Portions taken from mdump by J.P. Knight (J.P.Knight@lut.ac.uk)
+// Modifications by Todd Montgomery.
+
+size_t
+ACE::format_hexdump (const char *buffer,
+ size_t size,
+ ACE_TCHAR *obuf,
+ size_t obuf_sz)
+{
+ ACE_TRACE ("ACE::format_hexdump");
+
+ u_char c;
+ ACE_TCHAR textver[16 + 1];
+
+ // We can fit 16 bytes output in text mode per line, 4 chars per byte.
+ size_t maxlen = (obuf_sz / 68) * 16;
+
+ if (size > maxlen)
+ size = maxlen;
+
+ size_t i;
+
+ size_t lines = size / 16;
+ for (i = 0; i < lines; i++)
+ {
+ size_t j;
+
+ for (j = 0 ; j < 16; j++)
+ {
+ c = (u_char) buffer[(i << 4) + j]; // or, buffer[i*16+j]
+ ACE_OS::sprintf (obuf,
+ ACE_TEXT ("%02x "),
+ c);
+ obuf += 3;
+ if (j == 7)
+ {
+ ACE_OS::sprintf (obuf,
+ ACE_TEXT (" "));
+ ++obuf;
+ }
+ textver[j] = ACE_OS::ace_isprint (c) ? c : '.';
+ }
+
+ textver[j] = 0;
+
+ ACE_OS::sprintf (obuf,
+ ACE_TEXT (" %s\n"),
+ textver);
+
+ while (*obuf != '\0')
+ ++obuf;
+ }
+
+ if (size % 16)
+ {
+ for (i = 0 ; i < size % 16; i++)
+ {
+ c = (u_char) buffer[size - size % 16 + i];
+ ACE_OS::sprintf (obuf,
+ ACE_TEXT ("%02x "),
+ c);
+ obuf += 3;
+ if (i == 7)
+ {
+ ACE_OS::sprintf (obuf,
+ ACE_TEXT (" "));
+ ++obuf;
+ }
+ textver[i] = ACE_OS::ace_isprint (c) ? c : '.';
+ }
+
+ for (i = size % 16; i < 16; i++)
+ {
+ ACE_OS::sprintf (obuf,
+ ACE_TEXT (" "));
+ obuf += 3;
+ if (i == 7)
+ {
+ ACE_OS::sprintf (obuf,
+ ACE_TEXT (" "));
+ ++obuf;
+ }
+ textver[i] = ' ';
+ }
+
+ textver[i] = 0;
+ ACE_OS::sprintf (obuf,
+ ACE_TEXT (" %s\n"),
+ textver);
+ }
+ return size;
+}
+
+// Returns the current timestamp in the form
+// "hour:minute:second:microsecond." The month, day, and year are
+// also stored in the beginning of the date_and_time array.
+
+ACE_TCHAR *
+ACE::timestamp (ACE_TCHAR date_and_time[],
+ int date_and_timelen,
+ int return_pointer_to_first_digit)
+{
+ //ACE_TRACE ("ACE::timestamp");
+
+ if (date_and_timelen < 35)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+
+#if defined (WIN32)
+ // Emulate Unix. Win32 does NOT support all the UNIX versions
+ // below, so DO we need this ifdef.
+ static const ACE_TCHAR *day_of_week_name[] =
+ {
+ ACE_TEXT ("Sun"),
+ ACE_TEXT ("Mon"),
+ ACE_TEXT ("Tue"),
+ ACE_TEXT ("Wed"),
+ ACE_TEXT ("Thu"),
+ ACE_TEXT ("Fri"),
+ ACE_TEXT ("Sat")
+ };
+
+ static const ACE_TCHAR *month_name[] =
+ {
+ ACE_TEXT ("Jan"),
+ ACE_TEXT ("Feb"),
+ ACE_TEXT ("Mar"),
+ ACE_TEXT ("Apr"),
+ ACE_TEXT ("May"),
+ ACE_TEXT ("Jun"),
+ ACE_TEXT ("Jul"),
+ ACE_TEXT ("Aug"),
+ ACE_TEXT ("Sep"),
+ ACE_TEXT ("Oct"),
+ ACE_TEXT ("Nov"),
+ ACE_TEXT ("Dec")
+ };
+
+ SYSTEMTIME local;
+ ::GetLocalTime (&local);
+
+ ACE_OS::sprintf (date_and_time,
+ ACE_TEXT ("%3s %3s %2d %04d %02d:%02d:%02d.%06d"),
+ day_of_week_name[local.wDayOfWeek],
+ month_name[local.wMonth - 1],
+ (int) local.wDay,
+ (int) local.wYear,
+ (int) local.wHour,
+ (int) local.wMinute,
+ (int) local.wSecond,
+ (int) (local.wMilliseconds * 1000));
+ return &date_and_time[15 + (return_pointer_to_first_digit != 0)];
+#else /* UNIX */
+ ACE_TCHAR timebuf[26]; // This magic number is based on the ctime(3c) man page.
+ ACE_Time_Value cur_time = ACE_OS::gettimeofday ();
+ time_t secs = cur_time.sec ();
+
+ ACE_OS::ctime_r (&secs,
+ timebuf,
+ sizeof timebuf);
+ // date_and_timelen > sizeof timebuf!
+ ACE_OS::strsncpy (date_and_time,
+ timebuf,
+ date_and_timelen);
+ ACE_TCHAR yeartmp[5];
+ ACE_OS::strsncpy (yeartmp,
+ &date_and_time[20],
+ 5);
+ ACE_TCHAR timetmp[9];
+ ACE_OS::strsncpy (timetmp,
+ &date_and_time[11],
+ 9);
+ ACE_OS::sprintf (&date_and_time[11],
+# if defined (ACE_USES_WCHAR)
+ ACE_TEXT ("%ls %ls.%06ld"),
+# else
+ ACE_TEXT ("%s %s.%06ld"),
+# endif /* ACE_USES_WCHAR */
+ yeartmp,
+ timetmp,
+ cur_time.usec ());
+ date_and_time[33] = '\0';
+ return &date_and_time[15 + (return_pointer_to_first_digit != 0)];
+#endif /* WIN32 */
+}
+
+// This function rounds the request to a multiple of the page size.
+
+size_t
+ACE::round_to_pagesize (size_t len)
+{
+ ACE_TRACE ("ACE::round_to_pagesize");
+
+ if (ACE::pagesize_ == 0)
+ ACE::pagesize_ = ACE_OS::getpagesize ();
+
+ return (len + (ACE::pagesize_ - 1)) & ~(ACE::pagesize_ - 1);
+}
+
+size_t
+ACE::round_to_allocation_granularity (size_t len)
+{
+ ACE_TRACE ("ACE::round_to_allocation_granularity");
+
+ if (ACE::allocation_granularity_ == 0)
+ ACE::allocation_granularity_ = ACE_OS::allocation_granularity ();
+
+ return (len + (ACE::allocation_granularity_ - 1)) & ~(ACE::allocation_granularity_ - 1);
+}
+
+ACE_HANDLE
+ACE::handle_timed_complete (ACE_HANDLE h,
+ const ACE_Time_Value *timeout,
+ int is_tli)
+{
+ ACE_TRACE ("ACE::handle_timed_complete");
+
+#if !defined (ACE_WIN32) && defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT)
+
+ struct pollfd fds;
+
+ fds.fd = h;
+ fds.events = POLLIN | POLLOUT;
+ fds.revents = 0;
+
+#else
+ ACE_Handle_Set rd_handles;
+ ACE_Handle_Set wr_handles;
+
+ rd_handles.set_bit (h);
+ wr_handles.set_bit (h);
+#endif /* !ACE_WIN32 && ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */
+
+#if defined (ACE_WIN32)
+ // Winsock is different - it sets the exception bit for failed connect,
+ // unlike other platforms, where the read bit is set.
+ ACE_Handle_Set ex_handles;
+ ex_handles.set_bit (h);
+#endif /* ACE_WIN32 */
+
+ bool need_to_check = false;
+ bool known_failure = false;
+
+#if defined (ACE_WIN32)
+ int n = ACE_OS::select (0, // Ignored on Windows: int (h) + 1,
+ 0,
+ wr_handles,
+ ex_handles,
+ timeout);
+#else
+# if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT)
+
+ int n = ACE_OS::poll (&fds, 1, timeout);
+
+# else
+ int n = ACE_OS::select (int (h) + 1,
+ rd_handles,
+ wr_handles,
+ 0,
+ timeout);
+# endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */
+#endif /* ACE_WIN32 */
+
+ // If we failed to connect within the time period allocated by the
+ // caller, then we fail (e.g., the remote host might have been too
+ // busy to accept our call).
+ if (n <= 0)
+ {
+ if (n == 0 && timeout != 0)
+ errno = ETIME;
+ return ACE_INVALID_HANDLE;
+ }
+
+ // Usually, a ready-for-write handle is successfully connected, and
+ // ready-for-read (exception on Win32) is a failure. On fails, we
+ // need to grab the error code via getsockopt. On possible success for
+ // any platform where we can't tell just from select() (e.g. AIX),
+ // we also need to check for success/fail.
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (is_tli);
+
+ // On Win32, ex_handle set indicates a failure. We'll do the check
+ // to try and get an errno value, but the connect failed regardless of
+ // what getsockopt says about the error.
+ if (ex_handles.is_set (h))
+ {
+ need_to_check = true;
+ known_failure = true;
+ }
+#elif defined (ACE_VXWORKS)
+ ACE_UNUSED_ARG (is_tli);
+
+ // Force the check on VxWorks. The read handle for "h" is not set,
+ // so "need_to_check" is false at this point. The write handle is
+ // set, for what it's worth.
+ need_to_check = true;
+#else
+ if (is_tli)
+
+# if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT)
+ need_to_check = (fds.revents & POLLIN) && !(fds.revents & POLLOUT);
+# else
+ need_to_check = rd_handles.is_set (h) && !wr_handles.is_set (h);
+# endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */
+
+ else
+#if defined(AIX)
+ // AIX is broken... both success and failed connect will set the
+ // write handle only, so always check.
+ need_to_check = true;
+#else
+# if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT)
+ need_to_check = (fds.revents & POLLIN);
+# else
+ need_to_check = rd_handles.is_set (h);
+# endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */
+#endif /* AIX */
+#endif /* ACE_WIN32 */
+
+ if (need_to_check)
+ {
+#if defined (SOL_SOCKET) && defined (SO_ERROR)
+ int sock_err = 0;
+ int sock_err_len = sizeof (sock_err);
+ int sockopt_ret = ACE_OS::getsockopt (h, SOL_SOCKET, SO_ERROR,
+ (char *)&sock_err, &sock_err_len);
+ if (sockopt_ret < 0)
+ {
+ h = ACE_INVALID_HANDLE;
+ }
+
+ if (sock_err != 0 || known_failure)
+ {
+ h = ACE_INVALID_HANDLE;
+ errno = sock_err;
+ }
+#else
+ char dummy;
+
+ // The following recv() won't block provided that the
+ // ACE_NONBLOCK flag has not been turned off .
+ n = ACE::recv (h, &dummy, 1, MSG_PEEK);
+
+ // If no data was read/peeked at, check to see if it's because
+ // of a non-connected socket (and therefore an error) or there's
+ // just no data yet.
+ if (n <= 0)
+ {
+ if (n == 0)
+ {
+ errno = ECONNREFUSED;
+ h = ACE_INVALID_HANDLE;
+ }
+ else if (errno != EWOULDBLOCK && errno != EAGAIN)
+ h = ACE_INVALID_HANDLE;
+ }
+#endif
+ }
+
+ // 1. The HANDLE is ready for writing and doesn't need to be checked or
+ // 2. recv() returned an indication of the state of the socket - if there is
+ // either data present, or a recv is legit but there's no data yet,
+ // the connection was successfully established.
+ return h;
+}
+
+// Wait up to <timeout> amount of time to accept a connection.
+
+int
+ACE::handle_timed_accept (ACE_HANDLE listener,
+ ACE_Time_Value *timeout,
+ int restart)
+{
+ ACE_TRACE ("ACE::handle_timed_accept");
+ // Make sure we don't bomb out on erroneous values.
+ if (listener == ACE_INVALID_HANDLE)
+ return -1;
+
+#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT)
+
+ struct pollfd fds;
+
+ fds.fd = listener;
+ fds.events = POLLIN;
+ fds.revents = 0;
+
+#else
+ // Use the select() implementation rather than poll().
+ ACE_Handle_Set rd_handle;
+ rd_handle.set_bit (listener);
+#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */
+
+ // We need a loop here if <restart> is enabled.
+
+ for (;;)
+ {
+#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT)
+
+ int n = ACE_OS::poll (&fds, 1, timeout);
+
+#else
+ int select_width;
+# if defined (ACE_WIN32)
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles.
+ select_width = 0;
+# else
+ select_width = int (listener) + 1;
+# endif /* ACE_WIN32 */
+ int n = ACE_OS::select (select_width,
+ rd_handle, 0, 0,
+ timeout);
+#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */
+
+ switch (n)
+ {
+ case -1:
+ if (errno == EINTR && restart)
+ continue;
+ else
+ return -1;
+ /* NOTREACHED */
+ case 0:
+ if (timeout != 0
+ && timeout->sec () == 0
+ && timeout->usec () == 0)
+ errno = EWOULDBLOCK;
+ else
+ errno = ETIMEDOUT;
+ return -1;
+ /* NOTREACHED */
+ case 1:
+ return 0;
+ /* NOTREACHED */
+ default:
+ errno = EINVAL;
+ return -1;
+ /* NOTREACHED */
+ }
+ }
+}
+
+// Make the current process a UNIX daemon. This is based on Stevens
+// code from APUE.
+
+int
+ACE::daemonize (const ACE_TCHAR pathname[],
+ bool close_all_handles,
+ const ACE_TCHAR program_name[])
+{
+ ACE_TRACE ("ACE::daemonize");
+#if !defined (ACE_LACKS_FORK)
+ pid_t pid = ACE_OS::fork ();
+
+ if (pid == -1)
+ return -1;
+ else if (pid != 0)
+ ACE_OS::exit (0); // Parent exits.
+
+ // 1st child continues.
+ ACE_OS::setsid (); // Become session leader.
+
+ ACE_OS::signal (SIGHUP, SIG_IGN);
+
+ pid = ACE_OS::fork (program_name);
+
+ if (pid != 0)
+ ACE_OS::exit (0); // First child terminates.
+
+ // Second child continues.
+
+ if (pathname != 0)
+ // change working directory.
+ ACE_OS::chdir (pathname);
+
+ ACE_OS::umask (0); // clear our file mode creation mask.
+
+ // Close down the I/O handles.
+ if (close_all_handles)
+ for (int i = ACE::max_handles () - 1; i >= 0; i--)
+ ACE_OS::close (i);
+
+ return 0;
+#else
+ ACE_UNUSED_ARG (pathname);
+ ACE_UNUSED_ARG (close_all_handles);
+ ACE_UNUSED_ARG (program_name);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_LACKS_FORK */
+}
+
+pid_t
+ACE::fork (const ACE_TCHAR *program_name,
+ int avoid_zombies)
+{
+ if (avoid_zombies == 0)
+ return ACE_OS::fork (program_name);
+ else
+ {
+ // This algorithm is adapted from an example in the Stevens book
+ // "Advanced Programming in the Unix Environment" and an item in
+ // Andrew Gierth's Unix Programming FAQ. It creates an orphan
+ // process that's inherited by the init process; init cleans up
+ // when the orphan process terminates.
+ //
+ // Another way to avoid zombies is to ignore or catch the
+ // SIGCHLD signal; we don't use that approach here.
+
+ pid_t pid = ACE_OS::fork ();
+ if (pid == 0)
+ {
+ // The child process forks again to create a grandchild.
+ switch (ACE_OS::fork (program_name))
+ {
+ case 0: // grandchild returns 0.
+ return 0;
+ case -1: // assumes all errnos are < 256
+ ACE_OS::_exit (errno);
+ default: // child terminates, orphaning grandchild
+ ACE_OS::_exit (0);
+ }
+ }
+
+ // Parent process waits for child to terminate.
+ ACE_exitcode status;
+ if (pid < 0 || ACE_OS::waitpid (pid, &status, 0) < 0)
+ return -1;
+
+ // child terminated by calling exit()?
+ if (WIFEXITED ((status)))
+ {
+ // child terminated normally?
+ if (WEXITSTATUS ((status)) == 0)
+ return 1;
+ else
+ errno = WEXITSTATUS ((status));
+ }
+ else
+ // child didn't call exit(); perhaps it received a signal?
+ errno = EINTR;
+
+ return -1;
+ }
+}
+
+int
+ACE::max_handles (void)
+{
+ ACE_TRACE ("ACE::max_handles");
+#if defined (RLIMIT_NOFILE) && !defined (ACE_LACKS_RLIMIT)
+ rlimit rl;
+ int const r = ACE_OS::getrlimit (RLIMIT_NOFILE, &rl);
+# if !defined (RLIM_INFINITY)
+ if (r == 0)
+ return rl.rlim_cur;
+# else
+ if (r == 0 && rl.rlim_cur != RLIM_INFINITY)
+ return rl.rlim_cur;
+ // If == RLIM_INFINITY, fall through to the ACE_LACKS_RLIMIT sections
+# endif /* RLIM_INFINITY */
+#endif /* RLIMIT_NOFILE && !ACE_LACKS_RLIMIT */
+
+#if defined (_SC_OPEN_MAX)
+ return ACE_OS::sysconf (_SC_OPEN_MAX);
+#elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x620)
+ return maxFiles;
+#elif defined (FD_SETSIZE)
+ return FD_SETSIZE;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* _SC_OPEN_MAX */
+}
+
+// Set the number of currently open handles in the process.
+//
+// If NEW_LIMIT == -1 set the limit to the maximum allowable.
+// Otherwise, set it to be the value of NEW_LIMIT.
+
+int
+ACE::set_handle_limit (int new_limit,
+ int increase_limit_only)
+{
+ ACE_TRACE ("ACE::set_handle_limit");
+ int cur_limit = ACE::max_handles ();
+ int max_limit = cur_limit;
+
+ if (cur_limit == -1)
+ return -1;
+
+#if !defined (ACE_LACKS_RLIMIT) && defined (RLIMIT_NOFILE)
+ struct rlimit rl;
+
+ ACE_OS::memset ((void *) &rl, 0, sizeof rl);
+ int r = ACE_OS::getrlimit (RLIMIT_NOFILE, &rl);
+ if (r == 0)
+ max_limit = rl.rlim_max;
+#endif /* ACE_LACKS_RLIMIT */
+
+ if (new_limit == -1)
+ new_limit = max_limit;
+
+ if (new_limit < 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else if (new_limit > cur_limit)
+ {
+ // Increase the limit.
+#if !defined (ACE_LACKS_RLIMIT) && defined (RLIMIT_NOFILE)
+ rl.rlim_cur = new_limit;
+ return ACE_OS::setrlimit (RLIMIT_NOFILE, &rl);
+#elif defined (ACE_LACKS_RLIMIT_NOFILE)
+ return 0;
+#else
+ // Must return EINVAL errno.
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_LACKS_RLIMIT */
+ }
+ else if (increase_limit_only == 0)
+ {
+ // Decrease the limit.
+#if !defined (ACE_LACKS_RLIMIT) && defined (RLIMIT_NOFILE)
+ rl.rlim_cur = new_limit;
+ return ACE_OS::setrlimit (RLIMIT_NOFILE, &rl);
+#else
+ // We give a chance to platforms without RLIMIT to work.
+ // Instead of ACE_NOTSUP_RETURN (0), just return 0 because
+ // new_limit is <= cur_limit, so it's a no-op.
+ return 0;
+#endif /* ACE_LACKS_RLIMIT */
+ }
+
+ return 0;
+}
+
+// Euclid's greatest common divisor algorithm.
+u_long
+ACE::gcd (u_long x, u_long y)
+{
+ while (y != 0)
+ {
+ u_long r = x % y;
+ x = y;
+ y = r;
+ }
+
+ return x;
+}
+
+
+// Calculates the minimum enclosing frame size for the given values.
+u_long
+ACE::minimum_frame_size (u_long period1, u_long period2)
+{
+ // if one of the periods is zero, treat it as though it as
+ // uninitialized and return the other period as the frame size
+ if (0 == period1)
+ {
+ return period2;
+ }
+ if (0 == period2)
+ {
+ return period1;
+ }
+
+ // if neither is zero, find the greatest common divisor of the two periods
+ u_long greatest_common_divisor = ACE::gcd (period1, period2);
+
+ // explicitly consider cases to reduce risk of possible overflow errors
+ if (greatest_common_divisor == 1)
+ {
+ // periods are relative primes: just multiply them together
+ return period1 * period2;
+ }
+ else if (greatest_common_divisor == period1)
+ {
+ // the first period divides the second: return the second
+ return period2;
+ }
+ else if (greatest_common_divisor == period2)
+ {
+ // the second period divides the first: return the first
+ return period1;
+ }
+ else
+ {
+ // the current frame size and the entry's effective period
+ // have a non-trivial greatest common divisor: return the
+ // product of factors divided by those in their gcd.
+ return (period1 * period2) / greatest_common_divisor;
+ }
+}
+
+
+u_long
+ACE::is_prime (const u_long n,
+ const u_long min_factor,
+ const u_long max_factor)
+{
+ if (n > 3)
+ for (u_long factor = min_factor;
+ factor <= max_factor;
+ ++factor)
+ if (n / factor * factor == n)
+ return factor;
+
+ return 0;
+}
+
+const ACE_TCHAR *
+ACE::sock_error (int error)
+{
+#if defined (ACE_WIN32)
+ static ACE_TCHAR unknown_msg[64];
+
+ switch (error)
+ {
+ case WSAVERNOTSUPPORTED:
+ return ACE_TEXT ("version of WinSock not supported");
+ /* NOTREACHED */
+ case WSASYSNOTREADY:
+ return ACE_TEXT ("WinSock not present or not responding");
+ /* NOTREACHED */
+ case WSAEINVAL:
+ return ACE_TEXT ("app version not supported by DLL");
+ /* NOTREACHED */
+ case WSAHOST_NOT_FOUND:
+ return ACE_TEXT ("Authoritive: Host not found");
+ /* NOTREACHED */
+ case WSATRY_AGAIN:
+ return ACE_TEXT ("Non-authoritive: host not found or server failure");
+ /* NOTREACHED */
+ case WSANO_RECOVERY:
+ return ACE_TEXT ("Non-recoverable: refused or not implemented");
+ /* NOTREACHED */
+ case WSANO_DATA:
+ return ACE_TEXT ("Valid name, no data record for type");
+ /* NOTREACHED */
+ /*
+ case WSANO_ADDRESS:
+ return "Valid name, no MX record";
+ */
+ case WSANOTINITIALISED:
+ return ACE_TEXT ("WSA Startup not initialized");
+ /* NOTREACHED */
+ case WSAENETDOWN:
+ return ACE_TEXT ("Network subsystem failed");
+ /* NOTREACHED */
+ case WSAEINPROGRESS:
+ return ACE_TEXT ("Blocking operation in progress");
+ /* NOTREACHED */
+ case WSAEINTR:
+ return ACE_TEXT ("Blocking call cancelled");
+ /* NOTREACHED */
+ case WSAEAFNOSUPPORT:
+ return ACE_TEXT ("address family not supported");
+ /* NOTREACHED */
+ case WSAEMFILE:
+ return ACE_TEXT ("no file handles available");
+ /* NOTREACHED */
+ case WSAENOBUFS:
+ return ACE_TEXT ("no buffer space available");
+ /* NOTREACHED */
+ case WSAEPROTONOSUPPORT:
+ return ACE_TEXT ("specified protocol not supported");
+ /* NOTREACHED */
+ case WSAEPROTOTYPE:
+ return ACE_TEXT ("protocol wrong type for this socket");
+ /* NOTREACHED */
+ case WSAESOCKTNOSUPPORT:
+ return ACE_TEXT ("socket type not supported for address family");
+ /* NOTREACHED */
+ case WSAENOTSOCK:
+ return ACE_TEXT ("handle is not a socket");
+ /* NOTREACHED */
+ case WSAEWOULDBLOCK:
+ return ACE_TEXT ("resource temporarily unavailable");
+ /* NOTREACHED */
+ case WSAEADDRINUSE:
+ return ACE_TEXT ("address already in use");
+ /* NOTREACHED */
+ case WSAECONNABORTED:
+ return ACE_TEXT ("connection aborted");
+ /* NOTREACHED */
+ case WSAECONNRESET:
+ return ACE_TEXT ("connection reset");
+ /* NOTREACHED */
+ case WSAENOTCONN:
+ return ACE_TEXT ("not connected");
+ /* NOTREACHED */
+ case WSAETIMEDOUT:
+ return ACE_TEXT ("connection timed out");
+ /* NOTREACHED */
+ case WSAECONNREFUSED:
+ return ACE_TEXT ("connection refused");
+ /* NOTREACHED */
+ case WSAEHOSTDOWN:
+ return ACE_TEXT ("host down");
+ /* NOTREACHED */
+ case WSAEHOSTUNREACH:
+ return ACE_TEXT ("host unreachable");
+ /* NOTREACHED */
+ case WSAEADDRNOTAVAIL:
+ return ACE_TEXT ("address not available");
+ /* NOTREACHED */
+ case WSAEISCONN:
+ return ACE_TEXT ("socket is already connected");
+ /* NOTREACHED */
+ case WSAENETRESET:
+ return ACE_TEXT ("network dropped connection on reset");
+ /* NOTREACHED */
+ case WSAEMSGSIZE:
+ return ACE_TEXT ("message too long");
+ /* NOTREACHED */
+ case WSAENETUNREACH:
+ return ACE_TEXT ("network is unreachable");
+ /* NOTREACHED */
+ case WSAEFAULT:
+ return ACE_TEXT ("bad address");
+ /* NOTREACHED */
+ case WSAEDISCON:
+ return ACE_TEXT ("graceful shutdown in progress");
+ /* NOTREACHED */
+ case WSAEACCES:
+ return ACE_TEXT ("permission denied");
+ /* NOTREACHED */
+ case WSAESHUTDOWN:
+ return ACE_TEXT ("cannot send after socket shutdown");
+ /* NOTREACHED */
+ case WSAEPROCLIM:
+ return ACE_TEXT ("too many processes");
+ /* NOTREACHED */
+ case WSAEALREADY:
+ return ACE_TEXT ("operation already in progress");
+ /* NOTREACHED */
+ case WSAEPFNOSUPPORT:
+ return ACE_TEXT ("protocol family not supported");
+ /* NOTREACHED */
+ case WSAENOPROTOOPT:
+ return ACE_TEXT ("bad protocol option");
+ /* NOTREACHED */
+ case WSATYPE_NOT_FOUND:
+ return ACE_TEXT ("class type not found");
+ /* NOTREACHED */
+ case WSAEOPNOTSUPP:
+ return ACE_TEXT ("operation not supported");
+ /* NOTREACHED */
+ case WSAEDESTADDRREQ:
+ return ACE_TEXT ("destination address required");
+ /* NOTREACHED */
+ default:
+ ACE_OS::sprintf (unknown_msg, ACE_TEXT ("unknown error: %d"), error);
+ return unknown_msg;
+ /* NOTREACHED */
+ }
+#else
+ ACE_UNUSED_ARG (error);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_WIN32 */
+}
+
+bool
+ACE::is_sock_error (int error)
+{
+#if defined (ACE_WIN32)
+ switch (error)
+ {
+ case WSAVERNOTSUPPORTED:
+ case WSASYSNOTREADY:
+ case WSAEINVAL:
+ case WSAHOST_NOT_FOUND:
+ case WSATRY_AGAIN:
+ case WSANO_RECOVERY:
+ case WSANO_DATA:
+ /*
+ case WSANO_ADDRESS:
+ */
+ case WSANOTINITIALISED:
+ case WSAENETDOWN:
+ case WSAEINPROGRESS:
+ case WSAEINTR:
+ case WSAEAFNOSUPPORT:
+ case WSAEMFILE:
+ case WSAENOBUFS:
+ case WSAEPROTONOSUPPORT:
+ case WSAEPROTOTYPE:
+ case WSAESOCKTNOSUPPORT:
+ case WSAENOTSOCK:
+ case WSAEWOULDBLOCK:
+ case WSAEADDRINUSE:
+ case WSAECONNABORTED:
+ case WSAECONNRESET:
+ case WSAENOTCONN:
+ case WSAETIMEDOUT:
+ case WSAECONNREFUSED:
+ case WSAEHOSTDOWN:
+ case WSAEHOSTUNREACH:
+ case WSAEADDRNOTAVAIL:
+ case WSAEISCONN:
+ case WSAENETRESET:
+ case WSAEMSGSIZE:
+ case WSAENETUNREACH:
+ case WSAEFAULT:
+ case WSAEDISCON:
+ case WSAEACCES:
+ case WSAESHUTDOWN:
+ case WSAEPROCLIM:
+ case WSAEALREADY:
+ case WSAEPFNOSUPPORT:
+ case WSAENOPROTOOPT:
+ case WSATYPE_NOT_FOUND:
+ case WSAEOPNOTSUPP:
+ return true;
+ }
+#else
+ ACE_UNUSED_ARG (error);
+#endif /* ACE_WIN32 */
+ return false;
+}
+
+char *
+ACE::strndup (const char *str, size_t n)
+{
+ const char *t = str;
+ size_t len;
+
+ // Figure out how long this string is (remember, it might not be
+ // NUL-terminated).
+
+ for (len = 0;
+ len < n && *t++ != '\0';
+ len++)
+ continue;
+
+ char *s;
+ ACE_ALLOCATOR_RETURN (s,
+ (char *) ACE_OS::malloc (len + 1),
+ 0);
+ return ACE_OS::strsncpy (s, str, len + 1);
+}
+
+#if defined (ACE_HAS_WCHAR)
+wchar_t *
+ACE::strndup (const wchar_t *str, size_t n)
+{
+ const wchar_t *t = str;
+ size_t len;
+
+ // Figure out how long this string is (remember, it might not be
+ // NUL-terminated).
+
+ for (len = 0;
+ len < n && *t++ != '\0';
+ len++)
+ continue;
+
+ wchar_t *s;
+ ACE_ALLOCATOR_RETURN (s,
+ static_cast<wchar_t *> (
+ ACE_OS::malloc ((len + 1) * sizeof (wchar_t))),
+ 0);
+ return ACE_OS::strsncpy (s, str, len + 1);
+}
+#endif /* ACE_HAS_WCHAR */
+
+char *
+ACE::strnnew (const char *str, size_t n)
+{
+ const char *t = str;
+ size_t len;
+
+ // Figure out how long this string is (remember, it might not be
+ // NUL-terminated).
+
+ for (len = 0;
+ len < n && *t++ != L'\0';
+ len++)
+ continue;
+
+ char *s;
+ ACE_NEW_RETURN (s,
+ char[len + 1],
+ 0);
+ return ACE_OS::strsncpy (s, str, len + 1);
+}
+
+#if defined (ACE_HAS_WCHAR)
+wchar_t *
+ACE::strnnew (const wchar_t *str, size_t n)
+{
+ const wchar_t *t = str;
+ size_t len;
+
+ // Figure out how long this string is (remember, it might not be
+ // NUL-terminated).
+
+ for (len = 0;
+ len < n && *t++ != ACE_TEXT_WIDE ('\0');
+ len++)
+ continue;
+
+ wchar_t *s;
+ ACE_NEW_RETURN (s,
+ wchar_t[len + 1],
+ 0);
+ return ACE_OS::strsncpy (s, str, len + 1);
+}
+#endif /* ACE_HAS_WCHAR */
+
+const char *
+ACE::strend (const char *s)
+{
+ while (*s++ != '\0')
+ continue;
+
+ return s;
+}
+
+#if defined ACE_HAS_WCHAR
+const wchar_t *
+ACE::strend (const wchar_t *s)
+{
+ while (*s++ != ACE_TEXT_WIDE ('\0'))
+ continue;
+
+ return s;
+}
+#endif
+
+char *
+ACE::strnew (const char *s)
+{
+ if (s == 0)
+ return 0;
+ char *t = 0;
+ ACE_NEW_RETURN (t,
+ char [ACE_OS::strlen (s) + 1],
+ 0);
+ if (t == 0)
+ return 0;
+ else
+ return ACE_OS::strcpy (t, s);
+}
+
+#if defined (ACE_HAS_WCHAR)
+wchar_t *
+ACE::strnew (const wchar_t *s)
+{
+ if (s == 0)
+ return 0;
+ wchar_t *t = 0;
+ ACE_NEW_RETURN (t,
+ wchar_t[ACE_OS::strlen (s) + 1],
+ 0);
+ if (t == 0)
+ return 0;
+ else
+ return ACE_OS::strcpy (t, s);
+}
+#endif /* ACE_HAS_WCHAR */
+
+inline static bool equal_char(char a, char b, bool case_sensitive)
+{
+ if (case_sensitive)
+ return a == b;
+ return ACE_OS::ace_tolower(a) == ACE_OS::ace_tolower(b);
+}
+
+bool
+ACE::wild_match(const char* str, const char* pat, bool case_sensitive)
+{
+ if (str == pat)
+ return true;
+ if (pat == 0 || str == 0)
+ return false;
+
+ bool star = false;
+ const char* s = str;
+ const char* p = pat;
+ while (*s != '\0')
+ {
+ if (*p == '*')
+ {
+ star = true;
+ pat = p;
+ while (*++pat == '*');
+
+ if (*pat == '\0')
+ return true;
+ p = pat;
+ }
+ else if (*p == '?')
+ {
+ ++s;
+ ++p;
+ }
+ else if (! equal_char(*s, *p, case_sensitive))
+ {
+ if (!star)
+ return false;
+ s = ++str;
+ p = pat;
+ }
+ else
+ {
+ ++s;
+ ++p;
+ }
+ }
+ if (*p == '*')
+ while (*++p == '*');
+
+ return *p == '\0';
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ACE.h b/ACE/ace/ACE.h
new file mode 100644
index 00000000000..7dec2712fa4
--- /dev/null
+++ b/ACE/ace/ACE.h
@@ -0,0 +1,825 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file ACE.h
+ *
+ * $Id$
+ *
+ * This file contains value added ACE functions that extend the
+ * behavior of the UNIX and Win32 OS calls.
+ *
+ * All these ACE static functions are consolidated in a single place
+ * in order to manage the namespace better. These functions are put
+ * here rather than in @c ACE_OS in order to separate concerns.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ACE_H
+#define ACE_ACE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_math.h"
+#include "ace/Flag_Manip.h"
+#include "ace/Handle_Ops.h"
+#include "ace/Lib_Find.h"
+#include "ace/Init_ACE.h"
+#include "ace/Sock_Connect.h"
+#include "ace/Default_Constants.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+class ACE_Time_Value;
+class ACE_Message_Block;
+class ACE_Handle_Set;
+
+/**
+ * @namespace ACE
+ *
+ * @brief The namespace containing the ACE framework itself.
+ *
+ * The ACE namespace contains all types (classes, structures,
+ * typedefs, etc), and global functions and variables in the ACE
+ * framework.
+ */
+namespace ACE
+{
+ // = ACE version information.
+ /// e.g., the "5" in ACE 5.1.12.
+ extern ACE_Export u_int major_version (void);
+
+ /// e.g., the "1" in ACE 5.1.12.
+ extern ACE_Export u_int minor_version (void);
+
+ /// e.g., the "12" in ACE 5.1.12.
+ /// Returns 0 for "stable" (non-beta) releases.
+ extern ACE_Export u_int beta_version (void);
+
+ // = C++ compiler version information.
+ /// E.g., the "SunPro C++" in SunPro C++ 4.32.0
+ extern ACE_Export const ACE_TCHAR * compiler_name (void);
+
+ /// E.g., the "4" in SunPro C++ 4.32.0
+ extern ACE_Export u_int compiler_major_version (void);
+
+ /// E.g., the "32" in SunPro C++ 4.32.0
+ extern ACE_Export u_int compiler_minor_version (void);
+
+ /// E.g., the "0" in SunPro C++ 4.32.0
+ extern ACE_Export u_int compiler_beta_version (void);
+
+ /// Check if error indicates the process being out of handles (file
+ /// descriptors).
+ extern ACE_Export int out_of_handles (int error);
+
+ /// Simple wildcard matching function supporting '*' and '?'
+ /// return true if string s matches pattern.
+ extern ACE_Export bool wild_match(const char* s, const char* pattern, bool case_sensitive = true);
+
+ /**
+ * @name I/O operations
+ *
+ * Notes on common parameters:
+ *
+ * @a handle is the connected endpoint that will be used for I/O.
+ *
+ * @a buf is the buffer to write from or receive into.
+ *
+ * @a len is the number of bytes to transfer.
+ *
+ * The @a timeout parameter in the following methods indicates how
+ * long to blocking trying to transfer data. If @a 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, @c EWOULDBLOCK will be returned if no
+ * action is immediately possible.
+ *
+ * If @a timeout != 0, the call will wait until the relative time
+ * specified in @a *timeout elapses.
+ *
+ * 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 @c EWOULDBLOCK. @a 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, @c errno == @c ETIME.
+ * - On error, -1 is returned, @c errno is set to appropriate error.
+ * - On @c EOF, 0 is returned, @c errno is irrelevant.
+ *
+ * On partial transfers, i.e., if any data is transferred before
+ * timeout / error / @c EOF, @a bytes_transferred> will contain the
+ * number of bytes transferred.
+ *
+ * Methods with @a iovec parameter are I/O vector variants of the
+ * I/O operations.
+ *
+ * Methods with the extra @a flags argument will always result in
+ * @c send getting called. Methods without the extra @a flags
+ * argument will result in @c send getting called on Win32
+ * platforms, and @c write getting called on non-Win32 platforms.
+ */
+ //@{
+ extern ACE_Export ssize_t recv (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0);
+
+#if defined (ACE_HAS_TLI)
+
+ extern ACE_Export ssize_t t_rcv (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int *flags,
+ const ACE_Time_Value *timeout = 0);
+
+#endif /* ACE_HAS_TLI */
+
+ extern ACE_Export ssize_t recv (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout = 0);
+
+ extern ACE_Export ssize_t recvmsg (ACE_HANDLE handle,
+ struct msghdr *msg,
+ int flags,
+ const ACE_Time_Value *timeout = 0);
+
+ extern ACE_Export ssize_t recvfrom (ACE_HANDLE handle,
+ char *buf,
+ int len,
+ int flags,
+ struct sockaddr *addr,
+ int *addrlen,
+ const ACE_Time_Value *timeout = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t recv_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+#if defined (ACE_HAS_TLI)
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t t_rcv_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int *flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+#endif /* ACE_HAS_TLI */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t recv_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+ /// Receive into a variable number of pieces.
+ /**
+ * Accepts a variable, caller-specified, number of pointer/length
+ * pairs. Arguments following @a n are char *, size_t pairs.
+ *
+ * @param handle The I/O handle to receive on
+ * @param n The total number of char *, size_t pairs following @a n.
+ *
+ * @return -1 on error, else total number of bytes received.
+ */
+ extern ACE_Export ssize_t recv (ACE_HANDLE handle, size_t n, ...);
+
+ extern ACE_Export ssize_t recvv (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t recvv_n (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+ extern ACE_Export ssize_t recv_n (ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+ extern ACE_Export ssize_t send (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0);
+
+#if defined (ACE_HAS_TLI)
+
+ extern ACE_Export ssize_t t_snd (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0);
+
+#endif /* ACE_HAS_TLI */
+
+ extern ACE_Export ssize_t send (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout = 0);
+
+ extern ACE_Export ssize_t sendmsg (ACE_HANDLE handle,
+ const struct msghdr *msg,
+ int flags,
+ const ACE_Time_Value *timeout = 0);
+
+ extern ACE_Export ssize_t sendto (ACE_HANDLE handle,
+ const char *buf,
+ int len,
+ int flags,
+ const struct sockaddr *addr,
+ int addrlen,
+ const ACE_Time_Value *timeout = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t send_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+#if defined (ACE_HAS_TLI)
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t t_snd_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+#endif /* ACE_HAS_TLI */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t send_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+ /// Varargs variant.
+ extern ACE_Export ssize_t send (ACE_HANDLE handle, size_t n, ...);
+
+ extern ACE_Export ssize_t sendv (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t sendv_n (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+ /// Send all the @a message_blocks chained through their @c next and
+ /// @c cont pointers. This call uses the underlying OS gather-write
+ /// operation to reduce the domain-crossing penalty.
+ extern ACE_Export ssize_t send_n (ACE_HANDLE handle,
+ const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+ // = File system I/O functions (these don't support timeouts).
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t read_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ size_t *bytes_transferred = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t write_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ size_t *bytes_transferred = 0);
+
+ /// Write all the @a message_blocks chained through their @c next
+ /// and @c cont pointers. This call uses the underlying OS
+ /// gather-write operation to reduce the domain-crossing penalty.
+ extern ACE_Export ssize_t write_n (ACE_HANDLE handle,
+ const ACE_Message_Block *message_block,
+ size_t *bytes_transferred = 0);
+
+ extern ACE_Export ssize_t readv_n (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ size_t *bytes_transferred = 0);
+
+ extern ACE_Export ssize_t writev_n (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ size_t *bytes_transferred = 0);
+ //@}
+
+ /**
+ * Wait up to @a timeout amount of time to passively establish a
+ * connection. This method doesn't perform the @c accept, it just
+ * does the timed wait.
+ */
+ extern ACE_Export int handle_timed_accept (ACE_HANDLE listener,
+ ACE_Time_Value *timeout,
+ int restart);
+
+ /**
+ * Wait up to @a timeout amount of time to complete an actively
+ * established non-blocking connection. If @a is_tli is non-0 then
+ * we are being called by a TLI wrapper (which behaves slightly
+ * differently from a socket wrapper).
+ */
+ extern ACE_Export ACE_HANDLE handle_timed_complete (
+ ACE_HANDLE listener,
+ const ACE_Time_Value *timeout,
+ int is_tli = 0);
+
+ /**
+ * Reset the limit on the number of open handles. If @a new_limit
+ * == -1 set the limit to the maximum allowable. Otherwise, set
+ * the limit value to @a new_limit. If @a increase_limit_only is
+ * non-0 then only allow increases to the limit.
+ */
+ extern ACE_Export int set_handle_limit (int new_limit = -1,
+ int increase_limit_only = 0);
+
+ /**
+ * Returns the maximum number of open handles currently permitted in
+ * this process. This maximum may be extended using
+ * @c ACE::set_handle_limit.
+ */
+ extern ACE_Export int max_handles (void);
+
+ // = String functions
+#if !defined (ACE_HAS_WINCE)
+ /**
+ * Return a dynamically allocated duplicate of @a str, substituting
+ * the environment variable if @c str[0] @c == @c '$'. Note that
+ * the pointer is allocated with @c ACE_OS::malloc and must be freed
+ * by @c ACE_OS::free.
+ */
+ extern ACE_Export ACE_TCHAR *strenvdup (const ACE_TCHAR *str);
+#endif /* ACE_HAS_WINCE */
+
+ /// Returns a pointer to the "end" of the string, i.e., the character
+ /// past the '\0'.
+ extern ACE_Export const char *strend (const char *s);
+
+ /// This method is just like @c strdup, except that it uses
+ /// @c operator @c new rather than @c malloc. If @a s is NULL
+ /// returns NULL rather than segfaulting.
+ extern ACE_Export char *strnew (const char *s);
+
+ /// Delete the memory allocated by @c strnew.
+ ACE_NAMESPACE_INLINE_FUNCTION void strdelete (char *s);
+
+ /// Create a fresh new copy of @a str, up to @a n chars long. Uses
+ /// @c ACE_OS::malloc to allocate the new string.
+ extern ACE_Export char *strndup (const char *str, size_t n);
+
+ /// Create a fresh new copy of @a str, up to @a n chars long. Uses
+ /// @c ACE_OS::malloc to allocate the new string.
+ extern ACE_Export char *strnnew (const char *str, size_t n);
+
+#if defined (ACE_HAS_WCHAR)
+ extern ACE_Export const wchar_t *strend (const wchar_t *s);
+
+ extern ACE_Export wchar_t *strnew (const wchar_t *s);
+
+ ACE_NAMESPACE_INLINE_FUNCTION void strdelete (wchar_t *s);
+
+ extern ACE_Export wchar_t *strndup (const wchar_t *str, size_t n);
+
+ extern ACE_Export wchar_t *strnnew (const wchar_t *str, size_t n);
+
+#endif /* ACE_HAS_WCHAR */
+
+ /**
+ * On Windows, determines if a specified pathname ends with ".exe"
+ * (not case sensitive). If on Windows and there is no ".exe" suffix,
+ * a new ACE_TCHAR array is allocated and a copy of @c pathname with
+ * the ".exe" suffix is copied into it. In this case, the caller is
+ * responsible for calling delete [] on the returned pointer.
+ *
+ * @param pathname The name to check for a proper suffix.
+ *
+ * @retval @c pathname if there is a proper suffix for Windows. This is
+ * always the return value for non-Windows platforms.
+ * @retval If a suffix needs to be added, returns a pointer to new[]
+ * allocated memory containing the original @c pathname plus
+ * a ".exe" suffix. The caller is responsible for freeing the
+ * memory using delete [].
+ */
+ extern ACE_Export const ACE_TCHAR *execname (const ACE_TCHAR *pathname);
+
+ /**
+ * Returns the "basename" of a @a pathname separated by @a delim.
+ * For instance, the basename of "/tmp/foo.cpp" is "foo.cpp" when
+ * @a delim is @a '/'.
+ */
+ extern ACE_Export const ACE_TCHAR *basename (const ACE_TCHAR *pathname,
+ ACE_TCHAR delim =
+ ACE_DIRECTORY_SEPARATOR_CHAR);
+
+ /**
+ * Returns the "dirname" of a @a pathname. For instance, the
+ * dirname of "/tmp/foo.cpp" is "/tmp" when @a delim is @a '/'. If
+ * @a pathname has no @a delim ".\0" is returned. This method does
+ * not modify @a pathname and is not reentrant.
+ */
+ extern ACE_Export const ACE_TCHAR *dirname (const ACE_TCHAR *pathname,
+ ACE_TCHAR delim =
+ ACE_DIRECTORY_SEPARATOR_CHAR);
+
+ /**
+ * Returns the current timestamp in the form
+ * "hour:minute:second:microsecond." The month, day, and year are
+ * also stored in the beginning of the @a date_and_time array, which
+ * is a user-supplied array of size @a time_len> @c ACE_TCHARs.
+ * Returns 0 if unsuccessful, else returns pointer to beginning of the
+ * "time" portion of @a date_and_time. If @a
+ * return_pointer_to_first_digit is 0 then return a pointer to the
+ * space before the time, else return a pointer to the beginning of
+ * the time portion.
+ */
+ extern ACE_Export ACE_TCHAR *timestamp (ACE_TCHAR date_and_time[],
+ int time_len,
+ int return_pointer_to_first_digit =
+ 0);
+
+ /**
+ * if @a avoid_zombies == 0 call @c ACE_OS::fork directly, else
+ * create an orphan process that's inherited by the init process;
+ * init cleans up when the orphan process terminates so we don't
+ * create zombies. Returns -1 on failure and either the child PID
+ * on success if @a avoid_zombies == 0 or 1 on success if @a
+ * avoid_zombies != 0 (this latter behavior is a known bug that
+ * needs to be fixed).
+ */
+ extern ACE_Export pid_t fork (
+ const ACE_TCHAR *program_name = ACE_TEXT ("<unknown>"),
+ int avoid_zombies = 0);
+
+ /**
+ * Become a daemon process using the algorithm in Richard Stevens
+ * "Advanced Programming in the UNIX Environment." If
+ * @a close_all_handles is non-zero then all open file handles are
+ * closed.
+ */
+ extern ACE_Export int daemonize (
+ const ACE_TCHAR pathname[] = ACE_TEXT ("/"),
+ bool close_all_handles = ACE_DEFAULT_CLOSE_ALL_HANDLES,
+ const ACE_TCHAR program_name[] = ACE_TEXT ("<unknown>"));
+
+ // = Miscellaneous functions.
+ /// Rounds the request to a multiple of the page size.
+ extern ACE_Export size_t round_to_pagesize (size_t len);
+
+ /// Rounds the request to a multiple of the allocation granularity.
+ extern ACE_Export size_t round_to_allocation_granularity (size_t len);
+
+ // @@ UNICODE what about buffer?
+ /// Format buffer into printable format. This is useful for
+ /// debugging.
+ extern ACE_Export size_t format_hexdump (const char *buffer, size_t size,
+ ACE_TCHAR *obuf, size_t obuf_sz);
+
+ /// Computes the hash value of {str} using the "Hash PJW" routine.
+ extern ACE_Export u_long hash_pjw (const char *str);
+
+ /// Computes the hash value of {str} using the "Hash PJW" routine.
+ extern ACE_Export u_long hash_pjw (const char *str, size_t len);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Computes the hash value of {str} using the "Hash PJW" routine.
+ extern ACE_Export u_long hash_pjw (const wchar_t *str);
+
+ /// Computes the hash value of {str} using the "Hash PJW" routine.
+ extern ACE_Export u_long hash_pjw (const wchar_t *str, size_t len);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Computes CRC-CCITT for the string.
+ extern ACE_Export ACE_UINT16 crc_ccitt(const char *str);
+
+ /// Computes CRC-CCITT for the buffer.
+ extern ACE_Export ACE_UINT16 crc_ccitt(const void *buf, size_t len,
+ ACE_UINT16 crc = 0);
+
+ /// Computes CRC-CCITT for the @ len iovec buffers.
+ extern ACE_Export ACE_UINT16 crc_ccitt(const iovec *iov, int len,
+ ACE_UINT16 crc = 0);
+
+ /// Computes the ISO 8802-3 standard 32 bits CRC for the string.
+ extern ACE_Export ACE_UINT32 crc32 (const char *str);
+
+ /// Computes the ISO 8802-3 standard 32 bits CRC for the buffer.
+ extern ACE_Export ACE_UINT32 crc32 (const void *buf, size_t len,
+ ACE_UINT32 crc = 0);
+
+ /// Computes the ISO 8802-3 standard 32 bits CRC for the
+ /// @ len iovec buffers.
+ extern ACE_Export ACE_UINT32 crc32 (const iovec *iov, int len,
+ ACE_UINT32 crc = 0);
+
+ /// Euclid's greatest common divisor algorithm.
+ extern ACE_Export u_long gcd (u_long x, u_long y);
+
+ /// Calculates the minimum enclosing frame size for the given values.
+ extern ACE_Export u_long minimum_frame_size (u_long period1, u_long period2);
+
+ /**
+ * Function that can burn up noticeable CPU time: brute-force
+ * determination of whether number @a n is prime. Returns 0 if
+ * it is prime, or the smallest factor if it is not prime.
+ * @a min_factor and @a max_factor can be used to partition the work
+ * among threads. For just one thread, typical values are 2 and
+ * n/2.
+ */
+ extern ACE_Export u_long is_prime (const u_long n,
+ const u_long min_factor,
+ const u_long max_factor);
+
+ /// Map troublesome win32 errno values to values that standard C
+ /// strerr function understands. Thank you Microsoft.
+ extern ACE_Export int map_errno (int error);
+
+ /// Returns a string containing the error message corresponding to a
+ /// WinSock error. This works around an omission in the Win32 API.
+ /// @internal
+ extern ACE_Export const ACE_TCHAR * sock_error (int error);
+
+ /// Determins whether the given error code corresponds to to a
+ /// WinSock error. If so returns true, false otherwise.
+ /// @internal
+ extern ACE_Export bool is_sock_error (int error);
+
+ /**
+ * Checks if process with {pid} is still alive. Returns 1 if it is
+ * still alive, 0 if it isn't alive, and -1 if something weird
+ * happened.
+ */
+ extern ACE_Export int process_active (pid_t pid);
+
+ /**
+ * Terminate the process abruptly with id @a pid. On Win32 platforms
+ * this uses {TerminateProcess} and on POSIX platforms is uses
+ * {kill} with the -9 (SIGKILL) signal, which cannot be caught or
+ * ignored. Note that this call is potentially dangerous to use
+ * since the process being terminated may not have a chance to
+ * cleanup before it shuts down.
+ */
+ extern ACE_Export int terminate_process (pid_t pid);
+
+ /**
+ * This method uses process id and object pointer to come up with a
+ * machine wide unique name. The process ID will provide uniqueness
+ * between processes on the same machine. The "this" pointer of the
+ * {object} will provide uniqueness between other "live" objects in
+ * the same process. The uniqueness of this name is therefore only
+ * valid for the life of {object}.
+ */
+ ACE_NAMESPACE_INLINE_FUNCTION void unique_name (const void *object,
+ ACE_TCHAR *name,
+ size_t length);
+
+ /// Computes the base 2 logarithm of {num}.
+ ACE_NAMESPACE_INLINE_FUNCTION u_long log2 (u_long num);
+
+ /// Hex conversion utility.
+ ACE_NAMESPACE_INLINE_FUNCTION ACE_TCHAR nibble2hex (u_int n);
+
+ /// Convert a hex character to its byte representation.
+ ACE_NAMESPACE_INLINE_FUNCTION u_char hex2byte (ACE_TCHAR c);
+
+ // = Set/get the debug level.
+ extern ACE_Export bool debug (void);
+ extern ACE_Export void debug (bool onoff);
+
+ /// Wrapper facade for @c select that uses @c ACE_Handle_Sets.
+ extern ACE_Export int select (int width,
+ ACE_Handle_Set *readfds,
+ ACE_Handle_Set *writefds = 0,
+ ACE_Handle_Set *exceptfds = 0,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Wrapper facade for the most common use of @c select that uses
+ /// @c ACE_Handle_Sets.
+ extern ACE_Export int select (int width,
+ ACE_Handle_Set &readfds,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Timed wait for handle to get read ready.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int handle_read_ready (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout);
+
+ /// Timed wait for handle to get write ready.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int handle_write_ready (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout);
+
+ /// Timed wait for handle to get exception ready.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int handle_exception_ready (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout);
+
+ /// Timed wait for handle to get read, write, or exception ready.
+ extern ACE_Export int handle_ready (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout,
+ int read_ready,
+ int write_ready,
+ int exception_ready);
+
+ /// Wait for @a timeout before proceeding to a @c recv operation.
+ /// @a val keeps track of whether we're in non-blocking mode or
+ /// not.
+ extern ACE_Export int enter_recv_timedwait (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout,
+ int &val);
+
+ /// Wait for @a timeout before proceeding to a @c send operation.
+ /// @a val keeps track of whether we're in non-blocking mode or
+ /// not.
+ extern ACE_Export int enter_send_timedwait (ACE_HANDLE handle,
+ const ACE_Time_Value* timeout,
+ int &val);
+
+ /// This makes sure that @a handle is set into non-blocking mode.
+ /// @a val keeps track of whether were in non-blocking mode or not.
+ extern ACE_Export void record_and_set_non_blocking_mode (ACE_HANDLE handle,
+ int &val);
+
+ /// Cleanup after a timed operation, restore the appropriate
+ /// non-blocking status of @a handle.
+ extern ACE_Export void restore_non_blocking_mode (ACE_HANDLE handle,
+ int val);
+
+ // private:
+ // These functions aren't meant to be used internally, so they are
+ // not exported.
+
+ //
+ // = Recv_n helpers
+ //
+
+ ACE_NAMESPACE_INLINE_FUNCTION ssize_t recv_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len);
+
+ extern ACE_Export ssize_t recv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int flags,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t recv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred);
+
+#if defined (ACE_HAS_TLI)
+
+ extern ACE_Export ssize_t t_rcv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int *flags,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t t_rcv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int *flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred);
+
+#endif /* ACE_HAS_TLI */
+
+ extern ACE_Export ssize_t recv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t recv_n_i (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t recvv_n_i (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t recvv_n_i (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred);
+
+ //
+ // = Send_n helpers
+ //
+
+ ACE_NAMESPACE_INLINE_FUNCTION ssize_t send_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len);
+
+ extern ACE_Export ssize_t send_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t send_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred);
+
+#if defined (ACE_HAS_TLI)
+
+ extern ACE_Export ssize_t t_snd_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t t_snd_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred);
+
+#endif /* ACE_HAS_TLI */
+
+ extern ACE_Export ssize_t send_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t send_n_i (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t sendv_n_i (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ size_t *bytes_transferred);
+
+ extern ACE_Export ssize_t sendv_n_i (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred);
+
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/ACE.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ACE_H */
diff --git a/ACE/ace/ACE.inl b/ACE/ace/ACE.inl
new file mode 100644
index 00000000000..573cae93357
--- /dev/null
+++ b/ACE/ace/ACE.inl
@@ -0,0 +1,350 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_Thread.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_sys_socket.h"
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+
+// Wrappers for methods that have been moved to ACE_OS.
+
+ACE_INLINE ssize_t
+ACE::read_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ size_t *bytes_transferred)
+{
+ return ACE_OS::read_n (handle,
+ buf,
+ len,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE::write_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ size_t *bytes_transferred)
+{
+ return ACE_OS::write_n (handle,
+ buf,
+ len,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE::recv_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ if (timeout == 0)
+ return ACE::recv_n_i (handle,
+ buf,
+ len,
+ flags,
+ bytes_transferred);
+ else
+ return ACE::recv_n_i (handle,
+ buf,
+ len,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+#if defined (ACE_HAS_TLI)
+
+ACE_INLINE ssize_t
+ACE::t_rcv_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ int *flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ if (timeout == 0)
+ return ACE::t_rcv_n_i (handle,
+ buf,
+ len,
+ flags,
+ bytes_transferred);
+ else
+ return ACE::t_rcv_n_i (handle,
+ buf,
+ len,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+#endif /* ACE_HAS_TLI */
+
+ACE_INLINE ssize_t
+ACE::recv_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ if (timeout == 0)
+ return ACE::recv_n_i (handle,
+ buf,
+ len,
+ bytes_transferred);
+ else
+ return ACE::recv_n_i (handle,
+ buf,
+ len,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE::recvv_n (ACE_HANDLE handle,
+ iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ if (timeout == 0)
+ return ACE::recvv_n_i (handle,
+ iov,
+ iovcnt,
+ bytes_transferred);
+ else
+ return ACE::recvv_n_i (handle,
+ iov,
+ iovcnt,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE::send_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ if (timeout == 0)
+ return ACE::send_n_i (handle,
+ buf,
+ len,
+ flags,
+ bytes_transferred);
+ else
+ return ACE::send_n_i (handle,
+ buf,
+ len,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+#if defined (ACE_HAS_TLI)
+
+ACE_INLINE ssize_t
+ACE::t_snd_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ if (timeout == 0)
+ return ACE::t_snd_n_i (handle,
+ buf,
+ len,
+ flags,
+ bytes_transferred);
+ else
+ return ACE::t_snd_n_i (handle,
+ buf,
+ len,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+#endif /* ACE_HAS_TLI */
+
+ACE_INLINE ssize_t
+ACE::send_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ if (timeout == 0)
+ return ACE::send_n_i (handle,
+ buf,
+ len,
+ bytes_transferred);
+ else
+ return ACE::send_n_i (handle,
+ buf,
+ len,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE::sendv_n (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ if (timeout == 0)
+ return ACE::sendv_n_i (handle,
+ iov,
+ iovcnt,
+ bytes_transferred);
+ else
+ return ACE::sendv_n_i (handle,
+ iov,
+ iovcnt,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE::send_i (ACE_HANDLE handle, const void *buf, size_t len)
+{
+#if defined (ACE_WIN32) || defined (HPUX)
+ return ACE_OS::send (handle, (const char *) buf, len);
+#else
+ return ACE_OS::write (handle, (const char *) buf, len);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE::recv_i (ACE_HANDLE handle, void *buf, size_t len)
+{
+#if defined (ACE_WIN32) || defined (ACE_OPENVMS) || defined (ACE_TANDEM_T1248_PTHREADS)
+ return ACE_OS::recv (handle, (char *) buf, len);
+#else
+ return ACE_OS::read (handle, (char *) buf, len);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE::handle_read_ready (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout)
+{
+ return ACE::handle_ready (handle,
+ timeout,
+ 1,
+ 0,
+ 0);
+}
+
+ACE_INLINE int
+ACE::handle_write_ready (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout)
+{
+ return ACE::handle_ready (handle,
+ timeout,
+ 0,
+ 1,
+ 0);
+}
+
+ACE_INLINE int
+ACE::handle_exception_ready (ACE_HANDLE handle,
+ const ACE_Time_Value *timeout)
+{
+ return ACE::handle_ready (handle,
+ timeout,
+ 0,
+ 0,
+ 1);
+}
+
+ACE_INLINE void
+ACE::strdelete (char *s)
+{
+ delete [] s;
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE void
+ACE::strdelete (wchar_t *s)
+{
+ delete [] s;
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE void
+ACE::unique_name (const void *object,
+ ACE_TCHAR *name,
+ size_t length)
+{
+ ACE_OS::unique_name (object, name, length);
+}
+
+ACE_INLINE u_long
+ACE::log2 (u_long num)
+{
+ u_long log = 0;
+
+ for (; num > 1; ++log)
+ num >>= 1;
+
+ return log;
+}
+
+ACE_INLINE ACE_TCHAR
+ACE::nibble2hex (u_int n)
+{
+ // Hexadecimal characters.
+#if defined (ACE_VXWORKS) && !defined (__DCPLUSPLUS__)
+ // temporary solution to prevent Windriver GNU toolchains from spewing
+ // loads of warnings when inlining.
+ // problem (incorrect warning leftover from older GNU) has been reported as
+ // TSR to Windriver.
+ const ACE_TCHAR hex_chars[] = ACE_TEXT ("0123456789abcdef");
+#else
+ static const ACE_TCHAR hex_chars[] = ACE_TEXT ("0123456789abcdef");
+#endif
+
+ // Yes, this works for UNICODE
+ return hex_chars[n & 0x0f];
+}
+
+ACE_INLINE int
+ACE::map_errno (int error)
+{
+#if defined (ACE_WIN32)
+ switch (error)
+ {
+ case WSAEWOULDBLOCK:
+ return EAGAIN; // Same as UNIX errno EWOULDBLOCK.
+ }
+#endif /* ACE_WIN32 */
+
+ return error;
+}
+
+ACE_INLINE u_char
+ACE::hex2byte (ACE_TCHAR c)
+{
+ if (ACE_OS::ace_isdigit (c))
+ return (u_char) (c - ACE_TEXT ('0'));
+ else if (ACE_OS::ace_islower (c))
+ return (u_char) (10 + c - ACE_TEXT ('a'));
+ else
+ return (u_char) (10 + c - ACE_TEXT ('A'));
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ACE.pc.in b/ACE/ace/ACE.pc.in
new file mode 100644
index 00000000000..90b2a9eebd7
--- /dev/null
+++ b/ACE/ace/ACE.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE
+Description: ADAPTIVE Communication Environment
+Version: @VERSION@
+Libs: -L${libdir} -lACE @LIBS@
+Cflags: -I${includedir}
diff --git a/ACE/ace/ACE_crc32.cpp b/ACE/ace/ACE_crc32.cpp
new file mode 100644
index 00000000000..f9e91c652ce
--- /dev/null
+++ b/ACE/ace/ACE_crc32.cpp
@@ -0,0 +1,161 @@
+// $Id$
+
+#include "ace/ACE.h"
+
+ACE_RCSID (ace,
+ ACE_crc32,
+ "$Id$")
+
+
+namespace
+{
+ /*****************************************************************/
+ /* */
+ /* CRC LOOKUP TABLE */
+ /* ================ */
+ /* The following CRC lookup table was generated automagically */
+ /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
+ /* Program V1.0 using the following model parameters: */
+ /* */
+ /* Width : 4 bytes. */
+ /* Poly : 0x04C11DB7L */
+ /* Reverse : TRUE. */
+ /* */
+ /* For more information on the Rocksoft^tm Model CRC Algorithm, */
+ /* see the document titled "A Painless Guide to CRC Error */
+ /* Detection Algorithms" by Ross Williams */
+ /* (ross@guest.adelaide.edu.au.). This document is likely to be */
+ /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
+ /* */
+ /*****************************************************************/
+
+ const ACE_UINT32 crc_table[] =
+ {
+ 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
+ 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
+ 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
+ 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
+ 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
+ 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
+ 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
+ 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
+ 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
+ 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
+ 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
+ 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
+ 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
+ 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
+ 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
+ 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
+ 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
+ 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
+ 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
+ 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
+ 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
+ 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
+ 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
+ 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
+ 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
+ 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
+ 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
+ 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
+ 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
+ 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
+ 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
+ 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
+ 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
+ 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
+ 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
+ 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
+ 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
+ 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
+ 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
+ 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
+ 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
+ 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
+ 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
+ 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
+ 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
+ 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
+ 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
+ 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
+ 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
+ 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
+ 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
+ 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
+ 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
+ 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
+ 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
+ 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
+ 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
+ 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
+ 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
+ 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
+ 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
+ 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
+ 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
+ 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
+ };
+
+ /*****************************************************************/
+ /* End of CRC Lookup Table */
+ /*****************************************************************/
+}
+
+#define COMPUTE(var, ch) (var) = (crc_table[(var ^ ch) & 0xFF] ^ (var >> 8))
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_UINT32
+ACE::crc32 (const char *string)
+{
+ ACE_UINT32 crc = 0xFFFFFFFF;
+
+ for (const char *p = string;
+ *p != 0;
+ ++p)
+ {
+ COMPUTE (crc, *p);
+ }
+
+ return ~crc;
+}
+
+ACE_UINT32
+ACE::crc32 (const void *buffer, size_t len, ACE_UINT32 crc)
+{
+ crc = ~crc;
+
+ for (const char *p = (const char *) buffer,
+ *e = (const char *) buffer + len;
+ p != e;
+ ++p)
+ {
+ COMPUTE (crc, *p);
+ }
+
+ return ~crc;
+}
+
+ACE_UINT32
+ACE::crc32 (const iovec *iov, int len, ACE_UINT32 crc)
+{
+ crc = ~crc;
+
+ for (int i = 0; i < len; ++i)
+ {
+ for (const char *p = (const char *) iov[i].iov_base,
+ *e = (const char *) iov[i].iov_base + iov[i].iov_len;
+ p != e;
+ ++p)
+ COMPUTE (crc, *p);
+ }
+
+ return ~crc;
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#undef COMPUTE
diff --git a/ACE/ace/ACE_crc_ccitt.cpp b/ACE/ace/ACE_crc_ccitt.cpp
new file mode 100644
index 00000000000..f591b53aa10
--- /dev/null
+++ b/ACE/ace/ACE_crc_ccitt.cpp
@@ -0,0 +1,128 @@
+// $Id$
+
+#include "ace/ACE.h"
+
+ACE_RCSID (ace,
+ ACE_crc_ccitt,
+ "$Id$")
+
+namespace
+{
+ /*****************************************************************/
+ /* */
+ /* CRC LOOKUP TABLE */
+ /* ================ */
+ /* The following CRC lookup table was generated automagically */
+ /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
+ /* Program V1.0 using the following model parameters: */
+ /* */
+ /* Width : 2 bytes. */
+ /* Poly : 0x1021 */
+ /* Reverse : TRUE. */
+ /* */
+ /* For more information on the Rocksoft^tm Model CRC Algorithm, */
+ /* see the document titled "A Painless Guide to CRC Error */
+ /* Detection Algorithms" by Ross Williams */
+ /* (ross@guest.adelaide.edu.au.). This document is likely to be */
+ /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
+ /* */
+ /*****************************************************************/
+
+ const ACE_UINT16 crc_table[] =
+ {
+ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
+ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
+ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
+ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
+ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
+ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
+ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
+ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
+ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
+ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
+ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
+ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
+ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
+ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
+ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
+ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
+ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
+ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
+ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
+ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
+ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
+ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
+ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
+ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
+ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
+ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
+ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
+ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
+ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
+ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
+ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
+ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
+ };
+
+ /*****************************************************************/
+ /* End of CRC Lookup Table */
+ /*****************************************************************/
+}
+
+#define COMPUTE(var, ch) (var) = (crc_table[(var ^ ch) & 0xFF] ^ (var >> 8))
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_UINT16
+ACE::crc_ccitt (const char *string)
+{
+ ACE_UINT16 crc = 0xFFFF;
+
+ for (const char *p = string;
+ *p != 0;
+ ++p)
+ {
+ COMPUTE (crc, *p);
+ }
+
+ return ~crc;
+}
+
+ACE_UINT16
+ACE::crc_ccitt (const void *buffer, size_t len, ACE_UINT16 crc)
+{
+ crc = ~crc;
+
+ for (const char *p = (const char *) buffer,
+ *e = (const char *) buffer + len;
+ p != e;
+ ++p)
+ {
+ COMPUTE (crc, *p);
+ }
+
+ return ~crc;
+}
+
+ACE_UINT16
+ACE::crc_ccitt (const iovec *iov, int len, ACE_UINT16 crc)
+{
+ crc = ~crc;
+
+ for (int i = 0; i < len; ++i)
+ {
+ for (const char *p = (const char *) iov[i].iov_base,
+ *e = (const char *) iov[i].iov_base + iov[i].iov_len;
+ p != e;
+ ++p)
+ COMPUTE (crc, *p);
+ }
+
+ return ~crc;
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#undef COMPUTE
diff --git a/ACE/ace/ACE_export.h b/ACE/ace/ACE_export.h
new file mode 100644
index 00000000000..a988b143427
--- /dev/null
+++ b/ACE/ace/ACE_export.h
@@ -0,0 +1,76 @@
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by
+// generate_export_file.pl
+// ------------------------------
+
+#ifndef ACE_EXPORT_H
+#define ACE_EXPORT_H
+
+#include "ace/config-lite.h"
+
+#if defined (ACE_AS_STATIC_LIBS)
+
+# if !defined (ACE_HAS_DLL)
+# define ACE_HAS_DLL 0
+# endif /* ! ACE_HAS_DLL */
+#else
+# if !defined (ACE_HAS_DLL)
+# define ACE_HAS_DLL 1
+# endif /* ! ACE_HAS_DLL */
+#endif /* ACE_AS_STATIC_LIB */
+
+#if defined (ACE_HAS_DLL)
+# if (ACE_HAS_DLL == 1)
+# if defined (ACE_BUILD_DLL)
+# define ACE_Export ACE_Proper_Export_Flag
+# define ACE_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define ACE_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else
+# define ACE_Export ACE_Proper_Import_Flag
+# define ACE_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define ACE_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ACE_BUILD_DLL */
+# else
+# define ACE_Export
+# define ACE_SINGLETON_DECLARATION(T)
+# define ACE_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ! ACE_HAS_DLL == 1 */
+#else
+# define ACE_Export
+# define ACE_SINGLETON_DECLARATION(T)
+# define ACE_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* ACE_HAS_DLL */
+
+// Added by hand to help with ACE_OS namespace
+#if defined (__TANDEM) && defined (USE_EXPLICIT_EXPORT)
+#define ACE_NAMESPACE_STORAGE_CLASS ACE_EXPORT_MACRO extern
+#else
+#define ACE_NAMESPACE_STORAGE_CLASS extern ACE_EXPORT_MACRO
+#endif
+
+#if defined (__ACE_INLINE__)
+# if defined (_MSC_VER) || defined (__MINGW32__) || defined (CYGWIN32) || \
+ (defined (__SUNPRO_CC) && __SUNPRO_CC >= 0x560) || \
+ (defined (__HP_aCC) && (__HP_aCC >= 60500)) || \
+ (defined (__sgi) && \
+ defined (_COMPILER_VERSION) && _COMPILER_VERSION <= 730)
+# define ACE_NAMESPACE_INLINE_FUNCTION inline
+# else
+# define ACE_NAMESPACE_INLINE_FUNCTION ACE_NAMESPACE_STORAGE_CLASS inline
+# endif
+# define ACE_INLINE_TEMPLATE_FUNCTION inline
+#else
+# define ACE_NAMESPACE_INLINE_FUNCTION ACE_NAMESPACE_STORAGE_CLASS
+// Microsoft Visual C++ will accept 'extern'; others refuse.
+# if defined (_MSC_VER) || defined (__BORLANDC__)
+# define ACE_INLINE_TEMPLATE_FUNCTION ACE_Export
+# else
+# define ACE_INLINE_TEMPLATE_FUNCTION
+# endif
+#endif
+
+#endif /* ACE_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/ARGV.cpp b/ACE/ace/ARGV.cpp
new file mode 100644
index 00000000000..431db5b0ee7
--- /dev/null
+++ b/ACE/ace/ARGV.cpp
@@ -0,0 +1,359 @@
+// $Id$
+
+#ifndef ACE_ARGV_CPP
+#define ACE_ARGV_CPP
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Memory.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/ARGV.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, ARGV, "$Id$")
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_ARGV_Queue_Entry)
+ACE_ALLOC_HOOK_DEFINE (ACE_ARGV)
+
+template <typename CHAR_TYPE>
+void
+ACE_ARGV_Queue_Entry_T<CHAR_TYPE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_ARGV_Queue_Entry_T::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("arg_ = %s"), this->arg_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("quote_arg_ = %d"), (int)this->quote_arg_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <typename CHAR_TYPE>
+void
+ACE_ARGV_T<CHAR_TYPE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_ARGV_T::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("argc_ = %d"), this->argc_));
+
+ ACE_ARGV *this_obj = const_cast<ACE_ARGV *> (this);
+
+ for (int i = 0; i < this->argc_; i++)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\nargv_[%i] = %s"),
+ i,
+ this_obj->argv ()[i]));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nbuf = %s\n"), this->buf_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// Creates this->argv_ out of this->buf_. New memory is allocated for
+// each element of the array. This is used by the array-to-string
+// style constructor and for creating this->argv_ when in iterative
+// mode.
+
+template <typename CHAR_TYPE>
+int
+ACE_ARGV_T<CHAR_TYPE>::string_to_argv (void)
+{
+ ACE_TRACE ("ACE_ARGV_T::string_to_argv");
+
+ return ACE_OS::string_to_argv (this->buf_,
+ this->argc_,
+ this->argv_,
+ this->substitute_env_args_);
+}
+
+template <typename CHAR_TYPE>
+ACE_ARGV_T<CHAR_TYPE>::ACE_ARGV_T (const CHAR_TYPE buf[],
+ bool substitute_env_args)
+ : substitute_env_args_ (substitute_env_args),
+ iterative_ (false),
+ argc_ (0),
+ argv_ (0),
+ buf_ (0),
+ length_ (0),
+ queue_ ()
+{
+ ACE_TRACE ("ACE_ARGV_T::ACE_ARGV_T CHAR_TYPE[] to CHAR_TYPE *[]");
+
+ if (buf == 0 || buf[0] == 0)
+ return;
+
+ // Make an internal copy of the string.
+ ACE_NEW (this->buf_,
+ CHAR_TYPE[ACE_OS::strlen (buf) + 1]);
+ ACE_OS::strcpy (this->buf_, buf);
+
+ // Create this->argv_.
+ if (this->string_to_argv () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("string_to_argv")));
+}
+
+template <typename CHAR_TYPE>
+ACE_ARGV_T<CHAR_TYPE>::ACE_ARGV_T (CHAR_TYPE *argv[],
+ bool substitute_env_args,
+ bool quote_arg)
+ : substitute_env_args_ (substitute_env_args),
+ iterative_ (false),
+ argc_ (0),
+ argv_ (0),
+ buf_ (0),
+ length_ (0),
+ queue_ ()
+{
+ ACE_TRACE ("ACE_ARGV_T::ACE_ARGV_T CHAR_TYPE*[] to CHAR_TYPE[]");
+
+ if (argv == 0 || argv[0] == 0)
+ return;
+
+ this->argc_ = ACE_OS::argv_to_string (argv,
+ this->buf_,
+ substitute_env_args,
+ quote_arg);
+}
+
+template <typename CHAR_TYPE>
+ACE_ARGV_T<CHAR_TYPE>::ACE_ARGV_T (CHAR_TYPE *first_argv[],
+ CHAR_TYPE *second_argv[],
+ bool substitute_env_args,
+ bool quote_args)
+ : substitute_env_args_ (substitute_env_args),
+ iterative_ (false),
+ argc_ (0),
+ argv_ (0),
+ buf_ (0),
+ length_ (0),
+ queue_ ()
+{
+ ACE_TRACE ("ACE_ARGV_T::ACE_ARGV_T CHAR_TYPE*[] + CHAR_TYPE *[] to CHAR_TYPE[]");
+
+ int first_argc = 0;
+ int second_argc = 0;
+
+ CHAR_TYPE *first_buf = 0;
+ CHAR_TYPE *second_buf = 0;
+
+ // convert the first argv to a string
+ if (first_argv != 0 && first_argv[0] != 0)
+ {
+ first_argc = ACE_OS::argv_to_string (first_argv,
+ first_buf,
+ substitute_env_args,
+ quote_args);
+ }
+
+ // convert the second argv to a string
+ if (second_argv != 0 && second_argv[0] != 0)
+ {
+ second_argc = ACE_OS::argv_to_string (second_argv,
+ second_buf,
+ substitute_env_args,
+ quote_args);
+ }
+
+ // Add the number of arguments in both the argvs.
+ this->argc_ = first_argc + second_argc;
+
+ size_t buf_len =
+ ACE_OS::strlen (first_buf) + ACE_OS::strlen (second_buf) + 1;
+
+ // Allocate memory to the lenght of the combined argv string.
+ ACE_NEW (this->buf_,
+ CHAR_TYPE[buf_len + 1]);
+
+ // copy the first argv string to the buffer
+ ACE_OS::strcpy (this->buf_, first_buf);
+
+ // concatenate the second argv string to the buffer
+ ACE_OS::strcat (this->buf_, second_buf);
+
+ // Delete the first and second buffers
+ delete [] first_buf;
+ delete [] second_buf;
+}
+
+template <typename CHAR_TYPE>
+ACE_ARGV_T<CHAR_TYPE>::ACE_ARGV_T (bool substitute_env_args)
+ : substitute_env_args_ (substitute_env_args),
+ iterative_ (true),
+ argc_ (0),
+ argv_ (0),
+ buf_ (0),
+ length_ (0),
+ queue_ ()
+{
+ ACE_TRACE ("ACE_ARGV_T::ACE_ARGV_T Iterative");
+
+ // Nothing to do yet -- the user puts in arguments via add ()
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_ARGV_T<CHAR_TYPE>::add (const CHAR_TYPE *next_arg, bool quote_arg)
+{
+ // Only allow this to work in the "iterative" verion -- the
+ // ACE_ARGVs created with the one argument constructor.
+ if (!this->iterative_)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ this->length_ += ACE_OS::strlen (next_arg);
+ if (quote_arg && ACE_OS::strchr (next_arg, ' ') != 0)
+ {
+ this->length_ += 2;
+ if (ACE_OS::strchr (next_arg, '"') != 0)
+ for (const CHAR_TYPE * p = next_arg; *p != '\0'; ++p)
+ if (*p == '"') ++this->length_;
+ }
+ else
+ {
+ quote_arg = false;
+ }
+
+ // Put the new argument at the end of the queue.
+ if (this->queue_.enqueue_tail (ACE_ARGV_Queue_Entry_T<CHAR_TYPE> (next_arg, quote_arg)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Can't add more to ARGV queue")),
+ -1);
+
+ ++this->argc_;
+
+ // Wipe argv_ and buf_ away so that they will be recreated if the
+ // user calls argv () or buf ().
+ if (this->argv_ != 0)
+ {
+ for (int i = 0; this->argv_[i] != 0; i++)
+ ACE_OS::free ((void *) this->argv_[i]);
+
+ delete [] this->argv_;
+ this->argv_ = 0;
+ }
+
+ delete [] this->buf_;
+ this->buf_ = 0;
+
+ return 0;
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_ARGV_T<CHAR_TYPE>::add (CHAR_TYPE *argv[], bool quote_args)
+{
+ for (int i = 0; argv[i] != 0; i++)
+ if (this->add (argv[i], quote_args) == -1)
+ return -1;
+
+ return 0;
+}
+
+// Free up argv_ and buf_
+
+template <typename CHAR_TYPE>
+ACE_ARGV_T<CHAR_TYPE>::~ACE_ARGV_T (void)
+{
+ ACE_TRACE ("ACE_ARGV_T::~ACE_ARGV_T");
+
+ if (this->argv_ != 0)
+ for (int i = 0; this->argv_[i] != 0; i++)
+ ACE_OS::free ((void *) this->argv_[i]);
+
+ delete [] this->argv_;
+ delete [] this->buf_;
+}
+
+// Create buf_ out of the queue_. This is only used in the
+// "iterative" mode.
+
+template <typename CHAR_TYPE>
+int
+ACE_ARGV_T<CHAR_TYPE>::create_buf_from_queue (void)
+{
+ ACE_TRACE ("ACE_ARGV_T::create_buf_from_queue");
+
+ // If the are no arguments, don't do anything
+ if (this->argc_ <= 0)
+ return -1;
+
+ delete [] this->buf_;
+
+ ACE_NEW_RETURN (this->buf_,
+ CHAR_TYPE[this->length_ + this->argc_],
+ -1);
+
+ // Get an iterator over the queue
+ ACE_Unbounded_Queue_Iterator<ACE_ARGV_Queue_Entry_T<CHAR_TYPE> > iter (this->queue_);
+
+ ACE_ARGV_Queue_Entry_T<CHAR_TYPE> *arg = 0;
+ CHAR_TYPE *ptr = this->buf_;
+ size_t len;
+
+ while (!iter.done ())
+ {
+ // Get next argument from the queue.
+ iter.next (arg);
+ iter.advance ();
+
+ if (arg->quote_arg_)
+ {
+ *ptr++ = '"';
+ if (ACE_OS::strchr (arg->arg_, '"') != 0)
+ {
+ for (const CHAR_TYPE * p = arg->arg_; *p != '\0'; ++p)
+ {
+ if (*p == '"') *ptr++ = '\\';
+ *ptr++ = *p;
+ }
+ }
+ else
+ {
+ len = ACE_OS::strlen (arg->arg_);
+ // Copy the argument into buf_
+ ACE_OS::memcpy ((void *) ptr,
+ (const void *) (arg->arg_),
+ len * sizeof (CHAR_TYPE));
+ // Move the pointer down.
+ ptr += len;
+ }
+ *ptr++ = '"';
+ }
+ else
+ {
+ len = ACE_OS::strlen (arg->arg_);
+ // Copy the argument into buf_
+ ACE_OS::memcpy ((void *) ptr,
+ (const void *) (arg->arg_),
+ len * sizeof (CHAR_TYPE));
+ // Move the pointer down.
+ ptr += len;
+ }
+
+ // Put in an argument separating space.
+ *ptr++ = ' ';
+ }
+
+ // Put in the NUL terminator
+ ptr[-1] = '\0';
+
+ return 0;
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_ARGV_CPP */
diff --git a/ACE/ace/ARGV.h b/ACE/ace/ARGV.h
new file mode 100644
index 00000000000..a50535f1dea
--- /dev/null
+++ b/ACE/ace/ARGV.h
@@ -0,0 +1,306 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file ARGV.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Everett Anderson <eea1@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_ARGUMENT_VECTOR_H
+#define ACE_ARGUMENT_VECTOR_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+#include "ace/Unbounded_Queue.h"
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_ARGV_Queue_Entry_T
+ *
+ * @brief An entry in the queue which keeps user supplied arguments.
+ */
+template <typename CHAR_TYPE>
+class ACE_ARGV_Queue_Entry_T
+{
+public:
+ // = Initialization and termination.
+ /// Initialize a ACE_ARGV_Queue_Entry_T.
+ ACE_ARGV_Queue_Entry_T (void);
+
+ /**
+ * Initialize a ACE_ARGV_Queue_Entry_T.
+ *
+ * @param arg Pointer to an argument
+ *
+ * @param quote_arg The argument @a arg need to be quoted
+ * while adding to the vector.
+ */
+ ACE_ARGV_Queue_Entry_T (const CHAR_TYPE *arg,
+ bool quote_arg);
+
+ /**
+ * Initialize a ACE_ARGV_Queue_Entry_T.
+ *
+ * @param entry Pointer to a queue entry
+ */
+ ACE_ARGV_Queue_Entry_T (const ACE_ARGV_Queue_Entry_T<CHAR_TYPE> &entry);
+
+ /// We need this destructor to keep some compilers from complaining.
+ /// It's just a no-op, however.
+ ~ACE_ARGV_Queue_Entry_T (void);
+
+ /// Dump the state of this object.
+ void dump (void) const;
+
+ // Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Pointer to the argument.
+ const CHAR_TYPE * arg_;
+
+ /// The argument need to be quoted while adding to the vector.
+ bool quote_arg_;
+};
+
+/**
+ * @class ACE_ARGV_T
+ *
+ * @brief Builds a counted argument vector (ala argc/argv) from either
+ * a string or a set of separate tokens. This class preserves whitespace
+ * within tokens only if the whitespace-containing token is enclosed in
+ * either single (') or double (") quotes. This is consistent with the
+ * expected behavior if an argument vector obtained using this class is
+ * passed to, for example, ACE_Get_Opt.
+ *
+ * This class can substitute environment variable values for tokens that
+ * are environment variable references (e.g., @c $VAR). This only works
+ * if the token is an environment variable reference and nothing else; it
+ * doesn't substitute environment variable references within a token.
+ * For example, @c $HOME/file will not substitute the value of the HOME
+ * environment variable.
+ */
+template <typename CHAR_TYPE>
+class ACE_ARGV_T
+{
+public:
+ // = Initialization and termination.
+ /**
+ * Splits the specified string into an argument vector. Arguments in the
+ * string are delimited by whitespace. Whitespace-containing arguments
+ * must be enclosed in quotes, either single (') or double (").
+ *
+ * @param buf A nul-terminated CHAR_TYPE array to split into arguments
+ * for the vector.
+ *
+ * @param substitute_env_args If non-zero, any token that is an
+ * environment variable reference (e.g., @c $VAR) will have
+ * its environment variable value in the resultant vector
+ * in place of the environment variable name.
+ */
+ explicit ACE_ARGV_T (const CHAR_TYPE buf[],
+ bool substitute_env_args = true);
+
+ /**
+ * Initializes the argument vector from a set of arguments. Any environment
+ * variable references are translated (if applicable) during execution of
+ * this method.
+ *
+ * @param argv An array of tokens to initialize the object with. The
+ * array must be terminated with a 0 pointer. All needed
+ * data is copied from @a argv during this call; the pointers
+ * in @a argv are not needed after this call, and the memory
+ * referred to by @a argv is not referenced by this object.
+ *
+ * @param substitute_env_args If non-zero, any element of @a argv that is
+ * an environment variable reference (e.g., @c $VAR) will have
+ * its environment variable value in the resultant vector
+ * in place of the environment variable name.
+ *
+ * @param quote_args If non-zero each argument @a argv[i] needs to
+ * be enclosed in double quotes ('"').
+ */
+ explicit ACE_ARGV_T (CHAR_TYPE *argv[],
+ bool substitute_env_args = true,
+ bool quote_args = false);
+
+ /**
+ * Initializes the argument vector from two combined argument vectors.
+ *
+ * @param first_argv An array of tokens to initialize the object with.
+ * The array must be terminated with a 0 pointer.
+ * @param second_argv An array of tokens that is concatenated with the
+ * the tokens in @a first_argv. The array must be
+ * terminated with a 0 pointer.
+ * @param substitute_env_args If non-zero, any element of @a first_argv
+ * or @a second_argv that is an environment variable
+ * reference (e.g., @c $VAR) will have its environment
+ * variable value in the resultant vector in place
+ * of the environment variable name.
+ *
+ * @param quote_args If non-zero each arguments @a first_argv[i] and
+ * @a second_argv[i] needs to be enclosed
+ * in double quotes ('"').
+ */
+ ACE_ARGV_T (CHAR_TYPE *first_argv[],
+ CHAR_TYPE *second_argv[],
+ bool substitute_env_args = true,
+ bool quote_args = false);
+
+ /**
+ * Initialize this object so arguments can be added later using one
+ * of the add methods. This is referred to as the @i iterative method
+ * of adding arguments to this object.
+ */
+ explicit ACE_ARGV_T (bool substitute_env_args = true);
+
+ /// Destructor.
+ ~ACE_ARGV_T (void);
+
+ /** @name Accessor methods
+ *
+ * These methods access the argument vector contained in this object.
+ */
+ //@{
+ /**
+ * Returns the specified element of the current argument vector.
+ *
+ * @param index Index to the desired element.
+ *
+ * @retval Pointer to the indexed string.
+ * @retval 0 if @a index is out of bounds.
+ */
+ const CHAR_TYPE *operator[] (size_t index);
+
+ /**
+ * Returns the current argument vector. The returned pointers are to data
+ * maintained internally to this class. Do not change or delete either the
+ * pointers or the memory to which they refer.
+ */
+ CHAR_TYPE **argv (void);
+
+ /// Returns the current number of arguments.
+ int argc (void) const;
+
+ /**
+ * Returns a single string form of the current arguments. The returned
+ * pointer refers to memory maintained internally to this class. Do not
+ * change or delete it.
+ */
+ const CHAR_TYPE *buf (void);
+
+ //@}
+
+ /// Dump the state of this object.
+ void dump (void) const;
+
+ // Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /**
+ * Add another argument. This only works in the iterative mode.
+ *
+ * @note This method copies the specified pointer, but not the data
+ * contained in the referenced memory. Thus, if the content of
+ * the memory referred to by @a next_arg are changed after this
+ * method returns, the results are undefined.
+ *
+ * @param next_arg Pointer to the next argument to add to the vector.
+ *
+ * @param quote_arg The argument @a next_arg need to be quoted while
+ * adding to the vector.
+ *
+ * @retval 0 on success; -1 on failure. Most likely @c errno values are:
+ * - EINVAL: This object is not in iterative mode.
+ * - ENOMEM: Not enough memory available to save @a next_arg.
+ */
+ int add (const CHAR_TYPE *next_arg, bool quote_arg = false);
+
+ /**
+ * Add an array of arguments. This only works in the iterative mode.
+ *
+ * @note This method copies the specified pointers, but not the data
+ * contained in the referenced memory. Thus, if the content of
+ * the memory referred to by any of the @a argv elements is
+ * changed after this method returns, the results are undefined.
+ *
+ * @param argv Pointers to the arguments to add to the vector.
+ * @a argv must be terminated by a 0 pointer.
+ *
+ * @param quote_args If non-zero each argument @a argv[i] needs to
+ * be enclosed in double quotes ('"').
+ *
+ * @retval 0 on success; -1 on failure. Most likely @c errno values are:
+ * - EINVAL: This object is not in iterative mode.
+ * - ENOMEM: Not enough memory available to save @a next_arg.
+ */
+ int add (CHAR_TYPE *argv[], bool quote_args = false);
+
+private:
+ /// Copy constructor not implemented.
+ ACE_UNIMPLEMENTED_FUNC (ACE_ARGV_T (const ACE_ARGV_T<CHAR_TYPE>&))
+
+ /// Assignment operator not implemented.
+ ACE_UNIMPLEMENTED_FUNC (ACE_ARGV_T operator= (const ACE_ARGV_T<CHAR_TYPE>&))
+
+ /// Creates buf_ from the queue of added args, deletes previous buf_.
+ int create_buf_from_queue (void);
+
+ /// Converts buf_ into the CHAR_TYPE *argv[] format.
+ int string_to_argv (void);
+
+ /// Replace args with environment variable values?
+ bool substitute_env_args_;
+
+ bool iterative_;
+
+ /// Number of arguments in the ARGV array.
+ int argc_;
+
+ /// The array of string arguments.
+ CHAR_TYPE **argv_;
+
+ /// Buffer containing the <argv> contents.
+ CHAR_TYPE *buf_;
+
+ /// Total length of the arguments in the queue, not counting
+ /// separating spaces
+ size_t length_;
+
+ /// Queue which keeps user supplied arguments. This is only
+ /// active in the "iterative" mode.
+ ACE_Unbounded_Queue<ACE_ARGV_Queue_Entry_T<CHAR_TYPE> > queue_;
+};
+
+typedef ACE_ARGV_Queue_Entry_T<ACE_TCHAR> ACE_ARGV_Queue_Entry;
+typedef ACE_ARGV_T<ACE_TCHAR> ACE_ARGV;
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/ARGV.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/ARGV.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("ARGV.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_ARGUMENT_VECTOR_H */
diff --git a/ACE/ace/ARGV.inl b/ACE/ace/ARGV.inl
new file mode 100644
index 00000000000..e84166f49ba
--- /dev/null
+++ b/ACE/ace/ARGV.inl
@@ -0,0 +1,104 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Global_Macros.h"
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <typename CHAR_TYPE> ACE_INLINE
+ACE_ARGV_Queue_Entry_T<CHAR_TYPE>::ACE_ARGV_Queue_Entry_T (void)
+ : arg_(0),
+ quote_arg_(false)
+{
+ // No-op
+}
+
+template <typename CHAR_TYPE> ACE_INLINE
+ACE_ARGV_Queue_Entry_T<CHAR_TYPE>::ACE_ARGV_Queue_Entry_T (const CHAR_TYPE *arg,
+ bool quote_arg)
+ : arg_(arg),
+ quote_arg_(quote_arg)
+{
+ // No-op
+}
+
+template <typename CHAR_TYPE> ACE_INLINE
+ACE_ARGV_Queue_Entry_T<CHAR_TYPE>::ACE_ARGV_Queue_Entry_T (const ACE_ARGV_Queue_Entry_T<CHAR_TYPE> &entry)
+ : arg_(entry.arg_),
+ quote_arg_(entry.quote_arg_)
+{
+ // No-op
+}
+
+template <typename CHAR_TYPE> ACE_INLINE
+ACE_ARGV_Queue_Entry_T<CHAR_TYPE>::~ACE_ARGV_Queue_Entry_T (void)
+{
+ // No-op just to keep some compilers happy...
+}
+
+// Return the number of args
+template <typename CHAR_TYPE>
+ACE_INLINE int
+ACE_ARGV_T<CHAR_TYPE>::argc (void) const
+{
+ ACE_TRACE ("ACE_ARGV_T::argc");
+ // Try to create the argv_ if it isn't there
+ ACE_ARGV_T<CHAR_TYPE> *nonconst_this =
+ const_cast <ACE_ARGV_T<CHAR_TYPE> *> (this);
+ (void) nonconst_this->argv ();
+ return this->argc_;
+}
+
+// Return the arguments in a space-separated string
+template <typename CHAR_TYPE>
+ACE_INLINE const CHAR_TYPE *
+ACE_ARGV_T<CHAR_TYPE>::buf (void)
+{
+ ACE_TRACE ("ACE_ARGV_T::buf");
+
+ if (this->buf_ == 0 && this->iterative_)
+ this->create_buf_from_queue ();
+
+ return (const CHAR_TYPE *) this->buf_;
+}
+
+// Return the arguments in an entry-per-argument array
+
+template <typename CHAR_TYPE>
+ACE_INLINE CHAR_TYPE **
+ACE_ARGV_T<CHAR_TYPE>::argv (void)
+{
+ ACE_TRACE ("ACE_ARGV_T::argv");
+
+ // Try to create the argv_ if it isn't there
+ if (this->argv_ == 0)
+ {
+ if (this->iterative_ && this->buf_ == 0)
+ this->create_buf_from_queue ();
+
+ // Convert buf_ to argv_
+ if (this->string_to_argv () == -1)
+ return (CHAR_TYPE **) 0;
+ }
+
+ return (CHAR_TYPE **) this->argv_;
+}
+
+// Subscript operator.
+
+template <typename CHAR_TYPE>
+ACE_INLINE const CHAR_TYPE *
+ACE_ARGV_T<CHAR_TYPE>::operator[] (size_t i)
+{
+ ACE_TRACE ("ACE_ARGV_T::operator[]");
+
+ // Don't go out of bounds.
+ if (i >= static_cast<size_t> (this->argc_))
+ return 0;
+
+ return (const CHAR_TYPE *) this->argv ()[i];
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ATM_Acceptor.cpp b/ACE/ace/ATM_Acceptor.cpp
new file mode 100644
index 00000000000..5a78f1c32c8
--- /dev/null
+++ b/ACE/ace/ATM_Acceptor.cpp
@@ -0,0 +1,309 @@
+// $Id$
+
+#include "ace/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 "ace/ATM_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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)
+
+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,
+ 0,
+ 0) == 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_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,
+ 0,
+ 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 (),
+ 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_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,
+ 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,
+ reinterpret_cast<struct sockaddr *> (
+ &(local_sap_addr->sockaddratmsvc)),
+ sizeof (local_sap_addr->sockaddratmsvc)
+ ) == -1) {
+ ACE_DEBUG (LM_DEBUG,
+ ACE_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_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,
+ 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,
+ 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 */
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#endif /* ACE_HAS_ATM */
diff --git a/ACE/ace/ATM_Acceptor.h b/ACE/ace/ATM_Acceptor.h
new file mode 100644
index 00000000000..5ed236099e3
--- /dev/null
+++ b/ACE/ace/ATM_Acceptor.h
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file ATM_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Joe Hoffert
+ */
+//=============================================================================
+
+
+#ifndef ACE_ATM_ACCEPTOR_H
+#define ACE_ATM_ACCEPTOR_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_HAS_ATM)
+
+#include "ace/ATM_Stream.h"
+#include "ace/ATM_Params.h"
+#include "ace/ATM_QoS.h"
+
+#if defined (ACE_HAS_LINUX_ATM)
+#include /**/ "atm.h"
+#endif /* ACE_HAS_LINUX_ATM */
+
+#if defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
+#include "ace/SOCK_Acceptor.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef ACE_SOCK_Acceptor ATM_Acceptor;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#elif defined (ACE_HAS_FORE_ATM_XTI)
+#include "ace/TLI_Acceptor.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef ACE_TLI_Acceptor ATM_Acceptor;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif // ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+class ACE_Time_Value;
+
+/**
+ * @class ACE_ATM_Acceptor
+ *
+ * @brief Defines the member functions for ACE_ATM_Acceptor abstraction.
+ *
+ * This class wraps up the ACE_SOCK_Acceptor and ACE_TLI_Acceptor
+ * to make the mechanism for the ATM protocol transparent.
+ */
+class ACE_Export ACE_ATM_Acceptor
+{
+
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_ATM_Acceptor (void);
+
+ ~ACE_ATM_Acceptor ();
+
+ /// Initiate a passive mode connection.
+ ACE_ATM_Acceptor (const ACE_Addr &remote_sap,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ ACE_ATM_Params params = ACE_ATM_Params());
+
+ /// Initiate a passive mode socket.
+ ACE_HANDLE open (const ACE_Addr &remote_sap,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ ACE_ATM_Params params = ACE_ATM_Params());
+
+ /// Close down the acceptor and release resources.
+ int close (void);
+
+ // = Passive connection acceptance method.
+
+ /// Accept a new data transfer connection. A @a timeout of 0 means
+ /// block forever, a @a timeout of {0, 0} means poll. @a restart == 1
+ /// means "restart if interrupted."
+ int accept (ACE_ATM_Stream &new_sap,
+ ACE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0,
+ ACE_ATM_Params params = ACE_ATM_Params(),
+ ACE_ATM_QoS qos = ACE_ATM_QoS());
+
+ /// Get the local address currently listening on
+ int get_local_addr( ACE_ATM_Addr &local_addr );
+
+ // = Meta-type info
+ typedef ACE_ATM_Addr PEER_ADDR;
+ typedef ACE_ATM_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ATM_Acceptor acceptor_;
+};
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#if defined (__ACE_INLINE__)
+#include "ace/ATM_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_ATM */
+#include /**/ "ace/post.h"
+#endif /* ACE_ATM_ACCEPTOR_H */
diff --git a/ACE/ace/ATM_Acceptor.inl b/ACE/ace/ATM_Acceptor.inl
new file mode 100644
index 00000000000..c08fd048f68
--- /dev/null
+++ b/ACE/ace/ATM_Acceptor.inl
@@ -0,0 +1,43 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_ATM_Acceptor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_ATM_Acceptor::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_INLINE
+ACE_ATM_Acceptor::ACE_ATM_Acceptor (const ACE_Addr &remote_sap,
+ int backlog,
+ ACE_ATM_Params params)
+{
+ ACE_TRACE ("ACE_ATM_Acceptor::ACE_ATM_Acceptor");
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (open (remote_sap, backlog, params) < 0)
+ //FUZZ: enable check_for_lack_ACE_OS
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_ATM_Acceptor::ACE_ATM_Acceptor")));
+}
+
+ACE_INLINE
+int
+ACE_ATM_Acceptor::close (void)
+{
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
+ return (acceptor_.close());
+#else
+ return 0;
+#endif // ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ATM_Addr.cpp b/ACE/ace/ATM_Addr.cpp
new file mode 100644
index 00000000000..19088cef5b1
--- /dev/null
+++ b/ACE/ace/ATM_Addr.cpp
@@ -0,0 +1,522 @@
+// $Id$
+
+// Defines the Internet domain address family address format.
+
+#include "ace/ATM_Addr.h"
+#if defined (ACE_HAS_ATM)
+
+#include "ace/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.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, ATM_Addr, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_ATM_Addr)
+
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+#define BHLI_MAGIC "FORE_ATM"
+// This is line rate in cells/s for an OC-3 MM interface.
+const long ACE_ATM_Addr::LINE_RATE = 353207;
+const int ACE_ATM_Addr::OPT_FLAGS_CPID = 0x1;
+const int ACE_ATM_Addr::OPT_FLAGS_PMP = 0x2;
+const int ACE_ATM_Addr::DEFAULT_SELECTOR = 0x99;
+#elif defined (ACE_HAS_LINUX_ATM)
+//pbrandao:for Linux:
+//pbrandao:for now stick with current definitions
+//pbrandao:see if later need to change
+const long ACE_ATM_Addr::LINE_RATE = 353207;
+const int ACE_ATM_Addr::OPT_FLAGS_CPID = 0;
+const int ACE_ATM_Addr::OPT_FLAGS_PMP = 0;
+const int ACE_ATM_Addr::DEFAULT_SELECTOR = 0x99;
+#else
+const long ACE_ATM_Addr::LINE_RATE = 0L;
+const int ACE_ATM_Addr::OPT_FLAGS_CPID = 0;
+const int ACE_ATM_Addr::OPT_FLAGS_PMP = 0;
+const int ACE_ATM_Addr::DEFAULT_SELECTOR = 0x0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+
+// Default constructor
+
+ACE_ATM_Addr::ACE_ATM_Addr (u_char selector)
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ : ACE_Addr (AF_ATM,
+#elif defined (ACE_HAS_LINUX_ATM)
+ : ACE_Addr (PF_ATMSVC,
+#else
+ : ACE_Addr (AF_UNSPEC,
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+ sizeof this->atm_addr_)
+{
+ // ACE_TRACE ("ACE_ATM_Addr::ACE_ATM_Addr");
+ (void) ACE_OS::memset ((void *) &this->atm_addr_,
+ 0,
+ sizeof this->atm_addr_);
+ this->init (selector);
+}
+
+// Copy constructor.
+
+ACE_ATM_Addr::ACE_ATM_Addr (const ACE_ATM_Addr &sap,
+ u_char selector)
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ : ACE_Addr (AF_ATM,
+#elif defined (ACE_HAS_LINUX_ATM)
+ : ACE_Addr (PF_ATMSVC,
+#else
+ : ACE_Addr (AF_UNSPEC,
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+ sizeof this->atm_addr_)
+{
+ ACE_TRACE ("ACE_ATM_Addr::ACE_ATM_Addr");
+ this->set (sap, selector);
+#if defined (ACE_HAS_LINUX_ATM)
+ this->atm_addr_.sockaddratmsvc.sas_family = PF_ATMSVC;
+ this->atm_addr_.atmsap.blli[0].l3_proto = ATM_L3_NONE;
+ this->atm_addr_.atmsap.blli[0].l2_proto = ATM_L2_NONE;
+ this->atm_addr_.atmsap.bhli.hl_type = ATM_HL_NONE;
+#endif /* ACE_HAS_LINUX_ATM */
+}
+
+ACE_ATM_Addr::ACE_ATM_Addr (const ATM_Addr *sap,
+ u_char selector)
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ : ACE_Addr (AF_ATM,
+#elif defined (ACE_HAS_LINUX_ATM)
+ : ACE_Addr (PF_ATMSVC,
+#else
+ : ACE_Addr (AF_UNSPEC,
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+ sizeof this->atm_addr_)
+{
+ ACE_TRACE ("ACE_ATM_Addr::ACE_ATM_Addr");
+ this->set (sap, selector);
+}
+
+
+ACE_ATM_Addr::ACE_ATM_Addr (const ACE_TCHAR sap[],
+ u_char selector)
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ : ACE_Addr (AF_ATM,
+#elif defined (ACE_HAS_LINUX_ATM)
+ : ACE_Addr (PF_ATMSVC,
+#else
+ : ACE_Addr (AF_UNSPEC,
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+ sizeof this->atm_addr_)
+{
+ ACE_TRACE ("ACE_ATM_Addr::ACE_ATM_Addr");
+ this->set (sap, selector);
+}
+
+ACE_ATM_Addr::~ACE_ATM_Addr (void)
+{
+}
+
+// Return the address.
+
+void *
+ACE_ATM_Addr::get_addr (void) const
+{
+ ACE_TRACE ("ACE_ATM_Addr::get_addr");
+ return (void *) &this->atm_addr_;
+}
+
+void
+ACE_ATM_Addr::init (u_char selector)
+{
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ // Note: this approach may be FORE implementation-specific. When we
+ // bind with tag_addr ABSENT and tag_selector PRESENT, only the
+ // selector (i.e. address[19]) is used by the TP. The rest of the
+ // local address is filled in by the TP and can be obtained via the
+ // 'ret' parameter or with t_getname ()/t_getprotaddr ().
+
+ atm_addr_.addressType = (u_int16_t) AF_ATM;
+
+ atm_addr_.sap.t_atm_sap_addr.SVE_tag_addr = (int8_t) T_ATM_ABSENT;
+ atm_addr_.sap.t_atm_sap_addr.SVE_tag_selector = (int8_t) T_ATM_PRESENT;
+
+ atm_addr_.sap.t_atm_sap_addr.address_format = (u_int8_t) T_ATM_ENDSYS_ADDR;
+ atm_addr_.sap.t_atm_sap_addr.address_length = ATMNSAP_ADDR_LEN;
+ atm_addr_.sap.t_atm_sap_addr.address[ATMNSAP_ADDR_LEN - 1] = selector;
+
+ atm_addr_.sap.t_atm_sap_layer2.SVE_tag = (int8_t) T_ATM_ABSENT;
+ atm_addr_.sap.t_atm_sap_layer3.SVE_tag = (int8_t) T_ATM_ABSENT;
+
+ atm_addr_.sap.t_atm_sap_appl.SVE_tag = (int8_t) T_ATM_PRESENT;
+ atm_addr_.sap.t_atm_sap_appl.ID_type = (u_int8_t) T_ATM_USER_APP_ID;
+
+ ACE_OS::memcpy (atm_addr_.sap.t_atm_sap_appl.ID.user_defined_ID,
+ BHLI_MAGIC,
+ sizeof atm_addr_.sap.t_atm_sap_appl.ID);
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ ACE_OS::memset ((void *)&atm_addr_, 0, sizeof atm_addr_);
+ atm_addr_.satm_number.Addr[ ATM_ADDR_SIZE - 1 ] = (char)selector;
+ atm_addr_.satm_family = AF_ATM;
+ atm_addr_.satm_number.AddressType = ATM_NSAP;
+ atm_addr_.satm_number.NumofDigits = ATM_ADDR_SIZE;
+ atm_addr_.satm_blli.Layer2Protocol = SAP_FIELD_ABSENT;
+ atm_addr_.satm_blli.Layer3Protocol = SAP_FIELD_ABSENT;
+ atm_addr_.satm_bhli.HighLayerInfoType = SAP_FIELD_ABSENT;
+
+ // Need to know the correspondence.
+ //atm_addr_.sap.t_atm_sap_appl.SVE_tag = (int8_t) T_ATM_PRESENT;
+ //atm_addr_.sap.t_atm_sap_appl.ID_type = (u_int8_t) T_ATM_USER_APP_ID;
+ //ACE_OS::memcpy (atm_addr_.sap.t_atm_sap_appl.ID.user_defined_ID,
+ // BHLI_MAGIC,
+ // sizeof atm_addr_.sap.t_atm_sap_appl.ID);
+#elif defined (ACE_HAS_LINUX_ATM)
+ atm_addr_.sockaddratmsvc.sas_family = AF_ATMSVC;
+ atm_addr_.sockaddratmsvc.sas_addr.prv[ATM_ESA_LEN - 1] = (char)selector;
+ atm_addr_.atmsap.blli[0].l3_proto = ATM_L3_NONE;
+ atm_addr_.atmsap.blli[0].l2_proto = ATM_L2_NONE;
+ atm_addr_.atmsap.bhli.hl_type = ATM_HL_NONE;
+#else
+ ACE_UNUSED_ARG (selector);
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+}
+
+int
+ACE_ATM_Addr::set (const ACE_ATM_Addr &sap,
+ u_char selector)
+{
+ ACE_TRACE ("ACE_ATM_Addr::set");
+
+ this->init (selector);
+
+ this->ACE_Addr::base_set (sap.get_type (),
+ sap.get_size ());
+
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ ACE_ASSERT (sap.get_type () == AF_ATM);
+#elif defined (ACE_HAS_LINUX_ATM)
+ ACE_ASSERT (sap.get_type () == PF_ATMSVC);
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 */
+
+ (void) ACE_OS::memcpy ((void *) &this->atm_addr_,
+ (void *) &sap.atm_addr_,
+ sizeof this->atm_addr_);
+ return 0;
+}
+
+int
+ACE_ATM_Addr::set (const ATM_Addr *sap,
+ u_char selector)
+{
+ ACE_TRACE ("ACE_ATM_Addr::set");
+
+ this->init (selector);
+
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ this->ACE_Addr::base_set (AF_ATM,
+#elif defined (ACE_HAS_LINUX_ATM)
+ this->ACE_Addr::base_set (PF_ATMSVC,
+#else
+ this->ACE_Addr::base_set (AF_UNSPEC,
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 */
+ sizeof (*sap));
+
+ (void) ACE_OS::memcpy ((void *) &this->atm_addr_,
+ (void *) sap,
+ sizeof this->atm_addr_);
+ return 0;
+}
+
+int
+ACE_ATM_Addr::set (const ACE_TCHAR address[],
+ u_char selector)
+{
+ ACE_TRACE ("ACE_ATM_Addr::set");
+ int ret;
+
+ this->init (selector);
+
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ atm_addr_.sap.t_atm_sap_addr.SVE_tag_addr =
+ (int8_t) T_ATM_PRESENT;
+#endif /* ACE_HAS_FORE_ATM_XTI */
+
+ ret = this -> string_to_addr (address);
+ this -> set_selector (selector);
+ return ret;
+}
+
+// Transform the string into the current addressing format.
+
+int
+ACE_ATM_Addr::string_to_addr (const ACE_TCHAR sap[])
+{
+ ACE_TRACE ("ACE_ATM_Addr::string_to_addr");
+
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ this->ACE_Addr::base_set (AF_ATM,
+#elif defined (ACE_HAS_LINUX_ATM)
+ this->ACE_Addr::base_set (PF_ATMSVC,
+#else
+ this->ACE_Addr::base_set (AF_UNSPEC,
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+ sizeof this->atm_addr_);
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ struct hostent *entry;
+ struct atmnsap_addr *nsap;
+
+ // Yow, someone gave us a NULL ATM address!
+ if (sap == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else if ((entry = gethostbyname_atmnsap ((ACE_TCHAR *)sap)) != 0)
+ {
+ ACE_OS::memcpy (atm_addr_.sap.t_atm_sap_addr.address,
+ entry->h_addr_list[0],
+ ATMNSAP_ADDR_LEN - 1);
+ }
+ else if ((nsap = atmnsap_addr (sap)) != 0)
+ {
+ ACE_OS::memcpy (atm_addr_.sap.t_atm_sap_addr.address,
+ nsap->atmnsap,
+ ATMNSAP_ADDR_LEN);
+ }
+ else {
+ errno = EINVAL;
+ return -1;
+ }
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ DWORD dwValue;
+ HANDLE hLookup;
+ WSAQUERYSETW qsRestrictions;
+ CSADDR_INFO csaBuffer;
+ WCHAR tmpWStr[100];
+
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sap, -1, tmpWStr, 100);
+
+ csaBuffer.LocalAddr.iSockaddrLength = sizeof (struct sockaddr_atm);
+ csaBuffer.LocalAddr.lpSockaddr = (struct sockaddr *)&atm_addr_;
+ csaBuffer.RemoteAddr.iSockaddrLength = sizeof (struct sockaddr_atm);
+ csaBuffer.RemoteAddr.lpSockaddr = (struct sockaddr *)&atm_addr_;
+
+ qsRestrictions.dwSize = sizeof (WSAQUERYSETW);
+ qsRestrictions.lpszServiceInstanceName = 0;
+ qsRestrictions.lpServiceClassId = &FORE_NAME_CLASS;
+ qsRestrictions.lpVersion = 0;
+ qsRestrictions.lpszComment = 0;
+ qsRestrictions.dwNameSpace = FORE_NAME_SPACE;
+ qsRestrictions.lpNSProviderId = 0;
+ qsRestrictions.lpszContext = L"";
+ qsRestrictions.dwNumberOfProtocols = 0;
+ qsRestrictions.lpafpProtocols = 0;
+ qsRestrictions.lpszQueryString = tmpWStr;
+ qsRestrictions.dwNumberOfCsAddrs = 1;
+ qsRestrictions.lpcsaBuffer = &csaBuffer;
+ qsRestrictions.lpBlob = 0; //&blob;
+
+ if (::WSALookupServiceBeginW (&qsRestrictions, LUP_RETURN_ALL, &hLookup)
+ == SOCKET_ERROR) {
+ ACE_OS::printf ("Error: WSALookupServiceBeginW failed! %d\n",
+ ::WSAGetLastError ());
+ return -1;
+ }
+
+ dwValue = sizeof (WSAQUERYSETW);
+
+ if (::WSALookupServiceNextW (hLookup, 0, &dwValue, &qsRestrictions)
+ == SOCKET_ERROR) {
+ if (WSAGetLastError () != WSA_E_NO_MORE) {
+ ACE_OS::printf ("Error: WSALookupServiceNextW failed! %d\n",
+ ::WSAGetLastError ());
+ return -1;
+ }
+ }
+
+ if (WSALookupServiceEnd (hLookup) == SOCKET_ERROR) {
+ ACE_OS::printf ("Error : WSALookupServiceEnd failed! %d \n",
+ ::WSAGetLastError ());
+ errno = EINVAL;
+ return -1;
+ }
+#elif defined (ACE_HAS_LINUX_ATM)
+ if (sap == 0 || !ACE_OS::strcmp (sap,"")) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (text2atm ((ACE_TCHAR *)sap,
+ (struct sockaddr *)& (atm_addr_.sockaddratmsvc),
+ sizeof (atm_addr_.sockaddratmsvc),
+ T2A_SVC | T2A_NAME) < 0) {
+ ACE_DEBUG (LM_DEBUG,
+ "Error : text2atm failed!\n");
+ errno = EINVAL;
+ return -1;
+ }
+#else
+ ACE_UNUSED_ARG (sap);
+
+ return 0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
+ return 0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 */
+}
+
+// Transform the current address into string format.
+
+int
+ACE_ATM_Addr::addr_to_string (ACE_TCHAR addr[],
+ size_t addrlen) const
+{
+ ACE_TRACE ("ACE_ATM_Addr::addr_to_string");
+
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ ACE_TCHAR buffer[MAXNAMELEN + 1];
+ struct atmnsap_addr nsap;
+ ACE_OS::memcpy (nsap.atmnsap,
+ atm_addr_.sap.t_atm_sap_addr.address,
+ ATMNSAP_ADDR_LEN);
+ ACE_OS::sprintf (buffer,
+ ACE_TEXT ("%s"),
+ atmnsap_ntoa (nsap));
+
+ size_t total_len = ACE_OS::strlen (buffer) + sizeof ('\0');
+
+ if (addrlen < total_len)
+ return -1;
+ else
+ ACE_OS::strcpy (addr, buffer);
+
+ return 0;
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ ACE_TCHAR buffer[MAXNAMELEN + 1];
+ int i;
+
+ if (addrlen < ATM_ADDR_SIZE + 1)
+ return -1;
+
+ for (i = 0; i < ATM_ADDR_SIZE; i++) {
+ buffer[ i * 3 ] = '\0';
+ ACE_OS::sprintf (buffer, ACE_TEXT ("%s%02x."),
+ buffer,
+ atm_addr_.satm_number.Addr[ i ]);
+ }
+
+ buffer[ ATM_ADDR_SIZE * 3 - 1 ] = '\0';
+ ACE_OS::strcpy (addr, buffer);
+
+ return 0;
+#elif defined (ACE_HAS_LINUX_ATM)
+ ACE_TCHAR buffer[MAX_ATM_ADDR_LEN + 1];
+ int total_len;
+ if ((total_len = atm2text (buffer,
+ sizeof buffer,
+ (struct sockaddr *)& (atm_addr_.sockaddratmsvc),
+ A2T_PRETTY)) < 0) {
+ ACE_DEBUG ((LM_DEBUG,"ACE_ATM_Addr (addr_to_string): atm2text failed\n"));
+ return -1;
+ }
+ if (addrlen < (size_t)total_len)
+ return -1;
+ else
+ ACE_OS::strcpy (addr,
+ buffer);
+
+ return 0;
+#else
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ return -1;
+#endif /* ACE_HAS_FORE_ATM_XTI && ACE_HAS_FORE_ATM_WS2 */
+}
+
+const ACE_TCHAR *
+ACE_ATM_Addr::addr_to_string (void) const
+{
+ ACE_TRACE ("ACE_ATM_Addr::addr_to_string");
+
+ static ACE_TCHAR addr[MAXHOSTNAMELEN + 1];
+ if (this->addr_to_string (addr,
+ MAXHOSTNAMELEN + 1) < 0)
+ return 0;
+
+ return addr;
+}
+
+// Set a pointer to the address.
+void
+ACE_ATM_Addr::set_addr (void *addr, int len)
+{
+ ACE_TRACE ("ACE_ATM_Addr::set_addr");
+
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ this->ACE_Addr::base_set (AF_ATM,
+#elif defined (ACE_HAS_LINUX_ATM)
+ this->ACE_Addr::base_set (PF_ATMSVC,
+#else
+ this->ACE_Addr::base_set (AF_UNSPEC,
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_WS2 */
+ len);
+ ACE_OS::memcpy ((void *) &this->atm_addr_,
+ (void *) addr, len);
+}
+
+// Compare two addresses for inequality.
+
+bool
+ACE_ATM_Addr::operator != (const ACE_ATM_Addr &sap) const
+{
+ ACE_TRACE ("ACE_ATM_Addr::operator !=");
+ return ! ((*this) == sap);
+}
+
+// Compare two addresses for equality.
+
+bool
+ACE_ATM_Addr::operator == (const ACE_ATM_Addr &sap) const
+{
+ ACE_TRACE ("ACE_ATM_Addr::operator ==");
+
+#if defined (ACE_HAS_LINUX_ATM)
+ return (atm_equal ((const struct sockaddr *)& (this->atm_addr_.sockaddratmsvc),
+ (const struct sockaddr *)& (sap.atm_addr_.sockaddratmsvc),
+ 0,
+ 0)
+ &&
+ sap_equal (& (this->atm_addr_.atmsap),
+ & (sap.atm_addr_.atmsap),
+ 0));
+#else
+ return ACE_OS::memcmp (&atm_addr_,
+ &sap.atm_addr_,
+ sizeof (ATM_Addr)) == 0;
+#endif /* ACE_HAS_LINUX_ATM */
+}
+
+void
+ACE_ATM_Addr::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_ATM_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_TCHAR s[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16];
+ ACE_OS::sprintf (s,
+ ACE_TEXT ("%s"),
+ this->addr_to_string ());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%s"), s));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_ATM */
diff --git a/ACE/ace/ATM_Addr.h b/ACE/ace/ATM_Addr.h
new file mode 100644
index 00000000000..34cbfd876a6
--- /dev/null
+++ b/ACE/ace/ATM_Addr.h
@@ -0,0 +1,197 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file ATM_Addr.h
+ *
+ * $Id$
+ *
+ * @author Joe Hoffert <joeh@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_ATM_ADDR_H
+#define ACE_ATM_ADDR_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_HAS_ATM)
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/Addr.h"
+
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef ATMSAPAddress ATM_Addr;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+#define FORE_NAME_SPACE NS_ALL
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef struct sockaddr_atm ATM_Addr;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#elif defined (ACE_HAS_LINUX_ATM)
+
+#include /**/ "atm.h"
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//pbrandao:as Linux has this 2 structs separeted we "link it" here
+typedef struct _linux_atm_addr
+{
+ struct sockaddr_atmsvc sockaddratmsvc;
+ struct atm_sap atmsap;
+} ATM_Addr;
+#else
+typedef int ATM_Addr;
+#endif /* ACE_HAS_FORE_ATM_XTI/ACE_HAS_FORE_ATM_WS2/ACE_HAS_LINUX_ATM */
+
+/**
+ * @class ACE_ATM_Addr
+ *
+ * @brief Defines the ATM domain address family address format.
+ */
+class ACE_Export ACE_ATM_Addr : public ACE_Addr
+{
+public:
+ // Constants used for ATM options
+ static const long LINE_RATE;
+ static const int OPT_FLAGS_CPID;
+ static const int OPT_FLAGS_PMP;
+ static const int DEFAULT_SELECTOR;
+
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_ATM_Addr (u_char selector = DEFAULT_SELECTOR);
+
+ /// Copy constructor.
+ ACE_ATM_Addr (const ACE_ATM_Addr &,
+ u_char selector = DEFAULT_SELECTOR);
+
+ /**
+ * Creates an ACE_ATM_Addr from an ATMSAPAddress structure. This
+ * is vendor specific (FORE systems). May need to change when other
+ * vendors are supported.
+ */
+ ACE_ATM_Addr (const ATM_Addr *,
+ u_char selector = DEFAULT_SELECTOR);
+
+ /**
+ * Initializes an ACE_ATM_Addr from the <sap> which can be
+ * "atm-address" (e.g.,
+ * "47.0005.80.ffe100.0000.f20f.2200.0020480694f9.00") or "hostname"
+ * (e.g., "frisbee.cs.wustl.edu").
+ */
+ ACE_ATM_Addr (const ACE_TCHAR sap[],
+ u_char selector = DEFAULT_SELECTOR);
+
+ /// Default dtor.
+ ~ACE_ATM_Addr (void);
+
+ // = Initialization methods (useful after object construction).
+ /// Default initialization for non-address values (e.g.,
+ /// t_atm_sap_addr.SVE_tag_addr, t_atm_sap_addr.SVE_tag_selector)
+ void init (u_char selector = DEFAULT_SELECTOR);
+
+ /// Initializes from another ACE_ATM_Addr.
+ int set (const ACE_ATM_Addr &,
+ u_char selector = DEFAULT_SELECTOR);
+
+ /**
+ * Initializes an ACE_ATM_Addr from an ATMSAPAddress/sockaddr_atm
+ * structure. This is vendor specific (FORE systems). May need to
+ * change when other vendors are supported.
+ */
+ int set (const ATM_Addr *,
+ u_char selector = DEFAULT_SELECTOR);
+
+ /**
+ * Initializes an ACE_ATM_Addr from the <sap> which can be
+ * "atm-address" (e.g.,
+ * "47.0005.80.ffe100.0000.f20f.2200.0020480694f9.00") or "hostname"
+ * (e.g., "frisbee.cs.wustl.edu").
+ */
+ int set (const ACE_TCHAR sap[],
+ u_char selector = DEFAULT_SELECTOR);
+
+ /**
+ * Initializes an ACE_ATM_Addr from the <sap> which can be
+ * "atm-address" (e.g.,
+ * "47.0005.80.ffe100.0000.f20f.2200.0020480694f9.00") or "hostname"
+ * (e.g., "frisbee.cs.wustl.edu").
+ */
+ virtual int string_to_addr (const ACE_TCHAR sap[]);
+
+ /**
+ * Return the character representation of the ATM address (e.g.,
+ * "47.0005.80.ffe100.0000.f20f.2200.0020480694f9.00") storing it in
+ * the @a addr (which is assumed to be <addrlen> bytes long). This
+ * version is reentrant. Returns -1 if the <addrlen> of the @a addr
+ * is too small, else 0.
+ */
+ virtual int addr_to_string (ACE_TCHAR addr[],
+ size_t addrlen) const;
+
+ /**
+ * Return the character representation of the ATM address (e.g.,
+ * "47.0005.80.ffe100.0000.f20f.2200.0020480694f9.00"). Returns -1
+ * if the <size> of the <buffer> is too small, else 0.(This version
+ * is non-reentrant since it returns a pointer to a static data
+ * area.)
+ */
+ const ACE_TCHAR *addr_to_string (void) const;
+
+ /// 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);
+
+ /// Return the selector for network address.
+ u_char get_selector (void) const;
+
+ /// Set the selector for the network address.
+ void set_selector (u_char selector);
+
+ /**
+ * Compare two addresses for equality. The addresses are considered
+ * equal if they contain the same ATM address. Q: Is there any
+ * other check for equality needed for ATM?
+ */
+ bool operator == (const ACE_ATM_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ bool operator != (const ACE_ATM_Addr &SAP) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+// char *construct_options (ACE_HANDLE fd,
+// int qos_kb,
+// int flags,
+// long *optsize);
+// // Construct options for ATM connections
+
+private:
+ ATM_Addr atm_addr_;
+};
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#if defined (__ACE_INLINE__)
+#include "ace/ATM_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_ATM */
+#include /**/ "ace/post.h"
+#endif /* ACE_ATM_ADDR_H */
diff --git a/ACE/ace/ATM_Addr.inl b/ACE/ace/ATM_Addr.inl
new file mode 100644
index 00000000000..8120c6d11d5
--- /dev/null
+++ b/ACE/ace/ATM_Addr.inl
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE u_char
+ACE_ATM_Addr::get_selector (void) const
+{
+ ACE_TRACE ("ACE_ATM_Addr::get_selector");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ return atm_addr_.sap.t_atm_sap_addr.address[ATMNSAP_ADDR_LEN - 1];
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ return atm_addr_.satm_number.Addr[ ATM_ADDR_SIZE - 1 ];
+#elif defined (ACE_HAS_LINUX_ATM)
+ return atm_addr_.sockaddratmsvc.sas_addr.prv[ATM_ESA_LEN - 1];
+#else
+ return 0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+}
+
+ACE_INLINE void
+ACE_ATM_Addr::set_selector (u_char selector)
+{
+ ACE_TRACE ("ACE_ATM_Addr::set_selector");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ atm_addr_.sap.t_atm_sap_addr.address[ATMNSAP_ADDR_LEN - 1] = selector;
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ atm_addr_.satm_number.Addr[ ATM_ADDR_SIZE - 1 ] = selector;
+#elif defined (ACE_HAS_LINUX_ATM)
+ atm_addr_.sockaddratmsvc.sas_addr.prv[ATM_ESA_LEN - 1] = selector;
+#else
+ ACE_UNUSED_ARG (selector);
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ATM_Connector.cpp b/ACE/ace/ATM_Connector.cpp
new file mode 100644
index 00000000000..ca33a2bb833
--- /dev/null
+++ b/ACE/ace/ATM_Connector.cpp
@@ -0,0 +1,138 @@
+// ATM_Connector.cpp
+// $Id$
+
+#include "ace/ATM_Connector.h"
+#if defined (ACE_HAS_ATM)
+
+#include "ace/Handle_Set.h"
+
+ACE_RCSID(ace, ATM_Connector, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/ATM_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_ATM_Connector)
+
+ACE_ATM_Connector::ACE_ATM_Connector (void)
+{
+ ACE_TRACE ("ACE_ATM_Connector::ACE_ATM_Connector");
+}
+
+// Actively connect and produce a new ACE_ATM_Stream if things go well...
+// Connect the <new_stream> to the <remote_sap>, waiting up to
+// <timeout> amount of time if necessary.
+
+int
+ACE_ATM_Connector::connect (ACE_ATM_Stream &new_stream,
+ const ACE_ATM_Addr &remote_sap,
+ ACE_ATM_Params params,
+ ACE_ATM_QoS options,
+ ACE_Time_Value *timeout,
+ const ACE_ATM_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_ATM_Connector::connect");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ return connector_.connect(new_stream.get_stream(),
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ params.get_device(),
+ params.get_info(),
+ params.get_rw_flag(),
+ params.get_user_data(),
+ &options.get_qos());
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ ACE_DEBUG(LM_DEBUG,
+ ACE_TEXT ("ATM_Connector(connect): set QoS parameters\n" ));
+
+ ACE_HANDLE s = new_stream.get_handle();
+ struct sockaddr_atm *saddr = ( struct sockaddr_atm *)remote_sap.get_addr();
+ ACE_QoS cqos = options.get_qos();
+
+ ACE_QoS_Params qos_params = ACE_QoS_Params(0,
+ 0,
+ &cqos,
+ 0,
+ 0);
+
+ ACE_DEBUG(LM_DEBUG,
+ ACE_TEXT ("ATM_Connector(connect): connecting...\n"));
+
+ int result = ACE_OS::connect( s,
+ ( struct sockaddr *)saddr,
+ sizeof( struct sockaddr_atm ),
+ qos_params );
+
+ if ( result != 0 )
+ ACE_OS::printf( "ATM_Connector(connect): connection failed, %d\n",
+ ::WSAGetLastError());
+
+ return result;
+#elif defined (ACE_HAS_LINUX_ATM)
+ ACE_UNUSED_ARG (params);
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (reuse_addr);
+ ACE_UNUSED_ARG (perms);
+ ACE_UNUSED_ARG (flags);
+
+ ACE_HANDLE handle = new_stream.get_handle();
+ ATM_QoS qos =options.get_qos();
+ ATM_Addr *local_addr=(ATM_Addr*)local_sap.get_addr(),
+ *remote_addr=(ATM_Addr*)remote_sap.get_addr();
+
+ if (ACE_OS::setsockopt(handle,
+ SOL_ATM,
+ SO_ATMSAP,
+ reinterpret_cast<char*> (&(local_addr->atmsap)),
+ sizeof(local_addr->atmsap)) < 0) {
+ ACE_OS::printf( "ATM_Connector(connect): unable to set atmsap %d\nContinuing...",
+ errno);
+ }
+ if (ACE_OS::setsockopt(handle,
+ SOL_ATM,
+ SO_ATMQOS,
+ reinterpret_cast<char*> (&qos),
+ sizeof(qos)) < 0) {
+ ACE_DEBUG((LM_DEBUG,ACE_TEXT ("ATM_Connector(connect): unable to set qos %d\n"),
+ errno));
+ return -1;
+ }
+
+ int result = ACE_OS::connect(handle,
+ (struct sockaddr *)&(remote_addr->sockaddratmsvc),
+ sizeof( remote_addr->sockaddratmsvc));
+
+ if ( result != 0 )
+ ACE_DEBUG(LM_DEBUG,
+ ACE_TEXT ("ATM_Connector(connect): connection failed, %d\n"),
+ errno);
+
+ return result;
+#else
+ ACE_UNUSED_ARG (new_stream);
+ ACE_UNUSED_ARG (remote_sap);
+ ACE_UNUSED_ARG (params);
+ ACE_UNUSED_ARG (options);
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (local_sap);
+ ACE_UNUSED_ARG (reuse_addr);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (perms);
+ return 0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_ATM */
diff --git a/ACE/ace/ATM_Connector.h b/ACE/ace/ATM_Connector.h
new file mode 100644
index 00000000000..7e820ae765e
--- /dev/null
+++ b/ACE/ace/ATM_Connector.h
@@ -0,0 +1,164 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file ATM_Connector.h
+ *
+ * $Id$
+ *
+ * @author Joe Hoffert <joeh@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ATM_CONNECTOR_H
+#define ACE_ATM_CONNECTOR_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_HAS_ATM)
+
+#include "ace/ATM_Stream.h"
+#include "ace/ATM_Params.h"
+#include "ace/ATM_QoS.h"
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_LINUX_ATM)
+#include "ace/SOCK_Connector.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef ACE_SOCK_Connector ATM_Connector;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#else
+#include "ace/XTI_ATM_Mcast.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef ACE_XTI_ATM_Mcast ATM_Connector;
+// Open versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_ATM_Connector
+ *
+ * @brief Defines an active connection factory for the ACE_ATM C++
+ * wrappers.
+ */
+class ACE_Export ACE_ATM_Connector
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_ATM_Connector (void);
+
+ /**
+ * Actively connect and produce a @a new_stream if things go well.
+ * The @a remote_sap is the address that we are trying to connect
+ * with. The <params> are the parameters needed for either socket
+ * or XTI/ATM connections. The @a 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 @c 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
+ * @c errno == ETIME. The @a local_sap is the value of local address
+ * to bind to. If it's the default value of <ACE_ATM_Addr::sap_any> then
+ * the user is letting the OS do the binding. If @a reuse_addr == 1
+ * then the <local_addr> is reused, even if it hasn't been cleanedup yet.
+ */
+ ACE_ATM_Connector (ACE_ATM_Stream &new_stream,
+ const ACE_ATM_Addr &remote_sap,
+ ACE_ATM_Params params = ACE_ATM_Params(),
+ ACE_ATM_QoS options = ACE_ATM_QoS(),
+ ACE_Time_Value *timeout = 0,
+ const ACE_ATM_Addr &local_sap = ACE_ATM_Addr( "", 0 ),
+ int reuse_addr = 0,
+#if defined (ACE_WIN32)
+ int flags = 0,
+#else
+ int flags = O_RDWR,
+#endif /* ACE_WIN32 */
+ int perms = 0);
+
+ /**
+ * Actively connect and produce a @a new_stream if things go well.
+ * The @a remote_sap is the address that we are trying to connect
+ * with. The <params> are the parameters needed for either socket
+ * or XTI/ATM connections. The @a 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 @c 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
+ * @c errno == ETIME. The @a local_sap is the value of local address
+ * to bind to. If it's the default value of <ACE_ATM_Addr::sap_any> then
+ * the user is letting the OS do the binding. If @a reuse_addr == 1
+ * then the <local_addr> is reused, even if it hasn't been cleanedup yet.
+ */
+ int connect (ACE_ATM_Stream &new_stream,
+ const ACE_ATM_Addr &remote_sap,
+ ACE_ATM_Params params = ACE_ATM_Params(),
+ ACE_ATM_QoS options = ACE_ATM_QoS(),
+ ACE_Time_Value *timeout = 0,
+ const ACE_ATM_Addr &local_sap = ACE_ATM_Addr( "",
+ 0 ),
+ int reuse_addr = 0,
+#if defined (ACE_WIN32)
+ int flags = 0,
+#else
+ int flags = O_RDWR,
+#endif /* ACE_WIN32 */
+ int perms = 0);
+
+ /**
+ * Try to complete a non-blocking connection.
+ * If connection completion is successful then @a new_stream contains
+ * the connected ACE_SOCK_Stream. If @a remote_sap is non-NULL then it
+ * will contain the address of the connected peer.
+ */
+ int complete (ACE_ATM_Stream &new_stream,
+ ACE_ATM_Addr *remote_sap,
+ ACE_Time_Value *tv);
+
+ /**
+ * Actively add a leaf to the root (i.e., point-to-multipoint). The
+ * @a remote_sap is the address of the leaf that we
+ * are trying to add.
+ */
+ int add_leaf (ACE_ATM_Stream &current_stream,
+ const ACE_Addr &remote_sap,
+ ACE_ATM_QoS &qos);
+
+ /// Resets any event associations on this handle
+ int reset_new_handle (ACE_HANDLE handle);
+
+ // = Meta-type info
+ typedef ACE_ATM_Addr PEER_ADDR;
+ typedef ACE_ATM_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ATM_Connector connector_;
+};
+
+// Open versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/ATM_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_ATM */
+#include /**/ "ace/post.h"
+#endif /* ACE_ATM_CONNECTOR_H */
diff --git a/ACE/ace/ATM_Connector.inl b/ACE/ace/ATM_Connector.inl
new file mode 100644
index 00000000000..b9372ccb34d
--- /dev/null
+++ b/ACE/ace/ATM_Connector.inl
@@ -0,0 +1,132 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_ATM_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_ATM_Connector::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_INLINE
+ACE_ATM_Connector::ACE_ATM_Connector (ACE_ATM_Stream &new_stream,
+ const ACE_ATM_Addr &remote_sap,
+ ACE_ATM_Params params,
+ ACE_ATM_QoS options,
+ ACE_Time_Value *timeout,
+ const ACE_ATM_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_ATM_Connector::ACE_ATM_Connector");
+ if ((ACE_HANDLE)this->connect (new_stream,
+ remote_sap,
+ params,
+ options,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms) == ACE_INVALID_HANDLE
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_ATM_Stream::ACE_ATM_Stream")));
+}
+
+// Try to complete a non-blocking connection.
+
+ACE_INLINE
+int
+ACE_ATM_Connector::complete (ACE_ATM_Stream &new_stream,
+ ACE_ATM_Addr *remote_sap,
+ ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_ATM_Connector::complete");
+#if defined (ACE_HAS_ATM)
+ return connector_.complete(new_stream.get_stream(),
+ remote_sap,
+ tv);
+#else
+ ACE_UNUSED_ARG(new_stream);
+ ACE_UNUSED_ARG(remote_sap);
+ ACE_UNUSED_ARG(tv);
+ return 0;
+#endif
+}
+
+ACE_INLINE
+int
+ACE_ATM_Connector::add_leaf (ACE_ATM_Stream &current_stream,
+ const ACE_Addr &remote_sap,
+ ACE_ATM_QoS &qos)
+{
+ ACE_TRACE ("ACE_ATM_Connector::add_leaf");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ return connector_.add_leaf(current_stream.get_stream(),
+ remote_sap,
+ leaf_id,
+ timeout);
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ struct sockaddr_atm *saddr = (struct sockaddr_atm *)remote_sap.get_addr();
+ ACE_QoS cqos = qos.get_qos();
+ int addr_len = sizeof( struct sockaddr_atm );
+
+ ACE_QoS_Params qos_params(0,
+ 0,
+ &cqos,
+ 0,
+ (JL_SENDER_ONLY));
+
+ ACE_OS::printf( "ATM_Connector::add_leaf: connecting...\n" );
+
+ ACE_HANDLE result = ACE_OS::join_leaf(current_stream.get_handle(),
+ (struct sockaddr *)saddr,
+ addr_len,
+ qos_params);
+
+ if ( result == ACE_INVALID_HANDLE )
+ ACE_OS::printf( "ATM_Connector(add_leaf): connection failed, %d\n",
+ ::WSAGetLastError());
+
+ return (result != ACE_INVALID_HANDLE);
+#elif defined (ACE_HAS_LINUX_ATM)
+ ACE_OS::printf("ATM_Connector(add_leaf): not yet implemented in Linux \n");
+
+ ACE_UNUSED_ARG(current_stream);
+ ACE_UNUSED_ARG(remote_sap);
+ ACE_UNUSED_ARG(leaf_id);
+ ACE_UNUSED_ARG(timeout);
+
+ return 0;
+#else
+ ACE_UNUSED_ARG(current_stream);
+ ACE_UNUSED_ARG(remote_sap);
+ ACE_UNUSED_ARG(leaf_id);
+ ACE_UNUSED_ARG(timeout);
+ return 0;
+#endif
+}
+
+ACE_INLINE
+int
+ACE_ATM_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ // Reset the event association
+ return ::WSAEventSelect ((SOCKET) handle,
+ 0,
+ 0);
+#else /* !defined ACE_HAS_WINSOCK2 */
+ ACE_UNUSED_ARG (handle);
+ return 0;
+#endif /* ACE_WIN32 */
+}
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ATM_Params.cpp b/ACE/ace/ATM_Params.cpp
new file mode 100644
index 00000000000..cc6ec674ece
--- /dev/null
+++ b/ACE/ace/ATM_Params.cpp
@@ -0,0 +1,20 @@
+// $Id$
+
+#include "ace/ATM_Params.h"
+
+#if defined (ACE_HAS_ATM)
+
+ACE_RCSID(ace, ATM_Params, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/ATM_Params.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_ATM_Params)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_ATM */
+
diff --git a/ACE/ace/ATM_Params.h b/ACE/ace/ATM_Params.h
new file mode 100644
index 00000000000..82cf6999b3b
--- /dev/null
+++ b/ACE/ace/ATM_Params.h
@@ -0,0 +1,214 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file ATM_Params.h
+ *
+ * $Id$
+ *
+ * @author Joe Hoffert <joeh@cs.wustl.edu>
+ */
+//==========================================================================
+
+
+#ifndef ACE_ATM_PARAMS_H
+#define ACE_ATM_PARAMS_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_HAS_ATM)
+
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_HAS_FORE_ATM_XTI)
+#include "ace/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"
+#define ATM_PROTOCOL_DEFAULT ATMPROTO_AAL5
+#define ACE_XTI_ATM_DEVICE ""
+typedef int Param_Info;
+typedef int Param_Udata;
+#elif defined (ACE_HAS_LINUX_ATM)
+#include /**/ "atm.h"
+#define AF_ATM PF_ATMSVC
+#define ACE_XTI_ATM_DEVICE ""
+#define ATM_PROTOCOL_DEFAULT ATM_AAL5
+typedef int Param_Info;
+typedef int Param_Udata;
+#else
+#define ACE_XTI_ATM_DEVICE ""
+typedef int Param_Info;
+typedef int Param_Udata;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_ATM_Params
+ *
+ * @brief Wrapper class that simplifies the information passed to the ATM
+ * enabled ACE_ATM_Connector class.
+ */
+class ACE_Export ACE_ATM_Params
+{
+public:
+ /**
+ * Initialize the data members. This class combines options from
+ * ACE_SOCK_Connector (@a protocol_family, @a protocol, <type>,
+ * @a protocol_info, <group>, and @a flags) and
+ * ACE_TLI_Connector (<device>, <info>, <rw_flag>, <oflag>, and <udata>)
+ * so that either mechanism can be used transparently for ATM.
+ */
+ ACE_ATM_Params (int rw_flag = 1,
+ const char device[] = ACE_XTI_ATM_DEVICE,
+ Param_Info *info = 0,
+ Param_Udata *udata = 0,
+ int oflag = O_RDWR,
+ int protocol_family = AF_ATM,
+ int protocol = ATM_PROTOCOL_DEFAULT,
+ int type =
+#if defined (ACE_HAS_LINUX_ATM)
+ SOCK_DGRAM,
+#else
+ SOCK_RAW,
+#endif /* ACE_HAS_LINUX_ATM */
+ ACE_Protocol_Info *protocol_info = 0,
+ ACE_SOCK_GROUP g = 0,
+ u_long flags
+ = ACE_FLAG_MULTIPOINT_C_ROOT
+ | ACE_FLAG_MULTIPOINT_D_ROOT, // connector by default
+ int reuse_addr = 0);
+
+ /// Destructor.
+ ~ACE_ATM_Params ();
+
+ /// Get protocol family.
+ int get_protocol_family (void) const;
+
+ /// Set protocol family.
+ void set_protocol_family (int);
+
+ /// Get protocol.
+ int get_protocol (void) const;
+
+ /// Set protocol.
+ void set_protocol (int);
+
+ /// Get type.
+ int get_type (void) const;
+
+ /// Set type.
+ void set_type (int);
+
+ /// Get protocol info.
+ ACE_Protocol_Info *get_protocol_info( void );
+
+ /// Set protocol info.
+ void set_protocol_info( ACE_Protocol_Info *);
+
+ /// Get socket group.
+ ACE_SOCK_GROUP get_sock_group( void );
+
+ /// Set socket group.
+ void set_sock_group( ACE_SOCK_GROUP );
+
+ /// Get socket flags.
+ u_long get_flags( void );
+
+ /// Set socket flags.
+ void set_flags( u_long );
+
+ /// Get reuse_addr flag.
+ int get_reuse_addr (void) const;
+
+ /// Set reuse_addr flag.
+ void set_reuse_addr (int);
+
+ /// Get device.
+ const char* get_device (void) const;
+
+ /// Get info.
+ Param_Info* get_info (void) const;
+
+ /// Set info.
+ void set_info (Param_Info *);
+
+ /// Get r/w flag.
+ int get_rw_flag (void) const;
+
+ /// Set r/w flag.
+ void set_rw_flag (int);
+
+ /// Get user data.
+ Param_Udata* get_user_data (void) const;
+
+ /// Set user data.
+ void set_user_data (Param_Udata*);
+
+ /// Get open flag.
+ int get_oflag (void) const;
+
+ /// Set open flag.
+ void set_oflag (int);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Protocol family for sockets connections.
+ int protocol_family_;
+
+ /// Protocol for sockets connections.
+ int protocol_;
+
+ /// Type for opening sockets.
+ int type_;
+
+ /// Information about the protocol.
+ ACE_Protocol_Info *protocol_info_;
+
+ /// Socket group used (for sockets only).
+ ACE_SOCK_GROUP group_;
+
+ /// Flags for sockets (for sockets only).
+ u_long flags_;
+
+ /// Flag for reusing address for opening sockets.
+ int reuse_addr_;
+
+ /// Device name for XTI/ATM connections.
+ const char *device_;
+
+ /// Info for XTI/ATM connections.
+ Param_Info *info_;
+
+ /// R/W flag for XTI/ATM connections.
+ int rw_flag_;
+
+ /// User data for XTI/ATM connections.
+ Param_Udata *udata_;
+
+ /// Open flag for XTI/ATM connections.
+ int oflag_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/ATM_Params.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_ATM */
+#include /**/ "ace/post.h"
+#endif /* ACE_ATM_PARAMS_H */
diff --git a/ACE/ace/ATM_Params.inl b/ACE/ace/ATM_Params.inl
new file mode 100644
index 00000000000..5d60f6ba920
--- /dev/null
+++ b/ACE/ace/ATM_Params.inl
@@ -0,0 +1,235 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_ATM_Params::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_ATM_Params::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_INLINE
+ACE_ATM_Params::ACE_ATM_Params (int rw_flag,
+ const char device[],
+ Param_Info *info,
+ Param_Udata *udata,
+ int oflag,
+ int protocol_family,
+ int protocol,
+ int type,
+ ACE_Protocol_Info *protocol_info,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr)
+ : protocol_family_(protocol_family),
+ protocol_(protocol),
+ type_(type),
+ protocol_info_(protocol_info),
+ group_(g),
+ flags_(flags),
+ reuse_addr_(reuse_addr),
+ device_(device),
+ info_(info),
+ rw_flag_(rw_flag),
+ udata_(udata),
+ oflag_(oflag)
+{
+ ACE_TRACE ("ACE_ATM_Params::ACE_ATM_Params");
+}
+
+// Default dtor.
+ACE_INLINE
+ACE_ATM_Params::~ACE_ATM_Params (void)
+{
+ ACE_TRACE ("ACE_ATM_Params::~ACE_ATM_Params");
+}
+
+ACE_INLINE
+int
+ACE_ATM_Params::get_protocol_family (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_protocol_family");
+ return protocol_family_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_protocol_family (int family)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_protocol_family");
+ protocol_family_ = family;
+}
+
+ACE_INLINE
+int
+ACE_ATM_Params::get_protocol (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_protocol");
+ return protocol_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_protocol (int protocol)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_protocol");
+ protocol_ = protocol;
+}
+
+ACE_INLINE
+int
+ACE_ATM_Params::get_type (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_type");
+ return type_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_type (int type)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_type");
+ type_ = type;
+}
+
+ACE_INLINE
+ACE_Protocol_Info*
+ACE_ATM_Params::get_protocol_info( void )
+{
+ ACE_TRACE ("ACE_ATM_Params::get_protocol_info");
+ return protocol_info_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_protocol_info( ACE_Protocol_Info *protocol_info )
+{
+ ACE_TRACE ("ACE_ATM_Params::set_protocol_info");
+ protocol_info_ = protocol_info;
+}
+
+ACE_INLINE
+ACE_SOCK_GROUP
+ACE_ATM_Params::get_sock_group( void )
+{
+ ACE_TRACE ("ACE_ATM_Params::get_sock_group");
+ return group_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_sock_group( ACE_SOCK_GROUP g )
+{
+ ACE_TRACE ("ACE_ATM_Params::set_sock_group");
+ group_ = g;
+}
+
+ACE_INLINE
+u_long
+ACE_ATM_Params::get_flags( void )
+{
+ ACE_TRACE ("ACE_ATM_Params::get_flags");
+ return flags_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_flags( u_long flags)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_flags");
+ flags_ = flags;
+}
+
+ACE_INLINE
+int
+ACE_ATM_Params::get_reuse_addr (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_reuse_addr");
+ return reuse_addr_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_reuse_addr (int reuse_addr)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_reuse_addr");
+ reuse_addr_ = reuse_addr;
+}
+
+ACE_INLINE
+const char*
+ACE_ATM_Params::get_device (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_device");
+ return device_;
+}
+
+ACE_INLINE
+Param_Info*
+ACE_ATM_Params::get_info (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_info");
+ return info_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_info (Param_Info* info)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_info");
+ info_ = info;
+}
+
+ACE_INLINE
+int
+ACE_ATM_Params::get_rw_flag (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_rw_flag");
+ return rw_flag_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_rw_flag (int rw_flag)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_rw_flag");
+ rw_flag_ = rw_flag;
+}
+
+ACE_INLINE
+Param_Udata*
+ACE_ATM_Params::get_user_data (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_user_data");
+ return udata_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_user_data (Param_Udata *udata)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_user_data");
+ udata_ = udata;
+}
+
+ACE_INLINE
+int
+ACE_ATM_Params::get_oflag (void) const
+{
+ ACE_TRACE ("ACE_ATM_Params::get_oflag");
+ return oflag_;
+}
+
+ACE_INLINE
+void
+ACE_ATM_Params::set_oflag (int oflag)
+{
+ ACE_TRACE ("ACE_ATM_Params::set_oflag");
+ oflag_ = oflag;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ATM_QoS.cpp b/ACE/ace/ATM_QoS.cpp
new file mode 100644
index 00000000000..6a7e6d4f463
--- /dev/null
+++ b/ACE/ace/ATM_QoS.cpp
@@ -0,0 +1,631 @@
+// $Id$
+
+#include "ace/ATM_QoS.h"
+
+ACE_RCSID(ace, ATM_QoS, "$Id$")
+
+#if defined (ACE_HAS_ATM)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/ATM_QoS.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+#define BHLI_MAGIC "FORE_ATM"
+// This is line rate in cells/s for an OC-3 MM interface.
+const long ACE_ATM_QoS::LINE_RATE = 353207;
+const int ACE_ATM_QoS::OPT_FLAGS_CPID = 0x1;
+const int ACE_ATM_QoS::OPT_FLAGS_PMP = 0x2;
+const int ACE_ATM_QoS::DEFAULT_SELECTOR = 0x99;
+const int ACE_ATM_QoS::DEFAULT_PKT_SIZE = 8192;
+#elif defined (ACE_HAS_LINUX_ATM)
+//pbrandao:for Linux:
+//pbrandao:for now stick with current definitions
+//pbrandao:see if later need to change
+const long ACE_ATM_QoS::LINE_RATE = 353207;
+const int ACE_ATM_QoS::OPT_FLAGS_CPID = 0x1;
+const int ACE_ATM_QoS::OPT_FLAGS_PMP = 0x2;
+const int ACE_ATM_QoS::DEFAULT_SELECTOR = 0x99;
+const int ACE_ATM_QoS::DEFAULT_PKT_SIZE = 8192;
+#else
+const long ACE_ATM_QoS::LINE_RATE = 0L;
+const int ACE_ATM_QoS::OPT_FLAGS_CPID = 0;
+const int ACE_ATM_QoS::OPT_FLAGS_PMP = 0;
+const int ACE_ATM_QoS::DEFAULT_SELECTOR = 0x0;
+const int ACE_ATM_QoS::DEFAULT_PKT_SIZE = 0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+
+ACE_ALLOC_HOOK_DEFINE(ACE_ATM_QoS)
+
+ACE_ATM_QoS::ACE_ATM_QoS (int pktSize)
+{
+ ACE_TRACE ("ACE_ATM_QoS::ACE_ATM_QoS");
+#if defined (ACE_HAS_LINUX_ATM)
+ ACE_OS::memset(&qos_, 0, sizeof(qos_));
+ qos_.aal = ATM_PROTOCOL_DEFAULT;
+ qos_.rxtp.traffic_class = ATM_ANYCLASS;
+ qos_.rxtp.max_sdu = pktSize;
+ qos_.txtp.traffic_class = ATM_ANYCLASS;
+ qos_.txtp.max_sdu = pktSize;
+#else
+ ACE_UNUSED_ARG (pktSize);
+#endif /* ACE_HAS_LINUX_ATM */
+}
+
+ACE_ATM_QoS::ACE_ATM_QoS(int rate,
+ int pktSize)
+{
+ ACE_TRACE( "ACE_ATM_QoS::ACE_ATM_QoS" );
+#if defined (ACE_HAS_FORE_ATM_WS2)
+ AAL_PARAMETERS_IE ie_aalparams;
+ ATM_TRAFFIC_DESCRIPTOR_IE ie_td;
+ ATM_BROADBAND_BEARER_CAPABILITY_IE ie_bbc;
+ ATM_QOS_CLASS_IE ie_qos;
+ Q2931_IE *ie_ptr;
+ int size;
+
+ // Setting up cbr parameters ...
+ ie_aalparams.AALType = AALTYPE_5;
+ ie_aalparams.AALSpecificParameters.AAL5Parameters.ForwardMaxCPCSSDUSize
+ = pktSize; // was 1516;
+ ie_aalparams.AALSpecificParameters.AAL5Parameters.BackwardMaxCPCSSDUSize
+ = pktSize; // was 1516;
+ ie_aalparams.AALSpecificParameters.AAL5Parameters.Mode = AAL5_MODE_MESSAGE;
+ ie_aalparams.AALSpecificParameters.AAL5Parameters.SSCSType = AAL5_SSCS_NULL;
+
+ size = sizeof(Q2931_IE_TYPE) + sizeof(ULONG) + sizeof(AAL_PARAMETERS_IE);
+
+ ie_td.Forward.PeakCellRate_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Forward.PeakCellRate_CLP01 = rate;
+ ie_td.Forward.SustainableCellRate_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Forward.SustainableCellRate_CLP01 = SAP_FIELD_ABSENT;
+ ie_td.Forward.MaxBurstSize_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Forward.MaxBurstSize_CLP01 = SAP_FIELD_ABSENT;
+ ie_td.Forward.Tagging = SAP_FIELD_ABSENT;
+
+ ie_td.Backward.PeakCellRate_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Backward.PeakCellRate_CLP01 = rate;
+ ie_td.Backward.SustainableCellRate_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Backward.SustainableCellRate_CLP01 = SAP_FIELD_ABSENT;
+ ie_td.Backward.MaxBurstSize_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Backward.MaxBurstSize_CLP01 = SAP_FIELD_ABSENT;
+ ie_td.Backward.Tagging = SAP_FIELD_ABSENT;
+
+ ie_td.BestEffort = 0; // Note: this must be set to zero for CBR.
+
+ size += sizeof( Q2931_IE_TYPE )
+ + sizeof( ULONG )
+ + sizeof( ATM_TRAFFIC_DESCRIPTOR_IE );
+
+ ie_bbc.BearerClass = BCOB_X;
+ ie_bbc.TrafficType = TT_CBR;
+ ie_bbc.TimingRequirements = TR_END_TO_END;
+ ie_bbc.ClippingSusceptability = CLIP_NOT;
+ ie_bbc.UserPlaneConnectionConfig = UP_P2P;
+
+ size += sizeof( Q2931_IE_TYPE )
+ + sizeof( ULONG )
+ + sizeof( ATM_BROADBAND_BEARER_CAPABILITY_IE );
+
+ ie_qos.QOSClassForward = QOS_CLASS1;
+ ie_qos.QOSClassBackward = QOS_CLASS1; // This may not be really used
+ // since we do only simplex data xfer.
+
+ size += sizeof(Q2931_IE_TYPE) + sizeof(ULONG) + sizeof(ATM_QOS_CLASS_IE);
+
+ qos_.ProviderSpecific.buf = (char *) ACE_OS::malloc(size);
+ if (qos_.ProviderSpecific.buf == 0) {
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("ACE_ATM_QoS::ACE_ATM_QoS: Unable to allocate %d bytes for qos_.ProviderSpecific.buf\n"),
+ size));
+ return;
+ }
+ qos_.ProviderSpecific.len = size;
+ ACE_OS::memset(qos_.ProviderSpecific.buf, 0, size);
+
+ ie_ptr = (Q2931_IE *) qos_.ProviderSpecific.buf;
+ ie_ptr->IEType = IE_AALParameters;
+ ie_ptr->IELength = sizeof( Q2931_IE_TYPE )
+ + sizeof( ULONG )
+ + sizeof( AAL_PARAMETERS_IE );
+ ACE_OS::memcpy(ie_ptr->IE, &ie_aalparams, sizeof(AAL_PARAMETERS_IE));
+
+ ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
+ ie_ptr->IEType = IE_TrafficDescriptor;
+ ie_ptr->IELength = sizeof( Q2931_IE_TYPE )
+ + sizeof( ULONG )
+ + sizeof( ATM_TRAFFIC_DESCRIPTOR_IE );
+ ACE_OS::memcpy(ie_ptr->IE, &ie_td, sizeof(ATM_TRAFFIC_DESCRIPTOR_IE));
+
+ ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
+ ie_ptr->IEType = IE_BroadbandBearerCapability;
+ ie_ptr->IELength = sizeof( Q2931_IE_TYPE )
+ + sizeof( ULONG )
+ + sizeof( ATM_BROADBAND_BEARER_CAPABILITY_IE );
+ ACE_OS::memcpy(ie_ptr->IE,
+ &ie_bbc,
+ sizeof(ATM_BROADBAND_BEARER_CAPABILITY_IE));
+
+ ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
+ ie_ptr->IEType = IE_QOSClass;
+ ie_ptr->IELength = sizeof( Q2931_IE_TYPE )
+ + sizeof( ULONG )
+ + sizeof( ATM_QOS_CLASS_IE );
+ ACE_OS::memcpy(ie_ptr->IE, &ie_qos, sizeof(ATM_QOS_CLASS_IE));
+
+ // qos_.SendingFlowspec.TokenRate = 0xffffffff;
+ // qos_.SendingFlowspec.TokenBucketSize = 0xffffffff;
+ // qos_.SendingFlowspec.PeakBandwidth = 0xffffffff;
+ // qos_.SendingFlowspec.Latency = 0xffffffff;
+ // qos_.SendingFlowspec.DelayVariation = 0xffffffff;
+ // qos_.SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
+ // This will most probably be ignored by the service provider.
+ // qos_.SendingFlowspec.MaxSduSize = 0xffffffff;
+ // qos_.SendingFlowspec.MinimumPolicedSize = 0xffffffff;
+
+ // qos_.ReceivingFlowspec.TokenRate = 0xffffffff;
+ // qos_.ReceivingFlowspec.TokenBucketSize = 0xffffffff;
+ // qos_.ReceivingFlowspec.PeakBandwidth = 0xffffffff;
+ // qos_.ReceivingFlowspec.Latency = 0xffffffff;
+ // qos_.ReceivingFlowspec.DelayVariation = 0xffffffff;
+ // qos_.ReceivingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
+ // This will most probably be ignored by the service provider.
+ // qos_.ReceivingFlowspec.MaxSduSize = 0xffffffff;
+ // qos_.ReceivingFlowspec.MinimumPolicedSize = 0;
+
+ ACE_Flow_Spec send_fspec( 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ SERVICETYPE_BESTEFFORT,
+ // This will most probably ignored by SP.
+ 0xffffffff,
+ 0xffffffff,
+ 15,
+ ACE_DEFAULT_THREAD_PRIORITY ),
+ recv_fspec( 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ SERVICETYPE_BESTEFFORT,
+ // This will most probably ignored by SP.
+ 0xffffffff,
+ 0,
+ 15,
+ ACE_DEFAULT_THREAD_PRIORITY );
+
+ qos_.sending_flowspec (send_fspec);
+ qos_.receiving_flowspec (recv_fspec);
+#elif defined (ACE_HAS_FORE_ATM_XTI)
+ ACE_UNUSED_ARG (rate);
+ ACE_UNUSED_ARG (pktSize);
+#elif defined (ACE_HAS_LINUX_ATM)
+ ACE_OS::memset(&qos_,
+ 0,
+ sizeof(qos_));
+ qos_.aal = ATM_PROTOCOL_DEFAULT;
+ qos_.rxtp.max_sdu = pktSize;
+
+ if (rate > 0) {
+ qos_.rxtp.pcr = rate;
+ qos_.rxtp.traffic_class = ATM_CBR;
+ qos_.txtp.traffic_class = ATM_CBR;
+ qos_.txtp.pcr = rate;
+ }
+ else {
+ qos_.rxtp.traffic_class = ATM_UBR;
+ qos_.txtp.traffic_class = ATM_UBR;
+ }
+
+ qos_.txtp.max_sdu = pktSize;
+#else
+ ACE_UNUSED_ARG (rate);
+#endif /* ACE_HAS_FORE_ATM_WS2 || ACE_HAS_FORE_ATM_XTI || ACE_HAS_LINUX_ATM */
+}
+
+void
+ACE_ATM_QoS::set_cbr_rate (int rate,
+ int pktSize)
+{
+ ACE_TRACE ("ACE_ATM_QoS::set_cbr_rate");
+#if defined (ACE_HAS_FORE_ATM_WS2)
+ /*
+ AAL_PARAMETERS_IE ie_aalparams;
+ ATM_TRAFFIC_DESCRIPTOR_IE ie_td;
+ ATM_BROADBAND_BEARER_CAPABILITY_IE ie_bbc;
+ ATM_QOS_CLASS_IE ie_qos;
+ Q2931_IE *ie_ptr;
+ int size;
+ */
+
+ ACE_OS::printf( "ATM_QoS(set_cbr_rate): set rate to %d c/s\n", rate );
+
+ // Setting up cbr parameters ...
+ /*
+ FORE has changed this - we no longer specify QoS this way
+ ie_aalparams.AALType = AALTYPE_5;
+ ie_aalparams.AALSpecificParameters.AAL5Parameters.ForwardMaxCPCSSDUSize
+ = pktSize; // was 1516;
+ ie_aalparams.AALSpecificParameters.AAL5Parameters.BackwardMaxCPCSSDUSize
+ = pktSize; // was 1516;
+ ie_aalparams.AALSpecificParameters.AAL5Parameters.Mode = AAL5_MODE_MESSAGE;
+ ie_aalparams.AALSpecificParameters.AAL5Parameters.SSCSType = AAL5_SSCS_NULL;
+
+ size = sizeof(Q2931_IE_TYPE) + sizeof(ULONG) + sizeof(AAL_PARAMETERS_IE);
+
+ ie_td.Forward.PeakCellRate_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Forward.PeakCellRate_CLP01 = rate;
+ ie_td.Forward.SustainableCellRate_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Forward.SustainableCellRate_CLP01 = SAP_FIELD_ABSENT;
+ ie_td.Forward.MaxBurstSize_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Forward.MaxBurstSize_CLP01 = SAP_FIELD_ABSENT;
+ ie_td.Forward.Tagging = SAP_FIELD_ABSENT;
+
+ ie_td.Backward.PeakCellRate_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Backward.PeakCellRate_CLP01 = rate;
+ ie_td.Backward.SustainableCellRate_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Backward.SustainableCellRate_CLP01 = SAP_FIELD_ABSENT;
+ ie_td.Backward.MaxBurstSize_CLP0 = SAP_FIELD_ABSENT;
+ ie_td.Backward.MaxBurstSize_CLP01 = SAP_FIELD_ABSENT;
+ ie_td.Backward.Tagging = SAP_FIELD_ABSENT;
+
+ ie_td.BestEffort = 0; // Note: this must be set to zero for CBR.
+
+ size += sizeof( Q2931_IE_TYPE ) +
+ sizeof( ULONG ) +
+ sizeof( ATM_TRAFFIC_DESCRIPTOR_IE );
+
+ ie_bbc.BearerClass = BCOB_X;
+ ie_bbc.TrafficType = TT_CBR;
+ ie_bbc.TimingRequirements = TR_END_TO_END;
+ ie_bbc.ClippingSusceptability = CLIP_NOT;
+ ie_bbc.UserPlaneConnectionConfig = UP_P2P;
+
+ size += sizeof(Q2931_IE_TYPE) +
+ sizeof(ULONG) +
+ sizeof(ATM_BROADBAND_BEARER_CAPABILITY_IE);
+
+ ie_qos.QOSClassForward = QOS_CLASS1;
+ ie_qos.QOSClassBackward = QOS_CLASS1; // This may not be really used
+ // since we only simplex data xfer.
+
+ size += sizeof(Q2931_IE_TYPE) + sizeof(ULONG) + sizeof(ATM_QOS_CLASS_IE);
+
+ qos_.ProviderSpecific.buf = (char *) ACE_OS::malloc(size);
+ if (qos_.ProviderSpecific.buf == 0) {
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("ACE_ATM_QoS::ACE_ATM_QoS: Unable to allocate %d bytes for qos_.ProviderSpecific.buf\n"),
+ size));
+ return;
+ }
+ qos_.ProviderSpecific.len = size;
+ ACE_OS::memset(qos_.ProviderSpecific.buf, 0, size);
+
+ ie_ptr = (Q2931_IE *) qos_.ProviderSpecific.buf;
+ ie_ptr->IEType = IE_AALParameters;
+ ie_ptr->IELength = sizeof( Q2931_IE_TYPE ) +
+ sizeof( ULONG ) +
+ sizeof( AAL_PARAMETERS_IE );
+ ACE_OS::memcpy(ie_ptr->IE, &ie_aalparams, sizeof(AAL_PARAMETERS_IE));
+
+ ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
+ ie_ptr->IEType = IE_TrafficDescriptor;
+ ie_ptr->IELength = sizeof( Q2931_IE_TYPE ) +
+ sizeof( ULONG ) +
+ sizeof( ATM_TRAFFIC_DESCRIPTOR_IE );
+ ACE_OS::memcpy(ie_ptr->IE, &ie_td, sizeof(ATM_TRAFFIC_DESCRIPTOR_IE));
+
+ ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
+ ie_ptr->IEType = IE_BroadbandBearerCapability;
+ ie_ptr->IELength = sizeof( Q2931_IE_TYPE ) +
+ sizeof( ULONG ) +
+ sizeof( ATM_BROADBAND_BEARER_CAPABILITY_IE );
+ ACE_OS::memcpy( ie_ptr->IE,
+ &ie_bbc,
+ sizeof( ATM_BROADBAND_BEARER_CAPABILITY_IE ));
+
+ ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
+ ie_ptr->IEType = IE_QOSClass;
+ ie_ptr->IELength = sizeof(Q2931_IE_TYPE) + sizeof(ULONG) +
+ sizeof(ATM_QOS_CLASS_IE);
+ ACE_OS::memcpy(ie_ptr->IE, &ie_qos, sizeof(ATM_QOS_CLASS_IE));
+ */
+
+ const int BYTES_PER_ATM_CELL = 53;
+ ACE_OS::memset(&qos_, 0, sizeof(ATM_QoS));
+ // Setting the token rate sets the minimum rate. 3 Mbits/sec seems too high.
+ // Certainly for Vaudeville audio, we only need about 1000 c/s which is
+ // 424000 bits/sec which is 53000 bytes/sec.
+ //qos_.SendingFlowspec.TokenRate = 3*(1024*128); // 3Mbits/sec
+ qos_.SendingFlowspec.TokenRate = 53000; // 1000 cells/sec
+ qos_.SendingFlowspec.TokenBucketSize = 32*1024; // our block size
+ //ourQos.SendingFlowspec.PeakBandwidth = ourQos.SendingFlowspec.TokenRate;
+ qos_.SendingFlowspec.ServiceType = SERVICETYPE_GUARANTEED;
+ // Peak bandwidth is in bytes/sec. The rate is specified in cells/sec so
+ // we need to convert from cells/sec to bytes/sec (i.e., multiply by 53).
+ qos_.SendingFlowspec.PeakBandwidth = rate * BYTES_PER_ATM_CELL;
+ qos_.SendingFlowspec.Latency = -1; // we don't care too much
+ qos_.SendingFlowspec.DelayVariation = -1; // we don't care too much
+ // no provider-specific data allowed on ATM
+ qos_.ProviderSpecific.buf=0;
+ qos_.ProviderSpecific.len=0;
+ // unidirectional P2MP; we don't need to setup the Receiving flowspec
+
+ //qos_.SendingFlowspec.TokenRate = 0xffffffff;
+ //qos_.SendingFlowspec.TokenBucketSize = 0xffffffff;
+ //qos_.SendingFlowspec.PeakBandwidth = 0xffffffff;
+ //qos_.SendingFlowspec.Latency = 0xffffffff;
+ //qos_.SendingFlowspec.DelayVariation = 0xffffffff;
+ //qos_.SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
+ // This will most probably be ignored by the service provider.
+ //qos_.SendingFlowspec.MaxSduSize = 0xffffffff;
+ //qos_.SendingFlowspec.MinimumPolicedSize = 0xffffffff;
+
+ //qos_.ReceivingFlowspec.TokenRate = 0xffffffff;
+ //qos_.ReceivingFlowspec.TokenBucketSize = 0xffffffff;
+ //qos_.ReceivingFlowspec.PeakBandwidth = 0xffffffff;
+ //qos_.ReceivingFlowspec.Latency = 0xffffffff;
+ //qos_.ReceivingFlowspec.DelayVariation = 0xffffffff;
+ //qos_.ReceivingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
+ // This will most probably be ignored by the service provider.
+ //qos_.ReceivingFlowspec.MaxSduSize = 0xffffffff;
+ //qos_.ReceivingFlowspec.MinimumPolicedSize = 0;
+
+ /*
+ ACE_Flow_Spec send_fspec( 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ SERVICETYPE_BESTEFFORT,
+ // This will most probably ignored by SP.
+ 0xffffffff,
+ 0xffffffff,
+ 15,
+ ACE_DEFAULT_THREAD_PRIORITY ),
+ recv_fspec( 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ SERVICETYPE_BESTEFFORT,
+ // This will most probably ignored by SP.
+ 0xffffffff,
+ 0,
+ 15,
+ ACE_DEFAULT_THREAD_PRIORITY );
+
+ qos_.sending_flowspec( send_fspec );
+ qos_.receiving_flowspec( recv_fspec );
+ */
+#elif defined (ACE_HAS_FORE_ATM_XTI)
+ ACE_UNUSED_ARG (rate);
+ ACE_UNUSED_ARG (pktSize);
+#elif defined (ACE_HAS_LINUX_ATM)
+ ACE_UNUSED_ARG (pktSize);
+
+ qos_.rxtp.traffic_class = ATM_CBR;
+ qos_.rxtp.pcr = rate;
+ qos_.txtp.traffic_class = ATM_CBR;
+ qos_.txtp.pcr = rate;
+#else
+ ACE_UNUSED_ARG (rate);
+#endif /* ACE_HAS_FORE_ATM_WS2 || ACE_HAS_FORE_ATM_XTI || ACE_HAS_LINUX_ATM */
+}
+
+void
+ACE_ATM_QoS::set_rate (ACE_HANDLE fd,
+ int rate,
+ int flags)
+{
+ ACE_TRACE ("ACE_ATM_QoS::set_rate");
+#if defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
+ set_cbr_rate( rate );
+
+ ACE_UNUSED_ARG( fd );
+ ACE_UNUSED_ARG( flags );
+#elif defined (ACE_HAS_FORE_ATM_XTI)
+ long optlen = 0;
+ qos_.buf = construct_options(fd,
+ rate,
+ flags,
+ &optlen);
+ qos_.len = optlen;
+#else
+ ACE_UNUSED_ARG (rate);
+#endif /* ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM || ACE_HAS_FORE_ATM_XTI */
+}
+
+char*
+ACE_ATM_QoS::construct_options (ACE_HANDLE fd,
+ int rate,
+ int flags,
+ long *len)
+{
+#if defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
+ ACE_UNUSED_ARG (fd);
+ ACE_UNUSED_ARG (rate);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (len);
+ return (0);
+#elif defined (ACE_HAS_FORE_ATM_XTI)
+ struct t_opthdr *popt;
+ char *buf;
+ int qos_cells;
+ struct t_info info;
+
+ if (ACE_OS::t_getinfo (fd, &info) == -1)
+ {
+ ACE_OS::t_error ("t_getinfo");
+ return 0;
+ }
+
+ buf = (char *) ACE_OS::malloc (info.options);
+
+ if (buf == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Unable to allocate %d bytes for options\n"),
+ info.options),
+ 0);
+
+ popt = (struct t_opthdr *) buf;
+
+ if (flags & OPT_FLAGS_CPID)
+ {
+ // This constructs the T_ATM_ORIG_ADDR option, which is used to
+ // signal the UNI 3.1 Calling Party ID Information Element.
+ t_atm_addr *source_addr;
+
+ popt->len = sizeof (struct t_opthdr) + sizeof (t_atm_addr);
+ popt->level = T_ATM_SIGNALING;
+ popt->name = T_ATM_ORIG_ADDR;
+ popt->status = 0;
+
+ source_addr =
+ (t_atm_addr *)((char *) popt + sizeof (struct t_opthdr));
+
+ source_addr->address_format = T_ATM_ENDSYS_ADDR;
+ source_addr->address_length = ATMNSAP_ADDR_LEN;
+
+ ATMSAPAddress local_addr;
+ struct t_bind boundaddr;
+
+ boundaddr.addr.maxlen = sizeof(local_addr);
+ boundaddr.addr.buf = (char *) &local_addr;
+
+ //if (ACE_OS::t_getprotaddr(fd, &boundaddr, 0) < 0) {
+ if (ACE_OS::t_getname(fd,
+ &boundaddr.addr,
+ LOCALNAME) < 0)
+ {
+ ACE_OS::t_error("t_getname (local_address)");
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Can't get local address!\n")));
+ ACE_OS::free (buf);
+ return 0;
+ }
+
+ ACE_OS::memcpy(source_addr->address,
+ local_addr.sap.t_atm_sap_addr.address,
+ ATMNSAP_ADDR_LEN);
+
+ popt = T_OPT_NEXTHDR (buf, info.options , popt);
+ }
+
+ // This constructs all options necessary (bearer cap., QoS, and
+ // Traffic Descriptor) to signal for a CBR connection with the
+ // specified QoS in kbit/sec., and/or specify a PMP connection.
+
+ // For FORE 200e cards, the adapter shapes traffic to CBR with rate
+ // equal to PCR CLP=0+1 (traffic.forward.PCR_all_traffic)
+
+ qos_cells = (rate * 1000) / (48*8);
+
+ if ((qos_cells > 0 && qos_cells < LINE_RATE)
+ || (ACE_BIT_ENABLED (flags, OPT_FLAGS_PMP)))
+ {
+ struct t_atm_bearer *bearer;
+ struct t_atm_traffic *traffic;
+
+ // T_ATM_BEARER_CAP: Broadband bearer capability
+ popt->len = sizeof (struct t_opthdr) + sizeof (struct t_atm_bearer);
+ popt->level = T_ATM_SIGNALING;
+ popt->name = T_ATM_BEARER_CAP;
+ popt->status = 0;
+
+ bearer = (struct t_atm_bearer *)((char *) popt +
+ sizeof (struct t_opthdr));
+ bearer->bearer_class = T_ATM_CLASS_X;
+
+ if (qos_cells)
+ {
+ bearer->traffic_type = T_ATM_CBR;
+ bearer->timing_requirements = T_ATM_END_TO_END;
+ }
+ else
+ {
+ bearer->traffic_type = 0; // UBR
+ bearer->timing_requirements = 0;
+ }
+ bearer->clipping_susceptibility = T_ATM_NULL;
+
+ if (ACE_BIT_ENABLED (flags, OPT_FLAGS_PMP))
+ bearer->connection_configuration = T_ATM_1_TO_MANY;
+ else
+ bearer->connection_configuration = T_ATM_1_TO_1;
+
+ popt = T_OPT_NEXTHDR (buf, info.options, popt);
+
+ // T_ATM_TRAFFIC: traffic descriptor
+ popt->len = sizeof (struct t_opthdr) + sizeof (struct t_atm_traffic);
+ popt->level = T_ATM_SIGNALING;
+ popt->name = T_ATM_TRAFFIC;
+ popt->status = 0;
+
+ traffic = (struct t_atm_traffic *)((char *) popt +
+ sizeof (struct t_opthdr));
+
+ traffic->forward.PCR_high_priority = T_ATM_ABSENT;
+ traffic->forward.PCR_all_traffic = qos_cells ? qos_cells : LINE_RATE;
+ traffic->forward.SCR_high_priority = T_ATM_ABSENT;
+ traffic->forward.SCR_all_traffic = T_ATM_ABSENT;
+ traffic->forward.MBS_high_priority = T_ATM_ABSENT;
+ traffic->forward.MBS_all_traffic = T_ATM_ABSENT;
+ traffic->forward.tagging = T_NO;
+
+ traffic->backward.PCR_high_priority = T_ATM_ABSENT;
+ traffic->backward.PCR_all_traffic =
+ (ACE_BIT_ENABLED (flags, OPT_FLAGS_PMP))
+ ? 0 : qos_cells ? qos_cells : LINE_RATE;
+ traffic->backward.SCR_high_priority = T_ATM_ABSENT;
+ traffic->backward.SCR_all_traffic = T_ATM_ABSENT;
+ traffic->backward.MBS_high_priority = T_ATM_ABSENT;
+ traffic->backward.MBS_all_traffic = T_ATM_ABSENT;
+ traffic->backward.tagging = T_NO;
+
+ traffic->best_effort = qos_cells ? T_NO : T_YES;
+
+ popt = T_OPT_NEXTHDR (buf,
+ info.options,
+ popt);
+ }
+
+ if (qos_cells > 0 && qos_cells < LINE_RATE)
+ {
+ struct t_atm_qos *qos;
+
+ // T_ATM_QOS: Quality of Service
+ popt->len = sizeof (struct t_opthdr) + sizeof (struct t_atm_qos);
+ popt->level = T_ATM_SIGNALING;
+ popt->name = T_ATM_QOS;
+ popt->status = 0;
+
+ qos = (struct t_atm_qos *)((char *) popt + sizeof (struct t_opthdr));
+ qos->coding_standard = T_ATM_ITU_CODING;
+ qos->forward.qos_class = T_ATM_QOS_CLASS_1;
+ qos->backward.qos_class = T_ATM_QOS_CLASS_1;
+
+ popt = T_OPT_NEXTHDR (buf, info.options, popt);
+ }
+
+ // Return actual size of options and option buffer to user.
+ *len = (char *) popt - buf;
+
+ return buf;
+#else
+ ACE_UNUSED_ARG (fd);
+ ACE_UNUSED_ARG (rate);
+ ACE_UNUSED_ARG (flag);
+ ACE_UNUSED_ARG (len);
+ return (0);
+#endif /* ACE_HAS_FORE_ATM_WS2 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_ATM */
+
diff --git a/ACE/ace/ATM_QoS.h b/ACE/ace/ATM_QoS.h
new file mode 100644
index 00000000000..f548da3033d
--- /dev/null
+++ b/ACE/ace/ATM_QoS.h
@@ -0,0 +1,115 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file ATM_QoS.h
+ *
+ * $Id$
+ *
+ * @author Joe Hoffert
+ */
+//==========================================================================
+
+
+#ifndef ACE_ATM_QoS_H
+#define ACE_ATM_QoS_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_HAS_ATM)
+
+#if defined (ACE_HAS_FORE_ATM_WS2)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+// just map to WS2 GQOS struct
+typedef ACE_QoS ATM_QoS;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#elif defined (ACE_HAS_FORE_ATM_XTI)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef struct netbuf ATM_QoS;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#elif defined (ACE_HAS_LINUX_ATM)
+#include /**/ "atm.h"
+#include "ace/ATM_Params.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef struct atm_qos ATM_QoS;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#else
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef int ATM_QoS;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_HAS_FORE_ATM_WS2 || ACE_HAS_FORE_ATM_XTI || ACE_HAS_LINUX_ATM */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_ATM_QoS
+ *
+ * @brief Define the QoS parameters for ATM
+ *
+ * This class wraps up QoS parameters for both ATM/XTI and
+ * ATM/WinSock2 to make the mechanism for the ATM protocol
+ * transparent.
+ */
+class ACE_Export ACE_ATM_QoS
+{
+public:
+ // Constants used for ATM options
+ static const long LINE_RATE;
+ static const int OPT_FLAGS_CPID;
+ static const int OPT_FLAGS_PMP;
+ static const int DEFAULT_SELECTOR;
+ static const int DEFAULT_PKT_SIZE;
+
+ // = Initializattion and termination methods.
+ /// Default constructor.
+ ACE_ATM_QoS(int = DEFAULT_PKT_SIZE);
+
+ /// Constructor with a CBR rate.
+ ACE_ATM_QoS(int,
+ int = DEFAULT_PKT_SIZE);
+
+ ~ACE_ATM_QoS ();
+
+ /// Set the rate.
+ void set_rate (ACE_HANDLE,
+ int,
+ int);
+
+ /// Set CBR rate in cells per second.
+ void set_cbr_rate (int,
+ int = DEFAULT_PKT_SIZE);
+
+ /// Get ATM_QoS struct.
+ ATM_QoS get_qos (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Construct QoS options.
+ char* construct_options(ACE_HANDLE,
+ int,
+ int,
+ long*);
+
+private:
+ ATM_QoS qos_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/ATM_QoS.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_ATM */
+#include /**/ "ace/post.h"
+#endif /* ACE_ATM_QoS_H */
diff --git a/ACE/ace/ATM_QoS.inl b/ACE/ace/ATM_QoS.inl
new file mode 100644
index 00000000000..283baa3f560
--- /dev/null
+++ b/ACE/ace/ATM_QoS.inl
@@ -0,0 +1,29 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_ATM_QoS::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_ATM_QoS::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_INLINE
+ACE_ATM_QoS::~ACE_ATM_QoS ()
+{
+ ACE_TRACE ("ACE_ATM_QoS::~ACE_ATM_QoS");
+}
+
+ACE_INLINE
+ATM_QoS
+ACE_ATM_QoS::get_qos (void)
+{
+ ACE_TRACE ("ACE_ATM_QoS::get_qos");
+ return qos_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ATM_Stream.cpp b/ACE/ace/ATM_Stream.cpp
new file mode 100644
index 00000000000..21035b97f52
--- /dev/null
+++ b/ACE/ace/ATM_Stream.cpp
@@ -0,0 +1,290 @@
+// $Id$
+
+#include "ace/ATM_Stream.h"
+
+ACE_RCSID (ace, ATM_Stream, "$Id$")
+
+#if defined (ACE_HAS_ATM)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/ATM_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_ATM_Stream)
+
+char*
+ACE_ATM_Stream::get_peer_name (void) const
+{
+ ACE_TRACE ("ACE_ATM_Stream::get_peer_name");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ // // Use t_getprotaddr for XTI/ATM
+ // struct t_bind *localaddr
+ // = (struct t_bind *) ACE_OS::t_alloc (get_handle (),
+ // T_BIND,
+ // T_ADDR);
+ // struct t_bind *peeraddr
+ // = (struct t_bind *) ACE_OS::t_alloc (get_handle (),
+ // T_BIND,
+ // T_ADDR);
+ // ::t_getprotaddr (get_handle (),
+ // localaddr,
+ // peeraddr);
+
+ // char* connected_name = (char*) ACE_OS::malloc (peeraddr->addr.len + 1);
+ // ACE_OS::strcpy (connected_name,
+ // peeraddr->addr.buf);
+ // ACE_OS::t_free ((char *) localaddr,
+ // T_BIND);
+ // ACE_OS::t_free ((char *) peeraddr,
+ // T_BIND);
+ // return (connected_name);
+
+#error "This doesn't seem to work. May need to jimmy-rig something with the"
+#error "/etc/xti_hosts file - Ugh!"
+
+ ACE_ATM_Addr sa;
+ struct netbuf name;
+ name.maxlen = sa.get_size ();
+ name.buf = (char *) sa.get_addr ();
+ ACE_OS::t_getname (this->get_handle (), &name, REMOTENAME);
+ // ACE_OS::ioctl (this->get_handle (),
+ // TI_GETPEERNAME,
+ // &name);
+ return (name.buf);
+
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ // Use getpeername for WinSock2.
+ struct sockaddr_atm name;
+ ACE_OS::memset (&name, 0, sizeof (name));
+ int nameSize = sizeof (name);
+
+ if (ACE_OS::getpeername (this->get_handle (),
+ (struct sockaddr *) &name,
+ &nameSize) != 0) {
+ return 0;
+ }
+
+ char buffer[256];
+ for (unsigned int index = 0; index < ATM_ADDR_SIZE - 1; index++) {
+ buffer[ index * 3 ] = '\0';
+ ACE_OS::sprintf (buffer, "%s%02x.", buffer, name.satm_number.Addr[ index ]);
+ }
+ buffer[ (ATM_ADDR_SIZE - 1) * 3 ] = '\0';
+ ACE_OS::sprintf (buffer, "%s%02x.", buffer, 0);
+ buffer[ ATM_ADDR_SIZE * 3 - 1 ] = '\0';
+ for (index = 0; index < ACE_OS::strlen (buffer); ++index)
+ buffer[index] = ACE_OS::ace_tolower (buffer[index]);
+
+ ifstream atm_hosts ("C:/WINNT/atmhosts");
+ assert (atm_hosts.is_open ());
+
+ // Find the host address in the ATM hosts file and return the
+ // host name
+ char line[256];
+ char *host_ptr, *host_name = 0;
+ ACE_NEW_RETURN (host_name, char[256], 0);
+ while (!atm_hosts.eof ()) {
+ atm_hosts.getline (line, 256);
+ // Convert the line to lower case to ease comparison
+ for (index = 0; index < ACE_OS::strlen (line); ++index)
+ line[index] = ACE_OS::ace_tolower (line[index]);
+ if (ACE_OS::strstr (line, buffer) != 0)
+ {
+ char *strtok_p;
+ // Grab the second token which is the host name
+ ACE_OS::strtok_r (line, " \t", &strtok_p);
+ host_ptr = ACE_OS::strtok (0, " \t", &strtok_p);
+ ACE_OS::strcpy (host_name, host_ptr);
+ break;
+ }
+ }
+
+ return host_name;
+#elif defined (ACE_HAS_LINUX_ATM)
+ ATM_Addr name;
+ int nameSize = sizeof (name.sockaddratmsvc);
+
+ if (ACE_OS::getpeername (this->get_handle (),
+ (struct sockaddr *) & (name.sockaddratmsvc),
+ &nameSize) < 0) {
+ ACE_OS::perror ("ACE_ATM_Stream (get_peer_name) : ");
+ return 0;
+ }
+
+ static ACE_TCHAR buffer[MAX_ATM_ADDR_LEN + 1];
+ int total_len;
+ if ((total_len = atm2text (buffer,sizeof buffer,
+ (struct sockaddr *) & (name.sockaddratmsvc),
+ A2T_PRETTY|A2T_NAME)) < 0) {
+ ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("ACE_ATM_Stream (get_peer_name) :%d"),errno));
+ return 0;
+ }
+
+ return (char*) buffer;
+#else
+ return 0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+}
+
+ACE_HANDLE
+ACE_ATM_Stream::get_handle (void) const
+{
+ ACE_TRACE ("ACE_ATM_Stream::get_handle");
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
+ return stream_.get_handle ();
+#else
+ return 0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+}
+
+int
+ACE_ATM_Stream::get_vpi_vci (ACE_UINT16 &vpi,
+ ACE_UINT16 &vci) const
+{
+ ACE_TRACE ("ACE_ATM_Stream::get_vpi_vci");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ struct t_atm_conn_prop conn_prop;
+ char* connect_opts = (char *) &conn_prop;
+ int opt_size = sizeof (t_atm_conn_prop);
+ struct t_info info;
+ struct t_optmgmt opt_req, opt_ret;
+
+ if (ACE_OS::t_getinfo (stream_.get_handle (),
+ &info) < 0)
+ {
+ ACE_OS::t_error ("t_getinfo");
+ return -1;
+ }
+
+ char *buf_req = (char *) ACE_OS::malloc (info.options);
+ if (buf_req == 0)
+ {
+ ACE_OS::fprintf (stderr,
+ "Unable to allocate %ld bytes for options\n",
+ info.options);
+ return -1;
+ }
+
+ char *buf_ret = (char *) ACE_OS::malloc (info.options);
+ if (buf_ret == 0)
+ {
+ ACE_OS::fprintf (stderr,
+ "Unable to allocate %ld bytes for options\n",
+ info.options);
+ return -1;
+ }
+
+ ACE_OS::memset (&opt_req, 0, sizeof (opt_req));
+ ACE_OS::memset (&opt_ret, 0, sizeof (opt_ret));
+
+ struct t_opthdr *popt = (struct t_opthdr *) buf_req;
+ struct t_opthdr *popt_ret = (struct t_opthdr *) buf_ret;
+
+ popt->len= sizeof (struct t_opthdr) + opt_size;
+
+ // We are only concerned with SVCs so no other check or values are needed
+ // here.
+ popt->level = T_ATM_SIGNALING;
+ popt->name = T_ATM_CONN_PROP;
+ popt->status = 0;
+
+ opt_req.opt.len = popt->len;
+ opt_req.opt.buf = (char *) popt;
+ opt_req.flags = T_CURRENT;
+
+ popt = T_OPT_NEXTHDR (buf_req,
+ info.options,
+ popt);
+ opt_ret.opt.maxlen = info.options;
+ opt_ret.opt.buf = (char *) popt_ret;
+
+ if (ACE_OS::t_optmgmt (stream_.get_handle (),
+ &opt_req,
+ &opt_ret) < 0) {
+ ACE_OS::t_error ("t_optmgmt");
+ return -1;
+ }
+
+ ACE_OS::memcpy (connect_opts,
+ (char *) popt_ret + sizeof (struct t_opthdr),
+ opt_size);
+
+ ACE_OS::free (buf_ret);
+ ACE_OS::free (buf_req);
+
+ vpi = conn_prop.vpi;
+ vci = conn_prop.vci;
+ return (0);
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ ATM_CONNECTION_ID connID;
+ DWORD bytes = 0;
+
+ if (::WSAIoctl ((int) this -> get_handle (),
+ SIO_GET_ATM_CONNECTION_ID,
+ 0,
+ 0,
+ (LPVOID) &connID,
+ sizeof (ATM_CONNECTION_ID),
+ &bytes,
+ 0,
+ 0)
+ == SOCKET_ERROR) {
+ ACE_OS::printf ("Error: WSAIoctl %d\n", WSAGetLastError ());
+ }
+
+ vpi = (ACE_UINT16) connID.VPI;
+ vci = (ACE_UINT16) connID.VCI;
+
+ return 0;
+#elif defined (ACE_HAS_LINUX_ATM)
+#if defined (SO_ATMPVC) /* atm version>=0.62 */
+ struct sockaddr_atmpvc mypvcaddr;
+ int addrpvclen = sizeof (mypvcaddr);
+ if (ACE_OS::getsockopt (stream_.get_handle (),
+ SOL_ATM,
+ SO_ATMPVC,
+ reinterpret_cast<char*> (&mypvcaddr),
+ &addrpvclen) < 0) {
+ ACE_DEBUG (LM_DEBUG,
+ ACE_TEXT ("ACE_ATM_Stream::get_vpi_vci: getsockopt %d\n"),
+ errno);
+ return -1;
+ }
+ vpi = (ACE_UINT16) mypvcaddr.sap_addr.vpi;
+ vci = (ACE_UINT16) mypvcaddr.sap_addr.vci;
+
+ return 0;
+#elif defined (SO_VCID) /* patch for atm version 0.59 */
+ struct atm_vcid mypvcid;
+ int pvcidlen = sizeof (mypvcid);
+ if (ACE_OS::getsockopt (stream_.get_handle (),
+ SOL_ATM,SO_VCID,
+ reinterpret_cast<char*> (&mypvcid),
+ &pvcidlen) < 0) {
+ ACE_DEBUG (LM_DEBUG,
+ ACE_TEXT ("ACE_ATM_Stream::get_vpi_vci: getsockopt %d\n"),
+ errno);
+ return -1;
+ }
+ vpi = (ACE_UINT16) mypvcid.vpi;
+ vci = (ACE_UINT16) mypvcid.vci;
+
+ return 0;
+#else
+ ACE_DEBUG (LM_DEBUG,
+ ACE_TEXT ("ACE_ATM_Stream::get_vpi_vci: Not implemented in this ATM version. Update to >= 0.62\n Or patch 0.59"));
+ ACE_UNUSED_ARG (vci);
+ ACE_UNUSED_ARG (vpi);
+
+ return (-1);
+#endif /* SO_ATMPVC || SO_VCID */
+#else
+ return (-1);
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_ATM */
diff --git a/ACE/ace/ATM_Stream.h b/ACE/ace/ATM_Stream.h
new file mode 100644
index 00000000000..fde1294e1e3
--- /dev/null
+++ b/ACE/ace/ATM_Stream.h
@@ -0,0 +1,107 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file ATM_Stream.h
+ *
+ * $Id$
+ *
+ * @author Joe Hoffert
+ */
+//=============================================================================
+
+
+#ifndef ACE_ATM_STREAM_H
+#define ACE_ATM_STREAM_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_HAS_ATM)
+
+#include "ace/ATM_Addr.h"
+#include "ace/ATM_Params.h"
+
+#if defined (ACE_WIN32)
+#include "ace/SOCK_Stream.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef ACE_SOCK_Stream ATM_Stream;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#else
+#include "ace/TLI_Stream.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef ACE_TLI_Stream ATM_Stream;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_ATM_Stream
+ *
+ * @brief Defines the member functions for ACE_ATM_Stream abstraction.
+ */
+class ACE_Export ACE_ATM_Stream
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_ATM_Stream (void);
+
+ // = ATM-specific open and shutdown operations.
+ /// open the stream.
+ int open (ACE_ATM_Params params = ACE_ATM_Params());
+
+ /// Close down and release resources.
+ int close (void);
+
+ /// Get the underlying handle.
+ ACE_HANDLE get_handle (void) const;
+
+ /// Get the underlying stream.
+ ATM_Stream& get_stream (void);
+
+ /// Get the name of the connected host.
+ char* get_peer_name (void) const;
+
+ /// Get the VPI and VCI of the stream.
+ int get_vpi_vci (ACE_UINT16 &vpi,
+ ACE_UINT16 &vci) const;
+
+ /// Recv an n byte buffer from the connected transport mechanism.
+ ssize_t recv (void *buf,
+ size_t n,
+ int *flags = 0) const;
+
+ /// Send exactly n bytes to the connected transport mechanism.
+ ssize_t send_n (const void *buf,
+ size_t n,
+ int flags) const;
+
+ // = Meta-type info
+ typedef ACE_ATM_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Typedef'd to the appropriate stream mechanism above.
+ ATM_Stream stream_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/ATM_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_ATM */
+#include /**/ "ace/post.h"
+#endif /* ACE_ATM_STREAM_H */
diff --git a/ACE/ace/ATM_Stream.inl b/ACE/ace/ATM_Stream.inl
new file mode 100644
index 00000000000..b796af474e7
--- /dev/null
+++ b/ACE/ace/ATM_Stream.inl
@@ -0,0 +1,133 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_ATM_Stream::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_ATM_Stream::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_INLINE
+ACE_ATM_Stream::ACE_ATM_Stream (void)
+{
+ ACE_TRACE ("ACE_ATM_Stream::ACE_ATM_Stream");
+}
+
+ACE_INLINE
+int
+ACE_ATM_Stream::open (ACE_ATM_Params params)
+{
+ ACE_TRACE ("ACE_ATM_Stream::open");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ ACE_HANDLE handle = stream_.open (params.get_device(),
+ params.get_oflag(),
+ params.get_info());
+ return (handle == ACE_INVALID_HANDLE ? -1 : 0);
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ params.set_flags( ACE_FLAG_MULTIPOINT_C_ROOT | ACE_FLAG_MULTIPOINT_D_ROOT );
+
+ int retval = stream_.open (params.get_type(),
+ params.get_protocol_family(),
+ params.get_protocol(),
+ params.get_protocol_info(),
+ params.get_sock_group(),
+ params.get_flags(),
+ params.get_reuse_addr());
+ if (retval == -1)
+ return -1;
+
+ struct sockaddr_atm sock_addr;
+
+ ACE_OS::memset(&sock_addr, 0, sizeof(struct sockaddr_atm));
+ sock_addr.satm_family = AF_ATM;
+ sock_addr.satm_number.AddressType=ADDR_ANY;
+ sock_addr.satm_number.NumofDigits = ATM_ADDR_SIZE;
+ sock_addr.satm_blli.Layer2Protocol = SAP_FIELD_ABSENT;
+ sock_addr.satm_blli.Layer3Protocol = SAP_FIELD_ABSENT;
+ sock_addr.satm_bhli.HighLayerInfoType = SAP_FIELD_ABSENT;
+ if (ACE_OS::bind(get_handle(),
+ (struct sockaddr FAR *)&sock_addr,
+ sizeof(struct sockaddr_atm)) < 0)
+ {
+ ACE_OS::printf("Error binding local address: %d",WSAGetLastError());
+ return -1;
+ }
+
+ return 0;
+#else
+ ACE_UNUSED_ARG(params);
+ return 0;
+#endif /* ACE_HAS_FORE_ATM_XTI */
+}
+
+ACE_INLINE
+int
+ACE_ATM_Stream::close (void)
+{
+ ACE_TRACE ("ACE_ATM_Stream::close");
+#if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
+ return stream_.close ();
+#else
+ return 0;
+#endif /* ACE_HAS_FORE_ATM_XTI || ACE_HAS_FORE_ATM_WS2 */
+}
+
+ACE_INLINE
+ATM_Stream&
+ACE_ATM_Stream::get_stream (void)
+{
+ ACE_TRACE ("ACE_ATM_Stream::get_stream");
+ return stream_;
+}
+
+ACE_INLINE
+ssize_t
+ACE_ATM_Stream::recv (void *buf,
+ size_t n,
+ int *flags) const
+{
+ ACE_TRACE ("ACE_ATM_Stream::recv");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ return stream_.recv (buf,
+ n,
+ flags);
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ return stream_.recv (buf,
+ n);
+#else
+ ACE_UNUSED_ARG(buf);
+ ACE_UNUSED_ARG(n);
+ ACE_UNUSED_ARG(flags);
+ return (0);
+#endif /* ACE_HAS_FORE_ATM_XTI */
+}
+
+ACE_INLINE
+ssize_t
+ACE_ATM_Stream::send_n (const void *buf,
+ size_t n,
+ int flags) const
+{
+ ACE_TRACE ("ACE_ATM_Stream::send_n");
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ return stream_.send_n (buf,
+ n,
+ flags);
+#elif defined (ACE_HAS_FORE_ATM_WS2)
+ return stream_.send_n (buf,
+ n,
+ flags);
+#else
+ ACE_UNUSED_ARG(buf);
+ ACE_UNUSED_ARG(n);
+ ACE_UNUSED_ARG(flags);
+ return (0);
+#endif /* ACE_HAS_FORE_ATM_XTI */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Acceptor.cpp b/ACE/ace/Acceptor.cpp
new file mode 100644
index 00000000000..2dd5b52d926
--- /dev/null
+++ b/ACE/ace/Acceptor.cpp
@@ -0,0 +1,1226 @@
+#ifndef ACE_ACCEPTOR_CPP
+#define ACE_ACCEPTOR_CPP
+
+#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/Svc_Handler.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_select.h"
+
+ACE_RCSID (ace,
+ Acceptor,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ 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));
+#endif /* ACE_HAS_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 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!
+ (void) this->peer_acceptor_.enable (ACE_NONBLOCK);
+
+ int const result = reactor->register_handler (this,
+ ACE_Event_Handler::ACCEPT_MASK);
+ if (result != -1)
+ this->reactor (reactor);
+ else
+ this->peer_acceptor_.close ();
+
+ 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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%s\t %s %s"),
+ ACE_TEXT ("ACE_Acceptor"),
+ addr_str,
+ ACE_TEXT ("# acceptor factory\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return static_cast<int> (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_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.
+ 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)
+ {
+ // Ensure that errno is preserved in case the svc_handler
+ // close() method resets it
+ ACE_Errno_Guard error(errno);
+
+ // 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;
+# if defined (ACE_WIN32)
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles
+ int select_width = 0;
+# else
+ int select_width = int (listener) + 1;
+# endif /* ACE_WIN32 */
+
+ // 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 ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("make_svc_handler")));
+ return 0;
+ }
+ // Accept connection into the Svc_Handler.
+ else if (this->accept_svc_handler (svc_handler) == -1)
+ {
+ // Note that <accept_svc_handler> closes the <svc_handler>
+ // on failure.
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%p\n"),
+ ACE_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)
+ {
+ // Note that <activate_svc_handler> closes the <svc_handler>
+ // on failure.
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%p\n"),
+ ACE_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 (select_width,
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("delete_creation_strategy_ = %d"), delete_creation_strategy_));
+ this->accept_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_accept_strategy_ = %d"), delete_accept_strategy_));
+ this->concurrency_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_concurrency_strategy_ = %d"), delete_concurrency_strategy_));
+ this->scheduling_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_scheduling_strategy_ = %d"), delete_scheduling_strategy_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nservice_name_ = %s"),
+ this->service_name_ == 0 ? ACE_TEXT ("<unknown>") : this->service_name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nservice_description_ = %s"),
+ this->service_description_ == 0 ? ACE_TEXT ("<unknown>") : this->service_description_));
+ this->service_addr_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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,
+ int /* flags unused */,
+ int use_select,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");
+ return this->open
+ (local_addr, reactor, 0, 0, 0, 0, 0, 0, use_select, reuse_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,
+ int reuse_addr)
+{
+ 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_ = true;
+ }
+ 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_ = true;
+ }
+ this->accept_strategy_ = acc_s;
+
+ if (this->accept_strategy_->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!
+ 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_ = true;
+ }
+ 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_ = true;
+ }
+ 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,
+ int reuse_addr)
+ : creation_strategy_ (0),
+ delete_creation_strategy_ (false),
+ accept_strategy_ (0),
+ delete_accept_strategy_ (false),
+ concurrency_strategy_ (0),
+ delete_concurrency_strategy_ (false),
+ scheduling_strategy_ (0),
+ delete_scheduling_strategy_ (false),
+ service_name_ (0),
+ service_description_ (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;
+ this->reuse_addr_ = reuse_addr;
+}
+
+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,
+ int reuse_addr)
+ : creation_strategy_ (0),
+ delete_creation_strategy_ (false),
+ accept_strategy_ (0),
+ delete_accept_strategy_ (false),
+ concurrency_strategy_ (0),
+ delete_concurrency_strategy_ (false),
+ scheduling_strategy_ (0),
+ delete_scheduling_strategy_ (false),
+ service_name_ (0),
+ service_description_ (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,
+ reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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_ = false;
+ this->creation_strategy_ = 0;
+
+ if (this->delete_accept_strategy_)
+ delete this->accept_strategy_;
+ this->delete_accept_strategy_ = false;
+ this->accept_strategy_ = 0;
+
+ if (this->delete_concurrency_strategy_)
+ delete this->concurrency_strategy_;
+ this->delete_concurrency_strategy_ = false;
+ this->concurrency_strategy_ = 0;
+
+ if (this->delete_scheduling_strategy_)
+ delete this->scheduling_strategy_;
+ this->delete_scheduling_strategy_ = false;
+ 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::instance()->end_reactor_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_TEXT ("%s\t %s #%s\n"),
+ this->service_name_ == 0
+ ? ACE_TEXT ("<unknown>")
+ : this->service_name_,
+ service_addr_str,
+ this->service_description_ == 0
+ ? ACE_TEXT ("<unknown>")
+ : this->service_description_);
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return static_cast<int> (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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("\nsvc_handler_ = %x"), this->svc_handler_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nrestart_ = %d"), this->restart_));
+ this->peer_acceptor_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_concurrency_strategy_ = %d"),
+ delete_concurrency_strategy_));
+ this->concurrency_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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_ = true;
+ }
+ 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_ (false)
+{
+ 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_ (false)
+{
+ 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_TEXT ("%p\n"),
+ ACE_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_ = false;
+ 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_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_TEXT ("%s\t %s %s"),
+ ACE_TEXT ("ACE_Oneshot_Acceptor"),
+ addr_str,
+ ACE_TEXT ("#oneshot acceptor factory\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return static_cast<int> (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_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_ACCEPTOR_CPP */
diff --git a/ACE/ace/Acceptor.h b/ACE/ace/Acceptor.h
new file mode 100644
index 00000000000..741dca098e1
--- /dev/null
+++ b/ACE/ace/Acceptor.h
@@ -0,0 +1,684 @@
+// -*- 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_Object.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Strategies_T.h"
+#include "ace/Synch_Options.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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:
+
+ // Useful STL-style traits.
+ typedef ACE_PEER_ACCEPTOR_ADDR addr_type;
+ typedef ACE_PEER_ACCEPTOR acceptor_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+
+ /// "Do-nothing" constructor.
+ ACE_Acceptor (ACE_Reactor * = 0,
+ int use_select = 1);
+
+ /**
+ * Open the contained @c PEER_ACCEPTOR object to begin listening, and
+ * register with the specified reactor for accept events. An
+ * acceptor can only listen to one port at a time, so make sure to
+ * @c close() the acceptor before calling @c open() again.
+ *
+ * The @c PEER_ACCEPTOR handle is put into non-blocking mode as a
+ * safeguard against the race condition that can otherwise occur
+ * between the time when the passive-mode socket handle is "ready"
+ * and when the actual @c accept() call is made. During this
+ * interval, the client can shutdown the connection, in which case,
+ * the @c accept() call can hang.
+ *
+ * @param local_addr The address to listen at.
+ * @param reactor Pointer to the ACE_Reactor instance to register
+ * this object with. The default is the singleton.
+ * @param flags Flags to control what mode an accepted socket
+ * will be put into after it is accepted. The only
+ * legal value for this argument is @c ACE_NONBLOCK,
+ * which enables non-blocking mode on the accepted
+ * peer stream object in @c SVC_HANDLER. The default
+ * is 0.
+ * @param use_select Affects behavior when called back by the reactor
+ * when a connection can be accepted. If non-zero,
+ * this object will accept all pending connections,
+ * intead of just the one that triggered the reactor
+ * callback. Uses ACE_OS::select() internally to
+ * detect any remaining acceptable connections.
+ * The default is 1.
+ * @param reuse_addr Passed to the @c PEER_ACCEPTOR::open() method with
+ * @p local_addr. Generally used to request that the
+ * OS allow reuse of the listen port. The default is 1.
+ */
+ ACE_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor *reactor = ACE_Reactor::instance (),
+ int flags = 0,
+ int use_select = 1,
+ int reuse_addr = 1);
+
+ /**
+ * Open the contained @c PEER_ACCEPTOR object to begin listening, and
+ * register with the specified reactor for accept events. An
+ * acceptor can only listen to one port at a time, so make sure to
+ * @c close() the acceptor before calling @c open() again.
+ *
+ * The @c PEER_ACCEPTOR handle is put into non-blocking mode as a
+ * safeguard against the race condition that can otherwise occur
+ * between the time when the passive-mode socket handle is "ready"
+ * and when the actual @c accept() call is made. During this
+ * interval, the client can shutdown the connection, in which case,
+ * the @c accept() call can hang.
+ *
+ * @param local_addr The address to listen at.
+ * @param reactor Pointer to the ACE_Reactor instance to register
+ * this object with. The default is the singleton.
+ * @param flags Flags to control what mode an accepted socket
+ * will be put into after it is accepted. The only
+ * legal value for this argument is @c ACE_NONBLOCK,
+ * which enables non-blocking mode on the accepted
+ * peer stream object in @c SVC_HANDLER. The default
+ * is 0.
+ * @param use_select Affects behavior when called back by the reactor
+ * when a connection can be accepted. If non-zero,
+ * this object will accept all pending connections,
+ * intead of just the one that triggered the reactor
+ * callback. Uses ACE_OS::select() internally to
+ * detect any remaining acceptable connections.
+ * The default is 1.
+ * @param reuse_addr Passed to the @c PEER_ACCEPTOR::open() method with
+ * @p local_addr. Generally used to request that the
+ * OS allow reuse of the listen port. The default is 1.
+ *
+ * @retval 0 Success
+ * @retval -1 Failure, @c errno contains an error code.
+ */
+ virtual int open (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor *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:
+
+ // Useful STL-style traits.
+ typedef ACE_Creation_Strategy<SVC_HANDLER>
+ creation_strategy_type;
+ typedef ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>
+ accept_strategy_type;
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER>
+ concurrency_strategy_type;
+ typedef ACE_Scheduling_Strategy<SVC_HANDLER> scheduling_strategy_type;
+ typedef ACE_Acceptor <SVC_HANDLER, ACE_PEER_ACCEPTOR_2>
+ base_type;
+
+ // = Define some useful (old style) traits.
+ 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;
+
+
+
+ /// Default constructor.
+ ACE_Strategy_Acceptor (const ACE_TCHAR service_name[] = 0,
+ const ACE_TCHAR service_description[] = 0,
+ int use_select = 1,
+ int reuse_addr = 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,
+ int reuse_addr = 1);
+
+ /**
+ * Open the contained @c PEER_ACCEPTOR object to begin listening, and
+ * register with the specified reactor for accept events.
+ *
+ * The @c PEER_ACCEPTOR handle is put into non-blocking mode as a
+ * safeguard against the race condition that can otherwise occur
+ * between the time when the passive-mode socket handle is "ready"
+ * and when the actual @c accept call is made. During this
+ * interval, the client can shutdown the connection, in which case,
+ * the {accept} call can hang.
+ *
+ * @param local_addr The address to listen at.
+ * @param reactor Pointer to the ACE_Reactor instance to register
+ * this object with. The default is the singleton.
+ * @param flags Flags to control what mode an accepted socket
+ * will be put into after it is accepted. The only
+ * legal value for this argument is @c ACE_NONBLOCK,
+ * which enables non-blocking mode on the accepted
+ * peer stream object in @c SVC_HANDLER. The default
+ * is 0.
+ * @param use_select Affects behavior when called back by the reactor
+ * when a connection can be accepted. If non-zero,
+ * this object will accept all pending connections,
+ * intead of just the one that triggered the reactor
+ * callback. Uses ACE_OS::select() internally to
+ * detect any remaining acceptable connections.
+ * The default is 1.
+ * @param reuse_addr Passed to the @c PEER_ACCEPTOR::open() method with
+ * @p local_addr. Generally used to request that the
+ * OS allow reuse of the listen port. The default is 1.
+ *
+ * @retval 0 Success
+ * @retval -1 Failure, @c errno contains an error code.
+ */
+ virtual int open (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor *reactor,
+ int flags = 0,
+ int use_select = 1,
+ int reuse_addr = 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}.
+ */
+ virtual 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,
+ int reuse_addr = 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;
+
+ // = 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);
+
+protected:
+
+ /// 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.
+
+ // = Strategy objects.
+
+ /// Creation strategy for an Acceptor.
+ CREATION_STRATEGY *creation_strategy_;
+
+ /// true if {Acceptor} created the creation strategy and thus should
+ /// delete it, else false.
+ bool delete_creation_strategy_;
+
+ /// Accept strategy for an {Acceptor}.
+ ACCEPT_STRATEGY *accept_strategy_;
+
+ /// true if {Acceptor} created the accept strategy and thus should delete
+ /// it, else false.
+ bool delete_accept_strategy_;
+
+ /// Concurrency strategy for an {Acceptor}.
+ CONCURRENCY_STRATEGY *concurrency_strategy_;
+
+ /// true if {Acceptor} created the concurrency strategy and thus should
+ /// delete it, else false.
+ bool delete_concurrency_strategy_;
+
+ /// Scheduling strategy for an {Acceptor}.
+ SCHEDULING_STRATEGY *scheduling_strategy_;
+
+ /// true if {Acceptor} created the scheduling strategy and thus should
+ /// delete it, else false.
+ bool delete_scheduling_strategy_;
+
+ // = Service information objects.
+
+ /// Name of the service.
+ ACE_TCHAR *service_name_;
+
+ /// Description of the service.
+ ACE_TCHAR *service_description_;
+
+ /// 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:
+
+ // Useful STL-style traits.
+ typedef ACE_PEER_ACCEPTOR_ADDR addr_type;
+ typedef ACE_PEER_ACCEPTOR acceptor_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+
+ /// 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_;
+
+ /// true if Acceptor created the concurrency strategy and thus should
+ /// delete it, else false.
+ bool delete_concurrency_strategy_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#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/ace/Activation_Queue.cpp b/ACE/ace/Activation_Queue.cpp
new file mode 100644
index 00000000000..aef17d05e7a
--- /dev/null
+++ b/ACE/ace/Activation_Queue.cpp
@@ -0,0 +1,138 @@
+#include "ace/Activation_Queue.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Activation_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/Method_Request.h"
+#include "ace/Malloc_Base.h"
+#include "ace/Time_Value.h"
+
+ACE_RCSID (ace,
+ Activation_Queue,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Activation_Queue::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("delete_queue_ = %d\n"),
+ this->delete_queue_));
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("queue_: \n")));
+ if (this->queue_)
+ this->queue_->dump();
+ else
+ //FUZZ: disable check_for_NULL
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(NULL)\n")));
+ //FUZZ: enable check_for_NULL
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Activation_Queue::ACE_Activation_Queue (ACE_Message_Queue<ACE_SYNCH> *new_queue,
+ ACE_Allocator *alloc,
+ ACE_Allocator *db_alloc)
+ : delete_queue_ (false)
+ , allocator_(alloc)
+ , data_block_allocator_(db_alloc)
+{
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ if (new_queue)
+ this->queue_ = new_queue;
+ else
+ {
+ ACE_NEW (this->queue_,
+ ACE_Message_Queue<ACE_SYNCH>);
+ this->delete_queue_ = true;
+ }
+}
+
+void
+ACE_Activation_Queue::queue (ACE_Message_Queue<ACE_SYNCH> *q)
+{
+ // Destroy the internal queue if one exist.
+ if (this->delete_queue_)
+ {
+ // Destroy the current queue.
+ delete this->queue_;
+
+ // Set the flag to false. NOTE that the delete_queue_ flag is a
+ // flag used to only indicate whether or not if an internal
+ // ACE_Message_Queue has been created, therefore, it will not
+ // affect the user if the user decided to replace the queue with
+ // their own queue no matter how many time they call on this
+ // function.
+ this->delete_queue_ = false;
+ }
+
+ queue_ = q;
+}
+
+ACE_Activation_Queue::~ACE_Activation_Queue (void)
+{
+ if (this->delete_queue_)
+ delete this->queue_;
+}
+
+ACE_Method_Request *
+ACE_Activation_Queue::dequeue (ACE_Time_Value *tv)
+{
+ ACE_Message_Block *mb = 0;
+
+ // Dequeue the message.
+ if (this->queue_->dequeue_head (mb, tv) != -1)
+ {
+ // Get the next <Method_Request>.
+ ACE_Method_Request *mr =
+ reinterpret_cast<ACE_Method_Request *> (mb->base ());
+ // Delete the message block.
+ mb->release ();
+ return mr;
+ }
+ else
+ return 0;
+}
+
+int
+ACE_Activation_Queue::enqueue (ACE_Method_Request *mr,
+ ACE_Time_Value *tv)
+{
+ ACE_Message_Block *mb = 0;
+
+ // We pass sizeof (*mr) here so that flow control will work
+ // correctly. Since we also pass <mr> note that no unnecessary
+ // memory is actually allocated -- just the size field is set.
+ ACE_NEW_MALLOC_RETURN (mb,
+ static_cast<ACE_Message_Block *> (this->allocator_->malloc (sizeof (ACE_Message_Block))),
+ ACE_Message_Block (sizeof (*mr), // size
+ ACE_Message_Block::MB_DATA, // type
+ 0, // cont
+ (char *) mr, // data
+ 0, // allocator
+ 0, // locking strategy
+ mr->priority (), // priority
+ ACE_Time_Value::zero, // execution time
+ ACE_Time_Value::max_time, // absolute time of deadline
+ this->data_block_allocator_, // data_block allocator
+ this->allocator_), // message_block allocator
+ -1);
+
+ // Enqueue in priority order.
+ int const result = this->queue_->enqueue_prio (mb, tv);
+
+ // Free ACE_Message_Block if enqueue_prio failed.
+ if (result == -1)
+ ACE_DES_FREE (mb, this->allocator_->free, ACE_Message_Block);
+
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Activation_Queue.h b/ACE/ace/Activation_Queue.h
new file mode 100644
index 00000000000..87fffc0f73d
--- /dev/null
+++ b/ACE/ace/Activation_Queue.h
@@ -0,0 +1,173 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Activation_Queue.h
+ *
+ * $Id$
+ *
+ * @author Andres Kruse <Andres.Kruse@cern.ch>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ACTIVATION_QUEUE_H
+#define ACE_ACTIVATION_QUEUE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Message_Queue.h"
+#include "ace/Condition_Thread_Mutex.h"
+
+/// Define to be compatible with the terminology in the POSA2 book!
+#define ACE_Activation_List ACE_Activation_Queue
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Method_Request;
+
+/**
+ * @class ACE_Activation_Queue
+ *
+ * @brief Reifies a method into a request. Subclasses typically
+ * represent necessary state and behavior.
+ *
+ * Maintains a priority-ordered queue of ACE_Method_Request objects.
+ * A scheduler class (often derived from ACE_Task) subsequently removes
+ * each method request and invokes its @c call() method.
+ *
+ * This class is discussed in depth in the Active Object chapter
+ * of POSA2. In that book, it is referred to as an Activation List.
+ *
+ * @sa ACE_Method_Request
+ */
+class ACE_Export ACE_Activation_Queue
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ /**
+ * Initializes a new activation queue.
+ *
+ * @param new_queue The activation queue uses an ACE_Message_Queue to
+ * queue and order the method requests. If this argument
+ * is 0, a new ACE_Message_Queue is created for this
+ * object's use and will be deleted when this object is
+ * destroyed. If a non-zero pointer is supplied, the
+ * passed object will be used and will not be deleted when
+ * this object is destroyed. If an ACE_Task is being created
+ * to act as the scheduler, for instance, its
+ * ACE_Message_Queue pointer can be passed to this object.
+ * @param alloc Optional, the allocator to use when allocating
+ * ACE_Message_Block instances that wrap the method requests
+ * queued to this activation queue. Defaults to
+ * ACE_Allocator::instance().
+ * @param db_alloc Optional, the allocator to use when allocating
+ * data blocks for the ACE_Message_Block instances that
+ * wrap the method requests queued to this activation queue.
+ * Defaults to ACE_Allocator::instance().
+ */
+ ACE_Activation_Queue (ACE_Message_Queue<ACE_SYNCH> *new_queue = 0,
+ ACE_Allocator *alloc = 0,
+ ACE_Allocator *db_alloc = 0);
+
+ /// Destructor.
+ virtual ~ACE_Activation_Queue (void);
+
+ // = Activate Queue operations.
+
+ /// Dequeue the next available ACE_Method_Request.
+ /**
+ * @param tv If 0, the method will block until a method request is
+ * available, else will wait until the absolute time specified
+ * in the referenced ACE_Time_Value. This method will return,
+ * earlier, however, if queue is closed, deactivated, or when
+ * a signal occurs.
+ *
+ * @retval Pointer to the dequeued ACE_Method_Request object.
+ * @retval 0 an error occurs; errno contains further information. If
+ * the specified timeout elapses, errno will be @c EWOULDBLOCK.
+ */
+ ACE_Method_Request *dequeue (ACE_Time_Value *tv = 0);
+
+ /// Enqueue the ACE_Method_Request in priority order.
+ /**
+ * The priority of the method request is obtained via the @c priority()
+ * method of the queued method request. Priority ordering is determined
+ * by the ACE_Message_Queue class; 0 is the lowest priority.
+ *
+ * @param new_method_request Pointer to the ACE_Method_Request object to
+ * queue. This object's @c priority() method is called to obtain
+ * the priority.
+ * @param tv If 0, the method will block until the method request can
+ * be queued, else will wait until the absolute time specified
+ * in the referenced ACE_Time_Value. This method will return,
+ * earlier, however, if queue is closed, deactivated, or when
+ * a signal occurs.
+ *
+ * @retval >0 The number of method requests on the queue after adding
+ * the specified request.
+ * @retval -1 if an error occurs; errno contains further information. If
+ * the specified timeout elapses, errno will be @c EWOULDBLOCK.
+ */
+ int enqueue (ACE_Method_Request *new_method_request, ACE_Time_Value *tv = 0);
+
+ /// Get the current number of method objects in the queue.
+ size_t method_count (void) const;
+
+ /// Returns 1 if the queue is empty, 0 otherwise.
+ int is_empty (void) const;
+
+ /// Returns 1 if the queue is full, 0 otherwise.
+ int is_full (void) const;
+
+ /// Dump the state of an request.
+ void dump (void) const;
+
+ /// Get a pointer to the underlying queue.
+ ACE_Message_Queue<ACE_SYNCH> *queue (void) const;
+
+ /// Set the pointer to the underlying queue.
+ void queue (ACE_Message_Queue<ACE_SYNCH> *q);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ // = Prevent copying and assignment.
+ ACE_Activation_Queue (const ACE_Activation_Queue &);
+ void operator= (const ACE_Activation_Queue &);
+
+protected:
+
+ /// Stores the Method_Requests.
+ ACE_Message_Queue<ACE_SYNCH> *queue_;
+
+ /// Keeps track of whether we need to delete the queue.
+ bool delete_queue_;
+
+private:
+
+ /// Allocation strategy of the queue.
+ ACE_Allocator *allocator_;
+
+ /// Allocation strategy of the message blocks.
+ ACE_Allocator *data_block_allocator_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Activation_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_ACTIVATION_QUEUE_H */
diff --git a/ACE/ace/Activation_Queue.inl b/ACE/ace/Activation_Queue.inl
new file mode 100644
index 00000000000..50127f607d1
--- /dev/null
+++ b/ACE/ace/Activation_Queue.inl
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE size_t
+ACE_Activation_Queue::method_count (void) const
+{
+ return queue_->message_count ();
+}
+
+ACE_INLINE int
+ACE_Activation_Queue::is_full (void) const
+{
+ return queue_->is_full ();
+}
+
+ACE_INLINE int
+ACE_Activation_Queue::is_empty (void) const
+{
+ return queue_->is_empty ();
+}
+
+ACE_INLINE ACE_Message_Queue<ACE_SYNCH> *
+ACE_Activation_Queue::queue (void) const
+{
+ return queue_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Active_Map_Manager.cpp b/ACE/ace/Active_Map_Manager.cpp
new file mode 100644
index 00000000000..6f4b66191c7
--- /dev/null
+++ b/ACE/ace/Active_Map_Manager.cpp
@@ -0,0 +1,9 @@
+// $Id$
+
+#include "ace/Active_Map_Manager.h"
+
+ACE_RCSID(ace, Active_Map_Manager, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Active_Map_Manager.inl"
+#endif /* __ACE_INLINE__ */
diff --git a/ACE/ace/Active_Map_Manager.h b/ACE/ace/Active_Map_Manager.h
new file mode 100644
index 00000000000..1281302fdf8
--- /dev/null
+++ b/ACE/ace/Active_Map_Manager.h
@@ -0,0 +1,116 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Active_Map_Manager.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali
+ */
+//=============================================================================
+
+
+#ifndef ACE_ACTIVE_MAP_MANAGER_H
+#define ACE_ACTIVE_MAP_MANAGER_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Basic_Types.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Active_Map_Manager_Key
+ *
+ * @brief Key used in the Active Object Map.
+ *
+ * This key keeps information of the index and the generation
+ * count of the slot it represents. Since the index information
+ * is part of the key, lookups are super fast and predictable,
+ */
+class ACE_Export ACE_Active_Map_Manager_Key
+{
+public:
+ /// Default constructor.
+ ACE_Active_Map_Manager_Key (void);
+
+ /**
+ * Constructor given the @a slot_index and @a slot_generation number.
+ * This is useful once the user has somehow recovered the
+ * @a slot_index and @a slot_generation number from the client.
+ */
+ ACE_Active_Map_Manager_Key (ACE_UINT32 slot_index,
+ ACE_UINT32 slot_generation);
+
+ /// Get the slot_index.
+ ACE_UINT32 slot_index (void) const;
+
+ /// Set the slot_index.
+ void slot_index (ACE_UINT32 i);
+
+ /// Get the slot_generation number.
+ ACE_UINT32 slot_generation (void) const;
+
+ /// Set the slot_generation number.
+ void slot_generation (ACE_UINT32 g);
+
+ /// Size required to store information about active key.
+ static size_t size (void);
+
+ /// Recover state of active key from @a data. User must make sure
+ /// that @a data encoded using the encode() method.
+ void decode (const void *data);
+
+ /// Encode state of the active key into @a data. @a data must be as
+ /// big as the value returned from <size>.
+ void encode (void *data) const;
+
+ /// Compare keys.
+ bool operator== (const ACE_Active_Map_Manager_Key &rhs) const;
+ bool operator!= (const ACE_Active_Map_Manager_Key &rhs) const;
+
+ // = This really should be protected but because of template
+ // friends, they are not.
+
+ /// Increment the <slot_generation> number.
+ void increment_slot_generation_count (void);
+
+private:
+
+ /**
+ * @brief Data for the Active Object Map Key.
+ *
+ * This separate structure makes it easier to manage copying
+ * the index and the generation to and from the user buffer.
+ *
+ */
+ struct key_data
+ {
+ /// Slot index in the active map.
+ ACE_UINT32 slot_index_;
+
+ /// Slot generation number of <slot_index_> slot in the active map.
+ ACE_UINT32 slot_generation_;
+ };
+
+ /// Data for the Active Object Map Key.
+ key_data key_data_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Active_Map_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+// Include the templates here.
+#include "ace/Active_Map_Manager_T.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_ACTIVE_MAP_MANAGER_H */
diff --git a/ACE/ace/Active_Map_Manager.inl b/ACE/ace/Active_Map_Manager.inl
new file mode 100644
index 00000000000..652cf7c1f71
--- /dev/null
+++ b/ACE/ace/Active_Map_Manager.inl
@@ -0,0 +1,95 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Active_Map_Manager_Key::ACE_Active_Map_Manager_Key (void)
+{
+ // If you change ~0, please change ACE_Map_Manager::free_list_id()
+ // accordingly.
+ this->key_data_.slot_index_ = (ACE_UINT32) ~0;
+ this->key_data_.slot_generation_ = 0;
+}
+
+ACE_INLINE
+ACE_Active_Map_Manager_Key::ACE_Active_Map_Manager_Key (ACE_UINT32 slot_index,
+ ACE_UINT32 slot_generation)
+{
+ this->key_data_.slot_index_ = slot_index;
+ this->key_data_.slot_generation_ = slot_generation;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_Active_Map_Manager_Key::slot_index (void) const
+{
+ return this->key_data_.slot_index_;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_Active_Map_Manager_Key::slot_generation (void) const
+{
+ return this->key_data_.slot_generation_;
+}
+
+ACE_INLINE bool
+ACE_Active_Map_Manager_Key::operator== (const ACE_Active_Map_Manager_Key &rhs) const
+{
+ return
+ this->key_data_.slot_index_ == rhs.key_data_.slot_index_ &&
+ this->key_data_.slot_generation_ == rhs.key_data_.slot_generation_;
+}
+
+ACE_INLINE bool
+ACE_Active_Map_Manager_Key::operator!= (const ACE_Active_Map_Manager_Key &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+ACE_INLINE void
+ACE_Active_Map_Manager_Key::slot_index (ACE_UINT32 i)
+{
+ this->key_data_.slot_index_ = i;
+}
+
+ACE_INLINE void
+ACE_Active_Map_Manager_Key::slot_generation (ACE_UINT32 g)
+{
+ this->key_data_.slot_generation_ = g;
+}
+
+ACE_INLINE void
+ACE_Active_Map_Manager_Key::increment_slot_generation_count (void)
+{
+ ++this->key_data_.slot_generation_;
+}
+
+/* static */
+ACE_INLINE size_t
+ACE_Active_Map_Manager_Key::size (void)
+{
+ return sizeof (ACE_UINT32) + sizeof (ACE_UINT32);
+}
+
+ACE_INLINE void
+ACE_Active_Map_Manager_Key::decode (const void *data)
+{
+ // Copy the information from the user buffer into the key.
+ ACE_OS::memcpy (&this->key_data_,
+ data,
+ sizeof this->key_data_);
+}
+
+ACE_INLINE void
+ACE_Active_Map_Manager_Key::encode (void *data) const
+{
+ // Copy the key data to the user buffer.
+ ACE_OS::memcpy (data,
+ &this->key_data_,
+ sizeof this->key_data_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Active_Map_Manager_T.cpp b/ACE/ace/Active_Map_Manager_T.cpp
new file mode 100644
index 00000000000..b8cd14446ac
--- /dev/null
+++ b/ACE/ace/Active_Map_Manager_T.cpp
@@ -0,0 +1,22 @@
+// $Id$
+
+#ifndef ACE_ACTIVE_MAP_MANAGER_T_CPP
+#define ACE_ACTIVE_MAP_MANAGER_T_CPP
+
+#include "ace/Active_Map_Manager_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Active_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Active_Map_Manager)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_ACTIVE_MAP_MANAGER_T_CPP */
diff --git a/ACE/ace/Active_Map_Manager_T.h b/ACE/ace/Active_Map_Manager_T.h
new file mode 100644
index 00000000000..34b5a475652
--- /dev/null
+++ b/ACE/ace/Active_Map_Manager_T.h
@@ -0,0 +1,211 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Active_Map_Manager_T.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali
+ */
+//=============================================================================
+
+
+#ifndef ACE_ACTIVE_MAP_MANAGER_T_H
+#define ACE_ACTIVE_MAP_MANAGER_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Map_Manager.h"
+#include "ace/Active_Map_Manager.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Null_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Active_Map_Manager
+ *
+ * @brief Define a map abstraction that associates system generated
+ * keys with user specified values.
+ *
+ * Since the key is system generated, searches are very fast and
+ * take a constant amount of time.
+ */
+template <class T>
+class ACE_Active_Map_Manager : public ACE_Map_Manager<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex>
+{
+public:
+
+ // = Traits.
+ typedef ACE_Active_Map_Manager_Key key_type;
+ typedef T mapped_type;
+
+ typedef ACE_Map_Entry<ACE_Active_Map_Manager_Key, T> ENTRY;
+ typedef ACE_Map_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex> ITERATOR;
+ typedef ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex> REVERSE_ITERATOR;
+
+ typedef ENTRY entry;
+ typedef ITERATOR iterator;
+ typedef REVERSE_ITERATOR reverse_iterator;
+
+ // = Initialization and termination methods.
+ /// Initialize a <Active_Map_Manager> with the ACE_DEFAULT_MAP_SIZE.
+ ACE_Active_Map_Manager (ACE_Allocator *alloc = 0);
+
+ /// Initialize a <Active_Map_Manager> with @a size entries.
+ ACE_Active_Map_Manager (size_t size,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a <Active_Map_Manager> and release dynamically
+ /// allocated resources.
+ ~ACE_Active_Map_Manager (void);
+
+ /// Initialize a <Active_Map_Manager> with size @a length.
+ int open (size_t length = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a <Active_Map_Manager> and release dynamically
+ /// allocated resources.
+ int close (void);
+
+ /// Add @a value to the map, and the corresponding key produced by the
+ /// Active_Map_Manager is returned through @a key.
+ int bind (const T &value,
+ ACE_Active_Map_Manager_Key &key);
+
+ /// Add @a value to the map. The user does not care about the
+ /// corresponding key produced by the Active_Map_Manager.
+ int bind (const T &value);
+
+ /**
+ * Reserves a slot in the internal structure and returns the key and
+ * a pointer to the value. User should place their @a value into
+ * <*internal_value>. This method is useful in reducing the number
+ * of copies required in some cases. Note that <internal_value> is
+ * only a temporary pointer and will change when the map resizes.
+ * Therefore, the user should use the pointer immediately and not
+ * hold on to it.
+ */
+ int bind (ACE_Active_Map_Manager_Key &key,
+ T *&internal_value);
+
+ /// Reassociate @a key with @a value. The function fails if @a key is
+ /// not in the map.
+ int rebind (const ACE_Active_Map_Manager_Key &key,
+ const T &value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old value into the
+ * "out" parameter @a old_value. The function fails if @a key is not
+ * in the map.
+ */
+ int rebind (const ACE_Active_Map_Manager_Key &key,
+ const T &value,
+ T &old_value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old key and value
+ * into the "out" parameter @a old_key and @a old_value. The function
+ * fails if @a key is not in the map.
+ */
+ int rebind (const ACE_Active_Map_Manager_Key &key,
+ const T &value,
+ ACE_Active_Map_Manager_Key &old_key,
+ T &old_value);
+
+ /// Locate @a value associated with @a key.
+ int find (const ACE_Active_Map_Manager_Key &key,
+ T &value) const;
+
+ /// Is @a key in the map?
+ int find (const ACE_Active_Map_Manager_Key &key) const;
+
+ /**
+ * Locate @a value associated with @a key. The value is returned via
+ * <internal_value> and hence a copy is saved. Note that
+ * <internal_value> is only a temporary pointer and will change when
+ * the map resizes. Therefore, the user should use the pointer
+ * immediately and not hold on to it.
+ */
+ int find (const ACE_Active_Map_Manager_Key &key,
+ T *&internal_value) const;
+
+ // Creates a key. User should place their @a value into
+ // <*internal_value>. This method is useful in reducing the number
+ // of copies required in some cases.
+
+ /// Remove @a key from the map.
+ int unbind (const ACE_Active_Map_Manager_Key &key);
+
+ /// Remove @a key from the map, and return the @a value associated with
+ /// @a key.
+ int unbind (const ACE_Active_Map_Manager_Key &key,
+ T &value);
+
+ /**
+ * Locate @a value associated with @a key. The value is returned via
+ * <internal_value> and hence a copy is saved. Note that
+ * <internal_value> is only a temporary pointer and will change when
+ * the map resizes or when this slot is reused. Therefore, the user
+ * should use the pointer immediately and not hold on to it.
+ */
+ int unbind (const ACE_Active_Map_Manager_Key &key,
+ T *&internal_value);
+
+ /// Return the current size of the map.
+ size_t current_size (void) const;
+
+ /// Return the total size of the map.
+ size_t total_size (void) const;
+
+ /// Returns a key that cannot be found in the map.
+ static const ACE_Active_Map_Manager_Key npos (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ ACE_Map_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex> begin (void);
+ ACE_Map_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex> end (void);
+
+ /// Return reverse iterator.
+ ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex> rbegin (void);
+ ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex> rend (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ /// Private base class
+ typedef ACE_Map_Manager<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex> ACE_AMM_BASE;
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Active_Map_Manager<T> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Active_Map_Manager (const ACE_Active_Map_Manager<T> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Active_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Active_Map_Manager_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Active_Map_Manager_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_ACTIVE_MAP_MANAGER_T_H */
diff --git a/ACE/ace/Active_Map_Manager_T.inl b/ACE/ace/Active_Map_Manager_T.inl
new file mode 100644
index 00000000000..124f76c48c4
--- /dev/null
+++ b/ACE/ace/Active_Map_Manager_T.inl
@@ -0,0 +1,311 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::bind (ACE_Active_Map_Manager_Key &key,
+ T *&internal_value)
+{
+ ACE_UINT32 slot_index;
+ int result = this->next_free (slot_index);
+
+ if (result == 0)
+ {
+ // Move from free list to occupied list
+ this->move_from_free_list_to_occupied_list (slot_index);
+
+ // Reset the key.
+ this->search_structure_[slot_index].ext_id_.increment_slot_generation_count ();
+ this->search_structure_[slot_index].ext_id_.slot_index (slot_index);
+
+ // Copy the key for the user.
+ key = this->search_structure_[slot_index].ext_id_;
+
+ // This is where the user should place the value.
+ internal_value = &this->search_structure_[slot_index].int_id_;
+
+ // Update the current size.
+ ++this->cur_size_;
+ }
+
+ return result;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::bind (const T &value,
+ ACE_Active_Map_Manager_Key &key)
+{
+ T *internal_value = 0;
+ int result = this->bind (key,
+ internal_value);
+
+ if (result == 0)
+ {
+ // Store new value.
+ *internal_value = value;
+ }
+
+ return result;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::bind (const T &value)
+{
+ ACE_Active_Map_Manager_Key key;
+ return this->bind (value, key);
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::find (const ACE_Active_Map_Manager_Key &key,
+ T *&internal_value) const
+{
+ ACE_UINT32 slot_index = key.slot_index ();
+ ACE_UINT32 slot_generation = key.slot_generation ();
+
+ if (slot_index > this->total_size_ ||
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+ this->search_structure_[slot_index].free_ ||
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+ this->search_structure_[slot_index].ext_id_.slot_generation () != slot_generation ||
+ this->search_structure_[slot_index].ext_id_.slot_index () ==
+ (ACE_UINT32)this->free_list_id ())
+ {
+ return -1;
+ }
+ else
+ {
+ // This is where the user value is.
+ internal_value = &this->search_structure_[slot_index].int_id_;
+ }
+
+ return 0;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::find (const ACE_Active_Map_Manager_Key &key) const
+{
+ T *internal_value = 0;
+ return this->find (key,
+ internal_value);
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::find (const ACE_Active_Map_Manager_Key &key,
+ T &value) const
+{
+ T *internal_value = 0;
+ int result = this->find (key,
+ internal_value);
+
+ if (result == 0)
+ value = *internal_value;
+
+ return result;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::rebind (const ACE_Active_Map_Manager_Key &key,
+ const T &value)
+{
+ int result = this->find (key);
+
+ if (result == 0)
+ {
+ // Store new value.
+ this->search_structure_[key.slot_index ()].int_id_ = value;
+ }
+
+ return result;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::rebind (const ACE_Active_Map_Manager_Key &key,
+ const T &value,
+ T &old_value)
+{
+ int result = this->find (key);
+
+ if (result == 0)
+ {
+ // Copy old value.
+ old_value = this->search_structure_[key.slot_index ()].int_id_;
+
+ // Store new value.
+ this->search_structure_[key.slot_index ()].int_id_ = value;
+ }
+
+ return result;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::rebind (const ACE_Active_Map_Manager_Key &key,
+ const T &value,
+ ACE_Active_Map_Manager_Key &old_key,
+ T &old_value)
+{
+ int result = this->find (key);
+
+ if (result == 0)
+ {
+ // Copy old key.
+ old_key = this->search_structure_[key.slot_index ()].ext_id_;
+
+ // Copy old value.
+ old_value = this->search_structure_[key.slot_index ()].int_id_;
+
+ // Store new value.
+ this->search_structure_[key.slot_index ()].int_id_ = value;
+ }
+
+ return result;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::unbind (const ACE_Active_Map_Manager_Key &key,
+ T *&internal_value)
+{
+ int result = this->find (key,
+ internal_value);
+
+ if (result == 0)
+ {
+ ACE_UINT32 slot_index = key.slot_index ();
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ //
+ // In the case of lazy map managers, the movement of free slots
+ // from the occupied list to the free list is delayed until we
+ // run out of free slots in the free list.
+ //
+
+ this->search_structure_[slot_index].free_ = 1;
+
+#else
+
+ // Move from occupied list to free list.
+ this->move_from_occupied_list_to_free_list (slot_index);
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ // Reset the slot_index. This will tell us that this entry is free.
+ this->search_structure_[slot_index].ext_id_.slot_index (this->free_list_id ());
+
+ // Update the current size.
+ --this->cur_size_;
+ }
+
+ return result;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::unbind (const ACE_Active_Map_Manager_Key &key,
+ T &value)
+{
+ T *internal_value;
+ int result = this->unbind (key,
+ internal_value);
+
+ if (result == 0)
+ {
+ // Copy old value.
+ value = *internal_value;
+ }
+
+ return result;
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::unbind (const ACE_Active_Map_Manager_Key &key)
+{
+ T *internal_value;
+ return this->unbind (key,
+ internal_value);
+}
+
+template <class T> ACE_INLINE
+ACE_Active_Map_Manager<T>::ACE_Active_Map_Manager (ACE_Allocator *alloc)
+ : ACE_AMM_BASE (alloc)
+{
+}
+
+template <class T> ACE_INLINE
+ACE_Active_Map_Manager<T>::ACE_Active_Map_Manager (size_t size,
+ ACE_Allocator *alloc)
+ : ACE_AMM_BASE (size,
+ alloc)
+{
+}
+
+template <class T> ACE_INLINE
+ACE_Active_Map_Manager<T>::~ACE_Active_Map_Manager (void)
+{
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::open (size_t length,
+ ACE_Allocator *alloc)
+{
+ return ACE_AMM_BASE::open (length, alloc);
+}
+
+template <class T> ACE_INLINE int
+ACE_Active_Map_Manager<T>::close (void)
+{
+ return ACE_AMM_BASE::close ();
+}
+
+template <class T> ACE_INLINE size_t
+ACE_Active_Map_Manager<T>::current_size (void) const
+{
+ return ACE_AMM_BASE::current_size ();
+}
+
+template <class T> ACE_INLINE size_t
+ACE_Active_Map_Manager<T>::total_size (void) const
+{
+ return ACE_AMM_BASE::total_size ();
+}
+
+/* static */
+template <class T> ACE_INLINE const ACE_Active_Map_Manager_Key
+ACE_Active_Map_Manager<T>::npos (void)
+{
+ return ACE_Active_Map_Manager_Key (~0, ~0);
+}
+
+template <class T> ACE_INLINE void
+ACE_Active_Map_Manager<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_AMM_BASE::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T> ACE_Map_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex>
+ACE_Active_Map_Manager<T>::begin (void)
+{
+ return ACE_AMM_BASE::begin ();
+}
+
+template <class T> ACE_INLINE ACE_Map_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex>
+ACE_Active_Map_Manager<T>::end (void)
+{
+ return ACE_AMM_BASE::end ();
+}
+
+template <class T> ACE_INLINE ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex>
+ACE_Active_Map_Manager<T>::rbegin (void)
+{
+ return ACE_AMM_BASE::rbegin ();
+}
+
+template <class T> ACE_INLINE ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, T, ACE_Null_Mutex>
+ACE_Active_Map_Manager<T>::rend (void)
+{
+ return ACE_AMM_BASE::rend ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Addr.cpp b/ACE/ace/Addr.cpp
new file mode 100644
index 00000000000..f458e018eef
--- /dev/null
+++ b/ACE/ace/Addr.cpp
@@ -0,0 +1,73 @@
+// $Id$
+
+#include "ace/Addr.h"
+
+
+ACE_RCSID (ace,
+ Addr,
+ "$Id$")
+
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/os_include/sys/os_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Note: this object requires static construction and destruction.
+/* static */
+const ACE_Addr ACE_Addr::sap_any (AF_ANY, -1);
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Addr)
+
+
+// Initializes instance variables. Note that 0 is an unspecified
+// protocol family type...
+
+ACE_Addr::ACE_Addr (int type, int size) :
+ addr_type_ (type),
+ addr_size_ (size)
+{
+}
+
+ACE_Addr::~ACE_Addr (void)
+{
+}
+
+void *
+ACE_Addr::get_addr (void) const
+{
+ return 0;
+}
+
+void
+ACE_Addr::set_addr (void *, int)
+{
+}
+
+// Initializes instance variables.
+
+void
+ACE_Addr::base_set (int type, int size)
+{
+ this->addr_type_ = type;
+ this->addr_size_ = size;
+}
+
+void
+ACE_Addr::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("addr_type_ = %d"), this->addr_type_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\naddr_size_ = %d"), this->addr_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Addr.h b/ACE/ace/Addr.h
new file mode 100644
index 00000000000..530fb87c17f
--- /dev/null
+++ b/ACE/ace/Addr.h
@@ -0,0 +1,104 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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.
+ bool operator == (const ACE_Addr &sap) const;
+
+ /// Check for address inequality.
+ bool operator != (const ACE_Addr &sap) const;
+
+ /// Initializes instance variables.
+ void base_set (int type, int size);
+
+ /// Wild-card address.
+ static const ACE_Addr sap_any;
+
+ /// Returns a hash value. This should be overwritten by a subclass
+ /// that can produce a better hash value.
+ virtual unsigned 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ADDR_H */
diff --git a/ACE/ace/Addr.inl b/ACE/ace/Addr.inl
new file mode 100644
index 00000000000..3780e04b6aa
--- /dev/null
+++ b/ACE/ace/Addr.inl
@@ -0,0 +1,61 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// Return the address of the address.
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE bool
+ACE_Addr::operator == (const ACE_Addr &sap) const
+{
+ return (sap.addr_type_ == this->addr_type_ &&
+ sap.addr_size_ == this->addr_size_ );
+}
+
+ACE_INLINE bool
+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 unsigned long
+ACE_Addr::hash (void) const
+{
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Arg_Shifter.cpp b/ACE/ace/Arg_Shifter.cpp
new file mode 100644
index 00000000000..36c265c6d5a
--- /dev/null
+++ b/ACE/ace/Arg_Shifter.cpp
@@ -0,0 +1,230 @@
+#ifndef ACE_ARG_SHIFTER_T_CPP
+#define ACE_ARG_SHIFTER_T_CPP
+
+#include "ace/Arg_Shifter.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_strings.h"
+#include "ace/OS_Errno.h"
+#include "ace/OS_Memory.h"
+
+ACE_RCSID (ace,
+ Arg_Shifter,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <typename CHAR_TYPE>
+ACE_Arg_Shifter_T<CHAR_TYPE>::ACE_Arg_Shifter_T (int& argc,
+ const CHAR_TYPE** argv,
+ const CHAR_TYPE** temp)
+ : argc_ (argc),
+ total_size_ (argc),
+ temp_ (temp),
+ argv_ (argv),
+ current_index_ (0),
+ back_ (argc - 1),
+ front_ (0)
+{
+ this->init ();
+}
+
+template <typename CHAR_TYPE>
+ACE_Arg_Shifter_T<CHAR_TYPE>::ACE_Arg_Shifter_T (int& argc,
+ CHAR_TYPE** argv,
+ CHAR_TYPE** temp)
+ : argc_ (argc),
+ total_size_ (argc),
+ temp_ ((const CHAR_TYPE **) temp),
+ argv_ ((const CHAR_TYPE **) argv),
+ current_index_ (0),
+ back_ (argc - 1),
+ front_ (0)
+{
+ this->init ();
+}
+
+template <typename CHAR_TYPE>
+void
+ACE_Arg_Shifter_T<CHAR_TYPE>::init (void)
+{
+ // If not provided with one, allocate a temporary array.
+ if (this->temp_ == 0)
+ ACE_NEW (this->temp_,
+ const CHAR_TYPE *[this->total_size_]);
+
+ if (this->temp_ != 0)
+ {
+ // Fill the temporary array.
+ this->argc_ = 0;
+ for (int i = 0; i < this->total_size_; i++)
+ {
+ this->temp_[i] = this->argv_[i];
+ this->argv_[i] = 0;
+ }
+ }
+ else
+ {
+ // Allocation failed, prohibit iteration.
+ this->current_index_ = this->argc_;
+ this->front_ = this->argc_;
+ }
+}
+
+template <typename CHAR_TYPE>
+ACE_Arg_Shifter_T<CHAR_TYPE>::~ACE_Arg_Shifter_T (void)
+{
+ // Delete the temporary vector.
+ delete [] temp_;
+}
+
+template <typename CHAR_TYPE>
+const CHAR_TYPE *
+ACE_Arg_Shifter_T<CHAR_TYPE>::get_current (void) const
+{
+ const CHAR_TYPE * retval = 0;
+
+ if (this->is_anything_left ())
+ retval = this->temp_[current_index_];
+
+ return retval;
+}
+
+template <typename CHAR_TYPE>
+const CHAR_TYPE *
+ACE_Arg_Shifter_T<CHAR_TYPE>::get_the_parameter (const CHAR_TYPE *flag)
+{
+ // the return 0's abound because this method
+ // would otherwise be a deep if { } else { }
+
+ // check to see if any arguments still exist
+ if (!this->is_anything_left())
+ return 0;
+
+ // check to see if the flag is the argument
+ int const offset = this->cur_arg_strncasecmp (flag);
+ if (offset == -1)
+ return 0;
+
+ if (offset == 0)
+ {
+ this->consume_arg ();
+
+ if (!this->is_parameter_next())
+ {
+ return 0;
+ }
+ }
+ // the parameter is in the middle somewhere...
+ return this->temp_[current_index_] + offset;
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_Arg_Shifter_T<CHAR_TYPE>::cur_arg_strncasecmp (const CHAR_TYPE *flag)
+{
+ // Check for a current argument
+ if (this->is_anything_left())
+ {
+ size_t const flag_length = ACE_OS::strlen (flag);
+
+ // Check for presence of the flag
+ if (ACE_OS::strncasecmp(this->temp_[current_index_],
+ flag,
+ flag_length) == 0)
+ {
+ if (ACE_OS::strlen(temp_[current_index_]) ==
+ flag_length)
+ {
+ // match and lengths are equal
+ return 0;
+ }
+ else
+ {
+ // matches, with more info to boot!
+ size_t const remaining = ACE_OS::strspn
+ (this->temp_[current_index_] + flag_length,
+ ACE_TEXT (" ")) + flag_length;
+ return static_cast<int> (remaining);
+ }
+ }
+ }
+ // failure
+ return -1;
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_Arg_Shifter_T<CHAR_TYPE>::consume_arg (int number)
+{
+ int retval = 0;
+
+ // Stick knowns at the end of the vector (consumed).
+ if (this->is_anything_left() >= number)
+ {
+ for (int i = 0, j = this->back_ - (number - 1);
+ i < number;
+ ++i, ++j, ++this->current_index_)
+ this->argv_[j] = this->temp_[this->current_index_];
+
+ this->back_ -= number;
+ retval = 1;
+ }
+
+ return retval;
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_Arg_Shifter_T<CHAR_TYPE>::ignore_arg (int number)
+{
+ int retval = 0;
+
+ // Keep unknowns at the head of the vector.
+ if (this->is_anything_left () >= number)
+ {
+ for (int i = 0;
+ i < number;
+ i++, this->current_index_++, this->front_++)
+ this->argv_[this->front_] = this->temp_[this->current_index_];
+
+ retval = 1;
+ this->argc_ += number;
+ }
+
+ return retval;
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_Arg_Shifter_T<CHAR_TYPE>::is_anything_left (void) const
+{
+ return this->total_size_ - this->current_index_;
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_Arg_Shifter_T<CHAR_TYPE>::is_option_next (void) const
+{
+ return this->is_anything_left () &&
+ this->temp_[this->current_index_][0] == '-';
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_Arg_Shifter_T<CHAR_TYPE>::is_parameter_next (void) const
+{
+ return this->is_anything_left ()
+ && this->temp_[this->current_index_][0] != '-';
+}
+
+template <typename CHAR_TYPE>
+int
+ACE_Arg_Shifter_T<CHAR_TYPE>::num_ignored_args (void) const
+{
+ return this->front_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_ATOMIC_OP_T_CPP */
diff --git a/ACE/ace/Arg_Shifter.h b/ACE/ace/Arg_Shifter.h
new file mode 100644
index 00000000000..409ffa03a88
--- /dev/null
+++ b/ACE/ace/Arg_Shifter.h
@@ -0,0 +1,221 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Arg_Shifter.h
+ *
+ * $Id$
+ *
+ * @author Seth Widoff
+ */
+//=============================================================================
+
+#ifndef ACE_ARG_SHIFTER_H
+#define ACE_ARG_SHIFTER_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Arg_Shifter_T
+ *
+ * @brief This ADT operates on a specified set of arguments (@a argv).
+ * As known arguments are scanned, they are shifted to the back of the
+ * @a argv vector, so deeper levels of argument parsing can locate the yet
+ * unprocessed arguments at the beginning of the vector.
+ *
+ * The @c ACE_Arg_Shifter copies the pointers of the @a argv vector
+ * into a temporary array. As the @c ACE_Arg_Shifter iterates over
+ * the copied vector, it places known arguments in the rear of the
+ * vector, leaving the unknown ones in the beginning. So, after having
+ * visited all the arguments in the temporary vector, @c ACE_Arg_Shifter
+ * has placed all the unknown arguments in their original order at
+ * the front of original @a argv.
+ */
+template <typename CHAR_TYPE>
+class ACE_Arg_Shifter_T
+{
+public:
+ // = Initialization and termination methods.
+ /**
+ * Initialize the ACE_Arg_Shifter to the vector over which to
+ * iterate. Optionally, also provide the temporary array for
+ * use in shifting the arguments. If ACE_Arg_Shifter must allocate
+ * the temporary vector internally and dynamic allocation fails, the
+ * ACE_Arg_Shifter will set all indicators to end of the vector,
+ * forbidding iteration. Following iteration over @a argv, the
+ * @a argc value will be updated to contain the number of
+ * unconsumed arguments.
+ * @param argc The number of strings in @a argv. @a argc will be
+ * updated to reflect the number of unconsumed arguments.
+ * @param argv The argument vector to shift. The string pointers in
+ * the vector will be reordered to place the @a argc unconsumed
+ * arguments at the front of the vector.
+ * @param temp A vector of @c CHAR_TYPE pointers at least @a argc
+ * elements long. The vector will be used for argument shifting as
+ * the specified @a argv vector is consumed. The vector must not
+ * be modified while this object exists. If this argument is 0
+ * (the default) the object will allocate and free the temporary
+ * vector transparently.
+ */
+ ACE_Arg_Shifter_T (int& argc,
+ const CHAR_TYPE **argv,
+ const CHAR_TYPE **temp = 0);
+
+ /// Same behavior as the preceding constructor, but without the
+ /// "const" qualifier.
+ ACE_Arg_Shifter_T (int& argc,
+ CHAR_TYPE **argv,
+ CHAR_TYPE **temp = 0);
+
+ /// Destructor.
+ ~ACE_Arg_Shifter_T (void);
+
+ /// Get the current head of the vector.
+ const CHAR_TYPE *get_current (void) const;
+
+ /**
+ * If the @a flag matches the current_arg of arg shifter
+ * this method will attempt to return the associated
+ * parameter value
+ *
+ * Safe to call without checking that a current arg exists
+ *
+ * In the following examples, a pointer to the char* "value" is ret
+ *
+ * eg: main -foobar value, main -FooBar value
+ * main -FOOBARvalue
+ *
+ * all of the above will all match the @a flag == -FooBar
+ * and will return a char* to "value"
+ *
+ * main -foobar 4 would succeed and return a char* to "4"
+ * main -foobar -4 does not succeed (-4 is not a parameter)
+ * but instead, would return 0
+ *
+ * 0 is returned:
+ * If the current argument does not match flag
+ * If there is no parameter found after a 'matched' flag
+ *
+ * If the flag is matched and the flag and paramter DO NOT RUN
+ * together, the flag is consumed, the parameter is returned,
+ * and the new current argument is the parameter value.
+ * ie '-foobarflag VALUE' leaves the new cur arg == "VALUE"
+ *
+ * If the flag is matched and the flag and parameter RUN
+ * together '-foobarflagVALUE', the flag is NOT consumed
+ * and the cur arg is left pointing to the entire flag/value pair
+ */
+ const CHAR_TYPE *get_the_parameter (const CHAR_TYPE* flag);
+
+ /**
+ * Check if the current argument matches (case insensitive) <flag>
+ *
+ * ------------------------------------------------------------
+ *
+ * Case A: Perfect Match (case insensitive)
+ * 0 is returned.
+ *
+ * ie: when current_arg = "-foobar" or "-FOOBAR" or "-fooBAR"
+ * this->cur_arg_strncasecmp ("-FooBar);
+ * will return 0
+ *
+ * ------------------------------------------------------------
+ *
+ * Case B: Perfect Match (case insensitive) but the current_arg
+ * is longer than the flag. Returns a number equal to the index
+ * in the char* indicating the start of the extra characters
+ *
+ * ie: when current_arg = "-foobar98023"
+ * this->cur_arg_strncasecmp ("-FooBar);
+ * will return 7
+ *
+ * Notice: this number will always be > 0
+ *
+ * ------------------------------------------------------------
+ *
+ * Case C: If neither of Case A or B is met (no match)
+ * then -1 is returned
+ */
+ int cur_arg_strncasecmp (const CHAR_TYPE *flag);
+
+ /// Consume @a number argument(s) by sticking them/it on the end of
+ /// the vector.
+ int consume_arg (int number = 1);
+
+ /// Place @a number arguments in the same relative order ahead of the
+ /// known arguments in the vector.
+ int ignore_arg (int number = 1);
+
+ /// Returns the number of args left to see in the vector.
+ int is_anything_left (void) const;
+
+ /// Returns 1 if there's a next item in the vector and it begins with
+ /// '-'.
+ int is_option_next (void) const;
+
+ /// Returns 1 if there's a next item in the vector and it doesn't
+ /// begin with '-'.
+ int is_parameter_next (void) const;
+
+ /// Returns the number of irrelevant args seen.
+ int num_ignored_args (void) const;
+
+private:
+ /// Copy Constructor should not be used.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Arg_Shifter_T (const ACE_Arg_Shifter_T<CHAR_TYPE>&))
+
+ /// Assignment '=' operator should not be used.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Arg_Shifter_T operator= (const ACE_Arg_Shifter_T<CHAR_TYPE>&))
+
+ /// Refactor the constructor logic.
+ void init (void);
+
+ /// The size of the argument vector.
+ int& argc_;
+
+ /// The size of argv_.
+ int total_size_;
+
+ /// The temporary array over which we traverse.
+ const CHAR_TYPE **temp_;
+
+ /// The array in which the arguments are reordered.
+ const CHAR_TYPE **argv_;
+
+ /// The element in <temp_> we're currently examining.
+ int current_index_;
+
+ /// The index of <argv_> in which we'll stick the next unknown
+ /// argument.
+ int back_;
+
+ /// The index of <argv_> in which we'll stick the next known
+ /// argument.
+ int front_;
+};
+
+typedef ACE_Arg_Shifter_T<ACE_TCHAR> ACE_Arg_Shifter;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Arg_Shifter.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Arg_Shifter.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ARG_SHIFTER_H */
diff --git a/ACE/ace/Argv_Type_Converter.cpp b/ACE/ace/Argv_Type_Converter.cpp
new file mode 100644
index 00000000000..e16076818a4
--- /dev/null
+++ b/ACE/ace/Argv_Type_Converter.cpp
@@ -0,0 +1,204 @@
+// $Id$
+
+#include "ace/Argv_Type_Converter.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Argv_Type_Converter.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Argv_Type_Converter,
+ "$Id$")
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_USES_WCHAR)
+ACE_Argv_Type_Converter::ACE_Argv_Type_Converter (int &argc, wchar_t** argv)
+ : saved_argc_ (argc),
+ char_argv_ (0),
+ wchar_argv_ (argv),
+ before_pass_argc_ (argc),
+ original_type_ (true),
+ wchar_passed_ (false),
+ char_passed_ (false)
+{
+ this->initialize ();
+
+ for (int i = 0; i < argc; ++i)
+ this->char_argv_[i] = ACE_OS::strdup (ACE_TEXT_ALWAYS_CHAR (argv[i]));
+}
+#endif // ACE_USES_WCHAR
+
+
+ACE_Argv_Type_Converter::ACE_Argv_Type_Converter (int &argc, char **argv)
+ : saved_argc_(argc),
+ char_argv_(argv)
+#if defined (ACE_USES_WCHAR)
+ , wchar_argv_(0),
+ before_pass_argc_(argc),
+ original_type_(false),
+ wchar_passed_(false),
+ char_passed_(false)
+{
+ this->initialize();
+
+ for (int i = 0; i < argc; ++i)
+ this->wchar_argv_[i] = ACE_OS::strdup (ACE_TEXT_ANTI_TO_TCHAR (argv[i]));
+}
+#else
+{
+}
+#endif // ACE_USES_WCHAR
+
+ACE_Argv_Type_Converter::~ACE_Argv_Type_Converter (void)
+{
+#if defined (ACE_USES_WCHAR)
+ // selectively delete the 'copy' of argv
+ if (this->original_type_)
+ {
+ // if original type is wchar_t
+ if (this->char_passed_)
+ this->align_wchar_with_char ();
+
+ for (int i = 0; i < this->before_pass_argc_; ++i)
+ ACE_OS::free (this->char_argv_[i]);
+
+ delete [] this->char_argv_;
+ }
+ else
+ {
+ // if original type is char
+ if (this->wchar_passed_)
+ this->align_char_with_wchar ();
+
+ for (int i = 0; i < this->before_pass_argc_; ++i)
+ ACE_OS::free (this->wchar_argv_[i]);
+
+ delete [] this->wchar_argv_;
+ }
+#endif // ACE_USES_WCHAR
+}
+
+#if defined (ACE_USES_WCHAR)
+void
+ACE_Argv_Type_Converter::initialize (void)
+{
+ if (this->original_type_)
+ {
+ // Make a copy of argv in 'char'. type Create one more argv entry
+ // than original argc for the NULL.
+ ACE_NEW (char_argv_,
+ char *[this->saved_argc_ + 1]);
+ this->char_argv_[saved_argc_] = 0; // last entry of argv is
+ // always a NULL
+ }
+ else
+ {
+ // make a copy of argv in 'wchar_t' type
+ ACE_NEW (this->wchar_argv_,
+ wchar_t*[this->saved_argc_ + 1]);
+ this->wchar_argv_[saved_argc_] = 0;
+ }
+}
+
+
+void
+ACE_Argv_Type_Converter::align_char_with_wchar (void)
+{
+ int wchar_argv_index = 0;
+ wchar_t* match_argv = this->wchar_argv_[0]; // pick the initial entry
+
+ while (wchar_argv_index < this->saved_argc_)
+ {
+ // if n'th entries of both argv lists are different
+ if (ACE_OS::strcmp (this->char_argv_[wchar_argv_index],
+ ACE_TEXT_ALWAYS_CHAR (match_argv)) != 0)
+ {
+ // loop through the wchar argv list entries that are after
+ // wchar_argv_index
+ for (int i = wchar_argv_index + 1; i < before_pass_argc_; ++i)
+ {
+ if (ACE_OS::strcmp (this->char_argv_[i],
+ ACE_TEXT_ALWAYS_CHAR (match_argv)) == 0)
+ {
+ // swap the pointers in the char argv list
+ char *temp = this->char_argv_[wchar_argv_index];
+ this->char_argv_[wchar_argv_index] = this->char_argv_[i];
+ this->char_argv_[i] = temp;
+ break;
+ }
+ }
+ }
+
+ // move to the next wchar argv list entry
+ match_argv = this->wchar_argv_[++wchar_argv_index];
+ }
+
+ this->cleanup ();
+}
+
+void
+ACE_Argv_Type_Converter::align_wchar_with_char (void)
+{
+ int char_argv_index = 0;
+ char* match_argv = this->char_argv_[0]; // pick the initial entry
+
+ while (char_argv_index < saved_argc_)
+ {
+ // if n'th entries of both argv lists are different
+ if (ACE_OS::strcmp (
+ ACE_TEXT_ALWAYS_CHAR (this->wchar_argv_[char_argv_index]),
+ match_argv) != 0)
+ {
+ // loop through the wchar argv list entries that are after
+ // wchar_argv_index
+ for (int i = char_argv_index + 1; i < this->before_pass_argc_; ++i)
+ {
+ if (ACE_OS::strcmp (
+ ACE_TEXT_ALWAYS_CHAR(this->wchar_argv_[i]),
+ match_argv) == 0) {
+ // swap the pointers in the char argv list
+ wchar_t* temp = this->wchar_argv_[char_argv_index];
+ this->wchar_argv_[char_argv_index] = this->wchar_argv_[i];
+ this->wchar_argv_[i] = temp;
+ break;
+ }
+ }
+ }
+
+ // move to the next wchar argv list entry
+ match_argv = this->char_argv_[++char_argv_index];
+ }
+
+ this->cleanup();
+}
+
+void
+ACE_Argv_Type_Converter::cleanup (void)
+{
+ for (int i = this->saved_argc_; i < this->before_pass_argc_; ++i)
+ {
+ // Check whether it's ours to delete.
+ if (original_type_)
+ {
+ ACE_OS::free (this->char_argv_[i]);
+ this->char_argv_[i] = 0;
+ }
+ else
+ {
+ ACE_OS::free (this->wchar_argv_[i]);
+ this->wchar_argv_[i] = 0;
+ }
+ }
+
+ this->before_pass_argc_ = this->saved_argc_;
+
+ this->wchar_passed_ = false;
+ this->char_passed_ = false;
+}
+#endif // ACE_USES_WCHAR
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Argv_Type_Converter.h b/ACE/ace/Argv_Type_Converter.h
new file mode 100644
index 00000000000..205fa10c983
--- /dev/null
+++ b/ACE/ace/Argv_Type_Converter.h
@@ -0,0 +1,119 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Argv_Type_Converter.h
+ *
+ * $Id$
+ *
+ * @author Si Mong Park <spark@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef ACE_ARGV_TYPE_CONVERTER_H
+#define ACE_ARGV_TYPE_CONVERTER_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/OS_Memory.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Argv_Type_Converter
+ *
+ * @brief To convert 'char' input/command line parameter to 'wchar_t'.
+ *
+ * This class is to convert 'char' type command line paramter to
+ * wide-character (wchar_t) format and stores the copy of it.
+ * This is useful for all classes that use 'char**' argv but cannot
+ * be converted into 'ACE_TCHAR**' version.
+ * Note that the converted data will be lost upon destruction, so
+ * classes should use this class as their data member.
+ */
+class ACE_Export ACE_Argv_Type_Converter
+{
+public:
+
+ ACE_Argv_Type_Converter (int &argc, char** argv);
+
+#if defined (ACE_USES_WCHAR)
+ ACE_Argv_Type_Converter (int &argc, wchar_t** argv);
+#endif // ACE_USES_WCHAR
+
+ ~ACE_Argv_Type_Converter (void);
+
+ /// Returns the pointer of converted command line.
+ ACE_TCHAR** get_TCHAR_argv (void);
+
+ /// Returns the pointer of ASCII (char) command line.
+ char** get_ASCII_argv (void);
+
+ /// Returns the number of sub paramters (argc).
+ int& get_argc (void);
+
+private:
+
+ /// Copy Constructor should not be used.
+ ACE_Argv_Type_Converter (const ACE_Argv_Type_Converter&);
+
+ /// Assignment '=' operator should not be used.
+ ACE_Argv_Type_Converter operator= (const ACE_Argv_Type_Converter&);
+
+#if defined (ACE_USES_WCHAR)
+
+ /// Perform common initialization for two Ctor's.
+ void initialize (void);
+
+ /// Align all entries in the char type argv list with wchar_t type
+ /// argv list.
+ void align_char_with_wchar (void);
+
+ /// Align all entries in the wchar_t type argv list with char type
+ /// argv list.
+ void align_wchar_with_char (void);
+
+ /// Clean up removed (comsumed) argv entries and reset the pass flags.
+ void cleanup (void);
+#endif // ACE_USES_WCHAR
+
+private:
+ /// Original number of input paramter, same as 'argc'.
+ int &saved_argc_;
+
+ /// Data member pointer that contains converted argv in ACE_ANTI_TCHAR.
+ char** char_argv_;
+
+#if defined (ACE_USES_WCHAR)
+ /// Data member pointer that contains converted argv in ACE_TCHAR.
+ wchar_t** wchar_argv_;
+
+ /// argc value before any argv has been passed.
+ int before_pass_argc_;
+
+ /// false represents original argv passed in is char, and true
+ /// represents wchar_t.
+ bool const original_type_;
+
+ /// true indicates wchar_t type argv has been passed.
+ bool wchar_passed_;
+
+ /// true indicates char type argv has been passed.
+ bool char_passed_;
+#endif /* ACE_USES_WCHAR */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Argv_Type_Converter.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ARGV_TYPE_CONVERTER_H */
diff --git a/ACE/ace/Argv_Type_Converter.inl b/ACE/ace/Argv_Type_Converter.inl
new file mode 100644
index 00000000000..5bb0bafd2db
--- /dev/null
+++ b/ACE/ace/Argv_Type_Converter.inl
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_TCHAR**
+ACE_Argv_Type_Converter::get_TCHAR_argv (void)
+{
+#if defined (ACE_USES_WCHAR)
+ if (this->char_passed_)
+ {
+ this->align_wchar_with_char ();
+ }
+
+ this->wchar_passed_ = true;
+ return this->wchar_argv_;
+#else
+ return this->char_argv_;
+#endif // ACE_USES_WCHAR
+}
+
+ACE_INLINE char**
+ACE_Argv_Type_Converter::get_ASCII_argv (void)
+{
+#if defined (ACE_USES_WCHAR)
+ if (this->wchar_passed_)
+ {
+ this->align_char_with_wchar ();
+ }
+
+ this->char_passed_ = true;
+#endif // ACE_USES_WCHAR
+
+ return this->char_argv_;
+}
+
+ACE_INLINE int&
+ACE_Argv_Type_Converter::get_argc (void)
+{
+ return this->saved_argc_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Array.h b/ACE/ace/Array.h
new file mode 100644
index 00000000000..c3159cd7a89
--- /dev/null
+++ b/ACE/ace/Array.h
@@ -0,0 +1,29 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Array.h
+ *
+ * $Id$
+ *
+ * @deprecated
+ *
+ * @note This file has been deprecated and will soon go away. You
+ * should directly include "Containers_T.h" instead.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ARRAY_H
+#define ACE_ARRAY_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Containers_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_ARRAY_H */
diff --git a/ACE/ace/Array_Base.cpp b/ACE/ace/Array_Base.cpp
new file mode 100644
index 00000000000..280a12d8e17
--- /dev/null
+++ b/ACE/ace/Array_Base.cpp
@@ -0,0 +1,235 @@
+// $Id$
+
+#ifndef ACE_ARRAY_BASE_CPP
+#define ACE_ARRAY_BASE_CPP
+
+#include "ace/Array_Base.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Array_Base.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Malloc_Base.h"
+#include "ace/os_include/os_errno.h"
+
+#include <algorithm>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Dynamically initialize an array.
+template <class T>
+ACE_Array_Base<T>::ACE_Array_Base (typename ACE_Array_Base<T>::size_type size,
+ ACE_Allocator *alloc)
+ : max_size_ (size),
+ cur_size_ (size),
+ allocator_ (alloc)
+{
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ if (size != 0)
+ {
+ ACE_ALLOCATOR (this->array_,
+ (T *) this->allocator_->malloc (size * sizeof (T)));
+ for (size_type i = 0; i < size; ++i)
+ new (&array_[i]) T;
+ }
+ else
+ this->array_ = 0;
+}
+
+template <class T>
+ACE_Array_Base<T>::ACE_Array_Base (typename ACE_Array_Base<T>::size_type size,
+ const T &default_value,
+ ACE_Allocator *alloc)
+ : max_size_ (size),
+ cur_size_ (size),
+ allocator_ (alloc)
+{
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ if (size != 0)
+ {
+ ACE_ALLOCATOR (this->array_,
+ (T *) this->allocator_->malloc (size * sizeof (T)));
+ for (size_type i = 0; i < size; ++i)
+ new (&array_[i]) T (default_value);
+ }
+ else
+ this->array_ = 0;
+}
+
+// The copy constructor (performs initialization).
+
+template <class T>
+ACE_Array_Base<T>::ACE_Array_Base (const ACE_Array_Base<T> &s)
+ : max_size_ (s.size ()),
+ cur_size_ (s.size ()),
+ allocator_ (s.allocator_)
+{
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_ALLOCATOR (this->array_,
+ (T *) this->allocator_->malloc (s.size () * sizeof (T)));
+ for (size_type i = 0; i < this->size (); ++i)
+ new (&this->array_[i]) T (s.array_[i]);
+}
+
+// Assignment operator (performs assignment).
+
+template <class T> void
+ACE_Array_Base<T>::operator= (const ACE_Array_Base<T> &s)
+{
+ // Check for "self-assignment".
+
+ if (this != &s)
+ {
+ if (this->max_size_ < s.size ())
+ {
+ // Need to reallocate memory.
+
+ // Strongly exception-safe assignment.
+ //
+ // Note that we're swapping the allocators here, too.
+ // Should we? Probably. "*this" should be a duplicate of
+ // the "right hand side".
+ ACE_Array_Base<T> tmp (s);
+ this->swap (tmp);
+ }
+ else
+ {
+ // Underlying array is large enough. No need to reallocate
+ // memory.
+ //
+ // "*this" still owns the memory for the underlying array.
+ // Do not swap out the allocator.
+ //
+ // @@ Why don't we just drop the explicit destructor and
+ // placement operator new() calls with a straight
+ // element-by-element assignment? Is the existing
+ // approach more efficient?
+ // -Ossama
+
+ ACE_DES_ARRAY_NOFREE (this->array_,
+ s.size (),
+ T);
+
+ this->cur_size_ = s.size ();
+
+ for (size_type i = 0; i < this->size (); ++i)
+ new (&this->array_[i]) T (s.array_[i]);
+ }
+ }
+}
+
+// Set an item in the array at location slot.
+
+template <class T> int
+ACE_Array_Base<T>::set (const T &new_item,
+ typename ACE_Array_Base<T>::size_type slot)
+{
+ if (this->in_range (slot))
+ {
+ this->array_[slot] = new_item;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+// Get an item in the array at location slot.
+
+template <class T> int
+ACE_Array_Base<T>::get (T &item,
+ typename ACE_Array_Base<T>::size_type slot) const
+{
+ if (this->in_range (slot))
+ {
+ // Copies the item. If you don't want to copy, use operator []
+ // instead (but then you'll be responsible for range checking).
+ item = this->array_[slot];
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template<class T> int
+ACE_Array_Base<T>::max_size (typename ACE_Array_Base<T>::size_type new_size)
+{
+ if (new_size > this->max_size_)
+ {
+ T *tmp = 0;
+
+ ACE_ALLOCATOR_RETURN (tmp,
+ (T *) this->allocator_->malloc (new_size * sizeof (T)),
+ -1);
+ for (size_type i = 0; i < this->cur_size_; ++i)
+ new (&tmp[i]) T (this->array_[i]);
+
+ // Initialize the new portion of the array that exceeds the
+ // previously allocated section.
+ for (size_type j = this->cur_size_; j < new_size; ++j)
+ new (&tmp[j]) T;
+
+ ACE_DES_ARRAY_FREE (this->array_,
+ this->max_size_,
+ this->allocator_->free,
+ T);
+ this->array_ = tmp;
+ this->max_size_ = new_size;
+ this->cur_size_ = new_size;
+ }
+
+ return 0;
+}
+
+template<class T> int
+ACE_Array_Base<T>::size (typename ACE_Array_Base<T>::size_type new_size)
+{
+ int const r = this->max_size (new_size);
+
+ if (r == 0)
+ this->cur_size_ = new_size;
+
+ return r;
+}
+
+template<class T>
+void
+ACE_Array_Base<T>::swap (ACE_Array_Base<T> & rhs)
+{
+ std::swap (this->max_size_ , rhs.max_size_);
+ std::swap (this->cur_size_ , rhs.cur_size_);
+ std::swap (this->array_ , rhs.array_);
+ std::swap (this->allocator_, rhs.allocator_);
+}
+
+// ****************************************************************
+
+template <class T> int
+ACE_Array_Iterator<T>::next (T *&item)
+{
+ // ACE_TRACE ("ACE_Array_Iterator<T>::next");
+
+ if (this->done ())
+ {
+ item = 0;
+ return 0;
+ }
+ else
+ {
+ item = &array_[current_];
+ return 1;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_ARRAY_BASE_CPP */
diff --git a/ACE/ace/Array_Base.h b/ACE/ace/Array_Base.h
new file mode 100644
index 00000000000..210bab6d46d
--- /dev/null
+++ b/ACE/ace/Array_Base.h
@@ -0,0 +1,256 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Array_Base.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ARRAY_BASE_H
+#define ACE_ARRAY_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/Global_Macros.h"
+#include "ace/Malloc_Base.h"
+#include <iterator> /* For reverse_iterator adapters */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration.
+template <class T> class ACE_Array_Iterator;
+
+/**
+ * @class ACE_Array_Base
+ *
+ * @brief Implement a simple dynamic array
+ *
+ * This parametric class implements a simple dynamic array;
+ * resizing must be controlled by the user. No comparison or find
+ * operations are implemented.
+ */
+template<class T>
+class ACE_Array_Base
+{
+public:
+
+ // Old/ACE-style traits.
+ typedef T TYPE;
+ typedef ACE_Array_Iterator<T> ITERATOR;
+
+ // STL-style typedefs/traits.
+ typedef T value_type;
+ typedef value_type * iterator;
+ typedef value_type const * const_iterator;
+ typedef value_type & reference;
+ typedef value_type const & const_reference;
+ typedef value_type * pointer;
+ typedef value_type const * const_pointer;
+ typedef ptrdiff_t difference_type;
+ typedef ACE_Allocator::size_type size_type;
+
+ ACE_DECLARE_STL_REVERSE_ITERATORS
+
+ // = Initialization and termination methods.
+
+ /// Dynamically create an uninitialized array.
+ ACE_Array_Base (size_type size = 0,
+ ACE_Allocator * the_allocator = 0);
+
+ /// Dynamically initialize the entire array to the <default_value>.
+ ACE_Array_Base (size_type size,
+ T const & default_value,
+ ACE_Allocator * the_allocator = 0);
+
+ /**
+ * The copy constructor performs initialization by making an exact
+ * copy of the contents of parameter <s>, i.e., *this == s will
+ * return true.
+ */
+ ACE_Array_Base (ACE_Array_Base<T> const & s);
+
+ /**
+ * Assignment operator performs an assignment by making an exact
+ * copy of the contents of parameter <s>, i.e., *this == s will
+ * return true. Note that if the <max_size_> of <array_> is >= than
+ * <s.max_size_> we can copy it without reallocating. However, if
+ * <max_size_> is < <s.max_size_> we must delete the <array_>,
+ * reallocate a new <array_>, and then copy the contents of <s>.
+ */
+ void operator= (ACE_Array_Base<T> const & s);
+
+ /// Clean up the array (e.g., delete dynamically allocated memory).
+ ~ACE_Array_Base (void);
+
+ // = Set/get methods.
+
+ /// Set item in the array at location @a slot. Doesn't
+ /// perform range checking.
+ T & operator[] (size_type slot);
+
+ /// Get item in the array at location @a slot. Doesn't
+ /// perform range checking.
+ T const & operator[] (size_type slot) const;
+
+ /// Set an item in the array at location @a slot. Returns
+ /// -1 if @a slot is not in range, else returns 0.
+ int set (T const & new_item, size_type slot);
+
+ /**
+ * Get an item in the array at location @a slot. Returns -1 if
+ * @a slot is not in range, else returns 0. Note that this function
+ * copies the item. If you want to avoid the copy, you can use
+ * the const operator [], but then you'll be responsible for range checking.
+ */
+ int get (T & item, size_type slot) const;
+
+ /// Returns the <cur_size_> of the array.
+ size_type size (void) const;
+
+ /**
+ * Changes the size of the array to match <new_size>.
+ * It copies the old contents into the new array.
+ * Return -1 on failure.
+ */
+ int size (size_type new_size);
+
+ /// Returns the <max_size_> of the array.
+ size_type max_size (void) const;
+
+ /**
+ * Changes the size of the array to match <new_size>.
+ * It copies the old contents into the new array.
+ * Return -1 on failure.
+ * It does not affect new_size
+ */
+ int max_size (size_type new_size);
+
+ /**
+ * @name Forward Iterator Accessors
+ *
+ * Forward iterator accessors.
+ */
+ //@{
+ iterator begin (void);
+ iterator end (void);
+ const_iterator begin (void) const;
+ const_iterator end (void) const;
+ //@}
+
+ /**
+ * @name Reverse Iterator Accessors
+ *
+ * Reverse iterator accessors.
+ */
+ //@{
+ reverse_iterator rbegin (void);
+ reverse_iterator rend (void);
+ const_reverse_iterator rbegin (void) const;
+ const_reverse_iterator rend (void) const;
+ //@}
+
+ /// Swap the contents of this array with the given @a array in
+ /// an exception-safe manner.
+ void swap (ACE_Array_Base<T> & array);
+
+protected:
+
+ /// Returns 1 if @a slot is within range, i.e., 0 >= @a slot <
+ /// <cur_size_>, else returns 0.
+ bool in_range (size_type slot) const;
+
+ /// Maximum size of the array, i.e., the total number of <T> elements
+ /// in <array_>.
+ size_type max_size_;
+
+ /**
+ * Current size of the array. This starts out being == to
+ * <max_size_>. However, if we are assigned a smaller array, then
+ * <cur_size_> will become less than <max_size_>. The purpose of
+ * keeping track of both sizes is to avoid reallocating memory if we
+ * don't have to.
+ */
+ size_type cur_size_;
+
+ /// Pointer to the array's storage buffer.
+ value_type * array_;
+
+ /// Allocation strategy of the ACE_Array_Base.
+ ACE_Allocator * allocator_;
+
+ friend class ACE_Array_Iterator<T>;
+};
+
+// ****************************************************************
+
+/**
+ * @class ACE_Array_Iterator
+ *
+ * @brief Implement an iterator over an ACE_Array.
+ *
+ * This iterator is safe in the face of array element deletions.
+ * But it is NOT safe if the array is resized (via the ACE_Array
+ * assignment operator) during iteration. That would be very
+ * odd, and dangerous.
+ */
+template <class T>
+class ACE_Array_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Array_Iterator (ACE_Array_Base<T> &);
+
+ // = Iteration methods.
+
+ /// Pass back the <next_item> that hasn't been seen in the Array.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (T *&next_item);
+
+ /// Move forward by one element in the Array. Returns 0 when all the
+ /// items in the Array have been seen, else 1.
+ int advance (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to the current item in the iteration.
+ size_t current_;
+
+ /// Pointer to the Array we're iterating over.
+ ACE_Array_Base<T> &array_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Array_Base.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Array_Base.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Array_Base.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ARRAY_BASE_H */
diff --git a/ACE/ace/Array_Base.inl b/ACE/ace/Array_Base.inl
new file mode 100644
index 00000000000..849bcc18de2
--- /dev/null
+++ b/ACE/ace/Array_Base.inl
@@ -0,0 +1,146 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Clean up the array (e.g., delete dynamically allocated memory).
+template <class T> ACE_INLINE
+ACE_Array_Base<T>::~ACE_Array_Base (void)
+{
+ ACE_DES_ARRAY_FREE (this->array_,
+ this->max_size_,
+ this->allocator_->free,
+ T);
+}
+
+template <class T>
+ACE_INLINE typename ACE_Array_Base<T>::iterator
+ACE_Array_Base<T>::begin (void)
+{
+ return this->array_;
+}
+
+template <class T>
+ACE_INLINE typename ACE_Array_Base<T>::iterator
+ACE_Array_Base<T>::end (void)
+{
+ return this->array_ + this->cur_size_;
+}
+
+template <class T>
+ACE_INLINE typename ACE_Array_Base<T>::const_iterator
+ACE_Array_Base<T>::begin (void) const
+{
+ return this->array_;
+}
+
+template <class T>
+ACE_INLINE typename ACE_Array_Base<T>::const_iterator
+ACE_Array_Base<T>::end (void) const
+{
+ return this->array_ + this->cur_size_;
+}
+
+template <class T>
+ACE_INLINE typename ACE_Array_Base<T>::reverse_iterator
+ACE_Array_Base<T>::rbegin (void)
+{
+ return reverse_iterator (this->end ());
+}
+
+template <class T>
+ACE_INLINE typename ACE_Array_Base<T>::reverse_iterator
+ACE_Array_Base<T>::rend (void)
+{
+ return reverse_iterator (this->begin ());
+}
+
+template <class T>
+ACE_INLINE typename ACE_Array_Base<T>::const_reverse_iterator
+ACE_Array_Base<T>::rbegin (void) const
+{
+ return const_reverse_iterator (this->end ());
+}
+
+template <class T>
+ACE_INLINE typename ACE_Array_Base<T>::const_reverse_iterator
+ACE_Array_Base<T>::rend (void) const
+{
+ return const_reverse_iterator (this->begin ());
+}
+
+template <class T> ACE_INLINE typename ACE_Array_Base<T>::size_type
+ACE_Array_Base<T>::size (void) const
+{
+ return this->cur_size_;
+}
+
+template <class T> ACE_INLINE typename ACE_Array_Base<T>::size_type
+ACE_Array_Base<T>::max_size (void) const
+{
+ return this->max_size_;
+}
+
+template <class T> ACE_INLINE bool
+ACE_Array_Base<T>::in_range (typename ACE_Array_Base<T>::size_type index) const
+{
+ return index < this->cur_size_;
+}
+
+template <class T> ACE_INLINE T &
+ACE_Array_Base<T>::operator[] (typename ACE_Array_Base<T>::size_type index)
+{
+ return this->array_[index];
+}
+
+template <class T> ACE_INLINE const T &
+ACE_Array_Base<T>::operator[] (typename ACE_Array_Base<T>::size_type index) const
+{
+ return this->array_[index];
+}
+
+// ****************************************************************
+
+template <class T> ACE_INLINE void
+ACE_Array_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Array_Iterator<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T> ACE_INLINE
+ACE_Array_Iterator<T>::ACE_Array_Iterator (ACE_Array_Base<T> &a)
+ : current_ (0),
+ array_ (a)
+{
+ // ACE_TRACE ("ACE_Array_Iterator<T>::ACE_Array_Iterator");
+}
+
+template <class T> ACE_INLINE int
+ACE_Array_Iterator<T>::advance (void)
+{
+ // ACE_TRACE ("ACE_Array_Iterator<T>::advance");
+
+ if (this->current_ < array_.size ())
+ {
+ ++this->current_;
+ return 1;
+ }
+ else
+ {
+ // Already finished iterating.
+ return 0;
+ }
+}
+
+template <class T> ACE_INLINE int
+ACE_Array_Iterator<T>::done (void) const
+{
+ ACE_TRACE ("ACE_Array_Iterator<T>::done");
+
+ return this->current_ >= array_.size ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Array_Map.cpp b/ACE/ace/Array_Map.cpp
new file mode 100644
index 00000000000..62c6f553292
--- /dev/null
+++ b/ACE/ace/Array_Map.cpp
@@ -0,0 +1,299 @@
+// $Id$
+
+#ifndef ACE_ARRAY_MAP_CPP
+#define ACE_ARRAY_MAP_CPP
+
+#include "ace/Array_Map.h"
+
+#ifndef __ACE_INLINE__
+# include "ace/Array_Map.inl"
+#endif /* !__ACE_INLINE__ */
+
+#include "ace/checked_iterator.h"
+
+#include <algorithm>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#ifndef ACE_LACKS_MEMBER_TEMPLATES
+template<typename Key, typename Value, class EqualTo>
+template<typename InputIterator>
+ACE_Array_Map<Key, Value, EqualTo>::ACE_Array_Map (InputIterator f,
+ InputIterator l)
+ : size_ (l - f)
+ , capacity_ (size_)
+ , nodes_ (size_ == 0 ? 0 : new value_type[size_])
+{
+ (void) std::copy (f,
+ l,
+ ACE_make_checked_array_iterator (this->begin (),
+ this->size_));
+
+// iterator n = this->begin ();
+
+// for (InputIterator i = f; i != l; ++i, ++n)
+// *n = *i;
+}
+#else
+template<typename Key, typename Value, class EqualTo>
+ACE_Array_Map<Key, Value, EqualTo>::ACE_Array_Map (
+ typename ACE_Array_Map<Key, Value, EqualTo>::const_iterator f,
+ typename ACE_Array_Map<Key, Value, EqualTo>::const_iterator l)
+ : size_ (l - f)
+ , capacity_ (size_)
+ , nodes_ (size_ == 0 ? 0 : new value_type[size_])
+{
+ (void) std::copy (f,
+ l,
+ ACE_make_checked_array_iterator (this->begin (),
+ this->size_));
+
+// iterator n = this->begin ();
+
+// for (const_iterator i = f; i != l; ++i, ++n)
+// *n = *i;
+}
+#endif /* !ACE_LACKS_MEMBER_TEMPLATES */
+
+template<typename Key, typename Value, class EqualTo>
+ACE_Array_Map<Key, Value, EqualTo>::ACE_Array_Map (
+ ACE_Array_Map<Key, Value, EqualTo> const & map)
+ : size_ (map.size_)
+ , capacity_ (map.size_)
+ , nodes_ (size_ == 0 ? 0 : new value_type[size_])
+{
+ std::copy (map.begin (),
+ map.end (),
+ ACE_make_checked_array_iterator (this->begin (),
+ this->size_));
+
+// iterator f = map.begin ();
+// iterator l = map.end ();
+// iterator n = this->begin ();
+
+// for (iterator i = f; i != l; ++i, ++n)
+// *n = *i;
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_Array_Map<Key, Value, EqualTo>::~ACE_Array_Map (void)
+{
+ delete[] this->nodes_;
+}
+
+template<typename Key, typename Value, class EqualTo>
+void
+ACE_Array_Map<Key, Value, EqualTo>::swap (
+ ACE_Array_Map<Key, Value, EqualTo> & map)
+{
+ std::swap (this->size_, map.size_);
+ std::swap (this->capacity_, map.capacity_);
+ std::swap (this->nodes_, map.nodes_);
+}
+
+template<typename Key, typename Value, class EqualTo>
+std::pair<typename ACE_Array_Map<Key, Value, EqualTo>::iterator, bool>
+ACE_Array_Map<Key, Value, EqualTo>::insert (
+ typename ACE_Array_Map<Key, Value, EqualTo>::value_type const & x)
+{
+ // Linear insertion due to linear duplicate key search.
+
+ bool inserted = false;
+ iterator i = this->find (x.first);
+
+ if (i == this->end ())
+ {
+ // Add the element to the array.
+
+ size_type const old_size = this->size ();
+ this->grow (1); // Increase size by at least one.
+
+ i = this->begin () + old_size;
+ *i = x;
+
+ ++this->size_;
+
+ inserted = true;
+ }
+
+ return std::make_pair (i, inserted);
+}
+
+#ifndef ACE_LACKS_MEMBER_TEMPLATES
+template<typename Key, typename Value, class EqualTo>
+template<typename InputIterator>
+void
+ACE_Array_Map<Key, Value, EqualTo>::insert (InputIterator f, InputIterator l)
+{
+ this->grow (l - f); // Preallocate storage.
+
+ for (InputIterator i = f; i != l; ++i)
+ {
+ (void) this->insert (*i);
+ }
+}
+#else
+template<typename Key, typename Value, class EqualTo>
+void
+ACE_Array_Map<Key, Value, EqualTo>::insert (
+ typename ACE_Array_Map<Key, Value, EqualTo>::const_iterator f,
+ typename ACE_Array_Map<Key, Value, EqualTo>::const_iterator l)
+{
+ this->grow (l - f); // Preallocate storage.
+
+ for (const_iterator i = f; i != l; ++i)
+ {
+ (void) this->insert (*i);
+ }
+}
+#endif /* ACE_LACKS_MEMBER_TEMPLATES */
+
+template<typename Key, typename Value, class EqualTo>
+void
+ACE_Array_Map<Key, Value, EqualTo>::erase (
+ typename ACE_Array_Map<Key, Value, EqualTo>::iterator pos)
+{
+ iterator const first = this->begin ();
+ iterator const last = this->end ();
+
+ if (pos >= first && pos < last)
+ {
+ if (pos != last - 1)
+ {
+ // Relocate the tail element to the location of the erased
+ // element to prevent introduction of "holes" in the
+ // underlying array.
+ *pos = *(last - 1);
+ }
+
+ // Explicitly destroy the tail element by assigning a default
+ // constructed instance to it. Note that this also works for
+ // the case of a map of size 1.
+ *(last - 1) = value_type ();
+
+ --this->size_;
+ }
+}
+
+template<typename Key, typename Value, class EqualTo>
+typename ACE_Array_Map<Key, Value, EqualTo>::size_type
+ACE_Array_Map<Key, Value, EqualTo>::erase (
+ typename ACE_Array_Map<Key, Value, EqualTo>::key_type const & k)
+{
+ iterator pos = this->find (k);
+
+ size_type const old_size = this->size_;
+
+ this->erase (pos);
+
+ return old_size - this->size_;
+}
+
+template<typename Key, typename Value, class EqualTo>
+void
+ACE_Array_Map<Key, Value, EqualTo>::erase (
+ typename ACE_Array_Map<Key, Value, EqualTo>::iterator first,
+ typename ACE_Array_Map<Key, Value, EqualTo>::iterator last)
+{
+ if (this->begin () <= first && first < last && last < this->end ())
+ for (iterator i = first; i != last; ++i)
+ this->erase (i);
+}
+
+template<typename Key, typename Value, class EqualTo>
+void
+ACE_Array_Map<Key, Value, EqualTo>::clear (void)
+{
+ this->size_ = 0; // No need to deallocate array nor destroy elements.
+}
+
+template<typename Key, typename Value, class EqualTo>
+typename ACE_Array_Map<Key, Value, EqualTo>::iterator
+ACE_Array_Map<Key, Value, EqualTo>::find (
+ typename ACE_Array_Map<Key, Value, EqualTo>::key_type const & k)
+{
+ iterator const the_end = this->end ();
+
+ EqualTo eq;
+
+ for (iterator i = this->begin (); i != the_end; ++i)
+ if (eq (k, i->first))
+ return i;
+
+ return this->end ();
+}
+
+template<typename Key, typename Value, class EqualTo>
+typename ACE_Array_Map<Key, Value, EqualTo>::const_iterator
+ACE_Array_Map<Key, Value, EqualTo>::find (
+ typename ACE_Array_Map<Key, Value, EqualTo>::key_type const & k) const
+{
+ const_iterator const the_end = this->end ();
+
+ EqualTo eq;
+
+ for (const_iterator i = this->begin (); i != the_end; ++i)
+ if (eq (k, i->first))
+ return i;
+
+ return this->end ();
+}
+
+template<typename Key, typename Value, class EqualTo>
+void
+ACE_Array_Map<Key, Value, EqualTo>::grow (
+ typename ACE_Array_Map<Key, Value, EqualTo>::size_type s)
+{
+ if (this->size () + s > this->capacity_)
+ {
+ // This implementation focuses more on static footprint than
+ // speed.
+
+ // Strongly exception safe.
+
+ ACE_Array_Map<Key, Value, EqualTo> temp (this->size () + s);
+
+ std::copy (this->begin (),
+ this->end (),
+ ACE_make_checked_array_iterator (temp.begin (),
+ temp.capacity_));
+
+ size_type const n = this->size (); // Do not swap out the size
+ // since we bypassed the
+ // temporary map's element
+ // counting code.
+ this->swap (temp);
+
+ this->size_ = n;
+ }
+}
+
+// ---------------------------------------------------------------
+
+template <typename Key, typename Value, class EqualTo>
+bool
+operator== (ACE_Array_Map<Key, Value, EqualTo> const & lhs,
+ ACE_Array_Map<Key, Value, EqualTo> const & rhs)
+{
+ // Do not include Array_Map capacity in comparison. It isn't useful
+ // in this case.
+
+ return (lhs.size () == rhs.size ()
+ && std::equal (lhs.begin (),
+ lhs.end (),
+ ACE_make_checked_array_iterator (rhs.begin (),
+ rhs.size ())));
+}
+
+template <typename Key, typename Value, class EqualTo>
+bool
+operator< (ACE_Array_Map<Key, Value, EqualTo> const & lhs,
+ ACE_Array_Map<Key, Value, EqualTo> const & rhs)
+{
+ return std::lexicographical_compare (lhs.begin (), lhs.end (),
+ rhs.begin (), rhs.end ());
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_ARRAY_MAP_CPP */
diff --git a/ACE/ace/Array_Map.h b/ACE/ace/Array_Map.h
new file mode 100644
index 00000000000..cd0ae3efea6
--- /dev/null
+++ b/ACE/ace/Array_Map.h
@@ -0,0 +1,300 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Array_Map.h
+ *
+ * $Id$
+ *
+ * Light weight array-based map with fast iteration but linear
+ * (i.e. O(n)) search times. STL-style interface is exposed.
+ *
+ * @note This class requires the STL generic algorithms and
+ * reverse_iterator adapter.
+ *
+ * @author Ossama Othman
+ */
+//=============================================================================
+
+
+#ifndef ACE_ARRAY_MAP_H
+#define ACE_ARRAY_MAP_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include <utility>
+#include <iterator>
+#include <functional>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Array_Map
+ *
+ * @brief Light weight array-based map with fast iteration, but linear
+ * (i.e. O(n)) search times.
+ *
+ * Map implementation that focuses on small footprint and fast
+ * iteration. Search times are, however, linear (O(n)) meaning that
+ * this map isn't suitable for large data sets that will be searched
+ * in performance critical areas of code. Iteration over large data
+ * sets, however, is faster than linked list-based maps, for example,
+ * since spatial locality is maximized through the use of contiguous
+ * arrays as the underlying storage.
+ * @par
+ * An @c ACE_Array_Map is a unique associative container, meaning that
+ * duplicate values may not be added to the map. It is also pair
+ * associative (value_type is a std::pair<>). It is not a sorted
+ * container.
+ * @par
+ * An STL @c std::map -like interface is exposed by this class
+ * portability. Furthermore, this map's iterators are compatible with
+ * STL algorithms.
+ * @par
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Array
+ * - Duplicates allowed?
+ * No
+ * - Random access allowed?
+ * Yes
+ * - Search speed
+ * O(n)
+ * - Insert/replace speed
+ * O(n), can be longer if the map has to resize
+ * - Iterator still valid after change to container?
+ * No
+ * - Frees memory for removed elements?
+ * Yes
+ * - Items inserted by
+ * Value
+ * - Requirements for key type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator==
+ * - Requirements for object type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ */
+template<typename Key, typename Value, class EqualTo = std::equal_to<Key> >
+class ACE_Array_Map
+{
+public:
+
+ // STL-style typedefs/traits.
+ typedef Key key_type;
+ typedef Value data_type;
+ typedef std::pair<key_type, data_type> value_type;
+ typedef value_type * iterator;
+ typedef value_type const * const_iterator;
+ typedef value_type & reference;
+ typedef value_type const & const_reference;
+ typedef value_type * pointer;
+ typedef value_type const * const_pointer;
+ typedef ptrdiff_t difference_type;
+ typedef size_t size_type;
+
+ ACE_DECLARE_STL_REVERSE_ITERATORS
+
+ /// Default Constructor.
+ /**
+ * Create an empty map with a preallocated buffer of size @a s.
+ */
+ ACE_Array_Map (size_type s = 0);
+
+#ifndef ACE_LACKS_MEMBER_TEMPLATES
+ template<typename InputIterator>
+ ACE_Array_Map (InputIterator f, InputIterator l);
+#else
+ ACE_Array_Map (const_iterator f, const_iterator l);
+#endif /* !ACE_LACKS_MEMBER_TEMPLATES */
+
+ ACE_Array_Map (ACE_Array_Map const & map);
+ ACE_Array_Map & operator= (ACE_Array_Map const & map);
+
+ /// Destructor.
+ ~ACE_Array_Map (void);
+
+ /**
+ * @name Forward Iterator Accessors
+ *
+ * Forward iterator accessors.
+ */
+ //@{
+ iterator begin (void);
+ iterator end (void);
+ const_iterator begin (void) const;
+ const_iterator end (void) const;
+ //@}
+
+ /**
+ * @name Reverse Iterator Accessors
+ *
+ * Reverse iterator accessors.
+ */
+ //@{
+ reverse_iterator rbegin (void);
+ reverse_iterator rend (void);
+ const_reverse_iterator rbegin (void) const;
+ const_reverse_iterator rend (void) const;
+ //@}
+
+ /// Return current size of map.
+ /**
+ * @return The number of elements in the map.
+ */
+ size_type size (void) const;
+
+ /// Maximum number of elements the map can hold.
+ size_type max_size (void) const;
+
+ /// Return @c true if the map is empty, else @c false.
+ bool is_empty (void) const; // ACE style
+
+ /**
+ * Return @c true if the map is empty, else @c false. We recommend
+ * using @c is_empty() instead since it's more consistent with the
+ * ACE container naming conventions.
+ */
+ bool empty (void) const; // STL style
+
+ /// Swap the contents of this map with the given @a map in an
+ /// exception-safe manner.
+ void swap (ACE_Array_Map & map);
+
+ /// Insert the value @a x into the map.
+ /**
+ * STL-style map insertion method.
+ *
+ * @param x @c std::pair containing key and datum.
+ *
+ * @return @c std::pair::second will be @c false if the map already
+ * contains a value with the same key as @a x.
+ */
+ std::pair<iterator, bool> insert (value_type const & x);
+
+#ifndef ACE_LACKS_MEMBER_TEMPLATES
+ /// Insert range of elements into map.
+ template<typename InputIterator>
+ void insert (InputIterator f, InputIterator l);
+#else
+ /// Insert range of elements into map.
+ void insert (const_iterator f, const_iterator l);
+#endif /* ACE_LACKS_MEMBER_TEMPLATES */
+
+ /// Remove element at position @a pos from the map.
+ void erase (iterator pos);
+
+ /// Remove element corresponding to key @a k from the map.
+ /**
+ * @return Number of elements that were erased.
+ */
+ size_type erase (key_type const & k);
+
+ /// Remove range of elements [@a first, @a last) from the map.
+ /**
+ * @note [@a first, @a last) must be valid range within the map.
+ */
+ void erase (iterator first, iterator last);
+
+ /// Clear contents of map.
+ /**
+ * @note This a constant time (O(1)) operation.
+ */
+ void clear (void);
+
+ /**
+ * @name Search Operations
+ *
+ * Search the map for data corresponding to key @a k.
+ */
+ //@{
+ /**
+ * @return @c end() if data corresponding to key @a k is not in the
+ * map.
+ */
+ iterator find (key_type const & k);
+
+ /**
+ * @return @c end() if data corresponding to key @a k is not in the
+ * map.
+ */
+ const_iterator find (key_type const & k) const;
+ //@}
+
+ /// Count the number of elements corresponding to key @a k.
+ /**
+ * @return In the case of this map, the count will always be one if
+ * such exists in the map.
+ */
+ size_type count (key_type const & k);
+
+ /// Convenience array index operator.
+ /**
+ * Array index operator that allows insertion and retrieval of
+ * elements using an array index syntax, such as:
+ * @par
+ * map["Foo"] = 12;
+ */
+ data_type & operator[] (key_type const & k);
+
+private:
+
+ /// Increase size of underlying buffer by @a s.
+ void grow (size_type s);
+
+private:
+
+ /// Number of elements in the map.
+ size_type size_;
+
+ /// Current size of underlying array.
+ /**
+ * @note @c capacity_ is always greater than or equal to @c size_;
+ */
+ size_type capacity_;
+
+ /// Underlying array containing keys and data.
+ value_type * nodes_;
+
+};
+
+// --------------------------------------------------------------
+
+/// @c ACE_Array_Map equality operator.
+template <typename Key, typename Value, class EqualTo>
+bool operator== (ACE_Array_Map<Key, Value, EqualTo> const & lhs,
+ ACE_Array_Map<Key, Value, EqualTo> const & rhs);
+
+/// @c ACE_Array_Map lexicographical comparison operator.
+template <typename Key, typename Value, class EqualTo>
+bool operator< (ACE_Array_Map<Key, Value, EqualTo> const & lhs,
+ ACE_Array_Map<Key, Value, EqualTo> const & rhs);
+
+// --------------------------------------------------------------
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#ifdef __ACE_INLINE__
+# include "ace/Array_Map.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+# include "ace/Array_Map.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Array_Map.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ARRAY_MAP_H */
diff --git a/ACE/ace/Array_Map.inl b/ACE/ace/Array_Map.inl
new file mode 100644
index 00000000000..86a26d3f3aa
--- /dev/null
+++ b/ACE/ace/Array_Map.inl
@@ -0,0 +1,133 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE
+ACE_Array_Map<Key, Value, EqualTo>::ACE_Array_Map (
+ typename ACE_Array_Map<Key, Value, EqualTo>::size_type s)
+ : size_ (0)
+ , capacity_ (s)
+ , nodes_ (s == 0 ? 0 : new value_type[s])
+{
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE ACE_Array_Map<Key, Value, EqualTo> &
+ACE_Array_Map<Key, Value, EqualTo>::operator= (
+ ACE_Array_Map<Key, Value, EqualTo> const & map)
+{
+ // Strongly exception-safe assignment.
+
+ ACE_Array_Map<Key, Value, EqualTo> temp (map);
+ this->swap (temp);
+ return *this;
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::iterator
+ACE_Array_Map<Key, Value, EqualTo>::begin (void)
+{
+ return this->nodes_;
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::iterator
+ACE_Array_Map<Key, Value, EqualTo>::end (void)
+{
+ return this->nodes_ + this->size_;
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::const_iterator
+ACE_Array_Map<Key, Value, EqualTo>::begin (void) const
+{
+ return this->nodes_;
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::const_iterator
+ACE_Array_Map<Key, Value, EqualTo>::end (void) const
+{
+ return this->nodes_ + this->size_;
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::reverse_iterator
+ACE_Array_Map<Key, Value, EqualTo>::rbegin (void)
+{
+ return reverse_iterator (this->end ());
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::reverse_iterator
+ACE_Array_Map<Key, Value, EqualTo>::rend (void)
+{
+ return reverse_iterator (this->begin ());
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::const_reverse_iterator
+ACE_Array_Map<Key, Value, EqualTo>::rbegin (void) const
+{
+ return const_reverse_iterator (this->end ());
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::const_reverse_iterator
+ACE_Array_Map<Key, Value, EqualTo>::rend (void) const
+{
+ return const_reverse_iterator (this->begin ());
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::size_type
+ACE_Array_Map<Key, Value, EqualTo>::size (void) const
+{
+ return this->size_;
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::size_type
+ACE_Array_Map<Key, Value, EqualTo>::max_size (void) const
+{
+ return size_type (-1) / sizeof (value_type);
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE bool
+ACE_Array_Map<Key, Value, EqualTo>::is_empty (void) const
+{
+ return this->size_ == 0;
+}
+
+// The following method is deprecated.
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE bool
+ACE_Array_Map<Key, Value, EqualTo>::empty (void) const
+{
+ return this->is_empty ();
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::size_type
+ACE_Array_Map<Key, Value, EqualTo>::count (
+ typename ACE_Array_Map<Key, Value, EqualTo>::key_type const & k)
+{
+ return
+ (this->find (k) == this->end () ? 0 : 1); // Only one datum per key.
+}
+
+template<typename Key, typename Value, class EqualTo>
+ACE_INLINE typename ACE_Array_Map<Key, Value, EqualTo>::data_type &
+ACE_Array_Map<Key, Value, EqualTo>::operator[] (
+ typename ACE_Array_Map<Key, Value, EqualTo>::key_type const & k)
+{
+ iterator i = (this->insert (value_type (k, data_type ()))).first;
+ return (*i).second;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Assert.cpp b/ACE/ace/Assert.cpp
new file mode 100644
index 00000000000..06e4f34d2ea
--- /dev/null
+++ b/ACE/ace/Assert.cpp
@@ -0,0 +1,24 @@
+// $Id$
+
+#include "ace/Assert.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Assert, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// The following ASSERT macro is courtesy of Alexandre Karev
+// <akg@na47sun05.cern.ch>.
+void
+__ace_assert(const char *file, int line, const ACE_TCHAR *expression)
+{
+ int error = ACE_Log_Msg::last_error_adapter ();
+ ACE_Log_Msg *log = ACE_Log_Msg::instance ();
+
+ log->set (file, line, -1, error, log->restart (),
+ log->msg_ostream (), log->msg_callback ());
+
+ log->log (LM_ERROR, ACE_TEXT ("ACE_ASSERT: file %N, line %l assertion failed for '%s'.%a\n"), expression, -1);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Assert.h b/ACE/ace/Assert.h
new file mode 100644
index 00000000000..70e9b0060c4
--- /dev/null
+++ b/ACE/ace/Assert.h
@@ -0,0 +1,38 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Assert.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ASSERT_H
+#define ACE_ASSERT_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#include /**/ "ace/config-all.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+ACE_Export void __ace_assert(const char *file, int line, const ACE_TCHAR *expression);
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_NDEBUG)
+#define ACE_ASSERT(x) \
+ (static_cast<void>(0))
+#else
+#define ACE_ASSERT(X) \
+ ((X) \
+ ? static_cast<void>(0) \
+ : ACE_VERSIONED_NAMESPACE_NAME::__ace_assert(__FILE__, __LINE__, ACE_TEXT_CHAR_TO_TCHAR (#X)))
+#endif /* ACE_NDEBUG */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ASSERT */
diff --git a/ACE/ace/Asynch_Acceptor.cpp b/ACE/ace/Asynch_Acceptor.cpp
new file mode 100644
index 00000000000..7ded341609f
--- /dev/null
+++ b/ACE/ace/Asynch_Acceptor.cpp
@@ -0,0 +1,516 @@
+/* -*- 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_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
+// This only works on platforms that support async i/o.
+
+#include "ace/OS_Errno.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/Log_Msg.h"
+#include "ace/Message_Block.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Sock_Connect.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class HANDLER>
+ACE_Asynch_Acceptor<HANDLER>::ACE_Asynch_Acceptor (void)
+ : listen_handle_ (ACE_INVALID_HANDLE),
+ pass_addresses_ (false),
+ validate_new_connection_ (false),
+ 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_);
+ this->listen_handle_ = ACE_INVALID_HANDLE;
+ }
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::open (const ACE_INET_Addr &address,
+ size_t bytes_to_read,
+ bool pass_addresses,
+ int backlog,
+ int reuse_addr,
+ ACE_Proactor *proactor,
+ bool validate_new_connection,
+ int reissue_accept,
+ int number_of_initial_accepts)
+{
+ ACE_TRACE ("ACE_Asynch_Acceptor<>::open");
+
+ 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;
+ this->addr_family_ = address.get_type ();
+
+ // 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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_OS::socket")),
+ -1);
+ // Initialize the ACE_Asynch_Accept
+ if (this->asynch_accept_.open (*this,
+ this->listen_handle_,
+ 0,
+ this->proactor ()) == -1)
+ {
+ ACE_Errno_Guard g (errno);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Asynch_Accept::open")));
+ ACE_OS::closesocket (this->listen_handle_);
+ this->listen_handle_ = ACE_INVALID_HANDLE;
+ return -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_Errno_Guard g (errno);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_OS::setsockopt")));
+ ACE_OS::closesocket (this->listen_handle_);
+ this->listen_handle_ = ACE_INVALID_HANDLE;
+ return -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_,
+ INADDR_ANY,
+ address.get_type()) == -1)
+ {
+ ACE_Errno_Guard g (errno);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::bind_port")));
+ ACE_OS::closesocket (this->listen_handle_);
+ this->listen_handle_ = ACE_INVALID_HANDLE;
+ return -1;
+ }
+
+ // Bind to the specified port.
+ if (ACE_OS::bind (this->listen_handle_,
+ reinterpret_cast<sockaddr *> (address.get_addr ()),
+ address.get_size ()) == -1)
+ {
+ ACE_Errno_Guard g (errno);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_OS::bind")));
+ ACE_OS::closesocket (this->listen_handle_);
+ this->listen_handle_ = ACE_INVALID_HANDLE;
+ return -1;
+ }
+
+ // Start listening.
+ if (ACE_OS::listen (this->listen_handle_, backlog) == -1)
+ {
+ ACE_Errno_Guard g (errno);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_OS::listen")));
+ ACE_OS::closesocket (this->listen_handle_);
+ this->listen_handle_ = ACE_INVALID_HANDLE;
+ return -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_Errno_Guard g (errno);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Asynch_Acceptor::accept")));
+ ACE_OS::closesocket (this->listen_handle_);
+ this->listen_handle_ = ACE_INVALID_HANDLE;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::set_handle (ACE_HANDLE listen_handle)
+{
+ ACE_TRACE ("ACE_Asynch_Acceptor<>::set_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_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Asynch_Accept::open")),
+ -1);
+ return 0;
+}
+
+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_TRACE ("ACE_Asynch_Acceptor<>::accept");
+
+ ACE_Message_Block *message_block = 0;
+ // The space_needed calculation is drive by needs of Windows. POSIX doesn't
+ // need to extra 16 bytes, but it doesn't hurt.
+ size_t space_needed = sizeof (sockaddr_in) + 16;
+#if defined (ACE_HAS_IPV6)
+ if (PF_INET6 == this->addr_family_)
+ space_needed = sizeof (sockaddr_in6) + 16;
+#endif /* ACE_HAS_IPV6 */
+ space_needed = (2 * space_needed) + bytes_to_read;
+
+ // 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,
+ 0,
+ ACE_SIGRTMIN,
+ this->addr_family_) == -1)
+ {
+ // Cleanup on error
+ message_block->release ();
+ return -1;
+ }
+ return 0;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::handle_accept (const ACE_Asynch_Accept::Result &result)
+{
+ ACE_TRACE ("ACE_Asynch_Acceptor<>::handle_accept");
+
+ // Variable for error tracking
+ int error = 0;
+
+ // If the asynchronous accept fails.
+ if (!result.success () || result.accept_handle () == ACE_INVALID_HANDLE)
+ {
+ error = 1;
+ }
+
+#if defined (ACE_WIN32)
+ // 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;
+ }
+#endif /* ACE_WIN32 */
+
+ // 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_connection (result, remote_address, local_address) == -1))
+ {
+ error = 1;
+ }
+
+ HANDLER *new_handler = 0;
+ if (!error)
+ {
+ // The Template method
+ new_handler = this->make_handler ();
+ if (new_handler == 0)
+ {
+ error = 1;
+ }
+ }
+
+ // 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,
+ // unless we closed the listen socket already (from the destructor),
+ // or this callback is the result of a canceled/aborted accept.
+ if (this->should_reissue_accept () &&
+ this->listen_handle_ != ACE_INVALID_HANDLE
+#if defined (ACE_WIN32)
+ && result.error () != ERROR_OPERATION_ABORTED
+#else
+ && result.error () != ECANCELED
+#endif
+ )
+ this->accept (this->bytes_to_read_);
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::validate_connection
+ (const ACE_Asynch_Accept::Result& /* result */,
+ const ACE_INET_Addr& /* remote */,
+ const ACE_INET_Addr& /* local */)
+{
+ // Default implementation always validates the remote address.
+ return 0;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::cancel (void)
+{
+ ACE_TRACE ("ACE_Asynch_Acceptor<>::cancel");
+
+ // 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_WIN32_OVERLAPPED_IO) && \
+ (defined (_MSC_VER) || defined (__BORLANDC__))
+ return (int) ::CancelIo (this->listen_handle_);
+#else
+ // Supported now
+ return this->asynch_accept_.cancel();
+
+#endif /* defined (ACE_HAS_WIN32_OVERLAPPED_IO) && (defined (_MSC_VER)) || defined (__BORLANDC__)) */
+}
+
+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)
+{
+ ACE_TRACE ("ACE_Asynch_Acceptor<>::parse_address");
+
+#if defined (ACE_HAS_AIO_CALLS)
+
+ // Use an ACE_SOCK to get the addresses - it knows how to deal with
+ // ACE_INET_Addr objects and get IPv4/v6 addresses.
+ ACE_SOCK_Stream str (result.accept_handle ());
+ str.get_local_addr (local_address);
+ str.get_remote_addr (remote_address);
+
+#elif 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;
+ // This matches setup in accept().
+ size_t addr_size = sizeof (sockaddr_in) + 16;
+#if defined (ACE_HAS_IPV6)
+ if (this->addr_family_ == PF_INET6)
+ addr_size = sizeof (sockaddr_in6) + 16;
+#endif /* ACE_HAS_IPV6 */
+
+ ::GetAcceptExSockaddrs (message_block.rd_ptr (),
+ static_cast<DWORD> (this->bytes_to_read_),
+ static_cast<DWORD> (addr_size),
+ static_cast<DWORD> (addr_size),
+ &local_addr,
+ &local_size,
+ &remote_addr,
+ &remote_size);
+
+ local_address.set (reinterpret_cast<sockaddr_in *> (local_addr),
+ local_size);
+ remote_address.set (reinterpret_cast<sockaddr_in *> (remote_addr),
+ remote_size);
+#else
+ // just in case
+ errno = ENOTSUP;
+#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
+ return;
+}
+
+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> bool
+ACE_Asynch_Acceptor<HANDLER>::pass_addresses (void) const
+{
+ return this->pass_addresses_;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::pass_addresses (bool new_value)
+{
+ this->pass_addresses_ = new_value;
+}
+
+template <class HANDLER> bool
+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 (bool 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> size_t
+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 (size_t new_value)
+{
+ this->bytes_to_read_ = new_value;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::should_reissue_accept (void)
+{
+ return this->reissue_accept_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS */
+#endif /* ACE_ASYNCH_ACCEPTOR_C */
diff --git a/ACE/ace/Asynch_Acceptor.h b/ACE/ace/Asynch_Acceptor.h
new file mode 100644
index 00000000000..af7944e4b58
--- /dev/null
+++ b/ACE/ace/Asynch_Acceptor.h
@@ -0,0 +1,281 @@
+/* -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
+// This only works on platforms that support async i/o.
+
+#include "ace/Default_Constants.h"
+#include "ace/Asynch_IO.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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);
+
+ /**
+ * @c open starts one or more asynchronous accept requests on a
+ * @a address. Each accept operation may optionally read an
+ * initial buffer from the new connection when accepted.
+ *
+ * @param address The address to listen/accept connections on.
+ * If the address does not specify a port, a random
+ * port is selected and bound.
+ * @param bytes_to_read Optional, specifies the maximum number of bytes
+ * to read with the accept. The buffer for the initial
+ * data is allocated internally and passed to the
+ * @c ACE_Service_Handler::open() hook method. It is
+ * legitimate only during the @c open() method and must
+ * be copied if required after @c open() returns.
+ * This pre-read function works only on Windows.
+ * @param pass_addresses Optional, a non-zero value indicates that
+ * the local and peer addresses should be passed to the
+ * associated @c ACE_Service_Handler::addresses() method
+ * after any call to @c validate_new_connection() and prior
+ * to the @c open() hook method call.
+ * @param backlog Optional, defaulting to @c ACE_DEFAULT_ASYNCH_BACKLOG (which
+ * can be adjusted in your platform's @c config.h file).
+ * Specifies the listening backlog for the listening socket.
+ * @param reuse_addr Optional, indicates whether the @c SO_REUSEADDR
+ * option is set on the listening socket or not.
+ * @param proactor Optional, pointer to the @c ACE_Proactor to use for
+ * demultiplexing asynchronous accepts. If 0, the
+ * process's singleton @c ACE_Proactor is used.
+ * @param validate_new_connection Optional, if true, this object's
+ * @c validate_connection() method is called after
+ * the accept completes, but before the service handler's
+ * @c open() hook method is called. If @c
+ * validate_connection() returns -1, the newly-accepted
+ * socket is immediately closed, and the @c addresses()
+ * method is not called.
+ * @param reissue_accept Optional, if non-zero (the default), a new
+ * asynchronous accept operation is started after each
+ * completion, whether the completion is for success or
+ * failure, and whether or not a successfully-accepted
+ * connection is subsequently refused.
+ * @param number_of_initial_accepts Optional, the number of asynchronous
+ * accepts that are started immediately. If -1 (the
+ * default), the value of @a backlog is used.
+ *
+ * @note On Windows, the peer address is only available at the time
+ * the connection is accepted. Therefore, if you require the peer
+ * address on Windows, do not rely on the
+ * @c ACE_SOCK::get_remote_addr() method - it won't work. You must
+ * supply a non-zero value for @a pass_addresses and obtain the
+ * peer address in the @c ACE_Service_Handler::addresses() method.
+ *
+ * @see ACE_INET_Addr
+ * @see ACE_Service_Handler
+ */
+ virtual int open (const ACE_INET_Addr &address,
+ size_t bytes_to_read = 0,
+ bool pass_addresses = false,
+ int backlog = ACE_DEFAULT_ASYNCH_BACKLOG,
+ int reuse_addr = 1,
+ ACE_Proactor *proactor = 0,
+ bool validate_new_connection = false,
+ 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 int set_handle (ACE_HANDLE handle);
+
+ /// This initiates a new asynchronous accept operation.
+ /**
+ * You need only call this method if the @a reissue_accept argument
+ * passed to @c open() was 0.
+ */
+ virtual int accept (size_t bytes_to_read = 0, const void *act = 0);
+
+ /**
+ * Cancels all pending accepts operations issued by this object.
+ *
+ * @note On Windows, only accept operations initiated by the calling thread
+ * are canceled.
+ */
+ virtual int cancel (void);
+
+ /**
+ * Template method to validate peer before service is opened.
+ * This method is called after a new connection is accepted if the
+ * @a validate_connection argument to @c open() was non-zero or
+ * the @c validate_new_connection() method is called to turn this
+ * feature on. The default implementation returns 0. Users can
+ * reimplement this method to perform validation of the peer
+ * using it's address, running an authentication procedure (such as
+ * SSL) or anything else necessary or desireable. The return value
+ * from this method determines whether or not ACE will continue
+ * opening the service or abort the connection.
+ *
+ * @param result Result of the connection acceptance.
+ * @param remote Peer's address.
+ * @param local Local address connection was accepted at.
+ *
+ * @retval -1 ACE_Asynch_Acceptor will close the connection, and
+ * the service will not be opened.
+ * @retval 0 Service opening will proceeed.
+ */
+ virtual int validate_connection (const ACE_Asynch_Accept::Result& result,
+ const ACE_INET_Addr &remote,
+ const ACE_INET_Addr& local);
+
+ /**
+ * Template method for deciding whether to reissue accept.
+ *
+ * This hook method is called after each accept completes to decide if
+ * another accept should be initiated. If the method returns a non-zero
+ * value, another accept is initiated.
+ *
+ * The default implemenation always returns the value passed as the
+ * @c open() method's @a reissue_accept argument. That value can also
+ * be changed using the @c reissue_accept() method.
+ */
+ virtual int should_reissue_accept (void);
+
+ //
+ // These are low level tweaking methods
+ //
+
+ /// Get flag that indicates if parsing and passing of addresses to
+ /// the service_handler is necessary.
+ virtual bool pass_addresses (void) const;
+
+ /// Set flag that indicates if parsing and passing of addresses to
+ /// the service_handler is necessary.
+ virtual void pass_addresses (bool new_value);
+
+ /// Get flag that indicates if address validation is required.
+ virtual bool validate_new_connection (void) const;
+
+ /// Set flag that indicates if address validation is required.
+ virtual void validate_new_connection (bool new_value);
+
+ /// Get flag that indicates if a new accept should be reissued when a accept
+ /// completes.
+ virtual int reissue_accept (void) const;
+
+ /// Set flag that indicates if a new accept should be reissued when a accept
+ /// completes.
+ virtual void reissue_accept (int new_value);
+
+ /// Get bytes to be read with the <accept> call.
+ virtual size_t bytes_to_read (void) const;
+
+ /// Set bytes to be read with the <accept> call.
+ virtual void bytes_to_read (size_t new_value);
+
+ /// @deprecated address_size() assumes IPv4 use, so is not always valid.
+ /// This method will be removed after ACE 5.5. Internal uses have been
+ /// changes to base needed sizes on the addr_family_ member.
+ 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.
+ bool pass_addresses_;
+
+ /// Flag that indicates if address validation is required.
+ bool 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.
+ size_t bytes_to_read_;
+
+ /// Address family used to open this object. Obtained from @a address passed
+ /// to @c open().
+ int addr_family_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#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_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
+#include /**/ "ace/post.h"
+#endif /* ACE_ASYNCH_ACCEPTOR_H */
diff --git a/ACE/ace/Asynch_Connector.cpp b/ACE/ace/Asynch_Connector.cpp
new file mode 100644
index 00000000000..fd61fcfdb8a
--- /dev/null
+++ b/ACE/ace/Asynch_Connector.cpp
@@ -0,0 +1,296 @@
+// $Id$
+
+#ifndef ACE_ASYNCH_CONNECTOR_CPP
+#define ACE_ASYNCH_CONNECTOR_CPP
+
+#include "ace/Asynch_Connector.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (defined (ACE_WIN32) || defined (ACE_HAS_AIO_CALLS)) && !defined(ACE_HAS_WINCE)
+// This only works on platforms that support async I/O.
+
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_Memory.h"
+#include "ace/Flag_Manip.h"
+#include "ace/Log_Msg.h"
+#include "ace/Message_Block.h"
+#include "ace/INET_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class HANDLER>
+ACE_Asynch_Connector<HANDLER>::ACE_Asynch_Connector (void)
+ : pass_addresses_ (false),
+ validate_new_connection_ (false)
+{
+}
+
+template <class HANDLER>
+ACE_Asynch_Connector<HANDLER>::~ACE_Asynch_Connector (void)
+{
+ //this->asynch_connect_.close ();
+}
+
+template <class HANDLER> int
+ACE_Asynch_Connector<HANDLER>::open (bool pass_addresses,
+ ACE_Proactor *proactor,
+ bool validate_new_connection)
+{
+ this->proactor (proactor);
+ this->pass_addresses_ = pass_addresses;
+ this->validate_new_connection_ = validate_new_connection;
+
+ // Initialize the ACE_Asynch_Connect
+ if (this->asynch_connect_.open (*this,
+ ACE_INVALID_HANDLE,
+ 0,
+ this->proactor ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Asynch_Connect::open")),
+ -1);
+ return 0;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Connector<HANDLER>::connect (const ACE_INET_Addr & remote_sap,
+ const ACE_INET_Addr & local_sap,
+ int reuse_addr,
+ const void *act)
+{
+ // Initiate asynchronous connect
+ if (this->asynch_connect_.connect (ACE_INVALID_HANDLE,
+ remote_sap,
+ local_sap,
+ reuse_addr,
+ act) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Asynch_Connect::connect")),
+ -1);
+ return 0;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Connector<HANDLER>::handle_connect (const ACE_Asynch_Connect::Result &result)
+{
+ // Variable for error tracking
+ int error = 0;
+
+ // If the asynchronous connect fails.
+ if (!result.success () ||
+ result.connect_handle () == ACE_INVALID_HANDLE)
+ {
+ error = 1;
+ }
+
+ if (result.error () != 0)
+ {
+ error = 1;
+ }
+
+ // set blocking mode
+ if (!error &&
+ ACE::clr_flags
+ (result.connect_handle (), ACE_NONBLOCK) != 0)
+ {
+ error = 1;
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Asynch_Connector::handle_connect : Set blocking mode")));
+ }
+
+ // Parse the addresses.
+ ACE_INET_Addr local_address;
+ ACE_INET_Addr remote_address;
+ if (!error &&
+ (this->validate_new_connection_ || this->pass_addresses_))
+ this->parse_address (result,
+ remote_address,
+ local_address);
+
+ // Call validate_connection even if there was an error - it's the only
+ // way the application can learn the connect disposition.
+ if (this->validate_new_connection_ &&
+ this->validate_connection (result, remote_address, local_address) == -1)
+ {
+ error = 1;
+ }
+
+ 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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Asynch_Connector::handle_connect : 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.connect_handle ());
+
+ ACE_Message_Block mb;
+
+ // Initiate the handler with empty message block;
+ new_handler->open (result.connect_handle (), mb);
+ }
+
+ // On failure, no choice but to close the socket
+ if (error &&
+ result.connect_handle() != ACE_INVALID_HANDLE)
+ ACE_OS::closesocket (result.connect_handle ());
+}
+
+template <class HANDLER> int
+ACE_Asynch_Connector<HANDLER>::validate_connection
+ (const ACE_Asynch_Connect::Result &,
+ const ACE_INET_Addr & /* remote_address */,
+ const ACE_INET_Addr & /* local_address */)
+{
+ // Default implementation always validates the remote address.
+ return 0;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Connector<HANDLER>::cancel (void)
+{
+ return this->asynch_connect_.cancel ();
+}
+
+template <class HANDLER> void
+ACE_Asynch_Connector<HANDLER>::parse_address (const ACE_Asynch_Connect::Result &result,
+ ACE_INET_Addr &remote_address,
+ ACE_INET_Addr &local_address)
+{
+#if defined (ACE_HAS_IPV6)
+ // Getting the addresses.
+ sockaddr_in6 local_addr;
+ sockaddr_in6 remote_addr;
+#else
+ // Getting the addresses.
+ sockaddr_in local_addr;
+ sockaddr_in remote_addr;
+#endif /* ACE_HAS_IPV6 */
+
+ // Get the length.
+ int local_size = sizeof (local_addr);
+ int remote_size = sizeof (remote_addr);
+
+ // Get the local address.
+ if (ACE_OS::getsockname (result.connect_handle (),
+ reinterpret_cast<sockaddr *> (&local_addr),
+ &local_size) < 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("%p\n"),
+ ACE_TEXT("ACE_Asynch_Connector::<getsockname> failed")));
+
+ // Get the remote address.
+ if (ACE_OS::getpeername (result.connect_handle (),
+ reinterpret_cast<sockaddr *> (&remote_addr),
+ &remote_size) < 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("%p\n"),
+ ACE_TEXT("ACE_Asynch_Connector::<getpeername> failed")));
+
+ // Set the addresses.
+ local_address.set (reinterpret_cast<sockaddr_in *> (&local_addr),
+ local_size);
+ remote_address.set (reinterpret_cast<sockaddr_in *> (&remote_addr),
+ remote_size);
+
+#if 0
+ // @@ 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:%m:can't obtain local_address's address string"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_Asynch_Connector<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:%m:can't obtain remote_address's address string"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_Asynch_Connector<HANDLER>::parse_address : "
+ "Remote address %s\n",
+ remote_address_buf));
+#endif /* 0 */
+
+ return;
+}
+
+
+template <class HANDLER> ACE_Asynch_Connect &
+ACE_Asynch_Connector<HANDLER>::asynch_connect (void)
+{
+ return this->asynch_connect_;
+}
+
+template <class HANDLER> HANDLER *
+ACE_Asynch_Connector<HANDLER>::make_handler (void)
+{
+ // Default behavior
+ HANDLER *handler = 0;
+ ACE_NEW_RETURN (handler, HANDLER, 0);
+ return handler;
+}
+
+template <class HANDLER> bool
+ACE_Asynch_Connector<HANDLER>::pass_addresses (void) const
+{
+ return this->pass_addresses_;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Connector<HANDLER>::pass_addresses (bool new_value)
+{
+ this->pass_addresses_ = new_value;
+}
+
+template <class HANDLER> bool
+ACE_Asynch_Connector<HANDLER>::validate_new_connection (void) const
+{
+ return this->validate_new_connection_;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Connector<HANDLER>::validate_new_connection (bool new_value)
+{
+ this->validate_new_connection_ = new_value;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS */
+#endif /* ACE_ASYNCH_CONNECTOR_CPP */
diff --git a/ACE/ace/Asynch_Connector.h b/ACE/ace/Asynch_Connector.h
new file mode 100644
index 00000000000..4e049584d77
--- /dev/null
+++ b/ACE/ace/Asynch_Connector.h
@@ -0,0 +1,171 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Asynch_Connector.h
+ *
+ * $Id$
+ *
+ * @author Alexander Libman <alibman@ihug.com.au>
+ */
+//=============================================================================
+
+#ifndef ACE_ASYNCH_CONNECTOR_H
+#define ACE_ASYNCH_CONNECTOR_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_HAS_AIO_CALLS)) && !defined(ACE_HAS_WINCE)
+// This only works on platforms that support async i/o.
+
+#include "ace/Asynch_IO.h"
+#include "ace/INET_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations
+class ACE_Message_Block;
+
+/**
+ * @class ACE_Asynch_Connector
+ *
+ * @brief This class is an example of the Connector pattern. This class
+ * will establish new connections and create new HANDLER objects to handle
+ * the new connections.
+ *
+ * Unlike the ACE_Connector, however, this class is designed to
+ * be used asynchronously with the ACE Proactor framework.
+ */
+
+template <class HANDLER>
+class ACE_Asynch_Connector : public ACE_Handler
+{
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Connector (void);
+
+ /// Virtual destruction
+ virtual ~ACE_Asynch_Connector (void);
+
+ /**
+ * This opens asynch connector
+ */
+ virtual int open (bool pass_addresses = false,
+ ACE_Proactor *proactor = 0,
+ bool validate_new_connection = true);
+
+ /// This initiates a new asynchronous connect
+ virtual int connect (const ACE_INET_Addr &remote_sap,
+ const ACE_INET_Addr &local_sap =
+ (const ACE_INET_Addr &)ACE_Addr::sap_any,
+ int reuse_addr = 1,
+ const void *act = 0);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread.
+ *
+ * @note On Windows, this method does not cancel connect operations
+ * issued by other threads.
+ *
+ * @note On POSIX, delegates cancelation to ACE_POSIX_Asynch_Connect.
+ */
+ virtual int cancel (void);
+
+
+ /**
+ * Template method to validate peer before service is opened.
+ * This method is called when the connection attempt completes,
+ * whether it succeeded or failed, if the @a validate_connection
+ * argument to @c open() was non-zero or the @c validate_new_connection()
+ * method is called to turn this feature on. The default implementation
+ * returns 0. Users can (and probably should) reimplement this method
+ * to learn about the success or failure of the connection attempt.
+ * If the connection completed successfully, this method can be used to
+ * perform validation of the peer using it's address, running an
+ * authentication procedure (such as SSL) or anything else necessary or
+ * desireable. The return value from this method determines whether or
+ * not ACE will continue opening the service or abort the connection.
+ *
+ * @param result Result of the connection acceptance. Use
+ * result.success() to determine success or failure of
+ * the connection attempt.
+ * @param remote Peer's address. If the connection failed, this object
+ * is undefined.
+ * @param local Local address connection was completed from. If the
+ * connection failed, this object is undefined.
+ *
+ * @retval -1 ACE_Asynch_Connector will close the connection, and
+ * the service will not be opened.
+ * @retval 0 Service opening will proceeed.
+ * @return Return value is ignored if the connection attempt failed.
+ */
+ virtual int validate_connection (const ACE_Asynch_Connect::Result& result,
+ const ACE_INET_Addr &remote,
+ const ACE_INET_Addr& local);
+
+ //
+ // 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 bool pass_addresses (void) const;
+ virtual void pass_addresses (bool new_value);
+
+ /// Set and get flag that indicates if address validation is
+ /// required.
+ virtual bool validate_new_connection (void) const;
+ virtual void validate_new_connection (bool new_value);
+
+protected:
+
+ /// This is called when an outstanding accept completes.
+ virtual void handle_connect (const ACE_Asynch_Connect::Result &result);
+
+
+ /// This parses the address from read buffer.
+ void parse_address (const ACE_Asynch_Connect::Result &result,
+ ACE_INET_Addr &remote_address,
+ ACE_INET_Addr &local_address);
+
+ /// Return the asynch Connect object.
+ ACE_Asynch_Connect & asynch_connect (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:
+
+ /// Asynch_Connect used to make life easier :-)
+ ACE_Asynch_Connect asynch_connect_;
+
+ /// Flag that indicates if parsing of addresses is necessary.
+ bool pass_addresses_;
+
+ /// Flag that indicates if address validation is required.
+ bool validate_new_connection_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Asynch_Connector.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Asynch_Connector.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS */
+#include /**/ "ace/post.h"
+#endif /* ACE_ASYNCH_CONNECTOR_H */
diff --git a/ACE/ace/Asynch_IO.cpp b/ACE/ace/Asynch_IO.cpp
new file mode 100644
index 00000000000..3ebf11eff5c
--- /dev/null
+++ b/ACE/ace/Asynch_IO.cpp
@@ -0,0 +1,1411 @@
+// $Id$
+
+#include "ace/Asynch_IO.h"
+
+ACE_RCSID(ace, Asynch_IO, "$Id$")
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || 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"
+#include "ace/os_include/os_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+size_t
+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 ();
+}
+
+unsigned long
+ACE_Asynch_Result::error (void) const
+{
+ return this->implementation ()->error ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Result::event (void) const
+{
+ return this->implementation ()->event ();
+}
+
+unsigned long
+ACE_Asynch_Result::offset (void) const
+{
+ return this->implementation ()->offset ();
+}
+
+unsigned 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.proxy (),
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Operation::cancel (void)
+{
+ if (0 == this->implementation ())
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation ()->cancel ();
+}
+
+ACE_Proactor *
+ACE_Asynch_Operation::proactor (void) const
+{
+ if (0 == this->implementation ())
+ {
+ errno = EFAULT;
+ return 0;
+ }
+ return this->implementation ()->proactor ();
+}
+
+ACE_Asynch_Operation::ACE_Asynch_Operation (void)
+{
+}
+
+ACE_Asynch_Operation::~ACE_Asynch_Operation (void)
+{
+}
+
+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)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_read_stream ()) == 0)
+ return -1;
+
+ // 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,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->read (message_block,
+ bytes_to_read,
+ act,
+ priority,
+ signal_number);
+}
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+int
+ACE_Asynch_Read_Stream::readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->readv (message_block,
+ bytes_to_read,
+ act,
+ priority,
+ signal_number);
+}
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Read_Stream::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+size_t
+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)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_write_stream ()) == 0)
+ return -1;
+
+ // 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,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->write (message_block,
+ bytes_to_write,
+ act,
+ priority,
+ signal_number);
+}
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+int
+ACE_Asynch_Write_Stream::writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->writev (message_block,
+ bytes_to_write,
+ act,
+ priority,
+ signal_number);
+}
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Write_Stream::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+size_t
+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)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_read_file ()) == 0)
+ return -1;
+
+ // 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,
+ size_t bytes_to_read,
+ unsigned long offset,
+ unsigned long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->read (message_block,
+ bytes_to_read,
+ offset,
+ offset_high,
+ act,
+ priority,
+ signal_number);
+}
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+int
+ACE_Asynch_Read_File::readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ unsigned long offset,
+ unsigned long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->readv (message_block,
+ bytes_to_read,
+ offset,
+ offset_high,
+ act,
+ priority,
+ signal_number);
+}
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Read_File::implementation (void) const
+{
+ return this->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)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_write_file ()) == 0)
+ return -1;
+
+ // 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,
+ size_t bytes_to_write,
+ unsigned long offset,
+ unsigned long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->write (message_block,
+ bytes_to_write,
+ offset,
+ offset_high,
+ act,
+ priority,
+ signal_number);
+}
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+int
+ACE_Asynch_Write_File::writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ unsigned long offset,
+ unsigned long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->writev (message_block,
+ bytes_to_write,
+ offset,
+ offset_high,
+ act,
+ priority,
+ signal_number);
+}
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Write_File::implementation (void) const
+{
+ return this->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)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_accept ()) == 0)
+ return -1;
+
+ // 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,
+ size_t bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number,
+ int addr_family)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->accept (message_block,
+ bytes_to_read,
+ accept_handle,
+ act,
+ priority,
+ signal_number,
+ addr_family);
+}
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Accept::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+size_t
+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_Connect::ACE_Asynch_Connect (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Connect::~ACE_Asynch_Connect (void)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+int
+ACE_Asynch_Connect::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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_connect ()) == 0)
+ return -1;
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Connect::connect (ACE_HANDLE connect_handle,
+ const ACE_Addr & remote_sap,
+ const ACE_Addr & local_sap,
+ int reuse_addr,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->connect (connect_handle,
+ remote_sap,
+ local_sap,
+ reuse_addr,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Connect::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+ACE_Asynch_Connect::Result::Result (ACE_Asynch_Connect_Result_Impl *implementation)
+ : ACE_Asynch_Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Connect::Result::~Result (void)
+{
+ // Proactor will delete the implementation when the <complete> call
+ // completes.
+}
+
+ACE_HANDLE
+ACE_Asynch_Connect::Result::connect_handle (void) const
+{
+ return this->implementation ()->connect_handle ();
+}
+
+
+ACE_Asynch_Connect_Result_Impl *
+ACE_Asynch_Connect::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)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_transmit_file ()) == 0)
+ return -1;
+
+ // 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,
+ size_t bytes_to_write,
+ unsigned long offset,
+ unsigned long offset_high,
+ size_t bytes_per_send,
+ unsigned long flags,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ 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_Operation_Impl *
+ACE_Asynch_Transmit_File::implementation (void) const
+{
+ return 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 ();
+}
+
+size_t
+ACE_Asynch_Transmit_File::Result::bytes_to_write (void) const
+{
+ return this->implementation ()->bytes_to_write ();
+}
+
+size_t
+ACE_Asynch_Transmit_File::Result::bytes_per_send (void) const
+{
+ return this->implementation ()->bytes_per_send ();
+}
+
+unsigned 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,
+ size_t header_bytes,
+ ACE_Message_Block *trailer,
+ size_t 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,
+ size_t header_bytes,
+ ACE_Message_Block *trailer,
+ size_t 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;
+}
+
+size_t
+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 (size_t 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;
+}
+
+size_t
+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 (size_t 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 ();
+#if defined(ACE_WIN64)
+ this->transmit_buffers_.HeadLength =
+ static_cast<DWORD> (this->header_bytes_);
+#else
+ this->transmit_buffers_.HeadLength = this->header_bytes_;
+#endif /* ACE_WIN64 */
+ }
+ 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 ();
+#if defined(ACE_WIN64)
+ this->transmit_buffers_.TailLength =
+ static_cast<DWORD> (this->trailer_bytes_);
+#else
+ this->transmit_buffers_.TailLength = this->trailer_bytes_;
+#endif /* ACE_WIN64 */
+ }
+ 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::Proxy *p;
+ ACE_NEW (p, ACE_Handler::Proxy (this));
+ this->proxy_.reset (p);
+}
+
+ACE_Handler::ACE_Handler (ACE_Proactor *d)
+ : proactor_ (d), handle_ (ACE_INVALID_HANDLE)
+{
+ ACE_Handler::Proxy *p;
+ ACE_NEW (p, ACE_Handler::Proxy (this));
+ this->proxy_.reset (p);
+}
+
+ACE_Handler::~ACE_Handler (void)
+{
+ ACE_Handler::Proxy *p = this->proxy_.get ();
+ if (p)
+ p->reset ();
+}
+
+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_connect (const ACE_Asynch_Connect::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_Refcounted_Auto_Ptr<ACE_Handler::Proxy, ACE_SYNCH_MUTEX> &
+ACE_Handler::proxy (void)
+{
+ return this->proxy_;
+}
+
+// ************************************************************
+
+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 */ )
+{
+}
+
+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)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_read_dgram ()) == 0)
+ return -1;
+
+ // 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)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->recv (message_block,
+ number_of_bytes_recvd,
+ flags,
+ protocol_family,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Read_Dgram::implementation (void) const
+{
+ return 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 ();
+}
+
+size_t
+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)
+{
+ // Delete the implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+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);
+
+ // Now let us get the implementation initialized.
+ if ((this->implementation_ = proactor->create_asynch_write_dgram ()) == 0)
+ return -1;
+
+ // 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)
+{
+ if (0 == this->implementation_)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ return this->implementation_->send (message_block,
+ number_of_bytes_sent,
+ flags,
+ remote_addr,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Write_Dgram::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+size_t
+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)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
diff --git a/ACE/ace/Asynch_IO.h b/ACE/ace/Asynch_IO.h
new file mode 100644
index 00000000000..e71c16ca3ee
--- /dev/null
+++ b/ACE/ace/Asynch_IO.h
@@ -0,0 +1,1690 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Asynch_IO.h
+ *
+ * $Id$
+ *
+ * This works on Win32 (defined (ACE_WIN32) && !defined
+ * (ACE_HAS_WINCE)) platforms and on POSIX4 platforms with {aio_*}
+ * routines (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>
+ * @author Alexander Libman <alibman@ihug.com.au>
+ */
+//=============================================================================
+
+#ifndef ACE_ASYNCH_IO_H
+#define ACE_ASYNCH_IO_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
+
+#include "ace/Synch_Traits.h"
+#if defined (ACE_HAS_THREADS)
+# include "ace/Thread_Mutex.h"
+#else
+# include "ace/Null_Mutex.h"
+#endif /* ACE_HAS_THREADS */
+#include "ace/Refcounted_Auto_Ptr.h"
+
+#include "ace/os_include/os_signal.h"
+#include "ace/os_include/sys/os_socket.h"
+#include "ace/os_include/sys/os_types.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+typedef TRANSMIT_FILE_BUFFERS ACE_TRANSMIT_FILE_BUFFERS;
+typedef LPTRANSMIT_FILE_BUFFERS ACE_LPTRANSMIT_FILE_BUFFERS;
+typedef PTRANSMIT_FILE_BUFFERS ACE_PTRANSMIT_FILE_BUFFERS;
+
+# define ACE_INFINITE INFINITE
+# define ACE_STATUS_TIMEOUT STATUS_TIMEOUT
+# define ACE_WAIT_FAILED WAIT_FAILED
+# define ACE_WAIT_TIMEOUT WAIT_TIMEOUT
+# else /* ACE_HAS_WIN32_OVERLAPPED_IO */
+struct ACE_TRANSMIT_FILE_BUFFERS
+{
+ void *Head;
+ size_t HeadLength;
+ void *Tail;
+ size_t TailLength;
+};
+typedef ACE_TRANSMIT_FILE_BUFFERS* ACE_PTRANSMIT_FILE_BUFFERS;
+typedef ACE_TRANSMIT_FILE_BUFFERS* ACE_LPTRANSMIT_FILE_BUFFERS;
+
+# if !defined (ACE_INFINITE)
+# define ACE_INFINITE LONG_MAX
+# endif /* ACE_INFINITE */
+# define ACE_STATUS_TIMEOUT LONG_MAX
+# define ACE_WAIT_FAILED LONG_MAX
+# define ACE_WAIT_TIMEOUT LONG_MAX
+# endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+// Forward declarations
+class ACE_Proactor;
+class ACE_Handler;
+class ACE_Message_Block;
+class ACE_INET_Addr;
+class ACE_Addr;
+
+// Forward declarations
+class ACE_Asynch_Result_Impl;
+class ACE_Time_Value;
+
+/**
+ * @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.
+ size_t 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.
+ unsigned 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.
+ */
+ unsigned long offset (void) const;
+ unsigned 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.
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const = 0;
+
+ /// Get a proactor for/from the user
+ ACE_Proactor *get_proactor (ACE_Proactor *user_proactor,
+ ACE_Handler &handler) const;
+};
+
+// 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.
+ *
+ * @arg handler The ACE_Handler that will be called to handle completions
+ * for operations initiated using this factory.
+ * @arg handle The handle that future read operations will use.
+ * If handle == @c ACE_INVALID_HANDLE,
+ * ACE_Handler::handle() will be called on @ handler
+ * to get the correct handle.
+ *
+ * @retval 0 for success.
+ * @retval -1 for failure; consult @c errno for further information.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * Initiate an asynchronous read operation.
+ *
+ * @arg message_block The ACE_Message_Block to receive the data.
+ * Received bytes will be placed in the block
+ * beginning at its current write pointer.
+ * If data is read, the message block's write
+ * pointer will be advanced by the number of
+ * bytes read.
+ * @arg num_bytes_to_read The maximum number of bytes to read.
+ * @arg act Asynchronous Completion Token; passed through to
+ * the Result object corresponding to this operation.
+ * @arg priority Priority of the operation. On POSIX4-Unix,
+ * this is supported. Works like @c 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 priority, etc.
+ * @param is ignored on Windows.
+ * @arg signal_number The POSIX4 real-time signal number to be used
+ * to signal completion of the operation. Values
+ * range from ACE_SIGRTMIN to ACE_SIGRTMAX.
+ * This argument is ignored on non-POSIX4 systems.
+ */
+ int read (ACE_Message_Block &message_block,
+ size_t num_bytes_to_read,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+ /**
+ * Same as above but with scatter support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ int readv (ACE_Message_Block &message_block,
+ size_t num_bytes_to_read,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+#endif /* defined (ACE_HAS_WIN32_OVERLAPPED_IO) */
+
+ /// Return the underlying implementation class.
+ // (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// 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.
+ size_t 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,
+ size_t bytes_to_write,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+ /**
+ * Same as above but with gather support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ int writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+#endif /* defined (ACE_HAS_WIN32_OVERLAPPED_IO) */
+
+ /// Return the underlying implementation class.
+ /// @todo (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// Implementation class that all methods will be forwarded to.
+ ACE_Asynch_Write_Stream_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.
+ */
+ 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.
+ size_t 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:
+ /// Constructor.
+ 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,
+ size_t bytes_to_read,
+ unsigned long offset = 0,
+ unsigned long offset_high = 0,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ /**
+ * Same as above but with scatter support, through chaining of composite
+ * message blocks using the continuation field.
+ * @note In win32 Each data block payload must be at least the size of a system
+ * memory page and must be aligned on a system memory page size boundary
+ */
+ int readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ unsigned long offset = 0,
+ unsigned long offset_high = 0,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+ /// Return the underlying implementation class.
+ // (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// 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,
+ size_t bytes_to_write,
+ unsigned long offset = 0,
+ unsigned long offset_high = 0,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ /**
+ * Same as above but with gather support, through chaining of composite
+ * message blocks using the continuation field.
+ * @note In win32 Each data block payload must be at least the size of a system
+ * memory page and must be aligned on a system memory page size boundary
+ */
+ int writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ unsigned long offset = 0,
+ unsigned long offset_high = 0,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+ /// Return the underlying implementation class.
+ // (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// 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 specified to @c open().
+ * @param message_block A message block to receive initial data, as well
+ * as the local and remote addresses when the
+ * connection is made. Since the block receives
+ * the addresses regardless of whether or not
+ * initial data is available or requested, the
+ * message block size must be at least
+ * @a bytes_to_read plus two times the size of
+ * the addresses used (IPv4 or IPv6).
+ * @param bytes_to_read The maximum number of bytes of initial data
+ * to read into @a message_block.
+ * @param accept_handle The handle that the new connection will be
+ * accepted on. If @c INVALID_HANDLE, a new
+ * handle will be created using @a addr_family.
+ * @param act Value to be passed in result when operation
+ * completes.
+ * @param priority Priority of the operation. On POSIX4-Unix, this
+ * is supported. Works like @c 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 ignored.
+ * @param signal_number The POSIX4 real-time signal number to be used
+ * for the operation. Value range is from
+ * @c ACE_SIGRTMIN to @c ACE_SIGRTMAX.
+ * This argument is ignored on non-POSIX4 systems.
+ * @param addr_family The address family to use if @a accept_handle
+ * is @c ACE_INVALID_HANDLE and a new handle must
+ * be opened. Values are @c AF_INET and @c PF_INET6.
+ */
+ int accept (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ ACE_HANDLE accept_handle = ACE_INVALID_HANDLE,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN,
+ int addr_family = AF_INET);
+
+ /// Return the underlying implementation class.
+ // (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// 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.
+ size_t 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_Connect_Result_Impl;
+class ACE_Asynch_Connect_Impl;
+
+/**
+ * @class ACE_Asynch_Connect
+ *
+ * @brief This class is a factory for starting off asynchronous connects
+ * This class forwards all methods to its implementation class.
+ *
+ * Once @c open is called, multiple asynchronous connect operationss can
+ * started using this class. A ACE_Asynch_Connect::Result will
+ * be passed back to the associated ACE_Handler when the asynchronous connect
+ * completes through the ACE_Handler::handle_connect() callback.
+ */
+class ACE_Export ACE_Asynch_Connect : public ACE_Asynch_Operation
+{
+
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Connect (void);
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Connect (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call.
+ *
+ * @note @arg handle is ignored and should be @c ACE_INVALID_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 Connect.
+ */
+ int connect (ACE_HANDLE connect_handle,
+ const ACE_Addr & remote_sap,
+ const ACE_Addr & local_sap,
+ int reuse_addr,
+ const void *act=0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ // (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// Delegation/implementation class that all methods will be
+ /// forwarded to.
+ ACE_Asynch_Connect_Impl *implementation_;
+
+public:
+/**
+ * @class Result
+ *
+ * @brief This is that class which will be passed back to the
+ * handler when the asynchronous connect completes.
+ *
+ * This class has all the information necessary for the
+ * handler to uniquely identify the completion of the
+ * asynchronous connect.
+ */
+ class ACE_Export Result : public ACE_Asynch_Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Connect_Result;
+ friend class ACE_WIN32_Asynch_Connect_Result;
+
+ public:
+
+ /// I/O handle for the connection.
+ ACE_HANDLE connect_handle (void) const;
+
+ /// Get the implementation.
+ ACE_Asynch_Connect_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Contructor. Implementation will not be deleted.
+ Result (ACE_Asynch_Connect_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// Impelmentation class.
+ ACE_Asynch_Connect_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,
+ size_t bytes_to_write = 0,
+ unsigned long offset = 0,
+ unsigned long offset_high = 0,
+ size_t bytes_per_send = 0,
+ unsigned long flags = 0,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ // (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// 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.
+ size_t bytes_to_write (void) const;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ size_t bytes_per_send (void) const;
+
+ /// Flags which were passed into transmit file.
+ unsigned 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,
+ size_t header_bytes = 0,
+ ACE_Message_Block *trailer = 0,
+ size_t 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,
+ size_t header_bytes = 0,
+ ACE_Message_Block *trailer = 0,
+ size_t trailer_bytes = 0);
+
+ /// Get header which goes before the file data.
+ ACE_Message_Block *header (void) const;
+
+ /// Set header which goes before the file data.
+ void header (ACE_Message_Block *message_block);
+
+ /// Get size of the header data.
+ size_t header_bytes (void) const;
+
+ /// Set size of the header data.
+ void header_bytes (size_t bytes);
+
+ /// Get trailer which goes after the file data.
+ ACE_Message_Block *trailer (void) const;
+
+ /// Set trailer which goes after the file data.
+ void trailer (ACE_Message_Block *message_block);
+
+ /// Get size of the trailer data.
+ size_t trailer_bytes (void) const;
+
+ /// Set size of the trailer data.
+ void trailer_bytes (size_t bytes);
+
+ /// Conversion routine.
+ ACE_LPTRANSMIT_FILE_BUFFERS transmit_buffers (void);
+
+ protected:
+ /// Header data.
+ ACE_Message_Block *header_;
+
+ /// Size of header data.
+ size_t header_bytes_;
+
+ /// Trailer data.
+ ACE_Message_Block *trailer_;
+
+ /// Size of trailer data.
+ size_t 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.
+ // (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// 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.
+ size_t 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.
+ // (this should be protected...)
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const;
+
+protected:
+ /// Implementation class that all methods will be forwarded to.
+ ACE_Asynch_Write_Dgram_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.
+ */
+ 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.
+ size_t 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:
+ /// Constructor.
+ 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 connect completes.
+ virtual void handle_connect (const ACE_Asynch_Connect::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);
+
+ /**
+ * @class Proxy
+ *
+ * @brief The Proxy class acts as a proxy for dispatch of completions
+ * to operations issued for the associated handler. It allows the handler
+ * to be deleted while operations are outstanding. The proxy must be used
+ * to get the ACE_Handler pointer for dispatching, and if it's 0, the
+ * handler is no longer valid and the result should not be dispatched.
+ */
+ class ACE_Export Proxy
+ {
+ public:
+ Proxy (ACE_Handler *handler) : handler_ (handler) {};
+ void reset (void) { this->handler_ = 0; };
+ ACE_Handler *handler (void) { return this->handler_; };
+ private:
+ ACE_Handler *handler_;
+ };
+ typedef ACE_Refcounted_Auto_Ptr<Proxy, ACE_SYNCH_MUTEX>
+ Proxy_Ptr;
+
+ Proxy_Ptr &proxy (void);
+
+protected:
+ /// The proactor associated with this handler.
+ ACE_Proactor *proactor_;
+
+ /// The ACE_HANDLE in use with this handler.
+ ACE_HANDLE handle_;
+
+ /// Refers to proxy for this handler.
+ ACE_Refcounted_Auto_Ptr<Proxy, ACE_SYNCH_MUTEX> proxy_;
+
+ ACE_UNIMPLEMENTED_FUNC (ACE_Handler (const ACE_Handler &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Handler operator= (const ACE_Handler &))
+};
+
+// 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
+ * new connection is accepted. The handle for the new connection is
+ * passed along with the 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 *);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS*/
+#include /**/ "ace/post.h"
+#endif /* ACE_ASYNCH_IO_H */
diff --git a/ACE/ace/Asynch_IO_Impl.cpp b/ACE/ace/Asynch_IO_Impl.cpp
new file mode 100644
index 00000000000..5349f5e7ca1
--- /dev/null
+++ b/ACE/ace/Asynch_IO_Impl.cpp
@@ -0,0 +1,117 @@
+// $Id$
+
+#include "ace/Asynch_IO_Impl.h"
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || 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.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_Connect_Result_Impl::~ACE_Asynch_Connect_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Accept_Impl::~ACE_Asynch_Accept_Impl (void)
+{
+}
+
+ACE_Asynch_Connect_Impl::~ACE_Asynch_Connect_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)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
diff --git a/ACE/ace/Asynch_IO_Impl.h b/ACE/ace/Asynch_IO_Impl.h
new file mode 100644
index 00000000000..b2a308a7565
--- /dev/null
+++ b/ACE/ace/Asynch_IO_Impl.h
@@ -0,0 +1,816 @@
+/* -*- 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>
+ * @author Alexander Libman <alibman@ihug.com.au>
+ */
+//=============================================================================
+
+#ifndef ACE_ASYNCH_IO_IMPL_H
+#define ACE_ASYNCH_IO_IMPL_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_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
+// This only works on Win32 platforms and on Unix platforms supporting
+// aio calls.
+
+#include "ace/Asynch_IO.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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 size_t 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 (size_t bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error = 0) = 0;
+
+ /// Post @c 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 @a handle == ACE_INVALID_HANDLE,
+ * ACE_Handler::handle() will be called on the proxied handler to get the
+ * correct handle.
+ */
+ virtual int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 @a bytes_to_read will
+ /// be read and stored in the @a message_block.
+ virtual int read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ /**
+ * Same as above but with scatter support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ virtual int readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+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 size_t 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 @a bytes_to_write
+ /// will be written from the @a message_block.
+ virtual int write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ /**
+ * Same as above but with gather support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ virtual int writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+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 size_t 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 @a bytes_to_read will
+ * be read and stored in the @a message_block. The read will start
+ * at @a offset from the beginning of the file.
+ */
+ virtual int read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ /**
+ * Same as above but with scatter support, through chaining of composite
+ * message blocks using the continuation field.
+ * @note In win32 Each data block payload must be at least the size of a system
+ * memory page and must be aligned on a system memory page size boundary
+ */
+ virtual int readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+ /// This starts off an asynchronous read. Upto @a bytes_to_read will
+ /// be read and stored in the @a message_block.
+ virtual int read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ /**
+ * Same as above but with scatter support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ virtual int readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+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 @a bytes_to_write
+ * will be write and stored in the @a message_block. The write will
+ * start at @a offset from the beginning of the file.
+ */
+ virtual int write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ /**
+ * Same as above but with gather support, through chaining of composite
+ * message blocks using the continuation field.
+ * @note In win32 Each data block payload must be at least the size of a system
+ * memory page and must be aligned on a system memory page size boundary
+ */
+ virtual int writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+ /// This starts off an asynchronous write. Upto @a bytes_to_write
+ /// will be written from the @a message_block.
+ virtual int write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ /**
+ * Same as above but with gather support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ virtual int writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+#endif /* (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) */
+
+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 @a bytes_to_read will be read and stored in the
+ * @a message_block. The @a accept_handle will be used for the
+ * <accept> call. If (@a accept_handle == INVALID_HANDLE), a new
+ * handle will be created.
+ *
+ * @a 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,
+ size_t bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number,
+ int addr_family) = 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 size_t 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_Connect_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Connect.
+ *
+ */
+class ACE_Export ACE_Asynch_Connect_Impl : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ virtual ~ACE_Asynch_Connect_Impl (void);
+
+ /**
+ * This starts off an asynchronous connect
+ */
+ virtual int connect (ACE_HANDLE connect_handle,
+ const ACE_Addr & remote_sap,
+ const ACE_Addr & local_sap,
+ int reuse_addr,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Connect_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Connect_Result_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Connect.
+ *
+ */
+class ACE_Export ACE_Asynch_Connect_Result_Impl : public virtual ACE_Asynch_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Connect_Result_Impl (void);
+
+ /// I/O handle for the connection.
+ virtual ACE_HANDLE connect_handle (void) const = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Connect_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,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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 size_t bytes_to_write (void) const = 0;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ virtual size_t 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
+ * @a message_block. @a 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 @a 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 @a message_block's
+ * <wr_ptr>'s will be updated to reflect the added bytes for each
+ * @a message_block
+ *
+ * Priority of the operation is specified by @a 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, @a priority is a no-op.
+ * @a signal_number is the POSIX4 real-time signal number to be used
+ * for the operation. @a 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 size_t 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. @a 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 @a 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
+ * @a message_block's <rd_ptr>'s will be updated to reflect the bytes sent
+ * from each @a message_block.
+ *
+ * Priority of the operation is specified by @a 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.
+ * @a signal_number is the POSIX4 real-time signal number to be used
+ * for the operation. @a 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 size_t 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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Asynch_IO_Impl.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
+#include /**/ "ace/post.h"
+#endif /* ACE_ASYNCH_IO_IMPL_H */
diff --git a/ACE/ace/Asynch_IO_Impl.inl b/ACE/ace/Asynch_IO_Impl.inl
new file mode 100644
index 00000000000..495a768a972
--- /dev/null
+++ b/ACE/ace/Asynch_IO_Impl.inl
@@ -0,0 +1,106 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_Connect_Impl::ACE_Asynch_Connect_Impl (void)
+ : ACE_Asynch_Operation_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Connect_Result_Impl::ACE_Asynch_Connect_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 ()
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Asynch_Pseudo_Task.cpp b/ACE/ace/Asynch_Pseudo_Task.cpp
new file mode 100644
index 00000000000..6bc47866b6f
--- /dev/null
+++ b/ACE/ace/Asynch_Pseudo_Task.cpp
@@ -0,0 +1,130 @@
+// $Id$
+
+#include "ace/Asynch_Pseudo_Task.h"
+
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_signal.h"
+
+ACE_RCSID(ace, Asynch_Pseudo_Task, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Asynch_Pseudo_Task::ACE_Asynch_Pseudo_Task ()
+ : select_reactor_ (), // should be initialized before reactor_
+ reactor_ (&select_reactor_, 0) // don't delete implementation
+{
+}
+
+ACE_Asynch_Pseudo_Task::~ACE_Asynch_Pseudo_Task ()
+{
+ this->stop ();
+}
+
+int
+ACE_Asynch_Pseudo_Task::start (void)
+{
+ if (this->reactor_.initialized () == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%N:%l:%p\n"),
+ ACE_TEXT ("start reactor is not initialized")),
+ -1);
+
+ return this->activate () == -1 ? -1 : 0; // If started, return 0
+}
+
+int
+ACE_Asynch_Pseudo_Task::stop (void)
+{
+ if (this->thr_count () == 0) // already stopped
+ return 0;
+
+ if (this->reactor_.end_reactor_event_loop () == -1)
+ return -1;
+
+ this->wait ();
+ this->reactor_.close ();
+ return 0;
+}
+
+int
+ACE_Asynch_Pseudo_Task::svc (void)
+{
+#if !defined (ACE_WIN32)
+
+ sigset_t RT_signals;
+
+ sigemptyset (&RT_signals);
+ for (int si = ACE_SIGRTMIN; si <= ACE_SIGRTMAX; si++)
+ sigaddset (&RT_signals, si);
+
+ if (ACE_OS::pthread_sigmask (SIG_BLOCK, &RT_signals, 0) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Error:(%P | %t):%p\n"),
+ ACE_TEXT ("pthread_sigmask")));
+#endif
+
+ reactor_.owner (ACE_Thread::self ());
+ reactor_.run_reactor_event_loop ();
+
+ return 0;
+}
+
+
+
+int
+ACE_Asynch_Pseudo_Task::register_io_handler (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask,
+ int flg_suspend)
+{
+ // Register the handler with the reactor.
+ if (-1 == this->reactor_.register_handler (handle, handler, mask))
+ return -1;
+
+ if (flg_suspend == 0)
+ return 0;
+
+ // Suspend the handle now. Enable only when the accept is issued
+ // by the application.
+ if (this->reactor_.suspend_handler (handle) == -1)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l:%p\n"),
+ ACE_TEXT ("register_io_handler (suspended)")));
+ this->reactor_.remove_handler (handle, ACE_Event_Handler::ALL_EVENTS_MASK
+ | ACE_Event_Handler::DONT_CALL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Asynch_Pseudo_Task::remove_io_handler (ACE_HANDLE handle)
+{
+ return this->reactor_.remove_handler (handle,
+ ACE_Event_Handler::ALL_EVENTS_MASK
+ | ACE_Event_Handler::DONT_CALL);
+}
+
+int
+ACE_Asynch_Pseudo_Task::remove_io_handler (ACE_Handle_Set &set)
+{
+ return this->reactor_.remove_handler (set, ACE_Event_Handler::ALL_EVENTS_MASK
+ | ACE_Event_Handler::DONT_CALL);
+}
+
+int
+ACE_Asynch_Pseudo_Task::suspend_io_handler (ACE_HANDLE handle)
+{
+ return this->reactor_.suspend_handler (handle);
+}
+
+int
+ACE_Asynch_Pseudo_Task::resume_io_handler (ACE_HANDLE handle)
+{
+ return this->reactor_.resume_handler (handle);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Asynch_Pseudo_Task.h b/ACE/ace/Asynch_Pseudo_Task.h
new file mode 100644
index 00000000000..235d71411ba
--- /dev/null
+++ b/ACE/ace/Asynch_Pseudo_Task.h
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Asynch_Pseudo_Task.h
+ *
+ * $Id$
+ *
+ * @author Alexander Libman <alibman@ihug.com.au>
+ */
+//=============================================================================
+
+#ifndef ACE_ASYNCH_PSEUDO_TASK_H
+#define ACE_ASYNCH_PSEUDO_TASK_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/Reactor.h"
+#include "ace/Select_Reactor.h"
+#include "ace/Task.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/*
+ * Specialization hook to replace the Reactor with the
+ * concrete Reactor implementation, e.g., select_st,
+ * select_mt etc.
+ */
+//@@ REACTOR_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
+
+/**
+ * @class ACE_Asynch_Pseudo_Task
+ *
+ */
+class ACE_Export ACE_Asynch_Pseudo_Task : public ACE_Task<ACE_NULL_SYNCH>
+{
+public:
+ ACE_Asynch_Pseudo_Task();
+ virtual ~ACE_Asynch_Pseudo_Task();
+
+ int start (void);
+ int stop (void);
+
+ int register_io_handler (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask,
+ int flg_suspend);
+
+ int remove_io_handler (ACE_HANDLE handle);
+ int remove_io_handler (ACE_Handle_Set &set);
+ int resume_io_handler (ACE_HANDLE handle);
+ int suspend_io_handler (ACE_HANDLE handle);
+
+protected:
+ virtual int svc (void);
+
+ /// Should be initialized before reactor_
+ ACE_Select_Reactor select_reactor_;
+
+ ACE_Reactor reactor_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ASYNCH_PSEUDO_TASK_H */
diff --git a/ACE/ace/Atomic_Op.cpp b/ACE/ace/Atomic_Op.cpp
new file mode 100644
index 00000000000..9076b9f67ed
--- /dev/null
+++ b/ACE/ace/Atomic_Op.cpp
@@ -0,0 +1,310 @@
+// $Id$
+
+#include "ace/Atomic_Op.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID (ace,
+ Atomic_Op,
+ "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Atomic_Op.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
+
+#if defined (ACE_INCLUDE_ATOMIC_OP_SPARC)
+# include "ace/Atomic_Op_Sparc.h"
+#endif /* ACE_INCLUDE_ATOMIC_OP_SPARC */
+
+namespace {
+
+#if defined (_MSC_VER)
+// Disable "no return value" warning, as we will be putting
+// the return values directly into the EAX register.
+#pragma warning (push)
+#pragma warning (disable: 4035)
+#endif /* _MSC_VER */
+
+long
+single_cpu_increment (volatile long *value)
+{
+#if defined (ACE_HAS_INTEL_ASSEMBLY)
+ long tmp = 1;
+ unsigned long addr = reinterpret_cast<unsigned long> (value);
+ asm( "xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
+ return tmp + 1;
+#elif defined (sun) || \
+ (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
+ return ace_atomic_add_long (
+ reinterpret_cast<volatile unsigned long*> (value), 1);
+#elif defined(__GNUC__) && defined(PPC)
+ long tmp;
+ asm("lwz %0,%1" : "=r" (tmp) : "m" (*value) );
+ asm("addi %0,%0,1" : "+r" (tmp) );
+ asm("stw %0,%1" : "+r" (tmp), "=m" (*value) );
+ return tmp;
+#else /* ACE_HAS_INTEL_ASSEMBLY*/
+ ACE_UNUSED_ARG (value);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_INTEL_ASSEMBLY*/
+}
+
+long
+single_cpu_decrement (volatile long *value)
+{
+#if defined (ACE_HAS_INTEL_ASSEMBLY)
+ long tmp = -1;
+ unsigned long addr = reinterpret_cast<unsigned long> (value);
+ asm( "xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
+ return tmp - 1;
+#elif defined (sun) || \
+ (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
+ return ace_atomic_add_long (
+ reinterpret_cast<volatile unsigned long*> (value), -1);
+#elif defined(__GNUC__) && defined(PPC)
+ long tmp;
+ asm("lwz %0,%1" : "=r" (tmp) : "m" (*value) );
+ asm("addi %0,%0,-1" : "+r" (tmp) );
+ asm("stw %0,%1" : "+r" (tmp), "=m" (*value) );
+ return tmp;
+#else /* ACE_HAS_INTEL_ASSEMBLY*/
+ ACE_UNUSED_ARG (value);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_INTEL_ASSEMBLY*/
+}
+
+long
+single_cpu_exchange (volatile long *value, long rhs)
+{
+#if defined (ACE_HAS_INTEL_ASSEMBLY)
+ unsigned long addr = reinterpret_cast<unsigned long> (value);
+ asm( "xchg %0, (%1)" : "+r"(rhs) : "r"(addr) );
+ return rhs;
+#elif defined (sun) || \
+ (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
+ return ace_atomic_swap_long (
+ reinterpret_cast<volatile unsigned long*> (value), rhs);
+#elif defined(__GNUC__) && defined(PPC)
+ long tmp;
+ asm("lwz %0,%1" : "=r" (tmp) : "m" (rhs) );
+ asm("stw %0,%1" : "+r" (tmp), "=m" (*value) );
+ return tmp;
+#else /* ACE_HAS_INTEL_ASSEMBLY*/
+ ACE_UNUSED_ARG (value);
+ ACE_UNUSED_ARG (rhs);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_INTEL_ASSEMBLY*/
+}
+
+long
+single_cpu_exchange_add (volatile long *value, long rhs)
+{
+#if defined (ACE_HAS_INTEL_ASSEMBLY)
+ unsigned long addr = reinterpret_cast<unsigned long> (value);
+ asm( "xadd %0, (%1)" : "+r"(rhs) : "r"(addr) );
+ return rhs;
+#elif defined (sun) || \
+ (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
+ return ace_atomic_swap_add_long (
+ reinterpret_cast<volatile unsigned long*> (value), rhs);
+#elif defined(__GNUC__) && defined(PPC)
+ long tmp;
+ asm("add %0,%1,%2" : "=r" (tmp) : "r" (*value), "r" (rhs) );
+ asm("stw %0,%1" : "+r" (tmp), "=m" (*value) );
+ return tmp;
+#elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
+# if defined (_MSC_VER)
+ __asm
+ {
+ mov eax, rhs
+ mov edx, value
+ xadd [edx], eax
+ }
+ // Return value is already in EAX register.
+# elif defined (__BORLANDC__)
+ _EAX = rhs;
+ _EDX = reinterpret_cast<unsigned long> (value);
+ __emit__(0x0F, 0xC1, 0x02); // xadd [edx], eax
+ // Return value is already in EAX register.
+# else /* _MSC_VER */
+ ACE_UNUSED_ARG (value);
+ ACE_UNUSED_ARG (rhs);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* _MSC_VER */
+#else /* ACE_HAS_INTEL_ASSEMBLY*/
+ ACE_UNUSED_ARG (value);
+ ACE_UNUSED_ARG (rhs);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_INTEL_ASSEMBLY*/
+}
+
+long
+multi_cpu_increment (volatile long *value)
+{
+#if defined (ACE_HAS_INTEL_ASSEMBLY)
+ long tmp = 1;
+ unsigned long addr = reinterpret_cast<unsigned long> (value);
+ asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
+ return tmp + 1;
+#elif defined (sun) || \
+ (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
+ return ace_atomic_add_long (
+ reinterpret_cast<volatile unsigned long*> (value), 1);
+#else /* ACE_HAS_INTEL_ASSEMBLY*/
+ ACE_UNUSED_ARG (value);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_INTEL_ASSEMBLY*/
+}
+
+long
+multi_cpu_decrement (volatile long *value)
+{
+#if defined (ACE_HAS_INTEL_ASSEMBLY)
+ long tmp = -1;
+ unsigned long addr = reinterpret_cast<unsigned long> (value);
+ asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
+ return tmp - 1;
+#elif defined (sun) || \
+ (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
+ return ace_atomic_add_long (
+ reinterpret_cast<volatile unsigned long*> (value), -1);
+#else /* ACE_HAS_INTEL_ASSEMBLY*/
+ ACE_UNUSED_ARG (value);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_INTEL_ASSEMBLY*/
+}
+
+long
+multi_cpu_exchange (volatile long *value, long rhs)
+{
+#if defined (ACE_HAS_INTEL_ASSEMBLY)
+ unsigned long addr = reinterpret_cast<unsigned long> (value);
+ // The XCHG instruction automatically follows LOCK semantics
+ asm( "xchg %0, (%1)" : "+r"(rhs) : "r"(addr) );
+ return rhs;
+#elif defined (sun) || \
+ (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
+ return ace_atomic_swap_long (
+ reinterpret_cast<volatile unsigned long*> (value), rhs);
+#else /* ACE_HAS_INTEL_ASSEMBLY*/
+ ACE_UNUSED_ARG (value);
+ ACE_UNUSED_ARG (rhs);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_INTEL_ASSEMBLY*/
+}
+
+long
+multi_cpu_exchange_add (volatile long *value, long rhs)
+{
+#if defined (ACE_HAS_INTEL_ASSEMBLY)
+ unsigned long addr = reinterpret_cast<unsigned long> (value);
+ asm( "lock ; xadd %0, (%1)" : "+r"(rhs) : "r"(addr) );
+ return rhs;
+#elif defined (sun) || \
+ (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
+ return ace_atomic_swap_add_long (
+ reinterpret_cast<volatile unsigned long*> (value), rhs);
+#elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
+# if defined (_MSC_VER)
+ __asm
+ {
+ mov eax, rhs
+ mov edx, value
+ lock xadd [edx], eax
+ }
+ // Return value is already in EAX register.
+# elif defined (__BORLANDC__)
+ _EAX = rhs;
+ _EDX = reinterpret_cast<unsigned long> (value);
+ __emit__(0xF0, 0x0F, 0xC1, 0x02); // lock xadd [edx], eax
+ // Return value is already in EAX register.
+# else /* _MSC_VER */
+ ACE_UNUSED_ARG (value);
+ ACE_UNUSED_ARG (rhs);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* _MSC_VER */
+#else /* ACE_HAS_INTEL_ASSEMBLY*/
+ ACE_UNUSED_ARG (value);
+ ACE_UNUSED_ARG (rhs);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_INTEL_ASSEMBLY*/
+}
+
+#if defined (_MSC_VER)
+#pragma warning (pop)
+#endif /* _MSC_VER */
+
+} // end namespace
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::increment_fn_) (volatile long *) = multi_cpu_increment;
+long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::decrement_fn_) (volatile long *) = multi_cpu_decrement;
+long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::exchange_fn_) (volatile long *, long) = multi_cpu_exchange;
+long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::exchange_add_fn_) (volatile long *, long) = multi_cpu_exchange_add;
+
+void
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::init_functions (void)
+{
+ if (ACE_OS::num_processors () == 1)
+ {
+ increment_fn_ = single_cpu_increment;
+ decrement_fn_ = single_cpu_decrement;
+ exchange_fn_ = single_cpu_exchange;
+ exchange_add_fn_ = single_cpu_exchange_add;
+ }
+ else
+ {
+ increment_fn_ = multi_cpu_increment;
+ decrement_fn_ = multi_cpu_decrement;
+ exchange_fn_ = multi_cpu_exchange;
+ exchange_add_fn_ = multi_cpu_exchange_add;
+ }
+}
+
+void
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+long (*ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::increment_fn_) (volatile long *) = multi_cpu_increment;
+long (*ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::decrement_fn_) (volatile long *) = multi_cpu_decrement;
+long (*ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::exchange_fn_) (volatile long *, long) = multi_cpu_exchange;
+long (*ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::exchange_add_fn_) (volatile long *, long) = multi_cpu_exchange_add;
+
+void
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::init_functions (void)
+{
+ if (ACE_OS::num_processors () == 1)
+ {
+ increment_fn_ = single_cpu_increment;
+ decrement_fn_ = single_cpu_decrement;
+ exchange_fn_ = single_cpu_exchange;
+ exchange_add_fn_ = single_cpu_exchange_add;
+ }
+ else
+ {
+ increment_fn_ = multi_cpu_increment;
+ decrement_fn_ = multi_cpu_decrement;
+ exchange_fn_ = multi_cpu_exchange;
+ exchange_add_fn_ = multi_cpu_exchange_add;
+ }
+}
+
+void
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_BUILTIN_ATOMIC_OP */
diff --git a/ACE/ace/Atomic_Op.h b/ACE/ace/Atomic_Op.h
new file mode 100644
index 00000000000..24abb64ef1d
--- /dev/null
+++ b/ACE/ace/Atomic_Op.h
@@ -0,0 +1,260 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Atomic_Op.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ATOMIC_OP_H
+#define ACE_ATOMIC_OP_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/Thread_Mutex.h"
+
+// Include the templates here.
+#include "ace/Atomic_Op_T.h"
+
+// Determine whether builtin atomic op support is
+// available on this platform.
+#if defined (ACE_HAS_THREADS)
+# if defined (WIN32)
+# if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+# define ACE_HAS_BUILTIN_ATOMIC_OP
+# endif /* ACE_HAS_INTRINSIC_INTERLOCKED */
+# if defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
+# define ACE_HAS_BUILTIN_ATOMIC_OP
+# else /* ACE_HAS_INTERLOCKED_EXCHANGEADD */
+ // Inline assembly emulation of InterlockedExchangeAdd
+ // is currently only implemented for MSVC (x86 only) and Borland.
+# if (defined (_MSC_VER) && defined (_M_IX86)) || defined (__BORLANDC__)
+# define ACE_HAS_BUILTIN_ATOMIC_OP
+# endif /* _MSC_VER || __BORLANDC__ */
+# endif /* ACE_HAS_INTERLOCKED_EXCHANGEADD */
+# elif defined (ACE_HAS_INTEL_ASSEMBLY)
+# define ACE_HAS_BUILTIN_ATOMIC_OP
+# endif /* WIN32 */
+#endif /* ACE_HAS_THREADS */
+
+#if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Atomic_Op<ACE_Thread_Mutex, long>
+ *
+ * @brief Specialization of ACE_Atomic_Op for platforms that
+ * support atomic integer operations.
+ *
+ * Specialization of ACE_Atomic_Op for platforms that support atomic
+ * integer operations.
+ */
+template<>
+class ACE_Export ACE_Atomic_Op<ACE_Thread_Mutex, long>
+{
+public:
+ /// Initialize <value_> to 0.
+ ACE_Atomic_Op (void);
+
+ /// Initialize <value_> to c.
+ ACE_Atomic_Op (long c);
+
+ /// Manage copying...
+ ACE_Atomic_Op (const ACE_Atomic_Op<ACE_Thread_Mutex, long> &c);
+
+ /// Atomically pre-increment <value_>.
+ long operator++ (void);
+
+ /// Atomically post-increment <value_>.
+ long operator++ (int);
+
+ /// Atomically increment <value_> by rhs.
+ long operator+= (long rhs);
+
+ /// Atomically pre-decrement <value_>.
+ long operator-- (void);
+
+ /// Atomically post-decrement <value_>.
+ long operator-- (int);
+
+ /// Atomically decrement <value_> by rhs.
+ long operator-= (long rhs);
+
+ /// Atomically compare <value_> with rhs.
+ bool operator== (long rhs) const;
+
+ /// Atomically compare <value_> with rhs.
+ bool operator!= (long rhs) const;
+
+ /// Atomically check if <value_> greater than or equal to rhs.
+ bool operator>= (long rhs) const;
+
+ /// Atomically check if <value_> greater than rhs.
+ bool operator> (long rhs) const;
+
+ /// Atomically check if <value_> less than or equal to rhs.
+ bool operator<= (long rhs) const;
+
+ /// Atomically check if <value_> less than rhs.
+ bool operator< (long rhs) const;
+
+ /// Atomically assign rhs to <value_>.
+ ACE_Atomic_Op<ACE_Thread_Mutex, long> &operator= (long rhs);
+
+ /// Atomically assign <rhs> to <value_>.
+ ACE_Atomic_Op<ACE_Thread_Mutex, long> &operator= (const ACE_Atomic_Op<ACE_Thread_Mutex, long> &rhs);
+
+ /// Explicitly return <value_>.
+ long value (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Explicitly return <value_> (by reference).
+ volatile long &value_i (void);
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+ /// Used during ACE object manager initialization to optimize the fast
+ /// atomic op implementation according to the number of CPUs.
+ static void init_functions (void);
+
+private:
+
+ // This function cannot be supported by this template specialization.
+ // If you need access to an underlying lock, use the ACE_Atomic_Op_Ex
+ // template instead.
+ ACE_Thread_Mutex &mutex (void);
+
+private:
+
+ /// Current object decorated by the atomic op.
+ volatile long value_;
+
+ // Pointers to selected atomic op implementations.
+ static long (*increment_fn_) (volatile long *);
+ static long (*decrement_fn_) (volatile long *);
+ static long (*exchange_fn_) (volatile long *, long);
+ static long (*exchange_add_fn_) (volatile long *, long);
+};
+
+/**
+ * @class ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>
+ *
+ * @brief Specialization of ACE_Atomic_Op for platforms that
+ * support atomic integer operations.
+ *
+ * Specialization of ACE_Atomic_Op for platforms that support atomic
+ * integer operations.
+ */
+template<>
+class ACE_Export ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>
+{
+public:
+ /// Initialize <value_> to 0.
+ ACE_Atomic_Op (void);
+
+ /// Initialize <value_> to c.
+ ACE_Atomic_Op (unsigned long c);
+
+ /// Manage copying...
+ ACE_Atomic_Op (const ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> &c);
+
+ /// Atomically pre-increment <value_>.
+ unsigned long operator++ (void);
+
+ /// Atomically post-increment <value_>.
+ unsigned long operator++ (int);
+
+ /// Atomically increment <value_> by rhs.
+ unsigned long operator+= (unsigned long rhs);
+
+ /// Atomically pre-decrement <value_>.
+ unsigned long operator-- (void);
+
+ /// Atomically post-decrement <value_>.
+ unsigned long operator-- (int);
+
+ /// Atomically decrement <value_> by rhs.
+ unsigned long operator-= (unsigned long rhs);
+
+ /// Atomically compare <value_> with rhs.
+ bool operator== (unsigned long rhs) const;
+
+ /// Atomically compare <value_> with rhs.
+ bool operator!= (unsigned long rhs) const;
+
+ /// Atomically check if <value_> greater than or equal to rhs.
+ bool operator>= (unsigned long rhs) const;
+
+ /// Atomically check if <value_> greater than rhs.
+ bool operator> (unsigned long rhs) const;
+
+ /// Atomically check if <value_> less than or equal to rhs.
+ bool operator<= (unsigned long rhs) const;
+
+ /// Atomically check if <value_> less than rhs.
+ bool operator< (unsigned long rhs) const;
+
+ /// Atomically assign rhs to <value_>.
+ ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> &operator= (unsigned long rhs);
+
+ /// Atomically assign <rhs> to <value_>.
+ ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> &operator= (const ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> &rhs);
+
+ /// Explicitly return <value_>.
+ unsigned long value (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Explicitly return <value_> (by reference).
+ volatile unsigned long &value_i (void);
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+ /// Used during ACE object manager initialization to optimize the fast
+ /// atomic op implementation according to the number of CPUs.
+ static void init_functions (void);
+
+private:
+
+ // This function cannot be supported by this template specialization.
+ // If you need access to an underlying lock, use the ACE_Atomic_Op_Ex
+ // template instead.
+ ACE_Thread_Mutex &mutex (void);
+
+private:
+
+ /// Current object decorated by the atomic op.
+ volatile unsigned long value_;
+
+ // Pointers to selected atomic op implementations.
+ static long (*increment_fn_) (volatile long *);
+ static long (*decrement_fn_) (volatile long *);
+ static long (*exchange_fn_) (volatile long *, long);
+ static long (*exchange_add_fn_) (volatile long *, long);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_BUILTIN_ATOMIC_OP */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Atomic_Op.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /*ACE_ATOMIC_OP_H*/
diff --git a/ACE/ace/Atomic_Op.inl b/ACE/ace/Atomic_Op.inl
new file mode 100644
index 00000000000..4d55f05b091
--- /dev/null
+++ b/ACE/ace/Atomic_Op.inl
@@ -0,0 +1,335 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
+
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+# include "ace/os_include/os_intrin.h"
+
+#pragma intrinsic (_InterlockedExchange, _InterlockedExchangeAdd, _InterlockedIncrement, _InterlockedDecrement)
+#endif /* ACE_HAS_INTRINSIC_INTERLOCKED */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::ACE_Atomic_Op (void)
+ : value_ (0)
+{
+}
+
+ACE_INLINE
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::ACE_Atomic_Op (long c)
+ : value_ (c)
+{
+}
+
+ACE_INLINE
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::ACE_Atomic_Op (
+ const ACE_Atomic_Op<ACE_Thread_Mutex, long> &rhs)
+ : value_ (rhs.value_)
+{
+}
+
+ACE_INLINE long
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator++ (void)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ return ::_InterlockedIncrement (const_cast<long *> (&this->value_));
+#elif defined (WIN32)
+ return ::InterlockedIncrement (const_cast<long *> (&this->value_));
+#else /* WIN32 */
+ return (*increment_fn_) (&this->value_);
+#endif /* WIN32 */
+}
+
+ACE_INLINE long
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator++ (int)
+{
+ return ++*this - 1;
+}
+
+ACE_INLINE long
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator-- (void)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ return ::_InterlockedDecrement (const_cast<long *> (&this->value_));
+#elif defined (WIN32)
+ return ::InterlockedDecrement (const_cast<long *> (&this->value_));
+#else /* WIN32 */
+ return (*decrement_fn_) (&this->value_);
+#endif /* WIN32 */
+}
+
+ACE_INLINE long
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator-- (int)
+{
+ return --*this + 1;
+}
+
+ACE_INLINE long
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator+= (long rhs)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ return ::_InterlockedExchangeAdd (const_cast<long *> (&this->value_),
+ rhs) + rhs;
+#elif defined (WIN32) && defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
+ return ::InterlockedExchangeAdd (const_cast<long *> (&this->value_),
+ rhs) + rhs;
+#else /* WIN32 && ACE_HAS_INTERLOCKED_EXCHANGEADD */
+ return (*exchange_add_fn_) (&this->value_, rhs) + rhs;
+#endif /* WIN32 && ACE_HAS_INTERLOCKED_EXCHANGEADD */
+}
+
+ACE_INLINE long
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator-= (long rhs)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ return ::_InterlockedExchangeAdd (const_cast<long *> (&this->value_),
+ -rhs) - rhs;
+#elif defined (WIN32) && defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
+ return ::InterlockedExchangeAdd (const_cast<long *> (&this->value_),
+ -rhs) - rhs;
+#else /* WIN32 && ACE_HAS_INTERLOCKED_EXCHANGEADD */
+ return (*exchange_add_fn_) (&this->value_, -rhs) - rhs;
+#endif /* WIN32 && ACE_HAS_INTERLOCKED_EXCHANGEADD */
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator== (long rhs) const
+{
+ return (this->value_ == rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator!= (long rhs) const
+{
+ return (this->value_ != rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator>= (long rhs) const
+{
+ return (this->value_ >= rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator> (long rhs) const
+{
+ return (this->value_ > rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator<= (long rhs) const
+{
+ return (this->value_ <= rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator< (long rhs) const
+{
+ return (this->value_ < rhs);
+}
+
+ACE_INLINE ACE_Atomic_Op<ACE_Thread_Mutex, long> &
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator= (long rhs)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ ::_InterlockedExchange (const_cast<long *> (&this->value_), rhs);
+#elif defined (WIN32)
+ ::InterlockedExchange (const_cast<long *> (&this->value_), rhs);
+#else /* WIN32 */
+ (*exchange_fn_) (&this->value_, rhs);
+#endif /* WIN32 */
+ return *this;
+}
+
+ACE_INLINE ACE_Atomic_Op<ACE_Thread_Mutex, long> &
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator= (
+ const ACE_Atomic_Op<ACE_Thread_Mutex, long> &rhs)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ ::_InterlockedExchange (const_cast<long *> (&this->value_), rhs.value_);
+#elif defined (WIN32)
+ ::InterlockedExchange (const_cast<long *> (&this->value_), rhs.value_);
+#else /* WIN32 */
+ (*exchange_fn_) (&this->value_, rhs.value_);
+#endif /* WIN32 */
+ return *this;
+}
+
+ACE_INLINE long
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::value (void) const
+{
+ return this->value_;
+}
+
+ACE_INLINE volatile long &
+ACE_Atomic_Op<ACE_Thread_Mutex, long>::value_i (void)
+{
+ return this->value_;
+}
+
+
+ACE_INLINE
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::ACE_Atomic_Op (void)
+ : value_ (0)
+{
+}
+
+ACE_INLINE
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::ACE_Atomic_Op (unsigned long c)
+ : value_ (c)
+{
+}
+
+ACE_INLINE
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::ACE_Atomic_Op (
+ const ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> &rhs)
+ : value_ (rhs.value_)
+{
+}
+
+ACE_INLINE unsigned long
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator++ (void)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ return static_cast<unsigned long> (::_InterlockedIncrement (const_cast<long *> (reinterpret_cast<volatile long *>(&this->value_))));
+#elif defined (WIN32)
+ return static_cast<unsigned long> (::InterlockedIncrement (const_cast<long *> (reinterpret_cast<volatile long *>(&this->value_))));
+#else /* WIN32 */
+ return static_cast<unsigned long> ((*increment_fn_) (reinterpret_cast<volatile long *> (&this->value_)));
+#endif /* WIN32 */
+}
+
+ACE_INLINE unsigned long
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator++ (int)
+{
+ return ++*this - 1;
+}
+
+ACE_INLINE unsigned long
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator-- (void)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ return static_cast<unsigned long> (::_InterlockedDecrement (const_cast<long *> (reinterpret_cast<volatile long *>(&this->value_))));
+#elif defined (WIN32)
+ return static_cast<unsigned long> (::InterlockedDecrement (const_cast<long *> (reinterpret_cast<volatile long *>(&this->value_))));
+#else /* WIN32 */
+ return static_cast<unsigned long> ((*decrement_fn_) (reinterpret_cast<volatile long *> (&this->value_)));
+#endif /* WIN32 */
+}
+
+ACE_INLINE unsigned long
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator-- (int)
+{
+ return --*this + 1;
+}
+
+ACE_INLINE unsigned long
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator+= (unsigned long rhs)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ return static_cast<unsigned long> (::_InterlockedExchangeAdd (const_cast<long *> (reinterpret_cast <volatile long *>(&this->value_)),
+ rhs)) + rhs;
+#elif defined (WIN32) && defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
+ return static_cast<unsigned long> (::InterlockedExchangeAdd (const_cast<long *> (reinterpret_cast <volatile long *>(&this->value_)),
+ rhs)) + rhs;
+#else /* WIN32 && ACE_HAS_INTERLOCKED_EXCHANGEADD */
+ return static_cast<unsigned long> ((*exchange_add_fn_) (reinterpret_cast<volatile long *> (&this->value_), rhs)) + rhs;
+#endif /* WIN32 && ACE_HAS_INTERLOCKED_EXCHANGEADD */
+}
+
+ACE_INLINE unsigned long
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator-= (unsigned long rhs)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ return static_cast<unsigned long> (::_InterlockedExchangeAdd (const_cast<long *> (reinterpret_cast<volatile long *>(&this->value_)),
+ -static_cast<long>(rhs))) - rhs;
+#elif defined (WIN32) && defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
+ return static_cast<unsigned long> (::InterlockedExchangeAdd (const_cast<long *> (reinterpret_cast<volatile long *>(&this->value_)),
+ -static_cast<long>(rhs))) - rhs;
+#else /* WIN32 && ACE_HAS_INTERLOCKED_EXCHANGEADD */
+ long l_rhs = static_cast<long> (rhs);
+ return static_cast<unsigned long> ((*exchange_add_fn_) (reinterpret_cast<volatile long *> (&this->value_), -l_rhs)) - rhs;
+#endif /* WIN32 && ACE_HAS_INTERLOCKED_EXCHANGEADD */
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator== (unsigned long rhs) const
+{
+ return (this->value_ == rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator!= (unsigned long rhs) const
+{
+ return (this->value_ != rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator>= (unsigned long rhs) const
+{
+ return (this->value_ >= rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator> (unsigned long rhs) const
+{
+ return (this->value_ > rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator<= (unsigned long rhs) const
+{
+ return (this->value_ <= rhs);
+}
+
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator< (unsigned long rhs) const
+{
+ return (this->value_ < rhs);
+}
+
+ACE_INLINE ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> &
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator= (unsigned long rhs)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ ::_InterlockedExchange (const_cast<long *> (reinterpret_cast<volatile long*> (&this->value_)), rhs);
+#elif defined (WIN32)
+ ::InterlockedExchange (const_cast<long *> (reinterpret_cast<volatile long*> (&this->value_)), rhs);
+#else /* WIN32 */
+ (*exchange_fn_) (reinterpret_cast<volatile long *> (&this->value_), rhs);
+#endif /* WIN32 */
+ return *this;
+}
+
+ACE_INLINE ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> &
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator= (
+ const ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> &rhs)
+{
+#if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
+ ::_InterlockedExchange (const_cast<long *> (reinterpret_cast<volatile long*> (&this->value_)), rhs.value_);
+#elif defined (WIN32)
+ ::InterlockedExchange (const_cast<long *> (reinterpret_cast<volatile long*> (&this->value_)), rhs.value_);
+#else /* WIN32 */
+ (*exchange_fn_) (reinterpret_cast<volatile long *> (&this->value_), rhs.value_);
+#endif /* WIN32 */
+ return *this;
+}
+
+ACE_INLINE unsigned long
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::value (void) const
+{
+ return this->value_;
+}
+
+ACE_INLINE volatile unsigned long &
+ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::value_i (void)
+{
+ return this->value_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_BUILTIN_ATOMIC_OP */
diff --git a/ACE/ace/Atomic_Op_Sparc.c b/ACE/ace/Atomic_Op_Sparc.c
new file mode 100644
index 00000000000..75d64eb6ac5
--- /dev/null
+++ b/ACE/ace/Atomic_Op_Sparc.c
@@ -0,0 +1,187 @@
+/* $Id$
+ *
+ * This is a C file for a reason. The Sun C++ compiler does not accept
+ * inline assembler.
+ *
+ * Portions of this code are based on atomic operations found in the
+ * linux kernel source code.
+ */
+
+#if defined (ACE_INCLUDE_ATOMIC_OP_SPARC)
+
+#if defined(__i386) && defined(__SUNPRO_C)
+static void
+__sunpro_asm_code() {
+ __asm("\n\
+ .globl ace_atomic_add_long \n\
+ .type ace_atomic_add_long,@function \n\
+ .align 4 \n\
+ace_atomic_add_long: \n\
+ movl 0x00000004(%esp), %edx \n\
+ movl 0x00000008(%esp), %eax \n\
+ lock; xadd %eax, (%edx) \n\
+ addl 0x00000008(%esp), %eax \n\
+ ret \n\
+ ");
+
+ __asm("\n\
+ .globl ace_atomic_swap_long \n\
+ .type ace_atomic_swap_long,@function \n\
+ .align 4 \n\
+ace_atomic_swap_long: \n\
+ movl 0x00000004(%esp), %edx \n\
+ movl 0x00000008(%esp), %eax \n\
+ xchg %eax, (%edx) \n\
+ ret \n\
+ ");
+
+ __asm("\n\
+ .globl ace_atomic_swap_add_long \n\
+ .type ace_atomic_swap_add_long,@function \n\
+ .align 4 \n\
+ace_atomic_swap_add_long: \n\
+ movl 0x00000004(%esp), %edx \n\
+ movl 0x00000008(%esp), %eax \n\
+ lock; xadd %eax, (%edx) \n\
+ ret \n\
+ ");
+}
+
+#elif defined(__x86_64) && defined(__SUNPRO_C)
+
+static void
+__sunpro_asm_code() {
+ __asm("\n\
+ .globl ace_atomic_add_long \n\
+ .type ace_atomic_add_long,@function \n\
+ .align 16 \n\
+ace_atomic_add_long: \n\
+ movq %rsi, %rax \n\
+ lock; xaddq %rax, (%rdi) \n\
+ addq %rsi, %rax \n\
+ ret \n\
+ ");
+
+ __asm("\n\
+ .globl ace_atomic_swap_long \n\
+ .type ace_atomic_swap_long,@function \n\
+ .align 16 \n\
+ace_atomic_swap_long: \n\
+ xchgq %rsi, (%rdi) \n\
+ movq %rsi, %rax \n\
+ ret \n\
+ ");
+
+ __asm("\n\
+ .globl ace_atomic_swap_add_long \n\
+ .type ace_atomic_swap_add_long,@function \n\
+ .align 16 \n\
+ace_atomic_swap_add_long: \n\
+ lock; xaddq %rsi, (%rdi) \n\
+ movq %rsi, %rax \n\
+ ret \n\
+ ");
+}
+
+#elif defined (__sparcv9)
+
+unsigned long
+ace_atomic_add_long (volatile unsigned long *dest, long rhs)
+{
+ __asm ("restore\n"
+ "ldx [%o0], %o2\n"
+ ".again_add:\n"
+ "add %o2, %o1, %o3\n"
+ "casx [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %xcc, .again_add\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "add %o2, %o1, %o0\n");
+}
+
+unsigned long
+ace_atomic_swap_long (volatile unsigned long *dest, unsigned long rhs)
+{
+ __asm ("restore\n"
+ "ldx [%o0], %o2\n"
+ ".again_swap:\n"
+ "mov %o1, %o3\n"
+ "casx [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %xcc, .again_swap\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "mov %o3, %o0\n");
+}
+
+unsigned long
+ace_atomic_swap_add_long (volatile unsigned long *dest, long rhs)
+{
+ __asm ("restore\n"
+ "ldx [%o0], %o2\n"
+ ".again_swap_add:\n"
+ "mov %o2, %o4\n"
+ "add %o2, %o1, %o3\n"
+ "casx [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %xcc, .again_swap_add\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "mov %o4, %o0\n");
+}
+
+#else
+
+unsigned long
+ace_atomic_add_long (volatile unsigned long *dest, long rhs)
+{
+ __asm ("restore\n"
+ "ld [%o0], %o2\n"
+ ".again_add:\n"
+ "add %o2, %o1, %o3\n"
+ "cas [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %icc, .again_add\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "add %o2, %o1, %o0\n");
+}
+
+unsigned long
+ace_atomic_swap_long (volatile unsigned long *dest, unsigned long rhs)
+{
+ __asm ("restore\n"
+ "ld [%o0], %o2\n"
+ ".again_swap:\n"
+ "mov %o1, %o3\n"
+ "cas [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %icc, .again_swap\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "mov %o3, %o0\n");
+}
+
+unsigned long
+ace_atomic_swap_add_long (volatile unsigned long *dest, long rhs)
+{
+ __asm ("restore\n"
+ "ld [%o0], %o2\n"
+ ".again_swap_add:\n"
+ "mov %o2, %o4\n"
+ "add %o2, %o1, %o3\n"
+ "cas [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %icc, .again_swap_add\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "mov %o4, %o0\n");
+}
+
+# endif /* __sparcv9 */
+
+#elif !defined (__GNUC__) && !defined (__INTEL_COMPILER)
+/* Make compilers stop complaining about an empty translation unit */
+static int shut_up_compiler = 0;
+#endif /* ACE_INCLUDE_ATOMIC_OP_SPARC */
diff --git a/ACE/ace/Atomic_Op_Sparc.h b/ACE/ace/Atomic_Op_Sparc.h
new file mode 100644
index 00000000000..6e238e5e909
--- /dev/null
+++ b/ACE/ace/Atomic_Op_Sparc.h
@@ -0,0 +1,14 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_ATOMIC_OP_SPARC_H
+#define ACE_ATOMIC_OP_SPARC_H
+
+extern "C"
+{
+ unsigned long ace_atomic_add_long (volatile unsigned long *dest, long rhs);
+ unsigned long ace_atomic_swap_long (volatile unsigned long *dest, unsigned long rhs);
+ unsigned long ace_atomic_swap_add_long (volatile unsigned long *dest, long rhs);
+}
+
+#endif /* ACE_ATOMIC_OP_SPARC_H */
diff --git a/ACE/ace/Atomic_Op_T.cpp b/ACE/ace/Atomic_Op_T.cpp
new file mode 100644
index 00000000000..ad8f6b01059
--- /dev/null
+++ b/ACE/ace/Atomic_Op_T.cpp
@@ -0,0 +1,82 @@
+#ifndef ACE_ATOMIC_OP_T_CPP
+#define ACE_ATOMIC_OP_T_CPP
+
+#include "ace/Atomic_Op_T.h"
+
+#ifdef ACE_HAS_DUMP
+# include "ace/Log_Msg.h"
+#endif /* ACE_HAS_DUMP */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Atomic_Op_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Atomic_Op_Ex)
+ACE_ALLOC_HOOK_DEFINE(ACE_Atomic_Op)
+
+ACE_RCSID(ace, Atomic_Op_T, "$Id$")
+
+// *************************************************
+template <class ACE_LOCK, class TYPE> ACE_LOCK &
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::mutex (void)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::mutex");
+ return this->mutex_;
+}
+
+template <class ACE_LOCK, class TYPE>
+void
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->mutex_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex (ACE_LOCK & mtx)
+ : mutex_ (mtx)
+ , value_ (0)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex");
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex (
+ ACE_LOCK & mtx,
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type c)
+ : mutex_ (mtx)
+ , value_ (c)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex");
+}
+
+// ****************************************************************
+
+template <class ACE_LOCK, class TYPE>
+ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op (void)
+ : impl_ (this->own_mutex_)
+{
+ // ACE_TRACE ("ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op");
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type c)
+ : impl_ (own_mutex_, c)
+{
+ // ACE_TRACE ("ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_ATOMIC_OP_T_CPP */
diff --git a/ACE/ace/Atomic_Op_T.h b/ACE/ace/Atomic_Op_T.h
new file mode 100644
index 00000000000..cf9fbda184d
--- /dev/null
+++ b/ACE/ace/Atomic_Op_T.h
@@ -0,0 +1,369 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Atomic_Op_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ATOMIC_OP_T_H
+#define ACE_ATOMIC_OP_T_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<typename TYPE>
+struct ACE_Type_Traits
+{
+ typedef TYPE const & parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<bool>
+{
+ typedef bool parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<char>
+{
+ typedef char parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<signed char>
+{
+ typedef signed char parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<unsigned char>
+{
+ typedef unsigned char parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<short>
+{
+ typedef short parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<unsigned short>
+{
+ typedef unsigned short parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<int>
+{
+ typedef int parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<unsigned int>
+{
+ typedef unsigned int parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<long>
+{
+ typedef long parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<unsigned long>
+{
+ typedef unsigned long parameter_type;
+};
+
+#ifndef ACE_LACKS_LONGLONG_T
+template<>
+struct ACE_Type_Traits<long long>
+{
+ typedef long long parameter_type;
+};
+#endif /* !ACE_LACKS_LONGLONG_T */
+
+#if !defined (ACE_LACKS_LONGLONG_T) \
+ && !defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+template<>
+struct ACE_Type_Traits<unsigned long long>
+{
+ typedef unsigned long long parameter_type;
+};
+#endif /* !ACE_LACKS_LONGLONG_T && !ACE_LACKS_UNSIGNEDLONGLONG_T */
+
+template<>
+struct ACE_Type_Traits<float>
+{
+ typedef float parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<double>
+{
+ typedef double parameter_type;
+};
+
+template<>
+struct ACE_Type_Traits<long double>
+{
+ typedef long double parameter_type;
+};
+
+template<typename TYPE>
+struct ACE_Type_Traits<TYPE*>
+{
+ typedef TYPE* parameter_type;
+};
+
+/**
+ * @class ACE_Atomic_Op_Ex
+ *
+ * @brief Transparently parameterizes synchronization into basic
+ * arithmetic operations.
+ *
+ * This class is described in an article in the July/August 1994
+ * issue of the C++ Report magazine. It implements a
+ * templatized version of the Decorator pattern from the GoF book.
+ *
+ * ACE_Atomic_Op_Ex objects must be constructed with a reference
+ * to an existing lock. A single lock can be shared between
+ * multiple ACE_Atomic_Op_Ex objects. If you do not require this
+ * ability consider using the ACE_Atomic_Op class instead, which
+ * may be able to take advantage of platform-specific
+ * optimisations to provide atomic operations without requiring a
+ * lock.
+ */
+template <class ACE_LOCK, typename TYPE>
+class ACE_Atomic_Op_Ex
+{
+public:
+
+ typedef typename ACE_Type_Traits<TYPE>::parameter_type arg_type;
+
+ // = Initialization methods.
+
+ /// Initialize @c value_ to 0.
+ ACE_Atomic_Op_Ex (ACE_LOCK & mtx);
+
+ /// Initialize @c value_ to c.
+ ACE_Atomic_Op_Ex (ACE_LOCK & mtx, arg_type c);
+
+ // = Accessors.
+
+ /// Atomically pre-increment @c value_.
+ TYPE operator++ (void);
+
+ /// Atomically post-increment @c value_.
+ TYPE operator++ (int);
+
+ /// Atomically increment @c value_ by rhs.
+ TYPE operator+= (arg_type rhs);
+
+ /// Atomically pre-decrement @c value_.
+ TYPE operator-- (void);
+
+ /// Atomically post-decrement @c value_.
+ TYPE operator-- (int);
+
+ /// Atomically decrement @c value_ by rhs.
+ TYPE operator-= (arg_type rhs);
+
+ /// Atomically compare @c value_ with rhs.
+ bool operator== (arg_type rhs) const;
+
+ /// Atomically compare @c value_ with rhs.
+ bool operator!= (arg_type rhs) const;
+
+ /// Atomically check if @c value_ greater than or equal to rhs.
+ bool operator>= (arg_type rhs) const;
+
+ /// Atomically check if @c value_ greater than rhs.
+ bool operator> (arg_type rhs) const;
+
+ /// Atomically check if @c value_ less than or equal to rhs.
+ bool operator<= (arg_type rhs) const;
+
+ /// Atomically check if @c value_ less than rhs.
+ bool operator< (arg_type rhs) const;
+
+ /// Atomically assign rhs to @c value_.
+ ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> &operator= (arg_type rhs);
+
+ /// Atomically assign <rhs> to @c value_.
+ ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> &operator= (
+ ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> const & rhs);
+
+ /// Explicitly return @c value_.
+ TYPE value (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+ /// Manage copying...
+ ACE_Atomic_Op_Ex (ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> const &);
+
+ /**
+ * Returns a reference to the underlying <ACE_LOCK>. This makes it
+ * possible to acquire the lock explicitly, which can be useful in
+ * some cases if you instantiate the <ACE_Atomic_Op_Ex> with an
+ * ACE_Recursive_Mutex or ACE_Process_Mutex. @note the right
+ * name would be lock_, but HP/C++ will choke on that!
+ */
+ ACE_LOCK & mutex (void);
+
+ /**
+ * Explicitly return @c value_ (by reference). This gives the user
+ * full, unrestricted access to the underlying value. This method
+ * will usually be used in conjunction with explicit access to the
+ * lock. Use with care ;-)
+ */
+ TYPE & value_i (void);
+
+private:
+ /// Type of synchronization mechanism.
+ ACE_LOCK & mutex_;
+
+ /// Current object decorated by the atomic op.
+ TYPE value_;
+};
+
+/**
+ * @class ACE_Atomic_Op
+ *
+ * @brief Transparently parameterizes synchronization into basic
+ * arithmetic operations.
+ *
+ * This class is described in an article in the July/August 1994
+ * issue of the C++ Report magazine. It implements a
+ * templatized version of the Decorator pattern from the GoF book.
+ *
+ * Certain platforms may provide a template specialization for
+ * ACE_Atomic_Op <ACE_Thread_Mutex, long> that provides optimized
+ * atomic integer operations without actually requiring a mutex.
+ */
+template <class ACE_LOCK, typename TYPE>
+class ACE_Atomic_Op
+{
+public:
+
+ typedef typename ACE_Type_Traits<TYPE>::parameter_type arg_type;
+
+ /// Initialize @c value_ to 0.
+ ACE_Atomic_Op (void);
+
+ /// Initialize @c value_ to c.
+ ACE_Atomic_Op (arg_type c);
+
+ /// Manage copying...
+ ACE_Atomic_Op (ACE_Atomic_Op<ACE_LOCK, TYPE> const & c);
+
+ /// Atomically assign rhs to @c value_.
+ ACE_Atomic_Op<ACE_LOCK, TYPE> & operator= (arg_type rhs);
+
+ /// Atomically assign <rhs> to @c value_.
+ ACE_Atomic_Op<ACE_LOCK, TYPE> & operator= (
+ ACE_Atomic_Op<ACE_LOCK, TYPE> const & rhs);
+
+ /// Atomically pre-increment @c value_.
+ TYPE operator++ (void);
+
+ /// Atomically post-increment @c value_.
+ TYPE operator++ (int);
+
+ /// Atomically increment @c value_ by rhs.
+ TYPE operator+= (arg_type rhs);
+
+ /// Atomically pre-decrement @c value_.
+ TYPE operator-- (void);
+
+ /// Atomically post-decrement @c value_.
+ TYPE operator-- (int);
+
+ /// Atomically decrement @c value_ by rhs.
+ TYPE operator-= (arg_type rhs);
+
+ /// Atomically compare @c value_ with rhs.
+ bool operator== (arg_type rhs) const;
+
+ /// Atomically compare @c value_ with rhs.
+ bool operator!= (arg_type rhs) const;
+
+ /// Atomically check if @c value_ greater than or equal to rhs.
+ bool operator>= (arg_type rhs) const;
+
+ /// Atomically check if @c value_ greater than rhs.
+ bool operator> (arg_type rhs) const;
+
+ /// Atomically check if @c value_ less than or equal to rhs.
+ bool operator<= (arg_type rhs) const;
+
+ /// Atomically check if @c value_ less than rhs.
+ bool operator< (arg_type rhs) const;
+
+ /// Explicitly return @c value_.
+ TYPE value (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /**
+ * Returns a reference to the underlying <ACE_LOCK>. This makes it
+ * possible to acquire the lock explicitly, which can be useful in
+ * some cases if you instantiate the ACE_Atomic_Op with an
+ * ACE_Recursive_Mutex or ACE_Process_Mutex.
+ *
+ * @deprecated This member function is deprecated and so may go away in
+ * the future. If you need access to the underlying mutex, consider
+ * using the ACE_Atomic_Op_Ex template instead.
+ */
+ ACE_LOCK & mutex (void);
+
+ /**
+ * Explicitly return @c value_ (by reference). This gives the user
+ * full, unrestricted access to the underlying value. This method
+ * will usually be used in conjunction with explicit access to the
+ * lock. Use with care ;-)
+ */
+ TYPE & value_i (void);
+
+private:
+ /// Type of synchronization mechanism.
+ ACE_LOCK own_mutex_;
+
+ /// Underlying atomic op implementation.
+ ACE_Atomic_Op_Ex <ACE_LOCK, TYPE> impl_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Atomic_Op_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Atomic_Op_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Atomic_Op_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /*ACE_ATOMIC_OP_T_H*/
diff --git a/ACE/ace/Atomic_Op_T.inl b/ACE/ace/Atomic_Op_T.inl
new file mode 100644
index 00000000000..3d09ba304fe
--- /dev/null
+++ b/ACE/ace/Atomic_Op_T.inl
@@ -0,0 +1,340 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Guard_T.h"
+
+#include <algorithm>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//
+// ACE_Atomic_Op_Ex inline functions
+//
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator++ (void)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator++");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, this->value_);
+ return ++this->value_;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator+= (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator+=");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, this->value_);
+ return this->value_ += rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator-- (void)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator--");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, this->value_);
+ return --this->value_;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator-= (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator-=");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, this->value_);
+ return this->value_ -= rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex (
+ ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> const & rhs)
+ : mutex_ (rhs.mutex_)
+ , value_ (rhs.value ()) // rhs.value() returns atomically
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex");
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator++ (int)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator++");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, this->value_);
+ return this->value_++;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator-- (int)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator--");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, this->value_);
+ return this->value_--;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator== (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator==");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, false);
+ return this->value_ == rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator!= (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator!=");
+ return !(*this == rhs);
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator>= (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator>=");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, false);
+ return this->value_ >= rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator> (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator>");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, false);
+ return this->value_ > rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator<= (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator<=");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, false);
+ return this->value_ <= rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator< (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator<");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, false);
+ return this->value_ < rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> &
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator= (
+ ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> const & rhs)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator=");
+
+ ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> tmp (rhs);
+
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, *this);
+ std::swap (this->value_, tmp.value_);
+
+ return *this;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::value (void) const
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::value");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, this->value_);
+ return this->value_;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE &
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::value_i (void)
+{
+ // Explicitly return <value_> (by reference). This gives the user
+ // full, unrestricted access to the underlying value. This method
+ // will usually be used in conjunction with explicit access to the
+ // lock. Use with care ;-)
+ return this->value_;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE ACE_Atomic_Op_Ex<ACE_LOCK, TYPE> &
+ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator= (
+ typename ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::arg_type rhs)
+{
+ // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::operator=");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, *this);
+ this->value_ = rhs;
+ return *this;
+}
+
+//
+// ACE_Atomic_Op inline functions
+//
+
+template <class ACE_LOCK, class TYPE> ACE_INLINE
+ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op (
+ ACE_Atomic_Op<ACE_LOCK, TYPE> const & rhs)
+ : impl_ (own_mutex_, rhs.value ())
+{
+ // ACE_TRACE ("ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op");
+}
+
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE ACE_Atomic_Op<ACE_LOCK, TYPE> &
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator= (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type i)
+{
+ this->impl_ = i;
+ return *this;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE ACE_Atomic_Op<ACE_LOCK, TYPE> &
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator= (
+ ACE_Atomic_Op<ACE_LOCK, TYPE> const & rhs)
+{
+ this->impl_ = rhs.impl_;
+ return *this;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator++ (void)
+{
+ return ++this->impl_;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator++ (int)
+{
+ return this->impl_++;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator+= (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type rhs)
+{
+ return this->impl_ += rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator-- (void)
+{
+ return --this->impl_;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator-- (int)
+{
+ return this->impl_--;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator-= (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type rhs)
+{
+ return this->impl_ -= rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator== (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ return this->impl_ == rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator!= (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ return this->impl_ != rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator>= (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ return this->impl_ >= rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator> (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ return this->impl_ > rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator<= (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ return this->impl_ <= rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE bool
+ACE_Atomic_Op<ACE_LOCK, TYPE>::operator< (
+ typename ACE_Atomic_Op<ACE_LOCK, TYPE>::arg_type rhs) const
+{
+ return this->impl_ < rhs;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE
+ACE_Atomic_Op<ACE_LOCK, TYPE>::value (void) const
+{
+ return this->impl_.value ();
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE void
+ACE_Atomic_Op<ACE_LOCK, TYPE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->impl_.dump ();
+#endif /* ACE_HAS_DUMP */
+ return;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE ACE_LOCK &
+ACE_Atomic_Op<ACE_LOCK, TYPE>::mutex (void)
+{
+ return this->own_mutex_;
+}
+
+template <class ACE_LOCK, class TYPE>
+ACE_INLINE TYPE &
+ACE_Atomic_Op<ACE_LOCK, TYPE>::value_i (void)
+{
+ return this->impl_.value_i ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Auto_Event.cpp b/ACE/ace/Auto_Event.cpp
new file mode 100644
index 00000000000..9e106ac8119
--- /dev/null
+++ b/ACE/ace/Auto_Event.cpp
@@ -0,0 +1,49 @@
+// $Id$
+
+#include "ace/Auto_Event.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Auto_Event.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Auto_Event,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Auto_Event::ACE_Auto_Event (int initial_state,
+ int type,
+ const char *name,
+ void *arg)
+ : ACE_Event (0,
+ initial_state,
+ type,
+ ACE_TEXT_CHAR_TO_TCHAR (name),
+ arg)
+{
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_Auto_Event::ACE_Auto_Event (int initial_state,
+ int type,
+ const wchar_t *name,
+ void *arg)
+ : ACE_Event (0,
+ initial_state,
+ type,
+ ACE_TEXT_WCHAR_TO_TCHAR (name),
+ arg)
+{
+}
+#endif /* ACE_HAS_WCHAR */
+
+void
+ACE_Auto_Event::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_Event::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Auto_Event.h b/ACE/ace/Auto_Event.h
new file mode 100644
index 00000000000..c4ee11509bb
--- /dev/null
+++ b/ACE/ace/Auto_Event.h
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Auto_Event.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_AUTO_EVENT_H
+#define ACE_AUTO_EVENT_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Auto_Event
+ *
+ * @brief Auto Events.
+ *
+ * Specialization of Event mechanism which wakes up one waiting
+ * thread on <signal>. All platforms support process-scope locking
+ * support. However, only Win32 platforms support global naming and
+ * system-scope locking support.
+ */
+class ACE_Export ACE_Auto_Event : public ACE_Event
+{
+public:
+ /// Constructor which will create auto event
+ ACE_Auto_Event (int initial_state = 0,
+ int type = USYNC_THREAD,
+ const char *name = 0,
+ void *arg = 0);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Constructor which will create auto event (wchar_t version)
+ ACE_Auto_Event (int initial_state,
+ int type,
+ const wchar_t *name,
+ void *arg = 0);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Default dtor.
+ ~ACE_Auto_Event (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Auto_Event.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_AUTO_EVENT_H */
diff --git a/ACE/ace/Auto_Event.inl b/ACE/ace/Auto_Event.inl
new file mode 100644
index 00000000000..80048c29b99
--- /dev/null
+++ b/ACE/ace/Auto_Event.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Auto_Event::~ACE_Auto_Event (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Auto_Functor.cpp b/ACE/ace/Auto_Functor.cpp
new file mode 100644
index 00000000000..8d6e7f998bf
--- /dev/null
+++ b/ACE/ace/Auto_Functor.cpp
@@ -0,0 +1,39 @@
+// $Id$
+
+#ifndef ACE_AUTO_FUNCTOR_CPP
+#define ACE_AUTO_FUNCTOR_CPP
+
+#include "ace/Auto_Functor.h"
+
+#if !defined(__ACE_INLINE__)
+# include "ace/Auto_Functor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<typename X, typename Functor>
+ACE_Utils::Auto_Functor<X,Functor>::~Auto_Functor()
+{
+ reset(0);
+}
+
+template<typename X, typename Functor> void
+ACE_Utils::Auto_Functor<X,Functor>::reset(X * p)
+{
+ if(p_ != 0)
+ {
+ f_(p_);
+ }
+ p_ = p;
+}
+
+template<typename X, typename Functor>void
+ACE_Utils::Auto_Functor<X,Functor>::reset(X * p, Functor f)
+{
+ reset(p);
+ f_ = f;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /*ACE_AUTO_FUNCTOR_CPP*/
diff --git a/ACE/ace/Auto_Functor.h b/ACE/ace/Auto_Functor.h
new file mode 100644
index 00000000000..4ca55184b9a
--- /dev/null
+++ b/ACE/ace/Auto_Functor.h
@@ -0,0 +1,127 @@
+// -*- C++ -*-
+//=============================================================================
+/**
+ * @file Auto_Functor.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@atdesk.com>
+ */
+//=============================================================================
+#ifndef ACE_AUTO_FUNCTOR_H
+#define ACE_AUTO_FUNCTOR_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/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_Utils
+{
+/**
+ * @class Auto_Functor_Ref
+ *
+ * @brief Helper class to implement assignment and copy-construction
+ * as expected
+ */
+template<typename X, typename Functor>
+struct Auto_Functor_Ref
+{
+ X * p_;
+ Functor f_;
+
+ Auto_Functor_Ref(X * p, Functor f);
+};
+
+/**
+ * @class Auto_Functor
+ *
+ * @brief Helper template to implement auto_ptr<>-like classes, but
+ * executing a functor in the destructor, instead of always
+ * deleting things.
+ *
+ * The functor is called in the destructor, and it must implement:
+ *
+ * Functor() throw();<BR>
+ * Functor(Functor const &) throw();<BR>
+ * Functor & operator=(Functor const &) throw();<BR>
+ * void operator()(X * p) throw();<BR>
+ *
+ */
+template<typename X, typename Functor>
+class Auto_Functor
+{
+public:
+ typedef X element_type;
+ typedef Functor functor_type;
+
+ /// Constructor
+ explicit Auto_Functor (X * p = 0,
+ Functor functor = Functor()); // throw()
+
+ Auto_Functor (Auto_Functor & rhs); // throw()
+
+ Auto_Functor<X,Functor>& operator= (Auto_Functor & rhs); // throw()
+
+#if !defined(ACE_LACKS_MEMBER_TEMPLATES)
+ template<typename Y>
+ Auto_Functor(Auto_Functor<Y,Functor>& rhs); // throw()
+
+ template<typename Y>
+ Auto_Functor<X,Functor>& operator= (Auto_Functor<Y,Functor>& rhs); // throw()
+#endif /* ACE_LACKS_MEMBER_TEMPLATES */
+
+ ~Auto_Functor(); // throw()
+
+ X & operator*() const; // throw()
+
+ X * operator->() const; // throw()
+
+ X * get(); // throw()
+
+ X * release(); // throw()
+
+ void reset (X * p = 0); // throw()
+
+ void reset (X * p, Functor f); // throw()
+
+ Functor const & functor() const; // throw()
+
+ Auto_Functor(Auto_Functor_Ref<X,Functor> rhs); // throw()
+
+ Auto_Functor<X,Functor> & operator=(Auto_Functor_Ref<X,Functor> rhs); // throw()
+
+#if !defined(ACE_LACKS_MEMBER_TEMPLATES)
+ template<typename Y> operator Auto_Functor_Ref<Y,Functor>(); // throw()
+
+ template<typename Y> operator Auto_Functor<Y,Functor>(); // throw()
+#else
+ operator Auto_Functor_Ref<X,Functor>(); // throw()
+#endif /* ACE_LACKS_MEMBER_TEMPLATES */
+
+private:
+ X * p_;
+
+ Functor f_;
+};
+
+} // namespace ACE_Utils
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined(__ACE_INLINE__)
+# include "ace/Auto_Functor.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined(ACE_TEMPLATES_REQUIRE_SOURCE)
+# include "ace/Auto_Functor.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_AUTO_FUNCTOR_H*/
diff --git a/ACE/ace/Auto_Functor.inl b/ACE/ace/Auto_Functor.inl
new file mode 100644
index 00000000000..01f35b87eb5
--- /dev/null
+++ b/ACE/ace/Auto_Functor.inl
@@ -0,0 +1,134 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<typename X, typename Functor> ACE_INLINE
+ACE_Utils::Auto_Functor_Ref<X,Functor>::
+Auto_Functor_Ref(X * p, Functor f)
+ : p_(p)
+ , f_(f)
+{
+}
+
+template<typename X, typename Functor> ACE_INLINE
+ACE_Utils::Auto_Functor<X,Functor>::Auto_Functor(X * p, Functor f)
+ : p_(p)
+ , f_(f)
+{
+}
+
+template<typename X, typename Functor> ACE_INLINE
+ACE_Utils::Auto_Functor<X,Functor>::Auto_Functor(Auto_Functor & rhs)
+ : p_(rhs.release())
+ , f_(rhs.f_)
+{
+}
+
+template<typename X, typename Functor>
+ACE_INLINE ACE_Utils::Auto_Functor<X,Functor>&
+ACE_Utils::Auto_Functor<X,Functor>:: operator=(Auto_Functor & rhs)
+{
+ reset(rhs.release());
+ f_ = rhs.f_;
+ return *this;
+}
+
+#if !defined(ACE_LACKS_MEMBER_TEMPLATES)
+template<typename X, typename Functor> template<typename Y> ACE_INLINE
+ACE_Utils::Auto_Functor<X,Functor>::Auto_Functor(Auto_Functor<Y,Functor>& rhs)
+ : p_(rhs.release())
+ , f_(rhs.f_)
+{
+}
+
+template<typename X, typename Functor> template<typename Y>
+ACE_INLINE ACE_Utils::Auto_Functor<X,Functor>&
+ACE_Utils::Auto_Functor<X,Functor>::operator=(Auto_Functor<Y,Functor>& rhs)
+{
+ reset(rhs.release());
+ return *this;
+}
+#endif /* ACE_LACKS_MEMBER_TEMPLATES */
+
+template<typename X, typename Functor> ACE_INLINE X &
+ACE_Utils::Auto_Functor<X,Functor>::operator*() const
+{
+ return *p_;
+}
+
+template<typename X, typename Functor>
+ACE_INLINE X *
+ACE_Utils::Auto_Functor<X,Functor>::operator->() const
+{
+ return p_;
+}
+
+template<typename X, typename Functor>
+ACE_INLINE X *
+ACE_Utils::Auto_Functor<X,Functor>::get()
+{
+ return p_;
+}
+
+template<typename X, typename Functor>
+ACE_INLINE X *
+ACE_Utils::Auto_Functor<X,Functor>::release()
+{
+ X * tmp = p_;
+ p_ = 0;
+ return tmp;
+}
+
+template<typename X, typename Functor>
+ACE_INLINE Functor const &
+ACE_Utils::Auto_Functor<X,Functor>::functor() const
+{
+ return f_;
+}
+
+template<typename X, typename Functor> ACE_INLINE
+ACE_Utils::Auto_Functor<X,Functor>::Auto_Functor(Auto_Functor_Ref<X,Functor> rhs)
+ : p_(rhs.p_)
+ , f_(rhs.f_)
+{
+}
+
+template<typename X, typename Functor>
+ACE_INLINE ACE_Utils::Auto_Functor<X,Functor> &
+ACE_Utils::Auto_Functor<X,Functor>::operator=(Auto_Functor_Ref<X,Functor> rhs)
+{
+ if(rhs.p_ != p_)
+ {
+ reset(rhs.p_);
+ f_ = rhs.f_;
+ }
+ return *this;
+}
+
+#if !defined(ACE_LACKS_MEMBER_TEMPLATES)
+
+template<typename X, typename Functor> template<typename Y> ACE_INLINE
+ACE_Utils::Auto_Functor<X,Functor>::operator ACE_Utils::Auto_Functor_Ref<Y,Functor>()
+{
+ return ACE_Utils::Auto_Functor_Ref<Y,Functor>(release(), f_);
+}
+
+template<typename X, typename Functor> template<typename Y> ACE_INLINE
+ACE_Utils::Auto_Functor<X,Functor>::operator ACE_Utils::Auto_Functor<Y,Functor>()
+{
+ return ACE_Utils::Auto_Functor<Y,Functor>(release(), f_);
+}
+
+#else
+
+template<typename X, typename Functor>ACE_INLINE
+ACE_Utils::Auto_Functor<X,Functor>::operator ACE_Utils::Auto_Functor_Ref<X,Functor>()
+{
+ return ACE_Utils::Auto_Functor_Ref<X,Functor>(release(), f_);
+}
+
+#endif /* ACE_LACKS_MEMBER_TEMPLATES */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Auto_IncDec_T.cpp b/ACE/ace/Auto_IncDec_T.cpp
new file mode 100644
index 00000000000..cf33efd7d6e
--- /dev/null
+++ b/ACE/ace/Auto_IncDec_T.cpp
@@ -0,0 +1,34 @@
+// $Id$
+
+#ifndef ACE_AUTO_INCDEC_T_CPP
+#define ACE_AUTO_INCDEC_T_CPP
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Auto_IncDec_T.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Auto_IncDec_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Auto_IncDec)
+
+template <class ACE_SAFELY_INCREMENTABLE_DECREMENTABLE> void
+ACE_Auto_IncDec<ACE_SAFELY_INCREMENTABLE_DECREMENTABLE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Auto_IncDec<ACE_SAFELY_INCREMENTABLE_DECREMENTABLE>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_AUTO_INCDEC_T_CPP */
diff --git a/ACE/ace/Auto_IncDec_T.h b/ACE/ace/Auto_IncDec_T.h
new file mode 100644
index 00000000000..0f29f5c4f3f
--- /dev/null
+++ b/ACE/ace/Auto_IncDec_T.h
@@ -0,0 +1,91 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Auto_IncDec_T.h
+ *
+ * $Id$
+ *
+ * @author Edan Ayal <EdanA@cti2.com>
+ */
+//=============================================================================
+
+
+#ifndef ACE_AUTO_INCDEC_T_H
+#define ACE_AUTO_INCDEC_T_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/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Auto_IncDec
+ *
+ * @brief This class automatically increments and decrements a
+ * parameterized counter.
+ *
+ * This data structure is meant to be used within a method,
+ * function, or scope. The actual parameter given for the
+ * <ACE_SAFELY_INCREMENTABLE_DECREMENTABLE> template parameter
+ * must provide at least operators ++ and --.
+ */
+template <class ACE_SAFELY_INCREMENTABLE_DECREMENTABLE>
+class ACE_Auto_IncDec
+{
+public:
+
+ /// Implicitly increment the counter.
+ ACE_Auto_IncDec (ACE_SAFELY_INCREMENTABLE_DECREMENTABLE &counter);
+
+ /// Implicitly decrement the counter.
+ ~ACE_Auto_IncDec (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+protected:
+ /// Reference to the <ACE_SAFELY_INCREMENTABLE_DECREMENTABLE> counter
+ /// we're incrementing/decrementing.
+ ACE_SAFELY_INCREMENTABLE_DECREMENTABLE &counter_;
+
+private:
+ // = Prevent assignment and initialization.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const
+ ACE_Auto_IncDec<ACE_SAFELY_INCREMENTABLE_DECREMENTABLE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Auto_IncDec (const
+ ACE_Auto_IncDec<ACE_SAFELY_INCREMENTABLE_DECREMENTABLE> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Auto_IncDec_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Auto_IncDec_T.cpp"
+// On Win32 platforms, this code will be included as template source
+// code and will not be inlined. Therefore, we first turn off
+// ACE_INLINE, set it to be nothing, include the code, and then turn
+// ACE_INLINE back to its original setting. All this nonsense is
+// necessary, since the generic template code that needs to be
+// specialized cannot be inlined, else the compiler will ignore the
+// specialization code. Also, the specialization code *must* be
+// inlined or the compiler will ignore the specializations.
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Auto_IncDec_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_AUTO_INCDEC_T_H */
diff --git a/ACE/ace/Auto_IncDec_T.inl b/ACE/ace/Auto_IncDec_T.inl
new file mode 100644
index 00000000000..51daac0e84d
--- /dev/null
+++ b/ACE/ace/Auto_IncDec_T.inl
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Implicitly and automatically increment the counter.
+
+template <class ACE_SAFELY_INCREMENTABLE_DECREMENTABLE> ACE_INLINE
+ACE_Auto_IncDec<ACE_SAFELY_INCREMENTABLE_DECREMENTABLE>::ACE_Auto_IncDec
+ (ACE_SAFELY_INCREMENTABLE_DECREMENTABLE &counter)
+ : counter_ (counter)
+{
+ ++this->counter_;
+}
+
+// Implicitly and automatically decrement the counter.
+
+template <class ACE_SAFELY_INCREMENTABLE_DECREMENTABLE> ACE_INLINE
+ACE_Auto_IncDec<ACE_SAFELY_INCREMENTABLE_DECREMENTABLE>::~ACE_Auto_IncDec (void)
+{
+ --this->counter_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Auto_Ptr.cpp b/ACE/ace/Auto_Ptr.cpp
new file mode 100644
index 00000000000..081744ce316
--- /dev/null
+++ b/ACE/ace/Auto_Ptr.cpp
@@ -0,0 +1,21 @@
+// $Id$
+
+#ifndef ACE_AUTO_PTR_CPP
+#define ACE_AUTO_PTR_CPP
+
+#include "ace/Auto_Ptr.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Auto_Ptr.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Auto_Ptr, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Auto_Basic_Ptr)
+ACE_ALLOC_HOOK_DEFINE(ACE_Auto_Basic_Array_Ptr)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_AUTO_PTR_CPP */
diff --git a/ACE/ace/Auto_Ptr.h b/ACE/ace/Auto_Ptr.h
new file mode 100644
index 00000000000..ec955d30b21
--- /dev/null
+++ b/ACE/ace/Auto_Ptr.h
@@ -0,0 +1,242 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Auto_Ptr.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@uci.edu>
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Jack Reeves <jack@fx.com>
+ * @author Dr. Harald M. Mueller <mueller@garwein.hai.siemens.co.at>
+ */
+//=============================================================================
+
+#ifndef ACE_AUTO_PTR_H
+#define ACE_AUTO_PTR_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 (_MSC_VER)
+// Suppress warning e.g. "return type for
+// 'ACE_Auto_Array_Pointer<type>::operator ->' is 'type *' (i.e., not a UDT
+// or reference to a UDT. Will produce errors if applied using infix
+// notation)"
+# pragma warning(push)
+# pragma warning(disable: 4284)
+#endif /* _MSC_VER */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Auto_Basic_Ptr
+ *
+ * @brief Implements the draft C++ standard auto_ptr abstraction.
+ * This class allows one to work on non-object (basic) types
+ */
+template <typename X>
+class ACE_Auto_Basic_Ptr
+{
+public:
+ typedef X element_type;
+
+ // = Initialization and termination methods
+ explicit ACE_Auto_Basic_Ptr (X * p = 0) : p_ (p) {}
+
+ ACE_Auto_Basic_Ptr (ACE_Auto_Basic_Ptr<X> & ap);
+ ACE_Auto_Basic_Ptr<X> &operator= (ACE_Auto_Basic_Ptr<X> & rhs);
+ ~ACE_Auto_Basic_Ptr (void);
+
+ // = Accessor methods.
+ X &operator *() const;
+ X *get (void) const;
+ X *release (void);
+ void reset (X * p = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ X *p_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if !defined (ACE_LACKS_AUTO_PTR) && \
+ defined (ACE_HAS_STANDARD_CPP_LIBRARY) && \
+ (ACE_HAS_STANDARD_CPP_LIBRARY != 0)
+#include <memory>
+#if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB) && \
+ (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB != 0)
+using std::auto_ptr;
+#endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+#else /* ACE_HAS_STANDARD_CPP_LIBRARY */
+
+/**
+ * @class auto_ptr
+ *
+ * @brief Implements the draft C++ standard auto_ptr abstraction.
+ */
+template <typename X>
+class auto_ptr : public ACE_Auto_Basic_Ptr<X>
+{
+public:
+ typedef X element_type;
+
+ // = Initialization and termination methods
+ explicit auto_ptr (X * p = 0) : ACE_Auto_Basic_Ptr<X> (p) {}
+ auto_ptr (auto_ptr<X> & ap) : ACE_Auto_Basic_Ptr<X> (ap.release ()) {}
+
+ X *operator-> () const;
+};
+
+#endif /* ACE_HAS_STANDARD_CPP_LIBRARY */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @brief Implements the draft C++ standard auto_ptr abstraction.
+ * This version can be used instead of auto_ptr<T>, and obviates
+ * the need for the ACE_AUTO_PTR_RESET macro on platforms like
+ * VC6 where the auto_ptr<T> is broken.
+ */
+template <typename X>
+class ACE_Auto_Ptr : public ACE_Auto_Basic_Ptr <X>
+{
+public:
+ typedef X element_type;
+
+ // = Initialization and termination methods
+ explicit ACE_Auto_Ptr (X * p = 0) : ACE_Auto_Basic_Ptr<X> (p) {}
+
+ X *operator-> () const;
+};
+
+/**
+ * @class ACE_Auto_Basic_Array_Ptr
+ *
+ * @brief Implements an extension to the draft C++ standard auto_ptr
+ * abstraction. This class allows one to work on non-object
+ * (basic) types that must be treated as an array, e.g.,
+ * deallocated via "delete [] foo".
+ */
+template<typename X>
+class ACE_Auto_Basic_Array_Ptr
+{
+public:
+ typedef X element_type;
+
+ // = Initialization and termination methods.
+ explicit ACE_Auto_Basic_Array_Ptr (X * p = 0) : p_ (p) {}
+
+ ACE_Auto_Basic_Array_Ptr (ACE_Auto_Basic_Array_Ptr<X> & ap);
+ ACE_Auto_Basic_Array_Ptr<X> &operator= (ACE_Auto_Basic_Array_Ptr<X> & rhs);
+ ~ACE_Auto_Basic_Array_Ptr (void);
+
+ // = Accessor methods.
+ X & operator* () const;
+ X & operator[] (int i) const;
+ X * get (void) const;
+ X * release (void);
+ void reset (X * p = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ X * p_;
+};
+
+/**
+ * @class ACE_Auto_Array_Ptr
+ *
+ * @brief Implements an extension to the draft C++ standard auto_ptr
+ * abstraction.
+ */
+template<typename X>
+class ACE_Auto_Array_Ptr : public ACE_Auto_Basic_Array_Ptr<X>
+{
+public:
+ typedef X element_type;
+
+ // = Initialization and termination methods.
+ explicit ACE_Auto_Array_Ptr (X *p = 0)
+ : ACE_Auto_Basic_Array_Ptr<X> (p) {}
+
+ X *operator-> () const;
+};
+
+
+/**
+ * @brief Reset given @c auto_ptr element to new element.
+ *
+ * Some platforms have an older version of auto_ptr support, which
+ * lacks reset, and cannot be disabled easily. Portability to these
+ * platforms requires use of this function template. This function
+ * template also works for the @c ACE_Auto_{Basic_}Array_Ptr class
+ * template, as well.
+ */
+template<typename AUTO_PTR_TYPE, typename PTR_TYPE>
+inline void
+ACE_auto_ptr_reset (AUTO_PTR_TYPE & ap,
+ PTR_TYPE * p)
+{
+#if defined (ACE_AUTO_PTR_LACKS_RESET)
+ // Allow compiler to adjust pointer to potential base class pointer
+ // of element type found in auto_ptr.
+ typename AUTO_PTR_TYPE::element_type * const tp = p;
+ if (tp != ap.get ())
+ {
+ ap = AUTO_PTR_TYPE (tp);
+ }
+#else
+ ap.reset (p);
+#endif /* ACE_AUTO_PTR_LACKS_RESET */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Some platforms have an older version of auto_ptr
+// support, which lacks reset, and cannot be disabled
+// easily. Portability to these platforms requires
+// use of the following ACE_AUTO_PTR_RESET macro.
+//
+// The TYPE macro parameter is no longer necessary but we leave it
+// around for backward compatibility. This is also the reason why the
+// ACE_auto_ptr_reset function template is not called
+// ACE_AUTO_PTR_RESET.
+# define ACE_AUTO_PTR_RESET(AUTOPTR,NEWPTR,TYPE) \
+ ACE_auto_ptr_reset (AUTOPTR, NEWPTR);
+
+#if defined (__ACE_INLINE__)
+#include "ace/Auto_Ptr.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Auto_Ptr.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Auto_Ptr.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#if defined (_MSC_VER)
+// Restore the warning state to what it was before entry.
+# pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_AUTO_PTR_H */
diff --git a/ACE/ace/Auto_Ptr.inl b/ACE/ace/Auto_Ptr.inl
new file mode 100644
index 00000000000..57adb236261
--- /dev/null
+++ b/ACE/ace/Auto_Ptr.inl
@@ -0,0 +1,171 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class X> ACE_INLINE void
+ACE_Auto_Basic_Ptr<X>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Auto_Basic_Ptr<X>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template<class X> ACE_INLINE void
+ACE_Auto_Basic_Array_Ptr<X>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Auto_Basic_Array_Ptr<X>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template<class X> ACE_INLINE
+ACE_Auto_Basic_Ptr<X>::ACE_Auto_Basic_Ptr (ACE_Auto_Basic_Ptr<X> &rhs)
+ : p_ (rhs.release ())
+{
+ ACE_TRACE ("ACE_Auto_Basic_Ptr<X>::ACE_Auto_Basic_Ptr");
+}
+
+template<class X> ACE_INLINE X *
+ACE_Auto_Basic_Ptr<X>::get (void) const
+{
+ ACE_TRACE ("ACE_Auto_Basic_Ptr<X>::get");
+ return this->p_;
+}
+
+template<class X> ACE_INLINE X *
+ACE_Auto_Basic_Ptr<X>::release (void)
+{
+ ACE_TRACE ("ACE_Auto_Basic_Ptr<X>::release");
+ X *old = this->p_;
+ this->p_ = 0;
+ return old;
+}
+
+template<class X> ACE_INLINE void
+ACE_Auto_Basic_Ptr<X>::reset (X *p)
+{
+ ACE_TRACE ("ACE_Auto_Basic_Ptr<X>::reset");
+ if (this->get () != p)
+ delete this->get ();
+ this->p_ = p;
+}
+
+template<class X> ACE_INLINE ACE_Auto_Basic_Ptr<X> &
+ACE_Auto_Basic_Ptr<X>::operator= (ACE_Auto_Basic_Ptr<X> &rhs)
+{
+ ACE_TRACE ("ACE_Auto_Basic_Ptr<X>::operator=");
+ if (this != &rhs)
+ {
+ this->reset (rhs.release ());
+ }
+ return *this;
+}
+
+template<class X> ACE_INLINE
+ACE_Auto_Basic_Ptr<X>::~ACE_Auto_Basic_Ptr (void)
+{
+ ACE_TRACE ("ACE_Auto_Basic_Ptr<X>::~ACE_Auto_Basic_Ptr");
+ delete this->get ();
+}
+
+template<class X> ACE_INLINE X &
+ACE_Auto_Basic_Ptr<X>::operator *() const
+{
+ ACE_TRACE ("ACE_Auto_Basic_Ptr<X>::operator *()");
+ return *this->get ();
+}
+
+#if defined (ACE_LACKS_AUTO_PTR) || \
+ !defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0)
+
+template<class X> ACE_INLINE X *
+auto_ptr<X>::operator-> () const
+{
+ ACE_TRACE ("auto_ptr<X>::operator->");
+ return this->get ();
+}
+
+#endif /* ACE_HAS_STANDARD_CPP_LIBRARY */
+
+template<class X> ACE_INLINE X *
+ACE_Auto_Ptr<X>::operator-> () const
+{
+ ACE_TRACE ("ACE_Auto_Ptr<X>::operator->");
+ return this->get ();
+}
+
+template<class X> ACE_INLINE X *
+ACE_Auto_Basic_Array_Ptr<X>::get (void) const
+{
+ ACE_TRACE ("ACE_Auto_Basic_Array_Ptr<X>::get");
+ return this->p_;
+}
+
+template<class X> ACE_INLINE X *
+ACE_Auto_Basic_Array_Ptr<X>::release (void)
+{
+ ACE_TRACE ("ACE_Auto_Basic_Array_Ptr<X>::release");
+ X *old = this->p_;
+ this->p_ = 0;
+ return old;
+}
+
+template<class X> ACE_INLINE void
+ACE_Auto_Basic_Array_Ptr<X>::reset (X *p)
+{
+ ACE_TRACE ("ACE_Auto_Basic_Array_Ptr<X>::reset");
+ if (this->get () != p)
+ delete [] this->get ();
+ this->p_ = p;
+}
+
+template<class X> ACE_INLINE
+ACE_Auto_Basic_Array_Ptr<X>::ACE_Auto_Basic_Array_Ptr (ACE_Auto_Basic_Array_Ptr<X> &rhs)
+ : p_ (rhs.release ())
+{
+ ACE_TRACE ("ACE_Auto_Basic_Array_Ptr<X>::ACE_Auto_Basic_Array_Ptr");
+}
+
+template<class X> ACE_INLINE ACE_Auto_Basic_Array_Ptr<X> &
+ACE_Auto_Basic_Array_Ptr<X>::operator= (ACE_Auto_Basic_Array_Ptr<X> &rhs)
+{
+ ACE_TRACE ("ACE_Auto_Basic_Array_Ptr<X>::operator=");
+ if (this != &rhs)
+ {
+ this->reset (rhs.release ());
+ }
+ return *this;
+}
+
+template<class X> ACE_INLINE
+ACE_Auto_Basic_Array_Ptr<X>::~ACE_Auto_Basic_Array_Ptr (void)
+{
+ ACE_TRACE ("ACE_Auto_Basic_Array_Ptr<X>::~ACE_Auto_Basic_Array_Ptr");
+ delete [] this->get ();
+}
+
+template<class X> ACE_INLINE X &
+ACE_Auto_Basic_Array_Ptr<X>::operator *() const
+{
+ return *this->get ();
+}
+
+template<class X> ACE_INLINE X &
+ACE_Auto_Basic_Array_Ptr<X>::operator[](int i) const
+{
+ X *array = this->get ();
+ return array[i];
+}
+
+template<class X> ACE_INLINE X *
+ACE_Auto_Array_Ptr<X>::operator->() const
+{
+ return this->get ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Barrier.cpp b/ACE/ace/Barrier.cpp
new file mode 100644
index 00000000000..2cb82dba5b6
--- /dev/null
+++ b/ACE/ace/Barrier.cpp
@@ -0,0 +1,197 @@
+// $Id$
+
+#include "ace/Barrier.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Barrier.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Guard_T.h"
+#include "ace/OS_NS_errno.h"
+
+#if defined (ACE_HAS_DUMP)
+# include "ace/Log_Msg.h"
+#endif /* ACE_HAS_DUMP */
+
+ACE_RCSID (ace,
+ Barrier,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sub_Barrier)
+
+void
+ACE_Sub_Barrier::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Sub_Barrier::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->barrier_finished_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("running_threads_ = %d"), this->running_threads_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Sub_Barrier::ACE_Sub_Barrier (unsigned int count,
+ ACE_Thread_Mutex &lock,
+ const ACE_TCHAR *name,
+ void *arg)
+ : barrier_finished_ (lock, name, arg),
+ running_threads_ (count)
+{
+// ACE_TRACE ("ACE_Sub_Barrier::ACE_Sub_Barrier");
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Barrier)
+
+void
+ACE_Barrier::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Barrier::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("current_generation_ = %d"), this->current_generation_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncount_ = %d"), this->count_));
+ this->sub_barrier_1_.dump ();
+ this->sub_barrier_2_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Barrier::ACE_Barrier (unsigned int count,
+ const ACE_TCHAR *name,
+ void *arg)
+ : lock_ (name, (ACE_mutexattr_t *) arg),
+ current_generation_ (0),
+ count_ (count),
+ sub_barrier_1_ (count, lock_, name, arg),
+ sub_barrier_2_ (count, lock_, name, arg)
+{
+ ACE_TRACE ("ACE_Barrier::ACE_Barrier");
+ this->sub_barrier_[0] = &this->sub_barrier_1_;
+ this->sub_barrier_[1] = &this->sub_barrier_2_;
+}
+
+int
+ACE_Barrier::wait (void)
+{
+ ACE_TRACE ("ACE_Barrier::wait");
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
+
+ ACE_Sub_Barrier *sbp =
+ this->sub_barrier_[this->current_generation_];
+
+ // Check for shutdown...
+ if (sbp == 0)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ int retval = 0;
+
+ if (sbp->running_threads_ == 1)
+ {
+ // We're the last running thread, so swap generations and tell
+ // all the threads waiting on the barrier to continue on their
+ // way.
+ sbp->running_threads_ = this->count_;
+ // Swap generations.
+ this->current_generation_ = 1 - this->current_generation_;
+ sbp->barrier_finished_.broadcast ();
+ }
+ else
+ {
+ --sbp->running_threads_;
+
+ // Block until all the other threads wait().
+ while (sbp->running_threads_ != this->count_)
+ sbp->barrier_finished_.wait ();
+
+ // We're awake and the count has completed. See if it completed
+ // because all threads hit the barrier, or because the barrier
+ // was shut down.
+ if (this->sub_barrier_[this->current_generation_] == 0)
+ {
+ errno = ESHUTDOWN;
+ retval = -1;
+ }
+ }
+
+ return retval;
+}
+
+int
+ACE_Barrier::shutdown (void)
+{
+ ACE_TRACE ("ACE_Barrier::shutdown");
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
+
+ ACE_Sub_Barrier *sbp =
+ this->sub_barrier_[this->current_generation_];
+
+ // Check for shutdown...
+ if (sbp == 0)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ // Flag the shutdown
+ this->sub_barrier_[0] = 0;
+ this->sub_barrier_[1] = 0;
+ // Tell all the threads waiting on the barrier to continue on their way.
+ sbp->running_threads_ = this->count_;
+ sbp->barrier_finished_.broadcast ();
+
+ return 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Barrier)
+
+ACE_Thread_Barrier::ACE_Thread_Barrier (unsigned int count,
+ const ACE_TCHAR *name)
+ : ACE_Barrier (count, name)
+{
+// ACE_TRACE ("ACE_Thread_Barrier::ACE_Thread_Barrier");
+}
+
+void
+ACE_Thread_Barrier::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Thread_Barrier::dump");
+ ACE_Barrier::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+#if 0
+ACE_ALLOC_HOOK_DEFINE(ACE_Process_Barrier)
+
+ACE_Process_Barrier::ACE_Process_Barrier (u_int count,
+ const ACE_TCHAR *name)
+ : ACE_Barrier (count, USYNC_PROCESS, name)
+{
+// ACE_TRACE ("ACE_Process_Barrier::ACE_Process_Barrier");
+}
+
+void
+ACE_Process_Barrier::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Process_Barrier::dump");
+ ACE_Barrier::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+#endif /* 0 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/Barrier.h b/ACE/ace/Barrier.h
new file mode 100644
index 00000000000..00e22ec19f5
--- /dev/null
+++ b/ACE/ace/Barrier.h
@@ -0,0 +1,215 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Barrier.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_BARRIER_H
+#define ACE_BARRIER_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include /**/ "ace/config-all.h"
+
+// ACE platform supports some form of threading.
+#if !defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Barrier
+ *
+ * @brief This is a no-op to make ACE "syntactically consistent."
+ */
+class ACE_Export ACE_Barrier
+{
+public:
+ ACE_Barrier (unsigned int, const ACE_TCHAR * = 0, void * = 0) {}
+ ~ACE_Barrier (void) {}
+ int wait (void) { ACE_NOTSUP_RETURN (-1); }
+ void dump (void) const {}
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#else /* ACE_HAS_THREADS */
+
+#include "ace/Condition_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+struct ACE_Export ACE_Sub_Barrier
+{
+ // = Initialization.
+ ACE_Sub_Barrier (unsigned int count,
+ ACE_Thread_Mutex &lock,
+ const ACE_TCHAR *name = 0,
+ void *arg = 0);
+
+ ~ACE_Sub_Barrier (void);
+
+ /// True if this generation of the barrier is done.
+ ACE_Condition_Thread_Mutex barrier_finished_;
+
+ /// Number of threads that are still running.
+ int running_threads_;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Barrier
+ *
+ * @brief Implements "barrier synchronization".
+ *
+ * This class allows <count> number of threads to synchronize
+ * their completion of (one round of) a task, which is known as
+ * "barrier synchronization". After all the threads call <wait()>
+ * on the barrier they are all atomically released and can begin a new
+ * round.
+ *
+ * This implementation uses a "sub-barrier generation numbering"
+ * scheme to avoid overhead and to ensure that all threads wait to
+ * leave the barrier correct. This code is based on an article from
+ * SunOpsis Vol. 4, No. 1 by Richard Marejka
+ * (Richard.Marejka@canada.sun.com).
+ */
+class ACE_Export ACE_Barrier
+{
+public:
+ /// Initialize the barrier to synchronize @a count threads.
+ ACE_Barrier (unsigned int count,
+ const ACE_TCHAR *name = 0,
+ void *arg = 0);
+
+ /// Default dtor.
+ ~ACE_Barrier (void);
+
+ /// Block the caller until all @c count threads have called @c wait and
+ /// then allow all the caller threads to continue in parallel.
+ ///
+ /// @retval 0 after successfully waiting for all threads to wait.
+ /// @retval -1 if an error occurs or the barrier is shut
+ /// down (@sa shutdown ()).
+ int wait (void);
+
+ /// Shut the barrier down, aborting the wait of all waiting threads.
+ /// Any threads waiting on the barrier when it is shut down will return with
+ /// value -1, errno ESHUTDOWN.
+ ///
+ /// @retval 0 for success, -1 if already shut down.
+ ///
+ /// @since ACE beta 5.4.9.
+ int shutdown (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Serialize access to the barrier state.
+ ACE_Thread_Mutex lock_;
+
+ /// Either 0 or 1, depending on whether we are the first generation
+ /// of waiters or the next generation of waiters.
+ int current_generation_;
+
+ /// Total number of threads that can be waiting at any one time.
+ int count_;
+
+ /**
+ * We keep two @c sub_barriers, one for the first "generation" of
+ * waiters, and one for the next "generation" of waiters. This
+ * efficiently solves the problem of what to do if all the first
+ * generation waiters don't leave the barrier before one of the
+ * threads calls wait() again (i.e., starts up the next generation
+ * barrier).
+ */
+ ACE_Sub_Barrier sub_barrier_1_;
+ ACE_Sub_Barrier sub_barrier_2_;
+ ACE_Sub_Barrier *sub_barrier_[2];
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Barrier &);
+ ACE_Barrier (const ACE_Barrier &);
+};
+
+#if 0
+/**
+ * @class ACE_Process_Barrier
+ *
+ * @brief Implements "barrier synchronization" using ACE_Process_Mutexes!
+ *
+ * This class is just a simple wrapper for ACE_Barrier that
+ * selects the USYNC_PROCESS variant for the locks.
+ */
+class ACE_Export ACE_Process_Barrier : public ACE_Barrier
+{
+public:
+ /// Create a Process_Barrier, passing in the optional @a name.
+ ACE_Process_Barrier (unsigned int count, const ACE_TCHAR *name = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+#endif /* 0 */
+
+/**
+ * @class ACE_Thread_Barrier
+ *
+ * @brief Implements "barrier synchronization" using ACE_Thread_Mutexes!
+ *
+ * This class is just a simple wrapper for ACE_Barrier that
+ * selects the USYNC_THREAD variant for the locks.
+ */
+class ACE_Export ACE_Thread_Barrier : public ACE_Barrier
+{
+public:
+ /// Create a Thread_Barrier, passing in the optional @a name.
+ ACE_Thread_Barrier (unsigned int count, const ACE_TCHAR *name = 0);
+
+ /// Default dtor.
+ ~ACE_Thread_Barrier (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Barrier.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* !ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_BARRIER_H */
diff --git a/ACE/ace/Barrier.inl b/ACE/ace/Barrier.inl
new file mode 100644
index 00000000000..9ab5c9fb111
--- /dev/null
+++ b/ACE/ace/Barrier.inl
@@ -0,0 +1,22 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Sub_Barrier::~ACE_Sub_Barrier (void)
+{
+}
+
+ACE_INLINE
+ACE_Barrier::~ACE_Barrier (void)
+{
+}
+
+ACE_INLINE
+ACE_Thread_Barrier::~ACE_Thread_Barrier (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Base_Thread_Adapter.cpp b/ACE/ace/Base_Thread_Adapter.cpp
new file mode 100644
index 00000000000..2ba31a4328e
--- /dev/null
+++ b/ACE/ace/Base_Thread_Adapter.cpp
@@ -0,0 +1,120 @@
+// $Id$
+
+#include "ace/Base_Thread_Adapter.h"
+
+ACE_RCSID (ace,
+ Base_Thread_Adapter,
+ "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/Base_Thread_Adapter.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if defined (ACE_HAS_TSS_EMULATION)
+# include "ace/OS_NS_Thread.h"
+#endif /* ACE_HAS_TSS_EMULATION */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INIT_LOG_MSG_HOOK ACE_Base_Thread_Adapter::init_log_msg_hook_ = 0;
+ACE_INHERIT_LOG_MSG_HOOK ACE_Base_Thread_Adapter::inherit_log_msg_hook_ = 0;
+ACE_CLOSE_LOG_MSG_HOOK ACE_Base_Thread_Adapter::close_log_msg_hook_ = 0;
+ACE_SYNC_LOG_MSG_HOOK ACE_Base_Thread_Adapter::sync_log_msg_hook_ = 0;
+ACE_THR_DESC_LOG_MSG_HOOK ACE_Base_Thread_Adapter::thr_desc_log_msg_hook_ = 0;
+
+ACE_Base_Thread_Adapter::ACE_Base_Thread_Adapter (
+ ACE_THR_FUNC user_func,
+ void *arg,
+ ACE_THR_C_FUNC entry_point,
+ ACE_OS_Thread_Descriptor *td
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , ACE_SEH_EXCEPT_HANDLER selector
+ , ACE_SEH_EXCEPT_HANDLER handler
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ )
+ : user_func_ (user_func)
+ , arg_ (arg)
+ , entry_point_ (entry_point)
+ , thr_desc_ (td)
+{
+ ACE_OS_TRACE ("ACE_Base_Thread_Adapter::ACE_Base_Thread_Adapter");
+
+ if (ACE_Base_Thread_Adapter::init_log_msg_hook_ != 0)
+ (*ACE_Base_Thread_Adapter::init_log_msg_hook_) (
+ this->log_msg_attributes_
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , selector
+ , handler
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ );
+#ifdef ACE_USES_GPROF
+ getitimer (ITIMER_PROF, &itimer_);
+#endif // ACE_USES_GPROF
+}
+
+ACE_Base_Thread_Adapter::~ACE_Base_Thread_Adapter (void)
+{
+}
+
+void
+ACE_Base_Thread_Adapter::inherit_log_msg (void)
+{
+ if (ACE_Base_Thread_Adapter::inherit_log_msg_hook_ != 0)
+ (*ACE_Base_Thread_Adapter::inherit_log_msg_hook_)(
+ this->thr_desc_,
+ this->log_msg_attributes_);
+}
+
+void
+ACE_Base_Thread_Adapter::close_log_msg (void)
+{
+ if (ACE_Base_Thread_Adapter::close_log_msg_hook_ != 0)
+ (*ACE_Base_Thread_Adapter::close_log_msg_hook_) ();
+}
+
+void
+ACE_Base_Thread_Adapter::sync_log_msg (const ACE_TCHAR *prg)
+{
+ if (ACE_Base_Thread_Adapter::sync_log_msg_hook_ != 0)
+ (*ACE_Base_Thread_Adapter::sync_log_msg_hook_) (prg);
+}
+
+ACE_OS_Thread_Descriptor *
+ACE_Base_Thread_Adapter::thr_desc_log_msg (void)
+{
+ if (ACE_Base_Thread_Adapter::thr_desc_log_msg_hook_ != 0)
+ return (*ACE_Base_Thread_Adapter::thr_desc_log_msg_hook_) ();
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Run the thread entry point for the <ACE_Thread_Adapter>. This must
+// be an extern "C" to make certain compilers happy...
+
+extern "C" ACE_THR_FUNC_RETURN
+ACE_THREAD_ADAPTER_NAME (void *args)
+{
+ ACE_OS_TRACE ("ACE_THREAD_ADAPTER_NAME");
+
+#if defined (ACE_HAS_TSS_EMULATION)
+ // As early as we can in the execution of the new thread, allocate
+ // its local TS storage. Allocate it on the stack, to save dynamic
+ // allocation/dealloction.
+ void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX];
+ ACE_TSS_Emulation::tss_open (ts_storage);
+#endif /* ACE_HAS_TSS_EMULATION */
+
+ ACE_Base_Thread_Adapter * const thread_args =
+ static_cast<ACE_Base_Thread_Adapter *> (args);
+
+#ifdef ACE_USES_GPROF
+ setitimer (ITIMER_PROF, thread_args->timerval (), 0);
+#endif // ACE_USES_GPROF
+
+ // Invoke the user-supplied function with the args.
+ ACE_THR_FUNC_RETURN status = thread_args->invoke ();
+
+ return status;
+}
+
diff --git a/ACE/ace/Base_Thread_Adapter.h b/ACE/ace/Base_Thread_Adapter.h
new file mode 100644
index 00000000000..f33f0facd48
--- /dev/null
+++ b/ACE/ace/Base_Thread_Adapter.h
@@ -0,0 +1,186 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Base_Thread_Adapter.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_BASE_THREAD_ADAPTER_H
+#define ACE_BASE_THREAD_ADAPTER_H
+#include /**/ "ace/pre.h"
+
+#include "ace/OS_Log_Msg_Attributes.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/OS_Log_Msg_Attributes.h"
+
+#ifdef ACE_USES_GPROF
+#include "os_include/sys/os_time.h"
+#endif // ACE_USES_GPROF
+
+#if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
+# define ACE_THREAD_ADAPTER_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ace_thread_adapter)
+#else
+# define ACE_THREAD_ADAPTER_NAME ace_thread_adapter
+#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+// Run the thread entry point for the ACE_Thread_Adapter. This must
+// be an extern "C" to make certain compilers happy...
+
+extern "C" ACE_Export ACE_THR_FUNC_RETURN ACE_THREAD_ADAPTER_NAME (void *args);
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_OS_Thread_Descriptor
+ *
+ * @brief Parent class of all ACE_Thread_Descriptor classes.
+ * =
+ * Container for ACE_Thread_Descriptor members that are
+ * used in ACE_OS.
+ */
+class ACE_Export ACE_OS_Thread_Descriptor
+{
+public:
+ /// Get the thread creation flags.
+ long flags (void) const;
+
+protected:
+ /// For use by ACE_Thread_Descriptor.
+ ACE_OS_Thread_Descriptor (long flags = 0);
+
+ /**
+ * Keeps track of whether this thread was created "detached" or not.
+ * If a thread is *not* created detached then if someone calls
+ * <ACE_Thread_Manager::wait>, we need to join with that thread (and
+ * close down the handle).
+ */
+ long flags_;
+};
+
+/**
+ * @class ACE_Base_Thread_Adapter
+ *
+ * @brief Base class for all the Thread_Adapters.
+ *
+ * Converts a C++ function into a function that can be
+ * called from a thread creation routine
+ * (e.g., pthread_create() or _beginthreadex()) that expects an
+ * extern "C" entry point. This class also makes it possible to
+ * transparently provide hooks to register a thread with an
+ * ACE_Thread_Manager.
+ * This class is used in ACE_OS::thr_create(). In general, the
+ * thread that creates an object of this class is different from
+ * the thread that calls @c invoke() on this object. Therefore,
+ * the @c invoke() method is responsible for deleting itself.
+ */
+class ACE_Export ACE_Base_Thread_Adapter
+{
+public:
+
+ virtual ~ACE_Base_Thread_Adapter (void);
+
+ /// Virtual method invoked by the thread entry point.
+ virtual ACE_THR_FUNC_RETURN invoke (void) = 0;
+
+ /// Accessor for the C entry point function to the OS thread creation
+ /// routine.
+ ACE_THR_C_FUNC entry_point (void);
+
+#ifdef ACE_USES_GPROF
+ /// Accessor to the itimer_
+ /// followed http://sam.zoy.org/writings/programming/gprof.html
+ struct itimerval* timerval (void);
+#endif // ACE_USES_PROF
+
+ /// Invoke the close_log_msg_hook, if it is present
+ static void close_log_msg (void);
+
+ /// Invoke the sync_log_msg_hook, if it is present
+ static void sync_log_msg (const ACE_TCHAR *prog_name);
+
+ /// Invoke the thr_desc_log_msg_hook, if it is present
+ static ACE_OS_Thread_Descriptor *thr_desc_log_msg (void);
+
+protected:
+ /// Constructor.
+ ACE_Base_Thread_Adapter (ACE_THR_FUNC user_func,
+ void *arg,
+ ACE_THR_C_FUNC entry_point = (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
+ ACE_OS_Thread_Descriptor *td = 0
+# 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 */
+ );
+ /// Inherit the logging features if the parent thread has an
+ /// ACE_Log_Msg.
+ void inherit_log_msg (void);
+
+private:
+ /// The hooks to inherit and cleanup the Log_Msg attributes
+ static ACE_INIT_LOG_MSG_HOOK init_log_msg_hook_;
+ static ACE_INHERIT_LOG_MSG_HOOK inherit_log_msg_hook_;
+ static ACE_CLOSE_LOG_MSG_HOOK close_log_msg_hook_;
+ static ACE_SYNC_LOG_MSG_HOOK sync_log_msg_hook_;
+ static ACE_THR_DESC_LOG_MSG_HOOK thr_desc_log_msg_hook_;
+
+ /// Set the Log_Msg hooks
+ static void set_log_msg_hooks (ACE_INIT_LOG_MSG_HOOK init_hook,
+ ACE_INHERIT_LOG_MSG_HOOK inherit_hook,
+ ACE_CLOSE_LOG_MSG_HOOK close_hook,
+ ACE_SYNC_LOG_MSG_HOOK sync_hook,
+ ACE_THR_DESC_LOG_MSG_HOOK thr_desc);
+
+ /// Allow the ACE_Log_Msg class to set its hooks.
+ friend class ACE_Log_Msg;
+
+protected:
+ /// Thread startup function passed in by the user (C++ linkage).
+ ACE_THR_FUNC user_func_;
+
+ /// Argument to thread startup function.
+ void *arg_;
+
+ /// Entry point to the underlying OS thread creation call (C
+ /// linkage).
+ ACE_THR_C_FUNC entry_point_;
+
+ /**
+ * Optional thread descriptor. Passing this pointer in will force
+ * the spawned thread to cache this location in <Log_Msg> and wait
+ * until <Thread_Manager> fills in all information in thread
+ * descriptor.
+ */
+ ACE_OS_Thread_Descriptor *thr_desc_;
+
+ /// The ACE_Log_Msg attributes.
+ ACE_OS_Log_Msg_Attributes log_msg_attributes_;
+ /// That is usefull for gprof, define itimerval
+#ifdef ACE_USES_GPROF
+ struct itimerval itimer_;
+#endif // ACE_USES_GPROF
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/Base_Thread_Adapter.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_BASE_THREAD_ADAPTER_H */
diff --git a/ACE/ace/Base_Thread_Adapter.inl b/ACE/ace/Base_Thread_Adapter.inl
new file mode 100644
index 00000000000..7fa3959034b
--- /dev/null
+++ b/ACE/ace/Base_Thread_Adapter.inl
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE long
+ACE_OS_Thread_Descriptor::flags (void) const
+{
+ return flags_;
+}
+
+ACE_INLINE
+ACE_OS_Thread_Descriptor::ACE_OS_Thread_Descriptor (long flags)
+ : flags_ (flags)
+{
+}
+
+ACE_INLINE void
+ACE_Base_Thread_Adapter::set_log_msg_hooks (
+ ACE_INIT_LOG_MSG_HOOK init_hook,
+ ACE_INHERIT_LOG_MSG_HOOK inherit_hook,
+ ACE_CLOSE_LOG_MSG_HOOK close_hook,
+ ACE_SYNC_LOG_MSG_HOOK sync_hook,
+ ACE_THR_DESC_LOG_MSG_HOOK thr_desc_hook)
+{
+ ACE_Base_Thread_Adapter::init_log_msg_hook_ = init_hook;
+ ACE_Base_Thread_Adapter::inherit_log_msg_hook_ = inherit_hook;
+ ACE_Base_Thread_Adapter::close_log_msg_hook_ = close_hook;
+ ACE_Base_Thread_Adapter::sync_log_msg_hook_ = sync_hook;
+ ACE_Base_Thread_Adapter::thr_desc_log_msg_hook_ = thr_desc_hook;
+}
+
+ACE_INLINE ACE_THR_C_FUNC
+ACE_Base_Thread_Adapter::entry_point (void)
+{
+ return this->entry_point_;
+}
+
+#ifdef ACE_USES_GPROF
+ACE_INLINE itimerval*
+ACE_Base_Thread_Adapter::timerval (void)
+{
+ return &(this->itimer_);
+}
+#endif // ACE_USES_GPROF
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Based_Pointer_Repository.cpp b/ACE/ace/Based_Pointer_Repository.cpp
new file mode 100644
index 00000000000..a76d3dbcbd3
--- /dev/null
+++ b/ACE/ace/Based_Pointer_Repository.cpp
@@ -0,0 +1,119 @@
+// $Id$
+
+#include "ace/Map_Manager.h"
+#include "ace/Based_Pointer_Repository.h"
+#include "ace/Guard_T.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Synch_Traits.h"
+#include "ace/RW_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Based_Pointer_Repository_Rep
+ *
+ * @brief Implementation for the ACE_Based_Pointer_Repository.
+ *
+ * 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.
+ */
+class ACE_Based_Pointer_Repository_Rep
+{
+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;
+
+ /// Keeps track of the mapping between addresses and their associated
+ /// values.
+ MAP_MANAGER addr_map_;
+
+ /// Synchronize concurrent access to the map.
+ ACE_SYNCH_MUTEX lock_;
+};
+
+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_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<ACE_Based_Pointer_Repository, ACE_SYNCH_RW_MUTEX> *
+ ACE_Singleton<ACE_Based_Pointer_Repository, ACE_SYNCH_RW_MUTEX>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Based_Pointer_Repository.h b/ACE/ace/Based_Pointer_Repository.h
new file mode 100644
index 00000000000..f7d7ac64125
--- /dev/null
+++ b/ACE/ace/Based_Pointer_Repository.h
@@ -0,0 +1,91 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Singleton.h"
+#include "ace/Synch_Traits.h"
+#include "ace/os_include/os_stddef.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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 @a base_addr region that contains @a addr.
+ * Returns 1 on success and 0 if the @a addr isn't contained in any
+ * @a 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 @a 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_;
+
+};
+
+// ----------------------------------
+
+/// Declare a process wide singleton
+ACE_SINGLETON_DECLARE (ACE_Singleton,
+ ACE_Based_Pointer_Repository,
+ ACE_SYNCH_RW_MUTEX)
+
+/// 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;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_BASED_POINTER_REPOSITORY_H */
diff --git a/ACE/ace/Based_Pointer_T.cpp b/ACE/ace/Based_Pointer_T.cpp
new file mode 100644
index 00000000000..217e1634690
--- /dev/null
+++ b/ACE/ace/Based_Pointer_T.cpp
@@ -0,0 +1,121 @@
+// $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_TEXT (X), __LINE__, ACE_TEXT (__FILE__))
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Based_Pointer_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntarget_ = %d\n"), this->target_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base_offset_ = %d\n"), this->base_offset_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("computed pointer = %x\n"),
+ (CONCRETE *)(ACE_COMPUTE_BASED_POINTER (this))));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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.
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_BASED_POINTER_T_CPP */
diff --git a/ACE/ace/Based_Pointer_T.h b/ACE/ace/Based_Pointer_T.h
new file mode 100644
index 00000000000..bb5874f002f
--- /dev/null
+++ b/ACE/ace/Based_Pointer_T.h
@@ -0,0 +1,205 @@
+// -*- 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/config-all.h"
+#include "ace/Basic_Types.h"
+
+#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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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.
+ bool operator < (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Less than or equal operator.
+ bool operator <= (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Greater than operator.
+ bool operator > (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Greater than or equal operator.
+ bool operator >= (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Equality operator.
+ bool operator == (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Inequality operator.
+ bool 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:
+ ptrdiff_t target_;
+
+ /// Keep track of our offset from the base pointer.
+ ptrdiff_t 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 @a base_addr. @a 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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Based_Pointer_T.inl"
+#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/ace/Based_Pointer_T.inl b/ACE/ace/Based_Pointer_T.inl
new file mode 100644
index 00000000000..5fb2c985f40
--- /dev/null
+++ b/ACE/ace/Based_Pointer_T.inl
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#define ACE_COMPUTE_BASED_POINTER(P) (((char *) (P) - (P)->base_offset_) + (P)->target_)
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class CONCRETE> ACE_INLINE CONCRETE *
+ACE_Based_Pointer<CONCRETE>::operator->(void)
+{
+ ACE_TRACE ("ACE_Based_Pointer<CONCRETE>::operator->");
+ return reinterpret_cast<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 *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 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 =
+ 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 bool
+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 bool
+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 bool
+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 bool
+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 bool
+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 bool
+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 ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Basic_Stats.cpp b/ACE/ace/Basic_Stats.cpp
new file mode 100644
index 00000000000..9c0b2a7c2f5
--- /dev/null
+++ b/ACE/ace/Basic_Stats.cpp
@@ -0,0 +1,78 @@
+// $Id$
+
+#include "ace/Basic_Stats.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Basic_Stats.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace,
+ Basic_Stats,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Basic_Stats::accumulate (const ACE_Basic_Stats &rhs)
+{
+ if (rhs.samples_count_ == 0)
+ return;
+
+ if (this->samples_count_ == 0)
+ {
+ this->min_ = rhs.min_;
+ this->min_at_ = rhs.min_at_;
+
+ this->max_ = rhs.max_;
+ this->max_at_ = rhs.max_at_;
+ }
+ else
+ {
+ if (this->min_ > rhs.min_)
+ {
+ this->min_ = rhs.min_;
+ this->min_at_ = rhs.min_at_;
+ }
+ if (this->max_ < rhs.max_)
+ {
+ this->max_ = rhs.max_;
+ this->max_at_ = rhs.max_at_;
+ }
+ }
+
+ this->samples_count_ += rhs.samples_count_;
+ this->sum_ += rhs.sum_;
+}
+
+void
+ACE_Basic_Stats::dump_results (const ACE_TCHAR *msg, ACE_UINT32 sf) const
+{
+#ifndef ACE_NLOGGING
+ if (this->samples_count () == 0u)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%s : no data collected\n"), msg));
+ return;
+ }
+
+ ACE_UINT64 avg = this->sum_ / this->samples_count_;
+
+ ACE_UINT64 l_min = this->min_ / sf;
+ ACE_UINT64 l_max = this->max_ / sf;
+ ACE_UINT64 l_avg = avg / sf;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%s latency : %Q[%d]/%Q/%Q[%d] (min/avg/max)\n"),
+ msg,
+ l_min, this->min_at_,
+ l_avg,
+ l_max, this->max_at_));
+
+#else
+ ACE_UNUSED_ARG (msg);
+ ACE_UNUSED_ARG (sf);
+#endif /* ACE_NLOGGING */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Basic_Stats.h b/ACE/ace/Basic_Stats.h
new file mode 100644
index 00000000000..11f24ca6bf8
--- /dev/null
+++ b/ACE/ace/Basic_Stats.h
@@ -0,0 +1,87 @@
+
+//=============================================================================
+/**
+ * @file Basic_Stats.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_BASIC_STATS_H
+#define ACE_BASIC_STATS_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include "ace/Basic_Types.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Collect basic stats about a series of samples
+/**
+ * Compute the average and standard deviation (aka jitter) for an
+ * arbitrary number of samples, using constant space.
+ * Normally used for latency statistics.
+ */
+class ACE_Export ACE_Basic_Stats
+{
+public:
+ /// Constructor
+ /**
+ * The number of samples is pre-allocated, and cannot changes once
+ * the class is initialized.
+ */
+ ACE_Basic_Stats (void);
+
+ /// The number of samples received so far
+ ACE_UINT32 samples_count (void) const;
+
+ /// Record one sample.
+ void sample (ACE_UINT64 value);
+
+ /// Update the values to reflect the stats in @a rhs.
+ void accumulate (const ACE_Basic_Stats &rhs);
+
+ /// Dump all the samples
+ /**
+ * Prints out the results, using @a msg as a prefix for each message and
+ * scaling all the numbers by @a scale_factor. The latter is useful because
+ * high resolution timer samples are acquired in clock ticks, but often
+ * presented in microseconds.
+ */
+ void dump_results (const ACE_TCHAR *msg,
+ ACE_UINT32 scale_factor) const;
+
+ /// The number of samples
+ ACE_UINT32 samples_count_;
+
+ /// The minimum value
+ ACE_UINT64 min_;
+
+ /// The number of the sample that had the minimum value
+ ACE_UINT32 min_at_;
+
+ /// The maximum value
+ ACE_UINT64 max_;
+
+ /// The number of the sample that had the maximum value
+ ACE_UINT32 max_at_;
+
+ /// The sum of all the values
+ ACE_UINT64 sum_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Basic_Stats.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_BASIC_STATS_H */
diff --git a/ACE/ace/Basic_Stats.inl b/ACE/ace/Basic_Stats.inl
new file mode 100644
index 00000000000..bbdce099907
--- /dev/null
+++ b/ACE/ace/Basic_Stats.inl
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Basic_Stats::ACE_Basic_Stats (void)
+ : samples_count_ (0)
+ , min_ (0)
+ , min_at_ (0)
+ , max_ (0)
+ , max_at_ (0)
+ , sum_ (0)
+{
+}
+
+ACE_INLINE ACE_UINT32
+ACE_Basic_Stats::samples_count (void) const
+{
+ return this->samples_count_;
+}
+
+ACE_INLINE void
+ACE_Basic_Stats::sample (ACE_UINT64 value)
+{
+ ++this->samples_count_;
+
+ if (this->samples_count_ == 1u)
+ {
+ this->min_ = value;
+ this->min_at_ = this->samples_count_;
+ this->max_ = value;
+ this->max_at_ = this->samples_count_;
+ }
+ else
+ {
+ if (this->min_ > value)
+ {
+ this->min_ = value;
+ this->min_at_ = this->samples_count_;
+ }
+ if (this->max_ < value)
+ {
+ this->max_ = value;
+ this->max_at_ = this->samples_count_;
+ }
+ }
+
+ this->sum_ += value;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Basic_Types.cpp b/ACE/ace/Basic_Types.cpp
new file mode 100644
index 00000000000..f2e055b991e
--- /dev/null
+++ b/ACE/ace/Basic_Types.cpp
@@ -0,0 +1,139 @@
+#include "ace/Basic_Types.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Basic_Types.inl"
+#endif /* ! __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Basic_Types,
+ "$Id$")
+
+
+#if defined (ACE_LACKS_LONGLONG_T) && !defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+# include "ace/Log_Msg.h"
+# include "ace/OS_NS_stdio.h"
+# include "ace/OS_NS_string.h"
+# if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+// FUZZ: disable check_for_streams_include
+# include "ace/streams.h"
+# endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_U_LongLong::output (FILE *file) const
+{
+ if (h_ () > 0)
+ ACE_OS::fprintf (file, "0x%lx%0*lx", h_ (), 2 * sizeof l_ (), l_ ());
+ else
+ ACE_OS::fprintf (file, "0x%lx", l_ ());
+}
+
+
+ACE_TCHAR *
+ACE_U_LongLong::as_string (ACE_TCHAR *output,
+ unsigned int base,
+ unsigned int uppercase) const
+{
+ if (*this == 0)
+ {
+ ACE_OS::strcpy(output, "0");
+ }
+ else
+ {
+ switch(base)
+ {
+ case 8:
+ {
+ unsigned int index = 0;
+ int bshift = 31;
+ while(bshift >= 1)
+ {
+ unsigned int sval = (this->h_ () >> bshift) & 7;
+ if (sval > 0 || index != 0)
+ {
+ output[index] = sval + '0';
+ ++index;
+ }
+ bshift -= 3;
+ }
+ bshift = 30;
+ while(bshift >= 0)
+ {
+ unsigned int sval = (this->l_ () >> bshift) & 7;
+ // Combine the last bit of hi with the first 3-bit digit
+ if (bshift == 30)
+ {
+ sval |= (this->h_ () & 1) << 2;
+ }
+ if (sval > 0 || index != 0)
+ {
+ output[index] = sval + '0';
+ ++index;
+ }
+ bshift -= 3;
+ }
+ output[index] = '\0';
+ break;
+ }
+ case 10:
+ {
+ ACE_OS::sprintf(output, "%.0f", *this / 1.0);
+ break;
+ }
+ case 16:
+ {
+ if (this->h_ () != 0)
+ {
+ ACE_OS::sprintf(output,
+ (uppercase ? "%lX%0*lX" : "%lx%0*lx"),
+ this->h_ (), 2 * sizeof this->l_ (),
+ this->l_ ());
+ }
+ else
+ {
+ ACE_OS::sprintf(output,
+ (uppercase ? "%lX" : "%lx"), this->l_ ());
+
+ }
+ break;
+ }
+ default:
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Unsupported base = %u\n"), base));
+ output[0] = '\0';
+ }
+ }
+ }
+
+ return output;
+}
+
+
+# if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ostream&
+operator<< (ostream& os, const ACE_U_LongLong& ll)
+{
+#ifdef __TANDEM && (__CPLUSPLUS_VERSION >= 3)
+ unsigned long flags = os.flags();
+#else
+ unsigned long flags = os.setf(0);
+#endif
+ char buffer[32];
+
+ if ((flags & ios::oct) != 0)
+ os << ll.as_string (buffer, 8);
+ else if ((flags & ios::hex) != 0)
+ os << ll.as_string (buffer, 16, (flags & ios::uppercase));
+ else
+ os << ll.as_string (buffer);
+ return os;
+}
+# endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_LONGLONG_T */
+
diff --git a/ACE/ace/Basic_Types.h b/ACE/ace/Basic_Types.h
new file mode 100644
index 00000000000..2d6942bb511
--- /dev/null
+++ b/ACE/ace/Basic_Types.h
@@ -0,0 +1,890 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Basic_Types.h
+ *
+ * $Id$
+ *
+ * @author David L. Levine
+ *
+ * #defines the list of preprocessor macros below. The config.h file can
+ * pre-define any of these to short-cut the definitions. This is usually
+ * only necessary if the preprocessor does all of its math using integers.
+ *
+ * Sizes of built-in types:
+ * - ACE_SIZEOF_CHAR
+ * - ACE_SIZEOF_WCHAR
+ * - ACE_SIZEOF_SHORT
+ * - ACE_SIZEOF_INT
+ * - ACE_SIZEOF_LONG
+ * - ACE_SIZEOF_LONG_LONG
+ * - ACE_SIZEOF_VOID_P
+ * - ACE_SIZEOF_FLOAT
+ * - ACE_SIZEOF_DOUBLE
+ * - ACE_SIZEOF_LONG_DOUBLE
+ *
+ * Wrappers for built-in types of specific sizes:
+ * - ACE_USHORT16 (For backward compatibility. Use ACE_UINT16 instead.)
+ * - ACE_INT8
+ * - ACE_UINT8
+ * - ACE_INT16
+ * - ACE_UINT16
+ * - ACE_INT32
+ * - ACE_UINT32
+ * - ACE_UINT64
+ * (@note ACE_INT64 is partly defined, there is no ACE_LongLong for
+ * platforms that don't have a native 8-byte integer type.)
+ *
+ * Byte-order (endian-ness) determination:
+ * ACE_BYTE_ORDER, to either ACE_BIG_ENDIAN or ACE_LITTLE_ENDIAN
+ *
+ *
+ */
+//=============================================================================
+
+#include "ace/config-lite.h"
+
+#ifndef ACE_BASIC_TYPES_H
+# define ACE_BASIC_TYPES_H
+
+# include /**/ "ace/pre.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Pull in definitions
+# include "ace/os_include/os_limits.h" // Integer limits
+# include "ace/os_include/os_float.h" // Floating point limits
+# include "ace/os_include/os_stdlib.h" // Other types
+# include "ace/os_include/os_stddef.h" // Get ptrdiff_t - see further comments below
+
+# if defined(ACE_LACKS_LONGLONG_T)
+# include "ace/os_include/os_stdio.h" // For long long emulation
+# endif /* ACE_LACKS_LONGLONG_T */
+
+# include "ace/os_include/sys/os_types.h"
+
+# if !defined (ACE_LACKS_SYS_PARAM_H)
+# include /**/ <sys/param.h>
+# endif /* ACE_LACKS_SYS_PARAM_H */
+
+# include "ace/ACE_export.h"
+
+# if !defined (ACE_LACKS_STDINT_H)
+# include <stdint.h>
+# endif
+# if !defined (ACE_LACKS_INTTYPES_H)
+# include <inttypes.h>
+# endif
+
+#ifdef ACE_LACKS_INTPTR_T
+# include "ace/If_Then_Else.h"
+
+// This intptr_t typedef is here instead of
+// <ace/os_include/os_inttypes.h> since it depends on the template
+// metaprogramming in <ace/If_Then_Else.h>.
+
+// We could compare ACE_SIZEOF_VOID_P against ACE_SIZEOF_LONG, etc.
+// However, that depends on the ACE preprocessor symbol definitions in
+// the platform-specific configuration header being correct.
+// The template meta-programming approach we take below,
+// i.e. determining the type at compile-time rather than at
+// preprocessing-time, will work for all platforms, and does not
+// depend on ACE developer-defined configuration parameters.
+
+typedef ACE::If_Then_Else<
+ (sizeof (void*) == sizeof (signed int)),
+ signed int,
+ ACE::If_Then_Else<
+ (sizeof (void*) == sizeof (signed long)),
+ signed long,
+#ifdef ACE_LACKS_LONGLONG_T
+ void /* Unknown. Force an invalid type */
+#else
+ ACE::If_Then_Else<
+ (sizeof (void*) == sizeof (signed long long)),
+ signed long long,
+ void /* Unknown. Force an invalid type */
+ >::result_type
+#endif /* ACE_LACKS_LONGLONG_T */
+ >::result_type
+ >::result_type intptr_t;
+
+typedef ACE::If_Then_Else<
+ (sizeof (void*) == sizeof (unsigned int)),
+ unsigned int,
+ ACE::If_Then_Else<
+ (sizeof (void*) == sizeof (unsigned long)),
+ unsigned long,
+#ifdef ACE_LACKS_UNSIGNEDLONGLONG_T
+ void /* Unknown. Force an invalid type */
+#else
+ ACE::If_Then_Else<
+ (sizeof (void*) == sizeof (unsigned long long)),
+ unsigned long long,
+ void /* Unknown. Force an invalid type */
+ >::result_type
+#endif /* ACE_LACKS_UNSIGNEDLONGLONG_T */
+ >::result_type
+ >::result_type uintptr_t;
+
+#endif /* ACE_LACKS_INTPTR_T */
+
+// A char always has 1 byte, by definition.
+# define ACE_SIZEOF_CHAR 1
+
+// Unfortunately, there isn't a portable way to determine the size of a wchar.
+// So we just define them on a platform basis. If the platform doesn't
+// define it and it's an XPG4 system, assume wchar_t is 4 bytes. Some code
+// uses ACE_SIZEOF_WCHAR in preprocessor statements, so sizeof() isn't valid.
+// If the platform config doesn't set this, and this guess is wrong,
+// Basic_Types_Test should catch the inconsistency.
+# if defined (ACE_HAS_WCHAR)
+# if !defined (ACE_SIZEOF_WCHAR)
+# if defined (ACE_HAS_XPG4_MULTIBYTE_CHAR)
+# define ACE_SIZEOF_WCHAR 4
+# else
+// 0 so the Basic_Types test will catch this.
+# define ACE_SIZEOF_WCHAR 0
+# endif /* ACE_HAS_XPG4_MULTIBYTE_CHAR */
+# endif /* !ACE_SIZEOF_WCHAR */
+# endif /* ACE_HAS_WCHAR */
+
+// The number of bytes in a short.
+# if !defined (ACE_SIZEOF_SHORT)
+# if (USHRT_MAX) == 255U
+# define ACE_SIZEOF_SHORT 1
+# elif (USHRT_MAX) == 65535U
+# define ACE_SIZEOF_SHORT 2
+# elif (USHRT_MAX) == 4294967295U
+# define ACE_SIZEOF_SHORT 4
+# elif (USHRT_MAX) == 18446744073709551615U
+# define ACE_SIZEOF_SHORT 8
+# else
+# error: unsupported short size, must be updated for this platform!
+# endif /* USHRT_MAX */
+# endif /* !defined (ACE_SIZEOF_SHORT) */
+
+// The number of bytes in an int.
+# if !defined (ACE_SIZEOF_INT)
+# if (UINT_MAX) == 65535U
+# define ACE_SIZEOF_INT 2
+# elif (UINT_MAX) == 4294967295U
+# define ACE_SIZEOF_INT 4
+# elif (UINT_MAX) == 18446744073709551615U
+# define ACE_SIZEOF_INT 8
+# else
+# error: unsupported int size, must be updated for this platform!
+# endif /* UINT_MAX */
+# endif /* !defined (ACE_SIZEOF_INT) */
+
+// The number of bytes in a long.
+# if !defined (ACE_SIZEOF_LONG)
+# if (ULONG_MAX) == 65535UL
+# define ACE_SIZEOF_LONG 2
+# elif ((ULONG_MAX) == 4294967295UL)
+# define ACE_SIZEOF_LONG 4
+# elif ((ULONG_MAX) == 18446744073709551615UL)
+# define ACE_SIZEOF_LONG 8
+# else
+# error: unsupported long size, must be updated for this platform!
+# endif /* ULONG_MAX */
+# endif /* !defined (ACE_SIZEOF_LONG) */
+
+// The number of bytes in a long long.
+# if !defined (ACE_SIZEOF_LONG_LONG)
+# if defined (ACE_LACKS_LONGLONG_T)
+# define ACE_SIZEOF_LONG_LONG 8
+# elif defined (ULLONG_MAX)
+# if ((ULLONG_MAX) == 4294967295ULL)
+# define ACE_SIZEOF_LONG_LONG 4
+# elif ((ULLONG_MAX) == 18446744073709551615ULL)
+# define ACE_SIZEOF_LONG_LONG 8
+# endif
+# elif defined (ULONGLONG_MAX)
+# if ((ULONGLONG_MAX) == 4294967295ULL)
+# define ACE_SIZEOF_LONG_LONG 4
+# elif ((ULONGLONG_MAX) == 18446744073709551615ULL)
+# define ACE_SIZEOF_LONG_LONG 8
+# endif
+# endif
+# // If we can't determine the size of long long, assume it is 8
+# // instead of erroring out. (Either ULLONG_MAX and ULONGLONG_MAX
+# // may not be supported; or an extended C/C++ dialect may need to
+# // be selected. If this assumption is wrong, it can be addressed
+# // in the platform-specific config header.
+# if !defined (ACE_SIZEOF_LONG_LONG)
+# define ACE_SIZEOF_LONG_LONG 8
+# endif
+# endif /* !defined (ACE_SIZEOF_LONG_LONG) */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// The sizes of the commonly implemented types are now known. Set up
+// typedefs for whatever we can. Some of these are needed for certain
+// cases of ACE_UINT64, so do them before the 64-bit stuff.
+
+#if defined (ACE_INT8_TYPE)
+ typedef ACE_INT8_TYPE ACE_INT8;
+#elif defined (ACE_HAS_INT8_T)
+ typedef int8_t ACE_INT8;
+#elif !defined (ACE_LACKS_SIGNED_CHAR)
+ typedef signed char ACE_INT8;
+#else
+ typedef char ACE_INT8;
+#endif /* defined (ACE_INT8_TYPE) */
+
+#if defined (ACE_UINT8_TYPE)
+ typedef ACE_UINT8_TYPE ACE_UINT8;
+#elif defined (ACE_HAS_UINT8_T)
+ typedef uint8_t ACE_UINT8;
+#else
+ typedef unsigned char ACE_UINT8;
+#endif /* defined (ACE_UINT8_TYPE) */
+
+#if defined (ACE_INT16_TYPE)
+ typedef ACE_INT16_TYPE ACE_INT16;
+#elif defined (ACE_HAS_INT16_T)
+ typedef int16_t ACE_INT16;
+#elif ACE_SIZEOF_SHORT == 2
+ typedef short ACE_INT16;
+#elif ACE_SIZEOF_INT == 2
+ typedef int ACE_INT16;
+#else
+# error Have to add to the ACE_INT16 type setting
+#endif /* defined (ACE_INT16_TYPE) */
+
+#if defined (ACE_UINT16_TYPE)
+ typedef ACE_UINT16_TYPE ACE_UINT16;
+#elif defined (ACE_HAS_UINT16_T)
+ typedef uint16_t ACE_UINT16;
+#elif ACE_SIZEOF_SHORT == 2
+ typedef unsigned short ACE_UINT16;
+#elif ACE_SIZEOF_INT == 2
+ typedef unsigned int ACE_UINT16;
+#else
+# error Have to add to the ACE_UINT16 type setting
+#endif /* defined (ACE_UINT16_TYPE) */
+
+#if defined (ACE_INT32_TYPE)
+ typedef ACE_INT32_TYPE ACE_INT32;
+#elif defined (ACE_HAS_INT32_T)
+ typedef int32_t ACE_INT32;
+#elif ACE_SIZEOF_INT == 4
+ typedef int ACE_INT32;
+#elif ACE_SIZEOF_LONG == 4
+ typedef long ACE_INT32;
+#else
+# error Have to add to the ACE_INT32 type setting
+#endif /* defined (ACE_INT32_TYPE) */
+
+#if defined (ACE_UINT32_TYPE)
+ typedef ACE_UINT32_TYPE ACE_UINT32;
+#elif defined (ACE_HAS_UINT32_T)
+ typedef uint32_t ACE_UINT32;
+#elif ACE_SIZEOF_INT == 4
+ typedef unsigned int ACE_UINT32;
+#elif ACE_SIZEOF_LONG == 4
+ typedef unsigned long ACE_UINT32;
+#else
+# error Have to add to the ACE_UINT32 type setting
+#endif /* defined (ACE_UINT32_TYPE) */
+
+#if defined (ACE_INT64_TYPE)
+ typedef ACE_INT64_TYPE ACE_INT64;
+#elif defined (ACE_HAS_INT64_T)
+ typedef int64_t ACE_INT64;
+#elif ACE_SIZEOF_LONG == 8
+ typedef long ACE_INT64;
+#elif !defined (ACE_LACKS_LONGLONG_T) && ACE_SIZEOF_LONG_LONG == 8
+# ifdef __GNUC__
+ // Silence g++ "-pedantic" warnings regarding use of "long long"
+ // type.
+ __extension__
+# endif /* __GNUC__ */
+ typedef long long ACE_INT64;
+#endif /* defined (ACE_INT64_TYPE) */
+
+#if !(defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T))
+/* See matching #if around ACE_U_LongLong class declaration below */
+
+# if defined (ACE_UINT64_TYPE)
+ typedef ACE_UINT64_TYPE ACE_UINT64;
+# elif defined (ACE_HAS_UINT64_T)
+ typedef uint64_t ACE_UINT64;
+# elif ACE_SIZEOF_LONG == 8
+ typedef unsigned long ACE_UINT64;
+# elif ACE_SIZEOF_LONG_LONG == 8
+# ifdef __GNUC__
+ // Silence g++ "-pedantic" warnings regarding use of "long long"
+ // type.
+ __extension__
+# endif /* __GNUC__ */
+ typedef unsigned long long ACE_UINT64;
+# endif /* defined (ACE_UINT64_TYPE) */
+#endif /* !(ACE_LACKS_LONGLONG_T || ACE_LACKS_UNSIGNEDLONGLONG_T) */
+
+
+typedef ACE_UINT16 ACE_USHORT16; // @@ Backward compatibility.
+
+// Define a generic byte for use in codecs
+typedef unsigned char ACE_Byte;
+
+// Define a pseudo wide character type when wchar is not supported so we
+// can support basic wide character string operations.
+
+# if defined (ACE_HAS_WCHAR) || defined (ACE_HAS_XPG4_MULTIBYTE_CHAR)
+# define ACE_WINT_T wint_t
+# define ACE_WCHAR_T wchar_t
+# else
+# define ACE_WINT_T ACE_UINT16
+# define ACE_WCHAR_T ACE_UINT16
+# endif /* ACE_HAS_WCHAR */
+
+// The number of bytes in a void *.
+# ifndef ACE_SIZEOF_VOID_P
+# define ACE_SIZEOF_VOID_P ACE_SIZEOF_LONG
+# endif /* ACE_SIZEOF_VOID_P */
+
+// Type for doing arithmetic on pointers ... as elsewhere, we assume
+// that unsigned versions of a type are the same size as the signed
+// version of the same type.
+# if defined (ACE_HAS_WINCE) && (_WIN32_WCE < 400)
+typedef unsigned long ptrdiff_t; // evc3, PocketPC don't defined ptrdiff_t
+# endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Byte-order (endian-ness) determination.
+# if defined (BYTE_ORDER)
+# if (BYTE_ORDER == LITTLE_ENDIAN)
+# define ACE_LITTLE_ENDIAN 0x0123
+# define ACE_BYTE_ORDER ACE_LITTLE_ENDIAN
+# elif (BYTE_ORDER == BIG_ENDIAN)
+# define ACE_BIG_ENDIAN 0x3210
+# define ACE_BYTE_ORDER ACE_BIG_ENDIAN
+# else
+# error: unknown BYTE_ORDER!
+# endif /* BYTE_ORDER */
+# elif defined (_BYTE_ORDER)
+# if (_BYTE_ORDER == _LITTLE_ENDIAN)
+# define ACE_LITTLE_ENDIAN 0x0123
+# define ACE_BYTE_ORDER ACE_LITTLE_ENDIAN
+# elif (_BYTE_ORDER == _BIG_ENDIAN)
+# define ACE_BIG_ENDIAN 0x3210
+# define ACE_BYTE_ORDER ACE_BIG_ENDIAN
+# else
+# error: unknown _BYTE_ORDER!
+# endif /* _BYTE_ORDER */
+# elif defined (__BYTE_ORDER)
+# if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define ACE_LITTLE_ENDIAN 0x0123
+# define ACE_BYTE_ORDER ACE_LITTLE_ENDIAN
+# elif (__BYTE_ORDER == __BIG_ENDIAN)
+# define ACE_BIG_ENDIAN 0x3210
+# define ACE_BYTE_ORDER ACE_BIG_ENDIAN
+# else
+# error: unknown __BYTE_ORDER!
+# endif /* __BYTE_ORDER */
+# else /* ! BYTE_ORDER && ! __BYTE_ORDER */
+ // We weren't explicitly told, so we have to figure it out . . .
+# if defined (i386) || defined (__i386__) || defined (_M_IX86) || \
+ defined (vax) || defined (__alpha) || defined (__LITTLE_ENDIAN__) || \
+ defined (ARM) || defined (_M_IA64) || defined (__ia64__) || \
+ defined (_M_AMD64) || defined (__amd64)
+ // We know these are little endian.
+# define ACE_LITTLE_ENDIAN 0x0123
+# define ACE_BYTE_ORDER ACE_LITTLE_ENDIAN
+# else
+ // Otherwise, we assume big endian.
+# define ACE_BIG_ENDIAN 0x3210
+# define ACE_BYTE_ORDER ACE_BIG_ENDIAN
+# endif
+# endif /* ! BYTE_ORDER && ! __BYTE_ORDER */
+
+// Byte swapping macros to deal with differences between little endian
+// and big endian machines. Note that "long" here refers to 32 bit
+// quantities.
+# define ACE_SWAP_LONG(L) ((ACE_SWAP_WORD ((L) & 0xFFFF) << 16) \
+ | ACE_SWAP_WORD(((L) >> 16) & 0xFFFF))
+# define ACE_SWAP_WORD(L) ((((L) & 0x00FF) << 8) | (((L) & 0xFF00) >> 8))
+
+# if defined (ACE_LITTLE_ENDIAN)
+# define ACE_HTONL(X) ACE_SWAP_LONG (X)
+# define ACE_NTOHL(X) ACE_SWAP_LONG (X)
+# define ACE_IDL_NCTOHL(X) (X)
+# define ACE_IDL_NSTOHL(X) (X)
+# else
+# define ACE_HTONL(X) X
+# define ACE_NTOHL(X) X
+# define ACE_IDL_NCTOHL(X) (X << 24)
+# define ACE_IDL_NSTOHL(X) ((X) << 16)
+# endif /* ACE_LITTLE_ENDIAN */
+
+# if defined (ACE_LITTLE_ENDIAN)
+# define ACE_HTONS(x) ACE_SWAP_WORD(x)
+# define ACE_NTOHS(x) ACE_SWAP_WORD(x)
+# else
+# define ACE_HTONS(x) x
+# define ACE_NTOHS(x) x
+# endif /* ACE_LITTLE_ENDIAN */
+
+#if defined (ACE_LACKS_LONGLONG_T)
+ // This throws away the high 32 bits. It's very unlikely that a
+ // pointer will be more than 32 bits wide if the platform does not
+ // support 64-bit integers.
+# define ACE_LONGLONG_TO_PTR(PTR_TYPE, L) \
+ reinterpret_cast<PTR_TYPE> (L.lo ())
+#elif defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
+# define ACE_LONGLONG_TO_PTR(PTR_TYPE, L) \
+ reinterpret_cast<PTR_TYPE> (static_cast<int> (L))
+#else /* ! ACE_LACKS_LONGLONG_T */
+# define ACE_LONGLONG_TO_PTR(PTR_TYPE, L) \
+ reinterpret_cast<PTR_TYPE> (static_cast<intptr_t> (L))
+#endif /* ! ACE_LACKS_LONGLONG_T */
+
+// If the platform lacks an unsigned long long, define one.
+#if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+// Forward declaration for streams
+# include "ace/iosfwd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_U_LongLong
+ *
+ * @brief Unsigned long long for platforms that don't have one.
+ *
+ * Provide our own unsigned long long. This is intended to be
+ * use with ACE_High_Res_Timer, so the division operator assumes
+ * that the quotient fits into a u_long.
+ * Please note that the constructor takes (optionally) two values.
+ * The high one contributes 0x100000000 times its value. So,
+ * for example, (0, 2) is _not_ 20000000000, but instead
+ * 0x200000000. To emphasize this, the default values are expressed
+ * in hex, and output () dumps the value in hex.
+ */
+ class ACE_Export ACE_U_LongLong
+ {
+ public:
+ // = Initialization and termination methods.
+#if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+ ACE_U_LongLong (const long long value = 0x0);
+#else
+ ACE_U_LongLong (const ACE_UINT32 lo = 0x0, const ACE_UINT32 hi = 0x0);
+#endif
+ ACE_U_LongLong (const ACE_U_LongLong &);
+ ACE_U_LongLong &operator= (const ACE_U_LongLong &);
+ ACE_U_LongLong &operator= (const ACE_INT32 &);
+ ACE_U_LongLong &operator= (const ACE_UINT32 &);
+ ~ACE_U_LongLong (void);
+
+ // = Overloaded relation operators.
+ bool operator== (const ACE_U_LongLong &) const;
+ bool operator== (const ACE_UINT32) const;
+ bool operator!= (const ACE_U_LongLong &) const;
+ bool operator!= (const ACE_UINT32) const;
+ bool operator< (const ACE_U_LongLong &) const;
+ bool operator< (const ACE_UINT32) const;
+ bool operator<= (const ACE_U_LongLong &) const;
+ bool operator<= (const ACE_UINT32) const;
+ bool operator> (const ACE_U_LongLong &) const;
+ bool operator> (const ACE_UINT32) const;
+ bool operator>= (const ACE_U_LongLong &) const;
+ bool operator>= (const ACE_UINT32) const;
+
+ ACE_U_LongLong operator+ (const ACE_U_LongLong &) const;
+ ACE_U_LongLong operator+ (const ACE_UINT32) const;
+ ACE_U_LongLong operator- (const ACE_U_LongLong &) const;
+ ACE_U_LongLong operator- (const ACE_UINT32) const;
+ ACE_U_LongLong operator* (const ACE_UINT32) const;
+ ACE_U_LongLong &operator*= (const ACE_UINT32);
+
+ ACE_U_LongLong operator<< (const unsigned int) const;
+ ACE_U_LongLong &operator<<= (const unsigned int);
+ ACE_U_LongLong operator>> (const unsigned int) const;
+ ACE_U_LongLong &operator>>= (const unsigned int);
+
+ double operator/ (const double) const;
+
+ ACE_U_LongLong &operator+= (const ACE_U_LongLong &);
+ ACE_U_LongLong &operator+= (const ACE_UINT32);
+ ACE_U_LongLong &operator-= (const ACE_U_LongLong &);
+ ACE_U_LongLong &operator-= (const ACE_UINT32);
+ ACE_U_LongLong &operator++ ();
+ ACE_U_LongLong &operator-- ();
+ const ACE_U_LongLong operator++ (int);
+ const ACE_U_LongLong operator-- (int);
+ ACE_U_LongLong &operator|= (const ACE_U_LongLong);
+ ACE_U_LongLong &operator|= (const ACE_UINT32);
+ ACE_U_LongLong &operator&= (const ACE_U_LongLong);
+ ACE_U_LongLong &operator&= (const ACE_UINT32);
+
+ // Note that the following take ACE_UINT32 arguments. These are
+ // typical use cases, and easy to implement. But, they limit the
+ // return values to 32 bits as well. There are no checks for
+ // overflow.
+ ACE_UINT32 operator/ (const ACE_UINT32) const;
+ ACE_UINT32 operator% (const ACE_UINT32) const;
+
+ // The following only operate on the lower 32 bits (they take only
+ // 32 bit arguments).
+ ACE_UINT32 operator| (const ACE_INT32) const;
+ ACE_UINT32 operator& (const ACE_INT32) const;
+
+ // The following operators convert their arguments to
+ // ACE_UINT32. So, there may be information loss if they are
+ // used.
+ ACE_U_LongLong operator* (const ACE_INT32) const;
+ ACE_U_LongLong &operator*= (const ACE_INT32);
+ ACE_UINT32 operator/ (const ACE_INT32) const;
+# if ACE_SIZEOF_INT == 4
+ ACE_UINT32 operator/ (const unsigned long) const;
+ ACE_UINT32 operator/ (const long) const;
+# else /* ACE_SIZEOF_INT != 4 */
+ ACE_UINT32 operator/ (const unsigned int) const;
+ ACE_UINT32 operator/ (const int) const;
+# endif /* ACE_SIZEOF_INT != 4 */
+
+ // = Helper methods.
+ /// Outputs the value to the FILE, in hex.
+ void output (FILE * = stdout) const;
+
+ ACE_TCHAR *as_string (ACE_TCHAR *string,
+ unsigned int base = 10,
+ unsigned int uppercase = 0) const;
+
+ ACE_UINT32 hi (void) const;
+ ACE_UINT32 lo (void) const;
+
+ void hi (const ACE_UINT32 hi);
+ void lo (const ACE_UINT32 lo);
+
+#if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+ long long to_int64 (void) const;
+# endif
+
+ private:
+
+#if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+ long long data_;
+#else
+ public:
+ struct ace_hi_lo_correct_endian
+ {
+# if defined (ACE_BIG_ENDIAN)
+ /// High 32 bits.
+ ACE_UINT32 hi_;
+ /// Low 32 bits.
+ ACE_UINT32 lo_;
+
+# else
+
+ /// Low 32 bits.
+ ACE_UINT32 lo_;
+ /// High 32 bits.
+ ACE_UINT32 hi_;
+# endif /* ! ACE_BIG_ENDIAN */
+ };
+ private:
+ union
+ {
+ struct ace_hi_lo_correct_endian data_;
+
+ /// To ensure alignment on 8-byte boundary.
+ double for_alignment_;
+ };
+
+ // @note the following four accessors are inlined here in
+ // order to minimize the extent of the data_ struct. It's
+ // only used here; the .i and .cpp files use the accessors.
+
+ /// Internal utility function to hide access through struct.
+ const ACE_UINT32 &h_ () const { return data_.hi_; }
+
+ /// Internal utility function to hide access through struct.
+ ACE_UINT32 &h_ () { return data_.hi_; }
+
+ /// Internal utility function to hide access through struct.
+ const ACE_UINT32 &l_ () const { return data_.lo_; }
+
+ /// Internal utility function to hide access through struct.
+ ACE_UINT32 &l_ () { return data_.lo_; }
+
+ // @note the above four accessors are inlined here in
+ // order to minimize the extent of the data_ struct. It's
+ // only used here; the .inl and .cpp files use the accessors.
+
+ /// These functions are used to implement multiplication.
+ ACE_UINT32 ul_shift (ACE_UINT32 a,
+ ACE_UINT32 c_in,
+ ACE_UINT32 *c_out) const;
+ ACE_U_LongLong ull_shift (ACE_U_LongLong a,
+ ACE_UINT32 c_in,
+ ACE_UINT32 *c_out) const;
+ ACE_U_LongLong ull_add (ACE_U_LongLong a,
+ ACE_U_LongLong b,
+ ACE_UINT32 *carry) const;
+ ACE_U_LongLong ull_mult (ACE_U_LongLong a,
+ ACE_UINT32 b,
+ ACE_UINT32 *carry) const;
+#endif // ACE_LACKS_UNSIGNEDLONGLONG_T
+ };
+
+ typedef ACE_U_LongLong ACE_UINT64;
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ ostream &operator<< (ostream &, const ACE_U_LongLong &);
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# endif /* ACE_LACKS_LONGLONG_T */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Conversions from ACE_UINT64 to ACE_UINT32. ACE_CU64_TO_CU32 should
+// be used on const ACE_UINT64's.
+# if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+inline ACE_UINT32
+ACE_U64_TO_U32 (ACE_U_LongLong const & n)
+{
+ /**
+ * @note We could add a cast operator to ACE_U_LongLong but that may
+ * cause more problems than it solves. Force users to perform
+ * an explicit cast via ACE_{C}U64_TO_{C}U32.
+ */
+ return n.lo ();
+}
+
+inline ACE_UINT32
+ACE_CU64_TO_CU32 (ACE_U_LongLong const & n)
+{
+ return ACE_U64_TO_U32 (n);
+}
+# else /* ! ACE_LACKS_LONGLONG_T */
+inline ACE_UINT32
+ACE_U64_TO_U32 (ACE_UINT64 n)
+{
+ return static_cast<ACE_UINT32> (n);
+}
+
+inline ACE_UINT32
+ACE_CU64_TO_CU32 (ACE_UINT64 n)
+{
+ return static_cast<ACE_UINT32> (n);
+}
+# endif /* ! ACE_LACKS_LONGLONG_T */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// 64-bit literals require special marking on some platforms.
+# if defined (ACE_LACKS_LONGLONG_T)
+ // Can only specify 32-bit arguments.
+# define ACE_UINT64_LITERAL(n) n ## UL
+ // This one won't really work, but it'll keep
+ // some compilers happy until we have better support
+# define ACE_INT64_LITERAL(n) n ## L
+# elif defined (ACE_WIN32)
+# if defined (__MINGW32__)
+# define ACE_UINT64_LITERAL(n) n ## ull
+# define ACE_INT64_LITERAL(n) n ## ll
+# else
+# define ACE_UINT64_LITERAL(n) n ## ui64
+# define ACE_INT64_LITERAL(n) n ## i64
+# endif /* defined (__MINGW32__) */
+# elif defined (__TANDEM)
+# define ACE_UINT64_LITERAL(n) n ## LL
+# define ACE_INT64_LITERAL(n) n ## LL
+# else /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */
+# define ACE_UINT64_LITERAL(n) n ## ull
+# define ACE_INT64_LITERAL(n) n ## ll
+# endif /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */
+
+#if !defined (ACE_INT8_FORMAT_SPECIFIER)
+# if defined (PRId8)
+# define ACE_INT8_FORMAT_SPECIFIER ACE_TEXT ("%") ACE_TEXT (PRId8)
+# else
+# define ACE_INT8_FORMAT_SPECIFIER ACE_TEXT ("%d")
+# endif /* defined (PRId8) */
+#endif /* ACE_INT8_FORMAT_SPECIFIER */
+
+#if !defined (ACE_UINT8_FORMAT_SPECIFIER)
+# if defined (PRIu8)
+# define ACE_UINT8_FORMAT_SPECIFIER ACE_TEXT ("%") ACE_TEXT (PRIu8)
+# else
+# define ACE_UINT8_FORMAT_SPECIFIER ACE_TEXT ("%u")
+# endif /* defined (PRIu8) */
+#endif /* ACE_UINT8_FORMAT_SPECIFIER */
+
+#if !defined (ACE_INT16_FORMAT_SPECIFIER)
+# if defined (PRId16)
+# define ACE_INT16_FORMAT_SPECIFIER ACE_TEXT ("%") ACE_TEXT (PRId16)
+# else
+# define ACE_INT16_FORMAT_SPECIFIER ACE_TEXT ("%d")
+# endif /* defined (PRId16) */
+#endif /* ACE_INT16_FORMAT_SPECIFIER */
+
+#if !defined (ACE_UINT16_FORMAT_SPECIFIER)
+# if defined (PRIu16)
+# define ACE_UINT16_FORMAT_SPECIFIER ACE_TEXT ("%") ACE_TEXT (PRIu16)
+# else
+# define ACE_UINT16_FORMAT_SPECIFIER ACE_TEXT ("%u")
+# endif /* defined (PRIu16) */
+#endif /* ACE_UINT16_FORMAT_SPECIFIER */
+
+#if !defined (ACE_INT32_FORMAT_SPECIFIER)
+# if defined (PRId32)
+# define ACE_INT32_FORMAT_SPECIFIER ACE_TEXT ("%") ACE_TEXT (PRId32)
+# elif ACE_SIZEOF_INT == 4
+# define ACE_INT32_FORMAT_SPECIFIER ACE_TEXT ("%d")
+# else
+# define ACE_INT32_FORMAT_SPECIFIER ACE_TEXT ("%ld")
+# endif /* defined (PRId32) */
+#endif /* ACE_INT32_FORMAT_SPECIFIER */
+
+#if !defined (ACE_UINT32_FORMAT_SPECIFIER)
+# if defined (PRIu32)
+# define ACE_UINT32_FORMAT_SPECIFIER ACE_TEXT ("%") ACE_TEXT (PRIu32)
+# elif ACE_SIZEOF_INT == 4
+# define ACE_UINT32_FORMAT_SPECIFIER ACE_TEXT ("%u")
+# else
+# define ACE_UINT32_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+# endif /* defined (PRIu32) */
+#endif /* ACE_UINT32_FORMAT_SPECIFIER */
+
+#if !defined (ACE_INT64_FORMAT_SPECIFIER)
+# if defined (PRId64)
+# define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%") ACE_TEXT (PRId64)
+# elif ACE_SIZEOF_LONG == 8
+# define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%ld")
+# else
+# define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%lld")
+# endif /* defined (PRId64) */
+#endif /* ACE_INT64_FORMAT_SPECIFIER */
+
+#if !defined (ACE_UINT64_FORMAT_SPECIFIER)
+# if defined (PRIu64)
+# define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%") ACE_TEXT (PRIu64)
+# elif ACE_SIZEOF_LONG == 8
+# define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+# else
+# define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%llu")
+# endif /* defined (PRIu64) */
+#endif /* ACE_UINT64_FORMAT_SPECIFIER */
+
+#if !defined (ACE_SSIZE_T_FORMAT_SPECIFIER)
+# if defined (ACE_WIN64)
+# define ACE_SSIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%I64d")
+# else
+# define ACE_SSIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%d")
+# endif /* ACE_WIN64 */
+#endif /* ACE_SSIZE_T_FORMAT_SPECIFIER */
+
+#if !defined (ACE_SIZE_T_FORMAT_SPECIFIER)
+# if defined (ACE_WIN64)
+# define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%I64u")
+# else
+# define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%u")
+# endif /* ACE_WIN64 */
+#endif /* ACE_SIZE_T_FORMAT_SPECIFIER */
+
+// Cast from UINT64 to a double requires an intermediate cast to INT64
+// on some platforms.
+# if defined (ACE_LACKS_LONGLONG_T)
+ // Only use the low 32 bits.
+# define ACE_UINT64_DBLCAST_ADAPTER(n) ACE_U64_TO_U32 (n)
+# elif defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+# define ACE_UINT64_DBLCAST_ADAPTER(n) ((n).to_int64 ())
+# elif defined (ACE_WIN32)
+# define ACE_UINT64_DBLCAST_ADAPTER(n) static_cast<__int64> (n)
+# else /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */
+# define ACE_UINT64_DBLCAST_ADAPTER(n) (n)
+# endif /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */
+
+
+// The number of bytes in a float.
+# ifndef ACE_SIZEOF_FLOAT
+# if FLT_MAX_EXP == 128
+# define ACE_SIZEOF_FLOAT 4
+# elif FLT_MAX_EXP == 1024
+# define ACE_SIZEOF_FLOAT 8
+# else
+# error: unsupported float size, must be updated for this platform!
+# endif /* FLT_MAX_EXP */
+# endif /* ACE_SIZEOF_FLOAT */
+
+// The number of bytes in a double.
+# ifndef ACE_SIZEOF_DOUBLE
+# if DBL_MAX_EXP == 128
+# define ACE_SIZEOF_DOUBLE 4
+# elif DBL_MAX_EXP == 1024
+# define ACE_SIZEOF_DOUBLE 8
+# else
+# error: unsupported double size, must be updated for this platform!
+# endif /* DBL_MAX_EXP */
+# endif /* ACE_SIZEOF_DOUBLE */
+
+// The number of bytes in a long double.
+# ifndef ACE_SIZEOF_LONG_DOUBLE
+# if LDBL_MAX_EXP == 128
+# define ACE_SIZEOF_LONG_DOUBLE 4
+# elif LDBL_MAX_EXP == 1024
+# define ACE_SIZEOF_LONG_DOUBLE 8
+# elif LDBL_MAX_EXP == 16384
+# if defined (LDBL_DIG) && LDBL_DIG == 18
+# if defined (__ia64) || defined (__x86_64)
+# define ACE_SIZEOF_LONG_DOUBLE 16
+# else /* ! __ia64 */
+# define ACE_SIZEOF_LONG_DOUBLE 12
+# endif /* __ia64 */
+# else /* ! LDBL_DIG || LDBL_DIG != 18 */
+# define ACE_SIZEOF_LONG_DOUBLE 16
+# endif /* ! LDBL_DIG || LDBL_DIG != 18 */
+# else
+# error: unsupported double size, must be updated for this platform!
+# endif /* LDBL_MAX_EXP */
+# endif /* ACE_SIZEOF_LONG_DOUBLE */
+
+// Max and min sizes for the ACE integer types.
+#define ACE_CHAR_MAX 0x7F
+#define ACE_CHAR_MIN -(ACE_CHAR_MAX)-1
+#define ACE_OCTET_MAX 0xFF
+#define ACE_INT16_MAX 0x7FFF
+#define ACE_INT16_MIN -(ACE_INT16_MAX)-1
+#define ACE_UINT16_MAX 0xFFFF
+#define ACE_WCHAR_MAX ACE_UINT16_MAX
+#define ACE_INT32_MAX 0x7FFFFFFF
+#define ACE_INT32_MIN -(ACE_INT32_MAX)-1
+#define ACE_UINT32_MAX 0xFFFFFFFF
+#define ACE_INT64_MAX ACE_INT64_LITERAL(0x7FFFFFFFFFFFFFFF)
+#define ACE_INT64_MIN -(ACE_INT64_MAX)-1
+
+#if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+// ACE_U_LongLong's constructor accepts a "long long" in this
+// case. Set it to ACE_U_LongLong (-1) since the bit pattern for long
+// long (-1) is the same as the maximum unsigned long long value.
+# define ACE_UINT64_MAX ACE_U_LongLong (ACE_INT64_LITERAL (0xFFFFFFFFFFFFFFFF))
+#elif defined (ACE_LACKS_LONGLONG_T)
+// ACE_U_LongLong's constructor accepts an ACE_UINT32 low and high
+// pair of parameters.
+# define ACE_UINT64_MAX ACE_U_LongLong (0xFFFFFFFFu, 0xFFFFFFFFu)
+#else
+# define ACE_UINT64_MAX ACE_UINT64_LITERAL (0xFFFFFFFFFFFFFFFF)
+#endif /* ACE_LACKS_UNSIGNEDLONGLONG_T */
+
+// These use ANSI/IEEE format.
+#define ACE_FLT_MAX 3.402823466e+38F
+#define ACE_FLT_MIN 1.175494351e-38F
+#define ACE_DBL_MAX 1.7976931348623158e+308
+#define ACE_DBL_MIN 2.2250738585072014e-308
+
+# if defined (__ACE_INLINE__)
+# include "ace/Basic_Types.inl"
+# endif /* __ACE_INLINE__ */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_BASIC_TYPES_H */
diff --git a/ACE/ace/Basic_Types.inl b/ACE/ace/Basic_Types.inl
new file mode 100644
index 00000000000..15f9a9a1ab6
--- /dev/null
+++ b/ACE/ace/Basic_Types.inl
@@ -0,0 +1,954 @@
+// -*- C++ -*-
+//
+// $Id$
+
+# if !defined (ACE_LACKS_LONGLONG_T) && defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Implementation for ACE_U_LongLong when we have signed long long
+// but no unsigned long long.
+
+ACE_INLINE
+ACE_U_LongLong::ACE_U_LongLong (const long long value)
+ : data_ (value)
+{
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::hi (void) const
+{
+ return (data_ >> 32) & 0xFFFFFFFF;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::lo (void) const
+{
+ return data_ & 0xFFFFFFFF;
+}
+
+ACE_INLINE void
+ACE_U_LongLong::hi (const ACE_UINT32 hi)
+{
+ data_ = hi;
+ data_ <<= 32;
+}
+
+ACE_INLINE void
+ACE_U_LongLong::lo (const ACE_UINT32 lo)
+{
+ data_ = lo;
+}
+
+ACE_INLINE long long
+ACE_U_LongLong::to_int64 (void) const
+{
+ return data_;
+}
+
+ACE_INLINE
+ACE_U_LongLong::~ACE_U_LongLong (void)
+{
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator== (const ACE_U_LongLong &n) const
+{
+ return data_ == n.data_;
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator== (const ACE_UINT32 n) const
+{
+ return data_ == n;
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator!= (const ACE_U_LongLong &n) const
+{
+ return ! (*this == n);
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator!= (const ACE_UINT32 n) const
+{
+ return ! (*this == n);
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator< (const ACE_U_LongLong &n) const
+{
+ if (data_ > 0)
+ if (n.data_ > 0)
+ return data_ < n.data_;
+ else
+ return true;
+ else
+ if (n.data_ > 0)
+ return false;
+ else
+ return data_ < n.data_;
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator< (const ACE_UINT32 n) const
+{
+ return operator< (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator<= (const ACE_U_LongLong &n) const
+{
+ if (data_ == n.data_) return true;
+
+ return data_ < n.data_;
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator<= (const ACE_UINT32 n) const
+{
+ return operator<= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator> (const ACE_U_LongLong &n) const
+{
+ if (data_ > 0)
+ if (n.data_ > 0)
+ return data_ > n.data_;
+ else
+ return false;
+ else
+ if (n.data_ > 0)
+ return true;
+ else
+ return data_ > n.data_;
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator> (const ACE_UINT32 n) const
+{
+ return operator> (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator>= (const ACE_U_LongLong &n) const
+{
+ if (data_ == n.data_) return true;
+
+ return data_ > n.data_;
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator>= (const ACE_UINT32 n) const
+{
+ return operator>= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE
+ACE_U_LongLong::ACE_U_LongLong (const ACE_U_LongLong &n)
+ : data_ (n.data_)
+{
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator= (const ACE_U_LongLong &n)
+{
+ data_ = n.data_;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator= (const ACE_INT32 &rhs)
+{
+ if (rhs >= 0)
+ {
+ data_ = rhs;
+ data_ &= 0xFFFFFFFF;
+ }
+ else
+ {
+ // We do not handle the case where a negative 32 bit integer is
+ // assigned to this representation of a 64 bit unsigned integer.
+ // The "undefined behavior" behavior performed by this
+ // implementation is to simply set all bits to zero.
+ data_ = 0;
+ }
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator= (const ACE_UINT32 &rhs)
+{
+ data_ = rhs;
+
+ return *this;
+}
+
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator+ (const ACE_U_LongLong &n) const
+{
+ return data_ + n.data_;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator+ (const ACE_UINT32 n) const
+{
+ return operator+ (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator- (const ACE_U_LongLong &n) const
+{
+ return data_ - n.data_;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator- (const ACE_UINT32 n) const
+{
+ return operator- (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator<< (const u_int n) const
+{
+ return data_ << n;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator<<= (const u_int n)
+{
+ data_ <<= n;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator>> (const u_int n) const
+{
+ return data_ >> n;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator>>= (const u_int n)
+{
+ data_ >>= n;
+
+ return *this;
+}
+
+ACE_INLINE double
+ACE_U_LongLong::operator/ (const double n) const
+{
+ return data_ / n;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator+= (const ACE_U_LongLong &n)
+{
+ data_ += n.data_;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator+= (const ACE_UINT32 n)
+{
+ return operator+= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator* (const ACE_UINT32 n) const
+{
+ return data_ * n;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator*= (const ACE_UINT32 n)
+{
+ data_ *= n;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator-= (const ACE_U_LongLong &n)
+{
+ data_ -= n.data_;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator-= (const ACE_UINT32 n)
+{
+ return operator-= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator++ ()
+{
+ ++data_;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator-- ()
+{
+ --data_;
+
+ return *this;
+}
+
+ACE_INLINE const ACE_U_LongLong
+ACE_U_LongLong::operator++ (int)
+{
+ // Post-increment operator should always be implemented in terms of
+ // the pre-increment operator to enforce consistent semantics.
+ ACE_U_LongLong temp (*this);
+ ++*this;
+ return temp;
+}
+
+ACE_INLINE const ACE_U_LongLong
+ACE_U_LongLong::operator-- (int)
+{
+ // Post-decrement operator should always be implemented in terms of
+ // the pre-decrement operator to enforce consistent semantics.
+ ACE_U_LongLong temp (*this);
+ --*this;
+ return temp;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator|= (const ACE_U_LongLong n)
+{
+ data_ |= n.data_;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator|= (const ACE_UINT32 n)
+{
+ return operator|= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator&= (const ACE_U_LongLong n)
+{
+ data_ &= n.data_;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator&= (const ACE_UINT32 n)
+{
+ return operator&= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const ACE_UINT32 n) const
+{
+ return data_ / n;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator% (const ACE_UINT32 n) const
+{
+ return data_ % n;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator| (const ACE_INT32 n) const
+{
+ return data_ | n;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator& (const ACE_INT32 n) const
+{
+ return data_ & n;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator* (const ACE_INT32 n) const
+{
+ return operator* ((ACE_UINT32) n);
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator*= (const ACE_INT32 n)
+{
+ return operator*= ((ACE_UINT32) n);
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const ACE_INT32 n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+
+#if ACE_SIZEOF_INT == 4
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const u_long n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const long n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+
+#else /* ACE_SIZEOF_INT != 4 */
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const u_int n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const int n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+#endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#elif defined (ACE_LACKS_LONGLONG_T)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_U_LongLong::ACE_U_LongLong (const ACE_UINT32 lo, const ACE_UINT32 hi)
+{
+ h_ () = hi;
+ l_ () = lo;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::hi (void) const
+{
+ return h_ ();
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::lo (void) const
+{
+ return l_ ();
+}
+
+ACE_INLINE void
+ACE_U_LongLong::hi (const ACE_UINT32 hi)
+{
+ h_ () = hi;
+}
+
+ACE_INLINE void
+ACE_U_LongLong::lo (const ACE_UINT32 lo)
+{
+ l_ () = lo;
+}
+
+ACE_INLINE
+ACE_U_LongLong::~ACE_U_LongLong (void)
+{
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator== (const ACE_U_LongLong &n) const
+{
+ return h_ () == n.h_ () && l_ () == n.l_ ();
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator== (const ACE_UINT32 n) const
+{
+ return h_ () == 0 && l_ () == n;
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator!= (const ACE_U_LongLong &n) const
+{
+ return ! (*this == n);
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator!= (const ACE_UINT32 n) const
+{
+ return ! (*this == n);
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator< (const ACE_U_LongLong &n) const
+{
+ return h_ () < n.h_ () ? 1
+ : h_ () > n.h_ () ? 0
+ : l_ () < n.l_ ();
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator< (const ACE_UINT32 n) const
+{
+ return operator< (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator<= (const ACE_U_LongLong &n) const
+{
+ return h_ () < n.h_ () ? 1
+ : h_ () > n.h_ () ? 0
+ : l_ () <= n.l_ ();
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator<= (const ACE_UINT32 n) const
+{
+ return operator<= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator> (const ACE_U_LongLong &n) const
+{
+ return h_ () > n.h_ () ? 1
+ : h_ () < n.h_ () ? 0
+ : l_ () > n.l_ ();
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator> (const ACE_UINT32 n) const
+{
+ return operator> (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator>= (const ACE_U_LongLong &n) const
+{
+ return h_ () > n.h_ () ? 1
+ : h_ () < n.h_ () ? 0
+ : l_ () >= n.l_ ();
+}
+
+ACE_INLINE bool
+ACE_U_LongLong::operator>= (const ACE_UINT32 n) const
+{
+ return operator>= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE
+ACE_U_LongLong::ACE_U_LongLong (const ACE_U_LongLong &n)
+{
+ h_ () = n.h_ ();
+ l_ () = n.l_ ();
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator= (const ACE_U_LongLong &n)
+{
+ h_ () = n.h_ ();
+ l_ () = n.l_ ();
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator= (const ACE_INT32 &rhs)
+{
+ if (rhs >= 0)
+ {
+ l_ () = static_cast<ACE_UINT32> (rhs);
+ h_ () = 0;
+ }
+ else
+ {
+ // We do not handle the case where a negative 32 bit integer is
+ // assigned to this representation of a 64 bit unsigned integer.
+ // The "undefined behavior" behavior performed by this
+ // implementation is to simply set all bits to zero.
+ l_ () = 0;
+ h_ () = 0;
+ }
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator= (const ACE_UINT32 &rhs)
+{
+ l_ () = rhs;
+ h_ () = 0;
+
+ return *this;
+}
+
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator+ (const ACE_U_LongLong &n) const
+{
+ ACE_U_LongLong ret (l_ () + n.l_ (), h_ () + n.h_ ());
+ if (ret.l_ () < n.l_ ()) /* carry */ ++ret.h_ ();
+
+ return ret;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator+ (const ACE_UINT32 n) const
+{
+ return operator+ (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator- (const ACE_U_LongLong &n) const
+{
+ ACE_U_LongLong ret (l_ () - n.l_ (), h_ () - n.h_ ());
+ if (l_ () < n.l_ ()) /* borrow */ --ret.h_ ();
+
+ return ret;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator- (const ACE_UINT32 n) const
+{
+ return operator- (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator<< (const u_int n) const
+{
+ const ACE_UINT32 carry_mask = l_ () >> (32 - n);
+ ACE_U_LongLong ret (n < 32 ? l_ () << n : 0,
+ n < 32 ? (h_ () << n) | carry_mask : carry_mask);
+
+ return ret;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator<<= (const u_int n)
+{
+ const ACE_UINT32 carry_mask = l_ () >> (32 - n);
+ h_ () = n < 32 ? (h_ () << n) | carry_mask : carry_mask;
+
+ // g++ 2.7.2.3/Solaris 2.5.1 doesn't modify l_ () if shifted by 32.
+ l_ () = n < 32 ? l_ () << n : 0;
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator>> (const u_int n) const
+{
+ const ACE_UINT32 carry_mask = h_ () << (32 - n);
+ ACE_U_LongLong ret (n < 32 ? (l_ () >> n) | carry_mask : 0,
+ n < 32 ? h_ () >> n : 0);
+
+ return ret;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator>>= (const u_int n)
+{
+ const ACE_UINT32 carry_mask = h_ () << (32 - n);
+ l_ () = n < 32 ? (l_ () >> n) | carry_mask : carry_mask;
+ h_ () = n < 32 ? h_ () >> n : 0;
+
+ return *this;
+}
+
+ACE_INLINE double
+ACE_U_LongLong::operator/ (const double n) const
+{
+ // See the derivation above in operator/ (const ACE_UINT32).
+
+ return ((double) 0xffffffffu - n + 1.0) / n * h_ () +
+ (double) h_ () + (double) l_ () / n;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator+= (const ACE_U_LongLong &n)
+{
+ h_ () += n.h_ ();
+ l_ () += n.l_ ();
+ if (l_ () < n.l_ ()) /* carry */ ++h_ ();
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator+= (const ACE_UINT32 n)
+{
+ return operator+= (static_cast<const ACE_U_LongLong> (n));
+}
+
+#define ACE_HIGHBIT (~(~0UL >> 1))
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::ul_shift (ACE_UINT32 a, ACE_UINT32 c_in, ACE_UINT32 *c_out) const
+{
+ const ACE_UINT32 b = (a << 1) | c_in;
+ *c_out = (*c_out << 1) + ((a & ACE_HIGHBIT) > 0);
+
+ return b;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::ull_shift (ACE_U_LongLong a,
+ ACE_UINT32 c_in,
+ ACE_UINT32 *c_out) const
+{
+ ACE_U_LongLong b;
+
+ b.l_ () = (a.l_ () << 1) | c_in;
+ c_in = ((a.l_ () & ACE_HIGHBIT) > 0);
+ b.h_ () = (a.h_ () << 1) | c_in;
+ *c_out = (*c_out << 1) + ((a.h_ () & ACE_HIGHBIT) > 0);
+
+ return b;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::ull_add (ACE_U_LongLong a, ACE_U_LongLong b, ACE_UINT32 *carry) const
+{
+ ACE_U_LongLong r (0, 0);
+ ACE_UINT32 c1, c2, c3, c4;
+
+ c1 = a.l_ () % 2;
+ c2 = b.l_ () % 2;
+ c3 = 0;
+
+ r.l_ () = a.l_ ()/2 + b.l_ ()/2 + (c1+c2)/2;
+ r.l_ () = ul_shift (r.l_ (), (c1+c2)%2, &c3);
+
+ c1 = a.h_ () % 2;
+ c2 = b.h_ () % 2;
+ c4 = 0;
+
+ r.h_ () = a.h_ ()/2 + b.h_ ()/2 + (c1+c2+c3)/2;
+ r.h_ () = ul_shift (r.h_ (), (c1+c2+c3)%2, &c4);
+
+ *carry = c4;
+
+ return r;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::ull_mult (ACE_U_LongLong a, ACE_UINT32 b, ACE_UINT32 *carry) const
+{
+ register ACE_UINT32 mask = ACE_HIGHBIT;
+ const ACE_U_LongLong zero (0, 0);
+ ACE_U_LongLong accum (0, 0);
+ ACE_UINT32 c;
+
+ *carry = 0;
+ if (b > 0)
+ do
+ {
+ accum = ull_shift (accum, 0U, carry);
+ if (b & mask)
+ accum = ull_add (accum, a, &c);
+ else
+ accum = ull_add (accum, zero, &c);
+ *carry += c;
+ mask >>= 1;
+ }
+ while (mask > 0);
+
+ return accum;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator* (const ACE_UINT32 n) const
+{
+ ACE_UINT32 carry; // will throw the carry away
+
+ return ull_mult (*this, n, &carry);
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator*= (const ACE_UINT32 n)
+{
+ ACE_UINT32 carry; // will throw the carry away
+
+ return *this = ull_mult (*this, n, &carry);
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator-= (const ACE_U_LongLong &n)
+{
+ h_ () -= n.h_ ();
+ if (l_ () < n.l_ ()) /* borrow */ --h_ ();
+ l_ () -= n.l_ ();
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator-= (const ACE_UINT32 n)
+{
+ return operator-= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator++ ()
+{
+ ++l_ ();
+ if (l_ () == 0) /* carry */ ++h_ ();
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator-- ()
+{
+ if (l_ () == 0) /* borrow */ --h_ ();
+ --l_ ();
+
+ return *this;
+}
+
+ACE_INLINE const ACE_U_LongLong
+ACE_U_LongLong::operator++ (int)
+{
+ // Post-increment operator should always be implemented in terms of
+ // the pre-increment operator to enforce consistent semantics.
+ ACE_U_LongLong temp (*this);
+ ++*this;
+ return temp;
+}
+
+ACE_INLINE const ACE_U_LongLong
+ACE_U_LongLong::operator-- (int)
+{
+ // Post-decrement operator should always be implemented in terms of
+ // the pre-decrement operator to enforce consistent semantics.
+ ACE_U_LongLong temp (*this);
+ --*this;
+ return temp;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator|= (const ACE_U_LongLong n)
+{
+ l_ () |= n.l_ ();
+ h_ () |= n.h_ ();
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator|= (const ACE_UINT32 n)
+{
+ return operator|= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator&= (const ACE_U_LongLong n)
+{
+ l_ () &= n.l_ ();
+ h_ () &= n.h_ ();
+
+ return *this;
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator&= (const ACE_UINT32 n)
+{
+ return operator&= (static_cast<const ACE_U_LongLong> (n));
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const ACE_UINT32 n) const
+{
+ // This takes advantage of the fact that the return type has only 32
+ // bits. Replace 0x100000000 with 0xffffffff + 1 because the former
+ // has 33 bits.
+ // Quotient = (0x100000000u * hi_ + lo_) / n
+ // = ((0x100000000u - n + n) * hi_ + lo_) / n
+ // = ((0x100000000u - n) / n * hi_ + hi_ * n / n + lo_ / n
+ // = (0x100000000u - n) / n * hi_ + hi_ + lo_ / n
+ // = (0xffffffffu - n + 1) / n * hi_ + hi_ + lo_ / n
+
+ return (0xffffffffu - n + 1) / n * h_ () + h_ () + l_ () / n;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator% (const ACE_UINT32 n) const
+{
+ // Because the argument is an ACE_UINT32, the result can never be
+ // bigger than 32 bits. Replace 0x100000000 with 0xffffffff + 1
+ // because the former has 33 bits.
+ // Mod = (0x100000000u * hi_ + lo_) % n
+ // = (0x100000000u % n * hi_ + lo_ % n) % n
+ // = ((0x100000000u - n) % n * hi_ + lo_ % n) % n
+ // = ((0xffffffffu - n + 1) % n * hi_ + lo_ % n) % n
+
+ return ((0xffffffff - n + 1) % n * h_ () + l_ () % n) % n;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator| (const ACE_INT32 n) const
+{
+ return l_ () | n;
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator& (const ACE_INT32 n) const
+{
+ return l_ () & n;
+}
+
+ACE_INLINE ACE_U_LongLong
+ACE_U_LongLong::operator* (const ACE_INT32 n) const
+{
+ return operator* ((ACE_UINT32) n);
+}
+
+ACE_INLINE ACE_U_LongLong &
+ACE_U_LongLong::operator*= (const ACE_INT32 n)
+{
+ return operator*= ((ACE_UINT32) n);
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const ACE_INT32 n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+
+#if ACE_SIZEOF_INT == 4
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const u_long n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const long n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+
+#else /* ACE_SIZEOF_INT != 4 */
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const u_int n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+
+ACE_INLINE ACE_UINT32
+ACE_U_LongLong::operator/ (const int n) const
+{
+ return operator/ ((ACE_UINT32) n);
+}
+#endif /* ACE_SIZEOF_INT != 4 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_LONGLONG_T || ACE_LACKS_UNSIGNEDLONGLONG_T */
diff --git a/ACE/ace/Bound_Ptr.h b/ACE/ace/Bound_Ptr.h
new file mode 100644
index 00000000000..a310e3b8a56
--- /dev/null
+++ b/ACE/ace/Bound_Ptr.h
@@ -0,0 +1,388 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Bound_Ptr.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ * @author Boris Kolpackov <boris@codesynthesis.com>
+ */
+//=============================================================================
+
+#ifndef ACE_BOUND_PTR_H
+#define ACE_BOUND_PTR_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/Auto_Ptr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 (long 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 long 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 long 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 bool 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 (long init_obj_ref_count);
+
+private:
+
+ /// 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.
+ long obj_ref_count_;
+
+ /// Reference count of this counter.
+ long 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.
+ 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.
+ explicit ACE_Strong_Bound_Ptr (auto_ptr<X> p);
+
+ /// Copy constructor binds @c this and @a r to the same object.
+ ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Constructor binds @c this and @a r to the same object.
+ ACE_Strong_Bound_Ptr (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Copy constructor binds @c this and @a r to the same object if
+ /// Y* can be implicitly converted to X*.
+ template <class Y>
+ ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr<Y, ACE_LOCK> &r)
+ : counter_ (r.counter_),
+ ptr_ (dynamic_cast<X_t*>(r.ptr_))
+ {
+ // This ctor is temporarily defined here to increase our chances
+ // of being accepted by broken compilers.
+ //
+ COUNTER::attach_strong (this->counter_);
+ }
+
+ /// Destructor.
+ ~ACE_Strong_Bound_Ptr (void);
+
+ /// Assignment operator that binds @c this and @a r to the same object.
+ void operator = (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Assignment operator that binds @c this and @a r to the same object.
+ void operator = (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Assignment operator that binds @c this and @a r to the same object
+ /// if Y* can be implicitly converted to X*.
+ template <class Y>
+ ACE_Weak_Bound_Ptr<X, ACE_LOCK>&
+ operator= (const ACE_Strong_Bound_Ptr<Y, ACE_LOCK> &r)
+ {
+ // This operator is temporarily defined here to increase our chances
+ // of being accepted by broken compilers.
+ //
+
+ // This will work if &r == this, by first increasing the ref count
+
+ COUNTER *new_counter = r.counter_;
+ X* new_ptr = dynamic_cast<X_t*> (r.ptr_);
+ COUNTER::attach_strong (new_counter);
+ if (COUNTER::detach_strong (this->counter_) == 0)
+ delete this->ptr_;
+ this->counter_ = new_counter;
+ this->ptr_ = new_ptr;
+
+ return *this;
+ }
+
+ /// Equality operator that returns @c true if both
+ /// ACE_Strong_Bound_Ptr instances point to the same underlying
+ /// object.
+ /**
+ * @note It also returns @c true if both objects have just been
+ * instantiated and not used yet.
+ */
+ bool operator == (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Equality operator that returns true if the ACE_Strong_Bound_Ptr
+ /// and ACE_Weak_Bound_Ptr objects point to the same underlying
+ /// object.
+ /**
+ * @note It also returns @c true if both objects have just been
+ * instantiated and not used yet.
+ */
+ bool operator == (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Equality operator that returns @c true if the
+ /// ACE_Strong_Bound_Ptr and the raw pointer point to the same
+ /// underlying object.
+ bool operator == (X *p) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ bool operator != (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ bool operator != (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ bool operator != (X *p) const;
+
+ /// Redirection operator
+ X *operator-> (void) const;
+
+ /// Dereference operator
+ X &operator * (void) const;
+
+ /// Get the pointer value.
+ X *get (void) const;
+
+ /// 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:
+ typedef X X_t; // This indirection is for Borland C++.
+
+ friend class ACE_Weak_Bound_Ptr<X, ACE_LOCK>;
+
+ template <class Y, class L>
+ friend class ACE_Strong_Bound_Ptr;
+
+ /// 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.
+ explicit ACE_Weak_Bound_Ptr (X *p = 0);
+
+ /// Copy constructor binds @c this and @a r to the same object.
+ ACE_Weak_Bound_Ptr (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Constructor binds @c this and @a 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 @c this and @a r to the same object.
+ void operator = (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Assignment operator that binds @c this and @a r to the same object.
+ void operator = (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Equality operator that returns @c true if both
+ /// ACE_Weak_Bound_Ptr objects point to the same underlying object.
+ /**
+ * @note It also returns @c true if both objects have just been
+ * instantiated and not used yet.
+ */
+ bool operator == (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Equality operator that returns @c true if the ACE_Weak_Bound_Ptr
+ /// and ACE_Strong_Bound_Ptr objects point to the same underlying
+ /// object.
+ /**
+ * @note It also returns @c true if both objects have just been
+ * instantiated and not used yet.
+ */
+ bool operator == (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Equality operator that returns @c true if the ACE_Weak_Bound_Ptr
+ /// and the raw pointer point to the same underlying object.
+ bool operator == (X *p) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ bool operator != (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ bool operator != (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ bool 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.
+ */
+ long 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.
+ */
+ long 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:
+ typedef X X_t; // This indirection is for Borland C++.
+
+ 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include "ace/Bound_Ptr.inl"
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_BOUND_PTR_H */
diff --git a/ACE/ace/Bound_Ptr.inl b/ACE/ace/Bound_Ptr.inl
new file mode 100644
index 00000000000..52c100e16b0
--- /dev/null
+++ b/ACE/ace/Bound_Ptr.inl
@@ -0,0 +1,494 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Bound_Ptr.i
+
+#include "ace/Guard_T.h"
+#if !defined (ACE_NEW_THROWS_EXCEPTIONS)
+# include "ace/Log_Msg.h"
+#endif /* ACE_NEW_THROWS_EXCEPTIONS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_LOCK> inline ACE_Bound_Ptr_Counter<ACE_LOCK> *
+ACE_Bound_Ptr_Counter<ACE_LOCK>::internal_create (long 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 long
+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;
+
+ long new_obj_ref_count = ++counter->obj_ref_count_;
+ ++counter->self_ref_count_;
+
+ return new_obj_ref_count;
+}
+
+template <class ACE_LOCK> inline long
+ACE_Bound_Ptr_Counter<ACE_LOCK>::detach_strong (ACE_Bound_Ptr_Counter<ACE_LOCK>* counter)
+{
+ ACE_Bound_Ptr_Counter<ACE_LOCK> *counter_del = 0;
+ long 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 bool
+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 (long 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, but
+ // why go through all that?
+ if (&rhs == this)
+ return;
+
+ COUNTER *new_counter = rhs.counter_;
+ X_t *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, but
+ // why go through all that?
+ if (&rhs == this)
+ return;
+
+ COUNTER *new_counter = rhs.counter_;
+ X_t *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 bool
+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 bool
+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 bool
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator== (X *p) const
+{
+ return this->ptr_ == p;
+}
+
+template <class X, class ACE_LOCK> inline bool
+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 bool
+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 bool
+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) const
+{
+ 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_t *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_t *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 bool
+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 bool
+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 bool
+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 bool
+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 bool
+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 bool
+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 long
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::add_ref ()
+{
+ return COUNTER::attach_strong (counter_);
+}
+
+template<class X, class ACE_LOCK> inline long
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::remove_ref ()
+{
+ long 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/CDR_Base.cpp b/ACE/ace/CDR_Base.cpp
new file mode 100644
index 00000000000..eb6f0bb0514
--- /dev/null
+++ b/ACE/ace/CDR_Base.cpp
@@ -0,0 +1,799 @@
+#include "ace/CDR_Base.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/CDR_Base.inl"
+#endif /* ! __ACE_INLINE__ */
+
+#include "ace/Message_Block.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ CDR_Base,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (NONNATIVE_LONGDOUBLE)
+static const ACE_INT16 max_eleven_bit = 0x3ff;
+static const ACE_INT16 max_fifteen_bit = 0x3fff;
+#endif /* NONNATIVE_LONGDOUBLE */
+
+//
+// See comments in CDR_Base.inl about optimization cases for swap_XX_array.
+//
+
+void
+ACE_CDR::swap_2_array (char const * orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ // We pretend that AMD64/GNU G++ systems have a Pentium CPU to
+ // take advantage of the inline assembly implementation.
+
+ // 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 && \
+ !((defined(__amd64__) || defined (__x86_64__)) && defined(__GNUG__))
+ char const * 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
+ char const * 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.
+ char const * const end = orig + 2 * (n & (~3));
+
+ // See if we're aligned for writting in 64 or 32 bit chunks...
+#if ACE_SIZEOF_LONG == 8 && \
+ !((defined(__amd64__) || defined (__x86_64__)) && defined(__GNUG__))
+ 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_INTEL_ASSEMBLY)
+ unsigned int a =
+ * reinterpret_cast<const unsigned int*> (orig);
+ unsigned int b =
+ * 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) );
+ * reinterpret_cast<unsigned int*> (target) = a;
+ * 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 =
+ * reinterpret_cast<const unsigned long*> (orig);
+
+ register unsigned long a1 = (a & 0x00ff00ff00ff00ffUL) << 8;
+ register unsigned long a2 = (a & 0xff00ff00ff00ff00UL) >> 8;
+
+ a = (a1 | a2);
+
+ * reinterpret_cast<unsigned long*> (target) = a;
+#else
+ register ACE_UINT32 a =
+ * reinterpret_cast<const ACE_UINT32*> (orig);
+ register ACE_UINT32 b =
+ * 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);
+
+ * reinterpret_cast<ACE_UINT32*> (target) = a;
+ * 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_INTEL_ASSEMBLY)
+ unsigned int a =
+ * reinterpret_cast<const unsigned int*> (orig);
+ unsigned int b =
+ * 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.
+ * reinterpret_cast<unsigned short*> (target + 2)
+ = (unsigned short) (a & 0xffff);
+ * 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) );
+ * reinterpret_cast<unsigned short*> (target + 0)
+ = (unsigned short) (a & 0xffff);
+ * 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 =
+ * 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 = static_cast<ACE_UINT16> (a >> 48);
+ ACE_UINT16 b2 = static_cast<ACE_UINT16> ((a >> 32) & 0xffff);
+ ACE_UINT16 b3 = static_cast<ACE_UINT16> ((a >> 16) & 0xffff);
+ ACE_UINT16 b4 = static_cast<ACE_UINT16> (a & 0xffff);
+
+#if defined(ACE_LITTLE_ENDIAN)
+ * reinterpret_cast<ACE_UINT16*> (target) = b4;
+ * reinterpret_cast<ACE_UINT16*> (target + 2) = b3;
+ * reinterpret_cast<ACE_UINT16*> (target + 4) = b2;
+ * reinterpret_cast<ACE_UINT16*> (target + 6) = b1;
+#else
+ * reinterpret_cast<ACE_UINT16*> (target) = b1;
+ * reinterpret_cast<ACE_UINT16*> (target + 2) = b2;
+ * reinterpret_cast<ACE_UINT16*> (target + 4) = b3;
+ * reinterpret_cast<ACE_UINT16*> (target + 6) = b4;
+#endif
+#else
+ register ACE_UINT32 a =
+ * reinterpret_cast<const ACE_UINT32*> (orig);
+ register ACE_UINT32 b =
+ * 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 = static_cast<ACE_UINT16> (a >> 16);
+ ACE_UINT32 c2 = static_cast<ACE_UINT16> (a & 0xffff);
+ ACE_UINT32 c3 = static_cast<ACE_UINT16> (b >> 16);
+ ACE_UINT32 c4 = static_cast<ACE_UINT16> (b & 0xffff);
+
+#if defined(ACE_LITTLE_ENDIAN)
+ * reinterpret_cast<ACE_UINT16*> (target) = c2;
+ * reinterpret_cast<ACE_UINT16*> (target + 2) = c1;
+ * reinterpret_cast<ACE_UINT16*> (target + 4) = c4;
+ * reinterpret_cast<ACE_UINT16*> (target + 6) = c3;
+#else
+ * reinterpret_cast<ACE_UINT16*> (target) = c1;
+ * reinterpret_cast<ACE_UINT16*> (target + 2) = c2;
+ * reinterpret_cast<ACE_UINT16*> (target + 4) = c3;
+ * 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 (char const * orig, char* target, size_t n)
+{
+ // ACE_ASSERT (n > 0); The caller checks that n > 0
+
+#if ACE_SIZEOF_LONG == 8
+ // Later, we read from *orig in 64 bit chunks,
+ // so make sure we don't generate unaligned readings.
+ char const * const o8 = ACE_ptr_align_binary (orig, 8);
+ // The mismatch can only be by 4.
+ if (orig != o8)
+ {
+ ACE_CDR::swap_4 (orig, target);
+ orig += 4;
+ target += 4;
+ --n;
+ }
+#endif /* ACE_SIZEOF_LONG == 8 */
+
+ 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.
+ char const * const end = orig + 4 * (n & (~3));
+
+#if ACE_SIZEOF_LONG == 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 =
+ * reinterpret_cast<const long*> (orig);
+ register unsigned long b =
+ * reinterpret_cast<const long*> (orig + 8);
+
+#if defined(ACE_HAS_INTEL_ASSEMBLY)
+ asm ("bswapq %1" : "=r" (a) : "0" (a));
+ asm ("bswapq %1" : "=r" (b) : "0" (b));
+ asm ("rol $32, %1" : "=r" (a) : "0" (a));
+ asm ("rol $32, %1" : "=r" (b) : "0" (b));
+#else
+ 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);
+#endif
+
+ * reinterpret_cast<long*> (target) = a;
+ * 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 =
+ * reinterpret_cast<const long*> (orig);
+ register unsigned long b =
+ * reinterpret_cast<const long*> (orig + 8);
+
+#if defined(ACE_HAS_INTEL_ASSEMBLY)
+ asm ("bswapq %1" : "=r" (a) : "0" (a));
+ asm ("bswapq %1" : "=r" (b) : "0" (b));
+ asm ("rol $32, %1" : "=r" (a) : "0" (a));
+ asm ("rol $32, %1" : "=r" (b) : "0" (b));
+#else
+ 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);
+#endif
+
+ ACE_UINT32 c1 = static_cast<ACE_UINT32> (a >> 32);
+ ACE_UINT32 c2 = static_cast<ACE_UINT32> (a & 0xffffffff);
+ ACE_UINT32 c3 = static_cast<ACE_UINT32> (b >> 32);
+ ACE_UINT32 c4 = static_cast<ACE_UINT32> (b & 0xffffffff);
+
+#if defined (ACE_LITTLE_ENDIAN)
+ * reinterpret_cast<ACE_UINT32*> (target + 0) = c2;
+ * reinterpret_cast<ACE_UINT32*> (target + 4) = c1;
+ * reinterpret_cast<ACE_UINT32*> (target + 8) = c4;
+ * reinterpret_cast<ACE_UINT32*> (target + 12) = c3;
+#else
+ * reinterpret_cast<ACE_UINT32*> (target + 0) = c1;
+ * reinterpret_cast<ACE_UINT32*> (target + 4) = c2;
+ * reinterpret_cast<ACE_UINT32*> (target + 8) = c3;
+ * reinterpret_cast<ACE_UINT32*> (target + 12) = c4;
+#endif
+ orig += 16;
+ target += 16;
+ }
+ }
+
+#else /* ACE_SIZEOF_LONG != 8 */
+
+ while (orig < end)
+ {
+#if defined (ACE_HAS_PENTIUM) && defined (__GNUG__)
+ register unsigned int a =
+ *reinterpret_cast<const unsigned int*> (orig);
+ register unsigned int b =
+ *reinterpret_cast<const unsigned int*> (orig + 4);
+ register unsigned int c =
+ *reinterpret_cast<const unsigned int*> (orig + 8);
+ register unsigned int d =
+ *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));
+
+ *reinterpret_cast<unsigned int*> (target) = a;
+ *reinterpret_cast<unsigned int*> (target + 4) = b;
+ *reinterpret_cast<unsigned int*> (target + 8) = c;
+ *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 =
+ * reinterpret_cast<const ACE_UINT32*> (orig);
+ register ACE_UINT32 b =
+ * reinterpret_cast<const ACE_UINT32*> (orig + 4);
+ register ACE_UINT32 c =
+ * reinterpret_cast<const ACE_UINT32*> (orig + 8);
+ register ACE_UINT32 d =
+ * 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);
+
+ * reinterpret_cast<ACE_UINT32*> (target) = a;
+ * reinterpret_cast<ACE_UINT32*> (target + 4) = b;
+ * reinterpret_cast<ACE_UINT32*> (target + 8) = c;
+ * reinterpret_cast<ACE_UINT32*> (target + 12) = d;
+#endif
+
+ orig += 16;
+ target += 16;
+ }
+
+#endif /* ACE_SIZEOF_LONG == 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 (char const * orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ char const * const end = orig + 8*n;
+ while (orig < end)
+ {
+ swap_8 (orig, target);
+ orig += 8;
+ target += 8;
+ }
+}
+
+void
+ACE_CDR::swap_16_array (char const * orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ char const * const end = orig + 16*n;
+ while (orig < end)
+ {
+ swap_16 (orig, target);
+ orig += 16;
+ target += 16;
+ }
+}
+
+void
+ACE_CDR::mb_align (ACE_Message_Block *mb)
+{
+#if !defined (ACE_CDR_IGNORE_ALIGNMENT)
+ char * const start = ACE_ptr_align_binary (mb->base (),
+ ACE_CDR::MAX_ALIGNMENT);
+#else
+ char * const start = mb->base ();
+#endif /* ACE_CDR_IGNORE_ALIGNMENT */
+ mb->rd_ptr (start);
+ mb->wr_ptr (start);
+}
+
+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 (0, newsize);
+
+ if (db == 0)
+ return -1;
+
+ // Do the equivalent of ACE_CDR::mb_align() here to avoid having
+ // to allocate an ACE_Message_Block on the stack thereby avoiding
+ // the manipulation of the data blocks reference count
+ size_t mb_len = mb->length ();
+ char *start = ACE_ptr_align_binary (db->base (),
+ ACE_CDR::MAX_ALIGNMENT);
+
+ ACE_OS::memcpy (start, mb->rd_ptr (), mb_len);
+ mb->data_block (db);
+
+ // Setting the data block on the mb resets the read and write
+ // pointers back to the beginning. We must set the rd_ptr to the
+ // aligned start and adjust the write pointer to the end
+ mb->rd_ptr (start);
+ mb->wr_ptr (start + mb_len);
+
+ // 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);
+
+#if !defined (ACE_CDR_IGNORE_ALIGNMENT)
+ // We must copy the contents of <src> into the new buffer, but
+ // respecting the alignment.
+ ptrdiff_t srcalign =
+ ptrdiff_t(src->rd_ptr ()) % ACE_CDR::MAX_ALIGNMENT;
+ ptrdiff_t dstalign =
+ ptrdiff_t(dst->rd_ptr ()) % ACE_CDR::MAX_ALIGNMENT;
+ ptrdiff_t offset = srcalign - dstalign;
+ if (offset < 0)
+ offset += ACE_CDR::MAX_ALIGNMENT;
+ dst->rd_ptr (static_cast<size_t> (offset));
+ dst->wr_ptr (dst->rd_ptr ());
+#endif /* ACE_CDR_IGNORE_ALIGNMENT */
+
+ for (const ACE_Message_Block* i = src;
+ i != 0;
+ i = i->cont ())
+ {
+ // If the destination and source are the same, do not
+ // attempt to copy the data. Just update the write pointer.
+ if (dst->wr_ptr () != i->rd_ptr ())
+ dst->copy (i->rd_ptr (), i->length ());
+ else
+ dst->wr_ptr (i->length ());
+ }
+}
+
+#if defined (NONNATIVE_LONGLONG)
+bool
+ACE_CDR::LongLong::operator== (const ACE_CDR::LongLong &rhs) const
+{
+ return this->h == rhs.h && this->l == rhs.l;
+}
+
+bool
+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)
+ACE_CDR::LongDouble&
+ACE_CDR::LongDouble::assign (const ACE_CDR::LongDouble::NativeImpl& rhs)
+{
+ ACE_OS::memset (this->ld, 0, sizeof (this->ld));
+
+ if (sizeof (rhs) == 8)
+ {
+#if defined (ACE_LITTLE_ENDIAN)
+ static const size_t byte_zero = 1;
+ static const size_t byte_one = 0;
+ char rhs_ptr[16];
+ ACE_CDR::swap_8 (reinterpret_cast<const char*> (&rhs), rhs_ptr);
+#else
+ static const size_t byte_zero = 0;
+ static const size_t byte_one = 1;
+ const char* rhs_ptr = reinterpret_cast<const char*> (&rhs);
+#endif
+ ACE_INT16 sign = static_cast<ACE_INT16> (
+ static_cast<signed char> (rhs_ptr[0])) & 0x8000;
+ ACE_INT16 exponent = ((rhs_ptr[0] & 0x7f) << 4) |
+ ((rhs_ptr[1] >> 4) & 0xf);
+ const char* exp_ptr = reinterpret_cast<const char*> (&exponent);
+
+ // Infinity and NaN have an exponent of 0x7ff in 64-bit IEEE
+ if (exponent == 0x7ff)
+ {
+ exponent = 0x7fff;
+ }
+ else
+ {
+ exponent = (exponent - max_eleven_bit) + max_fifteen_bit;
+ }
+ exponent |= sign;
+
+ // Store the sign bit and exponent
+ this->ld[0] = exp_ptr[byte_zero];
+ this->ld[1] = exp_ptr[byte_one];
+
+ // Store the mantissa. In an 8 byte double, it is split by
+ // 4 bits (because of the 12 bits for sign and exponent), so
+ // we have to shift and or the rhs to get the right bytes.
+ size_t li = 2;
+ bool direction = true;
+ for (size_t ri = 1; ri < sizeof (rhs);)
+ {
+ if (direction)
+ {
+ this->ld[li] |= ((rhs_ptr[ri] << 4) & 0xf0);
+ direction = false;
+ ++ri;
+ }
+ else
+ {
+ this->ld[li] |= ((rhs_ptr[ri] >> 4) & 0xf);
+ direction = true;
+ ++li;
+ }
+ }
+#if defined (ACE_LITTLE_ENDIAN)
+ ACE_OS::memcpy (rhs_ptr, this->ld, sizeof (this->ld));
+ ACE_CDR::swap_16 (rhs_ptr, this->ld);
+#endif
+ }
+ else
+ {
+ ACE_OS::memcpy(this->ld,
+ reinterpret_cast<const char*> (&rhs), sizeof (rhs));
+ }
+ return *this;
+}
+
+ACE_CDR::LongDouble&
+ACE_CDR::LongDouble::assign (const ACE_CDR::LongDouble& rhs)
+{
+ if (this != &rhs)
+ *this = rhs;
+ return *this;
+}
+
+bool
+ACE_CDR::LongDouble::operator== (const ACE_CDR::LongDouble &rhs) const
+{
+ return ACE_OS::memcmp (this->ld, rhs.ld, 16) == 0;
+}
+
+bool
+ACE_CDR::LongDouble::operator!= (const ACE_CDR::LongDouble &rhs) const
+{
+ return ACE_OS::memcmp (this->ld, rhs.ld, 16) != 0;
+}
+
+ACE_CDR::LongDouble::operator ACE_CDR::LongDouble::NativeImpl () const
+{
+ ACE_CDR::LongDouble::NativeImpl ret = 0.0;
+ char* lhs_ptr = reinterpret_cast<char*> (&ret);
+
+ if (sizeof (ret) == 8)
+ {
+#if defined (ACE_LITTLE_ENDIAN)
+ static const size_t byte_zero = 1;
+ static const size_t byte_one = 0;
+ char copy[16];
+ ACE_CDR::swap_16 (this->ld, copy);
+#else
+ static const size_t byte_zero = 0;
+ static const size_t byte_one = 1;
+ const char* copy = this->ld;
+#endif
+ ACE_INT16 exponent = 0;
+ char* exp_ptr = reinterpret_cast<char*> (&exponent);
+ exp_ptr[byte_zero] = copy[0];
+ exp_ptr[byte_one] = copy[1];
+
+ ACE_INT16 sign = (exponent & 0x8000);
+ exponent &= 0x7fff;
+
+ // Infinity and NaN have an exponent of 0x7fff in 128-bit IEEE
+ if (exponent == 0x7fff)
+ {
+ exponent = 0x7ff;
+ }
+ else
+ {
+ exponent = (exponent - max_fifteen_bit) + max_eleven_bit;
+ }
+ exponent = (exponent << 4) | sign;
+
+ // Store the sign and exponent
+ lhs_ptr[0] = exp_ptr[byte_zero];
+ lhs_ptr[1] = exp_ptr[byte_one];
+
+ // Store the mantissa. In an 8 byte double, it is split by
+ // 4 bits (because of the 12 bits for sign and exponent), so
+ // we have to shift and or the rhs to get the right bytes.
+ size_t li = 1;
+ bool direction = true;
+ for (size_t ri = 2; li < sizeof (ret);) {
+ if (direction)
+ {
+ lhs_ptr[li] |= ((copy[ri] >> 4) & 0xf);
+ direction = false;
+ ++li;
+ }
+ else
+ {
+ lhs_ptr[li] |= ((copy[ri] & 0xf) << 4);
+ direction = true;
+ ++ri;
+ }
+ }
+
+#if defined (ACE_LITTLE_ENDIAN)
+ ACE_CDR::swap_8 (lhs_ptr, lhs_ptr);
+#endif
+ }
+ else
+ {
+ ACE_OS::memcpy(lhs_ptr, this->ld, sizeof (ret));
+ }
+
+ // This bit of code is unnecessary. However, this code is
+ // necessary to work around a bug in the gcc 4.1.1 optimizer.
+ ACE_CDR::LongDouble tmp;
+ tmp.assign (ret);
+
+ return ret;
+}
+#endif /* NONNATIVE_LONGDOUBLE */
+
+#if defined(_UNICOS) && !defined(_CRAYMPP)
+// placeholders to get things compiling
+ACE_CDR::Float::Float (void)
+{
+}
+
+ACE_CDR::Float::Float (const float & /* init */)
+{
+}
+
+ACE_CDR::Float &
+ACE_CDR::Float::operator= (const float & /* rhs */)
+{
+ return *this;
+}
+
+bool
+ACE_CDR::Float::operator!= (const ACE_CDR::Float & /* rhs */) const
+{
+ return false;
+}
+#endif /* _UNICOS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/CDR_Base.h b/ACE/ace/CDR_Base.h
new file mode 100644
index 00000000000..afd278a5e59
--- /dev/null
+++ b/ACE/ace/CDR_Base.h
@@ -0,0 +1,353 @@
+// -*- 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/Default_Constants.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Message_Block;
+
+/**
+ * @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 (char const *orig, char *target);
+ static void swap_4 (char const *orig, char *target);
+ static void swap_8 (char const *orig, char *target);
+ static void swap_16 (char const *orig, char *target);
+ static void swap_2_array (char const *orig,
+ char *target,
+ size_t length);
+ static void swap_4_array (char const *orig,
+ char *target,
+ size_t length);
+ static void swap_8_array (char const *orig,
+ char *target,
+ size_t length);
+ static void swap_16_array (char const *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
+ * @a 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 @a minsize bytes.
+ static size_t next_size (size_t minsize);
+
+ /**
+ * Increase the capacity of mb to contain at least @a minsize bytes.
+ * If @a minsize is zero the size is increased by an amount at least
+ * large enough to contain any of the basic IDL types.
+ * @retval -1 Failure
+ * @retval 0 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 first message block of the
+ /// original stream, not the following message blocks.
+ 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);
+
+ /**
+ * @name Basic OMG IDL Types
+ *
+ * These types are for use in the CDR classes. The cleanest way to
+ * avoid complaints from all compilers is to define them all.
+ */
+ //@{
+ typedef bool Boolean;
+ typedef unsigned char Octet;
+ typedef char Char;
+ typedef ACE_WCHAR_T 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)) || (defined (__BORLANDC__))
+ typedef __int64 LongLong;
+# elif ACE_SIZEOF_LONG == 8 && !defined(_CRAYMPP)
+ typedef long LongLong;
+# elif defined(__TANDEM)
+ typedef long long LongLong;
+# elif ACE_SIZEOF_LONG_LONG == 8 && !defined (ACE_LACKS_LONGLONG_T)
+# if defined (sun) && !defined (ACE_LACKS_U_LONGLONG_T)
+ // 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
+ struct ACE_Export LongLong
+ {
+# if defined (ACE_BIG_ENDIAN)
+ ACE_CDR::Long h;
+ ACE_CDR::Long l;
+# else
+ ACE_CDR::Long l;
+ ACE_CDR::Long h;
+# endif /* ! ACE_BIG_ENDIAN */
+
+ /**
+ * @name Overloaded Relation Operators.
+ *
+ * The canonical comparison operators.
+ */
+ //@{
+ bool operator== (const LongLong &rhs) const;
+ bool operator!= (const LongLong &rhs) const;
+ //@}
+ };
+# 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 unsigned int to get word alignment.
+ unsigned 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);
+ bool 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.
+ unsigned 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
+# define ACE_CDR_LONG_DOUBLE_ASSIGNMENT(LHS, RHS) LHS = RHS
+# else
+# define NONNATIVE_LONGDOUBLE
+# define ACE_CDR_LONG_DOUBLE_INITIALIZER {{0}}
+# define ACE_CDR_LONG_DOUBLE_ASSIGNMENT(LHS, RHS) LHS.assign (RHS)
+ struct ACE_Export LongDouble
+ {
+ // VxWorks' compiler (gcc 2.96) gets confused by the operator long
+ // double, so we avoid using long double as the NativeImpl.
+ // Linux's x86 long double format (12 or 16 bytes) is incompatible
+ // with Windows, Solaris, AIX, MacOS X and HP-UX (and probably others)
+ // long double format (8 or 16 bytes). If you need 32-bit Linux to
+ // inter-operate with 64-bit Linux you will want to define this
+ // macro to 0 so that "long double" is used. Otherwise, do not define
+ // this macro.
+# if defined (ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE) && \
+ (ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE == 1)
+ typedef double NativeImpl;
+# else
+ typedef long double NativeImpl;
+# endif /* ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE==1 */
+
+ char ld[16];
+
+ LongDouble& assign (const NativeImpl& rhs);
+ LongDouble& assign (const LongDouble& rhs);
+
+ bool operator== (const LongDouble &rhs) const;
+ bool operator!= (const LongDouble &rhs) const;
+
+ LongDouble& operator*= (const NativeImpl rhs) {
+ return this->assign (static_cast<NativeImpl> (*this) * rhs);
+ }
+ LongDouble& operator/= (const NativeImpl rhs) {
+ return this->assign (static_cast<NativeImpl> (*this) / rhs);
+ }
+ LongDouble& operator+= (const NativeImpl rhs) {
+ return this->assign (static_cast<NativeImpl> (*this) + rhs);
+ }
+ LongDouble& operator-= (const NativeImpl rhs) {
+ return this->assign (static_cast<NativeImpl> (*this) - rhs);
+ }
+ LongDouble& operator++ () {
+ return this->assign (static_cast<NativeImpl> (*this) + 1);
+ }
+ LongDouble& operator-- () {
+ return this->assign (static_cast<NativeImpl> (*this) - 1);
+ }
+ LongDouble operator++ (int) {
+ LongDouble ldv = *this;
+ this->assign (static_cast<NativeImpl> (*this) + 1);
+ return ldv;
+ }
+ LongDouble operator-- (int) {
+ LongDouble ldv = *this;
+ this->assign (static_cast<NativeImpl> (*this) - 1);
+ return ldv;
+ }
+
+ operator NativeImpl () const;
+ };
+# 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 */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#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/ace/CDR_Base.inl b/ACE/ace/CDR_Base.inl
new file mode 100644
index 00000000000..b84470af87f
--- /dev/null
+++ b/ACE/ace/CDR_Base.inl
@@ -0,0 +1,255 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_INTRINSIC_BYTESWAP)
+// Take advantage of MSVC++ byte swapping compiler intrinsics (found
+// in <stdlib.h>).
+# pragma intrinsic (_byteswap_ushort, _byteswap_ulong, _byteswap_uint64)
+#endif /* ACE_HAS_INTRINSIC_BYTESWAP */
+
+#if defined (ACE_HAS_BSWAP_16) || defined (ACE_HAS_BSWAP_32) || defined (ACE_HAS_BSWAP_64)
+# include "ace/os_include/os_byteswap.h"
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//
+// The ACE_CDR::swap_X and ACE_CDR::swap_X_array routines are broken
+// in 5 cases for optimization:
+//
+// * MSVC++ 7.1 or better
+// => Compiler intrinsics
+//
+// * AMD64 CPU + gnu g++
+// => gcc amd64 inline assembly.
+//
+// * 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_INTRINSIC_BYTESWAP)
+ // Take advantage of MSVC++ compiler intrinsic byte swapping
+ // function.
+ *reinterpret_cast<unsigned short *> (target) =
+ _byteswap_ushort (*reinterpret_cast<unsigned short const *> (orig));
+#elif defined (ACE_HAS_BSWAP16)
+ *reinterpret_cast<uint16_t *> (target) =
+ bswap16 (*reinterpret_cast<uint16_t const *> (orig));
+#elif defined (ACE_HAS_BSWAP_16)
+ *reinterpret_cast<uint16_t *> (target) =
+ bswap_16 (*reinterpret_cast<uint16_t const *> (orig));
+#elif defined(ACE_HAS_INTEL_ASSEMBLY)
+ unsigned short a =
+ *reinterpret_cast<const unsigned short*> (orig);
+ asm( "rolw $8, %0" : "=r" (a) : "0" (a) );
+ *reinterpret_cast<unsigned short*> (target) = a;
+#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 ax, [ebx];
+ __asm rol ax, 8;
+ __asm mov [ecx], ax;
+#else
+ register ACE_UINT16 usrc = * reinterpret_cast<const ACE_UINT16*> (orig);
+ register ACE_UINT16* udst = 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_INTRINSIC_BYTESWAP)
+ // Take advantage of MSVC++ compiler intrinsic byte swapping
+ // function.
+ *reinterpret_cast<unsigned long *> (target) =
+ _byteswap_ulong (*reinterpret_cast<unsigned long const *> (orig));
+#elif defined (ACE_HAS_BSWAP32)
+ *reinterpret_cast<uint32_t *> (target) =
+ bswap32 (*reinterpret_cast<uint32_t const *> (orig));
+#elif defined (ACE_HAS_BSWAP_32)
+ *reinterpret_cast<uint32_t *> (target) =
+ bswap_32 (*reinterpret_cast<uint32_t const *> (orig));
+#elif defined(ACE_HAS_INTEL_ASSEMBLY)
+ // We have ACE_HAS_PENTIUM, so we know the sizeof's.
+ register unsigned int j =
+ *reinterpret_cast<const unsigned int*> (orig);
+ asm ("bswap %1" : "=r" (j) : "0" (j));
+ *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 = * reinterpret_cast<const ACE_UINT32*> (orig);
+ x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
+ * reinterpret_cast<ACE_UINT32*> (target) = x;
+#endif /* ACE_HAS_INTRINSIC_BYTESWAP */
+}
+
+ACE_INLINE void
+ACE_CDR::swap_8 (const char* orig, char* target)
+{
+#if defined (ACE_HAS_INTRINSIC_BYTESWAP)
+ // Take advantage of MSVC++ compiler intrinsic byte swapping
+ // function.
+ *reinterpret_cast<unsigned __int64 *> (target) =
+ _byteswap_uint64 (*reinterpret_cast<unsigned __int64 const *> (orig));
+#elif defined (ACE_HAS_BSWAP64)
+ *reinterpret_cast<uint64_t *> (target) =
+ bswap64 (*reinterpret_cast<uint64_t const *> (orig));
+#elif defined (ACE_HAS_BSWAP_64)
+ *reinterpret_cast<uint64_t *> (target) =
+ bswap_64 (*reinterpret_cast<uint64_t const *> (orig));
+#elif (defined (__amd64__) || defined (__x86_64__)) && defined(__GNUG__)
+ register unsigned long x =
+ * reinterpret_cast<const unsigned long*> (orig);
+ asm ("bswapq %1" : "=r" (x) : "0" (x));
+ *reinterpret_cast<unsigned long*> (target) = x;
+#elif defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ register unsigned int i =
+ *reinterpret_cast<const unsigned int*> (orig);
+ register unsigned int j =
+ *reinterpret_cast<const unsigned int*> (orig + 4);
+ asm ("bswap %1" : "=r" (i) : "0" (i));
+ asm ("bswap %1" : "=r" (j) : "0" (j));
+ *reinterpret_cast<unsigned int*> (target + 4) = i;
+ *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 =
+ * 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);
+ *reinterpret_cast<unsigned long*> (target) = x;
+#else
+ register ACE_UINT32 x =
+ * reinterpret_cast<const ACE_UINT32*> (orig);
+ register ACE_UINT32 y =
+ * 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);
+ * reinterpret_cast<ACE_UINT32*> (target) = y;
+ * reinterpret_cast<ACE_UINT32*> (target + 4) = x;
+#endif /* ACE_HAS_INTRINSIC_BYTESWAP */
+}
+
+ACE_INLINE void
+ACE_CDR::swap_16 (const char* orig, char* target)
+{
+ swap_8 (orig + 8, target);
+ swap_8 (orig, target + 8);
+}
+
+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.
+
+ // Quickly multiply by two using a bit shift. This is
+ // guaranteed to work since the variable is an unsigned
+ // integer.
+ newsize <<= 1;
+ }
+ 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)
+ // Quickly multiply by two using a bit shift. This is
+ // guaranteed to work since the variable is an unsigned
+ // integer.
+ newsize <<= 1;
+ else
+ newsize += ACE_CDR::LINEAR_GROWTH_CHUNK;
+ }
+
+ return newsize;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// ****************************************************************
diff --git a/ACE/ace/CDR_Size.cpp b/ACE/ace/CDR_Size.cpp
new file mode 100644
index 00000000000..c737db786d9
--- /dev/null
+++ b/ACE/ace/CDR_Size.cpp
@@ -0,0 +1,244 @@
+#include "ace/CDR_Size.h"
+#include "ace/SString.h"
+#include "ace/OS_Memory.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/CDR_Size.inl"
+#endif /* ! __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ CDR_Size,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_wchar (ACE_CDR::WChar x)
+{
+ // Note: translator framework is not supported.
+ //
+ if (ACE_OutputCDR::wchar_maxbytes () == 0)
+ {
+ errno = EACCES;
+ return (this->good_bit_ = false);
+ }
+ if (static_cast<ACE_CDR::Short> (major_version_) == 1
+ && static_cast<ACE_CDR::Short> (minor_version_) == 2)
+ {
+ ACE_CDR::Octet len =
+ static_cast<ACE_CDR::Octet> (ACE_OutputCDR::wchar_maxbytes ());
+ if (this->write_1 (&len))
+ {
+ if (ACE_OutputCDR::wchar_maxbytes () == sizeof(ACE_CDR::WChar))
+ return
+ this->write_octet_array (
+ reinterpret_cast<const ACE_CDR::Octet*> (&x),
+ static_cast<ACE_CDR::ULong> (len));
+ else
+ if (ACE_OutputCDR::wchar_maxbytes () == 2)
+ {
+ ACE_CDR::Short sx = static_cast<ACE_CDR::Short> (x);
+ return
+ this->write_octet_array (
+ reinterpret_cast<const ACE_CDR::Octet*> (&sx),
+ static_cast<ACE_CDR::ULong> (len));
+ }
+ else
+ {
+ ACE_CDR::Octet ox = static_cast<ACE_CDR::Octet> (x);
+ return
+ this->write_octet_array (
+ reinterpret_cast<const ACE_CDR::Octet*> (&ox),
+ static_cast<ACE_CDR::ULong> (len));
+ }
+ }
+ }
+ else if (static_cast<ACE_CDR::Short> (minor_version_) == 0)
+ { // wchar is not allowed with GIOP 1.0.
+ errno = EINVAL;
+ return (this->good_bit_ = false);
+ }
+ if (ACE_OutputCDR::wchar_maxbytes () == sizeof (ACE_CDR::WChar))
+ {
+ const void *temp = &x;
+ return this->write_4 (reinterpret_cast<const ACE_CDR::ULong *> (temp));
+ }
+ else if (ACE_OutputCDR::wchar_maxbytes () == 2)
+ {
+ ACE_CDR::Short sx = static_cast<ACE_CDR::Short> (x);
+ return this->write_2 (reinterpret_cast<const ACE_CDR::UShort *> (&sx));
+ }
+ ACE_CDR::Octet ox = static_cast<ACE_CDR::Octet> (x);
+ return this->write_1 (reinterpret_cast<const ACE_CDR::Octet *> (&ox));
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_string (ACE_CDR::ULong len,
+ const ACE_CDR::Char *x)
+{
+ // Note: translator framework is not supported.
+ //
+ 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 (this->good_bit_ = false);
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::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 (static_cast<ACE_CDR::ULong> (x.length ()),
+ x.c_str());
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_wstring (ACE_CDR::ULong len,
+ const ACE_CDR::WChar *x)
+{
+ // Note: translator framework is not supported.
+ //
+ if (ACE_OutputCDR::wchar_maxbytes () == 0)
+ {
+ errno = EACCES;
+ return (this->good_bit_ = false);
+ }
+
+ if (static_cast<ACE_CDR::Short> (this->major_version_) == 1
+ && 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 (ACE_OutputCDR::wchar_maxbytes () * 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 (this->good_bit_ = false);
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_1 (const ACE_CDR::Octet *)
+{
+ this->adjust (1);
+ return true;
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_2 (const ACE_CDR::UShort *)
+{
+ this->adjust (ACE_CDR::SHORT_SIZE);
+ return true;
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_4 (const ACE_CDR::ULong *)
+{
+ this->adjust (ACE_CDR::LONG_SIZE);
+ return true;
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_8 (const ACE_CDR::ULongLong *)
+{
+ this->adjust (ACE_CDR::LONGLONG_SIZE);
+ return true;
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_16 (const ACE_CDR::LongDouble *)
+{
+ this->adjust (ACE_CDR::LONGDOUBLE_SIZE,
+ ACE_CDR::LONGDOUBLE_ALIGN);
+ return true;
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_wchar_array_i (const ACE_CDR::WChar *,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return true;
+
+ size_t const align = (ACE_OutputCDR::wchar_maxbytes () == 2) ?
+ ACE_CDR::SHORT_ALIGN :
+ ACE_CDR::OCTET_ALIGN;
+
+ this->adjust (ACE_OutputCDR::wchar_maxbytes () * length, align);
+ return true;
+}
+
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_array (const void *,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return true;
+
+ this->adjust (size * length, align);
+ return true;
+}
+
+ACE_CDR::Boolean
+ACE_SizeCDR::write_boolean_array (const ACE_CDR::Boolean*,
+ ACE_CDR::ULong length)
+{
+ this->adjust (length, 1);
+ return true;
+}
+
+void
+ACE_SizeCDR::adjust (size_t size)
+{
+ adjust (size, size);
+}
+
+void
+ACE_SizeCDR::adjust (size_t size,
+ size_t align)
+{
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ const size_t offset = ACE_align_binary (size_, align) - size_;
+ size_ += offset;
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+ size_ += size;
+}
+
+ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, const ACE_CString &x)
+{
+ ss.write_string (x);
+ return ss.good_bit ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/CDR_Size.h b/ACE/ace/CDR_Size.h
new file mode 100644
index 00000000000..a7ff689479b
--- /dev/null
+++ b/ACE/ace/CDR_Size.h
@@ -0,0 +1,241 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file CDR_Size.h
+ *
+ * $Id$
+ *
+ *
+ * ACE Common Data Representation (CDR) size-calculating stream.
+ *
+ *
+ * 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 Boris Kolpackov <boris@kolpackov.net>
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_CDR_SIZE_H
+#define ACE_CDR_SIZE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/CDR_Base.h"
+#include "ace/CDR_Stream.h" // for ACE_OutputCDR::from_*
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SStringfwd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SizeCDR
+ *
+ * @brief A CDR stream for calculating size of the representation.
+ *
+ */
+class ACE_Export ACE_SizeCDR
+{
+public:
+ /// Default constructor.
+ ACE_SizeCDR (ACE_CDR::Octet major_version = ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet minor_version = ACE_CDR_GIOP_MINOR_VERSION);
+
+ /// Returns @c false if an error has ocurred.
+ bool good_bit (void) const;
+
+
+ /// Reset current size.
+ void reset (void);
+
+
+ /// Return current size.
+ size_t total_length (void) const;
+
+
+ // Return 0 on failure and 1 on success.
+ //@{ @name Size-calculating pseudo-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);
+
+ ///
+ /// Adjust to @a size and count <size> octets.
+ void adjust (size_t size);
+
+ /// As above, but now the size and alignment requirements may be
+ /// different.
+ void adjust (size_t size,
+ size_t align);
+
+private:
+ /// disallow copying...
+ ACE_SizeCDR (const ACE_SizeCDR& rhs);
+ ACE_SizeCDR& operator= (const ACE_SizeCDR& 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 @a length elements, each of @a 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);
+
+
+ ACE_CDR::Boolean write_wchar_array_i (const ACE_CDR::WChar* x,
+ ACE_CDR::ULong length);
+
+private:
+ /// Set to false when an error ocurrs.
+ bool good_bit_;
+
+ /// Current size.
+ size_t size_;
+
+protected:
+ /// GIOP version information
+ ACE_CDR::Octet major_version_;
+ ACE_CDR::Octet minor_version_;
+};
+
+// @@ This operator should not be inlined since they force SString.h
+// to be included in this header.
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ const ACE_CString &x);
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/CDR_Size.inl"
+#else /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Not used by CORBA or TAO
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::Char x);
+
+// CDR size-calculating output operators for primitive types
+
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::Short x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::UShort x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::Long x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::ULong x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::LongLong x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::ULongLong x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR& ss,
+ ACE_CDR::LongDouble x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::Float x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_CDR::Double x);
+
+// CDR size-calculating output operator from helper classes
+
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_OutputCDR::from_boolean x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_OutputCDR::from_char x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_OutputCDR::from_wchar x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_OutputCDR::from_octet x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_OutputCDR::from_string x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ ACE_OutputCDR::from_wstring x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ const ACE_CDR::Char* x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_SizeCDR &ss,
+ const ACE_CDR::WChar* x);
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* __ACE_INLINE__ */
+
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CDR_SIZE_H */
diff --git a/ACE/ace/CDR_Size.inl b/ACE/ace/CDR_Size.inl
new file mode 100644
index 00000000000..2527af22989
--- /dev/null
+++ b/ACE/ace/CDR_Size.inl
@@ -0,0 +1,424 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SizeCDR::ACE_SizeCDR (ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : good_bit_ (true),
+ size_ (0),
+ major_version_ (major_version),
+ minor_version_ (minor_version)
+{
+}
+
+ACE_INLINE bool
+ACE_SizeCDR::good_bit (void) const
+{
+ return this->good_bit_;
+}
+
+ACE_INLINE void
+ACE_SizeCDR::reset (void)
+{
+ this->size_ = 0;
+}
+
+ACE_INLINE size_t
+ACE_SizeCDR::total_length (void) const
+{
+ return this->size_;
+}
+
+
+// Encode the CDR stream.
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_octet (ACE_CDR::Octet x)
+{
+ return this->write_1 (reinterpret_cast<const ACE_CDR::Octet *> (&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_boolean (ACE_CDR::Boolean x)
+{
+ return (ACE_CDR::Boolean) this->write_octet (x ? (ACE_CDR::Octet) 1 : (ACE_CDR::Octet) 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_char (ACE_CDR::Char x)
+{
+ // Note: translator framework is not supported.
+ //
+ return this->write_1 (reinterpret_cast<const ACE_CDR::Octet*> (&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_short (ACE_CDR::Short x)
+{
+ return this->write_2 (reinterpret_cast<const ACE_CDR::UShort*> (&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_ushort (ACE_CDR::UShort x)
+{
+ return this->write_2 (reinterpret_cast<const ACE_CDR::UShort*> (&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_long (ACE_CDR::Long x)
+{
+ return this->write_4 (reinterpret_cast<const ACE_CDR::ULong*> (&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_ulong (ACE_CDR::ULong x)
+{
+ return this->write_4 (reinterpret_cast<const ACE_CDR::ULong*> (&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_longlong (const ACE_CDR::LongLong &x)
+{
+ return this->write_8 (reinterpret_cast<const ACE_CDR::ULongLong*> (&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_ulonglong (const ACE_CDR::ULongLong &x)
+{
+ const void *temp = &x;
+ return this->write_8 (reinterpret_cast<const ACE_CDR::ULongLong *> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_float (ACE_CDR::Float x)
+{
+ const void *temp = &x;
+ return this->write_4 (reinterpret_cast<const ACE_CDR::ULong *> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_double (const ACE_CDR::Double &x)
+{
+ const void *temp = &x;
+ return this->write_8 (reinterpret_cast<const ACE_CDR::ULongLong*> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_longdouble (const ACE_CDR::LongDouble &x)
+{
+ const void *temp = &x;
+ return this->write_16 (reinterpret_cast<const ACE_CDR::LongDouble*> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_string (const ACE_CDR::Char *x)
+{
+ if (x != 0)
+ {
+ const ACE_CDR::ULong len =
+ static_cast<ACE_CDR::ULong> (ACE_OS::strlen (x));
+ return this->write_string (len, x);
+ }
+ return this->write_string (0, 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_wstring (const ACE_CDR::WChar *x)
+{
+ if (x != 0)
+ {
+ ACE_CDR::ULong len =
+ static_cast<ACE_CDR::ULong> (ACE_OS::strlen (x));
+ return this->write_wstring (len, x);
+ }
+ return this->write_wstring (0, 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_char_array (const ACE_CDR::Char *x,
+ ACE_CDR::ULong length)
+{
+ // Note: translator framework is not supported.
+ //
+ return this->write_array (x,
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::write_wchar_array (const ACE_CDR::WChar* x,
+ ACE_CDR::ULong length)
+{
+ // Note: translator framework is not supported.
+ //
+ if (ACE_OutputCDR::wchar_maxbytes () == 0)
+ {
+ errno = EACCES;
+ return (ACE_CDR::Boolean) (this->good_bit_ = false);
+ }
+ if (ACE_OutputCDR::wchar_maxbytes () == sizeof (ACE_CDR::WChar))
+ return this->write_array (x,
+ sizeof (ACE_CDR::WChar),
+ sizeof (ACE_CDR::WChar) == 2
+ ? ACE_CDR::SHORT_ALIGN
+ : ACE_CDR::LONG_ALIGN,
+ length);
+ return this->write_wchar_array_i (x,length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_SizeCDR::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_SizeCDR::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_SizeCDR::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_SizeCDR::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_SizeCDR::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_SizeCDR::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_SizeCDR::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_SizeCDR::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_SizeCDR::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_SizeCDR::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 ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::Char x)
+{
+ ss.write_char (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::Short x)
+{
+ ss.write_short (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::UShort x)
+{
+ ss.write_ushort (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::Long x)
+{
+ ss.write_long (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::ULong x)
+{
+ ss.write_ulong (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::LongLong x)
+{
+ ss.write_longlong (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::ULongLong x)
+{
+ ss.write_ulonglong (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::LongDouble x)
+{
+ ss.write_longdouble (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::Float x)
+{
+ ss.write_float (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_CDR::Double x)
+{
+ ss.write_double (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, const ACE_CDR::Char *x)
+{
+ ss.write_string (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, const ACE_CDR::WChar *x)
+{
+ ss.write_wstring (x);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+// The following use the helper classes
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_OutputCDR::from_boolean x)
+{
+ ss.write_boolean (x.val_);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_OutputCDR::from_char x)
+{
+ ss.write_char (x.val_);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_OutputCDR::from_wchar x)
+{
+ ss.write_wchar (x.val_);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_OutputCDR::from_octet x)
+{
+ ss.write_octet (x.val_);
+ return (ACE_CDR::Boolean) ss.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_OutputCDR::from_string x)
+{
+ ACE_CDR::ULong len = 0;
+
+ if (x.val_ != 0)
+ {
+ len = static_cast<ACE_CDR::ULong> (ACE_OS::strlen (x.val_));
+ }
+
+ ss.write_string (len, x.val_);
+ return
+ (ACE_CDR::Boolean) (ss.good_bit () && (!x.bound_ || len <= x.bound_));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_SizeCDR &ss, ACE_OutputCDR::from_wstring x)
+{
+ ACE_CDR::ULong len = 0;
+
+ if (x.val_ != 0)
+ {
+ len = static_cast<ACE_CDR::ULong> (ACE_OS::strlen (x.val_));
+ }
+
+ ss.write_wstring (len, x.val_);
+ return
+ (ACE_CDR::Boolean) (ss.good_bit () && (!x.bound_ || len <= x.bound_));
+}
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/CDR_Stream.cpp b/ACE/ace/CDR_Stream.cpp
new file mode 100644
index 00000000000..00af2b70940
--- /dev/null
+++ b/ACE/ace/CDR_Stream.cpp
@@ -0,0 +1,1892 @@
+#include "ace/CDR_Stream.h"
+#include "ace/SString.h"
+#include "ace/Auto_Ptr.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/CDR_Stream.inl"
+#endif /* ! __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ CDR_Stream,
+ "$Id$")
+
+// ****************************************************************
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+size_t ACE_OutputCDR::wchar_maxbytes_ = sizeof (ACE_CDR::WChar);
+
+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 : (size_t) 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),
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ current_alignment_ (0),
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+ current_is_writable_ (true),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (true),
+ 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),
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ current_alignment_ (0),
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+ current_is_writable_ (true),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (true),
+ 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_Data_Block *data_block,
+ int byte_order,
+ ACE_Allocator *message_block_allocator,
+ size_t memcpy_tradeoff,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (data_block,
+ ACE_Message_Block::DONT_DELETE,
+ message_block_allocator),
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ current_alignment_ (0),
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+ current_is_writable_ (true),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (true),
+ 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 ()),
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ current_alignment_ (0),
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+ current_is_writable_ (true),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (true),
+ 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_;
+}
+
+/*static*/ void
+ACE_OutputCDR::wchar_maxbytes (size_t maxbytes)
+{
+ ACE_OutputCDR::wchar_maxbytes_ = maxbytes;
+}
+
+/*static*/ size_t
+ACE_OutputCDR::wchar_maxbytes ()
+{
+ return ACE_OutputCDR::wchar_maxbytes_;
+}
+
+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;
+
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ minsize += ACE_CDR::MAX_ALIGNMENT;
+#endif /* ACE_LACKS_CDR_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 const newsize = ACE_CDR::next_size (minsize);
+
+ this->good_bit_ = false;
+ ACE_Message_Block* tmp = 0;
+ 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);
+
+ // Message block initialization may fail while the construction
+ // succeds. Since as a matter of policy, ACE may throw no
+ // exceptions, we have to do a separate check like this.
+ if (tmp != 0 && tmp->size () < newsize)
+ {
+ delete tmp;
+ errno = ENOMEM;
+ return -1;
+ }
+
+ this->good_bit_ = true;
+
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ // The new block must start with the same alignment as the
+ // previous block finished.
+ ptrdiff_t const tmpalign =
+ reinterpret_cast<ptrdiff_t> (tmp->rd_ptr ()) % ACE_CDR::MAX_ALIGNMENT;
+ ptrdiff_t const curalign =
+ static_cast<ptrdiff_t> (this->current_alignment_) % ACE_CDR::MAX_ALIGNMENT;
+ ptrdiff_t offset = curalign - tmpalign;
+ if (offset < 0)
+ offset += ACE_CDR::MAX_ALIGNMENT;
+ tmp->rd_ptr (static_cast<size_t> (offset));
+ tmp->wr_ptr (tmp->rd_ptr ());
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ // 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_ = true;
+
+ return this->adjust (size, align, buf);
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_wchar (ACE_CDR::WChar x)
+{
+ if (this->wchar_translator_ != 0)
+ return (this->good_bit_ = this->wchar_translator_->write_wchar (*this, x));
+ if (ACE_OutputCDR::wchar_maxbytes_ == 0)
+ {
+ errno = EACCES;
+ return (this->good_bit_ = false);
+ }
+ if (static_cast<ACE_CDR::Short> (major_version_) == 1
+ && static_cast<ACE_CDR::Short> (minor_version_) == 2)
+ {
+ ACE_CDR::Octet len =
+ static_cast<ACE_CDR::Octet> (ACE_OutputCDR::wchar_maxbytes_);
+ if (this->write_1 (&len))
+ {
+ if (ACE_OutputCDR::wchar_maxbytes_ == sizeof(ACE_CDR::WChar))
+ return
+ this->write_octet_array (
+ reinterpret_cast<const ACE_CDR::Octet*> (&x),
+ static_cast<ACE_CDR::ULong> (len));
+ else
+ if (ACE_OutputCDR::wchar_maxbytes_ == 2)
+ {
+ ACE_CDR::Short sx = static_cast<ACE_CDR::Short> (x);
+ return
+ this->write_octet_array (
+ reinterpret_cast<const ACE_CDR::Octet*> (&sx),
+ static_cast<ACE_CDR::ULong> (len));
+ }
+ else
+ {
+ ACE_CDR::Octet ox = static_cast<ACE_CDR::Octet> (x);
+ return
+ this->write_octet_array (
+ reinterpret_cast<const ACE_CDR::Octet*> (&ox),
+ static_cast<ACE_CDR::ULong> (len));
+ }
+ }
+ }
+ else if (static_cast<ACE_CDR::Short> (minor_version_) == 0)
+ { // wchar is not allowed with GIOP 1.0.
+ errno = EINVAL;
+ return (this->good_bit_ = false);
+ }
+ if (ACE_OutputCDR::wchar_maxbytes_ == sizeof (ACE_CDR::WChar))
+ {
+ void const * const temp = &x;
+ return
+ this->write_4 (reinterpret_cast<const ACE_CDR::ULong *> (temp));
+ }
+ else if (ACE_OutputCDR::wchar_maxbytes_ == 2)
+ {
+ ACE_CDR::Short sx = static_cast<ACE_CDR::Short> (x);
+ return this->write_2 (reinterpret_cast<const ACE_CDR::UShort *> (&sx));
+ }
+ ACE_CDR::Octet ox = static_cast<ACE_CDR::Octet> (x);
+ return this->write_1 (reinterpret_cast<const ACE_CDR::Octet *> (&ox));
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_string (ACE_CDR::ULong len,
+ const ACE_CDR::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 (this->good_bit_ = false);
+}
+
+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 (static_cast<ACE_CDR::ULong> (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_OutputCDR::wchar_maxbytes_ == 0)
+ {
+ errno = EACCES;
+ return (this->good_bit_ = false);
+ }
+
+ if (static_cast<ACE_CDR::Short> (this->major_version_) == 1
+ && 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 (ACE_OutputCDR::wchar_maxbytes_ * 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 (this->good_bit_ = false);
+}
+
+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 const 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,
+ static_cast<ACE_CDR::ULong> (length)))
+ return (this->good_bit_ = false);
+ 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,
+ static_cast<ACE_CDR::ULong> (length)))
+ return (this->good_bit_ = false);
+ continue;
+ }
+
+ ACE_Message_Block* cont = 0;
+ this->good_bit_ = false;
+ ACE_NEW_RETURN (cont,
+ ACE_Message_Block (i->data_block ()->duplicate ()),
+ false);
+ this->good_bit_ = true;
+
+ 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_ = false;
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ this->current_alignment_ =
+ (this->current_alignment_ + cont->length ()) % ACE_CDR::MAX_ALIGNMENT;
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+ }
+
+ return true;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_1 (const ACE_CDR::Octet *x)
+{
+ char *buf = 0;
+ if (this->adjust (1, buf) == 0)
+ {
+ *reinterpret_cast<ACE_CDR::Octet*> (buf) = *x;
+ return true;
+ }
+
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_2 (const ACE_CDR::UShort *x)
+{
+ char *buf = 0;
+ if (this->adjust (ACE_CDR::SHORT_SIZE, buf) == 0)
+ {
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *reinterpret_cast<ACE_CDR::UShort*> (buf) = *x;
+ return true;
+#else
+ if (!this->do_byte_swap_)
+ {
+ *reinterpret_cast<ACE_CDR::UShort *> (buf) = *x;
+ return true;
+ }
+ else
+ {
+ ACE_CDR::swap_2 (reinterpret_cast<const char*> (x), buf);
+ return true;
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_4 (const ACE_CDR::ULong *x)
+{
+ char *buf = 0;
+ if (this->adjust (ACE_CDR::LONG_SIZE, buf) == 0)
+ {
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *reinterpret_cast<ACE_CDR::ULong*> (buf) = *x;
+ return true;
+#else
+ if (!this->do_byte_swap_)
+ {
+ *reinterpret_cast<ACE_CDR::ULong *> (buf) = *x;
+ return true;
+ }
+ else
+ {
+ ACE_CDR::swap_4 (reinterpret_cast<const char*> (x), buf);
+ return true;
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_8 (const ACE_CDR::ULongLong *x)
+{
+ char *buf = 0;
+
+ if (this->adjust (ACE_CDR::LONGLONG_SIZE, buf) == 0)
+ {
+#if defined (__arm__)
+ // Convert to Intel format (12345678 => 56781234)
+ const char *orig = reinterpret_cast<const char *> (x);
+ char *target = buf;
+ register ACE_UINT32 x =
+ *reinterpret_cast<const ACE_UINT32 *> (orig);
+ register ACE_UINT32 y =
+ *reinterpret_cast<const ACE_UINT32 *> (orig + 4);
+ *reinterpret_cast<ACE_UINT32 *> (target) = y;
+ *reinterpret_cast<ACE_UINT32 *> (target + 4) = x;
+ return true;
+#else
+# if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *reinterpret_cast<ACE_CDR::ULongLong *> (buf) = *x;
+ return true;
+# else
+ if (!this->do_byte_swap_)
+ {
+ *reinterpret_cast<ACE_CDR::ULongLong *> (buf) = *x;
+ return true;
+ }
+ else
+ {
+ ACE_CDR::swap_8 (reinterpret_cast<const char*> (x), buf);
+ return true;
+ }
+# endif /* ACE_ENABLE_SWAP_ON_WRITE */
+#endif /* !__arm__ */
+ }
+
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_16 (const ACE_CDR::LongDouble *x)
+{
+ char* buf = 0;
+ if (this->adjust (ACE_CDR::LONGDOUBLE_SIZE,
+ ACE_CDR::LONGDOUBLE_ALIGN,
+ buf) == 0)
+ {
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *reinterpret_cast<ACE_CDR::LongDouble*> (buf) = *x;
+ return 1;
+#else
+ if (!this->do_byte_swap_)
+ {
+ *reinterpret_cast<ACE_CDR::LongDouble *> (buf) = *x;
+ return true;
+ }
+ else
+ {
+ ACE_CDR::swap_16 (reinterpret_cast<const char*> (x), buf);
+ return true;
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_wchar_array_i (const ACE_CDR::WChar *x,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return true;
+ char* buf = 0;
+ size_t const align = (ACE_OutputCDR::wchar_maxbytes_ == 2) ?
+ ACE_CDR::SHORT_ALIGN :
+ ACE_CDR::OCTET_ALIGN;
+
+ if (this->adjust (ACE_OutputCDR::wchar_maxbytes_ * length, align, buf) == 0)
+ {
+ if (ACE_OutputCDR::wchar_maxbytes_ == 2)
+ {
+ ACE_CDR::UShort *sb = reinterpret_cast<ACE_CDR::UShort *> (buf);
+ for (size_t i = 0; i < length; ++i)
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ sb[i] = static_cast<ACE_CDR::UShort> (x[i]);
+#else
+ if (!this->do_byte_swap_)
+ sb[i] = static_cast<ACE_CDR::UShort> (x[i]);
+ else
+ {
+ ACE_CDR::UShort sx = static_cast<ACE_CDR::UShort> (x[i]);
+ ACE_CDR::swap_2 (reinterpret_cast<char *> (&sx), &buf[i * 2]);
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+ else
+ {
+ for (size_t i = 0; i < length; ++i)
+ buf[i] = static_cast<char> (x[i]);
+ }
+ return this->good_bit_;
+ }
+ return false;
+}
+
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_array (const void *x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return true;
+ char *buf = 0;
+ if (this->adjust (size * length, align, buf) == 0)
+ {
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ ACE_OS::memcpy (buf, x, size*length);
+ return true;
+#else
+ if (!this->do_byte_swap_ || size == 1)
+ {
+ ACE_OS::memcpy (buf, x, size*length);
+ return true;
+ }
+ else
+ {
+ const char *source = reinterpret_cast<const char *> (x);
+ switch (size)
+ {
+ case 2:
+ ACE_CDR::swap_2_array (source, buf, length);
+ return true;
+ case 4:
+ ACE_CDR::swap_4_array (source, buf, length);
+ return true;
+ case 8:
+ ACE_CDR::swap_8_array (source, buf, length);
+ return true;
+ case 16:
+ ACE_CDR::swap_16_array (source, buf, length);
+ return true;
+ default:
+ // TODO: print something?
+ this->good_bit_ = false;
+ return false;
+ }
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+ this->good_bit_ = false;
+ return false;
+}
+
+
+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
+ // memory it is possible (though very unlikely) that a boolean has
+ // a non-zero value (different from 1).
+ // We resort to a simple loop.
+ ACE_CDR::Boolean const * const end = x + length;
+
+ for (ACE_CDR::Boolean const * i = x;
+ i != end && this->good_bit ();
+ ++i)
+ (void) this->write_boolean (*i);
+
+ return this->good_bit ();
+}
+
+
+char *
+ACE_OutputCDR::write_long_placeholder (void)
+{
+ this->align_write_ptr (ACE_CDR::LONG_SIZE);
+ char *pos = this->current_->wr_ptr ();
+ this->write_long (0);
+ return pos;
+}
+
+
+char *
+ACE_OutputCDR::write_short_placeholder (void)
+{
+ this->align_write_ptr (ACE_CDR::SHORT_SIZE);
+ char *pos = this->current_->wr_ptr();
+ this->write_short (0);
+ return pos;
+}
+
+
+ACE_CDR::Boolean
+ACE_OutputCDR::replace (ACE_CDR::Long x, char* loc)
+{
+ if (this->find (loc) == 0)
+ return false;
+
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *reinterpret_cast<ACE_CDR::Long*> (loc) = x;
+#else
+ if (!this->do_byte_swap_)
+ {
+ *reinterpret_cast<ACE_CDR::Long *> (loc) = x;
+ }
+ else
+ {
+ ACE_CDR::swap_4 (reinterpret_cast<const char*> (&x), loc);
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+
+ return true;
+}
+
+
+ACE_CDR::Boolean
+ACE_OutputCDR::replace (ACE_CDR::Short x, char* loc)
+{
+ if (this->find (loc) == 0)
+ return false;
+
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *reinterpret_cast<ACE_CDR::Short*> (loc) = x;
+#else
+ if (!this->do_byte_swap_)
+ {
+ *reinterpret_cast<ACE_CDR::Short *> (loc) = x;
+ }
+ else
+ {
+ ACE_CDR::swap_2 (reinterpret_cast<const char*> (&x), loc);
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+
+ return true;
+}
+
+
+int
+ACE_OutputCDR::consolidate (void)
+{
+ // Optimize by only doing something if we need to
+ if (this->current_ != &this->start_)
+ {
+ // Set the number of bytes in the top-level block, reallocating
+ // if necessary. The rd_ptr and wr_ptr remain at the original offsets
+ // into the buffer, even if it is reallocated.
+ // Return an error if the allocation failed.
+ size_t const newsize =
+ ACE_CDR::first_size (this->total_length ()
+ + ACE_CDR::MAX_ALIGNMENT);
+ if (this->start_.size (newsize) < 0)
+ {
+ return -1;
+ }
+
+ // Consolidate the chain into the first block. NOTE that
+ // ACE_CDR::consolidate can not be used since we don't want to
+ // overwrite what is already in the first block. We just append it since
+ // the read and write pointers weren't affected by the resizing above.
+ // We also don't have to worry about alignment since the start block is
+ // already aligned.
+ // NOTE also we know there is a continuation since we checked for it
+ // above. There is therefore no reason to check for a 0 continuation
+ // field here.
+ ACE_Message_Block *cont = this->start_.cont ();
+ for (const ACE_Message_Block* i = cont; i != 0; i = i->cont ())
+ {
+ this->start_.copy (i->rd_ptr (), i->length ());
+ }
+
+ // Release the old blocks that were consolidated and reset the
+ // current_ and current_is_writable_ to reflect the single used block.
+ ACE_Message_Block::release (cont);
+ this->start_.cont (0);
+ this->current_ = &this->start_;
+ this->current_is_writable_ = true;
+ }
+
+ return 0;
+}
+
+
+ACE_Message_Block*
+ACE_OutputCDR::find (char* loc)
+{
+ ACE_Message_Block* mb = 0;
+ for (mb = &this->start_; mb != 0; mb = mb->cont ())
+ {
+ if (loc <= mb->wr_ptr () && loc >= mb->rd_ptr ())
+ {
+ break;
+ }
+ }
+
+ return mb;
+}
+
+
+// ****************************************************************
+
+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_ (true),
+ major_version_ (major_version),
+ minor_version_ (minor_version),
+ char_translator_ (0),
+ wchar_translator_ (0)
+{
+ 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_ (true),
+ major_version_ (major_version),
+ minor_version_ (minor_version),
+ char_translator_ (0),
+ wchar_translator_ (0)
+{
+}
+
+ACE_InputCDR::ACE_InputCDR (const ACE_Message_Block *data,
+ int byte_order,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version,
+ ACE_Lock* lock)
+: start_ (0, ACE_Message_Block::MB_DATA, 0, 0, 0, lock),
+ good_bit_ (true),
+ major_version_ (major_version),
+ minor_version_ (minor_version),
+ char_translator_ (0),
+ wchar_translator_ (0)
+
+{
+ 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_ (true),
+ major_version_ (major_version),
+ minor_version_ (minor_version),
+ char_translator_ (0),
+ wchar_translator_ (0)
+
+{
+}
+
+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_ (true),
+ major_version_ (major_version),
+ minor_version_ (minor_version),
+ char_translator_ (0),
+ wchar_translator_ (0)
+
+{
+ // 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_ (true),
+ major_version_ (rhs.major_version_),
+ minor_version_ (rhs.minor_version_),
+ char_translator_ (rhs.char_translator_),
+ wchar_translator_ (rhs.wchar_translator_)
+
+{
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ // 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);
+#else
+ char *incoming_start = rhs.start_.base ();
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ const 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_ = false;
+}
+
+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_ (true),
+ major_version_ (rhs.major_version_),
+ minor_version_ (rhs.minor_version_),
+ char_translator_ (rhs.char_translator_),
+ wchar_translator_ (rhs.wchar_translator_)
+
+{
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ // 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);
+#else
+ char *incoming_start = rhs.start_.base ();
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ const 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 than what we actually want.
+ this->start_.rd_ptr (newpos);
+ this->start_.wr_ptr (newpos + size);
+
+ ACE_CDR::Octet byte_order = 0;
+ (void) this->read_octet (byte_order);
+ this->do_byte_swap_ = (byte_order != ACE_CDR_BYTE_ORDER);
+ }
+ else
+ this->good_bit_ = false;
+}
+
+ACE_InputCDR::ACE_InputCDR (const ACE_InputCDR& rhs)
+ : start_ (rhs.start_,
+ ACE_CDR::MAX_ALIGNMENT),
+ do_byte_swap_ (rhs.do_byte_swap_),
+ good_bit_ (true),
+ major_version_ (rhs.major_version_),
+ minor_version_ (rhs.minor_version_),
+ char_translator_ (rhs.char_translator_),
+ wchar_translator_ (rhs.wchar_translator_)
+{
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ char *buf = ACE_ptr_align_binary (rhs.start_.base (),
+ ACE_CDR::MAX_ALIGNMENT);
+#else
+ char *buf = rhs.start_.base ();
+#endif /* ACE_LACKS_CDR_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_ (true),
+ major_version_ (x.rhs_.major_version_),
+ minor_version_ (x.rhs_.minor_version_),
+ char_translator_ (x.rhs_.char_translator_),
+ wchar_translator_ (x.rhs_.wchar_translator_)
+{
+
+ 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_ = true;
+ this->char_translator_ = rhs.char_translator_;
+ 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_ (true),
+ major_version_ (rhs.major_version_),
+ minor_version_ (rhs.minor_version_),
+ char_translator_ (rhs.char_translator_),
+ wchar_translator_ (rhs.wchar_translator_)
+{
+ 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 (static_cast<ACE_CDR::Short> (major_version_) == 1
+ && static_cast<ACE_CDR::Short> (minor_version_) == 2)
+ {
+ ACE_CDR::Octet len;
+ if (this->read_1 (&len))
+ return this->skip_bytes (static_cast<size_t> (len));
+ }
+ else
+ {
+ ACE_CDR::WChar x;
+ void * const temp = &x;
+ if (ACE_OutputCDR::wchar_maxbytes_ == 2)
+ return this->read_2 (reinterpret_cast<ACE_CDR::UShort *> (temp));
+ else
+ return this->read_4 (reinterpret_cast<ACE_CDR::ULong *> (temp));
+ }
+
+ return (this->good_bit_ = false);
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_wchar (ACE_CDR::WChar& x)
+{
+ if (this->wchar_translator_ != 0)
+ {
+ this->good_bit_ = this->wchar_translator_->read_wchar (*this,x);
+ return this->good_bit_;
+ }
+ if (ACE_OutputCDR::wchar_maxbytes_ == 0)
+ {
+ errno = EACCES;
+ return (this->good_bit_ = false);
+ }
+
+ if (ACE_OutputCDR::wchar_maxbytes_ == sizeof (ACE_CDR::WChar))
+ {
+ if (static_cast<ACE_CDR::Short> (major_version_) == 1
+ && static_cast<ACE_CDR::Short> (minor_version_) == 2)
+ {
+ ACE_CDR::Octet len;
+
+ if (this->read_1 (&len))
+ return this->read_array
+ (reinterpret_cast<ACE_CDR::Octet*> (&x),
+ static_cast<ACE_CDR::ULong> (len),
+ ACE_CDR::OCTET_ALIGN,
+ 1);
+
+ else
+ return (this->good_bit_ = false);
+ }
+
+ void * const temp = &x;
+ if (sizeof (ACE_CDR::WChar) == 2)
+ return this->read_2 (reinterpret_cast<ACE_CDR::UShort *> (temp));
+ else
+ return this->read_4 (reinterpret_cast<ACE_CDR::ULong *> (temp));
+ }
+
+ if (static_cast<ACE_CDR::Short> (major_version_) == 1
+ && static_cast<ACE_CDR::Short> (minor_version_) == 2)
+ {
+ ACE_CDR::Octet len;
+
+ if (this->read_1 (&len))
+ {
+ if (len == 2)
+ {
+ ACE_CDR::Short sx;
+ if (this->read_array
+ (reinterpret_cast<ACE_CDR::Octet*> (&sx),
+ static_cast<ACE_CDR::ULong> (len),
+ ACE_CDR::OCTET_ALIGN,
+ 1))
+ {
+ x = static_cast<ACE_CDR::WChar> (sx);
+ return true;
+ }
+ }
+ else
+ {
+ ACE_CDR::Octet ox;
+ if (this->read_array
+ (reinterpret_cast<ACE_CDR::Octet*> (&ox),
+ static_cast<ACE_CDR::ULong> (len),
+ ACE_CDR::OCTET_ALIGN,
+ 1))
+ {
+ x = static_cast<ACE_CDR::WChar> (ox);
+ return true;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (ACE_OutputCDR::wchar_maxbytes_ == 2)
+ {
+ ACE_CDR::UShort sx;
+ if (this->read_2 (reinterpret_cast<ACE_CDR::UShort *> (&sx)))
+ {
+ x = static_cast<ACE_CDR::WChar> (sx);
+ return true;
+ }
+ }
+ else
+ {
+ ACE_CDR::Octet ox;
+ if (this->read_1 (&ox))
+ {
+ x = static_cast<ACE_CDR::WChar> (ox);
+ return true;
+ }
+
+ }
+ }
+ return (this->good_bit_ = false);
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_string (ACE_CDR::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)
+ {
+ this->good_bit_ = this->char_translator_->read_string (*this, x);
+ return this->good_bit_;
+ }
+
+ ACE_CDR::ULong len = 0;
+
+ if (!this->read_ulong (len))
+ return false;
+
+ // 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);
+
+ ACE_Auto_Basic_Array_Ptr<ACE_CDR::Char> safe_data (x);
+
+ if (this->read_char_array (x, len))
+ {
+ (void) safe_data.release ();
+ return true;
+ }
+ }
+ 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 (const_cast<char *&> (x), "");
+ return true;
+ }
+
+ x = 0;
+ return (this->good_bit_ = false);
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_string (ACE_CString &x)
+{
+ ACE_CDR::Char * data = 0;
+ if (this->read_string (data))
+ {
+ ACE_Auto_Basic_Array_Ptr<ACE_CDR::Char> safe_data (data);
+ x = data;
+ return true;
+ }
+
+ x = "";
+ return (this->good_bit_ = false);
+}
+
+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)
+ {
+ this->good_bit_ = this->wchar_translator_->read_wstring (*this, x);
+ return this->good_bit_;
+ }
+ if (ACE_OutputCDR::wchar_maxbytes_ == 0)
+ {
+ errno = EACCES;
+ return (this->good_bit_ = false);
+ }
+
+ ACE_CDR::ULong len = 0;
+ if (!this->read_ulong (len))
+ return false;
+
+ // 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_Auto_Basic_Array_Ptr<ACE_CDR::WChar> safe_data;
+
+ if (static_cast<ACE_CDR::Short> (this->major_version_) == 1
+ && static_cast<ACE_CDR::Short> (this->minor_version_) == 2)
+ {
+ len /= ACE_OutputCDR::wchar_maxbytes_;
+
+ //allocating one extra for the null character needed by applications
+ ACE_NEW_RETURN (x,
+ ACE_CDR::WChar [len + 1],
+ false);
+
+ ACE_auto_ptr_reset (safe_data, x);
+
+ 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';
+
+ (void) safe_data.release ();
+
+ return true;
+ }
+ }
+ else
+ {
+ ACE_NEW_RETURN (x,
+ ACE_CDR::WChar [len],
+ false);
+
+ ACE_auto_ptr_reset (safe_data, x);
+
+ if (this->read_wchar_array (x, len))
+ {
+ (void) safe_data.release ();
+
+ return true;
+ }
+ }
+ }
+ 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],
+ false);
+ x[0] = '\x00';
+ return true;
+ }
+
+ this->good_bit_ = false;
+ x = 0;
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_array (void* x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return true;
+ char* buf = 0;
+
+ 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 = 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_ = false;
+ return false;
+ }
+ }
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return this->good_bit_;
+ }
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_wchar_array_i (ACE_CDR::WChar* x,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return true;
+ char* buf = 0;
+ size_t const align = (ACE_OutputCDR::wchar_maxbytes_ == 2) ?
+ ACE_CDR::SHORT_ALIGN :
+ ACE_CDR::OCTET_ALIGN;
+
+ if (this->adjust (ACE_OutputCDR::wchar_maxbytes_ * length, align, buf) == 0)
+ {
+ if (ACE_OutputCDR::wchar_maxbytes_ == 2)
+ {
+ ACE_CDR::UShort *sb = reinterpret_cast<ACE_CDR::UShort *> (buf);
+ for (size_t i = 0; i < length; ++i)
+#if defined (ACE_DISABLE_SWAP_ON_READ)
+ x[i] = static_cast<ACE_CDR::WChar> (sb[i]);
+#else
+ if (!this->do_byte_swap_)
+ x[i] = static_cast<ACE_CDR::WChar> (sb[i]);
+ else
+ {
+ ACE_CDR::UShort sx;
+ ACE_CDR::swap_2 (&buf[i * 2], reinterpret_cast<char *> (&sx));
+ x[i] = static_cast<ACE_CDR::WChar> (sx);
+ }
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ }
+ else
+ {
+ for (size_t i = 0; i < length; ++i)
+ x[i] = static_cast<ACE_CDR::Octet> (buf[i]);
+ }
+ return this->good_bit_;
+ }
+ return false;
+}
+
+
+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 ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ // 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
+ // memory 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)
+ (void) 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 = *reinterpret_cast<ACE_CDR::Octet*> (this->rd_ptr ());
+ this->start_.rd_ptr (1);
+ return true;
+ }
+
+ this->good_bit_ = false;
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_2 (ACE_CDR::UShort *x)
+{
+ char *buf = 0;
+ if (this->adjust (ACE_CDR::SHORT_SIZE, buf) == 0)
+ {
+#if !defined (ACE_DISABLE_SWAP_ON_READ)
+ if (!this->do_byte_swap_)
+ *x = *reinterpret_cast<ACE_CDR::UShort*> (buf);
+ else
+ ACE_CDR::swap_2 (buf, reinterpret_cast<char*> (x));
+#else
+ *x = *reinterpret_cast<ACE_CDR::UShort*> (buf);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return true;
+ }
+ this->good_bit_ = false;
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_4 (ACE_CDR::ULong *x)
+{
+ char *buf = 0;
+ if (this->adjust (ACE_CDR::LONG_SIZE, buf) == 0)
+ {
+#if !defined (ACE_DISABLE_SWAP_ON_READ)
+ if (!this->do_byte_swap_)
+ *x = *reinterpret_cast<ACE_CDR::ULong*> (buf);
+ else
+ ACE_CDR::swap_4 (buf, reinterpret_cast<char*> (x));
+#else
+ *x = *reinterpret_cast<ACE_CDR::ULong*> (buf);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return true;
+ }
+ this->good_bit_ = false;
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_8 (ACE_CDR::ULongLong *x)
+{
+ char *buf = 0;
+
+ 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 = reinterpret_cast<char *> (x);
+ register ACE_UINT32 x =
+ *reinterpret_cast<const ACE_UINT32 *> (orig);
+ register ACE_UINT32 y =
+ *reinterpret_cast<const ACE_UINT32 *> (orig + 4);
+ *reinterpret_cast<ACE_UINT32 *> (target) = y;
+ *reinterpret_cast<ACE_UINT32 *> (target + 4) = x;
+ }
+ else
+ {
+ // Convert from Sparc format (12345678 => 43218765)
+ const char *orig = buf;
+ char *target = reinterpret_cast<char *> (x);
+ register ACE_UINT32 x =
+ *reinterpret_cast<const ACE_UINT32 *> (orig);
+ register ACE_UINT32 y =
+ *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);
+ *reinterpret_cast<ACE_UINT32 *> (target) = x;
+ *reinterpret_cast<ACE_UINT32 *> (target + 4) = y;
+ }
+# else
+ if (!this->do_byte_swap_)
+ *x = *reinterpret_cast<ACE_CDR::ULongLong *> (buf);
+ else
+ ACE_CDR::swap_8 (buf, reinterpret_cast<char *> (x));
+# endif /* !__arm__ */
+#else
+ *x = *reinterpret_cast<ACE_CDR::ULongLong *> (buf);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return true;
+ }
+
+ this->good_bit_ = false;
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_16 (ACE_CDR::LongDouble *x)
+{
+ char *buf = 0;
+ if (this->adjust (ACE_CDR::LONGDOUBLE_SIZE,
+ ACE_CDR::LONGDOUBLE_ALIGN,
+ buf) == 0)
+ {
+#if !defined (ACE_DISABLE_SWAP_ON_READ)
+ if (!this->do_byte_swap_)
+ *x = *reinterpret_cast<ACE_CDR::LongDouble *> (buf);
+ else
+ ACE_CDR::swap_16 (buf, reinterpret_cast<char*> (x));
+#else
+ *x = *reinterpret_cast<ACE_CDR::LongDouble*> (buf);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return true;
+ }
+
+ this->good_bit_ = false;
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::skip_string (void)
+{
+ ACE_CDR::ULong len = 0;
+ if (this->read_ulong (len))
+ {
+ if (this->rd_ptr () + len <= this->wr_ptr ())
+ {
+ this->rd_ptr (len);
+ return true;
+ }
+ this->good_bit_ = false;
+ }
+ return false;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::skip_wstring (void)
+{
+ ACE_CDR::Boolean continue_skipping = true;
+ ACE_CDR::ULong len = 0;
+
+ continue_skipping = read_ulong (len);
+
+ if (continue_skipping && len != 0)
+ {
+ if (static_cast<ACE_CDR::Short> (this->major_version_) == 1
+ && static_cast<ACE_CDR::Short> (this->minor_version_) == 2)
+ continue_skipping = this->skip_bytes ((size_t)len);
+ else
+ while (continue_skipping && 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 true;
+ }
+ this->good_bit_ = false;
+ return false;
+}
+
+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 const 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 const drd_pos =
+ cdr.start_.rd_ptr () - cdr.start_.base ();
+ size_t const dwr_pos =
+ cdr.start_.wr_ptr () - cdr.start_.base ();
+
+ // Get the source read & write pointers
+ size_t const srd_pos =
+ this->start_.rd_ptr () - this->start_.base ();
+ size_t const 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 const dmajor = cdr.major_version_;
+ ACE_CDR::Octet const 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_;
+
+ // 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;
+
+ ACE_CDR::mb_align (&this->start_);
+
+ ACE_Data_Block *db =
+ this->start_.data_block ();
+
+ // If the size of the data that needs to be copied are higher than
+ // what is available, then do a reallocation.
+ if (wr_bytes > (this->start_.size () - ACE_CDR::MAX_ALIGNMENT))
+ {
+ // @@NOTE: We need to probably add another method to the message
+ // block interface to simplify this
+ db =
+ cdr.start_.data_block ()->clone_nocopy ();
+
+ if (db == 0 || db->size ((wr_bytes) +
+ ACE_CDR::MAX_ALIGNMENT) == -1)
+ return 0;
+
+ // Replace our data block by using the incoming CDR stream.
+ db = this->start_.replace_data_block (db);
+
+ // 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);
+ }
+
+ // 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_;
+
+ // Copy the char/wchar translators
+ this->char_translator_ = cdr.char_translator_;
+ this->wchar_translator_ = cdr.wchar_translator_;
+
+ 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);
+}
+
+// --------------------------------------------------------------
+
+ACE_Char_Codeset_Translator::~ACE_Char_Codeset_Translator (void)
+{
+}
+
+// --------------------------------------------------------------
+
+ACE_WChar_Codeset_Translator::~ACE_WChar_Codeset_Translator (void)
+{
+}
+
+// --------------------------------------------------------------
+
+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 ();
+}
+
+#if defined (GEN_OSTREAM_OPS)
+
+std::ostream&
+operator<< (std::ostream &os, ACE_OutputCDR::from_boolean x)
+{
+ return (x.val_ ? os << "true" : os << "false");
+}
+
+std::ostream&
+operator<< (std::ostream &os, ACE_OutputCDR::from_char x)
+{
+ return os << '\'' << x.val_ << '\'';
+}
+
+std::ostream&
+operator<< (std::ostream &os, ACE_OutputCDR::from_wchar x)
+{
+ os.setf (ios_base::showbase);
+ os.setf (ios_base::hex, ios_base::basefield);
+ os << x.val_;
+ os.unsetf (ios_base::showbase);
+ os.setf (ios_base::dec, ios_base::basefield);
+ return os;
+}
+
+std::ostream&
+operator<< (std::ostream &os, ACE_OutputCDR::from_octet x)
+{
+ // Same format (hex) and no risk of overflow.
+ ACE_CDR::WChar w = static_cast<ACE_CDR::WChar> (x.val_);
+ ACE_OutputCDR::from_wchar tmp (w);
+ return os << tmp;
+}
+
+#endif /* GEN_OSTREAM_OPS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/CDR_Stream.h b/ACE/ace/CDR_Stream.h
new file mode 100644
index 00000000000..58ddea442ed
--- /dev/null
+++ b/ACE/ace/CDR_Stream.h
@@ -0,0 +1,1364 @@
+// -*- 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.
+ *
+ * Optimizations
+ * -------------
+ * ACE_LACKS_CDR_ALIGNMENT
+ * @author Arvind S. Krishna <arvindk@dre.vanderbilt.edu>
+ *
+ * CDR stream ignores alignment when marshaling data. Use this option
+ * only when ACE_DISABLE_SWAP_ON_READ can be enabled. This option requires
+ * ACE CDR engine to do both marshaling and demarshaling.
+ *
+ *
+ * @author TAO version by Aniruddha Gokhale <gokhale@cs.wustl.edu>
+ * @author Carlos O'Ryan <coryan@cs.wustl.edu>
+ * @author ACE version by Jeff Parsons <parsons@cs.wustl.edu>
+ * @author Istvan Buki <istvan.buki@euronet.be>
+ * @author Codeset translation by 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/SStringfwd.h"
+#include "ace/Message_Block.h"
+
+#if defined (GEN_OSTREAM_OPS)
+#include "ace/streams.h"
+#endif /* GEN_OSTREAM_OPS */
+
+// Stuff used by the ACE CDR classes.
+#if defined ACE_LITTLE_ENDIAN
+# define ACE_CDR_BYTE_ORDER 1
+// little endian encapsulation byte order has value = 1
+#else /* ! ACE_LITTLE_ENDIAN */
+# define ACE_CDR_BYTE_ORDER 0
+// big endian encapsulation byte order has value = 0
+#endif /* ! ACE_LITTLE_ENDIAN */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 @a size bytes in the internal
+ /// buffer, if @a 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 @a data will not point to the start of the
+ * output stream. @c begin()->rd_ptr() points to the start of the
+ * output stream. See @c 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 data block, it will *not* remove
+ /// <data_block>, since it did not allocated it. It's important to be
+ // careful with the alignment of <data_block>.
+ /**
+ * Create an output stream from an arbitrary data block, care must be
+ * exercised with alignment, because this contructor will align if
+ * needed. In this case @a data_block will not point to the
+ * start of the output stream. begin()->rd_ptr() 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 (ACE_Data_Block *data_block,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ 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 @a 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
+ {
+ explicit from_boolean (ACE_CDR::Boolean b);
+ ACE_CDR::Boolean val_;
+ };
+
+ struct ACE_Export from_octet
+ {
+ explicit from_octet (ACE_CDR::Octet o);
+ ACE_CDR::Octet val_;
+ };
+
+ struct ACE_Export from_char
+ {
+ explicit from_char (ACE_CDR::Char c);
+ ACE_CDR::Char val_;
+ };
+
+ struct ACE_Export from_wchar
+ {
+ explicit 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_;
+ };
+ //@}
+
+ /**
+ * @{ @name Write operations
+ * Return 0 on failure and 1 on success.
+ */
+ 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);
+ //@}
+
+ /**
+ * @{ @name Placeholder/replace operations
+ * Facilitates writing a placeholder into a CDR stream to be replaced
+ * later with a different value.
+ *
+ * @note An example use for this facility is:
+ * @code
+ ACE_OutputCDR strm;
+ ... // insert values...
+ char *pos = strm.write_long_placeholder ();
+ ... // insert more values
+ ACE_CDR::Long real_val; // Somehow assign the "correct" value
+ strm.replace (real_val, pos); // Replace earlier placeholder
+ @endcode
+ */
+
+ /**
+ * Write a placeholder into the stream. The placeholder's pointer
+ * is returned so it may later be passed as the @a loc argument to
+ * replace ().
+ * These methods align the stream's write pointer properly prior to
+ * writing the placeholder.
+ */
+ char* write_long_placeholder (void);
+ char* write_short_placeholder (void);
+
+ /**
+ * Writes a new value into a specific location. This is commonly
+ * used to update a prior "placeholder" location in the stream.
+ * The specified location is assumed to have proper CDR alignment for the
+ * type to insert. This requirement is satisfied by using one of the
+ * placeholder-writing methods to align the stream for the anticipated
+ * value and obtain the correct location.
+ * Treatment of @a x with repect to byte swapping is the same as for when
+ * any value is inserted.
+ *
+ * @param x The value to insert into the specified location.
+ * @param loc The location at which to insert @a x. @a loc must be a valid
+ * position within the stream's current set of message blocks.
+ *
+ * @sa write_long_placeholder(), write_short_placeholder ()
+ */
+ ACE_CDR::Boolean replace (ACE_CDR::Long x, char* loc);
+ ACE_CDR::Boolean replace (ACE_CDR::Short x, char* loc);
+ //@}
+
+ /**
+ * 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 @c false if an error has ocurred.
+ /**
+ * @note The only expected error is to run out of memory.
+ */
+ bool 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;
+
+ /// Replace the message block chain with a single message block.
+ /**
+ * Upon successful completion, there will be a single message block
+ * containing the data from the complete message block chain.
+ *
+ * @note The only expected error is to run out of memory.
+ */
+ int consolidate (void);
+
+ /**
+ * 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 size of first message block in the block chain. @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 null!
+ ACE_Char_Codeset_Translator *char_translator (void) const;
+ ACE_WChar_Codeset_Translator *wchar_translator (void) const;
+
+ /// Set the char codeset translator.
+ void char_translator (ACE_Char_Codeset_Translator *);
+ /// Set the wchar codeset translator.
+ void wchar_translator (ACE_WChar_Codeset_Translator *);
+
+ /// set the global size of serialized wchars. This may be different
+ /// than the size of a wchar_t.
+ static void wchar_maxbytes (size_t max_bytes);
+
+ /// access the serialized size of wchars.
+ static size_t wchar_maxbytes (void);
+
+ /**
+ * 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 @a buf) the next position in the buffer aligned to
+ * @a size, it advances the Message_Block wr_ptr past the data
+ * (i.e., @a buf + @a size). If necessary it grows the Message_Block
+ * buffer. Sets the good_bit to false 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.
+ bool 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;
+
+ /// 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
+ void set_version (ACE_CDR::Octet major, ACE_CDR::Octet minor);
+
+ /// Set the underlying GIOP version..
+ void get_version (ACE_CDR::Octet &major, ACE_CDR::Octet &minor);
+
+private:
+
+ // Find the message block in the chain of message blocks
+ // that the provide location locates.
+ ACE_Message_Block* find (char* loc);
+
+ /// 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 @a length elements, each of @a 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);
+
+
+ ACE_CDR::Boolean write_wchar_array_i (const ACE_CDR::WChar* x,
+ ACE_CDR::ULong length);
+
+
+ /**
+ * Grow the CDR stream. When it returns @a buf contains a pointer to
+ * memory in the CDR stream, with at least @a 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 where we are writing.
+ ACE_Message_Block *current_;
+
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ /**
+ * 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_;
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ /**
+ * 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.
+ */
+ bool current_is_writable_;
+
+ /**
+ * 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
+ * responsibility in the writers. THIS IS NOT A STANDARD IN CORBA,
+ * USE AT YOUR OWN RISK
+ */
+ bool do_byte_swap_;
+
+ /// Set to false when an error ocurrs.
+ bool good_bit_;
+
+ /// Break-even point for copying.
+ size_t const memcpy_tradeoff_;
+
+protected:
+ /// GIOP version information
+ ACE_CDR::Octet major_version_;
+ ACE_CDR::Octet minor_version_;
+
+ /// If not nil, invoke for translation of character and string data.
+ ACE_Char_Codeset_Translator *char_translator_;
+ ACE_WChar_Codeset_Translator *wchar_translator_;
+
+ /**
+ * Some wide char codesets may be defined with a maximum number
+ * of bytes that is smaller than the size of a wchar_t. This means
+ * that the CDR cannot simply memcpy a block of wchars to and from
+ * the stream, but must instead realign the bytes appropriately.
+ * In cases when wchar i/o is not allowed, such as with GIOP 1.0,
+ * or not having a native wchar codeset defined, the maxbytes is
+ * set to zero, indicating no wchar data is allowed.
+ */
+ static size_t wchar_maxbytes_;
+};
+
+
+// ****************************************************************
+
+/**
+ * @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
+ /**
+ * The alignment of the @arg data block is carried into the new
+ * ACE_InputCDR object. This constructor either increments the
+ * @arg data reference count, or copies the data (if it's a compound
+ * message block) so the caller can release the block immediately
+ * upon return.
+ */
+ 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,
+ ACE_Lock* lock = 0);
+
+ /// 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
+ {
+ explicit to_boolean (ACE_CDR::Boolean &b);
+ ACE_CDR::Boolean &ref_;
+ };
+
+ struct ACE_Export to_char
+ {
+ explicit to_char (ACE_CDR::Char &c);
+ ACE_CDR::Char &ref_;
+ };
+
+ struct ACE_Export to_wchar
+ {
+ explicit to_wchar (ACE_CDR::WChar &wc);
+ ACE_CDR::WChar &ref_;
+ };
+
+ struct ACE_Export to_octet
+ {
+ explicit to_octet (ACE_CDR::Octet &o);
+ ACE_CDR::Octet &ref_;
+ };
+
+ struct ACE_Export to_string
+ {
+ /**
+ * @deprecated 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 @c false on failure and @c true 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 @a x must be large enough to contain @a length
+ * elements.
+ * Return @c false on failure and @c true 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 @c false on failure and @c true 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 @c false on failure and @c true on success.
+ */
+ ACE_CDR::Boolean skip_wstring (void);
+ ACE_CDR::Boolean skip_string (void);
+
+ /// Skip @a n bytes in the CDR stream.
+ /**
+ * @return @c false on failure and @c true on success.
+ */
+ ACE_CDR::Boolean skip_bytes (size_t n);
+
+ /// returns @c false if a problem has been detected.
+ bool 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 @c rd_ptr to the first byte in
+ * the new buffer that is properly aligned, and set @c wr_ptr to @c
+ * rd_ptr @c + @c 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/her
+ * 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 @a 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 @a 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 @c cdr to this cdr and return the
+ /// data content (ie. the ACE_Data_Block) from this CDR to the
+ /// caller.
+ /**
+ * @note 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 @c rd_ptr.
+ char* rd_ptr (void);
+
+ /// Returns the current position for the @c 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 @a alignment-byte boundary.
+ * Argument MUST be a power of 2.
+ *
+ * @return 0 on success and -1 on failure.
+ */
+ int align_read_ptr (size_t alignment);
+
+ /// If @c true then this stream is writing in non-native byte order.
+ /// This is only meaningful if ACE_ENABLE_SWAP_ON_WRITE is defined.
+ bool do_byte_swap (void) const;
+
+ /// If @c do_byte_swap() returns @c false, 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;
+
+ /// Set the codeset translators.
+ void char_translator (ACE_Char_Codeset_Translator *);
+ void wchar_translator (ACE_WChar_Codeset_Translator *);
+
+ /**
+ * Returns (in @a buf) the next position in the buffer aligned to
+ * @a size. It advances the Message_Block @c rd_ptr past the data
+ * (i.e., @c buf @c + @c size). Sets the good_bit to @c false 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);
+
+ /// Set the underlying GIOP version..
+ void set_version (ACE_CDR::Octet major, ACE_CDR::Octet minor);
+
+ /// Set the underlying GIOP version..
+ void get_version (ACE_CDR::Octet &major, ACE_CDR::Octet &minor);
+
+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.
+ bool do_byte_swap_;
+
+ /// set to @c false when an error occurs.
+ bool good_bit_;
+
+ /// The GIOP versions for this stream
+ ACE_CDR::Octet major_version_;
+ ACE_CDR::Octet minor_version_;
+
+ /// 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 @a length elements, each of @a 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);
+
+ /**
+ * On those occasions when the native codeset for wchar is smaller than
+ * the size of a wchar_t, such as using UTF-16 with a 4-byte wchar_t, a
+ * special form of reading the array is needed. Actually, this should be
+ * a default translator.
+ */
+ ACE_CDR::Boolean read_wchar_array_i (ACE_CDR::WChar * x,
+ ACE_CDR::ULong length);
+
+ /// Move the rd_ptr ahead by @a offset bytes.
+ void rd_ptr (size_t offset);
+
+ /// Points to the continuation field of the current message block.
+ char* end (void);
+};
+
+// ****************************************************************
+
+/**
+ * @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.
+ *
+ * Translators are reference counted. This allows for stateful as well
+ * as stateless translators. Stateless translators will be allocated
+ * once whereas CDR Streams own their own copy of a stateful translator.
+ */
+class ACE_Export ACE_Char_Codeset_Translator
+{
+public:
+ virtual ~ACE_Char_Codeset_Translator ();
+
+ /// 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&,
+ 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;
+
+ virtual ACE_CDR::ULong ncs () = 0;
+ virtual ACE_CDR::ULong tcs () = 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 @a length elements of size @a 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 @a length elements of size @a 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 @a buf will contain a contiguous area in the CDR stream
+ * that can hold @a 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, bool bit);
+
+ /// Obtain the CDR Stream's major & minor version values.
+ ACE_CDR::Octet major_version (ACE_InputCDR& input);
+ ACE_CDR::Octet minor_version (ACE_InputCDR& input);
+ ACE_CDR::Octet major_version (ACE_OutputCDR& output);
+ ACE_CDR::Octet minor_version (ACE_OutputCDR& output);
+};
+
+// ****************************************************************
+
+/**
+ * @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_WChar_Codeset_Translator ();
+
+ 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&,
+ 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;
+
+ virtual ACE_CDR::ULong ncs () = 0;
+ virtual ACE_CDR::ULong tcs () = 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 @a length elements of size @a 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 @a length elements of size @a 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 @a buf will contain a contiguous area in the CDR stream
+ * that can hold @a 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, bool bit);
+
+ /// Obtain the CDR Stream's major & minor version values.
+ ACE_CDR::Octet major_version (ACE_InputCDR& input);
+ ACE_CDR::Octet minor_version (ACE_InputCDR& input);
+ ACE_CDR::Octet major_version (ACE_OutputCDR& output);
+ ACE_CDR::Octet minor_version (ACE_OutputCDR& output);
+
+};
+
+// @@ 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);
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/CDR_Stream.inl"
+#else /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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);
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* __ACE_INLINE__ */
+
+#if defined (GEN_OSTREAM_OPS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// ostream insertion operators for debugging code generated from IDL. All
+// but these below are either in generated code itself or are unambiguous
+// primitive types.
+
+ACE_Export std::ostream& operator<< (std::ostream &os,
+ ACE_OutputCDR::from_boolean x);
+
+ACE_Export std::ostream& operator<< (std::ostream &os,
+ ACE_OutputCDR::from_char x);
+
+ACE_Export std::ostream& operator<< (std::ostream &os,
+ ACE_OutputCDR::from_wchar x);
+
+ACE_Export std::ostream& operator<< (std::ostream &os,
+ ACE_OutputCDR::from_octet x);
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* GEN_OSTREAM_OPS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CDR_STREAM_H */
diff --git a/ACE/ace/CDR_Stream.inl b/ACE/ace/CDR_Stream.inl
new file mode 100644
index 00000000000..9f13889237f
--- /dev/null
+++ b/ACE/ace/CDR_Stream.inl
@@ -0,0 +1,1700 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Memory.h"
+
+// ****************************************************************
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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_ (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_ (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_ (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_ (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_ = true;
+ ACE_CDR::mb_align (&this->start_);
+
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ this->current_alignment_ = 0;
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ // 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 * const cont = this->start_.cont ();
+ if (cont)
+ {
+ 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 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_boolean (ACE_CDR::Boolean x)
+{
+ return
+ static_cast<ACE_CDR::Boolean> (
+ this->write_octet (
+ x
+ ? static_cast<ACE_CDR::Octet> (1)
+ : static_cast<ACE_CDR::Octet> (0)));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_char (ACE_CDR::Char x)
+{
+ if (this->char_translator_ == 0)
+ {
+ ACE_CDR::Octet temp = static_cast<ACE_CDR::Octet> (x);
+ return this->write_1 (&temp);
+ }
+ return this->char_translator_->write_char (*this, x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_short (ACE_CDR::Short x)
+{
+ ACE_CDR::UShort temp = static_cast<ACE_CDR::UShort> (x);
+ return this->write_2 (&temp);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ushort (ACE_CDR::UShort x)
+{
+ return this->write_2 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_long (ACE_CDR::Long x)
+{
+ ACE_CDR::ULong temp = static_cast<ACE_CDR::ULong> (x);
+ return this->write_4 (&temp);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ulong (ACE_CDR::ULong x)
+{
+ return this->write_4 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_longlong (const ACE_CDR::LongLong &x)
+{
+ void const * const temp = &x;
+ return this->write_8 (reinterpret_cast<ACE_CDR::ULongLong const *> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ulonglong (const ACE_CDR::ULongLong &x)
+{
+ return this->write_8 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_float (ACE_CDR::Float x)
+{
+ void const * const temp = &x;
+ return this->write_4 (reinterpret_cast<ACE_CDR::ULong const *> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_double (const ACE_CDR::Double &x)
+{
+ void const * const temp = &x;
+ return this->write_8 (reinterpret_cast<ACE_CDR::ULongLong const *> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_longdouble (const ACE_CDR::LongDouble &x)
+{
+ return this->write_16 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_string (const ACE_CDR::Char *x)
+{
+ if (x)
+ {
+ ACE_CDR::ULong const len =
+ static_cast<ACE_CDR::ULong> (ACE_OS::strlen (x));
+ return this->write_string (len, x);
+ }
+
+ return this->write_string (0, 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_wstring (const ACE_CDR::WChar *x)
+{
+ if (x)
+ {
+ ACE_CDR::ULong const len =
+ static_cast<ACE_CDR::ULong> (ACE_OS::strlen (x));
+ return this->write_wstring (len, 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_)
+ return this->wchar_translator_->write_wchar_array (*this, x, length);
+
+ if (ACE_OutputCDR::wchar_maxbytes_ == 0)
+ {
+ errno = EACCES;
+ return (ACE_CDR::Boolean) (this->good_bit_ = false);
+ }
+
+ if (ACE_OutputCDR::wchar_maxbytes_ == sizeof (ACE_CDR::WChar))
+ return this->write_array (x,
+ sizeof (ACE_CDR::WChar),
+ sizeof (ACE_CDR::WChar) == 2
+ ? ACE_CDR::SHORT_ALIGN
+ : ACE_CDR::LONG_ALIGN,
+ length);
+ return this->write_wchar_array_i (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 bool
+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);
+
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ size_t const offset =
+ ACE_align_binary (this->current_alignment_, align)
+ - this->current_alignment_;
+
+ buf = this->current_->wr_ptr () + offset;
+#else
+ buf = this->current_->wr_ptr ();
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ char * const end = buf + size;
+
+ if (end <= this->current_->end () &&
+ end >= buf)
+ {
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ this->current_alignment_ += offset + size;
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+ 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 void
+ACE_OutputCDR::set_version (ACE_CDR::Octet major, ACE_CDR::Octet minor)
+{
+ this->major_version_ = major;
+ this->minor_version_ = minor;
+}
+
+ACE_INLINE void
+ACE_OutputCDR::get_version (ACE_CDR::Octet &major, ACE_CDR::Octet &minor)
+{
+ major = this->major_version_;
+ minor = this->minor_version_;
+}
+
+
+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 bool
+ACE_OutputCDR::do_byte_swap (void) const
+{
+ return this->do_byte_swap_;
+}
+
+ACE_INLINE int
+ACE_OutputCDR::byte_order (void) const
+{
+ if (this->do_byte_swap ())
+ return !ACE_CDR_BYTE_ORDER;
+ else
+ return ACE_CDR_BYTE_ORDER;
+}
+
+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
+{
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ return this->current_alignment_;
+#else
+ // Default value set to 0
+ return 0;
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+}
+
+ACE_INLINE int
+ACE_OutputCDR::align_write_ptr (size_t alignment)
+{
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ char *dummy;
+ return this->adjust (0, alignment, dummy);
+#else
+ ACE_UNUSED_ARG (alignment);
+ // A return value of -1 from this function is used
+ // to indicate failure, returning 0
+ return 0;
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+}
+
+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 void
+ACE_OutputCDR::char_translator (ACE_Char_Codeset_Translator * ctran)
+{
+ this->char_translator_ = ctran;
+}
+
+ACE_INLINE void
+ACE_OutputCDR::wchar_translator (ACE_WChar_Codeset_Translator * wctran)
+{
+ this->wchar_translator_ = wctran;
+}
+
+// ****************************************************************
+
+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 = 0;
+ (void) this->read_octet (tmp);
+ x = tmp ? true : false;
+ 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)
+ {
+ void *temp = &x;
+ return this->read_1 (reinterpret_cast<ACE_CDR::Octet*> (temp));
+ }
+ return this->char_translator_->read_char (*this, x);
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_short (ACE_CDR::Short &x)
+{
+ void *temp = &x;
+ return this->read_2 (reinterpret_cast<ACE_CDR::UShort*> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ushort (ACE_CDR::UShort &x)
+{
+ return this->read_2 (&x);
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_long (ACE_CDR::Long &x)
+{
+ void *temp = &x;
+ return this->read_4 (reinterpret_cast<ACE_CDR::ULong*> (temp));
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ulong (ACE_CDR::ULong &x)
+{
+ return this->read_4 (&x);
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_longlong (ACE_CDR::LongLong &x)
+{
+ void *temp = &x;
+ return this->read_8 (reinterpret_cast<ACE_CDR::ULongLong*> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ulonglong (ACE_CDR::ULongLong &x)
+{
+ return this->read_8 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_float (ACE_CDR::Float &x)
+{
+ void *temp = &x;
+ return this->read_4 (reinterpret_cast<ACE_CDR::ULong*> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_double (ACE_CDR::Double &x)
+{
+ void *temp = &x;
+ return this->read_8 (reinterpret_cast<ACE_CDR::ULongLong*> (temp));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_longdouble (ACE_CDR::LongDouble &x)
+{
+ return this->read_16 (&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 ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_OutputCDR::wchar_maxbytes_ > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ if (this->wchar_translator_ != 0)
+ return this->wchar_translator_->read_wchar_array (*this, x, length);
+ if (ACE_OutputCDR::wchar_maxbytes_ != sizeof (ACE_CDR::WChar))
+ return this->read_wchar_array_i (x, length);
+ return this->read_array (x,
+ sizeof (ACE_CDR::WChar),
+ sizeof (ACE_CDR::WChar) == 2
+ ? ACE_CDR::SHORT_ALIGN
+ : ACE_CDR::LONG_ALIGN,
+ 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 * ACE_CDR::OCTET_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::SHORT_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::SHORT_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::LONG_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::LONG_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::LONGLONG_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::LONGLONG_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::LONG_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::LONGLONG_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+
+ 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 * ACE_CDR::LONGDOUBLE_SIZE > this->length ())
+ {
+ this->good_bit_ = false;
+ return false;
+ }
+ return this->read_array (x,
+ ACE_CDR::LONGDOUBLE_SIZE,
+ ACE_CDR::LONGDOUBLE_ALIGN,
+ length);
+}
+
+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_char (void)
+{
+ return this->skip_octet (); // sizeof (Char) == sizeof (Octet)
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_boolean (void)
+{
+ return this->skip_octet () && this->good_bit_;
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_ushort (void)
+{
+ ACE_CDR::UShort x;
+ return this->read_2 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_short (void)
+{
+ return this->skip_ushort ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_ulong (void)
+{
+ ACE_CDR::ULong x;
+ return this->read_4 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_long (void)
+{
+ return this->skip_ulong (); // sizeof (Long) == sizeof (ULong)
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_ulonglong (void)
+{
+ ACE_CDR::ULongLong x;
+ return this->read_8 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_longlong (void)
+{
+ return this->skip_ulonglong (); // sizeof (LongLong) == sizeof (ULongLong)
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_float (void)
+{
+ return this->skip_ulong (); // sizeof(Float) == sizeof (ULong)
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_double (void)
+{
+ return this->skip_ulonglong (); // sizeof(Double) == sizeof (ULongLong)
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_longdouble (void)
+{
+ ACE_CDR::LongDouble x;
+ return this->read_16 (&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)
+{
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ buf = ACE_ptr_align_binary (this->rd_ptr (), align);
+#else
+ buf = this->rd_ptr ();
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ char * const end = buf + size;
+ if (end <= this->wr_ptr ())
+ {
+ this->start_.rd_ptr (end);
+ return 0;
+ }
+
+ this->good_bit_ = false;
+ return -1;
+#if defined (ACE_LACKS_CDR_ALIGNMENT)
+ ACE_UNUSED_ARG (align);
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+}
+
+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 bool
+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 (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Short x)
+{
+ os.write_short (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::UShort x)
+{
+ os.write_ushort (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Long x)
+{
+ os.write_long (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::ULong x)
+{
+ os.write_ulong (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::LongLong x)
+{
+ os.write_longlong (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::ULongLong x)
+{
+ os.write_ulonglong (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::LongDouble x)
+{
+ os.write_longdouble (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Float x)
+{
+ os.write_float (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Double x)
+{
+ os.write_double (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, const ACE_CDR::Char *x)
+{
+ os.write_string (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, const ACE_CDR::WChar *x)
+{
+ os.write_wstring (x);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+// The following use the helper classes
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_boolean x)
+{
+ (void) os.write_boolean (x.val_);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_char x)
+{
+ os.write_char (x.val_);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_wchar x)
+{
+ os.write_wchar (x.val_);
+ return (ACE_CDR::Boolean) os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_octet x)
+{
+ os.write_octet (x.val_);
+ return (ACE_CDR::Boolean) 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 = static_cast<ACE_CDR::ULong> (ACE_OS::strlen (x.val_));
+ }
+
+ os.write_string (len, x.val_);
+ return
+ (ACE_CDR::Boolean) (os.good_bit () && (!x.bound_ || 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 = static_cast<ACE_CDR::ULong> (ACE_OS::strlen (x.val_));
+ }
+
+ os.write_wstring (len, x.val_);
+ return
+ (ACE_CDR::Boolean) (os.good_bit () && (!x.bound_ || len <= x.bound_));
+}
+
+// ****************************************************************
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Char &x)
+{
+ return is.read_char (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Short &x)
+{
+ return is.read_short (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::UShort &x)
+{
+ return is.read_ushort (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>>(ACE_InputCDR &is, ACE_CDR::Long &x)
+{
+ return is.read_long (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::ULong &x)
+{
+ return is.read_ulong (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR& is, ACE_CDR::LongLong &x)
+{
+ return is.read_longlong (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR& is, ACE_CDR::ULongLong &x)
+{
+ return is.read_ulonglong (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR& is, ACE_CDR::LongDouble &x)
+{
+ return is.read_longdouble (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Float &x)
+{
+ return is.read_float (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Double &x)
+{
+ return is.read_double (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Char *&x)
+{
+ return is.read_string (x) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::WChar *&x)
+{
+ return is.read_wstring (x) && is.good_bit ();
+}
+
+// The following use the helper classes
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_boolean x)
+{
+ return is.read_boolean (x.ref_);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_char x)
+{
+ return is.read_char (x.ref_) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_wchar x)
+{
+ return is.read_wchar (x.ref_) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_octet x)
+{
+ return is.read_octet (x.ref_) && is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_string x)
+{
+ // check if the bounds are satisfied
+ return
+ (is.read_string (const_cast<char *&> (x.val_))
+ && is.good_bit ()
+ && (!x.bound_
+ || ACE_OS::strlen (x.val_) <= x.bound_));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_wstring x)
+{
+ // check if the bounds are satisfied
+ return
+ (is.read_wstring (const_cast<ACE_CDR::WChar *&> (x.val_))
+ && is.good_bit ()
+ && (!x.bound_
+ || ACE_OS::strlen (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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+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) : false;
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_string (ACE_InputCDR &stream)
+{
+ ACE_CDR::Char *x;
+ const ACE_CDR::Boolean flag =
+ (stream.read_string (x) ? this->write_string (x) : false);
+ delete [] x;
+ return flag;
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_wstring (ACE_InputCDR &stream)
+{
+ ACE_CDR::WChar *x;
+ const ACE_CDR::Boolean flag =
+ (stream.read_wstring (x) ? this->write_wstring (x) : false);
+ 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 bool
+ACE_InputCDR::do_byte_swap (void) const
+{
+ return this->do_byte_swap_;
+}
+
+ACE_INLINE int
+ACE_InputCDR::byte_order (void) const
+{
+ return this->do_byte_swap () ? !ACE_CDR_BYTE_ORDER : ACE_CDR_BYTE_ORDER;
+}
+
+ACE_INLINE int
+ACE_InputCDR::align_read_ptr (size_t alignment)
+{
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ char *buf = ACE_ptr_align_binary (this->rd_ptr (),
+ alignment);
+#else
+ char *buf = this->rd_ptr ();
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ if (buf <= this->wr_ptr ())
+ {
+ this->start_.rd_ptr (buf);
+ return 0;
+ }
+
+ this->good_bit_ = false;
+ return -1;
+}
+
+ACE_INLINE void
+ACE_InputCDR::set_version (ACE_CDR::Octet major, ACE_CDR::Octet minor)
+{
+ this->major_version_ = major;
+ this->minor_version_ = minor;
+}
+
+ACE_INLINE void
+ACE_InputCDR::get_version (ACE_CDR::Octet &major, ACE_CDR::Octet &minor)
+{
+ major = this->major_version_;
+ minor = this->minor_version_;
+}
+
+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 void
+ACE_InputCDR::char_translator (ACE_Char_Codeset_Translator * ctran)
+{
+ this->char_translator_ = ctran;
+}
+
+ACE_INLINE void
+ACE_InputCDR::wchar_translator (ACE_WChar_Codeset_Translator * wctran)
+{
+ this->wchar_translator_ = wctran;
+}
+
+// ****************************************************************
+
+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, bool bit)
+{
+ out.good_bit_ = bit;
+}
+
+ACE_INLINE ACE_CDR::Octet
+ACE_Char_Codeset_Translator::major_version (ACE_InputCDR& input)
+{
+ return input.major_version_;
+}
+
+ACE_INLINE ACE_CDR::Octet
+ACE_Char_Codeset_Translator::minor_version (ACE_InputCDR& input)
+{
+ return input.minor_version_;
+}
+
+ACE_INLINE ACE_CDR::Octet
+ACE_Char_Codeset_Translator::major_version (ACE_OutputCDR& output)
+{
+ return output.major_version_;
+}
+
+ACE_INLINE ACE_CDR::Octet
+ACE_Char_Codeset_Translator::minor_version (ACE_OutputCDR& output)
+{
+ return output.minor_version_;
+}
+
+// ****************************************************************
+
+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, bool bit)
+{
+ out.good_bit_ = bit;
+}
+
+ACE_INLINE ACE_CDR::Octet
+ACE_WChar_Codeset_Translator::major_version (ACE_InputCDR& input)
+{
+ return input.major_version_;
+}
+
+ACE_INLINE ACE_CDR::Octet
+ACE_WChar_Codeset_Translator::minor_version (ACE_InputCDR& input)
+{
+ return input.minor_version_;
+}
+
+ACE_INLINE ACE_CDR::Octet
+ACE_WChar_Codeset_Translator::major_version (ACE_OutputCDR& output)
+{
+ return output.major_version_;
+}
+
+ACE_INLINE ACE_CDR::Octet
+ACE_WChar_Codeset_Translator::minor_version (ACE_OutputCDR& output)
+{
+ return output.minor_version_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/CE_Screen_Output.cpp b/ACE/ace/CE_Screen_Output.cpp
new file mode 100644
index 00000000000..800cc1c0926
--- /dev/null
+++ b/ACE/ace/CE_Screen_Output.cpp
@@ -0,0 +1,158 @@
+// $Id$
+
+#include "ace/CE_Screen_Output.h"
+#if defined (ACE_HAS_WINCE)
+
+#include "ace/Log_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_CE_Screen_Output::ACE_CE_Screen_Output(HWND hEdit)
+: handler_(hEdit)
+, pFile_(0)
+{
+}
+
+ACE_CE_Screen_Output::ACE_CE_Screen_Output()
+: handler_(0)
+, pFile_(0)
+{
+}
+
+ACE_CE_Screen_Output::~ACE_CE_Screen_Output()
+{
+ if (pFile_ != 0) {
+ fclose(pFile_);
+ }
+}
+
+void ACE_CE_Screen_Output::log(ACE_Log_Record &log_record)
+{
+ ACE_TCHAR verbose_msg[ACE_Log_Record::MAXVERBOSELOGMSGLEN];
+ int result = log_record.format_msg (ACE_TEXT("WindozeCE"), // host name
+ 0, // verbose flag
+ verbose_msg);
+
+ if (result == 0)
+ {
+ verbose_msg[ ACE_OS::strlen(verbose_msg) - 1 ] = 0; // CE does not like '\n' by itself.
+ *this << verbose_msg << endl;
+ }
+}
+
+void ACE_CE_Screen_Output::SetOutputWindow(HWND hEdit)
+{
+ handler_ = hEdit;
+}
+
+void ACE_CE_Screen_Output::clear()
+{
+ SetWindowText(handler_, 0);
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (ACE_TCHAR* output)
+{
+ int length = GetWindowTextLength(handler_);
+ SendMessage(handler_, EM_SETSEL, length, length);
+ SendMessage(handler_, EM_REPLACESEL, 0, (LPARAM)output);
+
+ if (pFile_ != 0)
+ {
+ fwprintf(pFile_, L"%s", output);
+ }
+
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (const ACE_TCHAR* output)
+{
+ ACE_TCHAR* buffer = ACE_OS::strdup(output);
+ if (buffer != 0)
+ {
+ *this << buffer;
+ delete buffer;
+ }
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (ACE_ANTI_TCHAR* output)
+{
+ *this << ACE_TEXT_CHAR_TO_TCHAR(output);
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (const ACE_ANTI_TCHAR* output)
+{
+ *this << ACE_TEXT_CHAR_TO_TCHAR(output);
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (char output)
+{
+ *this << (int)output;
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (unsigned char output)
+{
+ *this << (int)output;
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (unsigned short output)
+{
+ ACE_TCHAR buffer[20];
+ wsprintf(buffer, ACE_TEXT("%u"), output);
+ *this << buffer;
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (int output)
+{
+ ACE_TCHAR buffer[20];
+ wsprintf(buffer, ACE_TEXT("%d"), output);
+ *this << buffer;
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (unsigned int output)
+{
+ ACE_TCHAR buffer[20];
+ wsprintf(buffer, ACE_TEXT("%du"), output);
+ *this << buffer;
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (float output)
+{
+ ACE_TCHAR buffer[20];
+ swprintf(buffer, ACE_TEXT("%f"), output);
+ *this << buffer;
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (long output)
+{
+ ACE_TCHAR buffer[20];
+ wsprintf(buffer, ACE_TEXT("%l"), output);
+ *this << buffer;
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (unsigned long output)
+{
+ ACE_TCHAR buffer[20];
+ wsprintf(buffer, ACE_TEXT("%lu"), output);
+ *this << buffer;
+ return *this;
+}
+
+ACE_CE_Screen_Output& ACE_CE_Screen_Output::operator << (FILE* pFile)
+{
+ pFile_ = pFile;
+ return *this;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif // ACE_HAS_WINCE
diff --git a/ACE/ace/CE_Screen_Output.h b/ACE/ace/CE_Screen_Output.h
new file mode 100644
index 00000000000..e3ca13de295
--- /dev/null
+++ b/ACE/ace/CE_Screen_Output.h
@@ -0,0 +1,109 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file CE_Screen_Output.h
+ *
+ * $Id$
+ *
+ * @author Si Mong Park <spark@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef ACE_CE_SCREEN_OUTPUT_H
+#define ACE_CE_SCREEN_OUTPUT_H
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_WINCE)
+
+#include "ace/Log_Msg_Callback.h"
+#include "ace/Log_Record.h"
+
+namespace
+{
+ const ACE_TCHAR endl[] = ACE_TEXT("\r\n");
+ const ACE_TCHAR tab[] = ACE_TEXT("\t");
+}
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_CE_Screen_Output
+ *
+ * @brief Replacement of text output for Windows CE.
+ *
+ * This class allows standard text output to be displayed on
+ * text window for Windows CE. Generally, all ACE output will
+ * go through under CE if and only if user uses WindozeCE
+ * implementation by using main_ce instead of main.
+ * Also, for the easier debugging purpose, object pointer of
+ * this class can be gotten from ACE_Log_Msg::msg_callback()
+ * and then can be used directly by user just like cout stream.
+ */
+class ACE_Export ACE_CE_Screen_Output : public ACE_Log_Msg_Callback
+{
+public:
+
+ ACE_CE_Screen_Output (HWND hEdit);
+
+ ACE_CE_Screen_Output (void);
+
+ virtual ~ACE_CE_Screen_Output();
+
+ /// Implementation of pure virtual function from ACE_Log_Msg_Callback.
+ virtual void log (ACE_Log_Record &log_record);
+
+ /// Interface to specify active window handle.
+ void SetOutputWindow (HWND hWnd);
+
+ void clear (void);
+
+ /// Stream insertion operator that performs actual print out.
+ /**
+ * @note This is the only one operator that performs output. All
+ * other perators convert the type and use this operator
+ * underneath.
+ */
+ ACE_CE_Screen_Output& operator << (ACE_TCHAR*);
+ ACE_CE_Screen_Output& operator << (const ACE_TCHAR*);
+
+ ACE_CE_Screen_Output& operator << (ACE_ANTI_TCHAR* output);
+ ACE_CE_Screen_Output& operator << (const ACE_ANTI_TCHAR* output);
+
+ ACE_CE_Screen_Output& operator << (char output);
+ ACE_CE_Screen_Output& operator << (unsigned char output);
+
+ ACE_CE_Screen_Output& operator << (unsigned short output);
+
+ ACE_CE_Screen_Output& operator << (int output);
+ ACE_CE_Screen_Output& operator << (unsigned int output);
+
+ ACE_CE_Screen_Output& operator << (float output);
+
+ ACE_CE_Screen_Output& operator << (long output);
+ ACE_CE_Screen_Output& operator << (unsigned long output);
+
+ ACE_CE_Screen_Output& operator << (FILE* pFile);
+
+private:
+
+ ACE_CE_Screen_Output (ACE_CE_Screen_Output&);
+
+private:
+
+ HWND handler_;
+
+ /// FILE pointer that used to save output to file. This class does
+ /// not own the file handler pointer.
+ FILE* pFile_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif // ACE_HAS_WINCE
+#endif // ACE_CE_SCREEN_OUTPUT_H
diff --git a/ACE/ace/CORBA_macros.h b/ACE/ace/CORBA_macros.h
new file mode 100644
index 00000000000..22ded9a54b3
--- /dev/null
+++ b/ACE/ace/CORBA_macros.h
@@ -0,0 +1,575 @@
+// -*- C++ -*-
+
+// ============================================================================
+/**
+ * @file CORBA_macros.h
+ *
+ * $Id$
+ *
+ * Writing code that is portable between platforms with or without
+ * native C++ exceptions is hard. The following macros offer some
+ * help on this task, mostly oriented to making the ORB code and the
+ * IDL generated code portable.
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ * @author Aniruddha Gokhale <gokhale@sahyadri.research.bell-labs.com>
+ * @author Carlos O'Ryan <coryan@uci.edu>, et al.
+ */
+// ============================================================================
+
+// Macros for handling CORBA exceptions.
+
+#ifndef ACE_CORBA_MACROS_H
+#define ACE_CORBA_MACROS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#define ACE_ENV_POLLUTE_NAMES
+
+#include "ace/Exception_Macros.h"
+
+// The Windows MFC exception mechanism requires that a caught CException
+// (including the CMemoryException in use here) be freed using its Delete()
+// method. Thus, when MFC is in use and we're catching exceptions as a result
+// of new(), the exception's Delete() method has to be called. No other
+// platform imposes this sort of restriction/requirement. The Windows
+// config stuff (at least for MSVC/MFC) defines a ACE_del_bad_alloc macro
+// that works with its ACE_bad_alloc macro to implement this cleanup
+// requirement. Since no other platform requires this, define it as
+// empty here.
+#if !defined (ACE_del_bad_alloc)
+# define ACE_del_bad_alloc
+#endif
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+
+// If you wish to you use these macros for emulating exceptions on
+// platforms which lack native exception support, you need to do the
+// following:
+// 1. Define a class Exception. You can name it as you please. This class
+// should be at the root of the inheritance hierarchy of all the
+// exceptions used in your application. It should define at a minimum
+// the following pure virtual methods:
+// a) _downcast () - Which allows narrowing of the base exception type to a
+// derived type.
+// b) _raise() - Which throws an exception of type Exception.
+//
+// Classes which derive from these should implement these operations.
+//
+// 2. Define a class Environment. You can name it as you please. This class
+// is an exception holder. This class is always on the stack. It should
+// support at a minimum the following methods:
+// a) exception() - Which returns the Exception held in the current
+// Environment.
+// b) exception (Exception* foo) - Which replaces/sets the Exception
+// held in the current Environment with foo.
+// b) clear() - Which resets a particular instance of Environment.
+// c) A copy constructor and an assignment operator.
+//
+// Note that the above description assumes that you use the following
+// macros only within a particular domain. For example, if your
+// application has to interoperate across domains, then you need to define
+// an exception adapter to translate exceptions from one domain to
+// exceptions in the other. Please refer to Stroustrup's book on how to do
+// this. If your use case is this complex, you would be better off with
+// going with native exceptions rather than emulated exceptions, though
+// the macros should still work if you defined your adapter class as
+// ACE_EXCEPTION_TYPE.
+
+
+// The following macros assume that an environment variable is passed
+// in/out of each function that can throw an exception. The type of the
+// environment variable is defined by ACE_ENV_TYPE.
+
+#if !defined (ACE_ENV_TYPE)
+# define ACE_ENV_TYPE CORBA::Environment
+#endif /* ACE_ENV_TYPE */
+
+// The name of the variable is defined by ACE_TRY_ENV. Below is the name
+// that we use by default. If you wish to change it you can redefine
+// ACE_TRY_ENV to change the default name. Also ACE_ADOPT_ENV allows the
+// use of non-standard name within a scope.
+
+#if !defined (ACE_TRY_ENV)
+# define ACE_TRY_ENV _ACE_CORBA_Environment_variable
+#endif /* ACE_TRY_ENV */
+
+// The base type of Exception from which all the other exception types are
+// derived. You can set this to any type as you please. By default, it is
+// set to CORBA::Exception.
+
+#if !defined (ACE_EXCEPTION_TYPE)
+# define ACE_EXCEPTION_TYPE CORBA::Exception
+#endif /* ACE_EXCEPTION_TYPE */
+
+// This method is used to get the default value of the Environment
+// variable. In the case of TAO, this variable is part of the TSS ORB
+// resources and the method TAO_default_environment() returns the
+// Environment variable.
+
+#if !defined (ACE_DEFAULT_GET_ENV_METHOD)
+# define ACE_DEFAULT_GET_ENV_METHOD TAO_default_environment
+#endif /* ACE_DEFAULT_GET_ENV_METHOD */
+
+// This is the exception caught by ACE_CATCHANY.
+#if !defined (ACE_ANY_EXCEPTION)
+# define ACE_ANY_EXCEPTION ex
+#endif /* ACE_ANY_EXCEPTION */
+
+// Declare a new environment variable on the stack. The type of the
+// environment variable is determined by ACE_ENV_TYPE.
+#if defined (ACE_USES_NATIVE_EXCEPTIONS)
+// Don't instantiate an emulated exception environment at all when
+// using native C++ exception support. It won't be used.
+# define ACE_DECLARE_NEW_ENV
+#else
+# define ACE_DECLARE_NEW_ENV \
+ ACE_ENV_TYPE ACE_TRY_ENV
+#endif /* ACE_USES_NATIVE_EXCEPTIONS */
+
+// Provided for backward compatibility purposes. Don't use it in new code.
+// Use the definition above along with defining ACE_ENV_TYPE.
+
+#if defined (ACE_ENV_POLLUTE_NAMES)
+# define ACE_DECLARE_NEW_CORBA_ENV ACE_DECLARE_NEW_ENV
+#endif /* ACE_ENV_POLLUTE_NAMES */
+
+#if defined (ACE_USES_NATIVE_EXCEPTIONS)
+// -----------------------------------------------------------------
+
+// Provided for backward compatibility purposes. Don't use it in new code.
+#if defined (ACE_ENV_POLLUTE_NAMES)
+# define ACE_ADOPT_CORBA_ENV(ENV)
+#endif /* ACE_ENV_POLLUTE_NAMES */
+
+#define ACE_ADOPT_ENV (ENV)
+
+// No need to check. Native exceptions handle the control flow
+// automatically when an exception occurs.
+# define ACE_CHECK
+
+// Used when the function requires a return value.
+# define ACE_CHECK_RETURN(RETV)
+
+// ACE_THROW_INT should not be used by the user.
+# define ACE_THROW_INT(EXCEPTION) \
+ throw EXCEPTION
+
+// Throwing an exception is easy. These two macros should _NOT_ be
+// used within try blocks.
+# define ACE_THROW(EXCEPTION) \
+ throw EXCEPTION
+
+// Throwing an exception when the function requires a return value.
+# define ACE_THROW_RETURN(EXCEPTION,RETV) \
+ throw EXCEPTION
+
+// For compilers with native exceptions, we can simply use try to try. ;-)
+// do {} while (0) is required to avoid compilation warnings.
+# define ACE_TRY \
+ do \
+ { \
+ try \
+ {
+# define ACE_TRY_NEW_ENV \
+ do \
+ { \
+ try \
+ {
+# define ACE_TRY_EX(LABEL) \
+ do \
+ { \
+ try \
+ {
+
+// No need to check for exceptions within try block for compilers with
+// native exceptions.
+# define ACE_TRY_CHECK
+# define ACE_TRY_CHECK_EX(LABEL)
+
+// Likewise, throwing exceptions within try blocks is easy.
+# define ACE_TRY_THROW(EXCEPTION) throw EXCEPTION
+# define ACE_TRY_THROW_EX(EXCEPTION,LABEL) throw EXCEPTION
+
+// Same thing for catch.
+# define ACE_CATCH(EXCEPTION,VAR) \
+ } \
+ catch (EXCEPTION & VAR) \
+ { \
+ ACE_UNUSED_ARG (VAR);
+
+# define ACE_CATCHANY \
+ ACE_CATCH(ACE_EXCEPTION_TYPE, ACE_ANY_EXCEPTION)
+
+# define ACE_CATCHALL \
+ } \
+ catch (...) \
+ {
+
+# if defined (ACE_HAS_DEPRECATED_ACE_RETHROW)
+# define ACE_RETHROW throw
+# endif /* ACE_HAS_DEPRECATED_ACE_RETHROW */
+
+// Rethrowing the exception from catch blocks.
+# define ACE_RE_THROW throw
+# define ACE_RE_THROW_EX(LABEL) throw
+
+// Close the catch block.
+# define ACE_ENDTRY \
+ } \
+ } while (0)
+
+#else /* ! ACE_USES_NATIVE_EXCEPTIONS */
+// -----------------------------------------------------------------
+
+// When handling compilers without native exceptions, things get a bit
+// hairy. Exceptions are simulated using ACE_ENV_TYPE. The trick here is to
+// make sure the flow-of-control can simulate the case when native
+// exceptions occur...
+
+#if defined (ACE_ENV_POLLUTE_NAMES)
+# define ACE_ADOPT_CORBA_ENV(ENV) ACE_ENV_TYPE &ACE_TRY_ENV = ENV
+#endif /* ACE_ENV_POLLUTE_NAMES */
+
+# define ACE_ADOPT_ENV(ENV) ACE_ENV_TYPE &ACE_TRY_ENV = ENV
+
+// Follow every statement that could throw exceptions with ACE_CHECK or
+// ACE_CHECK_RETURN. These two macros should _NOT_ be used within try
+// blocks. Use ACE_TRY_CHECK or ACE_TRY_CHECK_EX instead.
+# define ACE_CHECK \
+ if (ACE_TRY_ENV . exception () != 0) \
+ return
+// When function requires a return value
+# define ACE_CHECK_RETURN(RETV) \
+ if (ACE_TRY_ENV . exception () != 0) \
+ return RETV
+
+// ACE_THROW_INT should not be used by the user.
+# define ACE_THROW_INT(EXCEPTION) ACE_TRY_ENV.exception (new EXCEPTION)
+
+// Throwing exceptions will inevitably cause a return from the current
+// function. These two macros should _NOT_ be used within try blocks. Use
+// ACE_TRY_THROW or ACE_TRY_THROW_EX instead.
+# define ACE_THROW(EXCEPTION) \
+ do \
+ { \
+ ACE_TRY_ENV.exception (new EXCEPTION); \
+ return; \
+ } while (0)
+
+# define ACE_THROW_RETURN(EXCEPTION,RETV) \
+ do \
+ { \
+ ACE_TRY_ENV.exception (new EXCEPTION); \
+ return RETV; \
+ } while (0)
+
+// ACE_TRY sets up flags to control program flow. ACE_TRY_FLAG acts like a
+// one-shot flip-flop. When an exception occurs (detected using
+// ACE_TRY_CHECK,) ACE_TRY_FLAG will be reset and the control goes back
+// into ACE_TRY_LABEL. Since ACE_TRY_FLAG is reset, the try block won't get
+// executed again and the control proceeds to the following catch blocks.
+// ACE_EXCEPTION_NOT_CAUGHT flag is used to prevent catching an exception
+// twice. This macro assumes there's already an ACE_ENV_TYPE variable
+// ACE_TRY_ENV defined (which should be the case normally)
+# define ACE_TRY \
+ do { \
+ int ACE_TRY_FLAG = 1; \
+ int ACE_EXCEPTION_NOT_CAUGHT = 1; \
+ ACE_TRY_LABEL: \
+ if (ACE_TRY_FLAG) \
+ do {
+
+// ACE_TRY_NEW_ENV functions like the macro ACE_TRY but defines a new
+// ACE_ENV_TYPE variable ACE_TRY_ENV. It is most often used in the outer
+// most function where no ACE_TRY_ENV is available.
+# define ACE_TRY_NEW_ENV \
+ do { \
+ ACE_DECLARE_NEW_ENV;\
+ int ACE_TRY_FLAG = 1; \
+ int ACE_EXCEPTION_NOT_CAUGHT = 1; \
+ ACE_TRY_LABEL: \
+ if (ACE_TRY_FLAG) \
+ do {
+
+// ACE_TRY_EX works exactly like ACE_TRY macro except the label used in the
+// try block is customizable to avoid name clashing. It should be used when
+// nested try blocks or multiple try blocks are required, in the same
+// function.
+# define ACE_TRY_EX(LABEL) \
+ do { \
+ int ACE_TRY_FLAG = 1; \
+ int ACE_EXCEPTION_NOT_CAUGHT = 1; \
+ ACE_TRY_LABEL ## LABEL: \
+ if (ACE_TRY_FLAG) \
+ do {
+
+// Check for exceptions within try blocks.
+# define ACE_TRY_CHECK \
+ { \
+ if (ACE_TRY_ENV.exception () != 0) \
+ { \
+ ACE_TRY_FLAG = 0; \
+ goto ACE_TRY_LABEL; \
+ } \
+ }
+
+// Checking exception within EX try blocks.
+# define ACE_TRY_CHECK_EX(LABEL) \
+ { \
+ if (ACE_TRY_ENV.exception () != 0) \
+ { \
+ ACE_TRY_FLAG = 0; \
+ goto ACE_TRY_LABEL ## LABEL; \
+ } \
+ }
+
+// Throwing exception within TRY blocks.
+# define ACE_TRY_THROW(EXCEPTION) \
+ { \
+ ACE_TRY_ENV.exception (new EXCEPTION); \
+ ACE_TRY_FLAG = 0; \
+ goto ACE_TRY_LABEL; \
+ }
+
+# define ACE_TRY_THROW_EX(EXCEPTION,LABEL) \
+ { \
+ ACE_TRY_ENV.exception (new EXCEPTION); \
+ ACE_TRY_FLAG = 0; \
+ goto ACE_TRY_LABEL ## LABEL; \
+ }
+
+// When exceptions occur or try block finishes execution without exception,
+// control will continue in the catch block. This macro first checks if
+// there's any uncaught exception left. If all the conditions are met, we
+// have caught an exception. It then resets ACE_EXCEPTION_NOT_CAUGHT to
+// prevent subsequent catch blocks from catching the same exception again,
+// and extracts out the underlying exception in ACE_TRY_ENV. We also make a
+// copy of ACE_TRY_ENV in ACE_CAUGHT_ENV, in case we want to rethrow the
+// exception. ACE_TRY_ENV is cleared out after the exception is caught so
+// you should not use ACE_TRY_ENV within the catch block(You should use the
+// exception directly).
+# define ACE_CATCH(TYPE,VAR) \
+ } while (0); \
+ do \
+ if (ACE_TRY_ENV.exception () != 0 && ACE_EXCEPTION_NOT_CAUGHT && \
+ TYPE::_downcast(ACE_TRY_ENV.exception ()) != 0) \
+ { \
+ ACE_ENV_TYPE ACE_CAUGHT_ENV = ACE_TRY_ENV;\
+ ACE_EXCEPTION_NOT_CAUGHT = 0; \
+ TYPE &VAR = *TYPE::_downcast (ACE_CAUGHT_ENV.exception ()); \
+ ACE_UNUSED_ARG (VAR); \
+ ACE_TRY_ENV.clear ();
+
+// ACE_CATCHANY uses ACE_CATCH to catch all exceptions derived from
+// ACE_EXCEPTION_TYPE
+# define ACE_CATCHANY ACE_CATCH (ACE_EXCEPTION_TYPE, ACE_ANY_EXCEPTION)
+
+// Since there's no other exception for compilers without exception
+// support, we simply catch all ACE_EXCEPTION_TYPE exceptions for
+// ACE_CATCHALL.
+# define ACE_CATCHALL ACE_CATCHANY
+
+# if defined (ACE_HAS_DEPRECATED_ACE_RETHROW)
+# define ACE_RETHROW \
+ do \
+ ACE_TRY_ENV = ACE_CAUGHT_ENV; \
+ while (0)
+# endif /* ACE_HAS_DEPRECATED_ACE_RETHROW */
+
+// Rethrowing exception within catch blocks. Notice that we depend on the
+// ACE_CHECK/ACE_CHECK_RETURN following the ACE_ENDTRY, or ACE_TRY_CHECK/
+// ACE_TRY_CHECK_EX following the ACE_ENDTRY when the catch block is within
+// another try block, to do the "Right Thing[TM]."
+# define ACE_RE_THROW \
+ do {\
+ ACE_TRY_ENV = ACE_CAUGHT_ENV; \
+ goto ACE_TRY_LABEL; \
+ } while (0)
+# define ACE_RE_THROW_EX(LABEL) \
+ do {\
+ ACE_TRY_ENV = ACE_CAUGHT_ENV; \
+ goto ACE_TRY_LABEL ## LABEL; \
+ } while (0)
+
+// Close the try block. Since exceptions may not get caught, and exceptions
+// can also be rethrown from the catch block, it's always a good idea to
+// follow ACE_ENDTRY with ACE_CHECK or ACE_TRY_CHECK (depending on the
+// context.)
+# define ACE_ENDTRY \
+ } while (0); \
+ } while (0)
+
+#endif /* ! ACE_USES_NATIVE_EXCEPTIONS */
+
+#endif /* !ACE_LACKS_DEPRECATED_MACROS */
+
+// ACE_HAS_EXCEPTIONS is not the same as ACE_NEW_THROWS_EXCEPTIONS.
+#if defined(ACE_NEW_THROWS_EXCEPTIONS)
+
+# if defined (ACE_HAS_NEW_NOTHROW)
+
+# define ACE_NEW_THROW_EX(POINTER,CONSTRUCTOR,EXCEPTION) \
+ do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \
+ if (POINTER == 0) { throw EXCEPTION; } \
+ } while (0)
+
+# else
+
+# define ACE_NEW_THROW_EX(POINTER,CONSTRUCTOR,EXCEPTION) \
+ do { try { POINTER = new CONSTRUCTOR; } \
+ catch (ACE_bad_alloc) { ACE_del_bad_alloc throw EXCEPTION; } \
+ } while (0)
+
+# endif /* ACE_HAS_NEW_NOTHROW */
+
+#else /* ! ACE_NEW_THROWS_EXCEPTIONS */
+
+# define ACE_NEW_THROW_EX(POINTER,CONSTRUCTOR,EXCEPTION) \
+ do { POINTER = new CONSTRUCTOR; \
+ if (POINTER == 0) { throw EXCEPTION; } \
+ } while (0)
+
+#endif /* ACE_NEW_THROWS_EXCEPTIONS */
+
+# define ACE_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \
+ ACE_Guard< MUTEX > OBJ (LOCK); \
+ if (OBJ.locked () == 0) throw EXCEPTION;
+
+# define ACE_READ_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \
+ ACE_Read_Guard< MUTEX > OBJ (LOCK); \
+ if (OBJ.locked () == 0) throw EXCEPTION;
+
+# define ACE_WRITE_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \
+ ACE_Write_Guard< MUTEX > OBJ (LOCK); \
+ if (OBJ.locked () == 0) throw EXCEPTION;
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+
+//@{
+/**
+ * @name Native C++ exceptions portability macros.
+ *
+ * The following macros are used to write code portable between platforms
+ * with and without native C++ exception support. Their main goal is to
+ * hide the presence of the ACE_ENV_TYPE argument, but they collaborate
+ * with the ACE_TRY_* macros to emulate the try/catch blocks.
+ */
+
+/// Define a macro to emit code only when ACE_ENV_TYPE is used
+#if !defined (ACE_USES_NATIVE_EXCEPTIONS) || defined (ACE_ENV_BKWD_COMPAT)
+# define ACE_ENV_EMIT_CODE(X) X
+#else
+# define ACE_ENV_EMIT_CODE(X)
+#endif /* ACE_USES_NATIVE_EXCEPTIONS && ! ACE_ENV_BKWD_COMPAT */
+
+/// Another macro to emit code only when ACE_ENV_TYPE is used
+#if !defined (ACE_USES_NATIVE_EXCEPTIONS) || defined (ACE_ENV_BKWD_COMPAT)
+# define ACE_ENV_EMIT_CODE2(X,Y) X,Y
+#else
+# define ACE_ENV_EMIT_CODE2(X,Y)
+#endif /* ACE_USES_NATIVE_EXCEPTIONS && ! ACE_ENV_BKWD_COMPAT */
+
+/// Helper macro
+#define ACE_ENV_EMIT_DUMMY
+
+/// Declare a ACE_ENV_TYPE argument as the last argument of a
+/// function
+/**
+ * Normally this macro is used as follows:
+ *
+ * <CODE>void my_funct (int x, int y ACE_ENV_ARG_DECL);</CODE>
+ *
+ * Its purpose is to provide developers (and users) with a mechanism to
+ * write code that is portable to platforms with and without native C++
+ * exceptions.
+ */
+#define ACE_ENV_ARG_DECL \
+ ACE_ENV_EMIT_CODE2(ACE_ENV_EMIT_DUMMY, \
+ ACE_ENV_TYPE &ACE_TRY_ENV)
+
+/// Declare a ACE_ENV_TYPE argument with the default value obtained from
+/// the ORB/application.
+/**
+ * It is similar to ACE_ENV_ARG_DECL. The name of the default environment
+ * getter method needs to be changed when switching ORBs or when used with
+ * another application.
+ */
+#define ACE_ENV_ARG_DECL_WITH_DEFAULTS \
+ ACE_ENV_EMIT_CODE2(ACE_ENV_EMIT_DUMMY, \
+ ACE_ENV_TYPE &ACE_TRY_ENV = \
+ ACE_DEFAULT_GET_ENV_METHOD ())
+
+/// Declare a ACE_ENV_TYPE argument that is not used by the
+/// function definition.
+/**
+ * Similar to ACE_ENV_ARG_DECL, but the formal parameter name is dropped to
+ * avoid warnings about unused parameters
+ */
+#define ACE_ENV_ARG_DECL_NOT_USED \
+ ACE_ENV_EMIT_CODE2(ACE_ENV_EMIT_DUMMY, \
+ ACE_ENV_TYPE &)
+
+/// Declare a ACE_ENV_TYPE argument for methods that do not take any other
+/// parameters
+#define ACE_ENV_SINGLE_ARG_DECL \
+ ACE_ENV_EMIT_CODE(ACE_ENV_TYPE &ACE_TRY_ENV)
+
+/// Declare a ACE_ENV_TYPE argument with a default value for methods that
+/// do not take any other parameters. The name of the default environment
+/// getter method needs to be changed when switching ORBs or when used in
+/// another application.
+#define ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS \
+ ACE_ENV_EMIT_CODE(ACE_ENV_TYPE &ACE_TRY_ENV = \
+ ACE_DEFAULT_GET_ENV_METHOD ())
+
+/// Declare a ACE_ENV_TYPE argument for methods which don't use it.
+#define ACE_ENV_SINGLE_ARG_DECL_NOT_USED \
+ ACE_ENV_EMIT_CODE(ACE_ENV_TYPE &)
+
+/// Use the ACE_ENV_TYPE argument in a nested call
+#define ACE_ENV_ARG_PARAMETER \
+ ACE_ENV_EMIT_CODE2(ACE_ENV_EMIT_DUMMY, \
+ ACE_TRY_ENV)
+
+/// Use the ACE_ENV_TYPE argument in a nested call, assuming that the
+/// called function takes only the ACE_TRY_ENV argument.
+#define ACE_ENV_SINGLE_ARG_PARAMETER \
+ ACE_ENV_EMIT_CODE(ACE_TRY_ENV)
+
+/// Eliminate unused argument warnings about ACE_TRY_ENV
+#define ACE_ENV_ARG_NOT_USED \
+ ACE_ENV_EMIT_CODE(ACE_UNUSED_ARG(ACE_TRY_ENV))
+//@}
+
+#if !defined (ACE_USES_NATIVE_EXCEPTIONS)
+// This thing can be moved above when we drop ACE_ENV_BKWD_COMPAT.
+# define ACE_ENV_RAISE(ex) ACE_TRY_ENV.exception (ex)
+#else
+# define ACE_ENV_RAISE(ex) (ex)->_raise ()
+#endif /* ACE_USES_NATIVE_EXCEPTIONS */
+
+// ============================================================
+
+// Print out a TAO exception. This is not CORBA compliant.
+# define ACE_PRINT_TAO_EXCEPTION(EX,INFO) \
+ EX._tao_print_exception (INFO)
+
+// Print out a CORBA exception. There is not portable way to
+// dump a CORBA exception. If you are using other ORB implementation,
+// redefine the macro to get what you want.
+# if !defined ACE_PRINT_EXCEPTION
+# define ACE_PRINT_EXCEPTION(EX,INFO) ACE_PRINT_TAO_EXCEPTION(EX,INFO)
+# endif /* ACE_PRINT_EXCEPTION */
+
+#endif /* !ACE_LACKS_DEPRECATED_MACROS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CORBA_MACROS_H */
diff --git a/ACE/ace/Cache_Map_Manager_T.cpp b/ACE/ace/Cache_Map_Manager_T.cpp
new file mode 100644
index 00000000000..b2526fcfa99
--- /dev/null
+++ b/ACE/ace/Cache_Map_Manager_T.cpp
@@ -0,0 +1,420 @@
+// $Id$
+
+#ifndef ACE_CACHE_MAP_MANAGER_T_CPP
+#define ACE_CACHE_MAP_MANAGER_T_CPP
+
+#include "ace/Cache_Map_Manager_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Log_Msg.h"
+#include "ace/Malloc_Base.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Cache_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Cache_Map_Manager)
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Cache_Map_Iterator)
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Cache_Map_Reverse_Iterator)
+
+#define ACE_T1 class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES
+#define ACE_T2 KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES
+
+template <ACE_T1>
+ACE_Cache_Map_Manager<ACE_T2>::ACE_Cache_Map_Manager (CACHING_STRATEGY &caching_s,
+ size_t size,
+ ACE_Allocator *alloc)
+ : caching_strategy_ (caching_s)
+{
+ if (this->open (size, alloc) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Cache_Map_Manager::ACE_Cache_Map_Manager")));
+
+}
+
+template <ACE_T1>
+ACE_Cache_Map_Manager<ACE_T2>::~ACE_Cache_Map_Manager (void)
+{
+ this->close ();
+}
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::open (size_t length,
+ ACE_Allocator *alloc)
+{
+ return this->map_.open (length,
+ alloc);
+}
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::close (void)
+{
+ return this->map_.close ();
+}
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::bind (const KEY &key,
+ const VALUE &value)
+{
+ // Insert an entry which has the <key> and the <cache_value> which
+ // is the combination of the <value> and the attributes of the
+ // caching strategy.
+ CACHE_VALUE cache_value (value,
+ this->caching_strategy_.attributes ());
+
+ int bind_result = this->map_.bind (key,
+ cache_value);
+
+ if (bind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_bind (bind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ {
+
+ this->map_.unbind (key);
+
+ // Unless the notification goes thru the bind operation is
+ // not complete.
+ bind_result = -1;
+
+ }
+
+ }
+
+ return bind_result;
+}
+
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::rebind (const KEY &key,
+ const VALUE &value)
+{
+ CACHE_VALUE cache_value (value,
+ this->caching_strategy_.attributes ());
+
+ int rebind_result = this->map_.rebind (key,
+ cache_value);
+
+ if (rebind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_rebind (rebind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ {
+
+ // Make sure the unbind operation is done only when the
+ // notification fails after a bind which is denoted by
+ // rebind_result = 0
+ if (rebind_result == 0)
+ this->map_.unbind (key);
+
+ // Unless the notification goes thru the rebind operation is
+ // not complete.
+ rebind_result = -1;
+
+ }
+
+ }
+
+ return rebind_result;
+}
+
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value)
+{
+ CACHE_VALUE cache_value (value,
+ this->caching_strategy_.attributes ());
+
+ CACHE_VALUE old_cache_value (old_value,
+ this->caching_strategy_.attributes ());
+
+ int rebind_result = this->map_.rebind (key,
+ cache_value,
+ old_cache_value);
+
+ if (rebind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_rebind (rebind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ {
+
+ // Make sure the unbind operation is done only when the
+ // notification fails after a bind which is denoted by
+ // rebind_result = 0
+ if (rebind_result == 0)
+ this->map_.unbind (key);
+
+ // Unless the notification goes thru the rebind operation is
+ // not complete.
+ rebind_result = -1;
+
+ }
+ else
+ {
+
+ old_value = old_cache_value.first ();
+
+ }
+
+ }
+
+ return rebind_result;
+}
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value)
+{
+ CACHE_VALUE cache_value (value,
+ this->caching_strategy_.attributes ());
+
+ CACHE_VALUE old_cache_value (old_value,
+ this->caching_strategy_.attributes ());
+
+ int rebind_result = this->map_.rebind (key,
+ cache_value,
+ old_key,
+ old_cache_value);
+
+ if (rebind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_rebind (rebind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ {
+
+ // Make sure the unbind operation is done only when the
+ // notification fails after a bind which is denoted by
+ // rebind_result = 0
+ if (rebind_result == 0)
+ this->map_.unbind (key);
+
+ // Unless the notification goes thru the rebind operation is
+ // not complete.
+ rebind_result = -1;
+
+ }
+ else
+ {
+
+ old_value = old_cache_value.first ();
+
+ }
+
+ }
+
+ return rebind_result;
+}
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::trybind (const KEY &key,
+ VALUE &value)
+{
+ CACHE_VALUE cache_value (value,
+ this->caching_strategy_.attributes ());
+
+ int trybind_result = this->map_.trybind (key,
+ cache_value);
+
+ if (trybind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_trybind (trybind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ {
+
+ // If the entry has got inserted into the map, it is removed
+ // due to failure.
+ if (trybind_result == 0)
+ this->map_.unbind (key);
+
+ trybind_result = -1;
+
+ }
+ else
+ {
+
+ // If an attempt is made to bind an existing entry the value
+ // is overwritten with the value from the map.
+ if (trybind_result == 1)
+ value = cache_value.first ();
+
+ }
+
+ }
+
+ return trybind_result;
+}
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::find (const KEY &key,
+ VALUE &value)
+{
+ // Lookup the key and populate the <value>.
+ CACHE_VALUE cache_value;
+
+ int find_result = this->map_.find (key,
+ cache_value);
+
+ if (find_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_find (find_result,
+ cache_value.second ());
+
+ // Unless the find and notification operations go thru, this
+ // method is not successful.
+ if (result == -1)
+ find_result = -1;
+ else
+ {
+
+ // Since the <cache_value> has now changed after the
+ // notification, we need to bind to the map again.
+ int rebind_result = this->map_.rebind (key,
+ cache_value);
+ if (rebind_result == -1)
+ find_result = -1;
+ else
+ value = cache_value.first ();
+
+ }
+
+ }
+
+ return find_result;
+}
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::find (const KEY &key)
+{
+ // Lookup the key and populate the <value>.
+ CACHE_VALUE cache_value;
+
+ int find_result = this->map_.find (key,
+ cache_value);
+
+ if (find_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_find (find_result,
+ cache_value.second ());
+
+ // Unless the find and notification operations go thru, this
+ // method is not successful.
+ if (result == -1)
+ find_result = -1;
+ else
+ {
+
+ // Since the <cache_value> has now changed after the
+ // notification, we need to bind to the map again.
+ int rebind_result = this->map_.rebind (key,
+ cache_value);
+
+ if (rebind_result == -1)
+ find_result = -1;
+
+ }
+
+ }
+
+ return find_result;
+}
+
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::unbind (const KEY &key)
+{
+ // Remove the entry from the cache.
+ CACHE_VALUE cache_value;
+
+ int unbind_result = this->map_.unbind (key,
+ cache_value);
+
+ if (unbind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_unbind (unbind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ unbind_result = -1;
+
+ }
+
+ return unbind_result;
+}
+
+template <ACE_T1> int
+ACE_Cache_Map_Manager<ACE_T2>::unbind (const KEY &key,
+ VALUE &value)
+{
+ // Remove the entry from the cache.
+ CACHE_VALUE cache_value;
+
+ int unbind_result = this->map_.unbind (key,
+ cache_value);
+
+ if (unbind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_unbind (unbind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ unbind_result = -1;
+ else
+ value = cache_value.first ();
+
+ }
+
+ return unbind_result;
+}
+
+template <ACE_T1> void
+ACE_Cache_Map_Manager<ACE_T2>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->map_.dump ();
+
+ this->caching_strategy_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+#undef ACE_T1
+#undef ACE_T2
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES>
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::~ACE_Cache_Map_Iterator (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_CACHE_MAP_MANAGER_T_CPP */
diff --git a/ACE/ace/Cache_Map_Manager_T.h b/ACE/ace/Cache_Map_Manager_T.h
new file mode 100644
index 00000000000..0c533f7a0ae
--- /dev/null
+++ b/ACE/ace/Cache_Map_Manager_T.h
@@ -0,0 +1,405 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Cache_Map_Manager_T.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CACHE_MAP_MANAGER_T_H
+#define ACE_CACHE_MAP_MANAGER_T_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/Default_Constants.h"
+#include "ace/Global_Macros.h"
+#include "ace/Pair_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration.
+class ACE_Allocator;
+
+#define ACE_Cache_Map_Iterator ACMI
+#define ACE_Cache_Map_Reverse_Iterator ACMRI
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES>
+class ACE_Cache_Map_Iterator;
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES>
+class ACE_Cache_Map_Reverse_Iterator;
+
+// For linkers that cant grok long names.
+#define ACE_Cache_Map_Manager ACMM
+
+/**
+ * @class ACE_Cache_Map_Manager
+ *
+ * @brief Defines a abstraction that will purge entries from a map.
+ *
+ * The <ACE_Cache_Map_Manager> will manage the map it contains
+ * and provide purging on demand from the map. The strategy for
+ * caching is decided by the user and provided to the Cache
+ * Manager. The Cache Manager acts as a agent and communicates
+ * between the Map and the Strategy for purging entries from the
+ * map.
+ * No locking mechanism provided since locking at this level
+ * isn't efficient. Locking has to be provided by the
+ * application.
+ */
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES>
+class ACE_Cache_Map_Manager
+{
+public:
+
+ // = Traits.
+ typedef KEY key_type;
+ typedef VALUE mapped_type;
+ typedef CMAP_TYPE map_type;
+ typedef CACHING_STRATEGY caching_strategy_type;
+
+ typedef ITERATOR_IMPL ITERATOR_IMPLEMENTATION;
+ typedef REVERSE_ITERATOR_IMPL REVERSE_ITERATOR_IMPLEMENTATION;
+
+ friend class ACE_Cache_Map_Iterator<KEY, VALUE, ITERATOR_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>;
+ friend class ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_ITERATOR_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>;
+
+ // = ACE-style iterator typedefs.
+ typedef ACE_Cache_Map_Iterator<KEY, VALUE, ITERATOR_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>
+ ITERATOR;
+ typedef ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_ITERATOR_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>
+ REVERSE_ITERATOR;
+
+ // = STL-style iterator typedefs.
+ typedef ITERATOR
+ iterator;
+ typedef REVERSE_ITERATOR
+ reverse_iterator;
+
+ /**
+ * The actual value mapped to the key in the map. The <attributes>
+ * are used by the strategy and is transparent to the user of this
+ * class.
+ */
+ typedef ACE_Pair<VALUE, ATTRIBUTES> CACHE_VALUE;
+
+ // = Initialization and termination methods.
+
+ /// Initialize a <Cache_Map_Manager> with <caching_strategy> and
+ /// @a size entries.
+ ACE_Cache_Map_Manager (CACHING_STRATEGY &caching_strategy,
+ size_t size = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a <Cache_Map_Manager> and release dynamically allocated
+ /// resources.
+ virtual ~ACE_Cache_Map_Manager (void);
+
+ /// Initialize a cache with size @a length.
+ int open (size_t length = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a cache and release dynamically allocated resources.
+ int close (void);
+
+ /**
+ * Associate @a key with @a value. If @a key is already in the CMAP_TYPE
+ * then the ENTRY is not changed. Returns 0 if a new entry is bound
+ * successfully, returns 1 if an attempt is made to bind an existing
+ * entry, and returns -1 if failures occur.
+ */
+ int bind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Lookup entry<key,value> in the cache. If it is not found, returns -1.
+ * If the @a key is located in the CMAP_TYPE object, the CACHING_STRATEGY is
+ * notified of it via notify_find (int result, ATTRIBUTES &attribute).
+ * If notify_find also returns 0 (success), then this function returns
+ * 0 (success) and sets the cached value in @a value.
+ */
+ int find (const KEY &key,
+ VALUE &value);
+
+ /**
+ * Lookup entry<key,value> in the cache. If it is not found, returns -1.
+ * If the @a key is located in the CMAP_TYPE object, the CACHING_STRATEGY is
+ * notified of it via notify_find (int result, ATTRIBUTES &attribute).
+ * If notify_find also returns 0 (success), then this function returns
+ * 0 (success).
+ */
+ int find (const KEY &key);
+
+ /**
+ * Reassociate the @a key with @a value. If the @a key already exists
+ * in the cache then returns 1, on a new bind returns 0 and returns
+ * -1 in case of any failures.
+ */
+ int rebind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old value into the
+ * "out" parameter @a old_value. The function fails if @a key is not
+ * in the cache for caches that do not allow user specified keys.
+ * However, for caches that allow user specified keys, if the key is
+ * not in the cache, a new @a key / @a value association is created.
+ */
+ int rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old key and value
+ * into the "out" parameters @a old_key and @a old_value. The
+ * function fails if @a key is not in the cache for caches that do
+ * not allow user specified keys. However, for caches that allow
+ * user specified keys, if the key is not in the cache, a new
+ * @a key / @a value association is created.
+ */
+ int rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value);
+
+ /**
+ * Associate @a key with @a value if and only if @a key is not in the
+ * cache. If @a key is already in the cache, then the @a value
+ * parameter is overwritten with the existing value in the
+ * cache. Returns 0 if a new @a key / @a value association is created.
+ * Returns 1 if an attempt is made to bind an existing entry. This
+ * function fails for maps that do not allow user specified keys.
+ */
+ int trybind (const KEY &key,
+ VALUE &value);
+
+ /// Remove @a key from the cache.
+ int unbind (const KEY &key);
+
+ /// Remove @a key from the cache, and return the @a value associated with
+ /// @a key.
+ int unbind (const KEY &key,
+ VALUE &value);
+
+ /// Remove entries from the cache depending upon the strategy.
+ int purge (void);
+
+ /// Return the current size of the cache.
+ size_t current_size (void) const;
+
+ /// Return the total size of the cache.
+ size_t total_size (void) const;
+
+ /// Dumps the state of the object.
+ void dump (void) const;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ ITERATOR begin (void);
+ ITERATOR end (void);
+
+ /// Return reverse iterator.
+ REVERSE_ITERATOR rbegin (void);
+ REVERSE_ITERATOR rend (void);
+
+ /// The map managed by the Cache_Map_Manager.
+ CMAP_TYPE &map (void);
+
+ /// The caching strategy used on the cache.
+ CACHING_STRATEGY &caching_strategy (void);
+
+protected:
+
+ /// The underlying map which needs to be cached.
+ CMAP_TYPE map_;
+
+ /// The strategy to be followed for caching entries in the map.
+ CACHING_STRATEGY &caching_strategy_;
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Cache_Map_Manager (const ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES> &))
+
+};
+
+/**
+ * @class ACE_Cache_Map_Iterator
+ *
+ * @brief Defines a iterator for the Cache_Map_Manager.
+ *
+ * Implementation to be provided by the iterator of the map
+ * managed by the ACE_Cache_Map_Manager.
+ */
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES>
+class ACE_Cache_Map_Iterator
+{
+
+public:
+
+ // = Traits.
+ /// The actual value mapped to the key in the cache. The <attributes>
+ /// are used by the strategy and is transperant to the cache user.
+ typedef ACE_Reference_Pair<KEY, VALUE>
+ value_type;
+ typedef ACE_Pair <VALUE, ATTRIBUTES>
+ CACHE_VALUE;
+
+ // = Initialisation and termination methods.
+
+ ACE_Cache_Map_Iterator (const IMPLEMENTATION &iterator_impl);
+
+ /// Copy constructor.
+ ACE_Cache_Map_Iterator (const ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs);
+
+ virtual ~ACE_Cache_Map_Iterator (void);
+
+ // = Iteration methods.
+
+ /// assignment operator.
+ ACE_Cache_Map_Iterator <KEY, VALUE, IMPLEMENTATION,
+ CACHING_STRATEGY, ATTRIBUTES> &operator=
+ (const ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION,
+ CACHING_STRATEGY, ATTRIBUTES> &rhs);
+
+ /// Comparision operators.
+ bool operator== (const ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs) const;
+ bool operator!= (const ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs) const;
+
+ /// Returns a reference to the internal element @c this is pointing
+ /// to.
+ ACE_Reference_Pair<KEY, VALUE> operator* (void) const;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance
+ ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> operator-- (int);
+
+ /// Returns the iterator of the internal map in the custody of the
+ /// Cache_Map_Manager.
+ IMPLEMENTATION &iterator_implementation (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// The actual iterator which iterates internally on the map
+ /// belonging to the Cache_Map_Manager.
+ IMPLEMENTATION iterator_implementation_;
+};
+
+/**
+ * @class ACE_Cache_Map_Reverse_Iterator
+ *
+ * @brief Defines a reverse iterator for the Cache_Map_Manager.
+ *
+ * Implementation to be provided by the reverse iterator of the map
+ * managed by thr Cache_Map_manager.
+ */
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES>
+class ACE_Cache_Map_Reverse_Iterator
+{
+public:
+
+ // = Traits.
+ /// The actual value mapped to the key in the cache. The <attributes>
+ /// are used by the strategy and is transperant to the cache user.
+ typedef ACE_Reference_Pair<KEY, VALUE> value_type;
+ typedef ACE_Pair <VALUE, ATTRIBUTES> CACHE_VALUE;
+
+ // = Initialisation and termination methods.
+
+ ACE_Cache_Map_Reverse_Iterator (const REVERSE_IMPLEMENTATION &iterator_impl);
+
+ /// Copy constructor.
+ ACE_Cache_Map_Reverse_Iterator (const ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs);
+
+ ~ACE_Cache_Map_Reverse_Iterator (void);
+
+ // = Iteration methods.
+
+ /// Assignment operator.
+ ACE_Cache_Map_Reverse_Iterator <KEY, VALUE, REVERSE_IMPLEMENTATION,
+ CACHING_STRATEGY, ATTRIBUTES> &operator=
+ (const ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION,
+ CACHING_STRATEGY, ATTRIBUTES> &rhs);
+
+ /// Comparision operators.
+ bool operator== (const ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs) const;
+ bool operator!= (const ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs) const;
+
+ /// Returns a reference to the internal element @c this is pointing
+ /// to.
+ ACE_Reference_Pair<KEY, VALUE> operator* (void) const;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance
+ ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> operator-- (int);
+
+ /// Returns the iterator of the internal map in the custody of the
+ /// Cache_Map_Manager.
+ REVERSE_IMPLEMENTATION &iterator_implementation (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// The actual iterator which iterates internally on the map
+ /// belonging to the Cache_Map_Manager.
+ REVERSE_IMPLEMENTATION reverse_iterator_implementation_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Cache_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Cache_Map_Manager_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Cache_Map_Manager_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CACHE_MAP_MANAGER_T_H */
diff --git a/ACE/ace/Cache_Map_Manager_T.inl b/ACE/ace/Cache_Map_Manager_T.inl
new file mode 100644
index 00000000000..ba30c528dd6
--- /dev/null
+++ b/ACE/ace/Cache_Map_Manager_T.inl
@@ -0,0 +1,245 @@
+// -*- C++ -*-
+//
+//$Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE int
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::purge (void)
+{
+ return this->caching_strategy ().caching_utility ().clear_cache (this->map_,
+ this->caching_strategy ().purge_percent ());
+}
+
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE size_t
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::current_size (void) const
+{
+ return this->map_.current_size ();
+}
+
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE size_t
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::total_size (void) const
+{
+ return this->map_.total_size ();
+}
+
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE CMAP_TYPE &
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::map (void)
+{
+ return this->map_;
+}
+
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE CACHING_STRATEGY &
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::caching_strategy (void)
+{
+ return this->caching_strategy_;
+}
+
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE ACE_Cache_Map_Iterator<KEY, VALUE, ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::begin (void)
+{
+ return ITERATOR (this->map_.begin ());
+}
+
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE ACE_Cache_Map_Iterator<KEY, VALUE, ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::end (void)
+{
+ return ITERATOR (this->map_.end ());
+}
+
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::rbegin (void)
+{
+ return REVERSE_ITERATOR (this->map_.rbegin ());
+}
+template <class KEY, class VALUE, class CMAP_TYPE, class ITERATOR_IMPL, class REVERSE_ITERATOR_IMPL, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>
+ACE_Cache_Map_Manager<KEY, VALUE, CMAP_TYPE, ITERATOR_IMPL, REVERSE_ITERATOR_IMPL, CACHING_STRATEGY, ATTRIBUTES>::rend (void)
+{
+ return REVERSE_ITERATOR (this->map_.rend ());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::ACE_Cache_Map_Iterator (const ACE_Cache_Map_Iterator <KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs)
+ : iterator_implementation_ (rhs.iterator_implementation_)
+{
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator= (const ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs)
+{
+ this->iterator_implementation_ = rhs.iterator_implementation_;
+ return *this;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE bool
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator== (const ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs) const
+{
+ return this->iterator_implementation_ == rhs.iterator_implementation_;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE bool
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator!= (const ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs) const
+{
+ return this->iterator_implementation_ != rhs.iterator_implementation_;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE ACE_Reference_Pair<KEY, VALUE>
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator* (void) const
+{
+ value_type retn ((*this->iterator_implementation_).ext_id_,
+ (*this->iterator_implementation_).int_id_.first ());
+ return retn;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator++ (void)
+{
+ ++this->iterator_implementation_;
+ return *this;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator++ (int)
+{
+ ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> retn = *this;
+ ++this->iterator_implementation_;
+ return retn;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator-- (void)
+{
+ --this->iterator_implementation_;
+ return *this;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator-- (int)
+{
+ ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> retn = *this;
+ --this->iterator_implementation_;
+ return retn;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE void
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->iterator_implementation_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::ACE_Cache_Map_Iterator (const IMPLEMENTATION &iterator_impl)
+ : iterator_implementation_ (iterator_impl)
+{
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE IMPLEMENTATION &
+ACE_Cache_Map_Iterator<KEY, VALUE, IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::iterator_implementation (void)
+{
+ return this->iterator_implementation_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::ACE_Cache_Map_Reverse_Iterator (const ACE_Cache_Map_Reverse_Iterator <KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs)
+ : reverse_iterator_implementation_ (rhs.reverse_iterator_implementation_)
+{
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::~ACE_Cache_Map_Reverse_Iterator (void)
+{
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator= (const ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs)
+{
+ this->reverse_iterator_implementation_ = rhs.reverse_iterator_implementation_;
+ return *this;
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE bool
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator== (const ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs) const
+{
+ return this->reverse_iterator_implementation_ == rhs.reverse_iterator_implementation_;
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE bool
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator!= (const ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &rhs) const
+{
+ return this->reverse_iterator_implementation_ != rhs.reverse_iterator_implementation_;
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE ACE_Reference_Pair<KEY, VALUE>
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator* (void) const
+{
+ value_type retv ((*this->reverse_iterator_implementation_).ext_id_,
+ (*this->reverse_iterator_implementation_).int_id_.first ());
+ return retv;
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator++ (void)
+{
+ ++this->reverse_iterator_implementation_;
+ return *this;
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator++ (int)
+{
+ ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> retn = *this;
+ ++this->reverse_iterator_implementation_;
+ return retn;
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> &
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator-- (void)
+{
+ --this->reverse_iterator_implementation_;
+ return *this;
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::operator-- (int)
+{
+ ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES> retn = *this;
+ --this->reverse_iterator_implementation_;
+ return retn;
+}
+
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE void
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->reverse_iterator_implementation_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::ACE_Cache_Map_Reverse_Iterator (const REVERSE_IMPLEMENTATION &iterator_impl)
+ : reverse_iterator_implementation_(iterator_impl)
+{
+}
+
+template <class KEY, class VALUE, class REVERSE_IMPLEMENTATION, class CACHING_STRATEGY, class ATTRIBUTES> ACE_INLINE REVERSE_IMPLEMENTATION &
+ACE_Cache_Map_Reverse_Iterator<KEY, VALUE, REVERSE_IMPLEMENTATION, CACHING_STRATEGY, ATTRIBUTES>::iterator_implementation (void)
+{
+ return this->reverse_iterator_implementation_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Cached_Connect_Strategy_T.cpp b/ACE/ace/Cached_Connect_Strategy_T.cpp
new file mode 100644
index 00000000000..5c4720b2085
--- /dev/null
+++ b/ACE/ace/Cached_Connect_Strategy_T.cpp
@@ -0,0 +1,734 @@
+//$Id$
+
+#ifndef ACE_CACHED_CONNECT_STRATEGY_T_CPP
+#define ACE_CACHED_CONNECT_STRATEGY_T_CPP
+
+#include "ace/Cached_Connect_Strategy_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/ACE.h"
+#include "ace/Service_Repository.h"
+#include "ace/Service_Types.h"
+#include "ace/Thread_Manager.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/Pair_T.h"
+
+#define ACE_T1 class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX
+#define ACE_T2 SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <ACE_T1>
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::ACE_Cached_Connect_Strategy_Ex
+(CACHING_STRATEGY &caching_s,
+ 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)
+ : CCSBASE (cre_s, con_s, rec_s, lock, delete_lock),
+ connection_cache_ (caching_s)
+{
+ if (this->open (cre_s, con_s, rec_s) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Cached_Connect_Strategy_Ex<ACE_T2>\n")));
+}
+
+template <ACE_T1>
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::~ACE_Cached_Connect_Strategy_Ex (void)
+{
+ cleanup ();
+}
+
+
+template <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::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>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&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_CACHE_ENTRY *possible_entry =
+ (CONNECTION_CACHE_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_.first ()->recycler (0, 0);
+ possible_entry->int_id_.first ()->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);
+
+ //
+ // Update the caching attributes directly since we don't do a
+ // find() on the cache map.
+ //
+
+ // Indicates successful find.
+ int find_result = 0;
+
+ int result = this->caching_strategy ().notify_find (find_result,
+ possible_entry->int_id_.second ());
+
+ if (result == -1)
+ return result;
+ }
+ 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 <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::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>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
+ int &found)
+{
+ 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.
+ while (this->find (search_addr, entry) != -1)
+ {
+ // We found a cached svc_handler.
+ // Get the cached <svc_handler>
+ sh = entry->int_id_.first ();
+
+ // Is the connection clean?
+ int state_result =
+ ACE::handle_ready (sh->peer ().get_handle (),
+ &ACE_Time_Value::zero,
+ 1, // read ready
+ 0, // write ready
+ 1);// exception ready
+
+ if (state_result == 1)
+ {
+
+ if (sh->close () == -1)
+ return -1;
+
+ sh = 0;
+
+ // Cycle it once again..
+ }
+ else if ((state_result == -1) && (errno == ETIME))
+ {
+ // Found!!!
+ // Set the flag
+ found = 1;
+
+ // Tell the <svc_handler> that it should prepare itself for
+ // being recycled.
+ if (this->prepare_for_recycling (sh) == -1)
+ return -1;
+
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ // Not found...
+
+ // 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;
+
+ // Connect using the svc_handler.
+ if (this->cached_connect (potential_handler,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms) == -1)
+ {
+ // Close the svc handler.
+ potential_handler->close (0);
+
+ return -1;
+ }
+ else
+ {
+ // Insert the new SVC_HANDLER instance into the cache.
+ if (this->connection_cache_.bind (search_addr,
+ potential_handler,
+ entry) == -1)
+ {
+ // Close the svc handler and reset <sh>.
+ 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);
+ }
+
+ return 0;
+}
+
+template <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cached_connect (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)
+{
+ // Actively establish the connection. This is a timed blocking
+ // connect.
+ if (this->new_connection (sh,
+ 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 == ETIMEDOUT)
+ errno = ENOTSUP;
+ else if (ACE::out_of_handles (errno) || errno == EADDRINUSE)
+ {
+ // If the connect failed due to the process running out of
+ // file descriptors then, auto_purging of some connections
+ // are done from the CONNECTION_CACHE. This frees the
+ // descriptors which get used in the connect process and
+ // hence the same method is called again!
+ if (this->purge_connections () == -1)
+ return -1;
+
+ // Try connecting again.
+ if (this->new_connection (sh,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms) == -1)
+ {
+ if (errno == EWOULDBLOCK || errno == ETIMEDOUT)
+ errno = ENOTSUP;
+ return -1;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ return 0;
+
+}
+
+
+template <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::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_CACHE_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;
+
+ // Increment the refcount
+ entry->ext_id_.increment ();
+ }
+
+ // 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);
+
+ return 0;
+}
+
+
+template <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cache_i (const void *recycling_act)
+{
+ // The wonders and perils of ACT
+ CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_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<ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::recycle_state_i (const void *recycling_act,
+ ACE_Recyclable_State new_state)
+{
+ // The wonders and perils of ACT
+ CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_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<ACE_T1> ACE_Recyclable_State
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::recycle_state_i (const void *recycling_act) const
+{
+ // The wonders and perils of ACT
+ CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_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 <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::purge_i (const void *recycling_act)
+{
+ // The wonders and perils of ACT
+ CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
+
+ return this->connection_cache_.unbind (entry);
+}
+
+
+template <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::mark_as_closed_i (const void *recycling_act)
+{
+ // The wonders and perils of ACT
+ CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *) recycling_act;
+
+ // Mark the <svc_handler> in the cache as CLOSED.
+ entry->ext_id_.recycle_state (ACE_RECYCLABLE_CLOSED);
+
+ return 0;
+}
+
+template <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::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_CACHE_ENTRY *entry = (CONNECTION_CACHE_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_.first ()->recycler (0, 0);
+ entry->int_id_.first ()->close ();
+ this->purge_i (entry);
+ }
+
+ return 0;
+}
+
+template <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::purge_connections (void)
+{
+ return this->connection_cache_.purge ();
+}
+
+template <ACE_T1> CACHING_STRATEGY &
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::caching_strategy (void)
+{
+ return this->connection_cache_.caching_strategy ();
+}
+
+template <ACE_T1> int
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::find (ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR> &search_addr,
+ ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry)
+{
+ typedef ACE_Hash_Map_Bucket_Iterator<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
+ ACE_Pair<SVC_HANDLER *, ATTRIBUTES>,
+ ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
+ ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
+ ACE_Null_Mutex>
+ CONNECTION_CACHE_BUCKET_ITERATOR;
+
+ CONNECTION_CACHE_BUCKET_ITERATOR iterator (this->connection_cache_.map (),
+ search_addr);
+
+ CONNECTION_CACHE_BUCKET_ITERATOR end (this->connection_cache_.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);
+
+ //
+ // Update the caching attributes directly since we don't do a
+ // find() on the cache map.
+ //
+
+ // Indicates successful find.
+ int find_result = 0;
+
+ int result = this->caching_strategy ().notify_find (find_result,
+ entry->int_id_.second ());
+
+ if (result == -1)
+ return result;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+template <ACE_T1> void
+ACE_Cached_Connect_Strategy_Ex<ACE_T2>::cleanup (void)
+{
+ // Excluded other threads from changing the cache while we cleanup
+ ACE_GUARD (MUTEX, ace_mon, *this->lock_);
+
+ // Close down all cached service handlers.
+ typename CONNECTION_CACHE::ITERATOR iter = this->connection_cache_.begin ();
+ while (iter != this->connection_cache_.end ())
+ {
+ if ((*iter).second () != 0)
+ {
+ // save entry for future use
+ CONNECTION_CACHE_ENTRY *entry = (CONNECTION_CACHE_ENTRY *)
+ (*iter).second ()->recycling_act ();
+
+ // close handler
+ (*iter).second ()->recycler (0, 0);
+ (*iter).second ()->close ();
+
+ // remember next iter
+ typename CONNECTION_CACHE::ITERATOR next_iter = iter;
+ ++next_iter;
+
+ // purge the item from the hash
+ this->purge_i (entry);
+
+ // assign next iter
+ iter = next_iter;
+ }
+ else
+ ++iter;
+ }
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Cached_Connect_Strategy_Ex)
+/////////////////////////////////////////////////////////////////////////
+
+template <ACE_T1>
+ACE_Bounded_Cached_Connect_Strategy<ACE_T2>::ACE_Bounded_Cached_Connect_Strategy
+(size_t max_size,
+ CACHING_STRATEGY &caching_s,
+ 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)
+ : CCSEBASE (caching_s, cre_s, con_s, rec_s, lock, delete_lock),
+ max_size_ (max_size)
+{
+}
+
+template <ACE_T1>
+ACE_Bounded_Cached_Connect_Strategy<ACE_T2>::~ACE_Bounded_Cached_Connect_Strategy(void)
+{
+}
+
+template <ACE_T1>
+int
+ACE_Bounded_Cached_Connect_Strategy<ACE_T2>::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>,
+ ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
+ int &found)
+{
+
+ 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.
+ while (this->find (search_addr, entry) != -1)
+ {
+ // We found a cached svc_handler.
+ // Get the cached <svc_handler>
+ sh = entry->int_id_.first ();
+
+ // Is the connection clean?
+ int state_result= ACE::handle_ready (sh->peer ().get_handle (),
+ &ACE_Time_Value::zero,
+ 1, // read ready
+ 0, // write ready
+ 1);// exception ready
+
+ if (state_result == 1)
+ {
+ // The connection was disconnected during idle.
+ // close the svc_handler down.
+ if (sh->close () == -1)
+ {
+ ACE_ASSERT (0);
+ return -1;
+ }
+ sh = 0;
+ // and rotate once more...
+ }
+ else if ((state_result == -1) && (errno == ETIME))
+ {
+ // Found!!!
+ // Set the flag
+ found = 1;
+
+ // Tell the <svc_handler> that it should prepare itself for
+ // being recycled.
+ if (this->prepare_for_recycling (sh) == -1)
+ {
+ ACE_ASSERT (0);
+ return -1;
+ }
+
+ return 0;
+ }
+ else // some other return value or error...
+ {
+ ACE_ASSERT (0); // just to see it coming
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t)ACE_Bounded_Cached_Connect_Strategy<>::")
+ ACE_TEXT ("find_or_create_svc_handler_i - ")
+ ACE_TEXT ("error polling server socket state.\n")));
+
+ return -1;
+ }
+ }
+
+ // Not found...
+
+ // Set the flag
+ found = 0;
+
+ // Check the limit of handlers...
+ if ((this->max_size_ > 0) &&
+ (this->connection_cache_.current_size () >= this->max_size_))
+ {
+ // Try to purge idle connections
+ if (this->purge_connections () == -1)
+ return -1;
+
+ // Check limit again.
+ if (this->connection_cache_.current_size () >= this->max_size_)
+ // still too much!
+ return -1;
+
+ // OK, we have room now...
+ }
+
+ // 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;
+
+ // Connect using the svc_handler.
+ if (this->cached_connect (potential_handler,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms) == -1)
+ {
+ // Close the svc handler.
+ potential_handler->close (0);
+ return -1;
+ }
+ else
+ {
+ // Insert the new SVC_HANDLER instance into the cache.
+ if (this->connection_cache_.bind (search_addr,
+ potential_handler,
+ entry) == -1)
+ {
+ // Close the svc handler and reset <sh>.
+ 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);
+ }
+
+ return 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Bounded_Cached_Connect_Strategy)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#undef ACE_T1
+#undef ACE_T2
+
+#endif /* ACE_CACHED_CONNECT_STRATEGY_T_CPP */
diff --git a/ACE/ace/Cached_Connect_Strategy_T.h b/ACE/ace/Cached_Connect_Strategy_T.h
new file mode 100644
index 00000000000..f5543727824
--- /dev/null
+++ b/ACE/ace/Cached_Connect_Strategy_T.h
@@ -0,0 +1,262 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Cached_Connect_Strategy_T.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef CACHED_CONNECT_STRATEGY_T_H
+#define CACHED_CONNECT_STRATEGY_T_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/Strategies_T.h"
+#include "ace/Hash_Cache_Map_Manager_T.h"
+#include "ace/Caching_Strategies_T.h"
+#include "ace/Functor_T.h"
+#include "ace/Pair_T.h"
+
+// For linkers which cant grok long names...
+#define ACE_Cached_Connect_Strategy_Ex ACCSE
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Cached_Connect_Strategy_Ex
+ *
+ * @brief A connection strategy which caches connections to peers
+ * (represented by SVC_HANDLER instances), thereby allowing
+ * subsequent re-use of unused, but available, connections.
+ *
+ * <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 and
+ * tweaking the role of the cache as per the caching strategy.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX>
+class ACE_Cached_Connect_Strategy_Ex
+ : public ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>
+{
+public:
+ /// Constructor
+ ACE_Cached_Connect_Strategy_Ex (
+ CACHING_STRATEGY &caching_s,
+ 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 *lock = 0,
+ int delete_lock = 0);
+
+ /// Destructor
+ virtual ~ACE_Cached_Connect_Strategy_Ex (void);
+
+ /// Explicit purging of connection entries from the connection cache.
+ virtual int purge_connections (void);
+
+ /// Mark as closed (non-locking version). This is used during the cleanup of the
+ /// connections purged.
+ virtual int mark_as_closed_i (const void *recycling_act);
+
+ /**
+ * Since g++ version < 2.8 arent happy with templates, this special
+ * method had to be devised to avoid memory leaks and perform
+ * cleanup of the <connection_cache_>.
+ */
+ void cleanup (void);
+
+ // = Typedefs for managing the map
+ typedef ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>
+ REFCOUNTED_HASH_RECYCLABLE_ADDRESS;
+ typedef ACE_Hash_Cache_Map_Manager<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
+ SVC_HANDLER *,
+ ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
+ ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
+ CACHING_STRATEGY,
+ ATTRIBUTES>
+ CONNECTION_CACHE;
+ typedef typename CONNECTION_CACHE::CACHE_ENTRY CONNECTION_CACHE_ENTRY;
+ typedef typename CONNECTION_CACHE::key_type KEY;
+ typedef typename CONNECTION_CACHE::mapped_type VALUE;
+
+ typedef ACE_Recyclable_Handler_Cleanup_Strategy<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
+ ACE_Pair<SVC_HANDLER *, ATTRIBUTES>,
+ ACE_Hash_Map_Manager_Ex<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
+ ACE_Pair<SVC_HANDLER *, ATTRIBUTES>,
+ ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
+ ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
+ MUTEX> >
+ CLEANUP_STRATEGY;
+
+ typedef ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>
+ CCSBASE;
+
+ // = Accessor.
+ CACHING_STRATEGY &caching_strategy (void);
+
+protected:
+
+ /// 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>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&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>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
+ int &found);
+
+ virtual 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>, ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&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);
+
+ /**
+ * Connection of the svc_handler with the remote host. This method
+ * also encapsulates the connection done with auto_purging under the
+ * hood. If the connect failed due to the process running out of
+ * file descriptors then, auto_purging of some connections are done
+ * from the CONNECTION_CACHE. This frees the descriptors which get
+ * used in the connect process and hence the connect operation can
+ * succeed.
+ */
+ virtual int cached_connect (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);
+
+ /// Table that maintains the cache of connected SVC_HANDLERs.
+ CONNECTION_CACHE connection_cache_;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+// For linkers which cant grok long names...
+#define ACE_Bounded_Cached_Connect_Strategy ABCCS
+
+/**
+ * @class ACE_Bounded_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.
+ * This strategy should be used when the cache is bounded by
+ * maximum size.
+ *
+ * <Bounded_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 and
+ * tweaking the role of the cache as per the caching strategy.
+ * Thanks to Edan Ayal <edana@bandwiz.com> for contributing this
+ * class and Susan Liebeskind <shl@janis.gtri.gatech.edu> for
+ * brainstorming about it.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1,
+ class CACHING_STRATEGY, class ATTRIBUTES,
+ class MUTEX>
+class ACE_Bounded_Cached_Connect_Strategy
+ : public ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>
+{
+
+ typedef ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>
+ CCSEBASE;
+
+ // = Typedefs for managing the map
+ typedef ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>
+ REFCOUNTED_HASH_RECYCLABLE_ADDRESS;
+
+public:
+
+ /// Constructor
+ ACE_Bounded_Cached_Connect_Strategy (size_t max_size,
+ CACHING_STRATEGY &caching_s,
+ 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 *lock = 0,
+ int delete_lock = 0);
+
+ /// Destructor
+ virtual ~ACE_Bounded_Cached_Connect_Strategy (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ virtual 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>,
+ ACE_Pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
+ int &found);
+
+protected:
+
+ /// max items in the cache, used as a bound for the creation of svc_handlers.
+ size_t max_size_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Cached_Connect_Strategy_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Cached_Connect_Strategy_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* CACHED_CONNECT_STRATEGY_T_H */
diff --git a/ACE/ace/Caching_Strategies_T.cpp b/ACE/ace/Caching_Strategies_T.cpp
new file mode 100644
index 00000000000..db2f9067ec9
--- /dev/null
+++ b/ACE/ace/Caching_Strategies_T.cpp
@@ -0,0 +1,59 @@
+//$Id$
+
+#ifndef ACE_CACHING_STRATEGIES_T_CPP
+#define ACECACHING_STRATEGIES_T_CPP
+
+#include "ace/Caching_Strategies_T.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Caching_Strategies_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_CACHING_STRATEGIES_T_CPP */
diff --git a/ACE/ace/Caching_Strategies_T.h b/ACE/ace/Caching_Strategies_T.h
new file mode 100644
index 00000000000..6d23824ba31
--- /dev/null
+++ b/ACE/ace/Caching_Strategies_T.h
@@ -0,0 +1,552 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Caching_Strategies_T.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CACHING_STRATEGIES_H
+#define ACE_CACHING_STRATEGIES_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include "ace/Caching_Utility_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# 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
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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;
+
+ /// Get the percentage of entries to purge.
+ virtual double purge_percent (void) = 0;
+
+ /// Set the percentage of entries to purge.
+ 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,
+ bool delete_implementation = false);
+
+ /// Destructor.
+ ~ACE_Caching_Strategy_Adapter (void);
+
+ /// Accessor method for the timer attributes.
+ ATTRIBUTES attributes (void);
+
+ /// Get the percentage of entries to purge.
+ double purge_percent (void);
+
+ /// Set the percentage of entries to purge.
+ 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?
+ bool 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);
+
+ /// Get the percentage of entries to purge.
+ double purge_percent (void);
+
+ /// Set the percentage of entries to purge.
+ 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);
+
+ /// Get the percentage of entries to purge.
+ double purge_percent (void);
+
+ /// Set the percentage of entries to purge.
+ 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);
+
+ /// Get the percentage of entries to purge.
+ double purge_percent (void);
+
+ /// Set the percentage of entries to purge.
+ 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);
+
+ /// Get the percentage of entries to purge.
+ double purge_percent (void);
+
+ /// Set the percentage of entries to purge.
+ 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Caching_Strategies_T.inl"
+#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 /* ACE_CACHING_STRATEGIES_H */
diff --git a/ACE/ace/Caching_Strategies_T.inl b/ACE/ace/Caching_Strategies_T.inl
new file mode 100644
index 00000000000..69f1ac99807
--- /dev/null
+++ b/ACE/ace/Caching_Strategies_T.inl
@@ -0,0 +1,456 @@
+// -*-C++-*-
+//
+//$Id$
+
+//////////////////////////////////////////////////////////////////////////////////
+
+#include "ace/OS_Memory.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::ACE_Caching_Strategy_Adapter (IMPLEMENTATION *implementation,
+ bool delete_implementation)
+ : implementation_ (implementation),
+ delete_implementation_ (delete_implementation)
+{
+ if (this->implementation_ == 0)
+ {
+ ACE_NEW (this->implementation_,
+ IMPLEMENTATION);
+ this->delete_implementation_ = true;
+ }
+}
+
+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_ = false;
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Caching_Strategy_Adapter::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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 */)
+{
+ 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 */)
+{
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_trybind (
+ int result,
+ ATTRIBUTES & /* 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 */)
+{
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_LRU_Caching_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("timer_ = %d "), this->timer_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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 */)
+{
+
+ 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 */)
+{
+ 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 */)
+{
+ 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 */)
+{
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_LFU_Caching_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FIFO_Caching_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("order_ = %d "), this->order_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Null_Caching_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+//////////////////////////////////////////////////////////////////////////////////
diff --git a/ACE/ace/Caching_Utility_T.cpp b/ACE/ace/Caching_Utility_T.cpp
new file mode 100644
index 00000000000..c8b7a48e807
--- /dev/null
+++ b/ACE/ace/Caching_Utility_T.cpp
@@ -0,0 +1,499 @@
+// $Id$
+
+#ifndef ACE_CACHING_UTILITY_T_CPP
+#define ACE_CACHING_UTILITY_T_CPP
+
+#include "ace/Caching_Utility_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Min_Max.h"
+#include "ace/OS_Memory.h"
+#include "ace/Recyclable.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Pair_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::ACE_Pair_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy,
+ int delete_cleanup_strategy)
+ : cleanup_strategy_ (cleanup_strategy),
+ delete_cleanup_strategy_ (delete_cleanup_strategy)
+{
+ if (cleanup_strategy == 0)
+ {
+ ACE_NEW (this->cleanup_strategy_,
+ CLEANUP_STRATEGY);
+ this->delete_cleanup_strategy_ = 1;
+ }
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Pair_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::~ACE_Pair_Caching_Utility (void)
+{
+ if (this->delete_cleanup_strategy_)
+ delete this->cleanup_strategy_;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> int
+ACE_Pair_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::clear_cache (CONTAINER &container,
+ double purge_percent)
+{
+ // Check that the purge_percent is non-zero.
+ if (purge_percent == 0)
+ return 0;
+
+ // Get the number of entries in the container.
+ size_t current_map_size = container.current_size ();
+
+ // Also whether the number of entries in the cache!
+ // Oops! then there is no way out but exiting. So return an error.
+ if (current_map_size == 0)
+ return 0;
+
+ // Calculate the no of entries to remove from the cache depending
+ // upon the <purge_percent>.
+ size_t const entries_to_remove
+ = ACE_MAX (static_cast<size_t> (1),
+ static_cast<size_t> (static_cast<double> (purge_percent)
+ / 100 * current_map_size));
+ KEY *key_to_remove = 0;
+ VALUE *value_to_remove = 0;
+
+ for (size_t i = 0; i < entries_to_remove ; ++i)
+ {
+ this->minimum (container,
+ key_to_remove,
+ value_to_remove);
+
+ // Simply verifying that the key is non-zero.
+ // This is important for strategies where the minimum
+ // entry cant be found due to constraints on the type of entry
+ // to remove.
+ if (key_to_remove == 0)
+ return 0;
+
+ if (this->cleanup_strategy_->cleanup (container,
+ key_to_remove,
+ value_to_remove) == -1)
+ return -1;
+
+ }
+
+ return 0;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> void
+ACE_Pair_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove)
+{
+ // Starting values.
+ ITERATOR iter = container.begin ();
+ ITERATOR end = container.end ();
+ ATTRIBUTES min = (*iter).int_id_.second ();
+ key_to_remove = &(*iter).ext_id_;
+ value_to_remove = &(*iter).int_id_;
+
+ // The iterator moves thru the container searching for the entry
+ // with the lowest ATTRIBUTES.
+ for (++iter;
+ iter != end;
+ ++iter)
+ {
+ if (min > (*iter).int_id_.second ())
+ {
+ // Ah! an item with lower ATTTRIBUTES...
+ min = (*iter).int_id_.second ();
+ key_to_remove = &(*iter).ext_id_;
+ value_to_remove = &(*iter).int_id_;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Recyclable_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::ACE_Recyclable_Handler_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy,
+ int delete_cleanup_strategy)
+ : cleanup_strategy_ (cleanup_strategy),
+ delete_cleanup_strategy_ (delete_cleanup_strategy)
+{
+ if (cleanup_strategy == 0)
+ {
+ ACE_NEW (this->cleanup_strategy_,
+ CLEANUP_STRATEGY);
+ this->delete_cleanup_strategy_ = 1;
+ }
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Recyclable_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::~ACE_Recyclable_Handler_Caching_Utility (void)
+{
+ if (this->delete_cleanup_strategy_)
+ delete this->cleanup_strategy_;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> int
+ACE_Recyclable_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::clear_cache (CONTAINER &container,
+ double purge_percent)
+{
+ // Check that the purge_percent is non-zero.
+ if (purge_percent == 0)
+ return 0;
+
+ // Get the number of entries in the container.
+ size_t current_map_size = container.current_size ();
+
+ // Also whether the number of entries in the cache is just one!
+ // Oops! then there is no way out but exiting. So return an error.
+ // if (current_map_size <= 1)
+ if (current_map_size == 0)
+ return 0;
+
+ // Calculate the no of entries to remove from the cache depending
+ // upon the <purge_percent>.
+ size_t const entries_to_remove
+ = ACE_MAX (static_cast<size_t> (1),
+ static_cast<size_t> (static_cast<double> (purge_percent)
+ / 100 * current_map_size));
+
+ KEY *key_to_remove = 0;
+ VALUE *value_to_remove = 0;
+
+ for (size_t i = 0; i < entries_to_remove ; ++i)
+ {
+ this->minimum (container,
+ key_to_remove,
+ value_to_remove);
+
+ // Simply verifying that the key is non-zero.
+ // This is important for strategies where the minimum
+ // entry cant be found due to constraints on the type of entry
+ // to remove.
+ if (key_to_remove == 0)
+ return 0;
+
+ if (this->cleanup_strategy_->cleanup (container,
+ key_to_remove,
+ value_to_remove) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> void
+ACE_Recyclable_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove)
+{
+ // Starting values.
+ ITERATOR end = container.end ();
+ ITERATOR iter = container.begin ();
+ ATTRIBUTES min = (*iter).int_id_.second ();
+ key_to_remove = 0;
+ value_to_remove = 0;
+ // Found the minimum entry to be purged?
+ int found = 0;
+
+ // The iterator moves thru the container searching for the entry
+ // with the lowest ATTRIBUTES.
+ for (;
+ iter != end;
+ ++iter)
+ {
+ // If the <min> entry isnt IDLE_AND_PURGABLE continue until you reach
+ // the first entry which can be purged. This is the minimum with
+ // which you will compare the rest of the purgable entries.
+ if ((*iter).ext_id_.recycle_state () == ACE_RECYCLABLE_IDLE_AND_PURGABLE ||
+ (*iter).ext_id_.recycle_state () == ACE_RECYCLABLE_PURGABLE_BUT_NOT_IDLE)
+ {
+ if (found == 0)
+ {
+ min = (*iter).int_id_.second ();
+ key_to_remove = &(*iter).ext_id_;
+ value_to_remove = &(*iter).int_id_;
+ found = 1;
+ }
+ else
+ {
+ // Ah! an entry with lower ATTTRIBUTES...
+ if (min > (*iter).int_id_.second ())
+ {
+ min = (*iter).int_id_.second ();
+ key_to_remove = &(*iter).ext_id_;
+ value_to_remove = &(*iter).int_id_;
+ }
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Refcounted_Recyclable_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::ACE_Refcounted_Recyclable_Handler_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy,
+ int delete_cleanup_strategy)
+ : cleanup_strategy_ (cleanup_strategy),
+ delete_cleanup_strategy_ (delete_cleanup_strategy),
+ marked_as_closed_entries_ (0)
+{
+ if (cleanup_strategy == 0)
+ {
+ ACE_NEW (this->cleanup_strategy_,
+ CLEANUP_STRATEGY);
+ this->delete_cleanup_strategy_ = 1;
+ }
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Refcounted_Recyclable_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::~ACE_Refcounted_Recyclable_Handler_Caching_Utility (void)
+{
+ if (this->delete_cleanup_strategy_)
+ delete this->cleanup_strategy_;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> int
+ACE_Refcounted_Recyclable_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::clear_cache (CONTAINER &container,
+ double purge_percent)
+{
+ // Check that the purge_percent is non-zero.
+ if (purge_percent == 0)
+ return 0;
+
+ // Get the number of entries in the container which can be considered for purging.
+ size_t const available_entries =
+ container.current_size () - this->marked_as_closed_entries_;
+
+ // Also whether the number of entries in the cache zero.
+ // Oops! then there is no way out but exiting.
+ if (available_entries <= 0)
+ return 0;
+
+ // Calculate the no of entries to remove from the cache depending
+ // upon the <purge_percent>.
+ size_t entries_to_remove
+ = ACE_MAX (static_cast<size_t> (1),
+ static_cast<size_t> (static_cast<double> (purge_percent)
+ / 100 * available_entries));
+
+ if (entries_to_remove >= available_entries || entries_to_remove == 0)
+ entries_to_remove = available_entries - 1;
+
+ KEY *key_to_remove = 0;
+ VALUE *value_to_remove = 0;
+
+ for (size_t i = 0; i < entries_to_remove ; ++i)
+ {
+ this->minimum (container,
+ key_to_remove,
+ value_to_remove);
+
+ // Simply verifying that the key is non-zero.
+ // This is important for strategies where the minimum
+ // entry cant be found due to constraints on the type of entry
+ // to remove.
+ if (key_to_remove == 0)
+ return 0;
+
+ if (this->cleanup_strategy_->cleanup (container,
+ key_to_remove,
+ value_to_remove) == -1)
+ return -1;
+
+ ++this->marked_as_closed_entries_;
+ }
+
+ return 0;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> void
+ACE_Refcounted_Recyclable_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove)
+{
+ // Starting values.
+ ITERATOR end = container.end ();
+ ITERATOR iter = container.begin ();
+ ATTRIBUTES min = (*iter).int_id_.second ();
+ key_to_remove = 0;
+ value_to_remove = 0;
+ // Found the minimum entry to be purged?
+ int found = 0;
+
+ // The iterator moves thru the container searching for the entry
+ // with the lowest ATTRIBUTES.
+ for (;
+ iter != end;
+ ++iter)
+ {
+ // If the <min> entry isnt IDLE_AND_PURGABLE continue until you reach
+ // the first entry which can be purged. This is the minimum with
+ // which you will compare the rest of the purgable entries.
+ if ((*iter).ext_id_.recycle_state () == ACE_RECYCLABLE_IDLE_AND_PURGABLE ||
+ (*iter).ext_id_.recycle_state () == ACE_RECYCLABLE_PURGABLE_BUT_NOT_IDLE)
+ {
+ if (found == 0)
+ {
+ min = (*iter).int_id_.second ();
+ key_to_remove = &(*iter).ext_id_;
+ value_to_remove = &(*iter).int_id_;
+ found = 1;
+ }
+ else
+ {
+ // Ah! an entry with lower ATTTRIBUTES...
+ if (min > (*iter).int_id_.second ())
+ {
+ min = (*iter).int_id_.second ();
+ key_to_remove = &(*iter).ext_id_;
+ value_to_remove = &(*iter).int_id_;
+ }
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::ACE_Handler_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy,
+ int delete_cleanup_strategy)
+ : cleanup_strategy_ (cleanup_strategy),
+ delete_cleanup_strategy_ (delete_cleanup_strategy)
+{
+ if (cleanup_strategy == 0)
+ {
+ ACE_NEW (this->cleanup_strategy_,
+ CLEANUP_STRATEGY);
+ this->delete_cleanup_strategy_ = 1;
+ }
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::~ACE_Handler_Caching_Utility (void)
+{
+ if (this->delete_cleanup_strategy_)
+ delete this->cleanup_strategy_;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> int
+ACE_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::clear_cache (CONTAINER &container,
+ double purge_percent)
+{
+ // Check that the purge_percent is non-zero.
+ if (purge_percent == 0)
+ return 0;
+
+ // Get the number of entries in the container.
+ size_t current_map_size = container.current_size ();
+
+ // Also whether the number of entries in the cache is just one!
+ // Oops! then there is no way out but exiting. So return an error.
+ if (current_map_size == 0)
+ return 0;
+
+ // Calculate the no of entries to remove from the cache depending
+ // upon the <purge_percent>.
+ size_t entries_to_remove
+ = ACE_MAX (static_cast<size_t> (1),
+ static_cast<size_t> (static_cast<double> (purge_percent)
+ / 100 * current_map_size));
+
+ KEY *key_to_remove = 0;
+ VALUE *value_to_remove = 0;
+
+ for (size_t i = 0; i < entries_to_remove ; ++i)
+ {
+ this->minimum (container,
+ key_to_remove,
+ value_to_remove);
+
+ if (this->cleanup_strategy_->cleanup (container,
+ key_to_remove,
+ value_to_remove) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> void
+ACE_Handler_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove)
+{
+ // Starting values.
+ ITERATOR iter = container.begin ();
+ ITERATOR end = container.end ();
+ ATTRIBUTES min = (*iter).int_id_->caching_attributes ();
+ key_to_remove = &(*iter).ext_id_;
+ value_to_remove = &(*iter).int_id_;
+
+ // The iterator moves thru the container searching for the entry
+ // with the lowest ATTRIBUTES.
+ for (++iter;
+ iter != end;
+ ++iter)
+ {
+ if (min > (*iter).int_id_->caching_attributes () &&
+ (*iter).int_id_->active () != 1)
+ {
+ // Ah! an item with lower ATTTRIBUTES...
+ min = (*iter).int_id_->caching_attributes ();
+ key_to_remove = &(*iter).ext_id_;
+ value_to_remove = &(*iter).int_id_;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Null_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::ACE_Null_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy,
+ int delete_cleanup_strategy)
+ : cleanup_strategy_ (cleanup_strategy),
+ delete_cleanup_strategy_ (delete_cleanup_strategy)
+{
+ if (cleanup_strategy == 0)
+ {
+ ACE_NEW (this->cleanup_strategy_,
+ CLEANUP_STRATEGY);
+ this->delete_cleanup_strategy_ = 1;
+ }
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+ACE_Null_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::~ACE_Null_Caching_Utility (void)
+{
+ if (this->delete_cleanup_strategy_)
+ delete this->cleanup_strategy_;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> int
+ACE_Null_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::clear_cache (CONTAINER &container,
+ double purge_percent)
+{
+ ACE_UNUSED_ARG (container);
+ ACE_UNUSED_ARG (purge_percent);
+
+ return 0;
+}
+
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES> void
+ACE_Null_Caching_Utility<KEY, VALUE, CONTAINER, ITERATOR, ATTRIBUTES>::minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove)
+{
+ ACE_UNUSED_ARG (container);
+ ACE_UNUSED_ARG (key_to_remove);
+ ACE_UNUSED_ARG (value_to_remove);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_CACHING_UTILITY_T_CPP */
diff --git a/ACE/ace/Caching_Utility_T.h b/ACE/ace/Caching_Utility_T.h
new file mode 100644
index 00000000000..1c1ce48894a
--- /dev/null
+++ b/ACE/ace/Caching_Utility_T.h
@@ -0,0 +1,347 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Caching_Utility_T.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CACHING_UTILITY_H
+#define ACE_CACHING_UTILITY_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/Global_Macros.h"
+#include "ace/Cleanup_Strategies_T.h"
+
+// For linkers that cant grok long names.
+#define ACE_Pair_Caching_Utility APUTIL
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Pair_Caching_Utility
+ *
+ * @brief Defines a helper class for the Caching Strategies.
+ *
+ * This class defines the methods commonly used by the different
+ * caching strategies. For instance: <clear_cache> method which
+ * decides and purges the entry from the container. @note This
+ * class helps in the caching_strategies using a container
+ * containing entries of <KEY, ACE_Pair<VALUE, attributes>>
+ * kind. The attributes helps in deciding the entries to be
+ * purged. The Cleanup_Strategy is the callback class to which the
+ * entries to be cleaned up will be delegated.
+ */
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+class ACE_Pair_Caching_Utility
+{
+public:
+
+ typedef ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY;
+
+ /// Constructor.
+ ACE_Pair_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy = 0,
+ int delete_cleanup_strategy = 0);
+
+ /// Destructor.
+ ~ACE_Pair_Caching_Utility (void);
+
+ /**
+ * Purge entries from the @a container. The Cleanup_Strategy will do the
+ * actual job of cleanup once the entries to be cleaned up are decided.
+ */
+ int clear_cache (CONTAINER &container,
+ double purge_percent);
+
+protected:
+
+ /// Find the entry with minimum caching attributes.
+ void minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove);
+
+ /// The cleanup strategy which can be used to destroy the entries of
+ /// the container.
+ CLEANUP_STRATEGY *cleanup_strategy_;
+
+ /// Whether the cleanup_strategy should be destroyed or not.
+ int delete_cleanup_strategy_;
+
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Pair_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Pair_Caching_Utility (const ACE_Pair_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+};
+
+////////////////////////////////////////////////////////////////////////////////
+#define ACE_Recyclable_Handler_Caching_Utility ARHUTIL
+
+/**
+ * @class ACE_Recyclable_Handler_Caching_Utility
+ *
+ * @brief Defines a helper class for the Caching Strategies.
+ *
+ * This class defines the methods commonly used by the different
+ * caching strategies. For instance: <clear_cache> method which
+ * decides and purges the entry from the container. @note This
+ * class helps in the caching_strategies using a container
+ * containing entries of <KEY, Svc_Handler> kind. The attributes
+ * helps in deciding the entries to be purged. The
+ * Cleanup_Strategy is the callback class to which the entries to
+ * be cleaned up will be delegated.
+ */
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+class ACE_Recyclable_Handler_Caching_Utility
+{
+
+public:
+
+ typedef ACE_Recyclable_Handler_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY;
+ typedef ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY_BASE;
+
+ /// Constructor.
+ ACE_Recyclable_Handler_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy = 0,
+ int delete_cleanup_strategy = 0);
+
+ /// Destructor.
+ ~ACE_Recyclable_Handler_Caching_Utility (void);
+
+ /**
+ * Purge entries from the <container>. The Cleanup_Strategy will do
+ * the actual job of cleanup once the entries to be cleaned up are
+ * decided.
+ */
+ int clear_cache (CONTAINER &container,
+ double purge_percent);
+
+protected:
+
+ /// Find the entry with minimum caching attributes.
+ void minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove);
+
+ /// This is the default Cleanup Strategy for this utility.
+ CLEANUP_STRATEGY_BASE *cleanup_strategy_;
+
+ /// Whether the cleanup_strategy should be destroyed or not.
+ int delete_cleanup_strategy_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Recyclable_Handler_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Recyclable_Handler_Caching_Utility (const ACE_Recyclable_Handler_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+};
+
+///////////////////////////////////////////////////////////////////////////
+#define ACE_Refcounted_Recyclable_Handler_Caching_Utility ARRHUTIL
+
+/**
+ * @class ACE_Refcounted_Recyclable_Handler_Caching_Utility
+ *
+ * @brief Defines a helper class for the Caching Strategies.
+ *
+ * This class defines the methods commonly used by the different
+ * caching strategies. For instance: clear_cache () method which
+ * decides and purges the entry from the container. @note This
+ * class helps in the caching_strategies using a container
+ * containing entries of <Refcounted_KEY,
+ * Recyclable_Connection_Handler> kind. The attributes helps in
+ * deciding the entries to be purged. The Cleanup_Strategy is the
+ * callback class to which the entries to be cleaned up will be
+ * delegated.
+ */
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+class ACE_Refcounted_Recyclable_Handler_Caching_Utility
+{
+
+public:
+
+ typedef ACE_Refcounted_Recyclable_Handler_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY;
+ typedef ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY_BASE;
+
+ /// Constructor.
+ ACE_Refcounted_Recyclable_Handler_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy = 0,
+ int delete_cleanup_strategy = 0);
+
+ /// Destructor.
+ ~ACE_Refcounted_Recyclable_Handler_Caching_Utility (void);
+
+ /**
+ * Purge entries from the <container>. The Cleanup_Strategy will do
+ * the actual job of cleanup once the entries to be cleaned up are
+ * decided.
+ */
+ int clear_cache (CONTAINER &container,
+ double purge_percent);
+
+protected:
+
+ /// Find the entry with minimum caching attributes.
+ void minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove);
+
+ /// This is the default Cleanup Strategy for this utility.
+ CLEANUP_STRATEGY_BASE *cleanup_strategy_;
+
+ /// Whether the cleanup_strategy should be destroyed or not.
+ int delete_cleanup_strategy_;
+
+ /**
+ * This figure denotes the number of entries are there in the
+ * container which have been marked as closed already but might
+ * not have been unbound from the container.
+ */
+ size_t marked_as_closed_entries_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Refcounted_Recyclable_Handler_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Refcounted_Recyclable_Handler_Caching_Utility (const ACE_Refcounted_Recyclable_Handler_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @class ACE_Handler_Caching_Utility
+ *
+ * @brief Defines a helper class for the Caching Strategies.
+ *
+ * This class defines the methods commonly used by the different
+ * caching strategies. For instance: <clear_cache> method which
+ * decides and purges the entry from the container. @note This
+ * class helps in the caching_strategies using a container
+ * containing entries of <KEY, HANDLER> kind where the HANDLER
+ * contains the caching attributes which help in deciding the
+ * entries to be purged. The Cleanup_Strategy is the callback
+ * class to which the entries to be cleaned up will be delegated.
+ */
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+class ACE_Handler_Caching_Utility
+{
+public:
+
+ typedef ACE_Handler_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY;
+ typedef ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY_BASE;
+
+ /// Constructor.
+ ACE_Handler_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy = 0,
+ int delete_cleanup_strategy = 0);
+
+ /// Destructor.
+ ~ACE_Handler_Caching_Utility (void);
+
+ /**
+ * Purge entries from the <container>. The Cleanup_Strategy will do
+ * the actual job of cleanup once the entries to be cleaned up are
+ * decided.
+ */
+ int clear_cache (CONTAINER &container,
+ double purge_percent);
+
+protected:
+
+ /**
+ * Find the entry with minimum caching attributes. This is handler
+ * specific since this utility is to be used very specifically for
+ * handler who have caching_attributes for server side acched
+ * connection management.
+ */
+ void minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove);
+
+ /// The cleanup strategy which can be used to destroy the entries of
+ /// the container.
+ CLEANUP_STRATEGY_BASE *cleanup_strategy_;
+
+ /// Whether the cleanup_strategy should be destroyed or not.
+ int delete_cleanup_strategy_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Handler_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Handler_Caching_Utility (const ACE_Handler_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+};
+
+///////////////////////////////////////////////////////////////////////////
+#define ACE_Null_Caching_Utility ANUTIL
+/**
+ * @class ACE_Null_Caching_Utility
+ *
+ * @brief Defines a dummy helper class for the Caching Strategies.
+ *
+ * This class defines the methods commonly used by the different
+ * caching strategies. For instance: <clear_cache> method which
+ * decides and purges the entry from the container. @note This
+ * class is be used with the Null_Caching_Strategy. The
+ * Cleanup_Strategy is the callback class to which the entries to
+ * be cleaned up will be delegated.
+ */
+template <class KEY, class VALUE, class CONTAINER, class ITERATOR, class ATTRIBUTES>
+class ACE_Null_Caching_Utility
+{
+public:
+
+ typedef ACE_Null_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY;
+ typedef ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> CLEANUP_STRATEGY_BASE;
+
+ /// Constructor.
+ ACE_Null_Caching_Utility (ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER> *cleanup_strategy = 0,
+ int delete_cleanup_strategy = 0);
+
+ /// Destructor.
+ ~ACE_Null_Caching_Utility (void);
+
+ /**
+ * Purge entries from the <container>. The Cleanup_Strategy will do
+ * the actual job of cleanup once the entries to be cleaned up are
+ * decided. @note Here it is a no-op.
+ */
+ int clear_cache (CONTAINER &container,
+ double purge_percent);
+
+protected:
+
+ /**
+ * Find the entry with minimum caching attributes. This is handler
+ * specific since this utility is to be used very specifically for
+ * handler who have caching_attributes for server side acched
+ * connection management.@note Here it is a no-op.
+ */
+ void minimum (CONTAINER &container,
+ KEY *&key_to_remove,
+ VALUE *&value_to_remove);
+
+ /// The cleanup strategy which can be used to destroy the entries of
+ /// the container.
+ CLEANUP_STRATEGY_BASE *cleanup_strategy_;
+
+ /// Whether the cleanup_strategy should be destroyed or not.
+ int delete_cleanup_strategy_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Null_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Null_Caching_Utility (const ACE_Null_Caching_Utility<KEY,VALUE,CONTAINER,ITERATOR,ATTRIBUTES> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Caching_Utility_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Caching_Utility_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CACHING_UTILITY_H */
diff --git a/ACE/ace/Capabilities.cpp b/ACE/ace/Capabilities.cpp
new file mode 100644
index 00000000000..04587194a77
--- /dev/null
+++ b/ACE/ace/Capabilities.cpp
@@ -0,0 +1,355 @@
+#include "ace/Capabilities.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Capabilities.inl"
+#endif /* !__ACE_INLINE__ */
+
+#include "ace/OS_NS_stdio.h"
+
+ACE_RCSID (ace,
+ Capabilities,
+ "$Id$")
+
+
+#define ACE_ESC ((ACE_TCHAR)0x1b)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_CapEntry::~ACE_CapEntry (void)
+{
+}
+
+ACE_Capabilities::ACE_Capabilities (void)
+ : caps_ ()
+{
+}
+
+ACE_Capabilities::~ACE_Capabilities (void)
+{
+ this->resetcaps ();
+}
+
+const ACE_TCHAR *
+ACE_Capabilities::parse (const ACE_TCHAR *buf, ACE_TString &cap)
+{
+ while (*buf != ACE_TEXT ('\0') && *buf != ACE_TEXT (','))
+ {
+ if (*buf == ACE_TEXT ('\\'))
+ {
+ ++buf;
+ if (*buf == ACE_TEXT ('E') || *buf == ACE_TEXT ('e'))
+ {
+ cap += ACE_ESC;
+ ++buf;
+ continue;
+ }
+ else if (*buf == ACE_TEXT ('r'))
+ {
+ cap += ACE_TEXT ('\r');
+ ++buf;
+ continue;
+ }
+ else if (*buf == ACE_TEXT ('n'))
+ {
+ cap += ACE_TEXT ('\n');
+ ++buf;
+ continue;
+ }
+ else if (*buf == ACE_TEXT ('t'))
+ {
+ cap += ACE_TEXT ('\t');
+ ++buf;
+ continue;
+ }
+ else if (*buf == ACE_TEXT ('\\'))
+ {
+ cap += *buf++;
+ continue;
+ }
+ if (ACE_OS::ace_isdigit(*buf))
+ {
+ // @@ UNICODE Does this work with unicode?
+ int oc = 0;
+ for (int i = 0;
+ i < 3 && *buf && ACE_OS::ace_isdigit (*buf);
+ i++)
+ oc = oc * 8 + (*buf++ - ACE_TEXT ('0'));
+
+ cap += (ACE_TCHAR) oc;
+ continue;
+ }
+ }
+ cap += *buf++;
+ }
+ return buf;
+}
+
+const ACE_TCHAR *
+ACE_Capabilities::parse (const ACE_TCHAR *buf, int &cap)
+{
+ int n = 0;
+
+ while (*buf && ACE_OS::ace_isdigit (*buf))
+ n = n * 10 + (*buf++ - ACE_TEXT ('0'));
+
+ cap = n;
+
+ return buf;
+}
+
+void
+ACE_Capabilities::resetcaps (void)
+{
+ for (CAPABILITIES_MAP::ITERATOR iter (this->caps_);
+ !iter.done ();
+ iter.advance ())
+ {
+ CAPABILITIES_MAP::ENTRY *entry = 0;
+ iter.next (entry);
+ delete entry->int_id_;
+ }
+
+ this->caps_.close ();
+ this->caps_.open ();
+}
+
+int
+ACE_Capabilities::fillent (const ACE_TCHAR *buf)
+{
+ this->resetcaps ();
+ while (*buf)
+ {
+ ACE_TString s;
+ int n;
+ ACE_TString name;
+ ACE_CapEntry *ce;
+
+ // Skip blanks
+ while (*buf && ACE_OS::ace_isspace(*buf)) buf++;
+ // If we get end of line return
+
+ if (*buf == ACE_TEXT ('\0'))
+ break;
+
+ if (*buf == ACE_TEXT ('#'))
+ {
+ while (*buf && *buf != ACE_TEXT ('\n'))
+ buf++;
+ if (*buf == ACE_TEXT ('\n'))
+ buf++;
+ continue;
+ }
+ while(*buf && *buf != ACE_TEXT ('=')
+ && *buf!= ACE_TEXT ('#')
+ && *buf != ACE_TEXT (','))
+ name += *buf++;
+
+ // If name is null.
+ switch (*buf)
+ {
+ case ACE_TEXT ('='):
+ // String property
+ buf = this->parse (buf + 1, s);
+ ACE_NEW_RETURN (ce,
+ ACE_StringCapEntry (s),
+ -1);
+ if (this->caps_.bind (name, ce) == -1)
+ {
+ delete ce;
+ return -1;
+ }
+ break;
+ case ACE_TEXT ('#'):
+ // Integer property
+ buf = this->parse (buf + 1, n);
+ ACE_NEW_RETURN (ce,
+ ACE_IntCapEntry (n),
+ -1);
+ if (this->caps_.bind (name, ce) == -1)
+ {
+ delete ce;
+ return -1;
+ }
+ break;
+ case ACE_TEXT (','):
+ // Boolean
+ ACE_NEW_RETURN (ce,
+ ACE_BoolCapEntry (1),
+ -1);
+ if (this->caps_.bind (name, ce) == -1)
+ {
+ delete ce;
+ return -1;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ if (*buf++ != ACE_TEXT (','))
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Capabilities::is_entry (const ACE_TCHAR *name, const ACE_TCHAR *line)
+{
+ for (;;)
+ {
+ // Skip blanks or irrelevant characters
+ while (*line && ACE_OS::ace_isspace(*line))
+ ++line;
+
+ // End of line reached
+ if (*line == ACE_TEXT ('\0'))
+ break;
+
+ // Build the entry name
+ ACE_TString nextname;
+ while (*line && *line != ACE_TEXT ('|') && *line != ACE_TEXT (','))
+ nextname += *line++;
+
+ // We have found the required entry?
+ if (ACE_OS::strcmp (nextname.c_str (), name) == 0)
+ return 1;
+
+ // Skip puntuaction char if neccesary.
+ if (*line == ACE_TEXT ('|') || *line == ACE_TEXT (','))
+ ++line;
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Invalid entry\n")));
+ break;
+ }
+ }
+ return 0;
+}
+
+int
+ACE_Capabilities::getline (FILE *fp, ACE_TString &line)
+{
+ int ch;
+
+ line.set (0, 0);
+
+ while ((ch = ACE_OS::fgetc (fp)) != EOF && ch != ACE_TEXT ('\n'))
+ line += (ACE_TCHAR) ch;
+
+ if (ch == EOF && line.length () == 0)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_Capabilities::getval (const ACE_TCHAR *keyname, ACE_TString &val)
+{
+ ACE_CapEntry* cap = 0;
+ if (this->caps_.find (keyname, cap) == -1)
+ return -1;
+
+ ACE_StringCapEntry *scap =
+ dynamic_cast<ACE_StringCapEntry *> (cap);
+ if (scap == 0)
+ return -1;
+
+ val = scap->getval ();
+ return 0;
+}
+
+int
+ACE_Capabilities::getval (const ACE_TCHAR *keyname, int &val)
+{
+ ACE_CapEntry *cap = 0;
+ if (this->caps_.find (keyname, cap) == -1)
+ return -1;
+
+ ACE_IntCapEntry *icap =
+ dynamic_cast<ACE_IntCapEntry *> (cap);
+ if (icap != 0)
+ {
+ val = icap->getval ();
+ return 0;
+ }
+
+ ACE_BoolCapEntry *bcap =
+ dynamic_cast<ACE_BoolCapEntry *> (cap);
+
+ if (bcap == 0)
+ return -1;
+
+ val = bcap->getval ();
+ return 0;
+}
+
+#if !defined (ACE_IS_SPLITTING)
+static int
+is_empty (const ACE_TCHAR *line)
+{
+ while (*line && ACE_OS::ace_isspace (*line))
+ ++line;
+
+ return *line == ACE_TEXT ('\0') || *line == ACE_TEXT ('#');
+}
+
+static int
+is_line (const ACE_TCHAR *line)
+{
+ while (*line && ACE_OS::ace_isspace (*line))
+ ++line;
+
+ return *line != ACE_TEXT ('\0');
+}
+#endif /* !ACE_IS_SPLITTING */
+
+int
+ACE_Capabilities::getent (const ACE_TCHAR *fname, const ACE_TCHAR *name)
+{
+ FILE *fp = ACE_OS::fopen (fname, ACE_TEXT ("r"));
+
+ if (fp == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Can't open %s file\n"),
+ fname),
+ -1);
+
+ int done;
+ ACE_TString line;
+
+ while (0 == (done = (this->getline (fp, line) == -1))
+ && is_empty (line.c_str ()))
+ continue;
+
+ while (!done)
+ {
+ ACE_TString newline;
+ ACE_TString description;
+
+ while (0 == (done = (this->getline (fp, newline) == -1)))
+ if (is_line (newline.c_str ()))
+ description += newline;
+ else
+ break;
+
+ if (this->is_entry (name, line.c_str()))
+ {
+ ACE_OS::fclose (fp);
+ return this->fillent (description.c_str ());
+ }
+
+ line = newline;
+ while (!done && is_empty (line.c_str ()))
+ done = this->getline (fp, line) == -1;
+ }
+
+ ACE_OS::fclose (fp);
+ return -1;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Capabilities.h b/ACE/ace/Capabilities.h
new file mode 100644
index 00000000000..4c26b9cb83a
--- /dev/null
+++ b/ACE/ace/Capabilities.h
@@ -0,0 +1,221 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Capabilities.h
+ *
+ * $Id$
+ *
+ * @author Arturo Montes <mitosys@colomsat.net.co>
+ */
+//=============================================================================
+
+
+#ifndef ACE_CAPABILITIES_H
+#define ACE_CAPABILITIES_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/Null_Mutex.h"
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Containers.h"
+#include "ace/SString.h"
+#include "ace/Functor_String.h"
+
+#if defined (ACE_IS_SPLITTING)
+# include "ace/OS_NS_ctype.h"
+#endif /* ACE_IS_SPLITTING */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_CapEntry
+ *
+ * @brief This class is the base class for all ACE Capabilities entry
+ * subclasses.
+ *
+ * This class is not instantiable and does not provide accessors
+ * or methods. If you want to add a new kind of attribute subclass
+ * this class and dynamic_cast to proper subclass.
+ */
+class ACE_Export ACE_CapEntry
+{
+public:
+
+ virtual ~ACE_CapEntry (void);
+
+protected:
+
+ enum
+ {
+ ACE_INTCAP = 0,
+ ACE_STRINGCAP = 1,
+ ACE_BOOLCAP = 2
+ };
+
+ ACE_CapEntry (int captype);
+
+protected:
+
+ int captype_;
+
+};
+
+/**
+ * @class ACE_IntCapEntry
+ *
+ * @brief This class implement the ACE Integer Capability subclass.
+ *
+ * This is a container class for ACE Capabilities integer container
+ * values.
+ */
+class ACE_Export ACE_IntCapEntry : public ACE_CapEntry
+{
+public:
+ ACE_IntCapEntry (int val);
+ int getval (void) const;
+
+protected:
+ int val_;
+};
+
+/**
+ * @class ACE_StringCapEntry
+ *
+ * @brief This class implement the ACE String Capability subclass.
+ *
+ * This is a container class for ACE Capabilities String container
+ * values.
+ */
+class ACE_Export ACE_StringCapEntry : public ACE_CapEntry
+{
+public:
+ ACE_StringCapEntry (const ACE_TString &val);
+ ACE_TString getval (void) const;
+
+protected:
+ ACE_TString val_;
+};
+
+/**
+ * @class ACE_BoolCapEntry
+ *
+ * @brief This class implement the ACE Bool Capability subclass.
+ *
+ * This is a container class for ACE Capabilities bool container
+ * values.
+ */
+class ACE_Export ACE_BoolCapEntry : public ACE_CapEntry
+{
+public:
+ ACE_BoolCapEntry (int val);
+ int getval (void) const;
+
+protected:
+ int val_;
+};
+
+/**
+ * @class ACE_Capabilities
+ *
+ * @brief This class implement the ACE Capabilities.
+ *
+ * This is a container class for ACE Capabilities
+ * values. Currently exist three different capability values:
+ * <ACE_IntCapEntry> (integer), <ACE_BoolCapEntry> (bool) and
+ * <ACE_StringCapEntry> (String). An ACE_Capabilities is a
+ * unordered set of pair = (<String>, <ACE_CapEntry> *). Where
+ * the first component is the name of capability and the second
+ * component is a pointer to the capability value container. A
+ * <FILE> is a container for ACE_Capabilities, the
+ * ACE_Capabilities has a name in the file, as a termcap file.
+ */
+class ACE_Export ACE_Capabilities
+{
+public:
+
+ typedef ACE_Hash_Map_Manager_Ex<ACE_TString, ACE_CapEntry *, ACE_Hash<ACE_TString>, ACE_Equal_To<ACE_TString>, ACE_Null_Mutex> CAPABILITIES_MAP;
+
+ /// The Constructor
+ ACE_Capabilities (void);
+
+ /// The Destructor
+ ~ACE_Capabilities(void);
+
+public:
+
+ /// Get a string entry.
+ int getval (const ACE_TCHAR *ent, ACE_TString &val);
+
+ /// Get an integer entry.
+ int getval (const ACE_TCHAR *ent, int &val);
+
+ /// Get the ACE_Capabilities name from FILE fname and load the
+ /// associated capabitily entries in map.
+ int getent (const ACE_TCHAR *fname, const ACE_TCHAR *name);
+
+protected:
+
+ /// Parse an integer property
+ const ACE_TCHAR *parse (const ACE_TCHAR *buf, int &cap);
+
+ /// Parse a string property
+ const ACE_TCHAR *parse (const ACE_TCHAR *buf, ACE_TString &cap);
+
+ /// Fill the ACE_Capabilities with description in ent.
+ int fillent(const ACE_TCHAR *ent);
+
+ /// Parse a cap entry
+ int parseent (const ACE_TCHAR *name, ACE_TCHAR *line);
+
+ /// Get a line from FILE input stream
+ int getline (FILE* fp,
+ ACE_TString &line);
+
+ /// Is a valid entry
+ int is_entry (const ACE_TCHAR *name, const ACE_TCHAR *line);
+
+ /// Reset the set of capabilities
+ void resetcaps (void);
+
+private:
+
+ /// This is the set of ACE_CapEntry.
+ CAPABILITIES_MAP caps_;
+
+};
+
+#if defined (ACE_IS_SPLITTING)
+int
+is_empty (const ACE_TCHAR *line)
+{
+ while (*line && ACE_OS::ace_isspace (*line))
+ ++line;
+
+ return *line == ACE_TEXT ('\0') || *line == ACE_TEXT ('#');
+}
+
+int
+is_line (const ACE_TCHAR *line)
+{
+ while (*line && ACE_OS::ace_isspace (*line))
+ ++line;
+
+ return *line != ACE_TEXT ('\0');
+}
+#endif /* ACE_IS_SPLITTING */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Capabilities.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* __ACE_CAPABILITIES_H__ */
diff --git a/ACE/ace/Capabilities.inl b/ACE/ace/Capabilities.inl
new file mode 100644
index 00000000000..053e0ecf7b6
--- /dev/null
+++ b/ACE/ace/Capabilities.inl
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_CapEntry::ACE_CapEntry (int captype)
+ : captype_ (captype)
+{
+}
+
+ACE_INLINE
+ACE_IntCapEntry::ACE_IntCapEntry (int val)
+ : ACE_CapEntry (ACE_INTCAP),
+ val_ (val)
+{
+}
+
+ACE_INLINE int
+ACE_IntCapEntry::getval (void) const
+{
+ return val_;
+}
+
+ACE_INLINE
+ACE_StringCapEntry::ACE_StringCapEntry (const ACE_TString &val)
+ : ACE_CapEntry (ACE_STRINGCAP),
+ val_ (val)
+{
+}
+
+ACE_INLINE ACE_TString
+ACE_StringCapEntry::getval (void) const
+{
+ return val_;
+}
+
+ACE_INLINE
+ACE_BoolCapEntry::ACE_BoolCapEntry (int val)
+ : ACE_CapEntry (ACE_BOOLCAP),
+ val_(val)
+{
+}
+
+ACE_INLINE int
+ACE_BoolCapEntry::getval (void) const
+{
+ return val_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Cleanup.cpp b/ACE/ace/Cleanup.cpp
new file mode 100644
index 00000000000..a6fc5de6a78
--- /dev/null
+++ b/ACE/ace/Cleanup.cpp
@@ -0,0 +1,192 @@
+// $Id$
+
+#include "ace/Cleanup.h"
+
+ACE_RCSID (ace,
+ Cleanup,
+ "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/Cleanup.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include "ace/OS_Memory.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Cleanup::cleanup (void *)
+{
+ delete this;
+}
+
+
+ACE_Cleanup::~ACE_Cleanup (void)
+{
+}
+
+/*****************************************************************************/
+
+extern "C" void
+ACE_CLEANUP_DESTROYER_NAME (ACE_Cleanup *object, void *param)
+{
+ object->cleanup (param);
+}
+
+/*****************************************************************************/
+
+ACE_Cleanup_Info::ACE_Cleanup_Info (void)
+ : object_ (0),
+ cleanup_hook_ (0),
+ param_ (0)
+{
+}
+
+bool
+ACE_Cleanup_Info::operator== (const ACE_Cleanup_Info &o) const
+{
+ return o.object_ == this->object_
+ && o.cleanup_hook_ == this->cleanup_hook_
+ && o.param_ == this->param_;
+}
+
+bool
+ACE_Cleanup_Info::operator!= (const ACE_Cleanup_Info &o) const
+{
+ return !(*this == o);
+}
+
+/*****************************************************************************/
+
+/**
+ * @class ACE_Cleanup_Info_Node
+ *
+ * @brief For maintaining a list of ACE_Cleanup_Info items.
+ *
+ * For internal use by ACE_Object_Manager.
+ */
+class ACE_Cleanup_Info_Node
+{
+public:
+ ACE_Cleanup_Info_Node (void);
+ ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info,
+ ACE_Cleanup_Info_Node *next);
+ ~ACE_Cleanup_Info_Node (void);
+ ACE_Cleanup_Info_Node *insert (const ACE_Cleanup_Info &);
+private:
+ ACE_Cleanup_Info cleanup_info_;
+ ACE_Cleanup_Info_Node *next_;
+
+ friend class ACE_OS_Exit_Info;
+};
+
+ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (void)
+ : cleanup_info_ (),
+ next_ (0)
+{
+}
+
+ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info,
+ ACE_Cleanup_Info_Node *next)
+ : cleanup_info_ (new_info),
+ next_ (next)
+{
+}
+
+ACE_Cleanup_Info_Node::~ACE_Cleanup_Info_Node (void)
+{
+ delete next_;
+}
+
+ACE_Cleanup_Info_Node *
+ACE_Cleanup_Info_Node::insert (const ACE_Cleanup_Info &new_info)
+{
+ ACE_Cleanup_Info_Node *new_node = 0;
+
+ ACE_NEW_RETURN (new_node,
+ ACE_Cleanup_Info_Node (new_info, this),
+ 0);
+
+ return new_node;
+}
+
+/*****************************************************************************/
+
+ACE_OS_Exit_Info::ACE_OS_Exit_Info (void)
+{
+ ACE_NEW (registered_objects_, ACE_Cleanup_Info_Node);
+}
+
+ACE_OS_Exit_Info::~ACE_OS_Exit_Info (void)
+{
+ delete registered_objects_;
+ registered_objects_ = 0;
+}
+
+int
+ACE_OS_Exit_Info::at_exit_i (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param)
+{
+ ACE_Cleanup_Info new_info;
+ new_info.object_ = object;
+ new_info.cleanup_hook_ = cleanup_hook;
+ new_info.param_ = param;
+
+ // Return -1 and sets errno if unable to allocate storage. Enqueue
+ // at the head and dequeue from the head to get LIFO ordering.
+
+ ACE_Cleanup_Info_Node *new_node = 0;
+
+ if ((new_node = registered_objects_->insert (new_info)) == 0)
+ return -1;
+ else
+ {
+ registered_objects_ = new_node;
+ return 0;
+ }
+}
+
+int
+ACE_OS_Exit_Info::find (void *object)
+{
+ // Check for already in queue, and return 1 if so.
+ for (ACE_Cleanup_Info_Node *iter = registered_objects_;
+ iter && iter->next_ != 0;
+ iter = iter->next_)
+ {
+ if (iter->cleanup_info_.object_ == object)
+ {
+ // The object has already been registered.
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void
+ACE_OS_Exit_Info::call_hooks (void)
+{
+ // Call all registered cleanup hooks, in reverse order of
+ // registration.
+ for (ACE_Cleanup_Info_Node *iter = registered_objects_;
+ iter && iter->next_ != 0;
+ iter = iter->next_)
+ {
+ ACE_Cleanup_Info &info = iter->cleanup_info_;
+ if (info.cleanup_hook_ == reinterpret_cast<ACE_CLEANUP_FUNC> (
+ ACE_CLEANUP_DESTROYER_NAME))
+ // The object is an ACE_Cleanup.
+ ACE_CLEANUP_DESTROYER_NAME (
+ reinterpret_cast<ACE_Cleanup *> (info.object_),
+ info.param_);
+ else if (info.object_ == &ace_exit_hook_marker)
+ // The hook is an ACE_EXIT_HOOK.
+ (* reinterpret_cast<ACE_EXIT_HOOK> (info.cleanup_hook_)) ();
+ else
+ (*info.cleanup_hook_) (info.object_, info.param_);
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Cleanup.h b/ACE/ace/Cleanup.h
new file mode 100644
index 00000000000..7acff23ab79
--- /dev/null
+++ b/ACE/ace/Cleanup.h
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Cleanup.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_CLEANUP_H
+# define ACE_CLEANUP_H
+
+# include /**/ "ace/pre.h"
+
+# include "ace/config-lite.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include /**/ "ace/ACE_export.h"
+
+#if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
+# include "ace/Global_Macros.h"
+# define ACE_CLEANUP_DESTROYER_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ace_cleanup_destroyer)
+#else
+# define ACE_CLEANUP_DESTROYER_NAME ace_cleanup_destroyer
+#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Cleanup
+ *
+ * @brief Base class for objects that are cleaned by ACE_Object_Manager.
+ */
+class ACE_Export ACE_Cleanup
+{
+public:
+ /// No-op constructor.
+ ACE_Cleanup (void);
+
+ /// Destructor.
+ virtual ~ACE_Cleanup (void);
+
+ /// Cleanup method that, by default, simply deletes itself.
+ virtual void cleanup (void *param = 0);
+};
+
+// Adapter for cleanup, used by ACE_Object_Manager.
+extern "C" ACE_Export
+void ACE_CLEANUP_DESTROYER_NAME (ACE_Cleanup *, void *param = 0);
+
+/**
+ * @class ACE_Cleanup_Info
+ *
+ * @brief Hold cleanup information for thread/process
+ */
+class ACE_Export ACE_Cleanup_Info
+{
+public:
+ /// Default constructor.
+ ACE_Cleanup_Info (void);
+
+ /// Equality operator.
+ bool operator== (const ACE_Cleanup_Info &o) const;
+
+ /// Inequality operator.
+ bool operator!= (const ACE_Cleanup_Info &o) const;
+
+ /// Point to object that gets passed into the <cleanup_hook_>.
+ void *object_;
+
+ /// Cleanup hook that gets called back.
+ ACE_CLEANUP_FUNC cleanup_hook_;
+
+ /// Parameter passed to the <cleanup_hook_>.
+ void *param_;
+};
+
+class ACE_Cleanup_Info_Node;
+
+/**
+ * @class ACE_OS_Exit_Info
+ *
+ * @brief Hold Object Manager cleanup (exit) information.
+ *
+ * For internal use by the ACE library, only.
+ */
+class ACE_Export ACE_OS_Exit_Info
+{
+public:
+ /// Default constructor.
+ ACE_OS_Exit_Info (void);
+
+ /// Destructor.
+ ~ACE_OS_Exit_Info (void);
+
+ /// Use to register a cleanup hook.
+ int at_exit_i (void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param);
+
+ /// Look for a registered cleanup hook object. Returns 1 if already
+ /// registered, 0 if not.
+ int find (void *object);
+
+ /// Call all registered cleanup hooks, in reverse order of
+ /// registration.
+ void call_hooks ();
+
+private:
+ /**
+ * Keeps track of all registered objects. The last node is only
+ * used to terminate the list (it doesn't contain a valid
+ * ACE_Cleanup_Info).
+ */
+ ACE_Cleanup_Info_Node *registered_objects_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/Cleanup.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_CLEANUP_H */
diff --git a/ACE/ace/Cleanup.inl b/ACE/ace/Cleanup.inl
new file mode 100644
index 00000000000..02d3c223f8d
--- /dev/null
+++ b/ACE/ace/Cleanup.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Cleanup::ACE_Cleanup (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Cleanup_Strategies_T.cpp b/ACE/ace/Cleanup_Strategies_T.cpp
new file mode 100644
index 00000000000..10804ba21ca
--- /dev/null
+++ b/ACE/ace/Cleanup_Strategies_T.cpp
@@ -0,0 +1,95 @@
+//$Id$
+
+#ifndef ACE_CLEANUP_STRATEGIES_T_CPP
+#define ACE_CLEANUP_STRATEGIES_T_CPP
+
+#include "ace/Cleanup_Strategies_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER>
+ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER>::~ACE_Cleanup_Strategy (void)
+{
+}
+
+template <class KEY, class VALUE, class CONTAINER> int
+ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER>::cleanup (CONTAINER &container,
+ KEY *key,
+ VALUE *)
+{
+ return container.unbind (*key);
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER> int
+ACE_Recyclable_Handler_Cleanup_Strategy<KEY, VALUE, CONTAINER>::cleanup (
+ CONTAINER &container,
+ KEY *key,
+ VALUE *)
+{
+ VALUE value;
+
+ if (container.unbind (*key, value) == -1)
+ return -1;
+
+ value.first ()->recycler (0, 0);
+
+ value.first ()->close ();
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER> int
+ACE_Refcounted_Recyclable_Handler_Cleanup_Strategy<KEY,
+ VALUE,
+ CONTAINER>::cleanup (
+ CONTAINER &,
+ KEY *,
+ VALUE *value)
+{
+ return value->first ()->handle_close_i ();
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER> int
+ACE_Handler_Cleanup_Strategy<KEY, VALUE, CONTAINER>::cleanup (
+ CONTAINER &container,
+ KEY *key,
+ VALUE *value)
+{
+ // Remove the item from cache only if the handler isnt in use.
+ if ((*value)->active () == 0)
+ {
+ (*value)->close ();
+
+ if (container.unbind (*key) == -1)
+ return -1;
+
+ }
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+template <class KEY, class VALUE, class CONTAINER> int
+ACE_Null_Cleanup_Strategy<KEY, VALUE, CONTAINER>::cleanup (CONTAINER &,
+ KEY *,
+ VALUE *)
+{
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_CLEANUP_STRATEGIES_T_CPP */
diff --git a/ACE/ace/Cleanup_Strategies_T.h b/ACE/ace/Cleanup_Strategies_T.h
new file mode 100644
index 00000000000..9a574ed2bcd
--- /dev/null
+++ b/ACE/ace/Cleanup_Strategies_T.h
@@ -0,0 +1,155 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Cleanup_Strategies_T.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef CLEANUP_STRATEGIES_H
+#define CLEANUP_STRATEGIES_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// For linkers that cant grok long names.
+#define ACE_Cleanup_Strategy ACLE
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Cleanup_Strategy
+ *
+ * @brief Defines a default strategy to be followed for cleaning up
+ * entries from a map which is the container.
+ *
+ * By default the entry to be cleaned up is removed from the
+ * container.
+ */
+template <class KEY, class VALUE, class CONTAINER>
+class ACE_Cleanup_Strategy
+{
+
+public:
+
+ /// Destructor.
+ virtual ~ACE_Cleanup_Strategy (void);
+
+ /// The method which will do the cleanup of the entry in the container.
+ virtual int cleanup (CONTAINER &container, KEY *key, VALUE *value);
+};
+
+//////////////////////////////////////////////////////////////////////
+#define ACE_Recyclable_Handler_Cleanup_Strategy ARHCLE
+
+/**
+ * @class ACE_Recyclable_Handler_Cleanup_Strategy
+ *
+ * @brief Defines a strategy to be followed for cleaning up
+ * entries which are svc_handlers from a container.
+ *
+ * The entry to be cleaned up is removed from the container.
+ * Here, since we are dealing with svc_handlers specifically, we
+ * perform a couple of extra operations. @note To be used when
+ * the handler is recyclable.
+ */
+template <class KEY, class VALUE, class CONTAINER>
+class ACE_Recyclable_Handler_Cleanup_Strategy : public ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER>
+{
+
+public:
+
+ /// The method which will do the cleanup of the entry in the container.
+ virtual int cleanup (CONTAINER &container, KEY *key, VALUE *value);
+};
+
+//////////////////////////////////////////////////////////////////////
+#define ACE_Refcounted_Recyclable_Handler_Cleanup_Strategy ARRHCLE
+
+/**
+ * @class ACE_Refcounted_Recyclable_Handler_Cleanup_Strategy
+ *
+ * @brief Defines a strategy to be followed for cleaning up
+ * entries which are svc_handlers from a container.
+ *
+ * The entry to be cleaned up is removed from the container.
+ * Here, since we are dealing with recyclable svc_handlers with
+ * addresses which are refcountable specifically, we perform a
+ * couple of extra operations and do so without any locking.
+ */
+template <class KEY, class VALUE, class CONTAINER>
+class ACE_Refcounted_Recyclable_Handler_Cleanup_Strategy : public ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER>
+{
+
+public:
+
+ /// The method which will do the cleanup of the entry in the container.
+ virtual int cleanup (CONTAINER &container, KEY *key, VALUE *value);
+};
+
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * @class ACE_Handler_Cleanup_Strategy
+ *
+ * @brief Defines a strategy to be followed for cleaning up
+ * entries which are svc_handlers from a container.
+ *
+ * The entry to be cleaned up is removed from the container.
+ * Here, since we are dealing with svc_handlers specifically, we
+ * perform a couple of extra operations. @note This cleanup strategy
+ * should be used in the case when the handler has the caching
+ * attributes.
+ */
+template <class KEY, class VALUE, class CONTAINER>
+class ACE_Handler_Cleanup_Strategy : public ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER>
+{
+
+public:
+
+ /// The method which will do the cleanup of the entry in the container.
+ virtual int cleanup (CONTAINER &container, KEY *key, VALUE *value);
+};
+
+//////////////////////////////////////////////////////////////////////
+#define ACE_Null_Cleanup_Strategy ANCLE
+
+/**
+ * @class ACE_Null_Cleanup_Strategy
+ *
+ * @brief Defines a do-nothing implementation of the cleanup strategy.
+ *
+ * This class simply does nothing at all! Can be used to nullify
+ * the effect of the Cleanup Strategy.
+ */
+template <class KEY, class VALUE, class CONTAINER>
+class ACE_Null_Cleanup_Strategy : public ACE_Cleanup_Strategy<KEY, VALUE, CONTAINER>
+{
+
+public:
+
+ /// The dummy cleanup method.
+ virtual int cleanup (CONTAINER &container, KEY *key, VALUE *value);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Cleanup_Strategies_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Cleanup_Strategies_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* CLEANUP_STRATEGIES_H */
diff --git a/ACE/ace/Codecs.cpp b/ACE/ace/Codecs.cpp
new file mode 100644
index 00000000000..505c5fc9916
--- /dev/null
+++ b/ACE/ace/Codecs.cpp
@@ -0,0 +1,234 @@
+#include "ace/Codecs.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_ctype.h"
+
+ACE_RCSID (ace,
+ Codecs,
+ "$Id$")
+
+namespace
+{
+ // Just in case ...
+#undef alphabet
+#undef pad
+#undef max_columns
+
+ // Symbols which form the Base64 alphabet (Defined as per RFC 2045)
+ ACE_Byte const alphabet[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ // The padding character used in the encoding
+ ACE_Byte const pad = '=';
+
+ // Number of columns per line of encoded output (Can have a maximum
+ // value of 76).
+ int const max_columns = 72;
+}
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+bool ACE_Base64::init_ = false;
+
+ACE_Byte ACE_Base64::decoder_[256];
+
+ACE_Byte ACE_Base64::member_[256];
+
+ACE_Byte*
+ACE_Base64::encode (const ACE_Byte* input,
+ const size_t input_len,
+ size_t* output_len,
+ bool is_chunked)
+{
+ if (!ACE_Base64::init_)
+ ACE_Base64::init();
+
+ if (!input)
+ return 0;
+
+ ACE_Byte* result = 0;
+
+ size_t length = ((input_len + 2) / 3) * 4;
+ size_t num_lines = length / max_columns + 1;
+ length += num_lines + 1;
+ ACE_NEW_RETURN (result, ACE_Byte[length], 0);
+
+ int char_count = 0;
+ int bits = 0;
+ size_t pos = 0;
+ int cols = 0;
+
+ for (size_t i = 0; i < input_len; ++i)
+ {
+ bits += input[i];
+ ++char_count;
+
+ if (char_count == 3)
+ {
+ result[pos++] = alphabet[bits >> 18];
+ result[pos++] = alphabet[(bits >> 12) & 0x3f];
+ result[pos++] = alphabet[(bits >> 6) & 0x3f];
+ result[pos++] = alphabet[bits & 0x3f];
+ cols += 4;
+ if (cols == max_columns) {
+ if (is_chunked)
+ result[pos++] = '\n';
+ cols = 0;
+ }
+ bits = 0;
+ char_count = 0;
+ }
+ else
+ {
+ bits <<= 8;
+ }
+ }
+
+ if (char_count != 0)
+ {
+ bits <<= (16 - (8 * char_count));
+ result[pos++] = alphabet[bits >> 18];
+ result[pos++] = alphabet[(bits >> 12) & 0x3f];
+ cols += 2;
+ if (char_count == 1)
+ {
+ result[pos++] = pad;
+ result[pos++] = pad;
+ cols += 2;
+ }
+ else
+ {
+ result[pos++] = alphabet[(bits >> 6) & 0x3f];
+ result[pos++] = pad;
+ cols += 2;
+ }
+ }
+
+ if (cols > 0 && is_chunked)
+ result[pos++] = '\n';
+
+ result[pos] = 0;
+ *output_len = pos;
+ return result;
+}
+
+size_t
+ACE_Base64::length (const ACE_Byte* input)
+{
+ if (!ACE_Base64::init_)
+ ACE_Base64::init();
+
+ ACE_Byte* ptr = const_cast<ACE_Byte*> (input);
+ while (*ptr != 0 &&
+ (member_[*(ptr)] == 1 || *ptr == pad
+ || ACE_OS::ace_isspace (*ptr)))
+ ++ptr;
+ size_t len = ptr - input;
+ len = ((len + 3) / 4) * 3 + 1 ;
+ return len;
+}
+
+ACE_Byte*
+ACE_Base64::decode (const ACE_Byte* input, size_t* output_len)
+{
+ if (!ACE_Base64::init_)
+ ACE_Base64::init();
+
+ if (!input)
+ return 0;
+
+ size_t result_len = ACE_Base64::length (input);
+ ACE_Byte* result = 0;
+ ACE_NEW_RETURN (result, ACE_Byte[result_len], 0);
+
+ ACE_Byte* ptr = const_cast<ACE_Byte*> (input);
+ while (*ptr != 0 &&
+ (member_[*(ptr)] == 1 || *ptr == pad
+ || ACE_OS::ace_isspace (*ptr)))
+ ++ptr;
+ size_t input_len = ptr - input;
+
+ int char_count = 0;
+ int bits = 0;
+ size_t pos = 0;
+
+ size_t i = 0;
+ for (; i < input_len; ++i)
+ {
+ if (input[i] == pad)
+ break;
+ if (!ACE_Base64::member_[input[i]])
+ continue;
+ bits += decoder_[input[i]];
+ ++char_count;
+
+ if (char_count == 4)
+ {
+ result[pos++] = static_cast<ACE_Byte> (bits >> 16);
+ result[pos++] = static_cast<ACE_Byte> ((bits >> 8) & 0xff);
+ result[pos++] = static_cast<ACE_Byte> (bits & 0xff);
+ bits = 0;
+ char_count = 0;
+ }
+ else
+ {
+ bits <<= 6;
+ }
+ }
+
+ int errors = 0;
+ if ( i == input_len)
+ {
+ if (char_count)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Decoding incomplete: atleast %d bits truncated\n"),
+ (4 - char_count) * 6));
+ ++errors;
+ }
+ }
+ else
+ {
+ switch (char_count)
+ {
+ case 1:
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Decoding incomplete: atleast 2 bits missing\n")));
+ ++errors;
+ break;
+ case 2:
+ result[pos++] = static_cast<ACE_Byte> (bits >> 10);
+ break;
+ case 3:
+ result[pos++] = static_cast<ACE_Byte> (bits >> 16);
+ result[pos++] = static_cast<ACE_Byte> ((bits >> 8) & 0xff);
+ break;
+ }
+ }
+
+ if (errors)
+ {
+ delete[] result;
+ return 0;
+ }
+ result[pos] = 0;
+ *output_len = pos;
+ return result;
+}
+
+void
+ACE_Base64::init ()
+{
+ if (!ACE_Base64::init_)
+ {
+ for (ACE_Byte i = 0; i < sizeof (alphabet); ++i)
+ {
+ ACE_Base64::decoder_[alphabet[i]] = i;
+ ACE_Base64::member_ [alphabet[i]] = 1;
+ }
+ ACE_Base64::init_ = true;
+ }
+ return;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Codecs.h b/ACE/ace/Codecs.h
new file mode 100644
index 00000000000..85447b75e06
--- /dev/null
+++ b/ACE/ace/Codecs.h
@@ -0,0 +1,121 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Codecs.h
+ *
+ * $Id$
+ *
+ * @author Krishnakumar B <kitty@cs.wustl.edu>
+ *
+ * Codecs is a generic wrapper for various encoding and decoding
+ * mechanisms. Currently it includes Base64 content transfer-encoding as
+ * specified by RFC 2045, Multipurpose Internet Mail Extensions (MIME) Part
+ * One: Format of Internet Message Bodies.
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_CODECS_H
+#define ACE_CODECS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Basic_Types.h"
+#include "ace/Global_Macros.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Base64
+ *
+ * @brief Encode/Decode a stream of bytes according to Base64 encoding.
+ *
+ * This class provides methods to encode or decode a stream of bytes
+ * to/from Base64 encoding. It doesn't convert the input stream to a
+ * canonical form before encoding.
+ *
+ */
+class ACE_Export ACE_Base64
+{
+public:
+
+ //@{
+
+ /**
+ * Encodes a stream of bytes to Base64 data
+ *
+ * @param input Binary data in byte stream.
+ * @param input_len Length of the byte stream.
+ * @param output_len Length of the encoded Base64 byte stream.
+ * @param is_chunked If true, terminate 72 character blocks with newline
+ * @return Encoded Base64 data in byte stream or NULL if input data cannot
+ * be encoded.
+ */
+
+ static ACE_Byte* encode (const ACE_Byte* input,
+ const size_t input_len,
+ size_t* output_len,
+ bool is_chunked = true);
+ /**
+ * Decodes a stream of Base64 to bytes data
+ *
+ * @param input Encoded Base64 data in byte stream.
+ * @param output_len Length of the binary byte stream.
+ * @return Binary data in byte stream or NULL if input data cannot
+ * be encoded.
+ */
+ static ACE_Byte* decode (const ACE_Byte* input,
+ size_t* output_len);
+
+ /**
+ * Return the length of the encoded input data
+ *
+ * @param input Encoded Base64 data in byte stream.
+ * @return Length of the encoded Base64 data.
+ *
+ */
+ static size_t length (const ACE_Byte* input);
+
+ //@}
+
+protected:
+
+ // Prevent default construction.
+ ACE_Base64 (void) {}
+
+private:
+
+ // Preventing copying and assignment.
+ ACE_Base64 (ACE_Base64 const &);
+ ACE_Base64 & operator= (ACE_Base64 const &);
+
+ /// Initialize the tables for encoding/decoding.
+ static void init (void);
+
+private:
+
+ /// Alphabet used for decoding i.e decoder_[alphabet_[i = 0..63]] = i
+ static ACE_Byte decoder_[];
+
+ /// Alphabet used to check valid range of encoded input i.e
+ /// member_[alphabet_[0..63]] = 1
+ static ACE_Byte member_[];
+
+ /// Boolean to denote whether initialization is complete
+ static bool init_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CODECS_H */
diff --git a/ACE/ace/Codeset_IBM1047.cpp b/ACE/ace/Codeset_IBM1047.cpp
new file mode 100644
index 00000000000..5e208fd373f
--- /dev/null
+++ b/ACE/ace/Codeset_IBM1047.cpp
@@ -0,0 +1,312 @@
+
+//=============================================================================
+/**
+ * @file Codeset_IBM1047.cpp
+ *
+ * $Id$
+ *
+ * Defines the arrays required to convert between ISO8859 (aka
+ * Latin/1) and IBM1047 (aka EBCDIC).
+ *
+ *
+ * @author Jim Rogers (jrogers@viasoft.com)
+ */
+//=============================================================================
+
+
+#include "ace/Codeset_IBM1047.h"
+
+#if defined (ACE_HAS_EBCDIC)
+
+ACE_RCSID (ace,
+ Codeset_IBM1047,
+ "$Id$")
+
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+
+namespace
+{
+ char const to_IBM1047[] =
+ {
+ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" // 00-0F
+ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x22\x1D\x35\x1F" // 10-1F
+ "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" // 20-2F
+ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" // 30-3F
+ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" // 40-4F
+ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D" // 50-5F
+ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" // 60-6F
+ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07" // 70-7F
+ "\x43\x20\x21\x1C\x23\xEB\x24\x9B\x71\x28\x38\x49\x90\xBA\xEC\xDF" // 80-8F
+ "\x45\x29\x2A\x9D\x72\x2B\x8A\x9A\x67\x56\x64\x4A\x53\x68\x59\x46" // 90-9F
+ "\xEA\xDA\x2C\xDE\x8B\x55\x41\xFE\x58\x51\x52\x48\x69\xDB\x8E\x8D" // A0-AF
+ "\x73\x74\x75\xFA\x15\xB0\xB1\xB3\xB4\xB5\x6A\xB7\xB8\xB9\xCC\xBC" // B0-BF
+ "\xAB\x3E\x3B\x0A\xBF\x8F\x3A\x14\xA0\x17\xCB\xCA\x1A\x1B\x9C\x04" // C0-CF
+ "\x34\xEF\x1E\x06\x08\x09\x77\x70\xBE\xBB\xAC\x54\x63\x65\x66\x62" // D0-DF
+ "\x30\x42\x47\x57\xEE\x33\xB6\xE1\xCD\xED\x36\x44\xCE\xCF\x31\xAA" // E0-EF
+ "\xFC\x9E\xAE\x8C\xDD\xDC\x39\xFB\x80\xAF\xFD\x78\x76\xB2\x9F\xFF" // F0-FF
+};
+
+ char const from_IBM1047[] =
+ {
+ "\x00\x01\x02\x03\xCF\x09\xD3\x7F\xD4\xD5\xC3\x0B\x0C\x0D\x0E\x0F" // 00-0F
+ "\x10\x11\x12\x13\xC7\xB4\x08\xC9\x18\x19\xCC\xCD\x83\x1D\xD2\x1F" // 10-1F
+ "\x81\x82\x1C\x84\x86\x0A\x17\x1B\x89\x91\x92\x95\xA2\x05\x06\x07" // 20-2F
+ "\x20\xEE\x16\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xC1\x1A" // 30-3F
+ "\x20\xA6\xE1\x80\xEB\x90\x9F\xE2\xAB\x8B\x9B\x2E\x3C\x28\x2B\x7C" // 40-4F
+ "\x26\xA9\xAA\x9C\xDB\xA5\x99\xE3\xA8\x9E\x21\x24\x2A\x29\x3B\x5E" // 50-5F
+ "\x2D\x2F\xDF\xDC\x9A\xDD\xDE\x98\x9D\xAC\xBA\x2C\x25\x5F\x3E\x3F" // 60-6F
+ "\xD7\x88\x94\xB0\xB1\xB2\xFC\xD6\xFB\x60\x3A\x23\x40\x27\x3D\x22" // 70-7F
+ "\xF8\x61\x62\x63\x64\x65\x66\x67\x68\x69\x96\xA4\xF3\xAF\xAE\xC5" // 80-8F
+ "\x8C\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x97\x87\xCE\x93\xF1\xFE" // 90-9F
+ "\xC8\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xEF\xC0\xDA\x5B\xF2\xF9" // A0-AF
+ "\xB5\xB6\xFD\xB7\xB8\xB9\xE6\xBB\xBC\xBD\x8D\xD9\xBF\x5D\xD8\xC4" // B0-BF
+ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xCB\xCA\xBE\xE8\xEC\xED" // C0-CF
+ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xA1\xAD\xF5\xF4\xA3\x8F" // D0-DF
+ "\x5C\xE7\x53\x54\x55\x56\x57\x58\x59\x5A\xA0\x85\x8E\xE9\xE4\xD1" // E0-EF
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xF7\xF0\xFA\xA7\xFF" // F0-FF
+ };
+}
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_IBM1047_ISO8859::ACE_IBM1047_ISO8859 (void)
+{
+}
+
+ACE_IBM1047_ISO8859::~ACE_IBM1047_ISO8859 (void)
+{
+}
+
+ACE_CDR::ULong
+ACE_IBM1047_ISO8859::ncs ()
+{
+ return 0x10020417;
+}
+
+ACE_CDR::ULong
+ACE_IBM1047_ISO8859::tcs ()
+{
+ return 0x00010001;
+}
+
+ACE_CDR::Boolean
+ACE_IBM1047_ISO8859::read_char (ACE_InputCDR &in,
+ ACE_CDR::Char &x)
+{
+ if (this->read_1 (in, reinterpret_cast<ACE_CDR::Octet*> (&x)))
+ {
+ x = to_IBM1047[x];
+ return 1;
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_IBM1047_ISO8859::read_string (ACE_InputCDR& in,
+ ACE_CDR::Char *& x)
+{
+ ACE_CDR::ULong len;
+
+ in.read_ulong (len);
+
+ if (len > 0)
+ {
+ ACE_NEW_RETURN (x,
+ ACE_CDR::Char[len],
+ 0);
+
+ if (this->read_char_array (in, x, len))
+ return 1;
+
+ delete [] x;
+ }
+
+ x = 0;
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_IBM1047_ISO8859::read_char_array (ACE_InputCDR& in,
+ ACE_CDR::Char* x,
+ ACE_CDR::ULong len)
+{
+ if (this->read_array (in,
+ x,
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ len))
+ {
+ for (ACE_CDR::ULong i = 0; i != len; ++i)
+ x[i] = to_IBM1047[x[i]];
+
+ return 1;
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_IBM1047_ISO8859::write_char (ACE_OutputCDR& out,
+ ACE_CDR::Char x)
+{
+ return
+ this->write_1 (out,
+ reinterpret_cast<const ACE_CDR::Octet*> (&from_IBM1047[x]));
+}
+
+ACE_CDR::Boolean
+ACE_IBM1047_ISO8859::write_string (ACE_OutputCDR& out,
+ ACE_CDR::ULong len,
+ const ACE_CDR::Char* x)
+{
+ if (out.write_ulong (len + 1))
+ return this->write_char_array (out, x, len + 1);
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_IBM1047_ISO8859::write_char_array (ACE_OutputCDR& out,
+ const ACE_CDR::Char* x,
+ ACE_CDR::ULong len)
+{
+ char *buf = 0;
+ if (this->adjust (out, len, 1, buf) == 0)
+ {
+ ACE_OS::memcpy (buf, x, len);
+
+ for (ACE_CDR::ULong i = 0; i != len; ++i)
+ buf[i] = from_IBM1047[buf[i]];
+
+ return 1;
+ }
+
+ this->good_bit(out, 0);
+ return 0;
+}
+
+// ****************************************************************
+
+ACE_ISO8859_IBM1047::ACE_ISO8859_IBM1047 (void)
+{
+}
+
+ACE_ISO8859_IBM1047::~ACE_ISO8859_IBM1047 (void)
+{
+}
+
+ACE_CDR::ULong
+ACE_ISO8859_IBM1047::ncs ()
+{
+ return 0x00010001;
+}
+
+ACE_CDR::ULong
+ACE_ISO8859_IBM1047::tcs ()
+{
+ return 0x10020417;
+}
+
+ACE_CDR::Boolean
+ACE_ISO8859_IBM1047::read_char (ACE_InputCDR& in,
+ ACE_CDR::Char& x)
+{
+ if (this->read_1 (in, reinterpret_cast<ACE_CDR::Octet*> (&x)))
+ {
+ x = from_IBM1047[x];
+ return 1;
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_ISO8859_IBM1047::read_string (ACE_InputCDR &in,
+ ACE_CDR::Char *&x)
+{
+ ACE_CDR::ULong len;
+
+ in.read_ulong (len);
+
+ if (len > 0)
+ {
+ ACE_NEW_RETURN (x,
+ ACE_CDR::Char[len],
+ 0);
+
+ if (this->read_char_array (in, x, len))
+ return 1;
+
+ delete [] x;
+ }
+
+ x = 0;
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_ISO8859_IBM1047::read_char_array (ACE_InputCDR &in,
+ ACE_CDR::Char *x,
+ ACE_CDR::ULong len)
+{
+ if (this->read_array (in,
+ x,
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ len))
+ {
+ for (ACE_CDR::ULong i = 0; i != len; ++i)
+ x[i] = from_IBM1047[x[i]];
+
+ return 1;
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_ISO8859_IBM1047::write_char (ACE_OutputCDR &out,
+ ACE_CDR::Char x)
+{
+ return
+ this->write_1 (out,
+ reinterpret_cast<const ACE_CDR::Octet *> (&to_IBM1047[x]));
+}
+
+ACE_CDR::Boolean
+ACE_ISO8859_IBM1047::write_string (ACE_OutputCDR& out,
+ ACE_CDR::ULong len,
+ const ACE_CDR::Char* x)
+{
+ if (out.write_ulong (len + 1))
+ return this->write_char_array (out, x, len + 1);
+ else
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_ISO8859_IBM1047::write_char_array (ACE_OutputCDR &out,
+ const ACE_CDR::Char *x,
+ ACE_CDR::ULong len)
+{
+ char *buf = 0;
+
+ if (this->adjust (out, len, 1, buf) == 0)
+ {
+ ACE_OS::memcpy (buf, x, len);
+
+ for (ACE_CDR::ULong i = 0; i != len; ++i)
+ buf[i] = to_IBM1047[buf[i]];
+
+ return 1;
+ }
+
+ this->good_bit (out, 0);
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#elif defined (__HP_aCC)
+// Make aC++ stop complaining about an empty translation unit
+static int const shut_up_aCC = 0;
+#endif /* ACE_HAS_EBCDIC */
diff --git a/ACE/ace/Codeset_IBM1047.h b/ACE/ace/Codeset_IBM1047.h
new file mode 100644
index 00000000000..c5bfdafcd49
--- /dev/null
+++ b/ACE/ace/Codeset_IBM1047.h
@@ -0,0 +1,128 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Codeset_IBM1047.h
+ *
+ * $Id$
+ *
+ * Declares the arrays required to convert between ISO8859 (aka
+ * Latin/1) and IBM1047 (aka EBCDIC).
+ *
+ *
+ * @author Jim Rogers (jrogers@viasoft.com)
+ */
+//=============================================================================
+
+
+#ifndef ACE_CODESET_IMB1047_H
+#define ACE_CODESET_IMB1047_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_HAS_EBCDIC)
+
+#include "ace/CDR_Stream.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// ****************************************************************
+
+/**
+ * @class ACE_IBM1047_ISO8859
+ *
+ * @brief Codeset translation specialization.
+ *
+ * This class performs the codeset translation:
+ * - Native: IBM_1047 (i.e. EBCDIC)
+ * - Stream: ISO-8859 (i.e. Latin/1)
+ */
+class ACE_Export ACE_IBM1047_ISO8859 : public ACE_Char_Codeset_Translator
+{
+public:
+ /// A do nothing constructor.
+ ACE_IBM1047_ISO8859 (void);
+
+ /// Virtual destruction
+ virtual ~ACE_IBM1047_ISO8859 (void);
+
+ // = Documented in $ACE_ROOT/ace/CDR_Stream.h
+ virtual ACE_CDR::Boolean read_char (ACE_InputCDR &,
+ ACE_CDR::Char &);
+ virtual ACE_CDR::Boolean read_string (ACE_InputCDR &,
+ ACE_CDR::Char *&);
+ virtual ACE_CDR::Boolean read_char_array (ACE_InputCDR &,
+ ACE_CDR::Char *,
+ ACE_CDR::ULong);
+ virtual ACE_CDR::Boolean write_char (ACE_OutputCDR &,
+ ACE_CDR::Char);
+ virtual ACE_CDR::Boolean write_string (ACE_OutputCDR &,
+ ACE_CDR::ULong,
+ const ACE_CDR::Char *);
+ virtual ACE_CDR::Boolean write_char_array (ACE_OutputCDR &,
+ const ACE_CDR::Char *,
+ ACE_CDR::ULong);
+
+ /// return the native codeset ID as defined in the OSF code and character
+ /// set registry, 0x10020417
+ virtual ACE_CDR::ULong ncs ();
+ /// return the translated codeset ID as defined in the OSF code and character
+ /// set registry, 0x00010001
+ virtual ACE_CDR::ULong tcs ();
+};
+
+/**
+ * @class ACE_ISO8859_IBM1047
+ *
+ * @brief Codeset translation specialization.
+ *
+ * This class performs the codeset translation:
+ * - Native: ISO-8859 (i.e. Latin/1)
+ * - Stream: IBM-1047 (i.e. EBCDIC)
+ */
+class ACE_Export ACE_ISO8859_IBM1047 : public ACE_Char_Codeset_Translator
+{
+public:
+ /// A do nothing constructor.
+ ACE_ISO8859_IBM1047 (void);
+
+ /// Virtual destruction
+ virtual ~ACE_ISO8859_IBM1047 (void);
+
+ // = Documented in $ACE_ROOT/ace/CDR_Stream.h
+ virtual ACE_CDR::Boolean read_char (ACE_InputCDR &,
+ ACE_CDR::Char &);
+ virtual ACE_CDR::Boolean read_string (ACE_InputCDR &,
+ ACE_CDR::Char *&);
+ virtual ACE_CDR::Boolean read_char_array (ACE_InputCDR &,
+ ACE_CDR::Char *,
+ ACE_CDR::ULong);
+ virtual ACE_CDR::Boolean write_char (ACE_OutputCDR &,
+ ACE_CDR::Char);
+ virtual ACE_CDR::Boolean write_string (ACE_OutputCDR &,
+ ACE_CDR::ULong,
+ const ACE_CDR::Char *);
+ virtual ACE_CDR::Boolean write_char_array (ACE_OutputCDR &,
+ const ACE_CDR::Char *,
+ ACE_CDR::ULong);
+
+ /// return the native codeset ID as defined in the OSF code and character
+ /// set registry, 0x00010001
+ virtual ACE_CDR::ULong ncs ();
+ /// return the translated codeset ID as defined in the OSF code and character
+ /// set registry, 0x10020417
+ virtual ACE_CDR::ULong tcs ();
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_EBCDIC */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CODESET_IMB1047_H */
diff --git a/ACE/ace/Codeset_Registry.cpp b/ACE/ace/Codeset_Registry.cpp
new file mode 100644
index 00000000000..b98a1dd7e89
--- /dev/null
+++ b/ACE/ace/Codeset_Registry.cpp
@@ -0,0 +1,111 @@
+//=============================================================================
+/**
+ * @file Codeset_Registry.cpp
+ *
+ * $Id$
+ *
+ * emulated codset regstry functions
+ *
+ *
+ * @author Phil Mesnier <mesnier_p@ociweb.com>
+ */
+//=============================================================================
+
+#include "ace/Codeset_Registry.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+
+// $Id$
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Codeset_Registry.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Codeset_Registry,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_Codeset_Registry::locale_to_registry_i (const ACE_CString &locale,
+ ACE_CDR::ULong &codeset_id,
+ ACE_CDR::UShort *num_sets,
+ ACE_CDR::UShort **char_sets)
+{
+ registry_entry const *element = 0;
+ for (size_t i = 0; element == 0 && i < num_registry_entries_; i++)
+ if (ACE_OS::strcmp (registry_db_[i].loc_name_, locale.c_str ()) == 0)
+ element = &registry_db_[i];
+ if (element == 0)
+ return 0;
+ codeset_id = element->codeset_id_;
+ if (num_sets != 0)
+ *num_sets = element->num_sets_;
+ if (char_sets != 0)
+ {
+ ACE_NEW_RETURN (*char_sets,ACE_CDR::UShort[element->num_sets_],0);
+ ACE_OS::memcpy (*char_sets, element->char_sets_,
+ element->num_sets_ * sizeof (ACE_CDR::UShort));
+ }
+ return 1;
+}
+
+int
+ACE_Codeset_Registry::registry_to_locale_i (ACE_CDR::ULong codeset_id,
+ ACE_CString &locale,
+ ACE_CDR::UShort *num_sets,
+ ACE_CDR::UShort **char_sets)
+{
+ registry_entry const *element = 0;
+ for (size_t i = 0; element == 0 && i < num_registry_entries_; i++)
+ if (codeset_id == registry_db_[i].codeset_id_)
+ element = &registry_db_[i];
+ if (element == 0)
+ return 0;
+ locale.set (element->loc_name_);
+ if (num_sets != 0)
+ *num_sets = element->num_sets_;
+ if (char_sets != 0)
+ {
+ ACE_NEW_RETURN (*char_sets,ACE_CDR::UShort[element->num_sets_],0);
+ ACE_OS::memcpy (*char_sets, element->char_sets_,
+ element->num_sets_ * sizeof (ACE_CDR::UShort));
+ }
+ return 1;
+}
+
+int
+ACE_Codeset_Registry::is_compatible_i (ACE_CDR::ULong codeset_id,
+ ACE_CDR::ULong other)
+{
+ registry_entry const *lhs = 0;
+ registry_entry const *rhs = 0;
+ for (size_t i = 0; (lhs == 0 || rhs == 0) && i < num_registry_entries_; i++)
+ {
+ if (codeset_id == registry_db_[i].codeset_id_)
+ lhs = &registry_db_[i];
+ if (other == registry_db_[i].codeset_id_)
+ rhs = &registry_db_[i];
+ }
+
+ if (lhs == 0 || rhs == 0)
+ return 0;
+
+ for (ACE_CDR::UShort l = 0; l < lhs->num_sets_; l++)
+ for (ACE_CDR::UShort r = 0; r < rhs->num_sets_; r++)
+ if (rhs->char_sets_[r] == lhs->char_sets_[l])
+ return 1;
+ return 0;
+}
+
+ACE_CDR::Short
+ACE_Codeset_Registry::get_max_bytes_i (ACE_CDR::ULong codeset_id)
+{
+ for (size_t i = 0; i < num_registry_entries_; i++)
+ if (codeset_id == registry_db_[i].codeset_id_)
+ return registry_db_[i].max_bytes_;
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Codeset_Registry.h b/ACE/ace/Codeset_Registry.h
new file mode 100644
index 00000000000..eb8d013d4af
--- /dev/null
+++ b/ACE/ace/Codeset_Registry.h
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+//=============================================================================
+/**
+ * @file Codeset_Registry.h
+ *
+ * $Id$
+ *
+ * ACE wrapper around access functions for the OSF's DCE codeset registry
+ * access functions
+ *
+ * For environments that intrinsicly support the DCE defined access functions,
+ * the methods in this class are simply wrappers. On other platforms, emulation
+ * is provided. The motivation for this class is to support interoperability
+ * via translators and the CDR streams, primarily in TAO, but this capability
+ * is not restricted to CORBA.
+ *
+ * The emulated functionalty supports Open Group RFC #40, currently RFC 40.2,
+ * www.opengroup.org/tech/rfc/rfc40.2.html
+ *
+ * @author Phil Mesnier <mesnier_p@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef ACE_CODESET_REGISTRY_H
+#define ACE_CODESET_REGISTRY_H
+
+#include /**/ "ace/pre.h"
+#include "ace/SString.h"
+#include "ace/CDR_Base.h"
+#include "ace/Codeset_Symbols.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_DCE_CODESET_REGISTRY)
+#include /**/ <dce/rpc.h>
+#endif /* ACE_HAS_DCE_CODESET_REGISTRY */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Export ACE_Codeset_Registry
+{
+public:
+
+ /// Based on a locale string, find the registry value and optional codeset
+ /// collection. This wraps the dce_cs_loc_to_rgy function, or emulates it.
+ static int locale_to_registry (const ACE_CString &locale,
+ ACE_CDR::ULong &codeset_id,
+ ACE_CDR::UShort * = 0,
+ ACE_CDR::UShort ** = 0);
+
+ /// Based on a registry value, find the locale string and optional codeset
+ /// collection. This wraps the dce_cs_rgy_to_loc function, or emulates it.
+ static int registry_to_locale (ACE_CDR::ULong codeset_id,
+ ACE_CString &locale,
+ ACE_CDR::UShort * = 0,
+ ACE_CDR::UShort ** = 0);
+
+ /// Tell if two codesets are compatible. This wraps the
+ /// rpc_cs_char_set_compat_check function.
+ static int is_compatible (ACE_CDR::ULong codeset_id,
+ ACE_CDR::ULong other);
+
+ /// Return the max number of bytes required to represent a single character.
+ /// This wraps the rpc_rgy_get_max_bytes function.
+ static ACE_CDR::Short get_max_bytes (ACE_CDR::ULong codeset_id);
+
+ enum {max_charsets_ = 5};
+protected:
+ typedef struct {
+ const char * desc_;
+ const char * loc_name_;
+ ACE_CDR::ULong codeset_id_;
+ ACE_CDR::UShort num_sets_;
+ ACE_CDR::UShort char_sets_[max_charsets_];
+ ACE_CDR::UShort max_bytes_;
+ } registry_entry;
+
+private:
+ static size_t const num_registry_entries_;
+ static registry_entry const registry_db_[];
+
+ static int locale_to_registry_i (const ACE_CString &locale,
+ ACE_CDR::ULong &codeset_id,
+ ACE_CDR::UShort * = 0,
+ ACE_CDR::UShort ** = 0);
+ static int registry_to_locale_i (ACE_CDR::ULong codeset_id,
+ ACE_CString &locale,
+ ACE_CDR::UShort * = 0,
+ ACE_CDR::UShort ** = 0);
+ static int is_compatible_i (ACE_CDR::ULong codeset_id,
+ ACE_CDR::ULong other);
+ static ACE_CDR::Short get_max_bytes_i (ACE_CDR::ULong codeset_id);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Codeset_Registry.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CODESET_REGISTRY_H */
diff --git a/ACE/ace/Codeset_Registry.inl b/ACE/ace/Codeset_Registry.inl
new file mode 100644
index 00000000000..d24e07cc83b
--- /dev/null
+++ b/ACE/ace/Codeset_Registry.inl
@@ -0,0 +1,102 @@
+// -*- C++ -*-
+//=============================================================================
+/**
+ * @file Codeset_Registry.inl
+ *
+ * $Id$
+ *
+ * ACE wrapper around access functions for the OSF's DCE codeset registry
+ * access functions - the inline functions either call the system supplied
+ * DCE based codeset regsitry function, or calls the emulation
+ *
+ *
+ * @author Phil Mesnier <mesnier_p@ociweb.com>
+ */
+//=============================================================================
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+int
+ACE_Codeset_Registry::locale_to_registry(const ACE_CString &locale,
+ ACE_CDR::ULong &codeset_id,
+ ACE_CDR::UShort *num_sets,
+ ACE_CDR::UShort **char_sets)
+{
+#if defined (ACE_HAS_DCE_CODESET_REGISTRY)
+ error_status_t result;
+ dce_cs_loc_to_rgy (locale.c_str(),
+ &codeset_id,
+ num_sets,
+ char_sets,
+ &result);
+ return (result == dce_cs_c_ok) ? 1 : 0;
+#else
+ return ACE_Codeset_Registry::locale_to_registry_i (locale,
+ codeset_id,
+ num_sets,
+ char_sets);
+#endif /* ACE_HAS_DCE_CODESET_REGISTRY */
+}
+
+// based on a registry value, find the locale string and optional codeset
+// collection. This wraps the dce_cs_rgy_to_loc function, or emulates it.
+ACE_INLINE
+int
+ACE_Codeset_Registry::registry_to_locale(ACE_CDR::ULong codeset_id,
+ ACE_CString &locale,
+ ACE_CDR::UShort *num_sets,
+ ACE_CDR::UShort **char_sets)
+{
+#if defined (ACE_HAS_DCE_CODESET_REGISTRY)
+ error_status_t result;
+ char *buffer;
+ dce_cs_rgy_to_loc (codeset_id,
+ &buffer,
+ num_sets,
+ char_sets,
+ &result);
+ locale.set(buffer); // does a copy :-(
+ free (buffer);
+ return (result == dce_cs_c_ok) ? 1 : 0;
+#else
+ return ACE_Codeset_Registry::registry_to_locale_i (codeset_id,
+ locale,
+ num_sets,
+ char_sets);
+#endif /* ACE_HAS_DCE_CODESET_REGISTRY */
+}
+
+// Tell if two codesets are compatible. This wraps the
+// rpc_cs_char_set_compat_check function.
+ACE_INLINE
+int
+ACE_Codeset_Registry::is_compatible (ACE_CDR::ULong codeset_id,
+ ACE_CDR::ULong other)
+{
+#if defined (ACE_HAS_DCE_CODESET_REGISTRY)
+ error_status_t result;
+ rpc_cs_char_set_compat_check(codeset_id,other,&result);
+ return (result == rpc_s_ok) ? 1 : 0;
+#else
+ return ACE_Codeset_Registry::is_compatible_i (codeset_id,other);
+#endif /* ACE_HAS_DCE_CODESET_REGISTRY */
+}
+
+// Return the max number of bytes required to represent a single character.
+// This wraps the rpc_rgy_get_max_bytes function.
+ACE_INLINE
+ACE_CDR::Short
+ACE_Codeset_Registry::get_max_bytes (ACE_CDR::ULong codeset_id)
+{
+#if defined (ACE_HAS_DCE_CODESET_REGISTRY)
+ error_status_t result;
+ short max_bytes;
+ rpc_rgy_get_max_bytes(codeset_id,&max_bytes,&result);
+ return (result == rpc_s_ok) ? (short)max_bytes : 0;
+#else
+ return ACE_Codeset_Registry::get_max_bytes_i (codeset_id);
+#endif /* ACE_HAS_DCE_CODESET_REGISTRY */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Codeset_Registry_db.cpp b/ACE/ace/Codeset_Registry_db.cpp
new file mode 100644
index 00000000000..8b1ef176576
--- /dev/null
+++ b/ACE/ace/Codeset_Registry_db.cpp
@@ -0,0 +1,29 @@
+/* $Id$
+ * Codeset registry DB, generated Fri Feb 28 21:01:30 2003
+ * source: code_set_registry1.2g.txt
+ *
+ * To populate the registry_db, construct a codeset registry text file based
+ * on the OSF's Character and Code Set Registry. See DCE RFC 40.1 for details
+ * on obtaining the full text for the current registry. Once you have composed
+ * a text file containing all the desired codeset information, build and run
+ * mkcsregdb. The source is in $ACE_ROOT/apps/mkcsregdb. It will generate a new
+ * copy of this file, with the registry_db_ array properly initialized.
+ */
+
+#include "ace/Codeset_Registry.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Codeset_Registry::registry_entry const
+ACE_Codeset_Registry::registry_db_[] =
+{
+ {"ISO 8859-1:1987; Latin Alphabet No. 1","ASCII",0x00010001,1,{0x0011},1},
+ {"IBM-1047 (CCSID 01047); Latin-1 Open System","EBCDIC",0x10020417,1,{0x0011},1},
+ {"ISO/IEC 10646-1:1993; UCS-4, Level 1","UCS-4",0x00010104,1,{0x1000},4},
+ {"ISO/IEC 10646-1:1993; UTF-16, UCS Transformation Format 16-bit form","Unicode",0x00010109,1,{0x1000},2},
+ {"X/Open UTF-8; UCS Transformation Format 8 (UTF-8)","UTF-8",0x05010001,1,{0x1000},6}
+};
+
+size_t const ACE_Codeset_Registry::num_registry_entries_ = 5;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Codeset_Symbols.h b/ACE/ace/Codeset_Symbols.h
new file mode 100644
index 00000000000..d2d20ce036b
--- /dev/null
+++ b/ACE/ace/Codeset_Symbols.h
@@ -0,0 +1,220 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Codeset_Symbols.h
+ *
+ * $Id$
+ *
+ * Symbolic names for codeset ids.
+ *
+ * @author Dale Wilson (wilson_d@ociweb.com)
+ */
+//=============================================================================
+#ifndef CODESET_SYMBOLS_H
+#define CODESET_SYMBOLS_H
+
+// These numbers are assigned by the OpenGroup, a database is
+// available at
+//
+// ftp://ftp.opengroup.org/pub/code_set_registry/
+//
+// Alas, the database is in a semi-regular text file -- difficult to use.
+// The following C/C++-friendly version of the codeset ids was captured
+// from Version 1.2g of the registry.
+//
+#define ACE_CODESET_ID_ISO_8859_1 0x00010001U
+#define ACE_CODESET_ID_ISO_8859_2 0x00010002U
+#define ACE_CODESET_ID_ISO_8859_3 0x00010003U
+#define ACE_CODESET_ID_ISO_8859_4 0x00010004U
+#define ACE_CODESET_ID_ISO_8859_5 0x00010005U
+#define ACE_CODESET_ID_ISO_8859_6 0x00010006U
+#define ACE_CODESET_ID_ISO_8859_7 0x00010007U
+#define ACE_CODESET_ID_ISO_8859_8 0x00010008U
+#define ACE_CODESET_ID_ISO_8859_9 0x00010009U
+#define ACE_CODESET_ID_ISO_8859_10 0x0001000AU
+#define ACE_CODESET_ID_ISO_8859_15 0x0001000FU
+#define ACE_CODESET_ID_ISO_646 0x00010020U
+#define ACE_CODESET_ID_ISO_UCS_2_LEVEL_1 0x00010100U
+#define ACE_CODESET_ID_ISO_UCS_2_LEVEL_2 0x00010101U
+#define ACE_CODESET_ID_ISO_UCS_2_LEVEL_3 0x00010102U
+#define ACE_CODESET_ID_ISO_UCS_4_LEVEL_1 0x00010104U
+#define ACE_CODESET_ID_ISO_UCS_4_LEVEL_2 0x00010105U
+#define ACE_CODESET_ID_ISO_UCS_4_LEVEL_3 0x00010106U
+#define ACE_CODESET_ID_ISO_UTF_8 0x00010108U
+#define ACE_CODESET_ID_ISO_UTF_16 0x00010109U
+#define ACE_CODESET_ID_JIS_X0201 0x00030001U
+#define ACE_CODESET_ID_JIS_X0208_1978 0x00030004U
+#define ACE_CODESET_ID_JIS_X0208_1983 0x00030005U
+#define ACE_CODESET_ID_JIS_X0208_1990 0x00030006U
+#define ACE_CODESET_ID_JIS_X0212 0x0003000AU
+#define ACE_CODESET_ID_JIS_EUCJP 0x00030010U
+#define ACE_CODESET_ID_KS_C5601 0x00040001U
+#define ACE_CODESET_ID_KS_C5657 0x00040002U
+#define ACE_CODESET_ID_KS_EUCKR 0x0004000AU
+#define ACE_CODESET_ID_CNS_11643_1986 0x00050001U
+#define ACE_CODESET_ID_CNS_11643_1992 0x00050002U
+#define ACE_CODESET_ID_CNS_EUCTW_1991 0x0005000AU
+#define ACE_CODESET_ID_CNS_EUCTW_1993 0x00050010U
+#define ACE_CODESET_ID_TIS_620_25290X000B0001U
+#define ACE_CODESET_ID_TTB_CCDC 0x000D0001U
+#define ACE_CODESET_ID_OSF_JAPANESE_UJIS 0x05000010U
+#define ACE_CODESET_ID_OSF_JAPANESE_SJIS_1 0x05000011U
+#define ACE_CODESET_ID_OSF_JAPANESE_SJIS_2 0x05000012U
+#define ACE_CODESET_ID_XOPEN_UTF_8 0x05010001U
+#define ACE_CODESET_ID_JVC_EUCJP 0x05020001U
+#define ACE_CODESET_ID_JVC_SJIS 0x05020002U
+#define ACE_CODESET_ID_DEC_KANJI 0x10000001U
+#define ACE_CODESET_ID_SUPER_DEC_KANJI 0x10000002U
+#define ACE_CODESET_ID_DEC_SHIFT_JIS 0x10000003U
+#define ACE_CODESET_ID_HP_ROMAN8 0x10010001U
+#define ACE_CODESET_ID_HP_KANA8 0x10010002U
+#define ACE_CODESET_ID_HP_ARABIC8 0x10010003U
+#define ACE_CODESET_ID_HP_GREEK8 0x10010004U
+#define ACE_CODESET_ID_HP_HEBREW8 0x10010005U
+#define ACE_CODESET_ID_HP_TURKISH8 0x10010006U
+#define ACE_CODESET_ID_HP15CN 0x10010007U
+#define ACE_CODESET_ID_HP_BIG5 0x10010008U
+#define ACE_CODESET_ID_HP_JAPANESE15__SJIS_ 0x10010009U
+#define ACE_CODESET_ID_HP_SJISHI 0x1001000AU
+#define ACE_CODESET_ID_HP_SJISPC 0x1001000BU
+#define ACE_CODESET_ID_HP_UJIS 0x1001000CU
+#define ACE_CODESET_ID_IBM_037 0x10020025U
+#define ACE_CODESET_ID_IBM_273 0x10020111U
+#define ACE_CODESET_ID_IBM_277 0x10020115U
+#define ACE_CODESET_ID_IBM_278 0x10020116U
+#define ACE_CODESET_ID_IBM_280 0x10020118U
+#define ACE_CODESET_ID_IBM_282 0x1002011AU
+#define ACE_CODESET_ID_IBM_284 0x1002011CU
+#define ACE_CODESET_ID_IBM_285 0x1002011DU
+#define ACE_CODESET_ID_IBM_290 0x10020122U
+#define ACE_CODESET_ID_IBM_297 0x10020129U
+#define ACE_CODESET_ID_IBM_300 0x1002012CU
+#define ACE_CODESET_ID_IBM_301 0x1002012DU
+#define ACE_CODESET_ID_IBM_420 0x100201A4U
+#define ACE_CODESET_ID_IBM_424 0x100201A8U
+#define ACE_CODESET_ID_IBM_437 0x100201B5U
+#define ACE_CODESET_ID_IBM_500 0x100201F4U
+#define ACE_CODESET_ID_IBM_833 0x10020341U
+#define ACE_CODESET_ID_IBM_834 0x10020342U
+#define ACE_CODESET_ID_IBM_835 0x10020343U
+#define ACE_CODESET_ID_IBM_836 0x10020344U
+#define ACE_CODESET_ID_IBM_837 0x10020345U
+#define ACE_CODESET_ID_IBM_838 0x10020346U
+#define ACE_CODESET_ID_IBM_839 0x10020347U
+#define ACE_CODESET_ID_IBM_850 0x10020352U
+#define ACE_CODESET_ID_IBM_852 0x10020354U
+#define ACE_CODESET_ID_IBM_855 0x10020357U
+#define ACE_CODESET_ID_IBM_856 0x10020358U
+#define ACE_CODESET_ID_IBM_857 0x10020359U
+#define ACE_CODESET_ID_IBM_861 0x1002035DU
+#define ACE_CODESET_ID_IBM_862 0x1002035EU
+#define ACE_CODESET_ID_IBM_863 0x1002035FU
+#define ACE_CODESET_ID_IBM_864 0x10020360U
+#define ACE_CODESET_ID_IBM_866 0x10020362U
+#define ACE_CODESET_ID_IBM_868 0x10020364U
+#define ACE_CODESET_ID_IBM_869 0x10020365U
+#define ACE_CODESET_ID_IBM_870 0x10020366U
+#define ACE_CODESET_ID_IBM_871 0x10020367U
+#define ACE_CODESET_ID_IBM_874 0x1002036AU
+#define ACE_CODESET_ID_IBM_875 0x1002036BU
+#define ACE_CODESET_ID_IBM_880 0x10020370U
+#define ACE_CODESET_ID_IBM_891 0x1002037BU
+#define ACE_CODESET_ID_IBM_896 0x10020380U
+#define ACE_CODESET_ID_IBM_897 0x10020381U
+#define ACE_CODESET_ID_IBM_903 0x10020387U
+#define ACE_CODESET_ID_IBM_904 0x10020388U
+#define ACE_CODESET_ID_IBM_918 0x10020396U
+#define ACE_CODESET_ID_IBM_921 0x10020399U
+#define ACE_CODESET_ID_IBM_922 0x1002039AU
+#define ACE_CODESET_ID_IBM_926 0x1002039EU
+#define ACE_CODESET_ID_IBM_927 0x1002039FU
+#define ACE_CODESET_ID_IBM_928 0x100203A0U
+#define ACE_CODESET_ID_IBM_929 0x100203A1U
+#define ACE_CODESET_ID_IBM_930 0x100203A2U
+#define ACE_CODESET_ID_IBM_932 0x100203A4U
+#define ACE_CODESET_ID_IBM_933 0x100203A5U
+#define ACE_CODESET_ID_IBM_934 0x100203A6U
+#define ACE_CODESET_ID_IBM_935 0x100203A7U
+#define ACE_CODESET_ID_IBM_936 0x100203A8U
+#define ACE_CODESET_ID_IBM_937 0x100203A9U
+#define ACE_CODESET_ID_IBM_938 0x100203AAU
+#define ACE_CODESET_ID_IBM_939 0x100203ABU
+#define ACE_CODESET_ID_IBM_941 0x100203ADU
+#define ACE_CODESET_ID_IBM_942 0x100203AEU
+#define ACE_CODESET_ID_IBM_943 0x100203AFU
+#define ACE_CODESET_ID_IBM_946 0x100203B2U
+#define ACE_CODESET_ID_IBM_947 0x100203B3U
+#define ACE_CODESET_ID_IBM_948 0x100203B4U
+#define ACE_CODESET_ID_IBM_949 0x100203B5U
+#define ACE_CODESET_ID_IBM_950 0x100203B6U
+#define ACE_CODESET_ID_IBM_951 0x100203B7U
+#define ACE_CODESET_ID_IBM_955 0x100203BBU
+#define ACE_CODESET_ID_IBM_964 0x100203C4U
+#define ACE_CODESET_ID_IBM_970 0x100203CAU
+#define ACE_CODESET_ID_IBM_1006 0x100203EEU
+#define ACE_CODESET_ID_IBM_1025 0x10020401U
+#define ACE_CODESET_ID_IBM_1026 0x10020402U
+#define ACE_CODESET_ID_IBM_1027 0x10020403U
+#define ACE_CODESET_ID_IBM_1040 0x10020410U
+#define ACE_CODESET_ID_IBM_1041 0x10020411U
+#define ACE_CODESET_ID_IBM_1043 0x10020413U
+#define ACE_CODESET_ID_IBM_1046 0x10020416U
+#define ACE_CODESET_ID_IBM_1047 0x10020417U
+#define ACE_CODESET_ID_IBM_1088 0x10020440U
+#define ACE_CODESET_ID_IBM_1097 0x10020449U
+#define ACE_CODESET_ID_IBM_1098 0x1002044AU
+#define ACE_CODESET_ID_IBM_1112 0x10020458U
+#define ACE_CODESET_ID_IBM_1114 0x1002045AU
+#define ACE_CODESET_ID_IBM_1115 0x1002045BU
+#define ACE_CODESET_ID_IBM_1122 0x10020462U
+#define ACE_CODESET_ID_IBM_1250 0x100204E2U
+#define ACE_CODESET_ID_IBM_1251 0x100204E3U
+#define ACE_CODESET_ID_IBM_1252 0x100204E4U
+#define ACE_CODESET_ID_IBM_1253 0x100204E5U
+#define ACE_CODESET_ID_IBM_1254 0x100204E6U
+#define ACE_CODESET_ID_IBM_1255 0x100204E7U
+#define ACE_CODESET_ID_IBM_1256 0x100204E8U
+#define ACE_CODESET_ID_IBM_1257 0x100204E9U
+#define ACE_CODESET_ID_IBM_1380 0x10020564U
+#define ACE_CODESET_ID_IBM_1381 0x10020565U
+#define ACE_CODESET_ID_IBM_1383 0x10020567U
+#define ACE_CODESET_ID_IBM_4396 0x1002112CU
+#define ACE_CODESET_ID_IBM_4946 0x10021352U
+#define ACE_CODESET_ID_IBM_4948 0x10021354U
+#define ACE_CODESET_ID_IBM_4951 0x10021357U
+#define ACE_CODESET_ID_IBM_4952 0x10021358U
+#define ACE_CODESET_ID_IBM_4953 0x10021359U
+#define ACE_CODESET_ID_IBM_4960 0x10021360U
+#define ACE_CODESET_ID_IBM_4964 0x10021364U
+#define ACE_CODESET_ID_IBM_4965 0x10021365U
+#define ACE_CODESET_ID_IBM_5026 0x100213A2U
+#define ACE_CODESET_ID_IBM_5031 0x100213A7U
+#define ACE_CODESET_ID_IBM_5035 0x100213ABU
+#define ACE_CODESET_ID_IBM_5048 0x100213B8U
+#define ACE_CODESET_ID_IBM_5049 0x100213B9U
+#define ACE_CODESET_ID_IBM_5067 0x100213CBU
+#define ACE_CODESET_ID_IBM_8612 0x100221A4U
+#define ACE_CODESET_ID_IBM_9025 0x10022341U
+#define ACE_CODESET_ID_IBM_9026 0x10022342U
+#define ACE_CODESET_ID_IBM_9030 0x10022346U
+#define ACE_CODESET_ID_IBM_9056 0x10022360U
+#define ACE_CODESET_ID_IBM_9066 0x1002236AU
+#define ACE_CODESET_ID_IBM_9125 0x100223A5U
+#define ACE_CODESET_ID_IBM_25426 0x10026352U
+#define ACE_CODESET_ID_IBM_25432 0x10026358U
+#define ACE_CODESET_ID_IBM_1042 0x10026412U
+#define ACE_CODESET_ID_IBM_28709 0x10027025U
+#define ACE_CODESET_ID_IBM_33624 0x10028358U
+#define ACE_CODESET_ID_IBM_33722 0x100283BAU
+#define ACE_CODESET_ID_HTCSJIS 0x10030001U
+#define ACE_CODESET_ID_HTCUJIS 0x10030002U
+#define ACE_CODESET_ID_FUJITSU_U90 0x10040001U
+#define ACE_CODESET_ID_FUJITSU_S90 0x10040002U
+#define ACE_CODESET_ID_FUJITSU_R90 0x10040003U
+#define ACE_CODESET_ID_EBCDIC_ASCII_AND_JEF 0x10040004U
+#define ACE_CODESET_ID_EBCDIC_KATAKANA_AND_JEF 0x10040005U
+#define ACE_CODESET_ID_EBCDIC_JAPANESE_ENGLISH_AND_JEF 0x10040006U
+
+#define ACE_CODESET_ID_TAO_BACKWARD_COMPATIBLE 0xf54414F0U
+#endif // CODESET_SYMBOLS_H
diff --git a/ACE/ace/Condition_Recursive_Thread_Mutex.cpp b/ACE/ace/Condition_Recursive_Thread_Mutex.cpp
new file mode 100644
index 00000000000..af80f4bfbfd
--- /dev/null
+++ b/ACE/ace/Condition_Recursive_Thread_Mutex.cpp
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+
+/**
+ * @file Condition_Recursive_Thread_Mutex.cpp
+ *
+ * $Id$
+ *
+ * Originally in Synch.cpp
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+
+#include "ace/Condition_Recursive_Thread_Mutex.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#if defined (ACE_HAS_DUMP)
+# include "ace/Log_Msg.h"
+#endif /* ACE_HAS_DUMP */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_Condition<ACE_Recursive_Thread_Mutex>::remove (void)
+{
+ return ACE_OS::cond_destroy (&this->cond_);
+}
+
+void
+ACE_Condition<ACE_Recursive_Thread_Mutex>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Condition<MUTEX>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ // No dump method for ACE_cond_t even in emulated mode.
+ // cond_.dump ();
+ this->mutex_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Condition<ACE_Recursive_Thread_Mutex>::~ACE_Condition (void)
+{
+ this->remove ();
+}
+
+ACE_Condition<ACE_Recursive_Thread_Mutex>::ACE_Condition (ACE_Recursive_Thread_Mutex &m)
+ : mutex_ (m)
+{
+ ACE_OS::cond_init (&this->cond_);
+}
+
+int
+ACE_Condition<ACE_Recursive_Thread_Mutex>::wait (const ACE_Time_Value *abstime)
+{
+ return this->wait (this->mutex_, abstime);
+}
+
+int
+ACE_Condition<ACE_Recursive_Thread_Mutex>::wait (ACE_Recursive_Thread_Mutex &mutex,
+ const ACE_Time_Value *abstime)
+{
+ ACE_recursive_mutex_state mutex_state_holder;
+ ACE_recursive_thread_mutex_t &recursive_mutex = mutex.mutex ();
+
+ if (ACE_OS::recursive_mutex_cond_unlock (&recursive_mutex,
+ mutex_state_holder) == -1)
+ return -1;
+
+ // We wait on the condition, specifying the nesting mutex. For platforms
+ // with ACE_HAS_RECURSIVE_MUTEXES, this is the recursive mutex itself,
+ // and is the same as recursive_mutex, above. The caller should have been
+ // holding the lock on entry to this method, and it is still held.
+ // For other platforms, this is the nesting mutex that guards the
+ // ACE_recursive_mutex_t internals, and recursive_mutex_cond_unlock()
+ // returned with the lock held, but waiters primed and waiting to be
+ // released. At cond_wait below, the mutex will be released.
+ // On return, it will be reacquired.
+ const int result = abstime == 0
+ ? ACE_OS::cond_wait (&this->cond_,
+ &mutex.get_nesting_mutex ())
+ : ACE_OS::cond_timedwait (&this->cond_,
+ &mutex.get_nesting_mutex (),
+ const_cast <ACE_Time_Value *> (abstime));
+ // We are holding the mutex, whether the wait succeeded or failed.
+ // Stash errno (in case it failed) and then we need to reset the
+ // recursive mutex state to what it was on entry to this method.
+ // Resetting it may require a wait for another thread to release
+ // the ACE_recursive_thread_mutex_t if this is a platform without
+ // ACE_HAS_RECURSIVE_MUTEXES, and recursive_mutex_cond_relock() takes
+ // care of that.
+ {
+ ACE_Errno_Guard error (errno);
+ ACE_OS::recursive_mutex_cond_relock (&recursive_mutex,
+ mutex_state_holder);
+ }
+
+ return result;
+}
+
+int
+ACE_Condition<ACE_Recursive_Thread_Mutex>::signal (void)
+{
+ return ACE_OS::cond_signal (&this->cond_);
+}
+
+int
+ACE_Condition<ACE_Recursive_Thread_Mutex>::broadcast (void)
+{
+ return ACE_OS::cond_broadcast (&this->cond_);
+}
+
+ACE_Recursive_Thread_Mutex &
+ACE_Condition<ACE_Recursive_Thread_Mutex>::mutex (void)
+{
+ return this->mutex_;
+}
+
+ACE_Condition_Recursive_Thread_Mutex::ACE_Condition_Recursive_Thread_Mutex (
+ ACE_Recursive_Thread_Mutex &m) :
+ ACE_Condition<ACE_Recursive_Thread_Mutex> (m)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/Condition_Recursive_Thread_Mutex.h b/ACE/ace/Condition_Recursive_Thread_Mutex.h
new file mode 100644
index 00000000000..cfcd46a9551
--- /dev/null
+++ b/ACE/ace/Condition_Recursive_Thread_Mutex.h
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Condition_Recursive_Thread_Mutex.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_CONDITION_RECURSIVE_THREAD_MUTEX_H
+#define ACE_CONDITION_RECURSIVE_THREAD_MUTEX_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_HAS_THREADS)
+# include "ace/Null_Condition.h"
+#else /* ACE_HAS_THREADS */
+#include "ace/Recursive_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_LOCK> class ACE_Condition;
+
+/**
+ * @class ACE_Condition<ACE_Recursive_Thread_Mutex>
+ *
+ * @brief ACE_Condition template specialization written using
+ * @a ACE_Recursive_Thread_Mutex. This allows threads to block until
+ * shared data changes state using recursive mutexes.
+ */
+template<>
+class ACE_Export ACE_Condition<ACE_Recursive_Thread_Mutex>
+{
+public:
+ /// Initialize the condition variable with a recursive mutex.
+ ACE_Condition (ACE_Recursive_Thread_Mutex &m);
+
+ /// Implicitly destroy the condition variable.
+ ~ACE_Condition (void);
+
+ /**
+ * Explicitly destroy the condition variable. Note that only one
+ * thread should call this method since it doesn't protect against
+ * race conditions.
+ */
+ int remove (void);
+
+ /**
+ * Block on condition, or until absolute time-of-day has passed. If
+ * abstime == 0 use "blocking" <wait> semantics. Else, if <abstime>
+ * != 0 and the call times out before the condition is signaled
+ * <wait> returns -1 and sets errno to ETIME.
+ */
+ int wait (const ACE_Time_Value *abstime = 0);
+
+ /**
+ * Block on condition or until absolute time-of-day has passed. If
+ * abstime == 0 use "blocking" wait() semantics on the recursive @a mutex
+ * passed as a parameter (this is useful if you need to store the
+ * <Condition> in shared memory). Else, if <abstime> != 0 and the
+ * call times out before the condition is signaled <wait> returns -1
+ * and sets errno to ETIME.
+ */
+ int wait (ACE_Recursive_Thread_Mutex &mutex,
+ const ACE_Time_Value *abstime = 0);
+
+ /// Signal one waiting thread.
+ int signal (void);
+
+ /// Signal *all* waiting threads.
+ int broadcast (void);
+
+ /// Returns a reference to the underlying mutex;
+ ACE_Recursive_Thread_Mutex &mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+private:
+
+ // = Prevent assignment and copying.
+ void operator= (const ACE_Condition<ACE_Recursive_Thread_Mutex> &);
+ ACE_Condition (const ACE_Condition<ACE_Recursive_Thread_Mutex> &);
+
+private:
+
+ /// A normal (i.e., non-recursive) condition variable.
+ ACE_cond_t cond_;
+
+ /// Reference to the recursive mutex.
+ ACE_Recursive_Thread_Mutex &mutex_;
+
+};
+
+class ACE_Export ACE_Condition_Recursive_Thread_Mutex
+ : public ACE_Condition<ACE_Recursive_Thread_Mutex>
+{
+public:
+ /// Initialize the condition variable with a recursive mutex.
+ ACE_Condition_Recursive_Thread_Mutex (ACE_Recursive_Thread_Mutex &m);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONDITION_RECURSIVE_THREAD_MUTEX_H */
diff --git a/ACE/ace/Condition_T.cpp b/ACE/ace/Condition_T.cpp
new file mode 100644
index 00000000000..fa0dab4e80a
--- /dev/null
+++ b/ACE/ace/Condition_T.cpp
@@ -0,0 +1,123 @@
+// $Id$
+
+#ifndef ACE_CONDITION_T_CPP
+#define ACE_CONDITION_T_CPP
+
+#include "ace/Condition_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Condition_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Condition)
+
+template <class MUTEX> void
+ACE_Condition<MUTEX>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Condition<MUTEX>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class MUTEX>
+ACE_Thread_Condition<MUTEX>::ACE_Thread_Condition (MUTEX &m,
+ const ACE_TCHAR *name,
+ void *arg)
+ : ACE_Condition<MUTEX> (m, USYNC_THREAD, name, arg)
+{
+// ACE_TRACE ("ACE_Thread_Condition<MUTEX>::ACE_Thread_Condition");
+}
+
+template <class MUTEX> void
+ACE_Thread_Condition<MUTEX>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Thread_Condition<MUTEX>::dump");
+
+ ACE_Condition<MUTEX>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class MUTEX>
+ACE_Condition<MUTEX>::ACE_Condition (MUTEX &m,
+ int type,
+ const ACE_TCHAR *name,
+ void *arg)
+ :
+ mutex_ (m)
+{
+ // ACE_TRACE ("ACE_Condition<MUTEX>::ACE_Condition");
+
+ if (ACE_OS::cond_init (&this->cond_,
+ (short) type,
+ name,
+ arg) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Condition::ACE_Condition")));
+}
+
+template <class MUTEX>
+ACE_Condition<MUTEX>::~ACE_Condition (void)
+{
+ // ACE_TRACE ("ACE_Condition<MUTEX>::~ACE_Condition");
+
+ if (this->remove () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Condition::~ACE_Condition")));
+}
+
+template <class MUTEX> int
+ACE_Condition<MUTEX>::wait (void)
+{
+ // ACE_TRACE ("ACE_Condition<MUTEX>::wait");
+ return ACE_OS::cond_wait (&this->cond_,
+ &this->mutex_.lock_);
+}
+
+template <class MUTEX> int
+ACE_Condition<MUTEX>::wait (MUTEX &mutex,
+ const ACE_Time_Value *abstime)
+{
+// ACE_TRACE ("ACE_Condition<MUTEX>::wait");
+ if (abstime == 0)
+ return this->wait ();
+ else
+ {
+ return ACE_OS::cond_timedwait (&this->cond_,
+ &mutex.lock_,
+ (ACE_Time_Value *) abstime);
+ }
+}
+
+// Peform an "alertable" timed wait. If the argument ABSTIME == 0
+// then we do a regular cond_wait(), else we do a timed wait for up to
+// ABSTIME using the Solaris cond_timedwait() function.
+
+template <class MUTEX> int
+ACE_Condition<MUTEX>::wait (const ACE_Time_Value *abstime)
+{
+// ACE_TRACE ("ACE_Condition<MUTEX>::wait");
+ return this->wait (this->mutex_, abstime);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
+
+#endif /* ACE_CONDITION_T_CPP */
diff --git a/ACE/ace/Condition_T.h b/ACE/ace/Condition_T.h
new file mode 100644
index 00000000000..535642a77e8
--- /dev/null
+++ b/ACE/ace/Condition_T.h
@@ -0,0 +1,167 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Condition_T.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_CONDITION_T_H
+#define ACE_CONDITION_T_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/OS_NS_Thread.h"
+#include "ace/Lock.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_THREADS) /* ACE platform supports some form of threading. */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Condition
+ *
+ * @brief ACE_Condition variable wrapper, which allows threads to block
+ * until shared data changes state.
+ *
+ * A condition variable enables threads to atomically block and
+ * test the condition under the protection of a mutual exclu-
+ * sion lock (mutex) until the condition is satisfied. That is,
+ * the mutex must have been held by the thread before calling
+ * wait or signal on the condition. If the condition is false,
+ * a thread blocks on a condition variable and atomically
+ * releases the mutex that is waiting for the condition to
+ * change. If another thread changes the condition, it may wake
+ * up waiting threads by signaling the associated condition
+ * variable. The waiting threads, upon awakening, reacquire the
+ * mutex and re-evaluate the condition.
+ * Note, you can only parameterize <ACE_Condition> with
+ * @a ACE_Thread_Mutex, @a ACE_Recursive_Thread_Mutex, or @a ACE_Null_Mutex.
+ */
+template <class MUTEX>
+class ACE_Condition
+{
+public:
+ // = Initialiation and termination methods.
+ /// Initialize the condition variable.
+ ACE_Condition (MUTEX &m, int type = USYNC_THREAD,
+ const ACE_TCHAR *name = 0, void *arg = 0);
+
+ /// Implicitly destroy the condition variable.
+ ~ACE_Condition (void);
+
+ // = Lock accessors.
+ /**
+ * Block on condition, or until absolute time-of-day has passed. If
+ * abstime == 0 use "blocking" <wait> semantics. Else, if <abstime>
+ * != 0 and the call times out before the condition is signaled
+ * <wait> returns -1 and sets errno to ETIME.
+ */
+ int wait (const ACE_Time_Value *abstime);
+
+ /// Block on condition.
+ int wait (void);
+
+ /**
+ * Block on condition or until absolute time-of-day has passed. If
+ * abstime == 0 use "blocking" wait() semantics on the <mutex>
+ * passed as a parameter (this is useful if you need to store the
+ * <Condition> in shared memory). Else, if <abstime> != 0 and the
+ * call times out before the condition is signaled <wait> returns -1
+ * and sets errno to ETIME.
+ */
+ int wait (MUTEX &mutex, const ACE_Time_Value *abstime = 0);
+
+ /// Signal one waiting thread.
+ int signal (void);
+
+ /// Signal *all* waiting threads.
+ int broadcast (void);
+
+ // = Utility methods.
+ /// Explicitly destroy the condition variable.
+ int remove (void);
+
+ /// Returns a reference to the underlying mutex_;
+ MUTEX &mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+protected:
+ /// Condition variable.
+ ACE_cond_t cond_;
+
+ /// Reference to mutex lock.
+ MUTEX &mutex_;
+
+private:
+ // = Prevent assignment and initialization.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Condition<MUTEX> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Condition (const ACE_Condition<MUTEX> &))
+};
+
+/**
+ * @class ACE_Thread_Condition
+ *
+ * @brief ACE_Condition variable wrapper that works within processes.
+ *
+ * A condition variable enables threads to atomically block and
+ * test the condition under the protection of a mutual exclu-
+ * sion lock (mutex) until the condition is satisfied. That is,
+ * the mutex must have been held by the thread before calling
+ * wait or signal on the condition. If the condition is false,
+ * a thread blocks on a condition variable and atomically
+ * releases the mutex that is waiting for the condition to
+ * change. If another thread changes the condition, it may wake
+ * up waiting threads by signaling the associated condition
+ * variable. The waiting threads, upon awakening, reacquire the
+ * mutex and re-evaluate the condition.
+ */
+template <class MUTEX>
+class ACE_Thread_Condition : public ACE_Condition<MUTEX>
+{
+public:
+ // = Initialization method.
+ ACE_Thread_Condition (MUTEX &m, const ACE_TCHAR *name = 0, void *arg = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Condition_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Condition_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Condition_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONDITION_T_H */
diff --git a/ACE/ace/Condition_T.inl b/ACE/ace/Condition_T.inl
new file mode 100644
index 00000000000..fd7bdb7abdc
--- /dev/null
+++ b/ACE/ace/Condition_T.inl
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class MUTEX> ACE_INLINE int
+ACE_Condition<MUTEX>::remove (void)
+{
+ // ACE_TRACE ("ACE_Condition<MUTEX>::remove");
+
+ // cond_destroy() is called in a loop if the condition variable is
+ // BUSY. This avoids a condition where a condition is signaled and
+ // because of some timing problem, the thread that is to be signaled
+ // has called the cond_wait routine after the signal call. Since
+ // the condition signal is not queued in any way, deadlock occurs.
+
+ int result = 0;
+
+ while ((result = ACE_OS::cond_destroy (&this->cond_)) == -1
+ && errno == EBUSY)
+ {
+ ACE_OS::cond_broadcast (&this->cond_);
+ ACE_OS::thr_yield ();
+ }
+
+ return result;
+}
+
+template<class MUTEX> ACE_INLINE MUTEX &
+ACE_Condition<MUTEX>::mutex (void)
+{
+ // ACE_TRACE ("ACE_Condition<MUTEX>::mutex");
+ return this->mutex_;
+}
+
+template <class MUTEX> ACE_INLINE int
+ACE_Condition<MUTEX>::signal (void)
+{
+// ACE_TRACE ("ACE_Condition<MUTEX>::signal");
+ return ACE_OS::cond_signal (&this->cond_);
+}
+
+template <class MUTEX> ACE_INLINE int
+ACE_Condition<MUTEX>::broadcast (void)
+{
+// ACE_TRACE ("ACE_Condition<MUTEX>::broadcast");
+ return ACE_OS::cond_broadcast (&this->cond_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Condition_Thread_Mutex.cpp b/ACE/ace/Condition_Thread_Mutex.cpp
new file mode 100644
index 00000000000..1535b4c87f3
--- /dev/null
+++ b/ACE/ace/Condition_Thread_Mutex.cpp
@@ -0,0 +1,126 @@
+/* -*- C++ -*- */
+/**
+ * @file Condition_Thread_Mutex.cpp
+ *
+ * $Id$
+ *
+ * Originally in Synch.cpp
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+
+#include "ace/Condition_Thread_Mutex.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Condition_Thread_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Condition_Thread_Mutex, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Condition_Thread_Mutex)
+
+void
+ACE_Condition_Thread_Mutex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+#if defined (ACE_WIN32)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("waiters = %d\n"),
+ this->cond_.waiters ()));
+#endif /* ACE_WIN32 */
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Condition_Thread_Mutex::ACE_Condition_Thread_Mutex (ACE_Thread_Mutex &m,
+ const ACE_TCHAR *name,
+ void *arg)
+ : mutex_ (m),
+ removed_ (false)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::ACE_Condition_Thread_Mutex");
+ if (ACE_OS::cond_init (&this->cond_,
+ (short) USYNC_THREAD,
+ name,
+ arg) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Condition_Thread_Mutex::ACE_Condition_Thread_Mutex")));
+}
+
+ACE_Condition_Thread_Mutex::
+ACE_Condition_Thread_Mutex (ACE_Thread_Mutex &m,
+ ACE_Condition_Attributes &attributes,
+ const ACE_TCHAR *name,
+ void *arg)
+ : mutex_ (m),
+ removed_ (false)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::ACE_Condition_Thread_Mutex");
+ if (ACE_OS::cond_init (&this->cond_, attributes.attributes_,
+ name, arg) != 0)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Condition_Thread_Mutex::ACE_Condition_Thread_Mutex")));
+}
+
+ACE_Condition_Thread_Mutex::~ACE_Condition_Thread_Mutex (void)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::~ACE_Condition_Thread_Mutex");
+ this->remove ();
+}
+
+// Peform an "alertable" timed wait. If the argument <abstime> == 0
+// then we do a regular <cond_wait>, else we do a timed wait for up to
+// <abstime> using the <cond_timedwait> function.
+
+int
+ACE_Condition_Thread_Mutex::wait (void)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::wait");
+ return ACE_OS::cond_wait (&this->cond_, &this->mutex_.lock_);
+}
+
+int
+ACE_Condition_Thread_Mutex::wait (ACE_Thread_Mutex &mutex,
+ const ACE_Time_Value *abstime)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::wait");
+ return ACE_OS::cond_timedwait (&this->cond_,
+ &mutex.lock_,
+ const_cast <ACE_Time_Value *> (abstime));
+}
+
+int
+ACE_Condition_Thread_Mutex::wait (const ACE_Time_Value *abstime)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::wait");
+ return this->wait (this->mutex_, abstime);
+}
+
+int
+ACE_Condition_Thread_Mutex::signal (void)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::signal");
+ return ACE_OS::cond_signal (&this->cond_);
+}
+
+int
+ACE_Condition_Thread_Mutex::broadcast (void)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::broadcast");
+ return ACE_OS::cond_broadcast (&this->cond_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/Condition_Thread_Mutex.h b/ACE/ace/Condition_Thread_Mutex.h
new file mode 100644
index 00000000000..2806f03691e
--- /dev/null
+++ b/ACE/ace/Condition_Thread_Mutex.h
@@ -0,0 +1,190 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Condition_Thread_Mutex.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_CONDITION_THREAD_MUTEX_H
+#define ACE_CONDITION_THREAD_MUTEX_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_HAS_THREADS)
+# include "ace/Null_Condition.h"
+#else /* ACE_HAS_THREADS */
+// ACE platform supports some form of threading.
+
+#include "ace/Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+class ACE_Export ACE_Condition_Attributes
+{
+public:
+ /// Constructor
+ ACE_Condition_Attributes (int type = ACE_DEFAULT_SYNCH_TYPE);
+
+ /// Destructor
+ ~ACE_Condition_Attributes (void);
+
+private:
+ friend class ACE_Condition_Thread_Mutex;
+
+ /// The attributes
+ ACE_condattr_t attributes_;
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Condition_Attributes &);
+ ACE_Condition_Attributes (const ACE_Condition_Attributes &);
+};
+
+/**
+ * @class ACE_Condition_Thread_Mutex
+ *
+ * @brief ACE_Condition variable wrapper written using ACE_Mutexes This
+ * allows threads to block until shared data changes state.
+ * A condition variable enables threads to atomically block and
+ * test the condition under the protection of a mutual exclu-
+ * sion lock (mutex) until the condition is satisfied. That is,
+ * the mutex must have been held by the thread before calling
+ * wait or signal on the condition. If the condition is false,
+ * a thread blocks on a condition variable and atomically
+ * releases the mutex that is waiting for the condition to
+ * change. If another thread changes the condition, it may wake
+ * up waiting threads by signaling the associated condition
+ * variable. The waiting threads, upon awakening, reacquire the
+ * mutex and re-evaluate the condition.
+ *
+ * This should be an instantiation of ACE_Condition but problems
+ * with compilers precludes this...
+ */
+class ACE_Export ACE_Condition_Thread_Mutex
+{
+public:
+ /// Initialize the condition variable.
+ ACE_Condition_Thread_Mutex (ACE_Thread_Mutex &m,
+ const ACE_TCHAR *name = 0,
+ void *arg = 0);
+
+ /// Initialize the condition variable.
+ ACE_Condition_Thread_Mutex (ACE_Thread_Mutex &m,
+ ACE_Condition_Attributes &attributes,
+ const ACE_TCHAR *name = 0,
+ void *arg = 0);
+
+ /// Implicitly destroy the condition variable.
+ ~ACE_Condition_Thread_Mutex (void);
+
+ /**
+ * Explicitly destroy the condition variable. Note that only one
+ * thread should call this method since it doesn't protect against
+ * race conditions.
+ */
+ int remove (void);
+
+ /**
+ * Block on condition, or until absolute time-of-day has passed. If
+ * abstime == 0 use "blocking" <wait> semantics. Else, if @a abstime
+ * != 0 and the call times out before the condition is signaled
+ * <wait> returns -1 and sets errno to ETIME.
+ */
+ int wait (const ACE_Time_Value *abstime);
+
+ /// Block on condition.
+ int wait (void);
+
+ /**
+ * Block on condition or until absolute time-of-day has passed. If
+ * abstime == 0 use "blocking" wait() semantics on the <mutex>
+ * passed as a parameter (this is useful if you need to store the
+ * <Condition> in shared memory). Else, if @a abstime != 0 and the
+ * call times out before the condition is signaled <wait> returns -1
+ * and sets errno to ETIME.
+ */
+ int wait (ACE_Thread_Mutex &mutex, const ACE_Time_Value *abstime = 0);
+
+ /// Signal one waiting thread.
+ int signal (void);
+
+ /// Signal *all* waiting threads.
+ int broadcast (void);
+
+ /// Returns a reference to the underlying mutex;
+ ACE_Thread_Mutex &mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Condition variable.
+ ACE_cond_t cond_;
+
+ /// Reference to mutex lock.
+ ACE_Thread_Mutex &mutex_;
+
+ /// Keeps track of whether <remove> has been called yet to avoid
+ /// multiple <remove> calls, e.g., explicitly and implicitly in the
+ /// destructor. This flag isn't protected by a lock, so make sure
+ /// that you don't have multiple threads simultaneously calling
+ /// <remove> on the same object, which is a bad idea anyway...
+ bool removed_;
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Condition_Thread_Mutex &);
+ ACE_Condition_Thread_Mutex (const ACE_Condition_Thread_Mutex &);
+};
+
+#if 0
+// The following class is commented out since there doesn't
+// appear to be a portable and robust means of implementing this
+// functionality across platforms. If you know of a portable and
+// robust way to implement this functionality please let us know.
+
+/**
+ * @class ACE_Process_Condition
+ *
+ * @brief ACE_Condition variable wrapper that works across processes.
+ */
+class ACE_Export ACE_Process_Condition
+{
+public:
+ ACE_Process_Condition (MUTEX &m, const ACE_TCHAR *name = 0, void *arg = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+};
+#endif /* 0 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Condition_Thread_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* !ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONDITION_THREAD_MUTEX_H */
diff --git a/ACE/ace/Condition_Thread_Mutex.inl b/ACE/ace/Condition_Thread_Mutex.inl
new file mode 100644
index 00000000000..12cc18a1bad
--- /dev/null
+++ b/ACE/ace/Condition_Thread_Mutex.inl
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Condition_Attributes::ACE_Condition_Attributes (int type)
+{
+ (void) ACE_OS::condattr_init (this->attributes_, type);
+}
+
+ACE_INLINE
+ACE_Condition_Attributes::~ACE_Condition_Attributes (void)
+{
+ ACE_OS::condattr_destroy (this->attributes_);
+}
+
+ACE_INLINE int
+ACE_Condition_Thread_Mutex::remove (void)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::remove");
+
+ // <cond_destroy> is called in a loop if the condition variable is
+ // BUSY. This avoids a condition where a condition is signaled and
+ // because of some timing problem, the thread that is to be signaled
+ // has called the cond_wait routine after the signal call. Since
+ // the condition signal is not queued in any way, deadlock occurs.
+
+ int result = 0;
+
+ if (!this->removed_)
+ {
+ this->removed_ = true;
+
+ while ((result = ACE_OS::cond_destroy (&this->cond_)) == -1
+ && errno == EBUSY)
+ {
+ ACE_OS::cond_broadcast (&this->cond_);
+ ACE_OS::thr_yield ();
+ }
+ }
+ return result;
+}
+
+ACE_INLINE ACE_Thread_Mutex &
+ACE_Condition_Thread_Mutex::mutex (void)
+{
+// ACE_TRACE ("ACE_Condition_Thread_Mutex::mutex");
+ return this->mutex_;
+}
+
+#if 0
+template <class MUTEX> void
+ACE_Process_Condition<MUTEX>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Process_Condition<MUTEX>::dump");
+
+ ACE_Condition<MUTEX>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class MUTEX>
+ACE_Process_Condition<MUTEX>::ACE_Process_Condition (MUTEX &m,
+ const ACE_TCHAR *name,
+ void *arg)
+ : ACE_Condition<MUTEX> (m, USYNC_PROCESS, name, arg)
+{
+// ACE_TRACE ("ACE_Process_Condition<MUTEX>::ACE_Process_Condition");
+}
+#endif /* 0 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Configuration.cpp b/ACE/ace/Configuration.cpp
new file mode 100644
index 00000000000..b54308ade7d
--- /dev/null
+++ b/ACE/ace/Configuration.cpp
@@ -0,0 +1,2148 @@
+// $Id$
+#include "ace/Configuration.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/SString.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_strings.h"
+
+// Can remove this when import_config and export_config are removed from
+// ACE_Configuration. They're deprecated at ACE 5.2.
+#include "ace/Configuration_Import_Export.h"
+
+#if !defined (ACE_LACKS_ACCESS)
+# include "ace/OS_NS_unistd.h"
+#endif /* ACE_LACKS_ACCESS */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Configuration.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Section_Key_Internal::ACE_Section_Key_Internal (void)
+ : ref_count_ (0)
+{
+}
+
+ACE_Section_Key_Internal::~ACE_Section_Key_Internal (void)
+{
+}
+
+int
+ACE_Section_Key_Internal::add_ref (void)
+{
+ ++ref_count_;
+ return 0;
+}
+
+int
+ACE_Section_Key_Internal::dec_ref (void)
+{
+ if (!--ref_count_)
+ delete this;
+ return 0;
+}
+
+ACE_Configuration_Section_Key::ACE_Configuration_Section_Key (void)
+ : key_ (0)
+{
+}
+
+ACE_Configuration_Section_Key::~ACE_Configuration_Section_Key (void)
+{
+ if (key_)
+ key_->dec_ref ();
+}
+
+ACE_Configuration_Section_Key::ACE_Configuration_Section_Key (ACE_Section_Key_Internal* key)
+ : key_ (key)
+{
+ if (key_)
+ key_->add_ref ();
+}
+
+ACE_Configuration_Section_Key::ACE_Configuration_Section_Key (const ACE_Configuration_Section_Key& rhs)
+ : key_ (rhs.key_)
+{
+ if (key_)
+ key_->add_ref ();
+}
+
+ACE_Configuration_Section_Key&
+ACE_Configuration_Section_Key::operator= (const ACE_Configuration_Section_Key& rhs)
+{
+ if (this != &rhs)
+ {
+ if (key_)
+ key_->dec_ref ();
+
+ key_ = rhs.key_;
+
+ if (key_)
+ key_->add_ref ();
+ }
+ return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+ACE_TCHAR ACE_Configuration::NULL_String_ = '\0';
+
+ACE_Configuration::ACE_Configuration (void)
+ : root_ ()
+{
+}
+
+ACE_Configuration::~ACE_Configuration (void)
+{
+}
+
+ACE_Section_Key_Internal*
+ACE_Configuration::get_internal_key (const ACE_Configuration_Section_Key& key)
+{
+ return key.key_;
+}
+
+int
+ACE_Configuration::expand_path (const ACE_Configuration_Section_Key& key,
+ const ACE_TString& path_in,
+ ACE_Configuration_Section_Key& key_out,
+ int create)
+{
+ // Make a copy of key
+ ACE_Configuration_Section_Key current_section = key;
+ ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> pData (path_in.rep ());
+ ACE_Tokenizer parser (pData.get ());
+ parser.delimiter_replace ('\\', '\0');
+ parser.delimiter_replace ('/', '\0');
+
+ for (ACE_TCHAR *temp = parser.next ();
+ temp != 0;
+ temp = parser.next ())
+ {
+ // Open the section
+ if (open_section (current_section,
+ temp,
+ create,
+ key_out))
+ return -1;
+
+ current_section = key_out;
+ }
+
+ return 0;
+
+}
+
+// import_config and export_config are here for backward compatibility,
+// and have been deprecated.
+int
+ACE_Configuration::export_config (const ACE_TCHAR* filename)
+{
+ ACE_Registry_ImpExp exporter (*this);
+ return exporter.export_config (filename);
+}
+
+int
+ACE_Configuration::import_config (const ACE_TCHAR* filename)
+{
+ ACE_Registry_ImpExp importer (*this);
+ return importer.import_config (filename);
+}
+
+int
+ACE_Configuration::validate_name (const ACE_TCHAR* name, int allow_path)
+{
+ // Invalid character set
+ const ACE_TCHAR* reject =
+ allow_path ? ACE_TEXT ("][") : ACE_TEXT ("\\][");
+
+ // Position of the first invalid character or terminating null.
+ size_t const pos = ACE_OS::strcspn (name, reject);
+
+ // Check if it is an invalid character.
+ if (name[pos] != ACE_TEXT ('\0'))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // The first character can never be a path separator.
+ if (name[0] == ACE_TEXT ('\\'))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Validate length.
+ if (pos == 0 || pos > 255)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration::validate_value_name (const ACE_TCHAR* name)
+{
+ if (name == 0 || *name == this->NULL_String_)
+ return 0;
+
+ return this->validate_name (name);
+}
+
+const ACE_Configuration_Section_Key&
+ACE_Configuration::root_section (void) const
+{
+ return root_;
+}
+
+/**
+ * Determine if the contents of this object is the same as the
+ * contents of the object on the right hand side.
+ * Returns 1 (True) if they are equal and 0 (False) if they are not equal
+ */
+bool
+ACE_Configuration::operator== (const ACE_Configuration& rhs) const
+{
+ bool rc = true;
+ int sectionIndex = 0;
+ ACE_TString sectionName;
+ ACE_Configuration *nonconst_this = const_cast<ACE_Configuration*> (this);
+ ACE_Configuration &nonconst_rhs = const_cast<ACE_Configuration&> (rhs);
+
+ const ACE_Configuration_Section_Key& rhsRoot = rhs.root_section ();
+ ACE_Configuration_Section_Key rhsSection;
+ ACE_Configuration_Section_Key thisSection;
+
+ // loop through each section in this object
+ while ((rc) && (nonconst_this->enumerate_sections (this->root_,
+ sectionIndex,
+ sectionName) == 0))
+ {
+ // find that section in the rhs object
+ if (nonconst_rhs.open_section (rhsRoot,
+ sectionName.c_str (),
+ 0,
+ rhsSection) != 0)
+ {
+ // If the rhs object does not contain the section then we are
+ // not equal.
+ rc = false;
+ }
+ else if (nonconst_this->open_section (this->root_,
+ sectionName.c_str (),
+ 0,
+ thisSection) != 0)
+ {
+ // if there is some error opening the section in this object
+ rc = false;
+ }
+ else
+ {
+ // Well the sections match
+ int valueIndex = 0;
+ ACE_TString valueName;
+ VALUETYPE valueType;
+ VALUETYPE rhsType;
+
+ // Enumerate each value in this section
+ while ((rc) && nonconst_this->enumerate_values (thisSection,
+ valueIndex,
+ valueName,
+ valueType) == 0)
+ {
+ // look for the same value in the rhs section
+ if (nonconst_rhs.find_value (rhsSection,
+ valueName.c_str (),
+ rhsType) != 0)
+ {
+ // We're not equal if the same value cannot
+ // be found in the rhs object.
+ rc = false;
+ }
+ else if (valueType != rhsType)
+ {
+ // we're not equal if the types do not match.
+ rc = false;
+ }
+ else
+ {
+ // finally compare values.
+ if (valueType == STRING)
+ {
+ ACE_TString thisString, rhsString;
+ if (nonconst_this->get_string_value (thisSection,
+ valueName.c_str (),
+ thisString) != 0)
+ {
+ // we're not equal if we cannot get this string
+ rc = false;
+ }
+ else if (nonconst_rhs.get_string_value (
+ rhsSection,
+ valueName.c_str (),
+ rhsString) != 0)
+ {
+ // we're not equal if we cannot get rhs string
+ rc = false;
+ }
+ rc = (thisString == rhsString);
+ }
+ else if (valueType == INTEGER)
+ {
+ u_int thisInt = 0;
+ u_int rhsInt = 0;
+ if (nonconst_this->get_integer_value (
+ thisSection,
+ valueName.c_str (),
+ thisInt) != 0)
+ {
+ // we're not equal if we cannot get this int
+ rc = false;
+ }
+ else if (nonconst_rhs.get_integer_value (
+ rhsSection,
+ valueName.c_str (),
+ rhsInt) != 0)
+ {
+ // we're not equal if we cannot get rhs int
+ rc = false;
+ }
+ rc = (thisInt == rhsInt);
+ }
+ else if (valueType == BINARY)
+ {
+ void* thisData = 0;
+ void* rhsData = 0;
+ size_t thisLength = 0;
+ size_t rhsLength = 0;
+ if (nonconst_this->get_binary_value (thisSection,
+ valueName.c_str (),
+ thisData,
+ thisLength) != 0)
+ {
+ // we're not equal if we cannot get this data
+ rc = false;
+ }
+ else if (nonconst_rhs.get_binary_value (
+ rhsSection,
+ valueName.c_str (),
+ rhsData,
+ rhsLength) != 0)
+ {
+ // we're not equal if we cannot get this data
+ rc = false;
+ }
+
+ rc = (thisLength == rhsLength);
+ // are the length's the same?
+
+ if (rc)
+ {
+ unsigned char* thisCharData =
+ (unsigned char*)thisData;
+ unsigned char* rhsCharData = (unsigned char*)rhsData;
+ // yes, then check each element
+ for (size_t count = 0;
+ (rc) && (count < thisLength);
+ count++)
+ {
+ rc = (* (thisCharData + count) == * (rhsCharData + count));
+ }
+
+ delete [] thisCharData;
+ delete [] rhsCharData;
+ }// end if the length's match
+ }
+ // We should never have valueTypes of INVALID, therefore
+ // we're not comparing them. How would we since we have
+ // no get operation for invalid types.
+ // So, if we have them, we guess they are equal.
+
+ }// end else if values match.
+
+ ++valueIndex;
+
+ }// end value while loop
+
+ // look in the rhs for values not in this
+ valueIndex = 0;
+ while ((rc) && (nonconst_rhs.enumerate_values (rhsSection,
+ valueIndex,
+ valueName,
+ rhsType) == 0))
+ {
+ // look for the same value in this section
+ if (nonconst_this->find_value (thisSection,
+ valueName.c_str (),
+ valueType) != 0)
+ {
+ // We're not equal if the same value cannot
+ // be found in the rhs object.
+ rc = false;
+ }
+ ++valueIndex;
+ }// end while for rhs values not in this.
+
+ }// end else if sections match.
+
+ ++sectionIndex;
+
+ }// end section while loop
+
+ // Finally, make sure that there are no sections in rhs that do not
+ // exist in this
+ sectionIndex = 0;
+ while ((rc)
+ && (nonconst_rhs.enumerate_sections (rhsRoot,
+ sectionIndex,
+ sectionName) == 0))
+ {
+ // find the section in this
+ if (nonconst_this->open_section (this->root_,
+ sectionName.c_str (),
+ 0,
+ thisSection) != 0)
+ {
+ // if there is some error opening the section in this object
+ rc = false;
+ }
+ else if (nonconst_rhs.open_section (rhsRoot,
+ sectionName.c_str (),
+ 0,
+ rhsSection) != 0)
+ {
+ // If the rhs object does not contain the section then we
+ // are not equal.
+ rc = false;
+ }
+ ++sectionIndex;
+ }
+ return rc;
+}
+
+bool
+ACE_Configuration::operator!= (const ACE_Configuration& rhs) const
+{
+ return !(*this == rhs);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_REGISTRY)
+
+static const int ACE_DEFAULT_BUFSIZE = 256;
+
+static const ACE_TCHAR *temp_name (const ACE_TCHAR *name)
+{
+ if (name && *name == ACE_Configuration::NULL_String_)
+ return 0;
+ return name;
+}
+
+ACE_Section_Key_Win32::ACE_Section_Key_Win32 (HKEY hKey)
+ : hKey_ (hKey)
+{
+}
+
+ACE_Section_Key_Win32::~ACE_Section_Key_Win32 (void)
+{
+ ::RegCloseKey (hKey_);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+bool
+ACE_Configuration_Win32Registry::operator== (const ACE_Configuration_Win32Registry &rhs) const
+{
+ ACE_UNUSED_ARG (rhs);
+ return true;
+}
+
+bool
+ACE_Configuration_Win32Registry::operator!= (const ACE_Configuration_Win32Registry &rhs) const
+{
+ ACE_UNUSED_ARG (rhs);
+ return true;
+}
+
+ACE_Configuration_Win32Registry::ACE_Configuration_Win32Registry (HKEY hKey)
+{
+ ACE_Section_Key_Win32 *temp = 0;
+
+ ACE_NEW (temp, ACE_Section_Key_Win32 (hKey));
+
+ root_ = ACE_Configuration_Section_Key (temp);
+}
+
+
+ACE_Configuration_Win32Registry::~ACE_Configuration_Win32Registry (void)
+{
+}
+
+int
+ACE_Configuration_Win32Registry::open_section (const ACE_Configuration_Section_Key& base,
+ const ACE_TCHAR* sub_section,
+ int create,
+ ACE_Configuration_Section_Key& result)
+{
+ if (validate_name (sub_section, 1))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (base, base_key))
+ return -1;
+
+ int errnum;
+ HKEY result_key;
+ if ((errnum = ACE_TEXT_RegOpenKeyEx (base_key,
+ sub_section,
+ 0,
+ KEY_ALL_ACCESS,
+ &result_key)) != ERROR_SUCCESS)
+ {
+ if (!create)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ if ((errnum = ACE_TEXT_RegCreateKeyEx (base_key,
+ sub_section,
+ 0,
+ 0,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ 0,
+ &result_key,
+#if defined (__MINGW32__)
+ (PDWORD) 0
+#else
+ 0
+#endif /* __MINGW32__ */
+ )) != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+ }
+
+ ACE_Section_Key_Win32 *temp;
+
+ ACE_NEW_RETURN (temp, ACE_Section_Key_Win32 (result_key), -1);
+ result = ACE_Configuration_Section_Key (temp);
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::remove_section (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* sub_section,
+ int recursive)
+{
+ if (validate_name (sub_section))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ if (recursive)
+ {
+ ACE_Configuration_Section_Key section;
+ if (open_section (key, sub_section, 0, section))
+ return -1;
+
+ HKEY sub_key;
+ if (load_key (section, sub_key))
+ return -1;
+
+ ACE_TCHAR name_buffer[ACE_DEFAULT_BUFSIZE];
+ DWORD buffer_size = ACE_DEFAULT_BUFSIZE;
+ // Note we don't increment the index because the
+ // enumeration becomes invalid if we change the
+ // subkey, which we do when we delete it. By leaving
+ // it 0, we always delete the top entry
+ while (ACE_TEXT_RegEnumKeyEx (sub_key,
+ 0,
+ name_buffer,
+ &buffer_size,
+ 0,
+ 0,
+ 0,
+ 0) == ERROR_SUCCESS)
+ {
+ remove_section (section, name_buffer, 1);
+ buffer_size = ACE_DEFAULT_BUFSIZE;
+ }
+ }
+
+ int errnum;
+ errnum = ACE_TEXT_RegDeleteKey (base_key, sub_section);
+ if (errnum != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::enumerate_values (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name,
+ VALUETYPE& type)
+{
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ ACE_TCHAR name_buffer[ACE_DEFAULT_BUFSIZE];
+ DWORD buffer_size = ACE_DEFAULT_BUFSIZE;
+ DWORD value_type;
+
+ int rc = ACE_TEXT_RegEnumValue (base_key,
+ index,
+ name_buffer,
+ &buffer_size,
+ 0,
+ &value_type,
+ 0,
+ 0);
+ if (rc == ERROR_NO_MORE_ITEMS)
+ return 1;
+ else if (rc != ERROR_SUCCESS)
+ {
+ errno = rc;
+ return -1;
+ }
+
+ name = name_buffer;
+
+ switch (value_type)
+ {
+ case REG_BINARY:
+ type = BINARY;
+ break;
+ case REG_SZ:
+ type = STRING;
+ break;
+ case REG_DWORD:
+ type = INTEGER;
+ break;
+ default:
+ type = INVALID;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::enumerate_sections (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name)
+{
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ ACE_TCHAR name_buffer[ACE_DEFAULT_BUFSIZE];
+ DWORD buffer_size = ACE_DEFAULT_BUFSIZE;
+ int rc = ACE_TEXT_RegEnumKeyEx (base_key,
+ index,
+ name_buffer,
+ &buffer_size,
+ 0,
+ 0,
+ 0,
+ 0);
+ if (rc == ERROR_NO_MORE_ITEMS)
+ return 1;
+ else if (rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS)
+ {
+ errno = rc;
+ return -1;
+ }
+
+ name = name_buffer;
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::set_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const ACE_TString& value)
+{
+ const ACE_TCHAR *t_name = temp_name (name);
+ if (validate_value_name (t_name))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ int errnum;
+ DWORD len = static_cast<DWORD> (value.length () + 1);
+ len *= sizeof (ACE_TCHAR);
+ if ((errnum = ACE_TEXT_RegSetValueEx (base_key,
+ t_name,
+ 0,
+ REG_SZ,
+ (BYTE *) value.fast_rep (),
+ len))
+ != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::set_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int value)
+{
+ const ACE_TCHAR *t_name = temp_name (name);
+ if (validate_value_name (t_name))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ int errnum;
+ if ((errnum = ACE_TEXT_RegSetValueEx (base_key,
+ t_name,
+ 0,
+ REG_DWORD,
+ (BYTE *) &value,
+ sizeof (value))) != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::set_binary_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const void* data,
+ size_t length)
+{
+ const ACE_TCHAR *t_name = temp_name (name);
+ if (validate_value_name (t_name))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ int errnum;
+ if ((errnum = ACE_TEXT_RegSetValueEx (base_key,
+ t_name,
+ 0,
+ REG_BINARY,
+ (BYTE *) data,
+ static_cast<DWORD> (length)))
+ != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::get_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ ACE_TString& value)
+{
+ const ACE_TCHAR *t_name = temp_name (name);
+ if (validate_value_name (t_name))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ // Get the size of the binary data from windows
+ int errnum;
+ DWORD buffer_length = 0;
+ DWORD type;
+ if ((errnum = ACE_TEXT_RegQueryValueEx (base_key,
+ t_name,
+ 0,
+ &type,
+ (BYTE *) 0,
+ &buffer_length)) != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ if (type != REG_SZ)
+ {
+ errno = ERROR_INVALID_DATATYPE;
+ return -1;
+ }
+
+ ACE_TCHAR *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_TCHAR[buffer_length],
+ -1);
+
+ ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> buffer (temp);
+
+ if ((errnum = ACE_TEXT_RegQueryValueEx (base_key,
+ t_name,
+ 0,
+ &type,
+ (BYTE *) buffer.get (),
+ &buffer_length)) != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ value = buffer.get ();
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::get_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int& value)
+{
+ const ACE_TCHAR *t_name = temp_name (name);
+ if (validate_value_name (t_name))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ int errnum;
+ DWORD length = sizeof (value);
+ DWORD type;
+ if ((errnum = ACE_TEXT_RegQueryValueEx (base_key,
+ t_name,
+ 0,
+ &type,
+ (BYTE *) &value,
+ &length)) != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ if (type != REG_DWORD)
+ {
+ errno = ERROR_INVALID_DATATYPE;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::get_binary_value (
+ const ACE_Configuration_Section_Key &key,
+ const ACE_TCHAR *name,
+ void *&data,
+ size_t &length)
+{
+ const ACE_TCHAR *t_name = temp_name (name);
+ if (validate_value_name (t_name))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ // Get the size of the binary data from windows
+ int errnum;
+ DWORD buffer_length = 0;
+ DWORD type;
+ if ((errnum = ACE_TEXT_RegQueryValueEx (base_key,
+ t_name,
+ 0,
+ &type,
+ (BYTE *) 0,
+ &buffer_length)) != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ if (type != REG_BINARY)
+ {
+ errno = ERROR_INVALID_DATATYPE;
+ return -1;
+ }
+
+ length = buffer_length;
+
+ BYTE * the_data = 0;
+ ACE_NEW_RETURN (the_data, BYTE[length], -1);
+ ACE_Auto_Basic_Array_Ptr<BYTE> safe_data (the_data);
+
+ if ((errnum = ACE_TEXT_RegQueryValueEx (base_key,
+ t_name,
+ 0,
+ &type,
+ the_data,
+ &buffer_length)) != ERROR_SUCCESS)
+ {
+ data = 0;
+ errno = errnum;
+ return -1;
+ }
+
+ data = safe_data.release ();
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::find_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ VALUETYPE& type_out)
+{
+ const ACE_TCHAR *t_name = temp_name (name);
+ if (validate_value_name (t_name))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ DWORD buffer_length=0;
+ DWORD type;
+ int result=ACE_TEXT_RegQueryValueEx (base_key,
+ t_name,
+ 0,
+ &type,
+ 0,
+ &buffer_length);
+ if (result != ERROR_SUCCESS)
+ {
+ errno = result;
+ return -1;
+ }
+
+ switch (type)
+ {
+ case REG_SZ:
+ type_out = STRING;
+ break;
+ case REG_DWORD:
+ type_out = INTEGER;
+ break;
+ case REG_BINARY:
+ type_out = BINARY;
+ break;
+ default:
+ return -1; // unknown type
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Win32Registry::remove_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name)
+{
+ const ACE_TCHAR *t_name = temp_name (name);
+ if (validate_value_name (t_name))
+ return -1;
+
+ HKEY base_key;
+ if (load_key (key, base_key))
+ return -1;
+
+ int errnum;
+ if ((errnum = ACE_TEXT_RegDeleteValue (base_key, t_name)) != ERROR_SUCCESS)
+ {
+ errno = errnum;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+ACE_Configuration_Win32Registry::load_key (const ACE_Configuration_Section_Key& key,
+ HKEY& hKey)
+{
+ ACE_Section_Key_Win32* pKey = dynamic_cast<ACE_Section_Key_Win32*> (get_internal_key (key));
+ if (!pKey)
+ return -1;
+
+ hKey = pKey->hKey_;
+ return 0;
+}
+
+HKEY
+ACE_Configuration_Win32Registry::resolve_key (HKEY hKey,
+ const ACE_TCHAR* path,
+ int create)
+{
+ HKEY result = 0;
+ // Make a copy of hKey
+ int errnum;
+#if defined (ACE_HAS_WINCE)
+ if ((errnum = RegOpenKeyEx (hKey, 0, 0, 0, &result)) != ERROR_SUCCESS)
+#else
+ if ((errnum = RegOpenKey (hKey, 0, &result)) != ERROR_SUCCESS)
+#endif // ACE_HAS_WINCE
+ {
+ errno = errnum;
+ return 0;
+ }
+
+ // recurse through the path
+ ACE_TCHAR *temp_path = 0;
+ ACE_NEW_RETURN (temp_path,
+ ACE_TCHAR[ACE_OS::strlen (path) + 1],
+ 0);
+ ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> pData (temp_path);
+ ACE_OS::strcpy (pData.get (), path);
+ ACE_Tokenizer parser (pData.get ());
+ parser.delimiter_replace ('\\', '\0');
+ parser.delimiter_replace ('/', '\0');
+
+ for (ACE_TCHAR *temp = parser.next ();
+ temp != 0;
+ temp = parser.next ())
+ {
+ // Open the key
+ HKEY subkey;
+
+#if defined (ACE_HAS_WINCE)
+ if ((errnum = ACE_TEXT_RegOpenKeyEx (result,
+ temp,
+ 0,
+ 0,
+ &subkey)) != ERROR_SUCCESS)
+#else
+ if ((errnum = ACE_TEXT_RegOpenKey (result,
+ temp,
+ &subkey)) != ERROR_SUCCESS)
+#endif // ACE_HAS_WINCE
+ {
+ // try creating it
+ if (!create || (errnum = ACE_TEXT_RegCreateKeyEx (result,
+ temp,
+ 0,
+ 0,
+ 0,
+ KEY_ALL_ACCESS,
+ 0,
+ &subkey,
+#if defined (__MINGW32__)
+ (PDWORD) 0
+#else
+ 0
+#endif /* __MINGW32__ */
+ )) !=ERROR_SUCCESS)
+ {
+ errno = errnum;
+ // error
+ ::RegCloseKey (result);
+ return 0;
+ }
+ }
+ // release our open key handle
+ ::RegCloseKey (result);
+ result = subkey;
+ }
+
+ return result;
+}
+
+#endif /* ACE_WIN32 && !ACE_LACKS_WIN32_REGISTRY */
+
+///////////////////////////////////////////////////////////////
+
+ACE_Configuration_Value_IntId::ACE_Configuration_Value_IntId (void)
+ : type_ (ACE_Configuration::INVALID),
+ length_ (0)
+{
+ this->data_.ptr_ = 0;
+}
+
+ACE_Configuration_Value_IntId::ACE_Configuration_Value_IntId (ACE_TCHAR* string)
+ : type_ (ACE_Configuration::STRING),
+ length_ (0)
+{
+ this->data_.ptr_ = string;
+}
+
+ACE_Configuration_Value_IntId::ACE_Configuration_Value_IntId (u_int integer)
+ : type_ (ACE_Configuration::INTEGER),
+ length_ (0)
+{
+ this->data_.int_ = integer;
+}
+
+ACE_Configuration_Value_IntId::ACE_Configuration_Value_IntId (void* data, size_t length)
+ : type_ (ACE_Configuration::BINARY),
+ length_ (length)
+{
+ this->data_.ptr_ = data;
+}
+
+ACE_Configuration_Value_IntId::ACE_Configuration_Value_IntId (const ACE_Configuration_Value_IntId& rhs)
+ : type_ (rhs.type_),
+ data_ (rhs.data_),
+ length_ (rhs.length_)
+{
+}
+
+ACE_Configuration_Value_IntId::~ACE_Configuration_Value_IntId (void)
+{
+}
+
+ACE_Configuration_Value_IntId& ACE_Configuration_Value_IntId::operator= (const ACE_Configuration_Value_IntId& rhs)
+{
+ if (this != &rhs)
+ {
+ type_ = rhs.type_;
+ data_ = rhs.data_;
+ length_ = rhs.length_;
+ }
+ return *this;
+}
+
+void
+ACE_Configuration_Value_IntId::free (ACE_Allocator *alloc)
+{
+ if (this->type_ == ACE_Configuration::STRING
+ || this->type_ == ACE_Configuration::BINARY)
+ alloc->free (data_.ptr_);
+ // Do nothing in other cases...
+}
+
+ACE_Configuration_ExtId::ACE_Configuration_ExtId (void)
+ : name_ (0)
+{
+}
+
+ACE_Configuration_ExtId::ACE_Configuration_ExtId (const ACE_TCHAR* name)
+ : name_ (name)
+{
+}
+
+ACE_Configuration_ExtId::ACE_Configuration_ExtId (const ACE_Configuration_ExtId& rhs)
+ : name_ (rhs.name_)
+{
+}
+
+ACE_Configuration_ExtId::~ACE_Configuration_ExtId (void)
+{
+}
+
+ACE_Configuration_ExtId& ACE_Configuration_ExtId::operator= (const ACE_Configuration_ExtId& rhs)
+{
+ if (this != &rhs)
+ name_ = rhs.name_;
+
+ return *this;
+}
+
+bool
+ACE_Configuration_ExtId::operator== (const ACE_Configuration_ExtId& rhs) const
+{
+ return (ACE_OS::strcasecmp (name_, rhs.name_) == 0);
+}
+
+bool
+ACE_Configuration_ExtId::operator!= (const ACE_Configuration_ExtId& rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+u_long
+ACE_Configuration_ExtId::hash (void) const
+{
+ ACE_TString temp (name_, 0, false);
+ return temp.hash ();
+}
+
+void
+ACE_Configuration_ExtId::free (ACE_Allocator *alloc)
+{
+ alloc->free ((void *) (name_));
+}
+
+///////////////////////////////////////////////////////////////////////
+
+ACE_Configuration_Section_IntId::ACE_Configuration_Section_IntId (void)
+ : value_hash_map_ (0),
+ section_hash_map_ (0)
+{
+}
+
+ACE_Configuration_Section_IntId::ACE_Configuration_Section_IntId (VALUE_MAP* value_hash_map, SUBSECTION_MAP* section_hash_map)
+ : value_hash_map_ (value_hash_map),
+ section_hash_map_ (section_hash_map)
+{
+}
+
+ACE_Configuration_Section_IntId::ACE_Configuration_Section_IntId (const ACE_Configuration_Section_IntId& rhs)
+ : value_hash_map_ (rhs.value_hash_map_),
+ section_hash_map_ (rhs.section_hash_map_)
+{
+
+}
+
+ACE_Configuration_Section_IntId::~ACE_Configuration_Section_IntId ()
+{
+}
+
+ACE_Configuration_Section_IntId&
+ACE_Configuration_Section_IntId::operator= (const ACE_Configuration_Section_IntId& rhs)
+{
+ if (this != &rhs)
+ {
+ value_hash_map_ = rhs.value_hash_map_;
+ section_hash_map_ = rhs.section_hash_map_;
+ }
+ return *this;
+}
+
+void
+ACE_Configuration_Section_IntId::free (ACE_Allocator *alloc)
+{
+ alloc->free ((void *) (value_hash_map_));
+ alloc->free ((void *) (section_hash_map_));
+}
+
+ACE_Configuration_Section_Key_Heap::ACE_Configuration_Section_Key_Heap (const ACE_TCHAR* path)
+ : path_ (0),
+ value_iter_ (0),
+ section_iter_ (0)
+{
+ path_ = ACE_OS::strdup (path);
+}
+
+ACE_Configuration_Section_Key_Heap::~ACE_Configuration_Section_Key_Heap ()
+{
+ delete value_iter_;
+ delete section_iter_;
+ ACE_OS::free (path_);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+ACE_Configuration_Heap::ACE_Configuration_Heap (void)
+ : allocator_ (0),
+ index_ (0),
+ default_map_size_ (0)
+{
+ ACE_Configuration_Section_Key_Heap *temp = 0;
+
+ ACE_NEW (temp, ACE_Configuration_Section_Key_Heap (ACE_TEXT ("")));
+ root_ = ACE_Configuration_Section_Key (temp);
+}
+
+ACE_Configuration_Heap::~ACE_Configuration_Heap (void)
+{
+ if (allocator_)
+ allocator_->sync ();
+
+ delete allocator_;
+}
+
+int
+ACE_Configuration_Heap::open (size_t default_map_size)
+{
+ default_map_size_ = default_map_size;
+ // Create the allocator with the appropriate options.
+ // The name used for the lock is the same as one used
+ // for the file.
+ ACE_NEW_RETURN (this->allocator_,
+ HEAP_ALLOCATOR (),
+ -1);
+ return create_index ();
+}
+
+
+int
+ACE_Configuration_Heap::open (const ACE_TCHAR* file_name,
+ void* base_address,
+ size_t default_map_size)
+{
+ default_map_size_ = default_map_size;
+
+ // Make sure that the file name is of the legal length.
+ if (ACE_OS::strlen (file_name) >= MAXNAMELEN + MAXPATHLEN)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ ACE_MMAP_Memory_Pool::OPTIONS options (base_address);
+
+ // Create the allocator with the appropriate options. The name used
+ // for the lock is the same as one used for the file.
+ ACE_NEW_RETURN (this->allocator_,
+ PERSISTENT_ALLOCATOR (file_name,
+ file_name,
+ &options),
+ -1);
+
+#if !defined (ACE_LACKS_ACCESS)
+ // Now check if the backing store has been created successfully.
+ if (ACE_OS::access (file_name, F_OK) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("create_index\n")),
+ -1);
+#endif /* ACE_LACKS_ACCESS */
+
+ return create_index ();
+}
+
+int
+ACE_Configuration_Heap::create_index (void)
+{
+ void *section_index = 0;
+
+ // This is the easy case since if we find hash table in the
+ // memory-mapped file we know it's already initialized.
+ if (this->allocator_->find (ACE_CONFIG_SECTION_INDEX, section_index) == 0)
+ this->index_ = (SECTION_MAP *) section_index;
+
+ // Create a new <index_> (because we've just created a new
+ // memory-mapped file).
+ else
+ {
+ size_t index_size = sizeof (SECTION_MAP);
+ section_index = this->allocator_->malloc (index_size);
+
+ if (section_index == 0
+ || create_index_helper (section_index) == -1
+ || this->allocator_->bind (ACE_CONFIG_SECTION_INDEX,
+ section_index) == -1)
+ {
+ // Attempt to clean up.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("create_index failed\n")));
+ this->allocator_->remove ();
+ return -1;
+ }
+ // Add the root section
+ return new_section (ACE_TEXT (""), root_);
+ }
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::create_index_helper (void *buffer)
+{
+ ACE_ASSERT (this->allocator_);
+ this->index_ = new (buffer) SECTION_MAP (this->allocator_);
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::load_key (const ACE_Configuration_Section_Key& key,
+ ACE_TString& name)
+{
+ ACE_ASSERT (this->allocator_);
+ ACE_Configuration_Section_Key_Heap* pKey =
+ dynamic_cast<ACE_Configuration_Section_Key_Heap*> (get_internal_key (key));
+
+ if (!pKey)
+ {
+ return -1;
+ }
+
+ ACE_TString temp (pKey->path_, 0, false);
+ name.assign_nocopy (temp);
+ return 0;
+}
+
+
+int
+ACE_Configuration_Heap::add_section (const ACE_Configuration_Section_Key& base,
+ const ACE_TCHAR* sub_section,
+ ACE_Configuration_Section_Key& result)
+{
+ ACE_ASSERT (this->allocator_);
+ ACE_TString section;
+ if (load_key (base, section))
+ return -1;
+
+ // Find the base section
+ ACE_Configuration_ExtId ExtId (section.fast_rep ());
+ ACE_Configuration_Section_IntId IntId;
+ if (index_->find (ExtId, IntId, allocator_))
+ return -1;
+
+ // See if this section already exists
+ ACE_Configuration_ExtId SubSectionExtId (sub_section);
+ int ignored = 0;
+
+ if (!IntId.section_hash_map_->find (SubSectionExtId, ignored, allocator_))
+ {
+ // already exists!
+ errno = EEXIST;
+ return -1;
+ }
+
+ // Create the new section name
+ // only prepend a separater if were not at the root
+ if (section.length ())
+ section += ACE_TEXT ("\\");
+
+ section += sub_section;
+
+ // Add it to the base section
+ ACE_TCHAR* pers_name = (ACE_TCHAR *) allocator_->malloc ((ACE_OS::strlen (sub_section) + 1) * sizeof (ACE_TCHAR));
+ ACE_OS::strcpy (pers_name, sub_section);
+ ACE_Configuration_ExtId SSExtId (pers_name);
+ if (IntId.section_hash_map_->bind (SSExtId, ignored, allocator_))
+ {
+ allocator_->free (pers_name);
+ return -1;
+ }
+ return (new_section (section, result));
+}
+
+int
+ACE_Configuration_Heap::new_section (const ACE_TString& section,
+ ACE_Configuration_Section_Key& result)
+{
+ ACE_ASSERT (this->allocator_);
+ // Create a new section and add it to the global list
+
+ // Allocate memory for items to be stored in the table.
+ size_t section_len = section.length () + 1;
+ ACE_TCHAR *ptr = (ACE_TCHAR*) this->allocator_->malloc (section_len * sizeof (ACE_TCHAR));
+
+ int return_value = -1;
+
+ if (ptr == 0)
+ return -1;
+ else
+ {
+ // Populate memory with data.
+ ACE_OS::strcpy (ptr, section.fast_rep ());
+
+ void *value_hash_map = 0;
+ size_t map_size = sizeof (VALUE_MAP);
+ value_hash_map = this->allocator_->malloc (map_size);
+
+ // If allocation failed ...
+ if (value_hash_map == 0)
+ return -1;
+
+ // Initialize allocated hash map through placement new.
+ if (value_open_helper (default_map_size_, value_hash_map ) == -1)
+ {
+ this->allocator_->free (value_hash_map );
+ return -1;
+ }
+
+ // create the section map
+ void* section_hash_map = 0;
+ map_size = sizeof (SUBSECTION_MAP);
+ section_hash_map = this->allocator_->malloc (map_size);
+
+ // If allocation failed
+ if (section_hash_map == 0)
+ return -1;
+
+ // initialize allocated hash map through placement new
+ if (section_open_helper (default_map_size_, section_hash_map) == -1)
+ {
+ this->allocator_->free (value_hash_map );
+ this->allocator_->free (section_hash_map);
+ return -1;
+ }
+
+ ACE_Configuration_ExtId name (ptr);
+ ACE_Configuration_Section_IntId entry ((VALUE_MAP*) value_hash_map,
+ (SUBSECTION_MAP*) section_hash_map);
+
+ // Do a normal bind. This will fail if there's already an
+ // entry with the same name.
+ return_value = this->index_->bind (name, entry, this->allocator_);
+
+ if (return_value == 1 /* Entry already existed so bind failed. */
+ || return_value == -1 /* Unable to bind for other reasons. */)
+ {
+ // Free our dynamically allocated memory.
+ this->allocator_->free (static_cast<void *> (ptr));
+ return return_value;
+ }
+
+ // If bind () succeed, it will automatically sync
+ // up the map manager entry. However, we must sync up our
+ // name/value memory.
+ this->allocator_->sync (ptr, section_len);
+ }
+
+ // set the result
+ ACE_Configuration_Section_Key_Heap *temp;
+ ACE_NEW_RETURN (temp,
+ ACE_Configuration_Section_Key_Heap (ptr),
+ -1);
+ result = ACE_Configuration_Section_Key (temp);
+ return return_value;
+}
+
+int
+ACE_Configuration_Heap::value_open_helper (size_t hash_table_size,
+ void *buffer)
+{
+ ACE_ASSERT (this->allocator_);
+ new (buffer) VALUE_MAP (hash_table_size, this->allocator_);
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::section_open_helper (size_t hash_table_size,
+ void *buffer)
+{
+ ACE_ASSERT (this->allocator_);
+ new (buffer) SUBSECTION_MAP (hash_table_size, this->allocator_);
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::open_section (const ACE_Configuration_Section_Key& base,
+ const ACE_TCHAR* sub_section,
+ int create,
+ ACE_Configuration_Section_Key& result)
+{
+ ACE_ASSERT (this->allocator_);
+ if (validate_name (sub_section, 1)) // 1 == allow_path
+ return -1;
+
+ result = base;
+
+ for (const ACE_TCHAR* separator;
+ (separator = ACE_OS::strchr (sub_section, ACE_TEXT ('\\'))) != 0;
+ )
+ {
+ ACE_TString simple_section (sub_section, separator - sub_section);
+ int ret_val =
+ open_simple_section (result, simple_section.c_str (), create, result);
+ if (ret_val)
+ return ret_val;
+ sub_section = separator + 1;
+ }
+
+ return open_simple_section (result, sub_section, create, result);
+}
+
+int
+ACE_Configuration_Heap::open_simple_section (const ACE_Configuration_Section_Key& base,
+ const ACE_TCHAR* sub_section,
+ int create,
+ ACE_Configuration_Section_Key& result)
+{
+ ACE_TString section (0, 0, false);
+
+ if (load_key (base, section))
+ {
+ return -1;
+ }
+
+ // Only add the \\ if were not at the root
+ if (section.length ())
+ {
+ section += ACE_TEXT ("\\");
+ }
+
+ section += sub_section;
+
+ // resolve the section
+ ACE_Configuration_ExtId ExtId (section.fast_rep ());
+ ACE_Configuration_Section_IntId IntId;
+
+ if (index_->find (ExtId, IntId, allocator_))
+ {
+ if (!create)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ return add_section (base, sub_section, result);
+ }
+
+ ACE_Configuration_Section_Key_Heap *temp;
+ ACE_NEW_RETURN (temp,
+ ACE_Configuration_Section_Key_Heap (section.fast_rep ()),
+ -1);
+ result = ACE_Configuration_Section_Key (temp);
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::remove_section (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* sub_section,
+ int recursive)
+{
+ ACE_ASSERT (this->allocator_);
+ if (validate_name (sub_section))
+ return -1;
+
+ ACE_TString section;
+ if (load_key (key, section))
+ return -1;
+
+ // Find this key
+ ACE_Configuration_ExtId ParentExtId (section.fast_rep ());
+ ACE_Configuration_Section_IntId ParentIntId;
+ if (index_->find (ParentExtId, ParentIntId, allocator_))
+ return -1;// no parent key
+
+ // Find this subkey
+ if (section.length ())
+ section += ACE_TEXT ("\\");
+
+ section += sub_section;
+ ACE_Configuration_ExtId SectionExtId (section.fast_rep ());
+ SECTION_HASH::ENTRY* section_entry;
+ SECTION_HASH* hashmap = index_;
+ if (hashmap->find (SectionExtId, section_entry))
+ return -1;
+
+ if (recursive)
+ {
+ ACE_Configuration_Section_Key section;
+ if (open_section (key, sub_section, 0, section))
+ return -1;
+
+ int index = 0;
+ ACE_TString name;
+ while (!enumerate_sections (section, index, name))
+ {
+ if (remove_section (section, name.fast_rep (), 1))
+ return -1;
+
+ ++index;
+ }
+ }
+
+ // Now make sure we dont have any subkeys
+ if (section_entry->int_id_.section_hash_map_->current_size ())
+ {
+ errno = ENOTEMPTY;
+ return -1;
+ }
+
+ // Now remove subkey from parent key
+ ACE_Configuration_ExtId SubSExtId (sub_section);
+ SUBSECTION_HASH::ENTRY* subsection_entry;
+ if (((SUBSECTION_HASH*)ParentIntId.section_hash_map_)->
+ find (SubSExtId, subsection_entry))
+ return -1;
+
+ if (ParentIntId.section_hash_map_->unbind (SubSExtId, allocator_))
+ return -1;
+
+ subsection_entry->ext_id_.free (allocator_);
+
+ // Remember the pointers so we can free them after we unbind
+ ACE_Configuration_ExtId ExtIdToFree (section_entry->ext_id_);
+ ACE_Configuration_Section_IntId IntIdToFree (section_entry->int_id_);
+
+ // iterate over all values and free memory
+ VALUE_HASH* value_hash_map = section_entry->int_id_.value_hash_map_;
+ VALUE_HASH::ITERATOR value_iter = value_hash_map->begin ();
+ while (!value_iter.done ())
+ {
+ VALUE_HASH::ENTRY* value_entry = 0;
+ if (!value_iter.next (value_entry))
+ return 1;
+
+ value_entry->ext_id_.free (allocator_);
+ value_entry->int_id_.free (allocator_);
+
+ value_iter.advance ();
+ }
+
+ // remove it
+ if (index_->unbind (SectionExtId, allocator_))
+ return -1;
+
+ value_hash_map->close ();
+ section_entry->int_id_.section_hash_map_->close (allocator_);
+
+ // Free the memory
+ ExtIdToFree.free (allocator_);
+ IntIdToFree.free (allocator_);
+
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::enumerate_values (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name,
+ VALUETYPE& type)
+{
+ ACE_ASSERT (this->allocator_);
+ ACE_Configuration_Section_Key_Heap* pKey =
+ dynamic_cast<ACE_Configuration_Section_Key_Heap*> (get_internal_key (key));
+ if (!pKey)
+ return -1;
+
+ name = pKey->path_;
+
+ // resolve the section
+ ACE_Configuration_ExtId ExtId (pKey->path_);
+ ACE_Configuration_Section_IntId IntId;
+ if (index_->find (ExtId, IntId, allocator_))
+ return -1;
+
+ // Handle iterator resets
+ if (index == 0)
+ {
+ ACE_Hash_Map_Manager_Ex<ACE_Configuration_ExtId ,
+ ACE_Configuration_Value_IntId,
+ ACE_Hash<ACE_Configuration_ExtId>,
+ ACE_Equal_To<ACE_Configuration_ExtId>,
+ ACE_Null_Mutex>* hash_map = IntId.value_hash_map_;
+ delete pKey->value_iter_;
+
+ ACE_NEW_RETURN (pKey->value_iter_,
+ VALUE_HASH::ITERATOR (hash_map->begin ()),
+ -1);
+ }
+
+ // Get the next entry
+ ACE_Hash_Map_Entry<ACE_Configuration_ExtId, ACE_Configuration_Value_IntId>* entry = 0;
+
+ if (!pKey->value_iter_->next (entry))
+ return 1;
+
+ // Return the value of the iterator and advance it
+ name = entry->ext_id_.name_;
+ type = entry->int_id_.type_;
+ pKey->value_iter_->advance ();
+
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::enumerate_sections (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name)
+{
+ ACE_ASSERT (this->allocator_);
+ // cast to a heap section key
+ ACE_Configuration_Section_Key_Heap* pKey =
+ dynamic_cast<ACE_Configuration_Section_Key_Heap*> (get_internal_key (key));
+ if (!pKey)
+ return -1; // not a heap key!
+
+ // resolve the section
+ ACE_Configuration_ExtId ExtId (pKey->path_);
+ ACE_Configuration_Section_IntId IntId;
+ if (index_->find (ExtId, IntId, allocator_))
+ return -1; // unknown section
+
+ // Handle iterator resets
+ if (index == 0)
+ {
+ if (pKey->section_iter_)
+ delete pKey->section_iter_;
+
+ ACE_NEW_RETURN (pKey->section_iter_,
+ SUBSECTION_HASH::ITERATOR (IntId.section_hash_map_->begin ()),
+ -1);
+ }
+
+ // Get the next entry
+ ACE_Hash_Map_Entry<ACE_Configuration_ExtId, int>* entry = 0;
+ if (!pKey->section_iter_->next (entry))
+ return 1;
+
+ // Return the value of the iterator and advance it
+ pKey->section_iter_->advance ();
+ name = entry->ext_id_.name_;
+
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::set_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const ACE_TString& value)
+{
+ ACE_ASSERT (this->allocator_);
+ const ACE_TCHAR *t_name = name ? name : &this->NULL_String_;
+ if (validate_value_name (t_name))
+ return -1;
+
+ ACE_TString section;
+ if (load_key (key, section))
+ return -1;
+
+ ACE_Configuration_ExtId section_ext (section.fast_rep ());
+ ACE_Configuration_Section_IntId section_int;
+ if (index_->find (section_ext, section_int, allocator_))
+ return -1;
+
+ // Get the entry for this item (if it exists)
+ VALUE_HASH::ENTRY* entry;
+ ACE_Configuration_ExtId item_name (t_name);
+ if (section_int.value_hash_map_->VALUE_HASH::find (item_name, entry) == 0)
+ {
+ // found item, replace it
+ // Free the old value
+ entry->int_id_.free (allocator_);
+ // Allocate the new value in this heap
+ ACE_TCHAR* pers_value =
+ (ACE_TCHAR *) allocator_->malloc ((value.length () + 1) * sizeof (ACE_TCHAR));
+ ACE_OS::strcpy (pers_value, value.fast_rep ());
+ ACE_Configuration_Value_IntId new_value_int (pers_value);
+ entry->int_id_ = new_value_int;
+ }
+ else
+ {
+ // it doesn't exist, bind it
+ ACE_TCHAR* pers_name =
+ (ACE_TCHAR *) allocator_->malloc ((ACE_OS::strlen (t_name) + 1) * sizeof (ACE_TCHAR));
+ ACE_OS::strcpy (pers_name, t_name);
+ ACE_TCHAR* pers_value =
+ (ACE_TCHAR *) allocator_->malloc ((value.length () + 1) * sizeof (ACE_TCHAR));
+ ACE_OS::strcpy (pers_value, value.fast_rep ());
+ ACE_Configuration_ExtId item_name (pers_name);
+ ACE_Configuration_Value_IntId item_value (pers_value);
+ if (section_int.value_hash_map_->bind (item_name, item_value, allocator_))
+ {
+ allocator_->free (pers_value);
+ allocator_->free (pers_name);
+ return -1;
+ }
+ return 0;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::set_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int value)
+{
+ ACE_ASSERT (this->allocator_);
+ const ACE_TCHAR *t_name = name ? name : &this->NULL_String_;
+ if (validate_value_name (t_name))
+ return -1;
+
+ // Get the section name from the key
+ ACE_TString section;
+ if (load_key (key, section))
+ return -1;
+
+ // Find this section
+ ACE_Configuration_ExtId section_ext (section.fast_rep ());
+ ACE_Configuration_Section_IntId section_int;
+ if (index_->find (section_ext, section_int, allocator_))
+ return -1; // section does not exist
+
+ // Get the entry for this item (if it exists)
+ VALUE_HASH::ENTRY* entry;
+ ACE_Configuration_ExtId item_name (t_name);
+ if (section_int.value_hash_map_->VALUE_HASH::find (item_name, entry) == 0)
+ {
+ // found item, replace it
+ ACE_Configuration_Value_IntId new_value_int (value);
+ entry->int_id_ = new_value_int;
+ }
+ else
+ {
+ // it doesn't exist, bind it
+ ACE_TCHAR* pers_name =
+ (ACE_TCHAR *) allocator_->malloc ((ACE_OS::strlen (t_name) + 1) * sizeof (ACE_TCHAR));
+ ACE_OS::strcpy (pers_name, t_name);
+ ACE_Configuration_ExtId item_name (pers_name);
+ ACE_Configuration_Value_IntId item_value (value);
+ if (section_int.value_hash_map_->bind (item_name, item_value, allocator_))
+ {
+ allocator_->free (pers_name);
+ return -1;
+ }
+ return 0;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::set_binary_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const void* data,
+ size_t length)
+{
+ ACE_ASSERT (this->allocator_);
+ const ACE_TCHAR *t_name = name ? name : &this->NULL_String_;
+ if (validate_value_name (t_name))
+ return -1;
+
+ // Get the section name from the key
+ ACE_TString section;
+ if (load_key (key, section))
+ return -1;
+
+ // Find this section
+ ACE_Configuration_ExtId section_ext (section.fast_rep ());
+ ACE_Configuration_Section_IntId section_int;
+ if (index_->find (section_ext, section_int, allocator_))
+ return -1; // section does not exist
+
+ // Get the entry for this item (if it exists)
+ VALUE_HASH::ENTRY* entry;
+ ACE_Configuration_ExtId item_name (t_name);
+ if (section_int.value_hash_map_->VALUE_HASH::find (item_name, entry) == 0)
+ {
+ // found item, replace it
+ // Free the old value
+ entry->int_id_.free (allocator_);
+ // Allocate the new value in this heap
+ ACE_TCHAR* pers_value = (ACE_TCHAR *) allocator_->malloc (length);
+ ACE_OS::memcpy (pers_value, data, length);
+ ACE_Configuration_Value_IntId new_value_int (pers_value, length);
+ entry->int_id_ = new_value_int;
+ }
+ else
+ {
+ // it doesn't exist, bind it
+ ACE_TCHAR* pers_name =
+ (ACE_TCHAR *) allocator_->malloc ((ACE_OS::strlen (t_name) + 1) * sizeof (ACE_TCHAR));
+ ACE_OS::strcpy (pers_name, t_name);
+ ACE_TCHAR* pers_value = (ACE_TCHAR *) allocator_->malloc (length);
+ ACE_OS::memcpy (pers_value, data, length);
+ ACE_Configuration_ExtId item_name (pers_name);
+ ACE_Configuration_Value_IntId item_value (pers_value, length);
+ if (section_int.value_hash_map_->bind (item_name, item_value, allocator_))
+ {
+ allocator_->free (pers_value);
+ allocator_->free (pers_name);
+ return -1;
+ }
+ return 0;
+ }
+
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::get_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ ACE_TString& value)
+{
+ ACE_ASSERT (this->allocator_);
+ const ACE_TCHAR *t_name = name ? name : &this->NULL_String_;
+ if (validate_value_name (t_name))
+ return -1;
+
+ // Get the section name from the key
+ ACE_TString section;
+ if (load_key (key, section))
+ return -1;
+
+ // Find this section
+ ACE_Configuration_ExtId ExtId (section.fast_rep ());
+ ACE_Configuration_Section_IntId IntId;
+ if (index_->find (ExtId, IntId, allocator_))
+ return -1; // section does not exist
+
+ // See if it exists first
+ ACE_Configuration_ExtId VExtId (t_name);
+ ACE_Configuration_Value_IntId VIntId;
+ if (IntId.value_hash_map_->find (VExtId, VIntId, allocator_))
+ return -1; // unknown value
+
+ // Check type
+ if (VIntId.type_ != ACE_Configuration::STRING)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ // everythings ok, return the data
+ value = static_cast<ACE_TCHAR*> (VIntId.data_.ptr_);
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::get_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int& value)
+{
+ ACE_ASSERT (this->allocator_);
+
+ const ACE_TCHAR *t_name = name ? name : &this->NULL_String_;
+ if (validate_value_name (t_name))
+ return -1;
+
+ // Get the section name from the key
+ ACE_TString section (0, 0, false);
+
+ if (this->load_key (key, section) != 0)
+ {
+ return -1;
+ }
+
+ // Find this section
+ ACE_Configuration_ExtId ExtId (section.fast_rep ());
+ ACE_Configuration_Section_IntId IntId;
+
+ if (index_->find (ExtId, IntId, allocator_) != 0)
+ {
+ return -1; // section does not exist
+ }
+
+
+ // See if it exists first
+ ACE_Configuration_ExtId VExtId (t_name);
+ ACE_Configuration_Value_IntId VIntId;
+
+ if (IntId.value_hash_map_->find (VExtId, VIntId, allocator_) != 0)
+ {
+ return -1; // unknown value
+ }
+
+ // Check type
+ if (VIntId.type_ != ACE_Configuration::INTEGER)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ // Everythings ok, return the data
+ value = VIntId.data_.int_;
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::get_binary_value (
+ const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ void*& data,
+ size_t& length)
+{
+ ACE_ASSERT (this->allocator_);
+ const ACE_TCHAR *t_name = name ? name : &this->NULL_String_;
+ if (validate_value_name (t_name))
+ return -1;
+
+ // Get the section name from the key
+ ACE_TString section;
+ if (load_key (key, section))
+ return -1;
+
+ // Find this section
+ ACE_Configuration_ExtId ExtId (section.fast_rep ());
+ ACE_Configuration_Section_IntId IntId;
+ if (index_->find (ExtId, IntId, allocator_))
+ return -1; // section does not exist
+
+ ACE_Configuration_ExtId VExtId (t_name);
+ ACE_Configuration_Value_IntId VIntId;
+ // See if it exists first
+ if (IntId.value_hash_map_->find (VExtId, VIntId, allocator_))
+ return -1; // unknown value
+
+ // Check type
+ if (VIntId.type_ != ACE_Configuration::BINARY)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ // Make a copy
+ ACE_NEW_RETURN (data, char[VIntId.length_], -1);
+ ACE_OS::memcpy (data, VIntId.data_.ptr_, VIntId.length_);
+ length = VIntId.length_;
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::find_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ VALUETYPE& type_out)
+{
+ ACE_ASSERT (this->allocator_);
+ const ACE_TCHAR *t_name = name ? name : &this->NULL_String_;
+ if (validate_value_name (t_name))
+ return -1;
+
+ // Get the section name from the key
+ ACE_TString section;
+ if (load_key (key, section))
+ return -1;
+
+ // Find this section
+ ACE_Configuration_ExtId ExtId (section.fast_rep ());
+ ACE_Configuration_Section_IntId IntId;
+ if (index_->find (ExtId, IntId, allocator_))
+ return -1; // section does not exist
+
+ // Find it
+ ACE_Configuration_ExtId ValueExtId (t_name);
+ VALUE_HASH::ENTRY* value_entry;
+ if (((VALUE_HASH *) IntId.value_hash_map_)->find (ValueExtId, value_entry))
+ return -1; // value does not exist
+
+ type_out = value_entry->int_id_.type_;
+ return 0;
+}
+
+int
+ACE_Configuration_Heap::remove_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name)
+{
+ ACE_ASSERT (this->allocator_);
+ const ACE_TCHAR *t_name = name ? name : &this->NULL_String_;
+ if (validate_value_name (t_name))
+ return -1;
+
+ // Get the section name from the key
+ ACE_TString section;
+ if (load_key (key, section))
+ return -1;
+
+ // Find this section
+ ACE_Configuration_ExtId ExtId (section.fast_rep ());
+ ACE_Configuration_Section_IntId IntId;
+ if (index_->find (ExtId, IntId, allocator_))
+ return -1; // section does not exist
+
+ // Find it
+ ACE_Configuration_ExtId ValueExtId (t_name);
+ VALUE_HASH::ENTRY* value_entry;
+ if (((VALUE_HASH *) IntId.value_hash_map_)->find (ValueExtId, value_entry))
+ return -1;
+
+ // free it
+ value_entry->ext_id_.free (allocator_);
+ value_entry->int_id_.free (allocator_);
+
+ // Unbind it
+ if (IntId.value_hash_map_->unbind (ValueExtId, allocator_))
+ return -1;
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Configuration.h b/ACE/ace/Configuration.h
new file mode 100644
index 00000000000..199d7ac166b
--- /dev/null
+++ b/ACE/ace/Configuration.h
@@ -0,0 +1,896 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Configuration.h
+ *
+ * $Id$
+ *
+ * @author Chris Hafey <chafey@stentor.com>
+ *
+ * The ACE configuration API provides a portable abstraction for
+ * program configuration similar to the Microsoft Windows registry.
+ * The API supports a tree based hierarchy of configuration sections. Each
+ * section contains other sections or values. Values may contain string,
+ * unsigned integer and binary data.
+ *
+ * @note These classes are not thread safe, if multiple threads use these
+ * classes, you are responsible for serializing access.
+ *
+ * For examples of using this class, see:
+ * -# The test code in ACE_wrappers/test
+ * -# wxConfigViewer, a Windows like Registry Editor for ACE_Configuration
+ * -# TAO's IFR, it makes extensive use of ACE_Configuration
+ *
+ * @todo Templatize this class with an ACE_LOCK to provide thread safety
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_CONFIGURATION_H
+#define ACE_CONFIGURATION_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SStringfwd.h"
+#include "ace/Hash_Map_With_Allocator_T.h"
+#include "ace/Malloc_T.h"
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Local_Memory_Pool.h"
+#include "ace/Synch_Traits.h"
+
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// configurable parameters
+
+#if !defined (ACE_CONFIG_SECTION_INDEX)
+# define ACE_CONFIG_SECTION_INDEX "Config_Section_Index"
+#endif /* ! ACE_CONFIG_SECTION_INDEX */
+
+#if !defined (ACE_DEFAULT_CONFIG_SECTION_SIZE)
+#define ACE_DEFAULT_CONFIG_SECTION_SIZE 16
+#endif /* ACE_DEFAULT_CONFIG_SECTION_SIZE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Section_Key_Internal
+ *
+ * @internal
+ *
+ * @brief A base class for internal handles to section keys for
+ * configuration implementations
+ *
+ * Implementations subclass this base class to represent a
+ * section key.
+ *
+ */
+class ACE_Export ACE_Section_Key_Internal
+{
+public:
+ /// Virtual destructor, make sure descendants are virtual!
+ virtual ~ACE_Section_Key_Internal (void);
+
+ /// Increment reference count
+ virtual int add_ref (void);
+
+ /// Decrement reference count. Will delete this if count gets to 0
+ virtual int dec_ref (void);
+protected:
+ ACE_Section_Key_Internal (void);
+ ACE_Section_Key_Internal (const ACE_Section_Key_Internal& rhs);
+ ACE_Section_Key_Internal& operator= (ACE_Section_Key_Internal& rhs);
+
+ u_int ref_count_;
+};
+
+/**
+ * @class ACE_Configuration_Section_Key
+ *
+ * @brief Reference counted wrapper for ACE_Section_Key_Internal.
+ *
+ * Reference counted wrapper class for the abstract internal
+ * section key. A user gets one of these to represent a section
+ * in the configuration database.
+ */
+class ACE_Export ACE_Configuration_Section_Key
+{
+ friend class ACE_Configuration;
+public:
+ /// Default constructor.
+ ACE_Configuration_Section_Key (void);
+
+ /// Constructor that initializes to a pointer to a concrete internal key.
+ /**
+ * @param key The section key to reference. Calls add_ref() with @a key.
+ */
+ explicit ACE_Configuration_Section_Key (ACE_Section_Key_Internal *key);
+
+ /// Copy constructor, increments the reference count on the key.
+ ACE_Configuration_Section_Key (const ACE_Configuration_Section_Key &rhs);
+
+ /// Destructor, decrements reference count on the referenced key.
+ ~ACE_Configuration_Section_Key (void);
+
+ /// Assignment operator, increments reference count for this object
+ /// and decrements it on @a rhs.
+ ACE_Configuration_Section_Key &
+ operator= (const ACE_Configuration_Section_Key &rhs);
+private:
+ ACE_Section_Key_Internal *key_;
+};
+
+/**
+ * @class ACE_Configuration
+ *
+ * @internal
+ *
+ * @brief Base class for configuration databases
+ *
+ * This class provides an interface for configuration databases. A concrete
+ * class is required that implements the interface.
+ *
+ * @sa ACE_Configuration_Heap
+ * @sa ACE_Configuration_Win32Registry
+ */
+class ACE_Export ACE_Configuration
+{
+public:
+ /// Enumeration for the various types of values we can store.
+ enum VALUETYPE
+ {
+ STRING,
+ INTEGER,
+ BINARY,
+ INVALID
+ };
+
+ /// Destructor
+ virtual ~ACE_Configuration (void);
+
+ /// Obtain a reference to the root section of this configuration.
+ /*
+ * @return Reference to the configuration's root section. Note that
+ * it is a const reference.
+ */
+ virtual const ACE_Configuration_Section_Key& root_section (void) const;
+
+ /**
+ * Opens a named section in an existing section.
+ *
+ * @param base Existing section in which to open the named section.
+ * @param sub_section Name of the section to open.
+ * @param create If zero, the named section must exist. If non-zero,
+ * the named section will be created if it does not exist.
+ * @param result Reference; receives the section key for the new
+ * section.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int open_section (const ACE_Configuration_Section_Key &base,
+ const ACE_TCHAR *sub_section,
+ int create,
+ ACE_Configuration_Section_Key& result) = 0;
+
+ /// Removes a named section.
+ /**
+ * @param key Section key to remove the named section from.
+ * @param sub_section Name of the section to remove.
+ * @param recursive If non zero, any subkeys below @a sub_section are
+ * removed as well.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int remove_section (const ACE_Configuration_Section_Key &key,
+ const ACE_TCHAR *sub_section,
+ int recursive) = 0;
+
+ /**
+ * Enumerates through the values in a section.
+ *
+ * @param key Section key to iterate through.
+ * @param index Iteration position. Must be zero on the first call to
+ * iterate through @a key. Increment @a index by one on each
+ * successive call to this method.
+ * @param name Receives the value's name.
+ * @param type Receives the value's data type.
+ *
+ * @note You may not delete or add values while enumerating. If the
+ * section is modified during enumeration, results are undefined;
+ * you must restart the enumeration from index 0.
+ *
+ * @retval 0 for success, @a name and @a type are valid.
+ * @retval 1 there are no more values in the section.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int enumerate_values (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name,
+ VALUETYPE& type) = 0;
+
+ /**
+ * Enumerates through the subsections in a section.
+ *
+ * @param key Section key to iterate through.
+ * @param index Iteration position. Must be zero on the first call to
+ * iterate through @a key. Increment @a index by one on each
+ * successive call to this method.
+ * @param name Receives the subsection's name.
+ *
+ * @note You may not modify the @a key section while enumerating. If the
+ * section is modified during enumeration, results are undefined;
+ * you must restart the enumeration from index 0.
+ *
+ * @retval 0 for success, @a name has a valid name.
+ * @retval 1 there are no more subsections in the section.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int enumerate_sections (const ACE_Configuration_Section_Key& key,
+ int index, ACE_TString& name) = 0;
+
+ /// Sets a string-typed value.
+ /**
+ * @param key Configuration section to set the value in.
+ * @param name Name of the configuration value to set. If a value with
+ * the specified name exists, it is replaced.
+ * @param value The string to set the configuration value to.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int set_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const ACE_TString& value) = 0;
+
+ /// Sets a integer-typed value.
+ /**
+ * @param key Configuration section to set the value in.
+ * @param name Name of the configuration value to set. If a value with
+ * the specified name exists, it is replaced.
+ * @param value The integer to set the configuration value to.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int set_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int value) = 0;
+
+ /// Sets a binary-typed value.
+ /**
+ * @param key Configuration section to set the value in.
+ * @param name Name of the configuration value to set. If a value with
+ * the specified name exists, it is replaced.
+ * @param data Pointer to the binary data for the value.
+ * @param length Number of bytes for the new value.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int set_binary_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const void* data,
+ size_t length) = 0;
+
+ /// Gets a string-typed value.
+ /**
+ * @param key Configuration section to get the value from.
+ * @param name Name of the configuration value to get.
+ * @param value Receives the configuration value if it exists and
+ * has type STRING.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int get_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ ACE_TString& value) = 0;
+
+ /// Gets an integer-typed value.
+ /**
+ * @param key Configuration section to get the value from.
+ * @param name Name of the configuration value to get.
+ * @param value Receives the configuration value if it exists and
+ * has type INTEGER.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int get_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int& value) = 0;
+
+ /// Gets a binary-typed value.
+ /**
+ * @param key Configuration section to get the value from.
+ * @param name Name of the configuration value to get.
+ * @param data Receives a pointer to memory holding the binary data
+ * for the value. This method allocates the memory pointed
+ * to using operator new[]. The caller is responsible for
+ * freeing the memory using operator delete[].
+ * @param length Receives the number of bytes in the value.
+ *
+ * @retval 0 for success; caller is responsible for freeing the
+ * returned memory.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int get_binary_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ void*& data,
+ size_t& length) = 0;
+
+ /**
+ * Retrieves the type of a named configuration value.
+ *
+ * @param key Configuration section to look up the name in.
+ * @param name Name of the configuration value to get the type of.
+ * @param type Receives the data type of the named value, if it exists.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int find_value(const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ VALUETYPE& type) = 0;
+
+ /// Removes a named value.
+ /**
+ * @param key Configuration section to remove the named value from.
+ * @param name Name of the configuration value to remove.
+ *
+ * @retval 0 for success.
+ * @retval -1 for error; ACE_OS::last_error() retrieves error code.
+ */
+ virtual int remove_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name) = 0;
+
+ /**
+ * Expands <path_in> to <key_out> from @a key. If create is true,
+ * the subsections are created. Returns 0 on success, non zero on
+ * error The path consists of sections separated by the backslash
+ * '\' or forward slash '/'.
+ * Returns 0 on success, -1 if <create) is 0 and the path refers
+ * a nonexistant section
+ */
+ int expand_path (const ACE_Configuration_Section_Key& key,
+ const ACE_TString& path_in,
+ ACE_Configuration_Section_Key& key_out,
+ int create = 1);
+
+ /**
+ * @deprecated Exports the configuration database to filename.
+ * If @a filename is already present, it is overwritten. This function is
+ * deprecated and will be removed in a future version of ACE. Please use
+ * either ACE_Registry_ImpExp or ACE_Ini_ImpExp instead.
+ */
+ int export_config (const ACE_TCHAR* filename);
+
+ /**
+ * @deprecated Imports the configuration database from filename. Any
+ * existing data is not removed. This function is deprecated and will be
+ * removed in a future version of ACE. Please use ACE_Registry_ImpExp
+ * or ACE_Ini_ImpExp instead.
+ */
+ int import_config (const ACE_TCHAR* filename);
+
+ /**
+ * Determine if the contents of this object is the same as the
+ * contents of the object on the right hand side.
+ * Returns 1 (True) if they are equal and 0 (False) if they are not equal
+ */
+ bool operator==(const ACE_Configuration& rhs) const;
+
+ /**
+ * Determine if the contents of this object are different from the
+ * contents of the object on the right hand side.
+ * Returns 0 (False) if they are equal and 1 (True) if they are not equal
+ */
+ bool operator!=(const ACE_Configuration& rhs) const;
+
+ /**
+ * * Represents the "NULL" string to simplify the internal logic.
+ * */
+ static ACE_TCHAR NULL_String_;
+
+protected:
+ /// Default ctor
+ ACE_Configuration (void);
+
+ /// Resolves the internal key from a section key
+ ACE_Section_Key_Internal* get_internal_key
+ (const ACE_Configuration_Section_Key& key);
+
+ /**
+ * Tests to see if @a name is valid. @a name must be < 255 characters
+ * and not contain the path separator '\', brackets [] or = (maybe
+ * just restrict to alphanumeric?) returns non zero if name is not
+ * valid. The path separator is allowed, except for the first character,
+ * if @a allow_path is true.
+ */
+ int validate_name (const ACE_TCHAR* name, int allow_path = 0);
+
+ /**
+ * Test to see if @a name is valid. The default value for a key can be
+ * unnamed, which means either @a name is == 0 or @a name == '\0` is
+ * valid. Otherwise, it calls validate_name() to test @a name for the
+ * same rules that apply to keys.
+ */
+ int validate_value_name (const ACE_TCHAR* name);
+
+ // Not used
+ ACE_Configuration (const ACE_Configuration& rhs);
+ ACE_Configuration& operator= (const ACE_Configuration& rhs);
+
+
+ ACE_Configuration_Section_Key root_;
+};
+
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_REGISTRY)
+
+/**
+ * @class ACE_Section_Key_Win32
+ *
+ * @brief The Win32 registry implementation of an internal section key.
+ *
+ * Holds the HKEY for a section (registry key).
+ */
+class ACE_Export ACE_Section_Key_Win32 : public ACE_Section_Key_Internal
+{
+public:
+ /// Constructor based on an HKEY
+ ACE_Section_Key_Win32 (HKEY hKey);
+
+ HKEY hKey_;
+
+protected:
+ /// Destructor - invokes <RegCloseKey>
+ virtual ~ACE_Section_Key_Win32 (void);
+
+ // Not used
+ ACE_Section_Key_Win32 (const ACE_Section_Key_Win32& rhs);
+ ACE_Section_Key_Win32& operator= (const ACE_Section_Key_Win32& rhs);
+};
+
+/**
+ * @class ACE_Configuration_Win32Registry
+ *
+ * @brief The win32 registry implementation of a configuration database
+ *
+ * The win32 implementation basically makes calls through to the
+ * registry functions. The API is very similar so very little
+ * work must be done
+ */
+class ACE_Export ACE_Configuration_Win32Registry : public ACE_Configuration
+{
+public:
+
+ /**
+ * Constructor for registry configuration database. hKey is the
+ * base registry key to attach to. This class takes ownership of
+ * hKey, it will invoke <RegCloseKey> on it upon destruction.
+ */
+ explicit ACE_Configuration_Win32Registry (HKEY hKey);
+
+ /// Destructor
+ virtual ~ACE_Configuration_Win32Registry (void);
+
+ virtual int open_section (const ACE_Configuration_Section_Key& base,
+ const ACE_TCHAR* sub_section,
+ int create,
+ ACE_Configuration_Section_Key& result);
+
+ virtual int remove_section (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* sub_section,
+ int recursive);
+
+ virtual int enumerate_values (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name,
+ VALUETYPE& type);
+
+ virtual int enumerate_sections (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name);
+
+ virtual int set_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const ACE_TString& value);
+
+ virtual int set_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int value);
+
+ virtual int set_binary_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const void* data,
+ size_t length);
+
+ virtual int get_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ ACE_TString& value);
+
+ virtual int get_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int& value);
+
+ virtual int get_binary_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ void*& data,
+ size_t& length);
+
+ virtual int find_value(const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ VALUETYPE& type);
+
+ /// Removes the the value @a name from @a key. returns non zero on error
+ virtual int remove_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name);
+
+ /**
+ * This method traverses <path> through <hKey>. It is useful when
+ * you want the HKEY for a specific registry key, especially when
+ * initializing this implementation. Caller is responsible for
+ * closeing this key when it is no longer used. If create is 1
+ * (default) the keys are create if they don't already exist.
+ * Returns 0 on error
+ */
+ static HKEY resolve_key (HKEY hKey,
+ const ACE_TCHAR* path,
+ int create = 1);
+ virtual bool operator== (const ACE_Configuration_Win32Registry &rhs) const;
+ virtual bool operator!= (const ACE_Configuration_Win32Registry &rhs) const;
+
+protected:
+
+ /// Gets the HKEY for a configuration section
+ int load_key (const ACE_Configuration_Section_Key& key, HKEY& hKey);
+
+ // Not used
+ ACE_Configuration_Win32Registry (void);
+ ACE_Configuration_Win32Registry (const ACE_Configuration_Win32Registry& rhs);
+ ACE_Configuration_Win32Registry& operator= (const ACE_Configuration_Win32Registry& rhs);
+};
+#endif /* ACE_WIN32 && !ACE_LACKS_WIN32_REGISTRY */
+
+// ACE_Allocator version
+
+typedef ACE_Allocator_Adapter <ACE_Malloc <ACE_MMAP_MEMORY_POOL,
+ ACE_SYNCH_MUTEX> >
+ PERSISTENT_ALLOCATOR;
+typedef ACE_Allocator_Adapter <ACE_Malloc <ACE_LOCAL_MEMORY_POOL,
+ ACE_SYNCH_MUTEX> >
+ HEAP_ALLOCATOR;
+
+/**
+ * @class ACE_Configuration_ExtId
+ *
+ * @brief External ID for the section and value hash
+ *
+ * Contains a pointer to the section or value name.
+ */
+class ACE_Export ACE_Configuration_ExtId
+{
+public:
+ /// Defeault ctor
+ ACE_Configuration_ExtId (void);
+
+ /// Named constructor
+ explicit ACE_Configuration_ExtId (const ACE_TCHAR* name);
+
+ /// Copy ctor
+ ACE_Configuration_ExtId (const ACE_Configuration_ExtId& rhs);
+
+ /// destructor
+ ~ACE_Configuration_ExtId (void);
+
+ /// Assignment operator
+ ACE_Configuration_ExtId& operator= (const ACE_Configuration_ExtId& rhs);
+
+ /// Equality comparison operator (must match name_).
+ bool operator== (const ACE_Configuration_ExtId &rhs) const;
+
+ /// Inequality comparison operator.
+ bool operator!= (const ACE_Configuration_ExtId &rhs) const;
+
+ /// Frees the name of the value. needed since we don't know the
+ /// allocator name_ was created in
+ void free (ACE_Allocator *alloc);
+
+ /// <hash> function is required in order for this class to be usable by
+ /// ACE_Hash_Map_Manager.
+ u_long hash (void) const;
+
+ // = Data members.
+
+ const ACE_TCHAR * name_;
+
+ // Accessors
+ const ACE_TCHAR *name (void);
+};
+
+typedef ACE_Hash_Map_With_Allocator<ACE_Configuration_ExtId, int>
+ SUBSECTION_MAP;
+typedef ACE_Hash_Map_Manager_Ex<ACE_Configuration_ExtId,
+ int,
+ ACE_Hash<ACE_Configuration_ExtId>,
+ ACE_Equal_To<ACE_Configuration_ExtId>,
+ ACE_Null_Mutex>
+ SUBSECTION_HASH;
+
+/// @deprecated Deprecated typedef. Use the SUBSECTION_HASH::ENTRY trait instead.
+typedef SUBSECTION_HASH::ENTRY SUBSECTION_ENTRY;
+
+/**
+ * @class ACE_Configuration_Value_IntId
+ *
+ * @brief The section hash table internal value class
+ *
+ * This class is present as the internal portion of a section's
+ * value hash table It may store string, integer or binary data.
+ */
+class ACE_Export ACE_Configuration_Value_IntId
+{
+public:
+ /// Default constructor
+ ACE_Configuration_Value_IntId (void);
+
+ /// String constructor, takes ownership of string
+ explicit ACE_Configuration_Value_IntId (ACE_TCHAR* string);
+
+ /// Integer constructor
+ explicit ACE_Configuration_Value_IntId (u_int integer);
+
+ /// Binary constructor, takes ownership of data
+ ACE_Configuration_Value_IntId (void* data, size_t length);
+
+ /// Copy ctor
+ ACE_Configuration_Value_IntId (const ACE_Configuration_Value_IntId& rhs);
+
+ /// Destructor
+ ~ACE_Configuration_Value_IntId (void);
+
+ /// Assignment operator
+ ACE_Configuration_Value_IntId& operator= (
+ const ACE_Configuration_Value_IntId& rhs);
+
+ void free (ACE_Allocator *alloc);
+
+ // = Data members.
+
+ /**
+ * Points to the string value or binary data or IS the integer
+ * Length is only used when type_ == BINARY
+ */
+ ACE_Configuration::VALUETYPE type_;
+ union {
+ void * ptr_;
+ u_int int_;
+ } data_;
+ size_t length_;
+};
+
+typedef ACE_Hash_Map_With_Allocator<ACE_Configuration_ExtId,
+ ACE_Configuration_Value_IntId>
+ VALUE_MAP;
+typedef ACE_Hash_Map_Manager_Ex<ACE_Configuration_ExtId,
+ ACE_Configuration_Value_IntId,
+ ACE_Hash<ACE_Configuration_ExtId>,
+ ACE_Equal_To<ACE_Configuration_ExtId>,
+ ACE_Null_Mutex>
+ VALUE_HASH;
+
+// Deprecated typedef. Use the VALUE_HASH::ENTRY trait instead.
+typedef VALUE_HASH::ENTRY VALUE_ENTRY;
+
+/**
+ * @class ACE_Configuration_Section_IntId
+ *
+ * @brief The internal ID for a section hash table
+ *
+ * Contains a hash table containing value name/values
+ */
+class ACE_Export ACE_Configuration_Section_IntId
+{
+public:
+ /// Default ctor
+ ACE_Configuration_Section_IntId (void);
+
+ /// Named ctor
+ ACE_Configuration_Section_IntId (VALUE_MAP* value_hash_map,
+ SUBSECTION_MAP* section_hash_map);
+
+ /// Copy ctor
+ ACE_Configuration_Section_IntId (const ACE_Configuration_Section_IntId& rhs);
+
+ /// Destructor
+ ~ACE_Configuration_Section_IntId (void);
+
+ /// Assignment operator
+ ACE_Configuration_Section_IntId& operator= (
+ const ACE_Configuration_Section_IntId& rhs);
+
+ /// Frees the hash table and all its values
+ void free (ACE_Allocator *alloc);
+
+ // = Data Members.
+ VALUE_MAP* value_hash_map_;
+
+ SUBSECTION_MAP* section_hash_map_;
+};
+
+typedef ACE_Hash_Map_With_Allocator<ACE_Configuration_ExtId,
+ ACE_Configuration_Section_IntId>
+ SECTION_MAP;
+typedef ACE_Hash_Map_Manager_Ex<ACE_Configuration_ExtId,
+ ACE_Configuration_Section_IntId,
+ ACE_Hash<ACE_Configuration_ExtId>,
+ ACE_Equal_To<ACE_Configuration_ExtId>,
+ ACE_Null_Mutex>
+ SECTION_HASH;
+
+// Deprecated typedef. Use the SECTION_HASH::ENTRY trait instead.
+typedef SECTION_HASH::ENTRY SECTION_ENTRY;
+
+/**
+ * @class ACE_Configuration_Section_Key_Heap
+ *
+ * @brief Internal section key class for heap based configuration
+ * database.
+ *
+ * Contains a value iterator and full path name of section.
+ */
+class ACE_Export ACE_Configuration_Section_Key_Heap
+ : public ACE_Section_Key_Internal
+{
+public:
+ /// Constructor based on the full path of the section
+ ACE_Configuration_Section_Key_Heap (const ACE_TCHAR* path);
+
+ /// The path itself
+ ACE_TCHAR* path_;
+
+ /// The value iterator
+ VALUE_HASH::ITERATOR* value_iter_;
+
+ /// The sub section iterator
+ SUBSECTION_HASH::ITERATOR* section_iter_;
+protected:
+ /// Destructor - will delete the iterators
+ virtual ~ACE_Configuration_Section_Key_Heap (void);
+
+ // Not used
+ ACE_Configuration_Section_Key_Heap (const ACE_Configuration_Section_Key_Heap& rhs);
+ ACE_Configuration_Section_Key_Heap& operator= (const ACE_Configuration_Section_Key_Heap& rhs);
+};
+
+/**
+ * @class ACE_Configuration_Heap
+ *
+ * @brief The concrete implementation of a allocator based
+ * configuration database
+ *
+ * This class uses ACE's Allocators to manage a memory
+ * representation of a configuraiton database. A persistent heap
+ * may be used to store configurations persistently
+ *
+ * @note Before using this class you must call one of the open methods.
+ *
+ * @todo
+ * - Need to investigate what happens if memory mapped file gets mapped to
+ * a location different than it was created with.
+ */
+class ACE_Export ACE_Configuration_Heap : public ACE_Configuration
+{
+public:
+
+ /// Default ctor
+ ACE_Configuration_Heap (void);
+
+ /// Destructor
+ virtual ~ACE_Configuration_Heap (void);
+
+ /// Opens a configuration based on a file name
+ int open (const ACE_TCHAR* file_name,
+ void* base_address = ACE_DEFAULT_BASE_ADDR,
+ size_t default_map_size = ACE_DEFAULT_CONFIG_SECTION_SIZE);
+
+ /// Opens a heap based configuration
+ int open (size_t default_map_size = ACE_DEFAULT_CONFIG_SECTION_SIZE);
+
+ virtual int open_section (const ACE_Configuration_Section_Key& base,
+ const ACE_TCHAR* sub_section,
+ int create, ACE_Configuration_Section_Key& result);
+
+ virtual int remove_section (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* sub_section,
+ int recursive);
+
+ virtual int enumerate_values (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name,
+ VALUETYPE& type);
+
+ virtual int enumerate_sections (const ACE_Configuration_Section_Key& key,
+ int index,
+ ACE_TString& name);
+
+ virtual int set_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const ACE_TString& value);
+
+ virtual int set_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int value);
+
+ virtual int set_binary_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ const void* data,
+ size_t length);
+
+ virtual int get_string_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ ACE_TString& value);
+
+ virtual int get_integer_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ u_int& value);
+
+ virtual int get_binary_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ void* &data,
+ size_t &length);
+
+ virtual int find_value(const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ VALUETYPE& type);
+
+ /// Removes the the value @a name from @a key. returns non zero on error
+ virtual int remove_value (const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name);
+
+private:
+ /// <sub_section> may not contain path separators
+ int open_simple_section (const ACE_Configuration_Section_Key &base,
+ const ACE_TCHAR *sub_section,
+ int create, ACE_Configuration_Section_Key &result);
+ /// Adds a new section
+ int add_section (const ACE_Configuration_Section_Key &base,
+ const ACE_TCHAR *sub_section,
+ ACE_Configuration_Section_Key &result);
+
+ /// Helper for the <open> method.
+ int create_index (void);
+
+ /// Helper for create_index() method: places hash table into an
+ /// allocated space.
+ int create_index_helper (void *buffer);
+
+ int value_open_helper (size_t hash_table_size, void *buffer);
+
+ int section_open_helper (size_t hash_table_size, void *buffer);
+
+ int load_key (const ACE_Configuration_Section_Key& key, ACE_TString& name);
+
+ int new_section (const ACE_TString& section,
+ ACE_Configuration_Section_Key& result);
+
+ ACE_Configuration_Heap (const ACE_Configuration_Heap& rhs);
+ ACE_Configuration_Heap& operator= (const ACE_Configuration_Heap& rhs);
+
+ ACE_Allocator *allocator_;
+ SECTION_MAP *index_;
+ size_t default_map_size_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Configuration.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIGURATION_H */
diff --git a/ACE/ace/Configuration.inl b/ACE/ace/Configuration.inl
new file mode 100644
index 00000000000..b7c9af26f5c
--- /dev/null
+++ b/ACE/ace/Configuration.inl
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE const ACE_TCHAR*
+ACE_Configuration_ExtId::name (void)
+{
+ return name_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Configuration_Import_Export.cpp b/ACE/ace/Configuration_Import_Export.cpp
new file mode 100644
index 00000000000..ce4cbac84c1
--- /dev/null
+++ b/ACE/ace/Configuration_Import_Export.cpp
@@ -0,0 +1,670 @@
+// $Id$
+
+#include "ace/Configuration_Import_Export.h"
+#include "ace/OS_Errno.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Config_ImpExp_Base::ACE_Config_ImpExp_Base (ACE_Configuration& config)
+ : config_ (config)
+{
+}
+
+ACE_Config_ImpExp_Base::~ACE_Config_ImpExp_Base (void)
+{
+}
+
+ACE_Registry_ImpExp::ACE_Registry_ImpExp (ACE_Configuration& config)
+ : ACE_Config_ImpExp_Base (config)
+{
+}
+
+ACE_Registry_ImpExp::~ACE_Registry_ImpExp (void)
+{
+}
+
+// Imports the configuration database from filename.
+// No existing data is removed.
+int
+ACE_Registry_ImpExp::import_config (const ACE_TCHAR* filename)
+{
+ if (0 == filename)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ FILE* in = ACE_OS::fopen (filename, ACE_TEXT ("r"));
+ if (!in)
+ return -1;
+
+ u_int buffer_size = 4096;
+ u_int read_pos = 0;
+ ACE_TCHAR *buffer = 0;
+ ACE_NEW_NORETURN (buffer, ACE_TCHAR[buffer_size]);
+ if (!buffer)
+ {
+ ACE_Errno_Guard guard (errno);
+ (void) ACE_OS::fclose (in);
+ return -1;
+ }
+ ACE_Configuration_Section_Key section;
+ ACE_TCHAR *end = 0;
+
+ while (ACE_OS::fgets (buffer+read_pos, buffer_size - read_pos, in))
+ {
+ // Check if we got all the line.
+ end = ACE_OS::strrchr (buffer + read_pos,
+ ACE_TEXT ('\n')); // look for end of line
+ if (!end) // we havn't reach the end of the line yet
+ {
+ // allocate a new buffer - double size the previous one
+ ACE_TCHAR *temp_buffer;
+ ACE_NEW_NORETURN (temp_buffer, ACE_TCHAR[buffer_size * 2]);
+ if (!temp_buffer)
+ {
+ ACE_Errno_Guard guard (errno);
+ delete [] buffer;
+ (void) ACE_OS::fclose (in);
+ return -1;
+ }
+
+ // copy the beginnning of the line
+ ACE_OS::memcpy (temp_buffer, buffer, buffer_size);
+ read_pos = buffer_size - 1;
+ buffer_size *= 2;
+ delete [] buffer;
+ buffer = temp_buffer;
+ continue;
+ }
+ read_pos = 0;
+
+ // Check for a comment
+ if (buffer[0] == ACE_TEXT (';') || buffer[0] == ACE_TEXT ('#'))
+ continue;
+
+ if (buffer[0] == ACE_TEXT ('['))
+ {
+ // We have a new section here, strip out the section name
+ end = ACE_OS::strrchr (buffer, ACE_TEXT (']'));
+ if (!end)
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -3;
+ }
+ *end = 0;
+
+ if (config_.expand_path (config_.root_section (), buffer + 1, section, 1))
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -3;
+ }
+ continue;
+ } // end if firs char is a [
+
+ if (buffer[0] == ACE_TEXT ('"'))
+ {
+ // we have a value
+ end = ACE_OS::strchr (buffer+1, '"');
+ if (!end) // no closing quote, not a value so just skip it
+ continue;
+
+ // null terminate the name
+ *end = 0;
+ ACE_TCHAR* name = buffer + 1;
+ end+=2;
+ // determine the type
+ if (*end == '\"')
+ {
+ // string type
+ // truncate trailing "
+ ++end;
+ ACE_TCHAR* trailing = ACE_OS::strrchr (end, '"');
+ if (trailing)
+ *trailing = 0;
+ if (config_.set_string_value (section, name, end))
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -4;
+ }
+ }
+ else if (ACE_OS::strncmp (end, ACE_TEXT ("dword:"), 6) == 0)
+ {
+ // number type
+ ACE_TCHAR* endptr = 0;
+ unsigned long value = ACE_OS::strtoul (end + 6, &endptr, 16);
+ if (config_.set_integer_value (section, name, value))
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -4;
+ }
+ }
+ else if (ACE_OS::strncmp (end, ACE_TEXT ("hex:"), 4) == 0)
+ {
+ // binary type
+ size_t string_length = ACE_OS::strlen (end + 4);
+ // divide by 3 to get the actual buffer length
+ size_t length = string_length / 3;
+ size_t remaining = length;
+ u_char* data = 0;
+ ACE_NEW_RETURN (data,
+ u_char[length],
+ -1);
+ u_char* out = data;
+ ACE_TCHAR* inb = end + 4;
+ ACE_TCHAR* endptr = 0;
+ while (remaining)
+ {
+ u_char charin = (u_char) ACE_OS::strtoul (inb, &endptr, 16);
+ *out = charin;
+ ++out;
+ --remaining;
+ inb += 3;
+ }
+ if (config_.set_binary_value (section, name, data, length))
+ {
+ ACE_OS::fclose (in);
+ delete [] data;
+ delete [] buffer;
+ return -4;
+ }
+ else
+ delete [] data;
+ }
+ else
+ {
+ // invalid type, ignore
+ continue;
+ }
+ }// end if first char is a "
+ else
+ {
+ // if the first character is not a ", [, ;, or # we may be
+ // processing a file in the old format.
+ // Try and process the line as such and if it fails,
+ // return an error
+ int rc = process_previous_line_format (buffer, section);
+ if (rc != 0)
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return rc;
+ }
+ } // end if maybe old format
+ } // end while fgets
+
+ if (ferror (in))
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -1;
+ }
+
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return 0;
+}
+
+// This method exports the entire configuration database to <filename>.
+// Once the file is opened this method calls 'export_section' passing
+// the root section.
+int
+ACE_Registry_ImpExp::export_config (const ACE_TCHAR* filename)
+{
+ if (0 == filename)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ int result = -1;
+
+ FILE* out = ACE_OS::fopen (filename, ACE_TEXT ("w"));
+ if (out)
+ {
+ result = this->export_section (config_.root_section (),
+ ACE_TEXT (""),
+ out);
+ // The data may have been buffered and will be flush on close,
+ // so we need to check that the close succeeds.
+ if (ACE_OS::fclose (out) < 0)
+ result = -7;
+ }
+ return result;
+}
+
+// Method provided by derived classes in order to write one section
+// to the file specified. Called by export_config when exporting
+// the entire configuration object.
+
+int
+ACE_Registry_ImpExp::export_section (const ACE_Configuration_Section_Key& section,
+ const ACE_TString& path,
+ FILE* out)
+{
+ // don't export the root
+ if (path.length ())
+ {
+ // Write out the section header
+ ACE_TString header = ACE_TEXT ("[");
+ header += path;
+ header += ACE_TEXT ("]");
+ header += ACE_TEXT (" \n");
+ if (ACE_OS::fputs (header.fast_rep (), out) < 0)
+ return -1;
+ // Write out each value
+ int index = 0;
+ ACE_TString name;
+ ACE_Configuration::VALUETYPE type;
+ ACE_TString line;
+ ACE_TCHAR int_value[32];
+ ACE_TCHAR bin_value[3];
+ void* binary_data;
+ size_t binary_length;
+ ACE_TString string_value;
+ while (!config_.enumerate_values (section, index, name, type))
+ {
+ line = ACE_TEXT ("\"") + name + ACE_TEXT ("\"=");
+ switch (type)
+ {
+ case ACE_Configuration::INTEGER:
+ {
+ u_int value;
+ if (config_.get_integer_value (section, name.fast_rep (), value))
+ return -2;
+ ACE_OS::sprintf (int_value, ACE_TEXT ("%08x"), value);
+ line += ACE_TEXT ("dword:");
+ line += int_value;
+ break;
+ }
+ case ACE_Configuration::STRING:
+ {
+ if (config_.get_string_value (section,
+ name.fast_rep (),
+ string_value))
+ return -2;
+ line += ACE_TEXT ("\"");
+ line += string_value + ACE_TEXT ("\"");
+ break;
+ }
+#ifdef _WIN32
+ case ACE_Configuration::INVALID:
+ break; // JDO added break. Otherwise INVALID is processed
+ // like BINARY. If that's correct, please remove the
+ // break and these comments
+#endif
+ case ACE_Configuration::BINARY:
+ {
+ // not supported yet - maybe use BASE64 codeing?
+ if (config_.get_binary_value (section,
+ name.fast_rep (),
+ binary_data,
+ binary_length))
+ return -2;
+ line += ACE_TEXT ("hex:");
+ unsigned char* ptr = (unsigned char*)binary_data;
+ while (binary_length)
+ {
+ if (ptr != binary_data)
+ {
+ line += ACE_TEXT (",");
+ }
+ ACE_OS::sprintf (bin_value, ACE_TEXT ("%02x"), *ptr);
+ line += bin_value;
+ --binary_length;
+ ++ptr;
+ }
+ delete [] (char*) binary_data;
+ break;
+ }
+ default:
+ return -3;
+ }
+ line += ACE_TEXT ("\n");
+ if (ACE_OS::fputs (line.fast_rep (), out) < 0)
+ return -4;
+ ++index;
+ }
+ }
+ // Export all sub sections
+ int index = 0;
+ ACE_TString name;
+ ACE_Configuration_Section_Key sub_key;
+ ACE_TString sub_section;
+ while (!config_.enumerate_sections (section, index, name))
+ {
+ ACE_TString sub_section (path);
+ if (path.length ())
+ sub_section += ACE_TEXT ("\\");
+ sub_section += name;
+ if (config_.open_section (section, name.fast_rep (), 0, sub_key))
+ return -5;
+ if (export_section (sub_key, sub_section.fast_rep (), out))
+ return -6;
+ ++index;
+ }
+ return 0;
+}
+
+//
+// This method read the line format origionally used in ACE 5.1
+//
+int
+ACE_Registry_ImpExp::process_previous_line_format (ACE_TCHAR* buffer,
+ ACE_Configuration_Section_Key& section)
+{
+ // Chop any cr/lf at the end of the line.
+ ACE_TCHAR *endp = ACE_OS::strpbrk (buffer, ACE_TEXT ("\r\n"));
+ if (endp != 0)
+ *endp = '\0';
+
+ // assume this is a value, read in the value name
+ ACE_TCHAR* end = ACE_OS::strchr (buffer, '=');
+ if (end) // no =, not a value so just skip it
+ {
+ // null terminate the name
+ *end = 0;
+ ++end;
+ // determine the type
+ if (*end == '\"')
+ {
+ // string type
+ if(config_.set_string_value (section, buffer, end + 1))
+ return -4;
+ }
+ else if (*end == '#')
+ {
+ // number type
+ u_int value = ACE_OS::atoi (end + 1);
+ if (config_.set_integer_value (section, buffer, value))
+ return -4;
+ }
+ }
+ return 0;
+} // end read_previous_line_format
+
+
+ACE_Ini_ImpExp::ACE_Ini_ImpExp (ACE_Configuration& config)
+ : ACE_Config_ImpExp_Base (config)
+{
+}
+
+ACE_Ini_ImpExp::~ACE_Ini_ImpExp (void)
+{
+}
+
+// Method to read file and populate object.
+int
+ACE_Ini_ImpExp::import_config (const ACE_TCHAR* filename)
+{
+ if (0 == filename)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ FILE* in = ACE_OS::fopen (filename, ACE_TEXT ("r"));
+ if (!in)
+ return -1;
+
+ // @@ Make this a dynamic size!
+ ACE_TCHAR buffer[4096];
+ ACE_Configuration_Section_Key section;
+ while (ACE_OS::fgets (buffer, sizeof buffer, in))
+ {
+ ACE_TCHAR *line = this->squish (buffer);
+ // Check for a comment and blank line
+ if (line[0] == ACE_TEXT (';') ||
+ line[0] == ACE_TEXT ('#') ||
+ line[0] == '\0')
+ continue;
+
+ if (line[0] == ACE_TEXT ('['))
+ {
+ // We have a new section here, strip out the section name
+ ACE_TCHAR* end = ACE_OS::strrchr (line, ACE_TEXT (']'));
+ if (!end)
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+ *end = 0;
+
+ if (config_.expand_path (config_.root_section (),
+ line + 1,
+ section,
+ 1))
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+
+ continue;
+ }
+
+ // We have a line; name ends at equal sign.
+ ACE_TCHAR *end = ACE_OS::strchr (line, ACE_TEXT ('='));
+ if (end == 0) // No '='
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+ *end++ = '\0';
+ ACE_TCHAR *name = this->squish (line);
+#if 0
+ if (ACE_OS::strlen (name) == 0) // No name; just an '='
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+#endif
+ // Now find the start of the value
+ ACE_TCHAR *value = this->squish (end);
+ size_t value_len = ACE_OS::strlen (value);
+ if (value_len > 0)
+ {
+ // ACE 5.2 (and maybe earlier) exported strings may be enclosed
+ // in quotes. If string is quote-delimited, strip the quotes.
+ // Newer exported files don't have quote delimiters.
+ if (value[0] == ACE_TEXT ('"') &&
+ value[value_len - 1] == ACE_TEXT ('"'))
+ {
+ // Strip quotes off both ends.
+ value[value_len - 1] = '\0';
+ ++value;
+ }
+ }
+
+ if (config_.set_string_value (section, name, value))
+ {
+ ACE_OS::fclose (in);
+ return -4;
+ }
+ } // end while fgets
+
+ if (ferror (in))
+ {
+ ACE_OS::fclose (in);
+ return -1;
+ }
+
+ ACE_OS::fclose (in);
+ return 0;
+}
+
+// This method exports the entire configuration database to <filename>.
+// Once the file is opened this method calls 'export_section' passing
+// the root section.
+int
+ACE_Ini_ImpExp::export_config (const ACE_TCHAR* filename)
+{
+ if (0 == filename)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ int result = -1;
+
+ FILE* out = ACE_OS::fopen (filename, ACE_TEXT ("w"));
+ if (out)
+ {
+ result = this->export_section (config_.root_section (),
+ ACE_TEXT (""),
+ out);
+ // The data may have been buffered and will be flush on close,
+ // so we need to check that the close succeeds.
+ if (ACE_OS::fclose (out) < 0)
+ result = -7;
+ }
+ return result;
+}
+
+// Method provided by derived classes in order to write one section to the
+// file specified. Called by export_config when exporting the entire
+// configuration objet
+
+int
+ACE_Ini_ImpExp::export_section (const ACE_Configuration_Section_Key& section,
+ const ACE_TString& path,
+ FILE* out)
+{
+ // don't export the root
+ if (path.length ())
+ {
+ // Write out the section header
+ ACE_TString header = ACE_TEXT ("[");
+ header += path;
+ header += ACE_TEXT ("]\n");
+ if (ACE_OS::fputs (header.fast_rep (), out) < 0)
+ return -1;
+ // Write out each value
+ int index = 0;
+ ACE_TString name;
+ ACE_Configuration::VALUETYPE type;
+ ACE_TString line;
+ ACE_TCHAR int_value[32];
+ ACE_TCHAR bin_value[3];
+ void* binary_data;
+ size_t binary_length;
+ ACE_TString string_value;
+ while (!config_.enumerate_values (section, index, name, type))
+ {
+ line = name + ACE_TEXT ("=");
+ switch (type)
+ {
+ case ACE_Configuration::INTEGER:
+ {
+ u_int value;
+ if (config_.get_integer_value (section, name.fast_rep (), value))
+ return -2;
+ ACE_OS::sprintf (int_value, ACE_TEXT ("%08x"), value);
+ line += int_value;
+ break;
+ }
+ case ACE_Configuration::STRING:
+ {
+ if (config_.get_string_value (section,
+ name.fast_rep (),
+ string_value))
+ return -2;
+ line += string_value;
+ break;
+ }
+#ifdef _WIN32
+ case ACE_Configuration::INVALID:
+ break; // JDO added break. Otherwise INVALID is processed
+ // like BINARY. If that's correct, please remove the
+ // break and these comments
+#endif
+ case ACE_Configuration::BINARY:
+ {
+ // not supported yet - maybe use BASE64 codeing?
+ if (config_.get_binary_value (section,
+ name.fast_rep (),
+ binary_data,
+ binary_length))
+ return -2;
+ line += ACE_TEXT ("\"");
+ unsigned char* ptr = (unsigned char*)binary_data;
+ while (binary_length)
+ {
+ if (ptr != binary_data)
+ {
+ line += ACE_TEXT (",");
+ }
+ ACE_OS::sprintf (bin_value, ACE_TEXT ("%02x"), *ptr);
+ line += bin_value;
+ --binary_length;
+ ++ptr;
+ }
+ line += ACE_TEXT ("\"");
+ delete [] (char *) binary_data;
+ break;
+ }
+ default:
+ return -3;
+
+ }// end switch on type
+
+ line += ACE_TEXT ("\n");
+ if (ACE_OS::fputs (line.fast_rep (), out) < 0)
+ return -4;
+ ++index;
+ }// end while enumerating values
+ }
+ // Export all sub sections
+ int index = 0;
+ ACE_TString name;
+ ACE_Configuration_Section_Key sub_key;
+ ACE_TString sub_section;
+ while (!config_.enumerate_sections (section, index, name))
+ {
+ ACE_TString sub_section (path);
+ if (path.length ())
+ sub_section += ACE_TEXT ("\\");
+ sub_section += name;
+ if (config_.open_section (section, name.fast_rep (), 0, sub_key))
+ return -5;
+ if (export_section (sub_key, sub_section.fast_rep (), out))
+ return -6;
+ ++index;
+ }
+ return 0;
+
+}
+
+// Method to squish leading and trailing whitespaces from a string.
+// Whitespace is defined as: spaces (' '), tabs ('\t') or end-of-line
+// (cr/lf). The terminating nul is moved up to expunge trailing
+// whitespace and the returned pointer points at the first
+// non-whitespace character in the string, which may be the nul
+// terminator if the string is all whitespace.
+
+ACE_TCHAR *
+ACE_Ini_ImpExp::squish (ACE_TCHAR *src)
+{
+ ACE_TCHAR *cp = 0;
+
+ if (src == 0)
+ return 0;
+
+ // Start at the end and work backwards over all whitespace.
+ for (cp = src + ACE_OS::strlen (src) - 1;
+ cp != src;
+ --cp)
+ if (!ACE_OS::ace_isspace (*cp))
+ break;
+ cp[1] = '\0'; // Chop trailing whitespace
+
+ // Now start at the beginning and move over all whitespace.
+ for (cp = src; ACE_OS::ace_isspace (*cp); ++cp)
+ continue;
+
+ return cp;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Configuration_Import_Export.h b/ACE/ace/Configuration_Import_Export.h
new file mode 100644
index 00000000000..41dc401e0c7
--- /dev/null
+++ b/ACE/ace/Configuration_Import_Export.h
@@ -0,0 +1,215 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Configuration_Import_Export.h
+ *
+ * $Id$
+ *
+ * @author Jerry D. Odenwelder Jr. <jerry.o@mindspring.com>
+ * Chris Hafey <chris@stentorsoft.com>
+ *
+ * Classes defined in this file provide the ability to import and export
+ * ACE Configuration objects to/from disk files. The base class
+ * ACE_Config_ImpExp_Base provides the common functionality and the derived
+ * classes implement the import/export functionality for the specific format.
+ *
+ * @todo
+ * - Add locking for thread safety.
+ * - Provide ability to read file in one format and write in another.
+ * - See todo's in each class
+ */
+//=============================================================================
+
+#ifndef ACE_CONFIGURATION_IMPORT_EXPORT_H
+#define ACE_CONFIGURATION_IMPORT_EXPORT_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Configuration.h"
+#include "ace/SString.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Config_ImpExp_Base
+ *
+ * @brief Base class for file import/export configuration.
+ *
+ * This class provides base functionality for configuration objects
+ * that are persisted in files. It takes an ACE_Configuration
+ * object that it populates with the data read.
+ *
+ */
+class ACE_Export ACE_Config_ImpExp_Base
+{
+public:
+ /// Constructor taking the ACE_Configuration to import/export to
+ ACE_Config_ImpExp_Base (ACE_Configuration& config);
+
+ /**
+ * Destructor
+ */
+ virtual ~ACE_Config_ImpExp_Base (void);
+
+ /**
+ * Imports the configuration database from @a filename.
+ * No existing data is removed.
+ */
+ virtual int import_config (const ACE_TCHAR* filename) = 0;
+
+ /**
+ * This method exports the entire configuration database to @a filename.
+ * Once the file is opened this method calls 'export_section' passing
+ * the root section.
+ */
+ virtual int export_config (const ACE_TCHAR* filename) = 0;
+
+protected:
+ ACE_Configuration &config_;
+
+private:
+ ACE_Config_ImpExp_Base (const ACE_Config_ImpExp_Base&);
+ ACE_Config_ImpExp_Base& operator= (const ACE_Config_ImpExp_Base&);
+};
+
+/**
+ * @class ACE_Registry_ImpExp
+ *
+ * @brief Configuration object that imports/exports data to a file formatted
+ * using the Win32 Registry file export format. This format looks like
+ * [Section]
+ * "key"="String Data"
+ * "key"=dword: numeric data in hexidecimal format
+ * "key"=hex: binary data
+ *
+ * @todo
+ * - Add dynamic buffer when importing. currently it will not allow
+ * importing of values greater than a fixed ammount (4096 bytes)
+ *
+ */
+class ACE_Export ACE_Registry_ImpExp : public ACE_Config_ImpExp_Base
+{
+public:
+ /// Construction
+ ACE_Registry_ImpExp (ACE_Configuration&);
+
+ /// Destruction.
+ virtual ~ACE_Registry_ImpExp (void);
+
+ /**
+ * Imports the configuration database from filename.
+ * No existing data is removed.
+ */
+ virtual int import_config (const ACE_TCHAR* filename);
+
+ /**
+ * This method exports the entire configuration database to @a filename.
+ * Once the file is opened this method calls export_section() passing
+ * the root section.
+ */
+ virtual int export_config (const ACE_TCHAR* filename);
+
+private:
+ int export_section (const ACE_Configuration_Section_Key& section,
+ const ACE_TString& path,
+ FILE* out);
+
+ int process_previous_line_format (ACE_TCHAR* buffer,
+ ACE_Configuration_Section_Key& section);
+
+ ACE_Registry_ImpExp ( const ACE_Registry_ImpExp&);
+ ACE_Registry_ImpExp& operator= ( const ACE_Registry_ImpExp&);
+};
+
+/**
+ * @class ACE_Ini_ImpExp
+ *
+ * @brief Imports the configuration database from filename as strings.
+ * Allows non-typed values. (no #, dword: hex:, etc. prefixes) and
+ * skips whitespace (tabs and spaces) as in standard .ini and .conf
+ * files. Values (to right of equal sign) can be double quote
+ * delimited to embed tabs and spaces in the string.
+ * Caller must convert string to type.
+ *
+ * This method allows for lines in the .ini or .conf file like this:
+ *
+ * TimeToLive = 100
+ * Delay = FALSE
+ * Flags = FF34
+ * Heading = "ACE - Adaptive Communication Environment"
+ *
+ * (note leading whitespace (tabs) in examples below)
+ *
+ * SeekIndex = 14
+ * TraceLevel = 6 # Can comment lines like this
+ * Justification = left_justified
+ *
+ * The caller can then retrieve the string with the regular
+ * <get_string_value> function and convert the string to the
+ * desired data type.
+ *
+ * @todo
+ * - Strings with embedded newlines cause the import to fail
+ * - Strings with embedded quotes " cause the import to fail
+ * - Importing/exporting for values in the root section does not work
+ * - Add dynamic buffer when importing. currently it will not allow
+ * importing of values greater than a fixed ammount (4096 bytes)
+*/
+class ACE_Export ACE_Ini_ImpExp : public ACE_Config_ImpExp_Base
+{
+public:
+ /**
+ * Construction
+ */
+ ACE_Ini_ImpExp (ACE_Configuration&);
+
+ /**
+ * Destructor
+ */
+ virtual ~ACE_Ini_ImpExp (void);
+
+ /**
+ * Imports the configuration database from filename.
+ * No existing data is removed.
+ */
+ virtual int import_config (const ACE_TCHAR* filename);
+
+ /**
+ * This method exports the entire configuration database to @a filename.
+ * Once the file is opened this method calls export_section() passing
+ * the root section.
+ */
+ virtual int export_config (const ACE_TCHAR* filename);
+
+private:
+ /**
+ * Method provided by derived classes in order to write one section
+ * to the file specified. Called by export_config() when exporting
+ * the entire configuration object.
+ */
+ int export_section (const ACE_Configuration_Section_Key& section,
+ const ACE_TString& path,
+ FILE* out);
+
+ /**
+ * Method to squish leading and trailing whitespaces in a string.
+ * Whitespace is defined as: spaces (' '), tabs ('\\t') or cr/lf.
+ * Returns a pointer to the first non-whitespace character in the
+ * buffer provided, or a pointer to the terminating null if the string
+ * is all whitespace. The terminating null is moved forward to the
+ * first character past the last non-whitespace.
+ */
+ ACE_TCHAR *squish (ACE_TCHAR *src);
+
+ ACE_Ini_ImpExp (const ACE_Ini_ImpExp&);
+ ACE_Ini_ImpExp& operator= (const ACE_Ini_ImpExp&);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIGURATION_IMPORT_EXPORT_H */
diff --git a/ACE/ace/Connection_Recycling_Strategy.cpp b/ACE/ace/Connection_Recycling_Strategy.cpp
new file mode 100644
index 00000000000..c5bc6910d21
--- /dev/null
+++ b/ACE/ace/Connection_Recycling_Strategy.cpp
@@ -0,0 +1,13 @@
+#include "ace/Connection_Recycling_Strategy.h"
+
+
+ACE_RCSID(ace, Connection_Recycling_Strategy, "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Connection_Recycling_Strategy::~ACE_Connection_Recycling_Strategy (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Connection_Recycling_Strategy.h b/ACE/ace/Connection_Recycling_Strategy.h
new file mode 100644
index 00000000000..fa9599f678c
--- /dev/null
+++ b/ACE/ace/Connection_Recycling_Strategy.h
@@ -0,0 +1,63 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Connection_Recycling_Strategy.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+#ifndef ACE_CONNECTION_RECYCLING_STRATEGY_H
+#define ACE_CONNECTION_RECYCLING_STRATEGY_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Recyclable.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Connection_Recycling_Strategy
+ *
+ * @brief Defines the interface for a connection recycler.
+ */
+class ACE_Export ACE_Connection_Recycling_Strategy
+{
+public:
+ /// Virtual Destructor
+ virtual ~ACE_Connection_Recycling_Strategy (void);
+
+ /// Remove from cache.
+ virtual int purge (const void *recycling_act) = 0;
+
+ /// Add to cache.
+ virtual int cache (const void *recycling_act) = 0;
+
+ virtual int recycle_state (const void *recycling_act,
+ ACE_Recyclable_State new_state) = 0;
+
+ /// Get/Set recycle_state.
+ virtual ACE_Recyclable_State recycle_state (const void *recycling_act) const = 0;
+
+ /// Mark as closed.
+ virtual int mark_as_closed (const void *recycling_act) = 0;
+
+ /// Mark as closed.(non-locking version)
+ virtual int mark_as_closed_i (const void *recycling_act) = 0;
+
+ /// Cleanup hint and reset @a act_holder to zero if @a act_holder != 0.
+ virtual int cleanup_hint (const void *recycling_act,
+ void **act_holder = 0) = 0;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /*ACE_CONNECTION_RECYCLING_STRATEGY*/
diff --git a/ACE/ace/Connector.cpp b/ACE/ace/Connector.cpp
new file mode 100644
index 00000000000..112fbca4003
--- /dev/null
+++ b/ACE/ace/Connector.cpp
@@ -0,0 +1,964 @@
+// $Id$
+
+#ifndef ACE_CONNECTOR_CPP
+#define ACE_CONNECTOR_CPP
+
+#include "ace/Connector.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/os_fcntl.h" /* Has ACE_NONBLOCK */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Connector)
+
+template <class SVC_HANDLER>
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler
+(ACE_Connector_Base<SVC_HANDLER> &connector,
+ SVC_HANDLER *sh,
+ long id)
+ : connector_ (connector)
+ , svc_handler_ (sh)
+ , timer_id_ (id)
+{
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler");
+
+ this->reference_counting_policy ().value
+ (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
+}
+
+template <class SVC_HANDLER> SVC_HANDLER *
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::svc_handler (void)
+{
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::svc_handler");
+ return this->svc_handler_;
+}
+
+template <class SVC_HANDLER> long
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id (void)
+{
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id");
+ return this->timer_id_;
+}
+
+template <class SVC_HANDLER> void
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id (long id)
+{
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id");
+ this->timer_id_ = id;
+}
+
+template <class SVC_HANDLER> void
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("svc_handler_ = %x"), this->svc_handler_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntimer_id_ = %d"), this->timer_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER> bool
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::close (SVC_HANDLER *&sh)
+{
+ // Make sure that we haven't already initialized the Svc_Handler.
+ if (!this->svc_handler_)
+ return false;
+
+ {
+ // Exclusive access to the Reactor.
+ ACE_GUARD_RETURN (ACE_Lock,
+ ace_mon,
+ this->reactor ()->lock (),
+ 0);
+
+ // Double check.
+ if (!this->svc_handler_)
+ return false;
+
+ // Remember the Svc_Handler.
+ sh = this->svc_handler_;
+ ACE_HANDLE h = sh->get_handle ();
+ this->svc_handler_ = 0;
+
+ // Remove this handle from the set of non-blocking handles
+ // in the Connector.
+ this->connector_.non_blocking_handles ().remove (h);
+
+ // Cancel timer.
+ if (this->reactor ()->cancel_timer (this->timer_id (),
+ 0,
+ 0) == -1)
+ return false;
+
+ // Remove from Reactor.
+ if (this->reactor ()->remove_handler (
+ h,
+ ACE_Event_Handler::ALL_EVENTS_MASK) == -1)
+ return false;
+ }
+
+ return true;
+}
+
+
+template <class SVC_HANDLER> int
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout
+(const ACE_Time_Value &tv,
+ const void *arg)
+{
+ // This method is called if a connection times out before completing.
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout");
+
+ SVC_HANDLER *svc_handler = 0;
+ int retval = this->close (svc_handler) ? 0 : -1;
+
+ // 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 (svc_handler != 0 && svc_handler->handle_timeout (tv, arg) == -1)
+ svc_handler->handle_close (svc_handler->get_handle (),
+ ACE_Event_Handler::TIMER_MASK);
+
+ return retval;
+}
+
+
+template <class SVC_HANDLER> int
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input (ACE_HANDLE)
+{
+ // Called when a failure occurs during asynchronous connection
+ // establishment.
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input");
+
+ SVC_HANDLER *svc_handler = 0;
+ int const retval = this->close (svc_handler) ? 0 : -1;
+
+ // Close Svc_Handler.
+ if (svc_handler != 0)
+ svc_handler->close (0);
+
+ return retval;
+}
+
+template <class SVC_HANDLER> int
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output (ACE_HANDLE handle)
+{
+ // Called when a connection is establishment asynchronous.
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output");
+
+ // Grab the connector ref before smashing ourselves in close().
+ ACE_Connector_Base<SVC_HANDLER> &connector = this->connector_;
+ SVC_HANDLER *svc_handler = 0;
+ int const retval = this->close (svc_handler) ? 0 : -1;
+
+ if (svc_handler != 0)
+ connector.initialize_svc_handler (handle, svc_handler);
+
+ return retval;
+}
+
+template <class SVC_HANDLER> int
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_exception (ACE_HANDLE h)
+{
+ // On Win32, the except mask must also be set for asynchronous
+ // connects.
+ ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_exception");
+ return this->handle_output (h);
+}
+
+template <class SVC_HANDLER> int
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::resume_handler (void)
+{
+ return ACE_Event_Handler::ACE_EVENT_HANDLER_NOT_RESUMED;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags_ = %d"), this->flags_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_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 <Connector> is using.
+ sh->reactor (this->reactor ());
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::activate_svc_handler (SVC_HANDLER *svc_handler)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_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 SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_PEER_CONNECTOR &
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connector (void) const
+{
+ return const_cast<ACE_PEER_CONNECTOR &> (this->connector_);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::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)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler");
+
+ return this->connector_.connect (svc_handler->peer (),
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::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)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_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 SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r, int flags)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open");
+ this->reactor (r);
+ this->flags_ = flags;
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector (ACE_Reactor *r,
+ int flags)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector");
+ (void) this->open (r, flags);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect
+(SVC_HANDLER *&sh,
+ 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)
+{
+ // Initiate connection to peer.
+ return this->connect_i (sh,
+ 0,
+ remote_addr,
+ synch_options,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect
+(SVC_HANDLER *&sh,
+ 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)
+{
+ // Initiate connection to peer.
+ return this->connect_i (sh,
+ &sh_copy,
+ remote_addr,
+ synch_options,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i
+(SVC_HANDLER *&sh,
+ 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)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_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 = 0;
+ int const use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR];
+
+ if (use_reactor)
+ timeout = const_cast<ACE_Time_Value *> (&ACE_Time_Value::zero);
+ else
+ timeout = const_cast<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);
+
+ // Activate immediately if we are connected.
+ if (result != -1)
+ return this->activate_svc_handler (sh);
+
+ // Delegate to connection strategy.
+ if (use_reactor && ACE_OS::last_error () == EWOULDBLOCK)
+ {
+ // If the connection hasn't completed and we are using
+ // non-blocking semantics then register
+ // ACE_NonBlocking_Connect_Handler 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->nonblocking_connect (sh, synch_options);
+ else
+ result = this->nonblocking_connect (*sh_copy, synch_options);
+
+ // If for some reason the <nonblocking_connect> 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 service handler to avoid handle
+ // leaks.
+ if (sh_copy == 0)
+ {
+ if (sh)
+ sh->close (0);
+ }
+ else if (*sh_copy)
+ (*sh_copy)->close (0);
+ }
+
+ return -1;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_n
+(size_t n,
+ SVC_HANDLER *sh[],
+ ACE_PEER_CONNECTOR_ADDR 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 SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cancel (SVC_HANDLER *sh)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cancel");
+
+ ACE_Event_Handler *handler =
+ this->reactor ()->find_handler (sh->get_handle ());
+
+ if (handler == 0)
+ return -1;
+
+ // find_handler() increments handler's refcount; ensure we decrement it.
+ ACE_Event_Handler_var safe_handler (handler);
+
+ NBCH *nbch =
+ dynamic_cast<NBCH *> (handler);
+
+ if (nbch == 0)
+ return -1;
+
+ SVC_HANDLER *tmp_sh = 0;
+
+ if (nbch->close (tmp_sh) == false)
+ return -1;
+
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::nonblocking_connect
+(SVC_HANDLER *sh,
+ const ACE_Synch_Options &synch_options)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::nonblocking_connect");
+
+ // Must have a valid Reactor for non-blocking connects to work.
+ if (this->reactor () == 0)
+ return -1;
+
+ // Register the pending SVC_HANDLER so that it can be activated
+ // later on when the connection completes.
+
+ ACE_HANDLE handle = sh->get_handle ();
+ long timer_id = -1;
+ ACE_Time_Value *tv = 0;
+ NBCH *nbch = 0;
+
+ ACE_NEW_RETURN (nbch,
+ NBCH (*this,
+ sh,
+ -1),
+ -1);
+
+ ACE_Event_Handler_var safe_nbch (nbch);
+
+ // Exclusive access to the Reactor.
+ ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), -1);
+
+ // Register handle with the reactor for connection events.
+ ACE_Reactor_Mask mask = ACE_Event_Handler::CONNECT_MASK;
+ if (this->reactor ()->register_handler (handle,
+ nbch,
+ mask) == -1)
+ goto reactor_registration_failure;
+
+ // Add handle to non-blocking handle set.
+ this->non_blocking_handles ().insert (handle);
+
+ // If we're starting connection under timer control then we need to
+ // schedule a timeout with the ACE_Reactor.
+ tv = const_cast<ACE_Time_Value *> (synch_options.time_value ());
+ if (tv != 0)
+ {
+ timer_id =
+ this->reactor ()->schedule_timer (nbch,
+ synch_options.arg (),
+ *tv);
+ if (timer_id == -1)
+ goto timer_registration_failure;
+
+ // Remember timer id.
+ nbch->timer_id (timer_id);
+ }
+
+ return 0;
+
+ // Undo previous actions using the ol' "goto label and fallthru"
+ // trick...
+ timer_registration_failure:
+
+ // Remove from Reactor.
+ this->reactor ()->remove_handler (handle, mask);
+
+ // Remove handle from the set of non-blocking handles.
+ this->non_blocking_handles ().remove (handle);
+
+ /* FALLTHRU */
+
+ reactor_registration_failure:
+ // Close the svc_handler
+
+ sh->close (0);
+
+ return -1;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector (void)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector");
+
+ this->close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::initialize_svc_handler
+(ACE_HANDLE handle,
+ SVC_HANDLER *svc_handler)
+{
+ // 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.
+ svc_handler->set_handle (handle);
+
+ ACE_PEER_CONNECTOR_ADDR raddr;
+
+ // Check to see if we're connected.
+ if (svc_handler->peer ().get_remote_addr (raddr) != -1)
+ this->activate_svc_handler (svc_handler);
+ else // Somethings gone wrong, so close down...
+ {
+#if defined (ACE_WIN32)
+ // 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 (svc_handler->peer ().get_remote_addr (raddr) != -1)
+ this->activate_svc_handler (svc_handler);
+ else // do the svc handler close below...
+#endif /* ACE_WIN32 */
+ svc_handler->close (0);
+ }
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::reactor (ACE_Reactor *reactor)
+{
+ this->reactor_ = reactor;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Reactor *
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::reactor (void) const
+{
+ return this->reactor_;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Unbounded_Set<ACE_HANDLE> &
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::non_blocking_handles (void)
+{
+ return this->non_blocking_handles_;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close (void)
+{
+ // If there are no non-blocking handle pending, return immediately.
+ if (this->non_blocking_handles ().size () == 0)
+ return 0;
+
+ // Exclusive access to the Reactor.
+ ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), -1);
+
+ // Go through all the non-blocking handles. It is necessary to
+ // create a new iterator each time because we remove from the handle
+ // set when we cancel the Svc_Handler.
+ ACE_HANDLE *handle = 0;
+ while (1)
+ {
+ ACE_Unbounded_Set_Iterator<ACE_HANDLE>
+ iterator (this->non_blocking_handles ());
+ if (!iterator.next (handle))
+ break;
+
+ ACE_Event_Handler *handler =
+ this->reactor ()->find_handler (*handle);
+ if (handler == 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%t: Connector::close h %d, no handler\n"),
+ *handle));
+ // Remove handle from the set of non-blocking handles.
+ this->non_blocking_handles ().remove (*handle);
+ continue;
+ }
+
+ // find_handler() incremented handler's refcount; ensure it's decremented
+ ACE_Event_Handler_var safe_handler (handler);
+ NBCH *nbch = dynamic_cast<NBCH *> (handler);
+ if (nbch == 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%t: Connector::close h %d handler %@ ")
+ ACE_TEXT ("not a legit handler\n"),
+ *handle,
+ handler));
+ // Remove handle from the set of non-blocking handles.
+ this->non_blocking_handles ().remove (*handle);
+ continue;
+ }
+ SVC_HANDLER *svc_handler = nbch->svc_handler ();
+
+ // Cancel the non-blocking connection.
+ this->cancel (svc_handler);
+
+ // Close the associated Svc_Handler.
+ svc_handler->close (0);
+ }
+
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::fini (void)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::fini");
+
+ return this->close ();
+}
+
+// Hook called by the explicit dynamic linking facility.
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::init (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::init");
+ return -1;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::suspend (void)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::suspend");
+ return -1;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume (void)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume");
+ return -1;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::info");
+ ACE_TCHAR buf[BUFSIZ];
+
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("%s\t %s"),
+ ACE_TEXT ("ACE_Connector"),
+ ACE_TEXT ("# connector factory\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return static_cast<int> (ACE_OS::strlen (buf));
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r,
+ int flags)
+{
+ ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open");
+ return this->open (r, 0, 0, 0, flags);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_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<SVC_HANDLER, ACE_PEER_CONNECTOR_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_ &&
+ cre_s != 0)
+ {
+ delete this->creation_strategy_;
+ this->creation_strategy_ = 0;
+ this->delete_creation_strategy_ = false;
+ }
+
+ 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_ = true;
+ }
+
+
+ // Initialize the accept strategy.
+
+ if (this->connect_strategy_ != 0 &&
+ this->delete_connect_strategy_ &&
+ conn_s != 0)
+ {
+ delete this->connect_strategy_;
+ this->connect_strategy_ = 0;
+ this->delete_connect_strategy_ = false;
+ }
+
+ 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_ = true;
+ }
+
+ // Initialize the concurrency strategy.
+
+ if (this->concurrency_strategy_ != 0 &&
+ this->delete_concurrency_strategy_ &&
+ con_s != 0)
+ {
+ delete this->concurrency_strategy_;
+ this->concurrency_strategy_ = 0;
+ this->delete_concurrency_strategy_ = false;
+ }
+
+ 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_ = true;
+ }
+
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_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_ (false),
+ connect_strategy_ (0),
+ delete_connect_strategy_ (false),
+ concurrency_strategy_ (0),
+ delete_concurrency_strategy_ (false)
+{
+ ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Strategy_Connector");
+
+ if (this->open (reactor, cre_s, conn_s, con_s, flags) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_Strategy_Connector::ACE_Strategy_Connector")));
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Strategy_Connector (void)
+{
+ ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Strategy_Connector");
+
+ // Close down
+ this->close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close (void)
+{
+ if (this->delete_creation_strategy_)
+ delete this->creation_strategy_;
+ this->delete_creation_strategy_ = false;
+ this->creation_strategy_ = 0;
+
+ if (this->delete_connect_strategy_)
+ delete this->connect_strategy_;
+ this->delete_connect_strategy_ = false;
+ this->connect_strategy_ = 0;
+
+ if (this->delete_concurrency_strategy_)
+ delete this->concurrency_strategy_;
+ this->delete_concurrency_strategy_ = false;
+ this->concurrency_strategy_ = 0;
+
+ return SUPER::close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ return this->creation_strategy_->make_svc_handler (sh);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Strategy_Connector<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)
+{
+ 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> int
+ACE_Strategy_Connector<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)
+{
+ return this->connect_strategy_->connect_svc_handler (sh,
+ sh_copy,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::activate_svc_handler (SVC_HANDLER *svc_handler)
+{
+ return this->concurrency_strategy_->activate_svc_handler (svc_handler, this);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Creation_Strategy<SVC_HANDLER> *
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::creation_strategy (void) const
+{
+ return this->creation_strategy_;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_strategy (void) const
+{
+ return this->connect_strategy_;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Concurrency_Strategy<SVC_HANDLER> *
+ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::concurrency_strategy (void) const
+{
+ return this->concurrency_strategy_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_CONNECTOR_C */
diff --git a/ACE/ace/Connector.h b/ACE/ace/Connector.h
new file mode 100644
index 00000000000..0b92d55efcd
--- /dev/null
+++ b/ACE/ace/Connector.h
@@ -0,0 +1,563 @@
+// -*- 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_Object.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Strategies_T.h"
+#include "ace/Synch_Options.h"
+#include "ace/Unbounded_Set.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Connector_Base
+ *
+ * @brief This base interface allows ACE_NonBlocking_Connect_Handler
+ * to only care about the SVC_HANDLER template parameter of the
+ * ACE_Connector. Otherwise, ACE_NonBlocking_Connect_Handler would
+ * have to be configured with all the template parameters that
+ * ACE_Connector is configured with.
+ */
+template <class SVC_HANDLER>
+class ACE_Connector_Base
+{
+public:
+
+ virtual ~ACE_Connector_Base (void) {}
+
+ /// Initialize the Svc_Handler.
+ virtual void initialize_svc_handler (ACE_HANDLE handle,
+ SVC_HANDLER *svc_handler) = 0;
+
+ /// Return the handle set representing the non-blocking connects in
+ /// progress.
+ virtual ACE_Unbounded_Set<ACE_HANDLE> &non_blocking_handles (void) = 0;
+};
+
+/**
+ * @class ACE_NonBlocking_Connect_Handler
+ *
+ * @brief Performs non-blocking connects on behalf of the Connector.
+ */
+template <class SVC_HANDLER>
+class ACE_NonBlocking_Connect_Handler : public ACE_Event_Handler
+{
+public:
+
+ /// Constructor.
+ ACE_NonBlocking_Connect_Handler (ACE_Connector_Base<SVC_HANDLER> &connector,
+ SVC_HANDLER *,
+ long timer_id);
+
+ /// Close up and return underlying SVC_HANDLER through @c sh.
+ /**
+ * If the return value is true the close was performed succesfully,
+ * implying that this object was removed from the reactor and thereby
+ * (by means of reference counting decremented to 0) deleted.
+ * If the return value is false, the close was not successful.
+ * The @c sh does not have any connection to the return
+ * value. The argument will return a valid svc_handler object if a
+ * valid one exists within the object. Returning a valid svc_handler
+ * pointer also invalidates the svc_handler contained in this
+ * object.
+ */
+ bool close (SVC_HANDLER *&sh);
+
+ /// Get SVC_HANDLER.
+ SVC_HANDLER *svc_handler (void);
+
+ /// Get handle.
+ ACE_HANDLE handle (void);
+
+ /// Set handle.
+ void handle (ACE_HANDLE);
+
+ /// Get timer id.
+ long timer_id (void);
+
+ /// Set timer id.
+ void timer_id (long timer_id);
+
+ /// 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 suceeds (on
+ /// some platforms only).
+ virtual int handle_exception (ACE_HANDLE fd);
+
+ /// This method is called if a connection times out before
+ /// completing.
+ virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg);
+
+ /// Should Reactor resume us if we have been suspended before the upcall?
+ virtual int resume_handler (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /// Connector base.
+ ACE_Connector_Base<SVC_HANDLER> &connector_;
+
+ /// Associated SVC_HANDLER.
+ SVC_HANDLER *svc_handler_;
+
+ /// Associated timer id.
+ long timer_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
+ * actively establishes connections. The SVC_HANDLER is instantiated
+ * with a concrete type that performs the application-specific
+ * service. Both blocking and non-blocking connects are supported.
+ * Further, non-blocking connects support timeouts.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+class ACE_Connector : public ACE_Connector_Base<SVC_HANDLER>, public ACE_Service_Object
+{
+public:
+
+ // Useful STL-style traits.
+ typedef typename SVC_HANDLER::addr_type addr_type;
+ typedef ACE_PEER_CONNECTOR connector_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+ typedef typename ACE_PEER_CONNECTOR::PEER_ADDR peer_addr_type;
+ typedef ACE_PEER_CONNECTOR_ADDR ACE_PEER_ADDR_TYPEDEF;
+
+ /**
+ * Initialize a connector. @a 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. @a 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 @a svc_handler to peer at @a remote_addr
+ * using @a synch_options. If the caller wants to designate the
+ * selected @a local_addr they can (and can also insist that the
+ * @a local_addr be reused by passing a value @a reuse_addr ==
+ * 1). @a flags and @a 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
+ = (peer_addr_type &) 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 @a 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 @a 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
+ = (peer_addr_type &) ACE_PEER_CONNECTOR_ADDR_ANY,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /**
+ * Initiate connection of @a n @a svc_handlers to peers at
+ * @a remote_addrs using @a synch_options. Returns -1 if failure
+ * occurs and 0 otherwise. If @a failed_svc_handlers is non-NULL, a
+ * 1 is placed in the corresponding index of @a failed_svc_handlers
+ * 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 the @a svc_handler that was started asynchronously. Note that
+ * this is the only case when the Connector does not actively close
+ * the @a svc_handler. It is left up to the caller of <cancel> to
+ * decide the fate of the @a svc_handler.
+ */
+ virtual int cancel (SVC_HANDLER *svc_handler);
+
+ /// Close down the Connector. All pending non-blocking connects are
+ /// canceled and the corresponding svc_handler is closed.
+ virtual int close (void);
+
+ /// Return the underlying PEER_CONNECTOR object.
+ virtual ACE_PEER_CONNECTOR &connector (void) const;
+
+ /// Initialize Svc_Handler.
+ virtual void initialize_svc_handler (ACE_HANDLE handle,
+ SVC_HANDLER *svc_handler);
+
+ /// Set Reactor.
+ virtual void reactor (ACE_Reactor *reactor);
+
+ /// Get Reactor.
+ virtual ACE_Reactor *reactor (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_NonBlocking_Connect_Handler<SVC_HANDLER> NBCH;
+
+ // = 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 @a sh == 0, else @a 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 @a svc_handler to the
+ * @a 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 @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);
+
+ /// Creates and registers ACE_NonBlocking_Connect_Handler.
+ int nonblocking_connect (SVC_HANDLER *,
+ const ACE_Synch_Options &);
+
+ /// Implementation of 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);
+
+ /// Return the handle set representing the non-blocking connects in
+ /// progress.
+ ACE_Unbounded_Set<ACE_HANDLE> &non_blocking_handles (void);
+
+ // = 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 @a buf.
+ virtual int info (ACE_TCHAR **strp, size_t length) 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:
+ /// This is the peer connector factory.
+ ACE_PEER_CONNECTOR connector_;
+
+ /**
+ * 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_;
+
+ /// Pointer to the Reactor.
+ ACE_Reactor *reactor_;
+
+ /// Handle set representing the non-blocking connects in progress.
+ ACE_Unbounded_Set<ACE_HANDLE> non_blocking_handles_;
+
+};
+
+/**
+ * @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:
+
+ // Useful STL-style traits.
+ typedef ACE_Creation_Strategy<SVC_HANDLER>
+ creation_strategy_type;
+ typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+ connect_strategy_type;
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER>
+ concurrency_strategy_type;
+ typedef ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+ base_type;
+
+ // = Define some useful (old style) 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;
+
+ /**
+ * Initialize a connector. @a 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. @a 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. @a 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);
+
+ // = 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 @a sh == 0, else @a 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>.
+ * @a sh_copy is used to obtain a copy of the @a 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 @a sh safely, using
+ * the internal locks in the Connect_Strategy, while saving a TSS
+ * copy in @a 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_;
+
+ /// true if Connector created the creation strategy and thus should
+ /// delete it, else false.
+ bool delete_creation_strategy_;
+
+ /// Connect strategy for a Connector.
+ CONNECT_STRATEGY *connect_strategy_;
+
+ /// true if Connector created the connect strategy and thus should
+ /// delete it, else false.
+ bool delete_connect_strategy_;
+
+ /// Concurrency strategy for an <Connector>.
+ CONCURRENCY_STRATEGY *concurrency_strategy_;
+
+ /// true if Connector created the concurrency strategy and thus should
+ /// delete it, else false.
+ bool delete_concurrency_strategy_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#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/ace/Containers.cpp b/ACE/ace/Containers.cpp
new file mode 100644
index 00000000000..2904225a3c9
--- /dev/null
+++ b/ACE/ace/Containers.cpp
@@ -0,0 +1,12 @@
+// $Id$
+
+#include "ace/Containers.h"
+
+ACE_RCSID (ace,
+ Containers,
+ "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Containers.inl"
+#endif /* __ACE_INLINE__ */
+
diff --git a/ACE/ace/Containers.h b/ACE/ace/Containers.h
new file mode 100644
index 00000000000..8fd886394b0
--- /dev/null
+++ b/ACE/ace/Containers.h
@@ -0,0 +1,71 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Containers.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CONTAINERS_H
+#define ACE_CONTAINERS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> class ACE_Double_Linked_List;
+template <class T> class ACE_Double_Linked_List_Iterator_Base;
+template <class T> class ACE_Double_Linked_List_Iterator;
+template <class T> class ACE_Double_Linked_List_Reverse_Iterator;
+
+/**
+ * @class ACE_DLList_Node
+ *
+ * @brief Base implementation of element in a DL list. Needed for
+ * ACE_Double_Linked_List.
+ */
+class ACE_Export ACE_DLList_Node
+{
+public:
+ friend class ACE_Double_Linked_List<ACE_DLList_Node>;
+ friend class ACE_Double_Linked_List_Iterator_Base<ACE_DLList_Node>;
+ friend class ACE_Double_Linked_List_Iterator<ACE_DLList_Node>;
+ friend class ACE_Double_Linked_List_Reverse_Iterator<ACE_DLList_Node>;
+
+ ACE_DLList_Node (void *i,
+ ACE_DLList_Node *n = 0,
+ ACE_DLList_Node *p = 0);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ void *item_;
+
+ ACE_DLList_Node *next_;
+ ACE_DLList_Node *prev_;
+
+protected:
+ ACE_DLList_Node (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Containers.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Containers_T.h"
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONTAINERS_H */
diff --git a/ACE/ace/Containers.inl b/ACE/ace/Containers.inl
new file mode 100644
index 00000000000..01b7a243891
--- /dev/null
+++ b/ACE/ace/Containers.inl
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_DLList_Node::ACE_DLList_Node (void)
+ : item_ (0),
+ next_ (0),
+ prev_ (0)
+{
+}
+
+ACE_INLINE
+ACE_DLList_Node::ACE_DLList_Node (void *i,
+ ACE_DLList_Node *n,
+ ACE_DLList_Node *p)
+ : item_ (i),
+ next_ (n),
+ prev_ (p)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Containers_T.cpp b/ACE/ace/Containers_T.cpp
new file mode 100644
index 00000000000..c28e3e1fc41
--- /dev/null
+++ b/ACE/ace/Containers_T.cpp
@@ -0,0 +1,1930 @@
+// $Id$
+
+#ifndef ACE_CONTAINERS_T_CPP
+#define ACE_CONTAINERS_T_CPP
+
+#include "ace/Log_Msg.h"
+#include "ace/Malloc_Base.h"
+#include "ace/OS_Memory.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Containers.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Containers_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Bounded_Stack)
+
+template <class T> void
+ACE_Bounded_Stack<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Bounded_Stack<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template<class T>
+ACE_Bounded_Stack<T>::ACE_Bounded_Stack (size_t size)
+ : size_ (size),
+ top_ (0)
+{
+ ACE_NEW (this->stack_,
+ T[size]);
+ ACE_TRACE ("ACE_Bounded_Stack<T>::ACE_Bounded_Stack");
+}
+
+template<class T>
+ACE_Bounded_Stack<T>::ACE_Bounded_Stack (const ACE_Bounded_Stack<T> &s)
+ : size_ (s.size_),
+ top_ (s.top_)
+{
+ ACE_NEW (this->stack_,
+ T[s.size_]);
+
+ ACE_TRACE ("ACE_Bounded_Stack<T>::ACE_Bounded_Stack");
+
+ for (size_t i = 0; i < this->top_; i++)
+ this->stack_[i] = s.stack_[i];
+}
+
+template<class T> void
+ACE_Bounded_Stack<T>::operator= (const ACE_Bounded_Stack<T> &s)
+{
+ ACE_TRACE ("ACE_Bounded_Stack<T>::operator=");
+
+ if (&s != this)
+ {
+ if (this->size_ < s.size_)
+ {
+ delete [] this->stack_;
+ ACE_NEW (this->stack_,
+ T[s.size_]);
+ this->size_ = s.size_;
+ }
+ this->top_ = s.top_;
+
+ for (size_t i = 0; i < this->top_; i++)
+ this->stack_[i] = s.stack_[i];
+ }
+}
+
+template<class T>
+ACE_Bounded_Stack<T>::~ACE_Bounded_Stack (void)
+{
+ ACE_TRACE ("ACE_Bounded_Stack<T>::~ACE_Bounded_Stack");
+ delete [] this->stack_;
+}
+
+// ----------------------------------------
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Fixed_Stack)
+
+template <class T, size_t ACE_SIZE> void
+ACE_Fixed_Stack<T, ACE_SIZE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template<class T, size_t ACE_SIZE>
+ACE_Fixed_Stack<T, ACE_SIZE>::ACE_Fixed_Stack (void)
+ : size_ (ACE_SIZE),
+ top_ (0)
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::ACE_Fixed_Stack");
+}
+
+template<class T, size_t ACE_SIZE>
+ACE_Fixed_Stack<T, ACE_SIZE>::ACE_Fixed_Stack (const ACE_Fixed_Stack<T, ACE_SIZE> &s)
+ : size_ (s.size_),
+ top_ (s.top_)
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::ACE_Fixed_Stack");
+ for (size_t i = 0; i < this->top_; i++)
+ this->stack_[i] = s.stack_[i];
+}
+
+template<class T, size_t ACE_SIZE> void
+ACE_Fixed_Stack<T, ACE_SIZE>::operator= (const ACE_Fixed_Stack<T, ACE_SIZE> &s)
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::operator=");
+
+ if (&s != this)
+ {
+ this->top_ = s.top_;
+
+ for (size_t i = 0; i < this->top_; i++)
+ this->stack_[i] = s.stack_[i];
+ }
+}
+
+template<class T, size_t ACE_SIZE>
+ACE_Fixed_Stack<T, ACE_SIZE>::~ACE_Fixed_Stack (void)
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::~ACE_Fixed_Stack");
+}
+
+//----------------------------------------
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Stack)
+
+template <class T> void
+ACE_Unbounded_Stack<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template<class T>
+ACE_Unbounded_Stack<T>::ACE_Unbounded_Stack (ACE_Allocator *alloc)
+ : head_ (0),
+ cur_size_ (0),
+ allocator_ (alloc)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::ACE_Unbounded_Stack");
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_NEW_MALLOC (this->head_,
+ (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)),
+ ACE_Node<T>);
+ this->head_->next_ = this->head_;
+}
+
+template<class T> void
+ACE_Unbounded_Stack<T>::delete_all_nodes (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::delete_all_nodes");
+
+ while (this->is_empty () == 0)
+ {
+ ACE_Node<T> *temp = this->head_->next_;
+ this->head_->next_ = temp->next_;
+ ACE_DES_FREE_TEMPLATE (temp, this->allocator_->free,
+ ACE_Node, <T>);
+ }
+
+ this->cur_size_ = 0;
+
+ ACE_ASSERT (this->head_ == this->head_->next_
+ && this->is_empty ());
+}
+
+template<class T> void
+ACE_Unbounded_Stack<T>::copy_all_nodes (const ACE_Unbounded_Stack<T> &s)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::copy_all_nodes");
+
+ ACE_ASSERT (this->head_ == this->head_->next_);
+
+ ACE_Node<T> *temp = this->head_;
+
+ for (ACE_Node<T> *s_temp = s.head_->next_;
+ s_temp != s.head_;
+ s_temp = s_temp->next_)
+ {
+ ACE_Node<T> *nptr = temp->next_;
+ ACE_NEW_MALLOC (temp->next_,
+ (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)),
+ ACE_Node<T> (s_temp->item_, nptr));
+ temp = temp->next_;
+ }
+ this->cur_size_ = s.cur_size_;
+}
+
+template<class T>
+ACE_Unbounded_Stack<T>::ACE_Unbounded_Stack (const ACE_Unbounded_Stack<T> &s)
+ : head_ (0),
+ cur_size_ (0),
+ allocator_ (s.allocator_)
+{
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_NEW_MALLOC (this->head_,
+ (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)),
+ ACE_Node<T>);
+ this->head_->next_ = this->head_;
+
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::ACE_Unbounded_Stack");
+ this->copy_all_nodes (s);
+}
+
+template<class T> void
+ACE_Unbounded_Stack<T>::operator= (const ACE_Unbounded_Stack<T> &s)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::operator=");
+
+ if (this != &s)
+ {
+ this->delete_all_nodes ();
+ this->copy_all_nodes (s);
+ }
+}
+
+template<class T>
+ACE_Unbounded_Stack<T>::~ACE_Unbounded_Stack (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::~ACE_Unbounded_Stack");
+
+ this->delete_all_nodes ();
+ ACE_DES_FREE_TEMPLATE (head_,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+}
+
+template<class T> int
+ACE_Unbounded_Stack<T>::push (const T &new_item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::push");
+
+ ACE_Node<T> *temp = 0;
+
+ ACE_NEW_MALLOC_RETURN (temp,
+ static_cast<ACE_Node<T> *> (this->allocator_->malloc (sizeof (ACE_Node<T>))),
+ ACE_Node<T> (new_item, this->head_->next_),
+ -1);
+ this->head_->next_ = temp;
+ ++this->cur_size_;
+ return 0;
+}
+
+template<class T> int
+ACE_Unbounded_Stack<T>::pop (T &item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::pop");
+
+ if (this->is_empty ())
+ return -1;
+ else
+ {
+ ACE_Node<T> *temp = this->head_->next_;
+ item = temp->item_;
+ this->head_->next_ = temp->next_;
+
+ ACE_DES_FREE_TEMPLATE (temp,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+ --this->cur_size_;
+ return 0;
+ }
+}
+
+template <class T> int
+ACE_Unbounded_Stack<T>::find (const T &item) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::find");
+ // Set <item> into the dummy node.
+ this->head_->item_ = item;
+
+ ACE_Node<T> *temp = this->head_->next_;
+
+ // Keep looping until we find the item.
+ while (!(temp->item_ == item))
+ temp = temp->next_;
+
+ // If we found the dummy node then it's not really there, otherwise,
+ // it is there.
+ return temp == this->head_ ? -1 : 0;
+}
+
+template <class T> int
+ACE_Unbounded_Stack<T>::insert (const T &item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::insert");
+
+ if (this->find (item) == 0)
+ return 1;
+ else
+ return this->push (item);
+}
+
+template <class T> int
+ACE_Unbounded_Stack<T>::remove (const T &item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::remove");
+
+ // Insert the item to be founded into the dummy node.
+ this->head_->item_ = item;
+
+ ACE_Node<T> *curr = this->head_;
+
+ while (!(curr->next_->item_ == item))
+ curr = curr->next_;
+
+ if (curr->next_ == this->head_)
+ return -1; // Item was not found.
+ else
+ {
+ ACE_Node<T> *temp = curr->next_;
+ // Skip over the node that we're deleting.
+ curr->next_ = temp->next_;
+ --this->cur_size_;
+ ACE_DES_FREE_TEMPLATE (temp,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+ return 0;
+ }
+}
+
+//--------------------------------------------------
+ACE_ALLOC_HOOK_DEFINE(ACE_Double_Linked_List_Iterator_Base)
+
+template <class T>
+ACE_Double_Linked_List_Iterator_Base<T>::ACE_Double_Linked_List_Iterator_Base (const ACE_Double_Linked_List<T> &dll)
+ : current_ (0), dllist_ (&dll)
+{
+ // Do nothing
+}
+
+template <class T>
+ACE_Double_Linked_List_Iterator_Base<T>::ACE_Double_Linked_List_Iterator_Base (const ACE_Double_Linked_List_Iterator_Base<T> &iter)
+ : current_ (iter.current_),
+ dllist_ (iter.dllist_)
+{
+ // Do nothing
+}
+
+
+template <class T> T *
+ACE_Double_Linked_List_Iterator_Base<T>::next (void) const
+{
+ return this->not_done ();
+}
+
+template <class T> int
+ACE_Double_Linked_List_Iterator_Base<T>::next (T *&ptr) const
+{
+ ptr = this->not_done ();
+ return ptr ? 1 : 0;
+}
+
+
+template <class T> int
+ACE_Double_Linked_List_Iterator_Base<T>::done (void) const
+{
+ return this->not_done () ? 0 : 1;
+}
+
+template <class T> T &
+ACE_Double_Linked_List_Iterator_Base<T>::operator* (void) const
+{
+ return *(this->not_done ());
+}
+
+// @@ Is this a valid retasking? Make sure to check with Purify and
+// whatnot that we're not leaking memory or doing any other screwing things.
+template <class T> void
+ACE_Double_Linked_List_Iterator_Base<T>::reset (ACE_Double_Linked_List<T> &dll)
+{
+ current_ = 0;
+ dllist_ = &dll;
+}
+
+ template <class T> int
+ACE_Double_Linked_List_Iterator_Base<T>::go_head (void)
+{
+ this->current_ = static_cast<T*> (dllist_->head_->next_);
+ return this->current_ ? 1 : 0;
+}
+
+template <class T> int
+ACE_Double_Linked_List_Iterator_Base<T>::go_tail (void)
+{
+ this->current_ = static_cast<T*> (dllist_->head_->prev_);
+ return this->current_ ? 1 : 0;
+}
+
+template <class T> T *
+ACE_Double_Linked_List_Iterator_Base<T>::not_done (void) const
+{
+ if (this->current_ != this->dllist_->head_)
+ return this->current_;
+ else
+ return 0;
+}
+
+template <class T> T *
+ACE_Double_Linked_List_Iterator_Base<T>::do_advance (void)
+{
+ if (this->not_done ())
+ {
+ this->current_ = static_cast<T*> (this->current_->next_);
+ return this->not_done ();
+ }
+ else
+ return 0;
+}
+
+template <class T> T *
+ACE_Double_Linked_List_Iterator_Base<T>::do_retreat (void)
+{
+ if (this->not_done ())
+ {
+ this->current_ = static_cast<T*> (this->current_->prev_);
+ return this->not_done ();
+ }
+ else
+ return 0;
+}
+
+template <class T> void
+ACE_Double_Linked_List_Iterator_Base<T>::dump_i (void) const
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("current_ = %x"), this->current_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+//--------------------------------------------------
+ACE_ALLOC_HOOK_DEFINE(ACE_Double_Linked_List_Iterator)
+
+template <class T>
+ACE_Double_Linked_List_Iterator<T>::ACE_Double_Linked_List_Iterator (const ACE_Double_Linked_List<T> &dll)
+ : ACE_Double_Linked_List_Iterator_Base <T> (dll)
+{
+ this->current_ = static_cast<T*> (dll.head_->next_);
+ // Advance current_ out of the null area and onto the first item in
+ // the list
+}
+
+template <class T> void
+ACE_Double_Linked_List_Iterator<T>::reset (ACE_Double_Linked_List<T> &dll)
+{
+ this->ACE_Double_Linked_List_Iterator_Base <T>::reset (dll);
+ this->current_ = static_cast<T*> (dll.head_->next_);
+ // Advance current_ out of the null area and onto the first item in
+ // the list
+}
+
+template <class T> int
+ACE_Double_Linked_List_Iterator<T>::first (void)
+{
+ return this->go_head ();
+}
+
+template <class T> int
+ACE_Double_Linked_List_Iterator<T>::advance (void)
+{
+ return this->do_advance () ? 1 : 0;
+}
+
+template <class T> T*
+ACE_Double_Linked_List_Iterator<T>::advance_and_remove (int dont_remove)
+{
+ T* item = 0;
+ if (dont_remove)
+ this->do_advance ();
+ else
+ {
+ item = this->next ();
+ this->do_advance ();
+ // It seems dangerous to remove nodes in an iterator, but so it goes...
+ ACE_Double_Linked_List<T> *dllist =
+ const_cast<ACE_Double_Linked_List<T> *> (this->dllist_);
+ dllist->remove (item);
+ }
+ return item;
+}
+
+template <class T> void
+ACE_Double_Linked_List_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+// Prefix advance.
+
+template <class T>
+ACE_Double_Linked_List_Iterator<T> &
+ACE_Double_Linked_List_Iterator<T>::operator++ (void)
+{
+ this->do_advance ();
+ return *this;
+}
+
+
+// Postfix advance.
+
+template <class T>
+ACE_Double_Linked_List_Iterator<T>
+ACE_Double_Linked_List_Iterator<T>::operator++ (int)
+{
+ ACE_Double_Linked_List_Iterator<T> retv (*this);
+ this->do_advance ();
+ return retv;
+}
+
+
+// Prefix reverse.
+
+template <class T>
+ACE_Double_Linked_List_Iterator<T> &
+ACE_Double_Linked_List_Iterator<T>::operator-- (void)
+{
+ this->do_retreat ();
+ return *this;
+}
+
+
+// Postfix reverse.
+
+template <class T>
+ACE_Double_Linked_List_Iterator<T>
+ACE_Double_Linked_List_Iterator<T>::operator-- (int)
+{
+ ACE_Double_Linked_List_Iterator<T> retv (*this);
+ this->do_retreat ();
+ return retv;
+}
+
+
+//--------------------------------------------------
+ACE_ALLOC_HOOK_DEFINE(ACE_Double_Linked_List_Reverse_Iterator)
+
+ template <class T>
+ACE_Double_Linked_List_Reverse_Iterator<T>::ACE_Double_Linked_List_Reverse_Iterator (ACE_Double_Linked_List<T> &dll)
+ : ACE_Double_Linked_List_Iterator_Base <T> (dll)
+{
+ this->current_ = static_cast<T*> (dll.head_->prev_);
+ // Advance current_ out of the null area and onto the last item in
+ // the list
+}
+
+template <class T> void
+ACE_Double_Linked_List_Reverse_Iterator<T>::reset (ACE_Double_Linked_List<T> &dll)
+{
+ this->ACE_Double_Linked_List_Iterator_Base <T>::reset (dll);
+ this->current_ = static_cast<T*> (dll.head_->prev_);
+ // Advance current_ out of the null area and onto the last item in
+ // the list
+}
+
+template <class T> int
+ACE_Double_Linked_List_Reverse_Iterator<T>::first (void)
+{
+ return this->go_tail ();
+}
+
+template <class T> int
+ACE_Double_Linked_List_Reverse_Iterator<T>::advance (void)
+{
+ return this->do_retreat () ? 1 : 0;
+}
+
+template <class T> T*
+ACE_Double_Linked_List_Reverse_Iterator<T>::advance_and_remove (int dont_remove)
+{
+ T* item = 0;
+ if (dont_remove)
+ this->do_retreat ();
+ else
+ {
+ item = this->next ();
+ this->do_retreat ();
+ // It seems dangerous to remove nodes in an iterator, but so it goes...
+ ACE_Double_Linked_List<T> *dllist =
+ const_cast<ACE_Double_Linked_List<T> *> (this->dllist_);
+ dllist->remove (item);
+ }
+ return item;
+}
+
+template <class T> void
+ACE_Double_Linked_List_Reverse_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+// Prefix advance.
+
+template <class T>
+ACE_Double_Linked_List_Reverse_Iterator<T> &
+ACE_Double_Linked_List_Reverse_Iterator<T>::operator++ (void)
+{
+ this->do_retreat ();
+ return *this;
+}
+
+
+// Postfix advance.
+
+template <class T>
+ACE_Double_Linked_List_Reverse_Iterator<T>
+ACE_Double_Linked_List_Reverse_Iterator<T>::operator++ (int)
+{
+ ACE_Double_Linked_List_Reverse_Iterator<T> retv (*this);
+ this->do_retreat ();
+ return retv;
+}
+
+
+// Prefix reverse.
+
+template <class T>
+ACE_Double_Linked_List_Reverse_Iterator<T> &
+ACE_Double_Linked_List_Reverse_Iterator<T>::operator-- (void)
+{
+ this->do_advance ();
+ return *this;
+}
+
+
+// Postfix reverse.
+
+template <class T>
+ACE_Double_Linked_List_Reverse_Iterator<T>
+ACE_Double_Linked_List_Reverse_Iterator<T>::operator-- (int)
+{
+ ACE_Double_Linked_List_Reverse_Iterator<T> retv (*this);
+ this->do_advance ();
+ return retv;
+}
+
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Double_Linked_List)
+
+ template <class T>
+ACE_Double_Linked_List<T>:: ACE_Double_Linked_List (ACE_Allocator *alloc)
+ : size_ (0), allocator_ (alloc)
+{
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_NEW_MALLOC (this->head_,
+ (T *) this->allocator_->malloc (sizeof (T)),
+ T);
+ this->init_head ();
+}
+
+template <class T>
+ACE_Double_Linked_List<T>::ACE_Double_Linked_List (const ACE_Double_Linked_List<T> &cx)
+ : allocator_ (cx.allocator_)
+{
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_NEW_MALLOC (this->head_,
+ (T *) this->allocator_->malloc (sizeof (T)),
+ T);
+ this->init_head ();
+ this->copy_nodes (cx);
+ this->size_ = cx.size_;
+}
+
+template <class T> void
+ACE_Double_Linked_List<T>::operator= (const ACE_Double_Linked_List<T> &cx)
+{
+ if (this != &cx)
+ {
+ this->delete_nodes ();
+ this->copy_nodes (cx);
+ }
+}
+
+template <class T>
+ACE_Double_Linked_List<T>::~ACE_Double_Linked_List (void)
+{
+ this->delete_nodes ();
+
+ ACE_DES_FREE (head_,
+ this->allocator_->free,
+ T);
+
+ this->head_ = 0;
+}
+
+template <class T> int
+ACE_Double_Linked_List<T>::is_empty (void) const
+{
+ return this->size () ? 0 : 1;
+}
+
+template <class T> int
+ACE_Double_Linked_List<T>::is_full (void) const
+{
+ return 0; // We have no bound.
+}
+
+template <class T> T *
+ACE_Double_Linked_List<T>::insert_tail (T *new_item)
+{
+ // Insert it before <head_>, i.e., at tail.
+ this->insert_element (new_item, 1);
+ return new_item;
+}
+
+template <class T> T *
+ACE_Double_Linked_List<T>::insert_head (T *new_item)
+{
+ this->insert_element (new_item); // Insert it after <head_>, i.e., at head.
+ return new_item;
+}
+
+template <class T> T *
+ACE_Double_Linked_List<T>::delete_head (void)
+{
+ if (this->is_empty ())
+ return 0;
+
+ T *temp = static_cast<T *> (this->head_->next_);
+ // Detach it from the list.
+ this->remove_element (temp);
+ return temp;
+}
+
+template <class T> T *
+ACE_Double_Linked_List<T>::delete_tail (void)
+{
+ if (this->is_empty ())
+ return 0;
+
+ T *temp = static_cast <T *> (this->head_->prev_);
+ // Detach it from the list.
+ this->remove_element (temp);
+ return temp;
+}
+
+template <class T> void
+ACE_Double_Linked_List<T>::reset (void)
+{
+ this->delete_nodes ();
+}
+
+template <class T> int
+ACE_Double_Linked_List<T>::get (T *&item, size_t slot)
+{
+ ACE_Double_Linked_List_Iterator<T> iter (*this);
+
+ for (size_t i = 0;
+ i < slot && !iter.done ();
+ i++)
+ iter.advance ();
+
+ item = iter.next ();
+ return item ? 0 : -1;
+}
+
+template <class T> size_t
+ACE_Double_Linked_List<T>::size (void) const
+{
+ return this->size_;
+}
+
+template <class T> void
+ACE_Double_Linked_List<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // Dump the state of an object.
+#endif /* ACE_HAS_DUMP */
+}
+
+#if 0
+template <class T> T *
+ACE_Double_Linked_List<T>::find (const T &item)
+{
+ for (ACE_Double_Linked_List_Iterator<T> iter (*this);
+ !iter.done ();
+ iter.advance ())
+ {
+ T *temp = iter.next ();
+
+ if (*temp == item)
+ return temp;
+ }
+
+ return 0;
+}
+
+template <class T> int
+ACE_Double_Linked_List<T>::remove (const T &item)
+{
+ T *temp = this->find (item);
+
+ if (temp != 0)
+ return this->remove (temp);
+ else
+ return -1;
+}
+#endif /* 0 */
+
+template <class T> int
+ACE_Double_Linked_List<T>::remove (T *n)
+{
+ return this->remove_element (n);
+}
+
+template <class T> void
+ACE_Double_Linked_List<T>::delete_nodes (void)
+{
+ while (! this->is_empty ())
+ {
+ T * temp = static_cast<T*> (this->head_->next_);
+ this->remove_element (temp);
+ ACE_DES_FREE (temp,
+ this->allocator_->free,
+ T);
+ }
+}
+
+template <class T> void
+ACE_Double_Linked_List<T>::copy_nodes (const ACE_Double_Linked_List<T> &c)
+{
+ for (ACE_Double_Linked_List_Iterator<T> iter (c);
+ !iter.done ();
+ iter.advance ())
+ {
+ T* temp = 0;
+ ACE_NEW_MALLOC (temp,
+ (T *)this->allocator_->malloc (sizeof (T)),
+ T (*iter.next ()));
+ this->insert_tail (temp);
+ }
+}
+
+template <class T> void
+ACE_Double_Linked_List<T>::init_head (void)
+{
+ this->head_->next_ = this->head_;
+ this->head_->prev_ = this->head_;
+}
+
+template <class T> int
+ACE_Double_Linked_List<T>::insert_element (T *new_item,
+ int before,
+ T *old_item)
+{
+ if (old_item == 0)
+ old_item = this->head_;
+
+ if (before)
+ old_item = static_cast<T *> (old_item->prev_);
+
+ new_item->next_ = old_item->next_;
+ new_item->next_->prev_ = new_item;
+ new_item->prev_ = old_item;
+ old_item->next_ = new_item;
+ ++this->size_;
+ return 0; // Well, what will cause errors here?
+}
+
+template <class T> int
+ACE_Double_Linked_List<T>::remove_element (T *item)
+{
+ // Notice that you have to ensure that item is an element of this
+ // list. We can't do much checking here.
+
+ if (item == this->head_ || item->next_ == 0
+ || item->prev_ == 0 || this->size () == 0) // Can't remove head
+ return -1;
+
+ item->prev_->next_ = item->next_;
+ item->next_->prev_ = item->prev_;
+ item->next_ = item->prev_ = 0; // reset pointers to prevent double removal.
+ --this->size_;
+ return 0;
+}
+
+//--------------------------------------------------
+ACE_ALLOC_HOOK_DEFINE(ACE_Fixed_Set)
+
+template <class T, size_t ACE_SIZE> size_t
+ACE_Fixed_Set<T, ACE_SIZE>::size (void) const
+{
+ ACE_TRACE ("ACE_Fixed_Set<T, ACE_SIZE>::size");
+ return this->cur_size_;
+}
+
+template <class T, size_t ACE_SIZE> void
+ACE_Fixed_Set<T, ACE_SIZE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Fixed_Set<T, ACE_SIZE>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T, size_t ACE_SIZE>
+ACE_Fixed_Set<T, ACE_SIZE>::~ACE_Fixed_Set (void)
+{
+ ACE_TRACE ("ACE_Fixed_Set<T, ACE_SIZE>::~ACE_Fixed_Set");
+ this->cur_size_ = 0;
+}
+
+template <class T, size_t ACE_SIZE>
+ACE_Fixed_Set<T, ACE_SIZE>::ACE_Fixed_Set (const ACE_Fixed_Set<T, ACE_SIZE> &fs)
+ : cur_size_ (fs.cur_size_)
+{
+ ACE_TRACE ("ACE_Fixed_Set<T>::ACE_Fixed_Set");
+
+ for (size_t i = 0, j = 0; i < fs.max_size_ && j < this->cur_size_; ++i)
+ if (fs.search_structure_[i].is_free_ == 0)
+ this->search_structure_[j++] = fs.search_structure_[i];
+}
+
+template <class T, size_t ACE_SIZE> void
+ACE_Fixed_Set<T, ACE_SIZE>::operator= (const ACE_Fixed_Set<T, ACE_SIZE> &fs)
+{
+ ACE_TRACE ("ACE_Fixed_Set<T>::operator=");
+
+ if (this != &fs)
+ {
+ this->cur_size_ = fs.cur_size_;
+
+ for (size_t i = 0, j = 0; i < fs.max_size_ && j < this->cur_size_; ++i)
+ if (fs.search_structure_[i].is_free_ == 0)
+ this->search_structure_[j++] = fs.search_structure_[i];
+ }
+}
+
+template <class T, size_t ACE_SIZE>
+ACE_Fixed_Set<T, ACE_SIZE>::ACE_Fixed_Set (void)
+ : cur_size_ (0),
+ max_size_ (ACE_SIZE)
+{
+ ACE_TRACE ("ACE_Fixed_Set<T, ACE_SIZE>::ACE_Fixed_Set");
+ for (size_t i = 0; i < this->max_size_; i++)
+ this->search_structure_[i].is_free_ = 1;
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set<T, ACE_SIZE>::find (const T &item) const
+{
+ ACE_TRACE ("ACE_Fixed_Set<T, ACE_SIZE>::find");
+
+ for (size_t i = 0, j = 0; i < this->max_size_ && j < this->cur_size_; ++i)
+ if (this->search_structure_[i].is_free_ == 0)
+ {
+ if (this->search_structure_[i].item_ == item)
+ return 0;
+ ++j;
+ }
+
+ return -1;
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set<T, ACE_SIZE>::insert (const T &item)
+{
+ ACE_TRACE ("ACE_Fixed_Set<T, ACE_SIZE>::insert");
+ ssize_t first_free = -1; // Keep track of first free slot.
+ size_t i;
+
+ for (i = 0;
+ i < this->max_size_ && first_free == -1;
+ ++i)
+
+ // First, make sure we don't allow duplicates.
+
+ if (this->search_structure_[i].is_free_ == 0)
+ {
+ if (this->search_structure_[i].item_ == item)
+ return 1;
+ }
+ else
+ first_free = static_cast<ssize_t> (i);
+
+ // If we found a free spot let's reuse it.
+
+ if (first_free > -1)
+ {
+ this->search_structure_[first_free].item_ = item;
+ this->search_structure_[first_free].is_free_ = 0;
+ this->cur_size_++;
+ return 0;
+ }
+ else /* No more room! */
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set<T, ACE_SIZE>::remove (const T &item)
+{
+ ACE_TRACE ("ACE_Fixed_Set<T, ACE_SIZE>::remove");
+
+ for (size_t i = 0, j = 0;
+ i < this->max_size_ && j < this->cur_size_;
+ ++i)
+ if (this->search_structure_[i].is_free_ == 0)
+ {
+ if (this->search_structure_[i].item_ == item)
+ {
+ // Mark this entry as being free.
+ this->search_structure_[i].is_free_ = 1;
+
+ --this->cur_size_;
+ return 0;
+ }
+ else
+ ++j;
+ }
+
+ return -1;
+}
+
+//--------------------------------------------------
+ACE_ALLOC_HOOK_DEFINE(ACE_Fixed_Set_Iterator_Base)
+
+template <class T, size_t ACE_SIZE> void
+ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::dump_i (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::dump_i");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T, size_t ACE_SIZE>
+ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::ACE_Fixed_Set_Iterator_Base (ACE_Fixed_Set<T, ACE_SIZE> &s)
+ : s_ (s),
+ next_ (-1),
+ iterated_items_ (0)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::ACE_Fixed_Set_Iterator_Base");
+ this->advance ();
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::advance (void)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::advance");
+
+ if (this->iterated_items_ < this->s_.cur_size_)
+ {
+ for (++this->next_;
+ static_cast<size_t> (this->next_) < this->s_.max_size_;
+ ++this->next_)
+ if (this->s_.search_structure_[this->next_].is_free_ == 0)
+ {
+ ++this->iterated_items_;
+ return 1;
+ }
+ }
+ else
+ ++this->next_;
+
+ return 0;
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::first (void)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::first");
+
+ next_ = -1;
+ iterated_items_ = 0;
+ return this->advance ();
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::done (void) const
+{
+ ACE_TRACE ("ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::done");
+
+ return ! (this->iterated_items_ < this->s_.cur_size_);
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::next_i (T *&item)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>::next_i");
+
+ if (static_cast<size_t> (this->next_) < this->s_.max_size_)
+ do
+ {
+ if (this->s_.search_structure_[this->next_].is_free_ == 0)
+ {
+ item = &this->s_.search_structure_[this->next_].item_;
+ this->advance ();
+ return 1;
+ }
+ }
+ while (this->advance () == 1);
+
+ return 0;
+}
+
+//--------------------------------------------------
+ACE_ALLOC_HOOK_DEFINE(ACE_Fixed_Set_Iterator)
+
+template <class T, size_t ACE_SIZE> void
+ACE_Fixed_Set_Iterator<T, ACE_SIZE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T, size_t ACE_SIZE>
+ACE_Fixed_Set_Iterator<T, ACE_SIZE>::ACE_Fixed_Set_Iterator (ACE_Fixed_Set<T, ACE_SIZE> &s)
+ : ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE> (s)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Iterator<T, ACE_SIZE>::ACE_Fixed_Set_Iterator");
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set_Iterator<T, ACE_SIZE>::next (T *&item)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Iterator<T, ACE_SIZE>::next");
+ return this->next_i (item);
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set_Iterator<T, ACE_SIZE>::remove (T *&item)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Iterator<T, ACE_SIZE>::remove");
+
+ if (this->s_.search_structure_[this->next_].is_free_ == 0)
+ {
+ item = &this->s_.search_structure_[this->next_].item_;
+ this->s_.remove (*item);
+ --(this->iterated_items_);
+ return 1;
+ }
+
+ return 0;
+}
+
+template <class T, size_t ACE_SIZE> T&
+ACE_Fixed_Set_Iterator<T, ACE_SIZE>::operator* (void)
+{
+ T *retv = 0;
+
+ if (this->s_.search_structure_[this->next_].is_free_ == 0)
+ retv = &this->s_.search_structure_[this->next_].item_;
+
+ ACE_ASSERT (retv != 0);
+
+ return *retv;
+}
+
+//--------------------------------------------------
+ACE_ALLOC_HOOK_DEFINE(ACE_Fixed_Set_Const_Iterator)
+
+template <class T, size_t ACE_SIZE> void
+ACE_Fixed_Set_Const_Iterator<T, ACE_SIZE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T, size_t ACE_SIZE>
+ACE_Fixed_Set_Const_Iterator<T, ACE_SIZE>::ACE_Fixed_Set_Const_Iterator (const ACE_Fixed_Set<T, ACE_SIZE> &s)
+ : ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE> (s)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Const_Iterator<T, ACE_SIZE>::ACE_Fixed_Set_Const_Iterator");
+}
+
+template <class T, size_t ACE_SIZE> int
+ACE_Fixed_Set_Const_Iterator<T, ACE_SIZE>::next (const T *&item)
+{
+ ACE_TRACE ("ACE_Fixed_Set_Const_Iterator<T, ACE_SIZE>::next");
+
+ return this->next_i (item);
+}
+
+template <class T, size_t ACE_SIZE> const T&
+ACE_Fixed_Set_Const_Iterator<T, ACE_SIZE>::operator* (void) const
+{
+ const T *retv = 0;
+
+ if (this->s_.search_structure_[this->next_].is_free_ == 0)
+ retv = &this->s_.search_structure_[this->next_].item_;
+
+ ACE_ASSERT (retv != 0);
+
+ return *retv;
+}
+
+//--------------------------------------------------
+ACE_ALLOC_HOOK_DEFINE(ACE_Bounded_Set)
+
+template <class T> void
+ACE_Bounded_Set<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Bounded_Set<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Bounded_Set<T>::~ACE_Bounded_Set (void)
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::~ACE_Bounded_Set");
+ delete [] this->search_structure_;
+}
+
+template <class T>
+ACE_Bounded_Set<T>::ACE_Bounded_Set (void)
+ : cur_size_ (0),
+ max_size_ (static_cast<size_t> (ACE_Bounded_Set<T>::DEFAULT_SIZE))
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::ACE_Bounded_Set");
+
+ ACE_NEW (this->search_structure_,
+ typename ACE_Bounded_Set<T>::Search_Structure[this->max_size_]);
+
+ for (size_t i = 0; i < this->max_size_; ++i)
+ this->search_structure_[i].is_free_ = 1;
+}
+
+template <class T> size_t
+ACE_Bounded_Set<T>::size (void) const
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::size");
+ return this->cur_size_;
+}
+
+template <class T>
+ACE_Bounded_Set<T>::ACE_Bounded_Set (const ACE_Bounded_Set<T> &bs)
+ : cur_size_ (bs.cur_size_),
+ max_size_ (bs.max_size_)
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::ACE_Bounded_Set");
+
+ ACE_NEW (this->search_structure_,
+ typename ACE_Bounded_Set<T>::Search_Structure[this->max_size_]);
+
+ for (size_t i = 0; i < this->cur_size_; i++)
+ this->search_structure_[i] = bs.search_structure_[i];
+}
+
+template <class T> void
+ACE_Bounded_Set<T>::operator= (const ACE_Bounded_Set<T> &bs)
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::operator=");
+
+ if (this != &bs)
+ {
+ if (this->max_size_ < bs.cur_size_)
+ {
+ delete [] this->search_structure_;
+ ACE_NEW (this->search_structure_,
+ typename ACE_Bounded_Set<T>::Search_Structure[bs.cur_size_]);
+ this->max_size_ = bs.cur_size_;
+ }
+
+ this->cur_size_ = bs.cur_size_;
+
+ for (size_t i = 0; i < this->cur_size_; i++)
+ this->search_structure_[i] = bs.search_structure_[i];
+ }
+}
+
+template <class T>
+ACE_Bounded_Set<T>::ACE_Bounded_Set (size_t size)
+ : cur_size_ (0),
+ max_size_ (size)
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::ACE_Bounded_Set");
+ ACE_NEW (this->search_structure_,
+ typename ACE_Bounded_Set<T>::Search_Structure[size]);
+
+ for (size_t i = 0; i < this->max_size_; i++)
+ this->search_structure_[i].is_free_ = 1;
+}
+
+template <class T> int
+ACE_Bounded_Set<T>::find (const T &item) const
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::find");
+
+ for (size_t i = 0; i < this->cur_size_; i++)
+ if (this->search_structure_[i].item_ == item
+ && this->search_structure_[i].is_free_ == 0)
+ return 0;
+
+ return -1;
+}
+
+template <class T> int
+ACE_Bounded_Set<T>::insert (const T &item)
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::insert");
+ int first_free = -1; // Keep track of first free slot.
+ size_t i;
+
+ for (i = 0; i < this->cur_size_; i++)
+ // First, make sure we don't allow duplicates.
+
+ if (this->search_structure_[i].item_ == item
+ && this->search_structure_[i].is_free_ == 0)
+ return 1;
+ else if (this->search_structure_[i].is_free_ && first_free == -1)
+ first_free = static_cast<int> (i);
+
+ if (first_free > -1) // If we found a free spot let's reuse it.
+ {
+ this->search_structure_[first_free].item_ = item;
+ this->search_structure_[first_free].is_free_ = 0;
+ return 0;
+ }
+ else if (i < this->max_size_) // Insert at the end of the active portion.
+ {
+ this->search_structure_[i].item_ = item;
+ this->search_structure_[i].is_free_ = 0;
+ this->cur_size_++;
+ return 0;
+ }
+ else /* No more room! */
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+}
+
+template <class T> int
+ACE_Bounded_Set<T>::remove (const T &item)
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::remove");
+ for (size_t i = 0; i < this->cur_size_; i++)
+ if (this->search_structure_[i].item_ == item)
+ {
+ // Mark this entry as being free.
+ this->search_structure_[i].is_free_ = 1;
+
+ // If we just unbound the highest entry, then we need to
+ // figure out where the next highest active entry is.
+ if (i + 1 == this->cur_size_)
+ {
+ while (i > 0 && this->search_structure_[--i].is_free_)
+ continue;
+
+ if (i == 0 && this->search_structure_[i].is_free_)
+ this->cur_size_ = 0;
+ else
+ this->cur_size_ = i + 1;
+ }
+ return 0;
+ }
+
+ return -1;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Bounded_Set_Iterator)
+
+ template <class T> void
+ACE_Bounded_Set_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Bounded_Set_Iterator<T>::ACE_Bounded_Set_Iterator (ACE_Bounded_Set<T> &s)
+ : s_ (s),
+ next_ (-1)
+{
+ ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::ACE_Bounded_Set_Iterator");
+ this->advance ();
+}
+
+template <class T> int
+ACE_Bounded_Set_Iterator<T>::advance (void)
+{
+ ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::advance");
+
+ for (++this->next_;
+ static_cast<size_t> (this->next_) < this->s_.cur_size_
+ && this->s_.search_structure_[this->next_].is_free_;
+ ++this->next_)
+ continue;
+
+ return static_cast<size_t> (this->next_) < this->s_.cur_size_;
+}
+
+template <class T> int
+ACE_Bounded_Set_Iterator<T>::first (void)
+{
+ ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::first");
+
+ next_ = -1;
+ return this->advance ();
+}
+
+template <class T> int
+ACE_Bounded_Set_Iterator<T>::done (void) const
+{
+ ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::done");
+
+ return static_cast<ACE_CAST_CONST size_t> (this->next_) >=
+ this->s_.cur_size_;
+}
+
+template <class T> int
+ACE_Bounded_Set_Iterator<T>::next (T *&item)
+{
+ ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::next");
+ if (static_cast<size_t> (this->next_) < this->s_.cur_size_)
+ {
+ item = &this->s_.search_structure_[this->next_].item_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_DNode)
+
+ template <class T>
+ACE_DNode<T>::ACE_DNode (const T &i, ACE_DNode<T> *n, ACE_DNode<T> *p)
+ : next_ (n), prev_ (p), item_ (i)
+{
+}
+
+template <class T>
+ACE_DNode<T>::~ACE_DNode (void)
+{
+}
+
+// ****************************************************************
+
+template <class T> void
+ACE_Unbounded_Stack_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Unbounded_Stack_Iterator<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Unbounded_Stack_Iterator<T>::ACE_Unbounded_Stack_Iterator (ACE_Unbounded_Stack<T> &q)
+ : current_ (q.head_->next_),
+ stack_ (q)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack_Iterator<T>::ACE_Unbounded_Stack_Iterator");
+}
+
+template <class T> int
+ACE_Unbounded_Stack_Iterator<T>::advance (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack_Iterator<T>::advance");
+ this->current_ = this->current_->next_;
+ return this->current_ != this->stack_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Stack_Iterator<T>::first (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack_Iterator<T>::first");
+ this->current_ = this->stack_.head_->next_;
+ return this->current_ != this->stack_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Stack_Iterator<T>::done (void) const
+{
+ ACE_TRACE ("ACE_Unbounded_Stack_Iterator<T>::done");
+
+ return this->current_ == this->stack_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Stack_Iterator<T>::next (T *&item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack_Iterator<T>::next");
+ if (this->current_ == this->stack_.head_)
+ return 0;
+ else
+ {
+ item = &this->current_->item_;
+ return 1;
+ }
+}
+
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Ordered_MultiSet)
+
+
+ template <class T>
+ACE_Ordered_MultiSet<T>::ACE_Ordered_MultiSet (ACE_Allocator *alloc)
+ : head_ (0)
+ , tail_ (0)
+ , cur_size_ (0)
+ , allocator_ (alloc)
+{
+ // ACE_TRACE ("ACE_Ordered_MultiSet<T>::ACE_Ordered_MultiSet");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+}
+
+template <class T>
+ACE_Ordered_MultiSet<T>::ACE_Ordered_MultiSet (const ACE_Ordered_MultiSet<T> &us)
+ : head_ (0)
+ , tail_ (0)
+ , cur_size_ (0)
+ , allocator_ (us.allocator_)
+{
+ ACE_TRACE ("ACE_Ordered_MultiSet<T>::ACE_Ordered_MultiSet");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ this->copy_nodes (us);
+}
+
+template <class T>
+ACE_Ordered_MultiSet<T>::~ACE_Ordered_MultiSet (void)
+{
+ // ACE_TRACE ("ACE_Ordered_MultiSet<T>::~ACE_Ordered_MultiSet");
+
+ this->delete_nodes ();
+}
+
+
+template <class T> void
+ACE_Ordered_MultiSet<T>::operator= (const ACE_Ordered_MultiSet<T> &us)
+{
+ ACE_TRACE ("ACE_Ordered_MultiSet<T>::operator=");
+
+ if (this != &us)
+ {
+ this->delete_nodes ();
+ this->copy_nodes (us);
+ }
+}
+
+
+template <class T> int
+ACE_Ordered_MultiSet<T>::insert (const T &item)
+{
+ // ACE_TRACE ("ACE_Ordered_MultiSet<T>::insert");
+
+ return this->insert_from (item, this->head_, 0);
+}
+
+template <class T> int
+ACE_Ordered_MultiSet<T>::insert (const T &new_item,
+ ITERATOR &iter)
+{
+ // ACE_TRACE ("ACE_Ordered_MultiSet<T>::insert using iterator");
+
+ return this->insert_from (new_item, iter.current_, &iter.current_);
+}
+
+template <class T> int
+ACE_Ordered_MultiSet<T>::remove (const T &item)
+{
+ // ACE_TRACE ("ACE_Ordered_MultiSet<T>::remove");
+
+ ACE_DNode<T> *node = 0;
+
+ int result = locate (item, 0, node);
+
+ // if we found the node, remove from list and free it
+ if (node && (result == 0))
+ {
+ if (node->prev_)
+ node->prev_->next_ = node->next_;
+ else
+ head_ = node->next_;
+
+ if (node->next_)
+ node->next_->prev_ = node->prev_;
+ else
+ tail_ = node->prev_;
+
+ --this->cur_size_;
+
+ ACE_DES_FREE_TEMPLATE (node,
+ this->allocator_->free,
+ ACE_DNode,
+ <T>);
+ return 0;
+ }
+
+ return -1;
+}
+
+template <class T> int
+ACE_Ordered_MultiSet<T>::find (const T &item,
+ ITERATOR &iter) const
+{
+ // search an occurance of item, using iterator's current position as a hint
+ ACE_DNode<T> *node = iter.current_;
+ int const result = locate (item, node, node);
+
+ // if we found the node, update the iterator and indicate success
+ if (node && (result == 0))
+ {
+ iter.current_ = node;
+ return 0;
+ }
+
+ return -1;
+}
+
+
+
+template <class T> void
+ACE_Ordered_MultiSet<T>::reset (void)
+{
+ ACE_TRACE ("reset");
+
+ this->delete_nodes ();
+}
+
+template <class T> void
+ACE_Ordered_MultiSet<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Ordered_MultiSet<T>::dump");
+ //
+ // ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_ = %u"), this->head_));
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_->next_ = %u"), this->head_->next_));
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d\n"), this->cur_size_));
+ //
+ // T *item = 0;
+ // size_t count = 1;
+ //
+ // for (ACE_Ordered_MultiSet_Iterator<T> iter (*(ACE_Ordered_MultiSet<T> *) this);
+ // iter.next (item) != 0;
+ // iter.advance ())
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("count = %d\n"), count++));
+ //
+ // ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T> int
+ACE_Ordered_MultiSet<T>::insert_from (const T &item, ACE_DNode<T> *position,
+ ACE_DNode<T> **new_position)
+{
+ // ACE_TRACE ("ACE_Ordered_MultiSet<T>::insert_from");
+
+ // create a new node
+ ACE_DNode<T> *temp = 0;
+ ACE_NEW_MALLOC_RETURN (temp,
+ static_cast<ACE_DNode<T>*> (this->allocator_->malloc (sizeof (ACE_DNode<T>))),
+ ACE_DNode<T> (item),
+ -1);
+ // obtain approximate location of the node
+ int result = locate (item, position, position);
+
+ // if there are nodes in the multiset
+ if (position)
+ {
+ switch (result)
+ {
+ // insert after the approximate position
+ case -1:
+
+ // if there is a following node
+ if (position->next_)
+ {
+ // link up with the following node
+ position->next_->prev_ = temp;
+ temp->next_ = position->next_;
+ }
+ else
+ // appending to the end of the set
+ tail_ = temp;
+
+ // link up with the preceeding node
+ temp->prev_ = position;
+ position->next_ = temp;
+
+ break;
+
+ // insert before the position
+ case 0:
+ case 1:
+
+ // if there is a preceeding node
+ if (position->prev_)
+ {
+ // link up with the preceeding node
+ position->prev_->next_ = temp;
+ temp->prev_ = position->prev_;
+ }
+ else
+ // prepending to the start of the set
+ head_ = temp;
+
+ // link up with the preceeding node
+ temp->next_ = position;
+ position->prev_ = temp;
+
+ break;
+
+ default:
+ return -1;
+ }
+ }
+ else
+ {
+ // point the head and tail to the new node.
+ this->head_ = temp;
+ this->tail_ = temp;
+ }
+
+ ++this->cur_size_;
+ if (new_position)
+ *new_position = temp;
+
+ return 0;
+}
+
+template <class T> int
+ACE_Ordered_MultiSet<T>::locate (const T &item, ACE_DNode<T> *start_position,
+ ACE_DNode<T> *&new_position) const
+{
+ if (! start_position)
+ start_position = this->head_;
+
+ // If starting before the item, move forward until at or just before
+ // item.
+ while (start_position && start_position->item_ < item &&
+ start_position->next_)
+ start_position = start_position->next_;
+
+ // If starting after the item, move back until at or just after item
+ while (start_position && item < start_position->item_ &&
+ start_position->prev_)
+ start_position = start_position->prev_;
+
+ // Save the (approximate) location in the passed pointer.
+ new_position = start_position;
+
+ // Show the location is after (1), before (-1) , or at (0) the item
+ if (!new_position)
+ return 1;
+ else if (item < new_position->item_)
+ return 1;
+ else if (new_position->item_ < item)
+ return -1;
+ else
+ return 0;
+}
+
+// Looks for first occurance of <item> in the ordered set, using the
+// passed starting position as a hint: if there is such an instance,
+// it updates the new_position pointer to point to one such node and
+// returns 0; if there is no such node, then if there is a node before
+// where the item would have been, it updates the new_position pointer
+// to point to this node and returns -1; if there is no such node,
+// then if there is a node after where the item would have been, it
+// updates the new_position pointer to point to this node (or 0 if
+// there is no such node) and returns 1;
+
+template <class T> void
+ACE_Ordered_MultiSet<T>::copy_nodes (const ACE_Ordered_MultiSet<T> &us)
+{
+ ACE_DNode<T> *insertion_point = this->head_;
+
+ for (ACE_DNode<T> *curr = us.head_;
+ curr != 0;
+ curr = curr->next_)
+ this->insert_from (curr->item_, insertion_point, &insertion_point);
+}
+
+template <class T> void
+ACE_Ordered_MultiSet<T>::delete_nodes (void)
+{
+ // iterate through list, deleting nodes
+ for (ACE_DNode<T> *curr = this->head_;
+ curr != 0;
+ )
+ {
+ ACE_DNode<T> *temp = curr;
+ curr = curr->next_;
+ ACE_DES_FREE_TEMPLATE (temp,
+ this->allocator_->free,
+ ACE_DNode,
+ <T>);
+ }
+
+ this->head_ = 0;
+ this->tail_ = 0;
+ this->cur_size_ = 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Ordered_MultiSet_Iterator)
+
+template <class T>
+ACE_Ordered_MultiSet_Iterator<T>::ACE_Ordered_MultiSet_Iterator (ACE_Ordered_MultiSet<T> &s)
+ : current_ (s.head_),
+ set_ (s)
+{
+ // ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::ACE_Ordered_MultiSet_Iterator");
+}
+
+template <class T> int
+ACE_Ordered_MultiSet_Iterator<T>::next (T *&item) const
+{
+ // ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::next");
+ if (this->current_)
+ {
+ item = &this->current_->item_;
+ return 1;
+ }
+
+ return 0;
+}
+
+template <class T> T&
+ACE_Ordered_MultiSet_Iterator<T>::operator* (void)
+{
+ //ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::operator*");
+ T *retv = 0;
+
+ int const result = this->next (retv);
+ ACE_ASSERT (result != 0);
+ ACE_UNUSED_ARG (result);
+
+ return *retv;
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_DLList_Node)
+
+template <class T> T *
+ACE_DLList<T>::insert_tail (T *new_item)
+{
+ ACE_DLList_Node *temp1 = 0;
+ ACE_NEW_MALLOC_RETURN (temp1,
+ static_cast<ACE_DLList_Node *> (this->allocator_->malloc (sizeof (ACE_DLList_Node))),
+ ACE_DLList_Node (new_item),
+ 0);
+ ACE_DLList_Node *temp2 = ACE_DLList_Base::insert_tail (temp1);
+ return (T *) (temp2 ? temp2->item_ : 0);
+}
+
+template <class T> T *
+ACE_DLList<T>::insert_head (T *new_item)
+{
+ ACE_DLList_Node *temp1 = 0;
+ ACE_NEW_MALLOC_RETURN (temp1,
+ (ACE_DLList_Node *) this->allocator_->malloc (sizeof (ACE_DLList_Node)),
+ ACE_DLList_Node (new_item), 0);
+ ACE_DLList_Node *temp2 = ACE_DLList_Base::insert_head (temp1);
+ return (T *) (temp2 ? temp2->item_ : 0);
+}
+
+template <class T> T *
+ACE_DLList<T>::delete_head (void)
+{
+ ACE_DLList_Node *temp1 = ACE_DLList_Base::delete_head ();
+ T *temp2 = (T *) (temp1 ? temp1->item_ : 0);
+ ACE_DES_FREE (temp1,
+ this->allocator_->free,
+ ACE_DLList_Node);
+
+ return temp2;
+}
+
+template <class T> T *
+ACE_DLList<T>::delete_tail (void)
+{
+ ACE_DLList_Node *temp1 = ACE_DLList_Base::delete_tail ();
+ T *temp2 = (T *) (temp1 ? temp1->item_ : 0);
+ ACE_DES_FREE (temp1,
+ this->allocator_->free,
+ ACE_DLList_Node);
+ return temp2;
+}
+
+// ****************************************************************
+
+// Compare this array with <s> for equality.
+
+template <class T> bool
+ACE_Array<T>::operator== (const ACE_Array<T> &s) const
+{
+ if (this == &s)
+ return true;
+ else if (this->size () != s.size ())
+ return false;
+
+ const size_t len = s.size ();
+ for (size_t slot = 0; slot < len; ++slot)
+ if ((*this)[slot] != s[slot])
+ return false;
+
+ return true;
+}
+
+// ****************************************************************
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_CONTAINERS_T_CPP */
diff --git a/ACE/ace/Containers_T.h b/ACE/ace/Containers_T.h
new file mode 100644
index 00000000000..fe0ec6e9cc0
--- /dev/null
+++ b/ACE/ace/Containers_T.h
@@ -0,0 +1,2024 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Containers_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CONTAINERS_T_H
+#define ACE_CONTAINERS_T_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Need by ACE_DLList_Node.
+#include "ace/Containers.h"
+
+// Shared with "ace/Unbounded_Set.h"
+#include "ace/Node.h"
+
+// Backwards compatibility, please include "ace/Array_Base.h" directly.
+#include "ace/Array_Base.h"
+
+// Backwards compatibility, please include "ace/Unbounded_Set.h" directly.
+#include "ace/Unbounded_Set.h"
+
+// Backwards compatibility, please include "ace/Unbounded_Queue.h" directly.
+#include "ace/Unbounded_Queue.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Allocator;
+
+
+/**
+ * @class ACE_Bounded_Stack
+ *
+ * @brief Implement a generic LIFO abstract data type.
+ *
+ * This implementation of a Stack uses a bounded array
+ * that is allocated dynamically. The Stack interface
+ * provides the standard constant time push, pop, and top
+ * operations.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Dynamic array
+ * - Duplicates allowed?
+ * Yes
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * N/A
+ * - Insert/replace speed
+ * N/A
+ * - Iterator still valid after change to container?
+ * N/A
+ * - Frees memory for removed elements?
+ * No
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ *
+ */
+template <class T>
+class ACE_Bounded_Stack
+{
+public:
+ // = Initialization, assignment, and termination methods.
+
+ /// Initialize a new empty stack with the provided size..
+ /**
+ * Initialize and allocate space for a new Bounded_Stack with the provided
+ * size.
+ */
+ ACE_Bounded_Stack (size_t size);
+
+ /// Initialize the stack to be a copy of the stack provided.
+ /**
+ * Initialize the stack to be an exact copy of the Bounded_Stack provided
+ * as a parameter.
+ */
+ ACE_Bounded_Stack (const ACE_Bounded_Stack<T> &s);
+
+ /// Assignment operator
+ /**
+ * Perform a deep copy operation using the Bounded_Stack parameter. If the
+ * capacity of the lhs isn't sufficient for the rhs, then the underlying data
+ * structure will be reallocated to accomadate the larger number of elements.
+ */
+ void operator= (const ACE_Bounded_Stack<T> &s);
+
+ /// Perform actions needed when stack goes out of scope.
+ /**
+ * Deallocate the memory used by the Bounded_Stack.
+ */
+ ~ACE_Bounded_Stack (void);
+
+ // = Classic Stack operations.
+
+ ///Add an element to the top of the stack.
+ /**
+ * Place a new item on top of the stack. Returns -1 if the stack
+ * is already full, 0 if the stack is not already full, and -1 if
+ * failure occurs.
+ */
+ int push (const T &new_item);
+
+ ///Remove an item from the top of stack.
+ /**
+ * Remove and return the top stack item. Returns -1 if the stack is
+ * already empty, 0 if the stack is not already empty, and -1 if
+ * failure occurs.
+ */
+ int pop (T &item);
+
+ ///Examine the contents of the top of stack.
+ /**
+ * Return top stack item without removing it. Returns -1 if the
+ * stack is already empty, 0 if the stack is not already empty, and
+ * -1 if failure occurs.
+ */
+ int top (T &item) const;
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ /**
+ * Performs constant time check to determine if the stack is empty.
+ */
+ int is_empty (void) const;
+
+ /// Returns 1 if the container is full, otherwise returns 0.
+ /**
+ * Performs constant time check to determine if the stack is at capacity.
+ */
+ int is_full (void) const;
+
+ /// The number of items in the stack.
+ /**
+ * Return the number of items currently in the stack.
+ */
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Size of the dynamically allocated data.
+ size_t size_;
+
+ /// Keeps track of the current top of stack.
+ size_t top_;
+
+ /// Holds the stack's contents.
+ T *stack_;
+};
+
+//----------------------------------------
+
+
+/**
+ * @class ACE_Fixed_Stack
+ *
+ * @brief Implement a generic LIFO abstract data type.
+ *
+ * This implementation of a Stack uses a fixed array
+ * with the size fixed at instantiation time.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Fixed array
+ * - Duplicates allowed?
+ * Yes
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * N/A
+ * - Insert/replace speed
+ * N/A
+ * - Iterator still valid after change to container?
+ * N/A
+ * - Frees memory for removed elements?
+ * No
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ *
+ */
+template <class T, size_t ACE_SIZE>
+class ACE_Fixed_Stack
+{
+public:
+ // = Initialization, assignment, and termination methods.
+ /// Initialize a new stack so that it is empty.
+ /**
+ * Initialize an empty stack.
+ */
+ ACE_Fixed_Stack (void);
+
+ /// The copy constructor (performs initialization).
+ /**
+ * Initialize the stack and copy the provided stack into the current stack.
+ */
+ ACE_Fixed_Stack (const ACE_Fixed_Stack<T, ACE_SIZE> &s);
+
+ /// Assignment operator (performs assignment).
+ /**
+ * Perform a deep copy of the provided stack.
+ */
+ void operator= (const ACE_Fixed_Stack<T, ACE_SIZE> &s);
+
+ /// Perform actions needed when stack goes out of scope.
+ /**
+ * Destroy the stack.
+ */
+ ~ACE_Fixed_Stack (void);
+
+ // = Classic Stack operations.
+
+ ///Constant time placement of element on top of stack.
+ /**
+ * Place a new item on top of the stack. Returns -1 if the stack
+ * is already full, 0 if the stack is not already full, and -1 if
+ * failure occurs.
+ */
+ int push (const T &new_item);
+
+ ///Constant time removal of top of stack.
+ /**
+ * Remove and return the top stack item. Returns -1 if the stack is
+ * already empty, 0 if the stack is not already empty, and -1 if
+ * failure occurs.
+ */
+ int pop (T &item);
+
+ ///Constant time examination of top of stack.
+ /**
+ * Return top stack item without removing it. Returns -1 if the
+ * stack is already empty, 0 if the stack is not already empty, and
+ * -1 if failure occurs.
+ */
+ int top (T &item) const;
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ /**
+ * Performs constant time check to see if stack is empty.
+ */
+ int is_empty (void) const;
+
+ /// Returns 1 if the container is full, otherwise returns 0.
+ /**
+ * Performs constant time check to see if stack is full.
+ */
+ int is_full (void) const;
+
+ /// The number of items in the stack.
+ /**
+ * Constant time access to the current size of the stack.
+ */
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Size of the allocated data.
+ size_t size_;
+
+ /// Keeps track of the current top of stack.
+ size_t top_;
+
+ /// Holds the stack's contents.
+ T stack_[ACE_SIZE];
+};
+
+//----------------------------------------
+
+template<class T> class ACE_Ordered_MultiSet;
+template<class T> class ACE_Ordered_MultiSet_Iterator;
+
+/**
+ * @class ACE_DNode
+ *
+ * @brief Implementation element in a bilinked list.
+ */
+template<class T>
+class ACE_DNode
+{
+ friend class ACE_Ordered_MultiSet<T>;
+ friend class ACE_Ordered_MultiSet_Iterator<T>;
+
+public:
+
+ /// This isn't necessary, but it keeps some compilers happy.
+ ~ACE_DNode (void);
+
+private:
+
+ // = Initialization methods
+ ACE_DNode (const T &i, ACE_DNode<T> *n = 0, ACE_DNode<T> *p = 0);
+
+ /// Pointer to next element in the list of {ACE_DNode}s.
+ ACE_DNode<T> *next_;
+
+ /// Pointer to previous element in the list of {ACE_DNode}s.
+ ACE_DNode<T> *prev_;
+
+ /// Current value of the item in this node.
+ T item_;
+};
+
+
+
+/**
+ * @class ACE_Unbounded_Stack
+ *
+ * @brief Implement a generic LIFO abstract data type.
+ *
+ * This implementation of an unbounded Stack uses a linked list.
+ * If you use the {insert} or {remove} methods you should keep
+ * in mind that duplicate entries aren't allowed. In general,
+ * therefore, you should avoid the use of these methods since
+ * they aren't really part of the ADT stack. The stack is implemented
+ * as a doubly linked list.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Double linked list
+ * - Duplicates allowed?
+ * No
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * Linear
+ * - Insert/replace speed
+ * Linear
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * Yes
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ *
+ */
+template <class T>
+class ACE_Unbounded_Stack
+{
+public:
+ friend class ACE_Unbounded_Stack_Iterator<T>;
+
+ // Trait definition.
+ typedef ACE_Unbounded_Stack_Iterator<T> ITERATOR;
+
+ // = Initialization, assignment, and termination methods.
+ /// Initialize a new stack so that it is empty. Use user defined
+ /// allocation strategy if specified.
+ /**
+ * Initialize an empty stack using the user specified allocation strategy
+ * if provided.
+ */
+ ACE_Unbounded_Stack (ACE_Allocator *the_allocator = 0);
+
+ /// The copy constructor (performs initialization).
+ /**
+ * Initialize this stack to be an exact copy of {s}.
+ */
+ ACE_Unbounded_Stack (const ACE_Unbounded_Stack<T> &s);
+
+ /// Assignment operator (performs assignment).
+ /**
+ * Perform a deep copy of the rhs into the lhs.
+ */
+ void operator= (const ACE_Unbounded_Stack<T> &s);
+
+ /// Perform actions needed when stack goes out of scope.
+ /**
+ * Destroy the underlying list for the stack.
+ */
+ ~ACE_Unbounded_Stack (void);
+
+ // = Classic Stack operations.
+
+
+ ///Push an element onto the top of stack.
+ /**
+ * Place a new item on top of the stack. Returns -1 if the stack
+ * is already full, 0 if the stack is not already full, and -1 if
+ * failure occurs.
+ */
+ int push (const T &new_item);
+
+ ///Pop the top element of the stack.
+ /**
+ * Remove and return the top stack item. Returns -1 if the stack is
+ * already empty, 0 if the stack is not already empty, and -1 if
+ * failure occurs.
+ */
+ int pop (T &item);
+
+ ///Examine the top of the stack.
+ /**
+ * Return top stack item without removing it. Returns -1 if the
+ * stack is already empty, 0 if the stack is not already empty, and
+ * -1 if failure occurs.
+ */
+ int top (T &item) const;
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ /**
+ * Constant time check to see if the stack is empty.
+ */
+ int is_empty (void) const;
+
+ /// Returns 1 if the container is full, otherwise returns 0.
+ /**
+ * Always resturns 0 since the stack is unbounded.
+ */
+ int is_full (void) const;
+
+ // = Auxiliary methods (not strictly part of the Stack ADT).
+
+ ///Linear Insert of an item.
+ /**
+ * Insert {new_item} into the Stack at the head (but doesn't allow
+ * duplicates). Returns -1 if failures occur, 1 if item is already
+ * present (i.e., no duplicates are allowed), else 0.
+ */
+ int insert (const T &new_item);
+
+ /// Remove @a item from the Stack. Returns 0 if it removes the item,
+ /// -1 if it can't find the item, and -1 if a failure occurs.
+ /**
+ * Linear remove operation.
+ */
+ int remove (const T &item);
+
+ /// Finds if @a item occurs the set. Returns 0 if finds, else -1.
+ /**
+ * Linear find operation.
+ */
+ int find (const T &item) const;
+
+ /// The number of items in the stack.
+ /**
+ * Constant time access to the current stack size.
+ */
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Delete all the nodes in the stack.
+ void delete_all_nodes (void);
+
+ /// Copy all nodes from {s} to {this}.
+ void copy_all_nodes (const ACE_Unbounded_Stack<T> &s);
+
+ /// Head of the linked list of Nodes.
+ ACE_Node<T> *head_;
+
+ /// Current size of the stack.
+ size_t cur_size_;
+
+ /// Allocation strategy of the stack.
+ ACE_Allocator *allocator_;
+};
+
+/**
+ * @class ACE_Unbounded_Stack_Iterator
+ *
+ * @brief Implement an iterator over an unbounded Stack.
+ */
+template <class T>
+class ACE_Unbounded_Stack_Iterator
+{
+public:
+ // = Initialization method.
+ /// Move to the first element in the {stack}.
+ ACE_Unbounded_Stack_Iterator (ACE_Unbounded_Stack<T> &stack);
+
+ // = Iteration methods.
+
+ /// Pass back the @a next_item that hasn't been seen in the Stack.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (T *&next_item);
+
+ /// Move forward by one element in the Stack. Returns 0 when all the
+ /// items in the Stack have been seen, else 1.
+ int advance (void);
+
+ /// Move to the first element in the Stack. Returns 0 if the
+ /// Stack is empty, else 1.
+ int first (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to the current node in the iteration.
+ ACE_Node<T> *current_;
+
+ /// Pointer to the Stack we're iterating over.
+ ACE_Unbounded_Stack<T> &stack_;
+};
+
+template <class T>
+class ACE_Double_Linked_List;
+
+/**
+ * @class ACE_Double_Linked_List_Iterator_Base
+ *
+ * @brief Implements a common base class for iterators for a double
+ * linked list ADT
+ */
+template <class T>
+class ACE_Double_Linked_List_Iterator_Base
+{
+public:
+ // = Iteration methods.
+
+ /// Passes back the {entry} under the iterator. Returns 0 if the
+ /// iteration has completed, otherwise 1
+ int next (T *&) const;
+
+ /**
+ * @deprecated Return the address of next (current) unvisited item in
+ * the list. 0 if there is no more element available.
+ */
+ T *next (void) const;
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// STL-like iterator dereference operator: returns a reference
+ /// to the node underneath the iterator.
+ T & operator* (void) const ;
+
+ /**
+ * Retasks the iterator to iterate over a new
+ * Double_Linked_List. This allows clients to reuse an iterator
+ * without incurring the constructor overhead. If you do use this,
+ * be aware that if there are more than one reference to this
+ * iterator, the other "clients" may be very bothered when their
+ * iterator changes. @@ Here be dragons. Comments?
+ */
+ void reset (ACE_Double_Linked_List<T> &);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Initialization methods.
+
+ /// Constructor
+ ACE_Double_Linked_List_Iterator_Base (const ACE_Double_Linked_List<T> &);
+
+ /// Copy constructor.
+ ACE_Double_Linked_List_Iterator_Base (const
+ ACE_Double_Linked_List_Iterator_Base<T>
+ &iter);
+
+ // = Iteration methods.
+ /**
+ * Move to the first element of the list. Returns 0 if the list is
+ * empty, else 1.
+ * @note the head of the ACE_DLList is actually a null entry, so the
+ * first element is actually the 2n'd entry
+ */
+ int go_head (void);
+
+ /// Move to the last element of the list. Returns 0 if the list is
+ /// empty, else 1.
+ int go_tail (void);
+
+ /**
+ * Check if we reach the end of the list. Can also be used to get
+ * the *current* element in the list. Return the address of the
+ * current item if there are still elements left , 0 if we run out
+ * of element.
+ */
+ T *not_done (void) const ;
+
+ /// Advance to the next element in the list. Return the address of the
+ /// next element if there are more, 0 otherwise.
+ T *do_advance (void);
+
+ /// Retreat to the previous element in the list. Return the address
+ /// of the previous element if there are more, 0 otherwise.
+ T *do_retreat (void);
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ /// Remember where we are.
+ T *current_;
+
+ const ACE_Double_Linked_List<T> *dllist_;
+};
+
+/**
+ * @class ACE_Double_Linked_List_Iterator
+ *
+ * @brief Implements an iterator for a double linked list ADT
+ *
+ * Iterate thru the double-linked list. This class provides
+ * an interface that let users access the internal element
+ * addresses directly. Notice {class T} must declare
+ * ACE_Double_Linked_List&lt;T&gt;,
+ * ACE_Double_Linked_List_Iterator_Base &lt;T&gt; and
+ * ACE_Double_Linked_List_Iterator as friend classes and class T
+ * should also have data members T* next_ and T* prev_.
+ */
+template <class T>
+class ACE_Double_Linked_List_Iterator : public ACE_Double_Linked_List_Iterator_Base <T>
+{
+public:
+ // = Initialization method.
+ ACE_Double_Linked_List_Iterator (const ACE_Double_Linked_List<T> &);
+
+ /**
+ * Retasks the iterator to iterate over a new
+ * Double_Linked_List. This allows clients to reuse an iterator
+ * without incurring the constructor overhead. If you do use this,
+ * be aware that if there are more than one reference to this
+ * iterator, the other "clients" may be very bothered when their
+ * iterator changes.
+ * @@ Here be dragons. Comments?
+ */
+ void reset (ACE_Double_Linked_List<T> &);
+
+ /// Move to the first element in the list. Returns 0 if the
+ /// list is empty, else 1.
+ int first (void);
+
+ /// Move forward by one element in the list. Returns 0 when all the
+ /// items in the list have been seen, else 1.
+ int advance (void);
+
+ /**
+ * Advance the iterator while removing the original item from the
+ * list. Return a pointer points to the original (removed) item.
+ * If {dont_remove} equals 0, this function behaves like {advance}
+ * but return 0 (NULL) instead.
+ */
+ T* advance_and_remove (int dont_remove);
+
+ // = STL-style iteration methods
+
+ /// Prefix advance.
+ ACE_Double_Linked_List_Iterator<T> & operator++ (void);
+
+ /// Postfix advance.
+ ACE_Double_Linked_List_Iterator<T> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Double_Linked_List_Iterator<T> & operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Double_Linked_List_Iterator<T> operator-- (int);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Double_Linked_List_Reverse_Iterator
+ *
+ * @brief Implements a reverse iterator for a double linked list ADT
+ *
+ * Iterate backwards over the double-linked list. This class
+ * provide an interface that let users access the internal
+ * element addresses directly, which seems to break the
+ * encapsulation. Notice {class T} must declare
+ * ACE_Double_Linked_List&lt;T&gt;,
+ * ACE_Double_Linked_List_Iterator_Base &lt;T&gt; and
+ * ACE_Double_Linked_List_Iterator as friend classes and class T
+ * should also have data members T* next_ and T* prev_.
+ */
+template <class T>
+class ACE_Double_Linked_List_Reverse_Iterator : public ACE_Double_Linked_List_Iterator_Base <T>
+{
+public:
+ // = Initialization method.
+ ACE_Double_Linked_List_Reverse_Iterator (ACE_Double_Linked_List<T> &);
+
+ /**
+ * Retasks the iterator to iterate over a new
+ * Double_Linked_List. This allows clients to reuse an iterator
+ * without incurring the constructor overhead. If you do use this,
+ * be aware that if there are more than one reference to this
+ * iterator, the other "clients" may be very bothered when their
+ * iterator changes.
+ * @@ Here be dragons. Comments?
+ */
+ void reset (ACE_Double_Linked_List<T> &);
+
+ /// Move to the first element in the list. Returns 0 if the
+ /// list is empty, else 1.
+ int first (void);
+
+ /// Move forward by one element in the list. Returns 0 when all the
+ /// items in the list have been seen, else 1.
+ int advance (void);
+
+ /**
+ * Advance the iterator while removing the original item from the
+ * list. Return a pointer points to the original (removed) item.
+ * If {dont_remove} equals 0, this function behaves like {advance}
+ * but return 0 (NULL) instead.
+ */
+ T* advance_and_remove (int dont_remove);
+
+ // = STL-style iteration methods
+
+ /// Prefix advance.
+ ACE_Double_Linked_List_Reverse_Iterator<T> & operator++ (void);
+
+ /// Postfix advance.
+ ACE_Double_Linked_List_Reverse_Iterator<T> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Double_Linked_List_Reverse_Iterator<T> & operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Double_Linked_List_Reverse_Iterator<T> operator-- (int);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+
+/**
+ * @class ACE_Double_Linked_List
+ *
+ * @brief A double-linked list implementation.
+ *
+ * This implementation of an unbounded double-linked list uses a
+ * circular linked list with a dummy node. It is pretty much
+ * like the {ACE_Unbounded_Queue} except that it allows removing
+ * of a specific element from a specific location.
+ * Notice that this class is an implementation of a very simple
+ * data structure. This is *NOT* a container class. You can use the
+ * class to implement other contains classes but it is *NOT* a
+ * general purpose container class.
+ * The parameter class *MUST* have members T* prev and T* next
+ * and users of this class are responsible to follow the general
+ * rules of using double-linked lists to maintaining the list
+ * integrity.
+ * If you need a double linked container class, use the DLList
+ * class which is a container but delegates to the Double_Linked_List
+ * class.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Double Linked List
+ * - Duplicates allowed?
+ * Yes
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * N/A
+ * - Insert/replace speed
+ * Linear
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * No
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ *
+ */
+template <class T>
+class ACE_Double_Linked_List
+{
+public:
+ friend class ACE_Double_Linked_List_Iterator_Base<T>;
+ friend class ACE_Double_Linked_List_Iterator<T>;
+ friend class ACE_Double_Linked_List_Reverse_Iterator<T>;
+
+ // Trait definition.
+ typedef ACE_Double_Linked_List_Iterator<T> ITERATOR;
+ typedef ACE_Double_Linked_List_Reverse_Iterator<T> REVERSE_ITERATOR;
+
+ // = Initialization and termination methods.
+ /// construction. Use user specified allocation strategy
+ /// if specified.
+ /**
+ * Initialize an empy list using the allocation strategy specified by the user.
+ * If none is specified, then use default allocation strategy.
+ */
+ ACE_Double_Linked_List (ACE_Allocator *the_allocator = 0);
+
+ /// Copy constructor.
+ /**
+ * Create a double linked list that is a copy of the provided
+ * parameter.
+ */
+ ACE_Double_Linked_List (const ACE_Double_Linked_List<T> &);
+
+ /// Assignment operator.
+ /**
+ * Perform a deep copy of the provided list by first deleting the nodes of the
+ * lhs and then copying the nodes of the rhs.
+ */
+ void operator= (const ACE_Double_Linked_List<T> &);
+
+ /// Destructor.
+ /**
+ * Clean up the memory allocated for the nodes of the list.
+ */
+ ~ACE_Double_Linked_List (void);
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, 0 otherwise.
+ /**
+ * Performs constant time check to determine if the list is empty.
+ */
+ int is_empty (void) const;
+
+ /// The list is unbounded, so this always returns 0.
+ /**
+ * Since the list is unbounded, the method simply returns 0.
+ */
+ int is_full (void) const;
+
+ // = Classic queue operations.
+
+ /// Adds @a new_item to the tail of the list. Returns the new item
+ /// that was inserted.
+ /**
+ * Provides constant time insertion at the end of the list structure.
+ */
+ T *insert_tail (T *new_item);
+
+ /// Adds @a new_item to the head of the list.Returns the new item that
+ /// was inserted.
+ /**
+ * Provides constant time insertion at the head of the list.
+ */
+ T *insert_head (T *new_item);
+
+ /// Removes the head of the list and returns a pointer to that item.
+ /**
+ * Removes and returns the first {item} in the list. Returns
+ * internal node's address on success, 0 if the queue was empty.
+ * This method will *not* free the internal node.
+ */
+ T* delete_head (void);
+
+ /// Removes the tail of the list and returns a pointer to that item.
+ /**
+ * Removes and returns the last {item} in the list. Returns
+ * internal nodes's address on success, 0 if the queue was
+ * empty. This method will *not* free the internal node.
+ */
+ T *delete_tail (void);
+
+ // = Additional utility methods.
+
+ ///Empty the list.
+ /**
+ * Reset the {ACE_Double_Linked_List} to be empty.
+ * Notice that since no one is interested in the items within,
+ * This operation will delete all items.
+ */
+ void reset (void);
+
+ /// Get the {slot}th element in the set. Returns -1 if the element
+ /// isn't in the range {0..{size} - 1}, else 0.
+ /**
+ * Iterates through the list to the desired index and assigns the provides pointer
+ * with the address of the node occupying that index.
+ */
+ int get (T *&item, size_t slot = 0);
+
+ /// The number of items in the queue.
+ /**
+ * Constant time call to return the current size of the list.
+ */
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Use DNode address directly.
+ /**
+ * Constant time removal of an item from the list using it's address.
+ */
+ int remove (T *n);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Delete all the nodes in the list.
+ /**
+ * Removes and deallocates memory for all of the list nodes.
+ */
+ void delete_nodes (void);
+
+ /// Copy nodes from {rhs} into this list.
+ /**
+ * Copy the elements of the provided list by allocated new nodes and assigning
+ * them with the proper data.
+ */
+ void copy_nodes (const ACE_Double_Linked_List<T> &rhs);
+
+ /// Setup header pointer. Called after we create the head node in ctor.
+ /**
+ * Initialize the head pointer so that the list has a dummy node.
+ */
+ void init_head (void);
+
+ ///Constant time insert a new item into the list structure.
+ /**
+ * Insert a @a new_item into the list. It will be added before
+ * or after @a old_item. Default is to insert the new item *after*
+ * {head_}. Return 0 if succeed, -1 if error occured.
+ */
+ int insert_element (T *new_item,
+ int before = 0,
+ T *old_item = 0);
+
+ ///Constant time delete an item from the list structure.
+ /**
+ * Remove @a item from the list. Return 0 if succeed, -1 otherwise.
+ * Notice that this function checks if item is {head_} and either its
+ * {next_} or {prev_} is NULL. The function resets item's {next_} and
+ * {prev_} to 0 to prevent clobbering the double-linked list if a user
+ * tries to remove the same node again.
+ */
+ int remove_element (T *item);
+
+ /// Head of the circular double-linked list.
+ T *head_;
+
+ /// Size of this list.
+ size_t size_;
+
+ /// Allocation Strategy of the queue.
+ ACE_Allocator *allocator_;
+};
+
+
+template <class T> class ACE_DLList;
+template <class T> class ACE_DLList_Iterator;
+template <class T> class ACE_DLList_Reverse_Iterator;
+
+typedef ACE_Double_Linked_List<ACE_DLList_Node> ACE_DLList_Base;
+
+//typedef ACE_Double_Linked_List_Iterator <ACE_DLList_Node>
+// ACE_DLList_Iterator_Base;
+//typedef ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>
+// ACE_DLList_Reverse_Iterator_Base;
+//@@ These two typedefs (inherited from James Hu's original design)
+// have been removed because Sun CC 4.2 had problems with it. I guess
+// having the DLList_Iterators inheriting from a class which is
+// actually a typedef leads to problems. #define'ing rather than
+// typedef'ing worked, but as per Carlos's reccomendation, I'm just
+// replacing all references to the base classes with their actual
+// type. Matt Braun (6/15/99)
+
+/**
+ * @class ACE_DLList
+ *
+ * @brief A double-linked list container class.
+ *
+ * This implementation uses ACE_Double_Linked_List to perform
+ * the logic behind this container class. It delegates all of its
+ * calls to ACE_Double_Linked_List.
+ */
+template <class T>
+class ACE_DLList : public ACE_DLList_Base
+{
+ friend class ACE_DLList_Node;
+ friend class ACE_Double_Linked_List_Iterator<T>;
+ friend class ACE_DLList_Iterator<T>;
+ friend class ACE_DLList_Reverse_Iterator<T>;
+
+public:
+
+ /// Delegates to ACE_Double_Linked_List.
+ void operator= (const ACE_DLList<T> &l);
+
+ // = Classic queue operations.
+
+ /// Delegates to ACE_Double_Linked_List.
+ T *insert_tail (T *new_item);
+
+ /// Delegates to ACE_Double_Linked_List.
+ T *insert_head (T *new_item);
+
+ /// Delegates to ACE_Double_Linked_List.
+ T *delete_head (void);
+
+ /// Delegates to ACE_Double_Linked_List.
+ T *delete_tail (void);
+
+ // = Additional utility methods.
+
+ /**
+ * Delegates to {ACE_Double_Linked_List}, but where
+ * {ACE_Double_Linked_List} returns the node as the item, this get
+ * returns the contents of the node in item.
+ */
+ int get (T *&item, size_t slot = 0);
+
+ /// Delegates to ACE_Double_Linked_List.
+ void dump (void) const;
+
+ /// Delegates to ACE_Double_Linked_List.
+ int remove (ACE_DLList_Node *n);
+
+ // = Initialization and termination methods.
+
+ /// Delegates to ACE_Double_Linked_List.
+ ACE_DLList (ACE_Allocator *the_allocator = 0);
+
+ /// Delegates to ACE_Double_Linked_List.
+ ACE_DLList (const ACE_DLList<T> &l);
+
+ /// Deletes the list starting from the head.
+ ~ACE_DLList (void);
+};
+
+/**
+ * @class ACE_DLList_Iterator
+ *
+ * @brief A double-linked list container class iterator.
+ *
+ * This implementation uses ACE_Double_Linked_List_Iterator to
+ * perform the logic behind this container class. It delegates
+ * all of its calls to ACE_Double_Linked_List_Iterator.
+ */
+template <class T>
+class ACE_DLList_Iterator : public ACE_Double_Linked_List_Iterator <ACE_DLList_Node>
+{
+
+ friend class ACE_DLList<T>;
+ friend class ACE_DLList_Node;
+
+public:
+
+ // = Initialization method.
+ ACE_DLList_Iterator (ACE_DLList<T> &l);
+
+ /**
+ * Retasks the iterator to iterate over a new
+ * Double_Linked_List. This allows clients to reuse an iterator
+ * without incurring the constructor overhead. If you do use this,
+ * be aware that if there are more than one reference to this
+ * iterator, the other "clients" may be very bothered when their
+ * iterator changes.
+ * @@ Here be dragons. Comments?
+ */
+ void reset (ACE_DLList<T> &l);
+
+ // = Iteration methods.
+ /// Move forward by one element in the list. Returns 0 when all the
+ /// items in the list have been seen, else 1.
+ int advance (void);
+
+ /// Pass back the {next_item} that hasn't been seen in the list.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (T *&);
+
+ /**
+ * @deprecated Delegates to ACE_Double_Linked_List_Iterator, except that
+ * whereas the Double_Linked_List version of next returns the node, this next
+ * returns the contents of the node
+ */
+ T *next (void) const;
+
+ /**
+ * Removes the current item (i.e., {next}) from the list.
+ * Note that DLList iterators do not support {advance_and_remove}
+ * directly (defined in its base class) and you will need to
+ * release the element returned by it.
+ */
+ int remove (void);
+
+ /// Delegates to ACE_Double_Linked_List_Iterator.
+ void dump (void) const;
+
+private:
+ ACE_DLList<T> *list_;
+};
+
+/**
+ * @class ACE_DLList_Reverse_Iterator
+ *
+ * @brief A double-linked list container class iterator.
+ *
+ * This implementation uses ACE_Double_Linked_List_Iterator to
+ * perform the logic behind this container class. It delegates
+ * all of its calls to ACE_Double_Linked_List_Iterator.
+ */
+template <class T>
+class ACE_DLList_Reverse_Iterator : public ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>
+{
+
+ friend class ACE_DLList<T>;
+ friend class ACE_DLList_Node;
+
+public:
+
+ // = Initialization method.
+ ACE_DLList_Reverse_Iterator (ACE_DLList<T> &l);
+
+ /**
+ * Retasks the iterator to iterate over a new
+ * Double_Linked_List. This allows clients to reuse an iterator
+ * without incurring the constructor overhead. If you do use this,
+ * be aware that if there are more than one reference to this
+ * iterator, the other "clients" may be very bothered when their
+ * iterator changes.
+ * @@ Here be dragons. Comments?
+ */
+ void reset (ACE_DLList<T> &l);
+
+ // = Iteration methods.
+ /// Move forward by one element in the list. Returns 0 when all the
+ /// items in the list have been seen, else 1.
+ int advance (void);
+
+ /// Pass back the {next_item} that hasn't been seen in the list.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (T *&);
+
+ /// @deprecated Delegates to ACE_Double_Linked_List_Iterator.
+ T *next (void) const;
+
+ /// Removes the current item (i.e., {next}) from the list.
+ /// Note that DLList iterators do not support {advance_and_remove}
+ /// directly (defined in its base class) and you will need to
+ /// release the element returned by it.
+ int remove (void);
+
+ /// Delegates to ACE_Double_Linked_List_Iterator.
+ void dump (void) const;
+
+private:
+ ACE_DLList<T> *list_;
+};
+
+// Forward declaration.
+template <class T, size_t ACE_SIZE>
+class ACE_Fixed_Set;
+
+/**
+ * @class ACE_Fixed_Set_Iterator_Base
+ *
+ * @brief Implements a common base class for iterators for a unordered set.
+ */
+template <class T, size_t ACE_SIZE>
+class ACE_Fixed_Set_Iterator_Base
+{
+public:
+ // = 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 (T *&next_item);
+
+ /// 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);
+
+ /// Move to the first element in the set. Returns 0 if the
+ /// set is empty, else 1.
+ int first (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Initialization method.
+ ACE_Fixed_Set_Iterator_Base (ACE_Fixed_Set<T, ACE_SIZE> &s);
+
+ /// Set we are iterating over.
+ ACE_Fixed_Set<T, ACE_SIZE> &s_;
+
+ /// How far we've advanced over the set.
+ ssize_t next_;
+
+ /// The number of non free items that the iterator had pointed at.
+ size_t iterated_items_;
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ /// 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_i (T *&next_item);
+};
+
+/**
+ * @class ACE_Fixed_Set_Iterator
+ *
+ * @brief Iterates through an unordered set.
+ *
+ * This implementation of an unordered set uses a fixed array.
+ * Allows deletions while iteration is occurring.
+ */
+template <class T, size_t ACE_SIZE>
+class ACE_Fixed_Set_Iterator : public ACE_Fixed_Set_Iterator_Base <T, ACE_SIZE>
+{
+public:
+ // = Initialization method.
+ ACE_Fixed_Set_Iterator (ACE_Fixed_Set<T, ACE_SIZE> &s);
+
+ // = 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 (T *&next_item);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Remove the item where the itearetor is located at.
+ /// Returns 1 if it removes a item, else 0.
+ /// Pass back the removed {item}.
+ int remove (T *&item);
+
+ /// STL-like iterator dereference operator: returns a reference
+ /// to the node underneath the iterator.
+ T & operator* (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Fixed_Set_Const_Iterator
+ *
+ * @brief Iterates through a const unordered set.
+ *
+ * This implementation of an unordered set uses a fixed array.
+ */
+template <class T, size_t ACE_SIZE>
+class ACE_Fixed_Set_Const_Iterator : public ACE_Fixed_Set_Iterator_Base <T, ACE_SIZE>
+{
+public:
+ // = Initialization method.
+ ACE_Fixed_Set_Const_Iterator (const ACE_Fixed_Set<T, ACE_SIZE> &s);
+
+ // = 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 (const T *&next_item);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// STL-like iterator dereference operator: returns a reference
+ /// to the node underneath the iterator.
+ const T & operator* (void) const ;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Fixed_Set
+ *
+ * @brief Implement a simple unordered set of {T} with maximum {ACE_SIZE}.
+ *
+ * This implementation of an unordered set uses a fixed array.
+ * It does not allow duplicate members. The set provides linear insertion/deletion
+ * operations.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Fixed array
+ * - Duplicates allowed?
+ * No
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * Linear
+ * - Insert/replace speed
+ * Linear
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * No
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator==
+ *
+ */
+template <class T, size_t ACE_SIZE>
+class ACE_Fixed_Set
+{
+public:
+ friend class ACE_Fixed_Set_Iterator_Base<T, ACE_SIZE>;
+ friend class ACE_Fixed_Set_Iterator<T, ACE_SIZE>;
+ friend class ACE_Fixed_Set_Const_Iterator<T, ACE_SIZE>;
+
+ // Trait definitions.
+ typedef ACE_Fixed_Set_Iterator<T, ACE_SIZE> ITERATOR;
+ typedef ACE_Fixed_Set_Const_Iterator<T, ACE_SIZE> CONST_ITERATOR;
+
+ // = Initialization and termination methods.
+ /// Default Constructor.
+ /**
+ * Creates an empy set
+ */
+ ACE_Fixed_Set (void);
+
+ /// Copy constructor.
+ /**
+ * Initializes a set to be a copy of the set parameter.
+ */
+ ACE_Fixed_Set (const ACE_Fixed_Set<T, ACE_SIZE> &);
+
+ /// Assignment operator.
+ /**
+ * Deep copy of one set to another.
+ */
+ void operator= (const ACE_Fixed_Set<T, ACE_SIZE> &);
+
+ /// Destructor.
+ /**
+ * Destroys a set.
+ */
+ ~ACE_Fixed_Set (void);
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ /**
+ * Performs constant time check to determine if a set is empty.
+ */
+ int is_empty (void) const;
+
+ /// Returns 1 if the container is full, otherwise returns 0.
+ /**
+ * Performs a constant time check to see if the set is full.
+ */
+ int is_full (void) const;
+
+ // = Classic unordered set operations.
+
+ ///Linear time insertion of an item unique to the set.
+ /**
+ * Insert @a new_item into the set (doesn't allow duplicates).
+ * Returns -1 if failures occur, 1 if item is already present, else
+ * 0.
+ */
+ int insert (const T &new_item);
+
+ ///Linear time removal operation of an item.
+ /**
+ * Remove first occurrence of {item} from the set. Returns 0 if
+ * it removes the item, -1 if it can't find the item, and -1 if a
+ * failure occurs. Removal doesn't reclaim memory for the @a item.
+ */
+ int remove (const T &item);
+
+ /// Finds if @a item occurs in the set. Returns 0 if finds, else -1.
+ /**
+ * Performs a linear find operation for the specified @a item.
+ */
+ int find (const T &item) const;
+
+ /// Size of the set.
+ /**
+ * Returns the current size of the set.
+ */
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Holds the contents of the set.
+ struct
+ {
+ /// Item in the set.
+ T item_;
+
+ /// Keeps track of whether this item is in use or not.
+ int is_free_;
+ } search_structure_[ACE_SIZE];
+
+ /// Current size of the set.
+ size_t cur_size_;
+
+ /// Maximum size of the set.
+ size_t max_size_;
+};
+
+// Forward declaration.
+template <class T>
+class ACE_Bounded_Set;
+
+/**
+ * @class ACE_Bounded_Set_Iterator
+ *
+ * @brief Iterates through an unordered set.
+ *
+ * This implementation of an unordered set uses a Bounded array.
+ * Allows deletions while iteration is occurring.
+ */
+template <class T>
+class ACE_Bounded_Set_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Bounded_Set_Iterator (ACE_Bounded_Set<T> &s);
+
+ // = 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 (T *&next_item);
+
+ /// 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);
+
+ /// Move to the first element in the set. Returns 0 if the
+ /// set is empty, else 1.
+ int first (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Set we are iterating over.
+ ACE_Bounded_Set<T> &s_;
+
+ /// How far we've advanced over the set.
+ ssize_t next_;
+};
+
+
+/**
+ * @class ACE_Bounded_Set
+ *
+ * @brief Implement a simple unordered set of {T} with maximum
+ * set at creation time.
+ *
+ * This implementation of an unordered set uses a Bounded array.
+ * This implementation does not allow duplicates. It provides
+ * linear insert/remove/find operations. Insertion/removal does not
+ * invalidate iterators, but caution should be taken to ensure
+ * expected behavior. Once initialized, the object has a maximum size
+ * which can only be increased by the assignment of another larger Bounded_Set.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Bounded array which can grow via assignment
+ * - Duplicates allowed?
+ * No
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * Linear
+ * - Insert/replace speed
+ * Linear
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * No
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator==
+ *
+ */
+template <class T>
+class ACE_Bounded_Set
+{
+public:
+ friend class ACE_Bounded_Set_Iterator<T>;
+
+ // Trait definition.
+ typedef ACE_Bounded_Set_Iterator<T> ITERATOR;
+
+ enum
+ {
+ DEFAULT_SIZE = 10
+ };
+
+ // = Initialization and termination methods.
+ /// Construct a Bounded_Set using the default size.
+ /**
+ * The default constructor initializes the Bounded_Set to a maximum size
+ * specified by the DEFAULT_SIZE.
+ */
+ ACE_Bounded_Set (void);
+
+ /// Construct a Bounded_Set with the provided sizeB.
+ /**
+ * Initialize the Bounded_Set to have a maximum size equal to the size
+ * parameter specified.
+ */
+ ACE_Bounded_Set (size_t size);
+
+ /// Construct a Bounded_Set that is a copy of the provides Bounded_Set.
+ /**
+ * Initialize the Bounded_Set to be a copy of the Bounded_Set parameter.
+ */
+ ACE_Bounded_Set (const ACE_Bounded_Set<T> &);
+
+ /// Assignment operator.
+ /**
+ * The assignment will make a deep copy of the Bounded_Set provided. If the
+ * rhs has more elements than the capacity of the lhs, then the lhs will be
+ * deleted and reallocated to accomadate the larger number of elements.
+ */
+ void operator= (const ACE_Bounded_Set<T> &);
+
+ /// Destructor
+ /**
+ * Clean up the underlying dynamically allocated memory that is used by
+ * the Bounded_Set.
+ */
+ ~ACE_Bounded_Set (void);
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ /**
+ * A constant time check is performed to determine if the Bounded_Set is
+ * empty.
+ */
+ int is_empty (void) const;
+
+ /// Returns 1 if the container is full, otherwise returns 0.
+ /**
+ * Performs a constant time check to determine if the Bounded_Set is at
+ * capacity.
+ */
+ int is_full (void) const;
+
+ // = Classic unordered set operations.
+
+ ///Inserts a new element unique to the set.
+ /**
+ * Insert @a new_item into the set (doesn't allow duplicates) in linear
+ * time.
+ * Returns -1 if failures occur, 1 if item is already present, else
+ * 0.
+ */
+ int insert (const T &new_item);
+
+ ///Finds the specified element and removes it from the set.
+ /**
+ * Remove first occurrence of @a item from the set. Returns 0 if it
+ * removes the item, -1 if it can't find the item, and -1 if a
+ * failure occurs. The linear remove operation does not reclaim the
+ * memory associated with the removed item.
+ */
+ int remove (const T &item);
+
+ /// Finds if @a item occurs in the set. Returns 0 if finds, else -1.
+ /**
+ * find preforms a linear search for {item} and returns 0 on successful
+ * find and -1 otherwise.
+ */
+ int find (const T &item) const;
+
+ /// Size of the set.
+ /**
+ * Returns a size_t representing the current size of the set.
+ */
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ struct Search_Structure
+ {
+ /// Item in the set.
+ T item_;
+
+ /// Keeps track of whether this item is in use or not.
+ int is_free_;
+ };
+
+ /// Holds the contents of the set.
+ Search_Structure *search_structure_;
+
+ /// Current size of the set.
+ size_t cur_size_;
+
+ /// Maximum size of the set.
+ size_t max_size_;
+};
+
+/**
+ * @class ACE_Ordered_MultiSet_Iterator
+ *
+ * @brief Implement a bidirectional iterator over an ordered multiset.
+ * This class template requires that < operator semantics be
+ * defined for the parameterized type {T}, but does not impose
+ * any restriction on how that ordering operator is implemented.
+ */
+template <class T>
+class ACE_Ordered_MultiSet_Iterator
+{
+public:
+ friend class ACE_Ordered_MultiSet<T>;
+
+ // = Initialization method.
+ ACE_Ordered_MultiSet_Iterator (ACE_Ordered_MultiSet<T> &s);
+
+ // = Iteration methods.
+
+ /// Pass back the {next_item} that hasn't been seen in the ordered multiset.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (T *&next_item) const;
+
+ /// Repositions the iterator at the first item in the ordered multiset
+ /// Returns 0 if the list is empty else 1.
+ int first (void);
+
+ /// Repositions the iterator at the last item in the ordered multiset
+ /// Returns 0 if the list is empty else 1.
+ int last (void);
+
+ /// 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);
+
+ /// Move backward by one element in the set. Returns 0 when all the
+ /// items in the set have been seen, else 1.
+ int retreat (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Returns a reference to the internal element {this} is pointing to.
+ T& operator* (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /// Pointer to the current node in the iteration.
+ ACE_DNode<T> *current_;
+
+ /// Pointer to the set we're iterating over.
+ ACE_Ordered_MultiSet<T> &set_;
+};
+
+
+/**
+ * @class ACE_Ordered_MultiSet
+ *
+ * @brief Implement a simple ordered multiset of {T} of unbounded size
+ * that allows duplicates. This class template requires that <
+ * operator semantics be defined for the parameterized type {T}, but
+ * does not impose any restriction on how that ordering operator is
+ * implemented. The set is implemented as a linked list.
+ *
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Double linked list
+ * - Duplicates allowed?
+ * Yes
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * Linear
+ * - Insert/replace speed
+ * Linear
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * Yes
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator==
+ * -# operator<
+ *
+ *
+ */
+template <class T>
+class ACE_Ordered_MultiSet
+{
+public:
+ friend class ACE_Ordered_MultiSet_Iterator<T>;
+
+ // Trait definition.
+ typedef ACE_Ordered_MultiSet_Iterator<T> ITERATOR;
+
+ // = Initialization and termination methods.
+ /// Constructor. Use user specified allocation strategy
+ /// if specified.
+ /**
+ * Initialize the set using the allocation strategy specified. If none, use the
+ * default strategy.
+ */
+ ACE_Ordered_MultiSet (ACE_Allocator *the_allocator = 0);
+
+ /// Copy constructor.
+ /**
+ * Initialize the set to be a copy of the provided set.
+ */
+ ACE_Ordered_MultiSet (const ACE_Ordered_MultiSet<T> &);
+
+ /// Destructor.
+ /**
+ * Delete the nodes of the set.
+ */
+ ~ACE_Ordered_MultiSet (void);
+
+ /// Assignment operator.
+ /**
+ * Delete the nodes in lhs, and copy the nodes from the rhs.
+ */
+ void operator= (const ACE_Ordered_MultiSet<T> &);
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ /**
+ * Constant time check to determine if the set is empty.
+ */
+ int is_empty (void) const;
+
+ /// Size of the set.
+ /**
+ * Constant time check to determine the size of the set.
+ */
+ size_t size (void) const;
+
+ // = Classic unordered set operations.
+
+ /// Insert @a new_item into the ordered multiset.
+ /// Returns -1 if failures occur, else 0.
+ /**
+ * Linear time, order preserving insert into the set beginning at the head.
+ */
+ int insert (const T &new_item);
+
+ ///Linear time insert beginning at the point specified by the provided iterator.
+ /**
+ * Insert @a new_item into the ordered multiset, starting its search at
+ * the node pointed to by the iterator, and if insertion was successful,
+ * updates the iterator to point to the newly inserted node.
+ * Returns -1 if failures occur, else 0.
+ */
+ int insert (const T &new_item, ITERATOR &iter);
+
+ /// Remove first occurrence of @a item from the set. Returns 0 if
+ /// it removes the item, -1 if it can't find the item.
+ /**
+ * Linear time search operation which removes the item from the set if found .
+ */
+ int remove (const T &item);
+
+ ///Linear find operation.
+ /**
+ * Finds first occurrence of @a item in the multiset, using the iterator's
+ * current position as a hint to improve performance. If find succeeds,
+ * it positions the iterator at that node and returns 0, or if it cannot
+ * locate the node, it leaves the iterator alone and just returns -1.
+ */
+ int find (const T &item, ITERATOR &iter) const;
+
+ /// Reset the ACE_Ordered_MultiSet to be empty.
+ /**
+ * Delete the nodes inside the set.
+ */
+ void reset (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /**
+ * Insert @a item, starting its search at the position given,
+ * and if successful updates the passed pointer to point to
+ * the newly inserted item's node.
+ */
+ int insert_from (const T &item, ACE_DNode<T> *start_position,
+ ACE_DNode<T> **new_position);
+
+ /**
+ * Looks for first occurance of @a item in the ordered set, using the
+ * passed starting position as a hint: if there is such an instance, it
+ * updates the new_position pointer to point to this node and returns 0;
+ * if there is no such node, then if there is a node before where the
+ * item would have been, it updates the new_position pointer to point
+ * to this node and returns -1; if there is no such node, then if there
+ * is a node after where the item would have been, it updates the
+ * new_position pointer to point to this node (or 0 if there is no such
+ * node) and returns 1;
+ */
+ int locate (const T &item, ACE_DNode<T> *start_position,
+ ACE_DNode<T> *&new_position) const;
+
+ /// Delete all the nodes in the Set.
+ void delete_nodes (void);
+
+ /// Copy nodes into this set.
+ void copy_nodes (const ACE_Ordered_MultiSet<T> &);
+
+ /// Head of the bilinked list of Nodes.
+ ACE_DNode<T> *head_;
+
+ /// Head of the bilinked list of Nodes.
+ ACE_DNode<T> *tail_;
+
+ /// Current size of the set.
+ size_t cur_size_;
+
+ /// Allocation strategy of the set.
+ ACE_Allocator *allocator_;
+};
+
+// ****************************************************************
+
+/**
+ * @class ACE_Array
+ *
+ * @brief A dynamic array class.
+ *
+ * This class extends ACE_Array_Base, adding comparison operators.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Dynamic array
+ * - Duplicates allowed?
+ * Yes
+ * - Random access allowed?
+ * Yes
+ * - Search speed
+ * N/A
+ * - Insert/replace speed
+ * O(1)
+ * - Iterator still valid after change to container?
+ * - In general, yes.
+ * - If array size is changed during iteration, no.
+ * - Frees memory for removed elements?
+ * No
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator!=
+ *
+ * @sa ACE_Array_Base. This class inherits its operations and requirements.
+ */
+template <class T>
+class ACE_Array : public ACE_Array_Base<T>
+{
+public:
+ // Define a "trait"
+ typedef T TYPE;
+
+ typedef ACE_Array_Iterator<T> ITERATOR;
+
+ // = Exceptions.
+
+ // = Initialization and termination methods.
+
+ /// Dynamically create an uninitialized array.
+ /**
+ * Initialize an empty array of the specified size using the provided
+ * allocation strategy.
+ */
+ ACE_Array (size_t size = 0,
+ ACE_Allocator* alloc = 0);
+
+ /// Dynamically initialize the entire array to the {default_value}.
+ /**
+ * Initialize an array the given size placing the default_value in each index.
+ */
+ ACE_Array (size_t size,
+ const T &default_value,
+ ACE_Allocator* alloc = 0);
+
+ ///Copy constructor.
+ /**
+ * The copy constructor performs initialization by making an exact
+ * copy of the contents of parameter {s}, i.e., *this == s will
+ * return true.
+ */
+ ACE_Array (const ACE_Array<T> &s);
+
+ ///Assignment operator
+ /**
+ * Assignment operator performs an assignment by making an exact
+ * copy of the contents of parameter {s}, i.e., *this == s will
+ * return true. Note that if the {max_size_} of {array_} is >= than
+ * {s.max_size_} we can copy it without reallocating. However, if
+ * {max_size_} is < {s.max_size_} we must delete the {array_},
+ * reallocate a new {array_}, and then copy the contents of {s}.
+ */
+ void operator= (const ACE_Array<T> &s);
+
+ // = Compare operators
+
+ ///Equality comparison operator.
+ /**
+ * Compare this array with {s} for equality. Two arrays are equal
+ * if their {size}'s are equal and all the elements from 0 .. {size}
+ * are equal.
+ */
+ bool operator== (const ACE_Array<T> &s) const;
+
+ ///Inequality comparison operator.
+ /**
+ * Compare this array with {s} for inequality such that {*this} !=
+ * {s} is always the complement of the boolean return value of
+ * {*this} == {s}.
+ */
+ bool operator!= (const ACE_Array<T> &s) const;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Containers_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Containers_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Containers_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONTAINERS_T_H */
diff --git a/ACE/ace/Containers_T.inl b/ACE/ace/Containers_T.inl
new file mode 100644
index 00000000000..425d6e167e8
--- /dev/null
+++ b/ACE/ace/Containers_T.inl
@@ -0,0 +1,479 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> ACE_INLINE int
+ACE_Bounded_Stack<T>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Bounded_Stack<T>::is_empty");
+ return this->top_ == 0;
+}
+
+template <class T> ACE_INLINE int
+ACE_Bounded_Stack<T>::is_full (void) const
+{
+ ACE_TRACE ("ACE_Bounded_Stack<T>::is_full");
+ return this->top_ >= this->size_;
+}
+
+template <class T> ACE_INLINE int
+ACE_Bounded_Stack<T>::push (const T &new_item)
+{
+ ACE_TRACE ("ACE_Bounded_Stack<T>::push");
+ if (this->is_full () == 0)
+ {
+ this->stack_[this->top_++] = new_item;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <class T> ACE_INLINE int
+ACE_Bounded_Stack<T>::pop (T &item)
+{
+ ACE_TRACE ("ACE_Bounded_Stack<T>::pop");
+ if (this->is_empty () == 0)
+ {
+ item = this->stack_[--this->top_];
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <class T> ACE_INLINE int
+ACE_Bounded_Stack<T>::top (T &item) const
+{
+ ACE_TRACE ("ACE_Bounded_Stack<T>::top");
+ if (this->is_empty () == 0)
+ {
+ item = this->stack_[this->top_ - 1];
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <class T> ACE_INLINE size_t
+ACE_Bounded_Stack<T>::size (void) const
+{
+ return this->size_;
+}
+
+//----------------------------------------
+
+template <class T, size_t ACE_SIZE> ACE_INLINE int
+ACE_Fixed_Stack<T, ACE_SIZE>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::is_empty");
+ return this->top_ == 0;
+}
+
+template <class T, size_t ACE_SIZE> ACE_INLINE int
+ACE_Fixed_Stack<T, ACE_SIZE>::is_full (void) const
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::is_full");
+ return this->top_ >= this->size_;
+}
+
+template <class T, size_t ACE_SIZE> ACE_INLINE int
+ACE_Fixed_Stack<T, ACE_SIZE>::push (const T &new_item)
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::push");
+ if (this->is_full () == 0)
+ {
+ this->stack_[this->top_++] = new_item;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <class T, size_t ACE_SIZE> ACE_INLINE int
+ACE_Fixed_Stack<T, ACE_SIZE>::pop (T &item)
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::pop");
+ if (this->is_empty () == 0)
+ {
+ item = this->stack_[--this->top_];
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <class T, size_t ACE_SIZE> ACE_INLINE int
+ACE_Fixed_Stack<T, ACE_SIZE>::top (T &item) const
+{
+ ACE_TRACE ("ACE_Fixed_Stack<T, ACE_SIZE>::top");
+ if (this->is_empty () == 0)
+ {
+ item = this->stack_[this->top_ - 1];
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <class T, size_t ACE_SIZE> ACE_INLINE size_t
+ACE_Fixed_Stack<T, ACE_SIZE>::size (void) const
+{
+ return this->size_;
+}
+
+template <class T> ACE_INLINE int
+ACE_Unbounded_Stack<T>::is_empty (void) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Stack<T>::is_empty");
+ return this->head_ == this->head_->next_;
+}
+
+template <class T> ACE_INLINE int
+ACE_Unbounded_Stack<T>::top (T &item) const
+{
+ ACE_TRACE ("ACE_Unbounded_Stack<T>::top");
+ if (this->is_empty () == 0)
+ {
+ item = this->head_->next_->item_;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <class T> ACE_INLINE int
+ACE_Unbounded_Stack<T>::is_full (void) const
+{
+ ACE_TRACE ("ACE_Unbounded_Stack<T>::is_full");
+ return 0; // ???
+}
+
+template <class T> ACE_INLINE size_t
+ACE_Unbounded_Stack<T>::size (void) const
+{
+ return this->cur_size_;
+}
+
+// ---
+
+
+// ---
+
+template <class T, size_t ACE_SIZE> ACE_INLINE int
+ACE_Fixed_Set<T, ACE_SIZE>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Fixed_Set<T>::is_empty");
+ return this->cur_size_ == 0;
+}
+
+template <class T, size_t ACE_SIZE> ACE_INLINE int
+ACE_Fixed_Set<T, ACE_SIZE>::is_full (void) const
+{
+ ACE_TRACE ("ACE_Fixed_Set<T, ACE_SIZE>::is_full");
+ return this->cur_size_ == this->max_size_;
+}
+
+// ---
+
+template <class T> ACE_INLINE int
+ACE_Bounded_Set<T>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::is_empty");
+ return this->cur_size_ == 0;
+}
+
+template <class T> ACE_INLINE int
+ACE_Bounded_Set<T>::is_full (void) const
+{
+ ACE_TRACE ("ACE_Bounded_Set<T>::is_full");
+ return this->cur_size_ == this->max_size_;
+}
+
+// --
+
+template <class T> ACE_INLINE int
+ACE_Ordered_MultiSet_Iterator<T>::first (void)
+{
+ ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::first");
+ current_ = set_.head_;
+
+ return (current_ ? 1 : 0);
+}
+
+template <class T> ACE_INLINE int
+ACE_Ordered_MultiSet_Iterator<T>::last (void)
+{
+ ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::last");
+ current_ = set_.tail_;
+
+ return (current_ ? 1 : 0);
+}
+
+template <class T> ACE_INLINE int
+ACE_Ordered_MultiSet_Iterator<T>::advance (void)
+{
+ ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::advance");
+
+ current_ = current_ ? current_->next_ : 0;
+
+ return (current_ ? 1 : 0);
+}
+
+template <class T> ACE_INLINE int
+ACE_Ordered_MultiSet_Iterator<T>::retreat (void)
+{
+ ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::retreat");
+
+ current_ = current_ ? current_->prev_ : 0;
+
+ return (current_ ? 1 : 0);
+}
+
+template <class T> ACE_INLINE int
+ACE_Ordered_MultiSet_Iterator<T>::done (void) const
+{
+ ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::done");
+
+ return (current_ ? 0 : 1);
+}
+
+template <class T> ACE_INLINE void
+ACE_Ordered_MultiSet_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Ordered_MultiSet_Iterator<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+
+
+// --
+
+template <class T> ACE_INLINE int
+ACE_Ordered_MultiSet<T>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Ordered_MultiSet<T>::is_empty");
+ return this->cur_size_ > 0 ? 0 : 1;
+}
+
+template <class T> ACE_INLINE size_t
+ACE_Ordered_MultiSet<T>::size (void) const
+{
+// ACE_TRACE ("ACE_Ordered_MultiSet<T>::size");
+ return this->cur_size_;
+}
+
+// ****************************************************************
+
+template <class T> ACE_INLINE
+ACE_Array<T>::ACE_Array (size_t size,
+ ACE_Allocator *alloc)
+ : ACE_Array_Base<T> (size, alloc)
+{
+}
+
+template <class T> ACE_INLINE
+ACE_Array<T>::ACE_Array (size_t size,
+ const T &default_value,
+ ACE_Allocator *alloc)
+ : ACE_Array_Base<T> (size, default_value, alloc)
+{
+}
+
+// The copy constructor (performs initialization).
+
+template <class T> ACE_INLINE
+ACE_Array<T>::ACE_Array (const ACE_Array<T> &s)
+ : ACE_Array_Base<T> (s)
+{
+}
+
+// Assignment operator (performs assignment).
+
+template <class T> ACE_INLINE void
+ACE_Array<T>::operator= (const ACE_Array<T> &s)
+{
+ // Check for "self-assignment".
+
+ if (this != &s)
+ this->ACE_Array_Base<T>::operator= (s);
+}
+
+// Compare this array with <s> for inequality.
+
+template <class T> ACE_INLINE bool
+ACE_Array<T>::operator!= (const ACE_Array<T> &s) const
+{
+ return !(*this == s);
+}
+
+// ****************************************************************
+
+
+// ****************************************************************
+
+template <class T> ACE_INLINE void
+ACE_DLList<T>::operator= (const ACE_DLList<T> &l)
+{
+ *(ACE_DLList_Base *) this = l;
+}
+
+template <class T> ACE_INLINE int
+ACE_DLList<T>::get (T *&item, size_t index)
+{
+ ACE_DLList_Node *node;
+ int result = ACE_DLList_Base::get (node, index);
+ if (result != -1)
+ item = (T *) node->item_;
+ return result;
+}
+
+template <class T> ACE_INLINE void
+ACE_DLList<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DLList_Base::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T> ACE_INLINE int
+ACE_DLList<T>::remove (ACE_DLList_Node *n)
+{
+ int result = ACE_DLList_Base::remove (n);
+ ACE_DES_FREE (n,
+ this->allocator_->free,
+ ACE_DLList_Node);
+ return result;
+}
+
+template <class T> ACE_INLINE
+ACE_DLList<T>::ACE_DLList (ACE_Allocator *alloc)
+ : ACE_DLList_Base (alloc)
+{
+}
+
+template <class T> ACE_INLINE
+ACE_DLList<T>::ACE_DLList (const ACE_DLList<T> &l)
+ : ACE_DLList_Base ((ACE_DLList<T> &) l)
+{
+}
+
+template <class T> ACE_INLINE
+ACE_DLList<T>::~ACE_DLList (void)
+{
+ while (this->delete_head ()) ;
+}
+
+template <class T> ACE_INLINE int
+ACE_DLList_Iterator<T>::remove (void)
+{
+ ACE_DLList_Node *temp = this->ACE_Double_Linked_List_Iterator <ACE_DLList_Node>::next ();
+ this->ACE_Double_Linked_List_Iterator <ACE_DLList_Node>::advance ();
+ return list_->remove (temp);
+}
+
+template <class T> ACE_INLINE
+ACE_DLList_Iterator<T>::ACE_DLList_Iterator (ACE_DLList<T> &l)
+ : ACE_Double_Linked_List_Iterator <ACE_DLList_Node> ((ACE_DLList_Base &)l),
+ list_ (&l)
+{
+}
+
+template <class T> ACE_INLINE void
+ACE_DLList_Iterator<T>::reset (ACE_DLList<T> &l)
+{
+ list_ = &l;
+ this->ACE_Double_Linked_List_Iterator <ACE_DLList_Node>::reset ((ACE_DLList_Base &)l);
+}
+
+template <class T> ACE_INLINE int
+ACE_DLList_Iterator<T>::next (T *&ptr)
+{
+ ACE_DLList_Node *temp =
+ ACE_Double_Linked_List_Iterator <ACE_DLList_Node>::next ();
+ if (temp)
+ ptr = (T *) temp->item_;
+ return temp ? 1 : 0;
+}
+
+template <class T> ACE_INLINE T *
+ACE_DLList_Iterator<T>::next (void) const
+{
+ ACE_DLList_Node *temp = ACE_Double_Linked_List_Iterator <ACE_DLList_Node>::next ();
+ return (T *) (temp ? temp->item_ : 0);
+}
+
+template <class T> ACE_INLINE int
+ACE_DLList_Iterator<T>::advance (void)
+{
+ return this->ACE_Double_Linked_List_Iterator <ACE_DLList_Node>::advance ();
+}
+
+template <class T> ACE_INLINE void
+ACE_DLList_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_Double_Linked_List_Iterator <ACE_DLList_Node>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+
+template <class T> ACE_INLINE int
+ACE_DLList_Reverse_Iterator<T>::remove (void)
+{
+ ACE_DLList_Node *temp = ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>::next ();
+ this->ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>::advance ();
+ return list_->remove (temp);
+}
+
+template <class T> ACE_INLINE
+ACE_DLList_Reverse_Iterator<T>::ACE_DLList_Reverse_Iterator (ACE_DLList<T> &l)
+ : ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node> ((ACE_DLList_Base &)l),
+ list_ (&l)
+{
+}
+
+template <class T> ACE_INLINE void
+ACE_DLList_Reverse_Iterator<T>::reset (ACE_DLList<T> &l)
+{
+ list_ = &l;
+ this->ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>::reset ((ACE_DLList_Base &)l);
+}
+
+template <class T> ACE_INLINE int
+ACE_DLList_Reverse_Iterator<T>::advance (void)
+{
+ return ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>::advance ();
+}
+
+template <class T> ACE_INLINE int
+ACE_DLList_Reverse_Iterator<T>::next (T *&ptr)
+{
+ ACE_DLList_Node *temp =
+ ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>::next ();
+ if (temp == 0)
+ return 0;
+ ptr = (T *) temp->item_;
+ return 1;
+}
+
+template <class T> ACE_INLINE T *
+ACE_DLList_Reverse_Iterator<T>::next (void) const
+{
+ ACE_DLList_Node *temp = ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>::next ();
+ return (T *) (temp ? temp->item_ : 0);
+}
+
+
+template <class T> ACE_INLINE void
+ACE_DLList_Reverse_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_Double_Linked_List_Reverse_Iterator <ACE_DLList_Node>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Copy_Disabled.cpp b/ACE/ace/Copy_Disabled.cpp
new file mode 100644
index 00000000000..d2fb124a182
--- /dev/null
+++ b/ACE/ace/Copy_Disabled.cpp
@@ -0,0 +1,23 @@
+/**
+ * @file Copy_Disabled.cpp
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+
+#include "ace/Copy_Disabled.h"
+
+
+ACE_RCSID (ace,
+ Copy_Disabled,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Copy_Disabled::ACE_Copy_Disabled (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Copy_Disabled.h b/ACE/ace/Copy_Disabled.h
new file mode 100644
index 00000000000..835b3c20f91
--- /dev/null
+++ b/ACE/ace/Copy_Disabled.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+//===========================================================================
+/**
+ * @file Copy_Disabled.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//===========================================================================
+
+#ifndef ACE_COPY_DISABLED_H
+#define ACE_COPY_DISABLED_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Copy_Disabled
+ *
+ * @brief Helper class to disable copy construction and assignment
+ *
+ * Classes used to control OS and other resources are not "canonical",
+ * i.e. they have their copy constructor and assignment operators
+ * disabled.
+ * This is often done by making the copy constructor and assignment
+ * operators private, effectively disallowing copying by clients of
+ * the class (including derived classes). If the copy constructor and
+ * assingment operators are left unimplemented then the class itself
+ * cannot make any copies of its instances, because it would result in
+ * link errors.
+ *
+ * To use this class simply use private inheritance:
+ *
+ * class Foo : private ACE_Copy_Disabled
+ * {
+ * // code here
+ * };
+ *
+ */
+class ACE_Export ACE_Copy_Disabled
+{
+public:
+
+ /// Default constructor
+ ACE_Copy_Disabled (void);
+
+private:
+ ACE_Copy_Disabled (const ACE_Copy_Disabled &);
+ ACE_Copy_Disabled &operator= (const ACE_Copy_Disabled &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_COPY_DISABLED_H */
diff --git a/ACE/ace/Countdown_Time.cpp b/ACE/ace/Countdown_Time.cpp
new file mode 100644
index 00000000000..4c95e2acfa1
--- /dev/null
+++ b/ACE/ace/Countdown_Time.cpp
@@ -0,0 +1,66 @@
+#include "ace/Countdown_Time.h"
+#include "ace/OS_NS_sys_time.h"
+
+ACE_RCSID (ace,
+ Countdown_Time,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Countdown_Time::ACE_Countdown_Time (ACE_Time_Value *max_wait_time)
+ : max_wait_time_ (max_wait_time),
+ stopped_ (false)
+{
+ this->start ();
+}
+
+ACE_Countdown_Time::~ACE_Countdown_Time (void)
+{
+ this->stop ();
+}
+
+void
+ACE_Countdown_Time::start (void)
+{
+ if (this->max_wait_time_ != 0)
+ {
+ this->start_time_ = ACE_OS::gettimeofday ();
+ this->stopped_ = false;
+ }
+}
+
+bool
+ACE_Countdown_Time::stopped (void) const
+{
+ return stopped_;
+}
+
+void
+ACE_Countdown_Time::stop (void)
+{
+ if (this->max_wait_time_ != 0 && this->stopped_ == false)
+ {
+ ACE_Time_Value elapsed_time = ACE_OS::gettimeofday () - this->start_time_;
+
+ if (*this->max_wait_time_ > elapsed_time)
+ {
+ *this->max_wait_time_ -= elapsed_time;
+ }
+ else
+ {
+ // Used all of timeout.
+ *this->max_wait_time_ = ACE_Time_Value::zero;
+ // errno = ETIME;
+ }
+ this->stopped_ = true;
+ }
+}
+
+void
+ACE_Countdown_Time::update (void)
+{
+ this->stop ();
+ this->start ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Countdown_Time.h b/ACE/ace/Countdown_Time.h
new file mode 100644
index 00000000000..207b9045fcc
--- /dev/null
+++ b/ACE/ace/Countdown_Time.h
@@ -0,0 +1,80 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Countdown_Time.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_COUNTDOWN_TIME_H
+#define ACE_COUNTDOWN_TIME_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Countdown_Time
+ *
+ * @brief Keeps track of the amount of elapsed time.
+ *
+ * This class has a side-effect on the @c max_wait_time -- every
+ * time the stop() method is called the @c max_wait_time is
+ * updated.
+ */
+class ACE_Export ACE_Countdown_Time
+{
+public:
+ /// Cache the @a max_wait_time and call @c start().
+ ACE_Countdown_Time (ACE_Time_Value *max_wait_time);
+
+ /// Destructor, makes sure the max_wait_time that got passed as pointer
+ /// to the constructor is updated with the time elapsed.
+ ~ACE_Countdown_Time (void);
+
+ /// Cache the current time and enter a start state.
+ void start (void);
+
+ /// Subtract the elapsed time from max_wait_time_ and enter a stopped
+ /// state.
+ void stop (void);
+
+ /// Calls stop and then start. max_wait_time_ is modified by the
+ /// call to stop.
+ void update (void);
+
+ /// Returns true if we've already been stopped, else false.
+ bool stopped (void) const;
+
+private:
+ /// Maximum time we were willing to wait.
+ ACE_Time_Value *max_wait_time_;
+
+ /// Beginning of the start time.
+ ACE_Time_Value start_time_;
+
+ /// Keeps track of whether we've already been stopped.
+ bool stopped_;
+
+ // Prevent copying
+ ACE_Countdown_Time (const ACE_Countdown_Time &);
+ ACE_Countdown_Time &operator= (const ACE_Countdown_Time &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_COUNTDOWN_TIME_H */
diff --git a/ACE/ace/DEV.cpp b/ACE/ace/DEV.cpp
new file mode 100644
index 00000000000..1ae27fc558e
--- /dev/null
+++ b/ACE/ace/DEV.cpp
@@ -0,0 +1,43 @@
+// $Id$
+
+#include "ace/DEV.h"
+
+#include "ace/OS_NS_unistd.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/DEV.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, DEV, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_DEV)
+
+void
+ACE_DEV::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_DEV::dump");
+#endif /* ACE_HAS_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DEV.h b/ACE/ace/DEV.h
new file mode 100644
index 00000000000..8b0c585ddf7
--- /dev/null
+++ b/ACE/ace/DEV.h
@@ -0,0 +1,78 @@
+/* -*- 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_IO
+#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_IO, ACE_DEV_Addr
+#endif /* ACE_TEMPLATE_TYPEDEFS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a 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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/DEV.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DEV_H */
diff --git a/ACE/ace/DEV.inl b/ACE/ace/DEV.inl
new file mode 100644
index 00000000000..e00f4fc705e
--- /dev/null
+++ b/ACE/ace/DEV.inl
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DEV_Addr.cpp b/ACE/ace/DEV_Addr.cpp
new file mode 100644
index 00000000000..39d1768051f
--- /dev/null
+++ b/ACE/ace/DEV_Addr.cpp
@@ -0,0 +1,108 @@
+// $Id$
+
+#include "ace/DEV_Addr.h"
+#if !defined (__ACE_INLINE__)
+#include "ace/DEV_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ DEV_Addr,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_DEV_Addr)
+
+// Transform the current address into string format.
+
+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.
+
+void *
+ACE_DEV_Addr::get_addr (void) const
+{
+ ACE_TRACE ("ACE_DEV_Addr::get_addr");
+
+ return (void *) &this->devname_;
+}
+
+void
+ACE_DEV_Addr::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_DEV_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("devname_ = %s"), this->devname_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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::strsncpy (this->devname_,
+ sa.devname_,
+ ACE_DEV_Addr::DEVNAME_LENGTH);
+ 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)
+ this->set (sa);
+
+ return *this;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DEV_Addr.h b/ACE/ace/DEV_Addr.h
new file mode 100644
index 00000000000..0646260c8f9
--- /dev/null
+++ b/ACE/ace/DEV_Addr.h
@@ -0,0 +1,90 @@
+// -*- 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/os_include/os_dirent.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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.
+ 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.
+ bool operator == (const ACE_DEV_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ bool 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:
+ enum { DEVNAME_LENGTH = MAXPATHLEN + 1 };
+ /// Name of the device.
+ ACE_TCHAR devname_[DEVNAME_LENGTH];
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/DEV_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_DEV_ADDR_H */
diff --git a/ACE/ace/DEV_Addr.inl b/ACE/ace/DEV_Addr.inl
new file mode 100644
index 00000000000..820b961d1d0
--- /dev/null
+++ b/ACE/ace/DEV_Addr.inl
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "ace/Global_Macros.h"
+#include "ace/os_include/sys/os_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_DEV_Addr::set (const ACE_TCHAR *devname)
+{
+ ACE_TRACE ("ACE_DEV_Addr::set");
+
+ this->ACE_Addr::base_set
+ (AF_DEV, static_cast<int> (ACE_OS::strlen (devname)));
+ ACE_OS::strsncpy (this->devname_, devname, ACE_DEV_Addr::DEVNAME_LENGTH);
+}
+
+// Compare two addresses for equality.
+
+ACE_INLINE bool
+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 bool
+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_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DEV_Connector.cpp b/ACE/ace/DEV_Connector.cpp
new file mode 100644
index 00000000000..a1fef807057
--- /dev/null
+++ b/ACE/ace/DEV_Connector.cpp
@@ -0,0 +1,53 @@
+// $Id$
+
+#include "ace/DEV_Connector.h"
+
+#include "ace/Handle_Ops.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/DEV_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ DEV_Connector,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_DEV_Connector)
+
+void
+ACE_DEV_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_DEV_Connector::dump");
+#endif /* ACE_HAS_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_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DEV_Connector.h b/ACE/ace/DEV_Connector.h
new file mode 100644
index 00000000000..9e001c412f4
--- /dev/null
+++ b/ACE/ace/DEV_Connector.h
@@ -0,0 +1,110 @@
+/* -*- 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"
+#include "ace/os_include/os_fcntl.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a new_io if things go well.
+ * The @a remote_sap is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a reuse_addr == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The @a flags and @a 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 @a new_io if things go well.
+ * The @a remote_sap is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a reuse_addr == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The @a flags and @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/DEV_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DEV_CONNECTOR_H */
diff --git a/ACE/ace/DEV_Connector.inl b/ACE/ace/DEV_Connector.inl
new file mode 100644
index 00000000000..314952699de
--- /dev/null
+++ b/ACE/ace/DEV_Connector.inl
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Creates a Local ACE_DEV.
+
+ACE_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_TEXT ("address %s, %p\n"),
+ remote_sap.get_path_name (), ACE_TEXT ("ACE_DEV_IO")));
+}
+
+ACE_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DEV_IO.cpp b/ACE/ace/DEV_IO.cpp
new file mode 100644
index 00000000000..f5367d1d5cd
--- /dev/null
+++ b/ACE/ace/DEV_IO.cpp
@@ -0,0 +1,131 @@
+// $Id$
+
+#include "ace/DEV_IO.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/DEV_IO.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, DEV_IO, "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_DEV_IO::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->addr_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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;
+ int total_tuples = static_cast<int> (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 (int 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;
+ int total_tuples = static_cast<int> (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 (int 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DEV_IO.h b/ACE/ace/DEV_IO.h
new file mode 100644
index 00000000000..d3b1aadaa2f
--- /dev/null
+++ b/ACE/ace/DEV_IO.h
@@ -0,0 +1,185 @@
+/* -*- 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 */
+
+#if defined (ACE_HAS_STREAM_PIPES)
+# include "ace/OS_NS_stropts.h"
+#endif /* ACE_HAS_STREAM_PIPES */
+
+#include "ace/os_include/os_stdio.h"
+#include "ace/os_include/sys/os_uio.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @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 @a n bytes in @a buf.
+ ssize_t send (const void *buf, size_t n) const;
+
+ /// Recv upto @a n bytes in @a 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;
+
+ /**
+ * @name I/O operations
+ *
+ * Notes on common parameters:
+ *
+ * @a buf is the buffer to write from or receive into.
+ *
+ * @a len is the number of bytes to transfer.
+ *
+ * The @a timeout parameter in the following methods indicates how
+ * long to blocking trying to transfer data. If @a 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 @a timeout != 0, the call will wait until the relative time
+ * specified in *@a timeout elapses.
+ *
+ * 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. @a 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, @a bytes_transferred will contain the number of
+ * bytes transferred.
+ */
+ ssize_t recv_n (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) 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 @a cntl and @a data via STREAM pipes.
+ ssize_t recv (ACE_Str_Buf *cntl,
+ ACE_Str_Buf *data,
+ int *flags) const;
+
+ /// Send @a cntl and @a 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 @a n bytes via Win32 WriteFile using overlapped I/O.
+ ssize_t send (const void *buf, size_t n, ACE_OVERLAPPED *overlapped) const;
+
+ /// Recv @a 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/DEV_IO.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DEV_IO_H */
diff --git a/ACE/ace/DEV_IO.inl b/ACE/ace/DEV_IO.inl
new file mode 100644
index 00000000000..cb9392e2bf3
--- /dev/null
+++ b/ACE/ace/DEV_IO.inl
@@ -0,0 +1,126 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_sys_uio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_Memory.h"
+
+#include "ace/ACE.h"
+
+// Send exactly N bytes from BUF to this device. Keeping trying until
+// this many bytes are sent.
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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.
+
+ACE_INLINE ssize_t
+ACE_DEV_IO::recv_n (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_DEV_IO::recv_n");
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (timeout);
+
+ return ACE::read_n (this->get_handle (),
+ buf,
+ n,
+ bytes_transferred);
+#else
+ return ACE::recv_n (this->get_handle (),
+ buf,
+ n,
+ timeout,
+ bytes_transferred);
+#endif /*ACE_WIN32*/
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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, static_cast<int> (n));
+}
+
+ACE_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, static_cast<int> (n));
+}
+
+ACE_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);
+}
+
+ACE_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)
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DLL.cpp b/ACE/ace/DLL.cpp
new file mode 100644
index 00000000000..cdee3c6bd24
--- /dev/null
+++ b/ACE/ace/DLL.cpp
@@ -0,0 +1,267 @@
+// $Id$
+
+#include "ace/DLL.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/DLL_Manager.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_dlfcn.h"
+#include "ace/OS_NS_Thread.h"
+
+#include <algorithm>
+
+ACE_RCSID(ace, DLL, "$Id$")
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Default constructor. Also, by default, the object will be closed
+// before it is destroyed.
+
+ACE_DLL::ACE_DLL (bool close_handle_on_destruction)
+ : open_mode_ (0),
+ dll_name_ (0),
+ close_handle_on_destruction_ (close_handle_on_destruction),
+ dll_handle_ (0),
+ error_ (0)
+{
+ ACE_TRACE ("ACE_DLL::ACE_DLL (int)");
+}
+
+ACE_DLL::ACE_DLL (const ACE_DLL &rhs)
+ : open_mode_ (0),
+ dll_name_ (0),
+ close_handle_on_destruction_ (false),
+ dll_handle_ (0),
+ error_ (0)
+{
+ ACE_TRACE ("ACE_DLL::ACE_DLL (const ACE_DLL &)");
+
+ if (rhs.dll_name_
+ // This will automatically up the refcount.
+ && this->open (rhs.dll_name_,
+ rhs.open_mode_,
+ rhs.close_handle_on_destruction_) != 0
+ && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_DLL::copy_ctor: error: %s\n"),
+ this->error ()));
+}
+
+// Assignment operator
+
+ACE_DLL &
+ACE_DLL::operator= (const ACE_DLL &rhs)
+{
+ ACE_TRACE ("ACE_DLL::operator= (const ACE_DLL &)");
+
+ ACE_DLL tmp (rhs);
+
+ std::swap (this->open_mode_, tmp.open_mode_);
+ std::swap (this->dll_name_, tmp.dll_name_);
+ std::swap (this->close_handle_on_destruction_,
+ tmp.close_handle_on_destruction_);
+ std::swap (this->dll_handle_, tmp.dll_handle_);
+ std::swap (this->error_, tmp.error_);
+
+ return *this;
+}
+
+
+// If the library name and the opening mode are specified than on
+// object creation the library is implicitly opened.
+
+ACE_DLL::ACE_DLL (const ACE_TCHAR *dll_name,
+ int open_mode,
+ bool close_handle_on_destruction)
+ : open_mode_ (open_mode),
+ dll_name_ (0),
+ close_handle_on_destruction_ (close_handle_on_destruction),
+ dll_handle_ (0),
+ error_ (0)
+{
+ ACE_TRACE ("ACE_DLL::ACE_DLL");
+
+ if (this->open (dll_name, this->open_mode_, close_handle_on_destruction) != 0
+ && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_DLL::open: error calling open: %s\n"),
+ this->error ()));
+}
+
+// The library is closed before the class gets destroyed depending on
+// the close_handle_on_destruction value specified which is stored in
+// close_handle_on_destruction_.
+
+ACE_DLL::~ACE_DLL (void)
+{
+ ACE_TRACE ("ACE_DLL::~ACE_DLL");
+
+ this->close ();
+
+ // Normally delete()d in ACE_DLL::close(). However, that may not
+ // occur if full ACE_DLL initialization is interrupted due to errors
+ // (e.g. attempting to open a DSO/DLL that does not exist). Make
+ // sure this->dll_name_ is deallocated.
+ delete [] this->dll_name_;
+}
+
+// This method opens the library based on the mode specified using the
+// ACE_SHLIB_HANDLE which is obtained on making the ACE_OS::dlopen call.
+// The default mode is:
+// RTLD_LAZY Only references to data symbols are relocate when the
+// object is first loaded.
+// The other modes include:
+// RTLD_NOW All necessary relocations are performed when the
+// object is first loaded.
+// RTLD_GLOBAL The object symbols are made available for the
+// relocation processing of any other object.
+
+int
+ACE_DLL::open (const ACE_TCHAR *dll_filename,
+ int open_mode,
+ bool close_handle_on_destruction)
+{
+ ACE_TRACE ("ACE_DLL::open");
+
+ return open_i (dll_filename, open_mode, close_handle_on_destruction);
+}
+
+int
+ACE_DLL::open_i (const ACE_TCHAR *dll_filename,
+ int open_mode,
+ bool close_handle_on_destruction,
+ ACE_SHLIB_HANDLE handle)
+{
+ ACE_TRACE ("ACE_DLL::open_i");
+
+ this->error_ = 0;
+
+ if (!dll_filename)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_DLL::open_i: dll_name is %s\n"),
+ this->dll_name_ == 0 ? ACE_TEXT ("(null)")
+ : this->dll_name_));
+ return -1;
+ }
+
+ if (this->dll_handle_)
+ {
+ // If we have a good handle and its the same name, just return.
+ if (ACE_OS::strcmp (this->dll_name_, dll_filename) == 0)
+ return 0;
+ else
+ this->close ();
+ }
+
+ if (!this->dll_name_)
+ this->dll_name_ = ACE::strnew (dll_filename);
+
+ this->open_mode_ = open_mode;
+ this->close_handle_on_destruction_ = close_handle_on_destruction;
+
+ this->dll_handle_ = ACE_DLL_Manager::instance()->open_dll (this->dll_name_,
+ this->open_mode_,
+ handle);
+
+ if (!this->dll_handle_)
+ this->error_ = 1;
+
+ return this->error_ ? -1 : 0;
+}
+
+// The symbol refernce of the name specified is obtained.
+
+void *
+ACE_DLL::symbol (const ACE_TCHAR *sym_name, int ignore_errors)
+{
+ ACE_TRACE ("ACE_DLL::symbol");
+
+ this->error_ = 0;
+
+ void *sym = 0;
+ if (this->dll_handle_)
+ sym = this->dll_handle_->symbol (sym_name, ignore_errors);
+
+ if (!sym)
+ this->error_ = 1;
+
+ return sym;
+}
+
+// The library is closed using the ACE_SHLIB_HANDLE object, i.e., the
+// shared object is now disassociated form the current process.
+
+int
+ACE_DLL::close (void)
+{
+ ACE_TRACE ("ACE_DLL::close");
+
+ int retval = 0;
+
+ if (this->dll_handle_
+ && this->close_handle_on_destruction_
+ && this->dll_name_
+ && (retval = ACE_DLL_Manager::instance ()->close_dll (this->dll_name_)) != 0)
+ this->error_ = 1;
+
+ // Even if close_dll() failed, go ahead and cleanup.
+ this->dll_handle_ = 0;
+ delete [] this->dll_name_;
+ this->dll_name_ = 0;
+ this->close_handle_on_destruction_ = false;
+
+ return retval;
+}
+
+// This method is used return the last error of a library operation.
+
+ACE_TCHAR *
+ACE_DLL::error (void) const
+{
+ ACE_TRACE ("ACE_DLL::error");
+ if (this->error_)
+ {
+ return ACE_OS::dlerror ();
+ }
+
+ return 0;
+}
+
+// Return the handle to the user either temporarily or forever, thus
+// orphaning it. If 0 means the user wants the handle forever and if 1
+// means the user temporarily wants to take the handle.
+
+ACE_SHLIB_HANDLE
+ACE_DLL::get_handle (int become_owner) const
+{
+ ACE_TRACE ("ACE_DLL::get_handle");
+
+ ACE_SHLIB_HANDLE handle = ACE_SHLIB_INVALID_HANDLE;
+
+ if (this->dll_handle_)
+ handle = this->dll_handle_->get_handle (become_owner);
+
+ return handle;
+}
+
+// Set the handle for the DLL. By default, the object will be closed
+// before it is destroyed.
+
+int
+ACE_DLL::set_handle (ACE_SHLIB_HANDLE handle,
+ bool close_handle_on_destruction)
+{
+ ACE_TRACE ("ACE_DLL::set_handle");
+
+ // Create a unique name. Note that this name is only quaranteed
+ // to be unique for the life of this object.
+ ACE_TCHAR temp[ACE_UNIQUE_NAME_LEN];
+ ACE_OS::unique_name (this, temp, ACE_UNIQUE_NAME_LEN);
+
+ return this->open_i (temp, 1, close_handle_on_destruction, handle);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DLL.h b/ACE/ace/DLL.h
new file mode 100644
index 00000000000..64cb646576a
--- /dev/null
+++ b/ACE/ace/DLL.h
@@ -0,0 +1,196 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file DLL.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_DLL_H
+#define ACE_DLL_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+#include "ace/os_include/os_dlfcn.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_DLL_Handle;
+
+/**
+ * @class ACE_DLL
+ *
+ * @brief Provides an abstract interface for handling various DLL
+ * operations.
+ *
+ * This class is a wrapper over the various methods for utilizing
+ * a dynamically linked library (DLL), which is called a shared
+ * library on some platforms. Operations @c open(), @c close(), and
+ * @c symbol() have been implemented to help opening/closing and
+ * extracting symbol information from a DLL, respectively.
+ */
+class ACE_Export ACE_DLL
+{
+public:
+ // = Initialization and termination methods.
+
+ /**
+ * Default constructor. By default, the close() operation on the
+ * object will be invoked before it is destroyed.
+ * @param close_handle_on_destruction Indicates whether or not the
+ * close() method will be called to close an open DLL when this
+ * object is destroyed. By default, close() will be called.
+ * Set this parameter to 0 for situations where the DLL's lifetime
+ * is controlled in a scope other than that of this ACE_DLL object.
+ * For example, termination by ACE_DLL_Manager via ACE::fini().
+ */
+ explicit ACE_DLL (bool close_handle_on_destruction = true);
+
+ /// Allow assignment
+ ACE_DLL& operator= (const ACE_DLL &rhs);
+
+
+ /**
+ * This constructor performs the actions of open() during construction.
+ * @param dll_name The name or path of the DLL to load.
+ * @param open_mode Flags to alter the actions taken when loading the DLL.
+ * The possible values are:
+ * @li @c RTLD_LAZY (this the default): loads identifier symbols but
+ * not the symbols for functions, which are loaded dynamically
+ * on-demand.
+ * @li @c RTLD_NOW: performs all necessary relocations when
+ * @a dll_name is first loaded
+ * @li RTLD_GLOBAL: makes symbols available for relocation
+ * processing of any other DLLs.
+ * @param close_handle_on_destruction Indicates whether or not the
+ * close() method will be called to close an open DLL when this
+ * object is destroyed. By default, close() will be called.
+ * Set this parameter to 0 for situations where the DLL's lifetime
+ * is controlled in a scope other than that of this ACE_DLL object.
+ * For example, termination by ACE_DLL_Manager via ACE::fini().
+ */
+ explicit ACE_DLL (const ACE_TCHAR *dll_name,
+ int open_mode = ACE_DEFAULT_SHLIB_MODE,
+ bool close_handle_on_destruction = true);
+
+ /// Copy constructor.
+ ACE_DLL (const ACE_DLL &);
+
+ /**
+ * This method opens and dynamically links a specified DLL.
+ * @param dll_name The filename or path of the DLL to load.
+ * If a filename is given to @c open(), the @c ACE::ldfind() is used
+ * to locate DLLs via the following algorithms: (1) DLL filename
+ * expansion: @c ACE::ldfind() determines the name of the DLL by
+ * adding the appropriate prefix and suffix, e.g., it adds the @c lib
+ * prefix and @c .so suffix for Solaris and the @c .dll suffix for
+ * Windows and (2) DLL search path: @c ACE::ldfind() will also search
+ * for the designated DLL using the platform's DLL search path
+ * environment variable, e.g., it searches for DLLs using @c
+ * LD_LIBRARY_PATH on many UNIX systems and @c PATH on Windows.
+ * @param open_mode Flags to alter the actions taken when loading the DLL.
+ * The possible values are:
+ * @li @c RTLD_LAZY (this the default): loads identifier symbols but
+ * not the symbols for functions, which are loaded dynamically
+ * on-demand.
+ * @li @c RTLD_NOW: performs all necessary relocations when
+ * @a dll_name is first loaded
+ * @li RTLD_GLOBAL: makes symbols available for relocation
+ * processing of any other DLLs.
+ * @param close_handle_on_destruction Indicates whether or not the
+ * close() method will be called to close an open DLL when this
+ * object is destroyed. By default, close() will be called.
+ * Set this parameter to 0 for situations where the DLL's lifetime
+ * is controlled in a scope other than that of this ACE_DLL object.
+ * For example, termination by ACE_DLL_Manager via ACE::fini().
+ * @retval -1 On failure
+ * @retval 0 On success.
+ */
+ int open (const ACE_TCHAR *dll_name,
+ int open_mode = ACE_DEFAULT_SHLIB_MODE,
+ bool close_handle_on_destruction = true);
+
+ /// Call to close the DLL object.
+ int close (void);
+
+ /**
+ * Called when the DLL object is destroyed -- invokes close() if the
+ * @a close_handle_on_destruction flag was set to non-zero in the
+ * constructor or open() method.
+ */
+ ~ACE_DLL (void);
+
+ /**
+ * Look up a named symbol in the DLL. DLL must be successfully opened
+ * before calling symbol().
+ * @param symbol_name The symbol name to look up.
+ * @param ignore_errors If set to 1, allows you to probe a dll without
+ * generating error messages in the log. Handy for determining
+ * the capabilities of a library.
+ * @return Returns the value of @a symbol_name if it is a valid symbol
+ * in the DLL. Otherwise, returns 0.
+ */
+ void *symbol (const ACE_TCHAR *symbol_name, int ignore_errors = 0);
+
+ /// Returns a pointer to a string explaining that an error occured. You
+ /// will need to consult the error log for the actual error string
+ /// returned by the OS.
+ ACE_TCHAR *error (void) const;
+
+ /**
+ * Return the handle to the caller. If @a become_owner is non-0 then
+ * caller assumes ownership of the handle and the ACE_DLL object
+ * won't call close() when it goes out of scope, even if
+ * <close_handle_on_destruction> is set.
+ */
+ ACE_SHLIB_HANDLE get_handle (int become_owner = 0) const;
+
+ /// Set the handle for the DLL object. By default, the close()
+ //operation on / the object will be invoked before it is destroyed.
+ int set_handle (ACE_SHLIB_HANDLE handle,
+ bool close_handle_on_destruction = true);
+
+private:
+
+ int open_i (const ACE_TCHAR *dll_name,
+ int open_mode = ACE_DEFAULT_SHLIB_MODE,
+ bool close_handle_on_destruction = true,
+ ACE_SHLIB_HANDLE handle = 0);
+
+
+ //private:
+public:
+
+ /// Open mode.
+ int open_mode_;
+
+ /// Keep track of the name of the loaded dll, so it can be used
+ /// to remove framework components, singletons that live in the dll,
+ /// prior to unloading the dll in the close() method.
+ ACE_TCHAR *dll_name_;
+
+ /// This flag keeps track of whether we should close the handle
+ /// automatically when the object is destroyed.
+ bool close_handle_on_destruction_;
+
+ ACE_DLL_Handle *dll_handle_;
+
+ /// Flag to record if the last operation had an error.
+ bool error_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DLL_H */
diff --git a/ACE/ace/DLL_Manager.cpp b/ACE/ace/DLL_Manager.cpp
new file mode 100644
index 00000000000..83c07cd125d
--- /dev/null
+++ b/ACE/ace/DLL_Manager.cpp
@@ -0,0 +1,787 @@
+// $Id$
+
+#include "ace/DLL_Manager.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/Framework_Component.h"
+
+#include "ace/Lib_Find.h"
+#include "ace/Object_Manager.h"
+#include "ace/SString.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Guard_T.h"
+#include "ace/OS_NS_dlfcn.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ DLL_Manager,
+ "DLL_Manager.cpp,v 4.23 2003/11/05 23:30:46 shuston Exp")
+
+/******************************************************************/
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+sig_atomic_t ACE_DLL_Handle::open_called_ = 0;
+
+ACE_DLL_Handle::ACE_DLL_Handle (void)
+ : refcount_ (0),
+ dll_name_ (0),
+ handle_ (ACE_SHLIB_INVALID_HANDLE)
+{
+ ACE_TRACE ("ACE_DLL_Handle::ACE_DLL_Handle");
+}
+
+ACE_DLL_Handle::~ACE_DLL_Handle (void)
+{
+ ACE_TRACE ("ACE_DLL_Handle::~ACE_DLL_Handle");
+ this->close (1);
+ delete[] this->dll_name_;
+}
+
+const ACE_TCHAR *
+ACE_DLL_Handle::dll_name (void) const
+{
+ ACE_TRACE ("ACE_DLL_Handle::dll_name");
+ return this->dll_name_;
+}
+
+int
+ACE_DLL_Handle::open (const ACE_TCHAR *dll_name,
+ int open_mode,
+ ACE_SHLIB_HANDLE handle)
+{
+ ACE_TRACE ("ACE_DLL_Handle::open");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ if (this->dll_name_)
+ {
+ // Once dll_name_ has been set, it can't be changed..
+ if (ACE_OS::strcmp (this->dll_name_, dll_name) != 0)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) DLL_Handle::open: error, ")
+ ACE_TEXT ("tried to reopen %s with name %s\n"),
+ this->dll_name_,
+ dll_name));
+
+ return -1;
+ }
+ }
+ else
+ this->dll_name_ = ACE::strnew (dll_name);
+
+ if (!this->open_called_)
+ this->open_called_ = 1;
+
+ // If it hasn't been loaded yet, go ahead and do that now.
+ if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
+ {
+ if (handle)
+ this->handle_ = handle;
+ else
+ {
+ /*
+ ** Get the set of names to try loading. We need to do this to
+ ** properly support the ability for a user to specify a simple,
+ ** unadorned name (for example, "ACE") that will work across
+ ** platforms. We apply platform specifics to get a name that will
+ ** work (e.g. libACE, ACEd.dll, ACE.dll, etc.) We rely on the
+ ** underlying dlopen() implementation to "Do The Right Thing" in
+ ** terms of using relative paths, LD_LIBRARY_PATH, system security
+ ** rules, etc. except when ACE_MUST_HELP_DLOPEN_SEARCH_PATH is set.
+ ** If it is set, then ACE::ldfind() scans the configured path
+ ** looking for a match on the name and prefix/suffix applications.
+ ** NOTE: having ACE scan for a file and then pass a fully-qualified
+ ** pathname to dlopen() is a potential security hole; therefore,
+ ** do not use ACE_MUST_HELP_DLOPEN_SEARCH_PATH unless necessary
+ ** and only after considering the risks.
+ */
+ ACE_Array<ACE_TString> dll_names;
+ dll_names.max_size (10); // Decent guess to avoid realloc later
+
+#if defined (ACE_MUST_HELP_DLOPEN_SEARCH_PATH)
+ // Find out where the library is
+ ACE_TCHAR dll_pathname[MAXPATHLEN + 1];
+
+ // Transform the pathname into the appropriate dynamic link library
+ // by searching the ACE_LD_SEARCH_PATH.
+ ACE::ldfind (dll_name,
+ dll_pathname,
+ (sizeof dll_pathname / sizeof (ACE_TCHAR)));
+ ACE_TString dll_str (dll_pathname);
+ dll_names.size (1);
+ dll_names.set (dll_str, 0);
+#else
+ this->get_dll_names (dll_name, dll_names);
+#endif
+
+ ACE_Array_Iterator<ACE_TString> name_iter (dll_names);
+ ACE_TString *name = 0;
+ while (name_iter.next (name))
+ {
+ // The ACE_SHLIB_HANDLE object is obtained.
+ this->handle_ = ACE_OS::dlopen (name->c_str (),
+ open_mode);
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::open ")
+ ACE_TEXT ("(\"%s\", 0x%x) -> %s: %s\n"),
+ name->c_str (),
+ open_mode,
+ ((this->handle_ != ACE_SHLIB_INVALID_HANDLE)
+ ? ACE_TEXT ("succeeded")
+ : ACE_TEXT ("failed")),
+ this->error()->c_str()));
+ }
+
+ if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) // Good one?
+ break;
+
+ // If errno is ENOENT we just skip over this one,
+ // anything else - like an undefined symbol, for
+ // instance must be flagged here or the next error will
+ // mask it.
+ // @TODO: If we've found our DLL _and_ it's
+ // broken, should we continue at all?
+ if ((errno != 0) && (errno != ENOENT) && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::open ")
+ ACE_TEXT ("(\'%s\') failed, errno=")
+ ACE_TEXT ("%d: %s\n"),
+ name->c_str (),
+ errno,
+ this->error ()->c_str ()));
+
+#if defined (AIX)
+ // AIX often puts the shared library file (most often named
+ // shr.o) inside an archive library. If this is an archive
+ // library name, then try appending [shr.o] and retry.
+ if (ACE_TString::npos != name->strstr (ACE_TEXT (".a")))
+ {
+ ACE_TCHAR aix_pathname[MAXPATHLEN + 1];
+ ACE_OS::strncpy (aix_pathname,
+ name->c_str (),
+ name->length ());
+ aix_pathname[name->length ()] = '\0';
+ ACE_OS::strcat (aix_pathname, ACE_TEXT ("(shr.o)"));
+ open_mode |= RTLD_MEMBER;
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::open ")
+ ACE_TEXT ("(\"%s\", 0x%x) -> %s: %s\n"),
+ aix_pathname,
+ open_mode,
+ ACE_TEXT ((this->handle_ != ACE_SHLIB_INVALID_HANDLE)
+ ? "succeeded"
+ : "failed"),
+ this->error()->c_str()));
+ }
+
+ this->handle_ = ACE_OS::dlopen (aix_pathname, open_mode);
+ if (this->handle_ != ACE_SHLIB_INVALID_HANDLE)
+ break;
+
+ // If errno is ENOENT we just skip over this one, anything
+ // else - like an undefined symbol, for instance
+ // must be flagged here or the next error will mask it.
+ //
+ // @TODO: If we've found our DLL _and_ it's broken,
+ // should we continue at all?
+ if (ACE::debug () && (errno != 0) && (errno != ENOENT))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::open ")
+ ACE_TEXT ("(\'%s\') failed, errno=")
+ ACE_TEXT ("%d: %s\n"),
+ name->c_str (),
+ errno,
+ this->error ()->c_str ()));
+
+ }
+#endif /* AIX */
+
+ name_iter.advance ();
+ }
+
+ if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::open (\"%s\"): ")
+ ACE_TEXT ("Invalid handle error: %s\n"),
+ this->dll_name_,
+ this->error ()->c_str ()));
+
+ return -1;
+ }
+ }
+ }
+
+ ++this->refcount_;
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::open - %s (%d), refcount=%d\n"),
+ this->dll_name_,
+ this->handle_,
+ this->refcount_));
+ return 0;
+}
+
+
+int
+ACE_DLL_Handle::close (int unload)
+{
+ ACE_TRACE ("ACE_DLL_Handle::close");
+
+ int retval = 0;
+ ACE_SHLIB_HANDLE h = ACE_SHLIB_INVALID_HANDLE;
+
+ // Only hold the lock until it comes time to dlclose() the DLL. Closing
+ // the DLL can cause further shutdowns as DLLs and their dependents are
+ // unloaded.
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ // Since we don't actually unload the dll as soon as the refcount
+ // reaches zero, we need to make sure we don't decrement it below
+ // zero.
+ if (this->refcount_ > 0)
+ --this->refcount_;
+ else
+ this->refcount_ = 0;
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::close - ")
+ ACE_TEXT ("%s (handle=%d, refcount=%d)\n"),
+ this->dll_name_,
+ this->handle_,
+ this->refcount_));
+
+ if (this->refcount_ == 0 &&
+ this->handle_ != ACE_SHLIB_INVALID_HANDLE &&
+ unload == 1)
+ {
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::close: ")
+ ACE_TEXT ("Unloading %s (handle=%d)\n"),
+ this->dll_name_,
+ this->handle_));
+
+ // First remove any associated Framework Components.
+ ACE_Framework_Repository *frPtr= ACE_Framework_Repository::instance ();
+ if (frPtr)
+ {
+ frPtr->remove_dll_components (this->dll_name_);
+ }
+
+ h = this->handle_;
+ this->handle_ = ACE_SHLIB_INVALID_HANDLE;
+ }
+ } // Release lock_ here
+
+ if (h != ACE_SHLIB_INVALID_HANDLE)
+ {
+ retval = ACE_OS::dlclose (h);
+
+ if (retval != 0 && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::close - ")
+ ACE_TEXT ("Failed with: \"%s\".\n"),
+ this->error ()->c_str ()));
+ }
+
+ return retval;
+}
+
+sig_atomic_t
+ACE_DLL_Handle::refcount (void) const
+{
+ return this->refcount_;
+}
+
+void *
+ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name, int ignore_errors)
+{
+ ACE_TRACE ("ACE_DLL_Handle::symbol");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ ACE_Auto_Array_Ptr <ACE_TCHAR> auto_name (ACE::ldname (sym_name));
+ // handle_ can be invalid especially when ACE_DLL_Handle resigned ownership
+ // BTW. Handle lifecycle management is a little crazy in ACE
+ if (this->handle_ != ACE_SHLIB_INVALID_HANDLE)
+ {
+#if defined (ACE_OPENVMS)
+ void *sym = ACE::ldsymbol (this->handle_, auto_name.get ());
+#else
+ void *sym = ACE_OS::dlsym (this->handle_, auto_name.get ());
+#endif
+
+ // Linux says that the symbol could be null and that it isn't an
+ // error. So you should check the error message also, but since
+ // null symbols won't do us much good anyway, let's still report
+ // an error.
+ if (!sym && ignore_errors != 1)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::symbol (\"%s\") ")
+ ACE_TEXT (" failed with \"%s\".\n"),
+ auto_name.get (),
+ this->error ()->c_str ()));
+
+ return 0;
+ }
+ return sym;
+ }
+ return 0;
+}
+
+ACE_SHLIB_HANDLE
+ACE_DLL_Handle::get_handle (int become_owner)
+{
+ ACE_TRACE ("ACE_DLL_Handle::get_handle");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ if (this->refcount_ == 0 && become_owner != 0)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) DLL_Handle::get_handle: ")
+ ACE_TEXT ("cannot become owner, refcount == 0.\n")));
+
+ return ACE_SHLIB_INVALID_HANDLE;
+ }
+
+ ACE_SHLIB_HANDLE handle = this->handle_;
+
+ if (become_owner != 0)
+ {
+ if (--this->refcount_ == 0)
+ this->handle_ = ACE_SHLIB_INVALID_HANDLE;
+ }
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) ACE_DLL_Handle::get_handle: ")
+ ACE_TEXT ("post call: handle %s, refcount %d\n"),
+ this->handle_ == ACE_SHLIB_INVALID_HANDLE ?
+ ACE_TEXT ("invalid") : ACE_TEXT ("valid"),
+ this->refcount_));
+
+ return handle;
+}
+
+// This method is used return the last error of a library operation.
+
+auto_ptr <ACE_TString>
+ACE_DLL_Handle::error (void)
+{
+ ACE_TRACE ("ACE_DLL_Handle::error");
+ const ACE_TCHAR *error = ACE_OS::dlerror ();
+ auto_ptr<ACE_TString> str
+ (new ACE_TString (error ? error : ACE_TEXT ("no error")));
+ return str;
+}
+
+void
+ACE_DLL_Handle::get_dll_names (const ACE_TCHAR *dll_name,
+ ACE_Array<ACE_TString> &try_names)
+{
+ // Build the array of DLL names to try on this platform by applying the
+ // proper prefixes and/or suffixes to the specified dll_name.
+ ACE_TString base (dll_name);
+ ACE_TString base_dir, base_file, base_suffix;
+
+ // 1. Separate the dll_name into the dir part and the file part. We
+ // only decorate the file part to determine the names to try loading.
+ ACE_TString::size_type pos = base.rfind (ACE_DIRECTORY_SEPARATOR_CHAR);
+ if (pos != ACE_TString::npos)
+ {
+ base_dir = base.substr (0, pos + 1);
+ base_file = base.substr (pos + 1);
+ }
+ else
+ base_file = base;
+
+ // 2. Locate the file suffix, if there is one. Move the '.' and the
+ // suffix to base_suffix.
+ if ((pos = base_file.rfind (ACE_TEXT ('.'))) != ACE_TString::npos)
+ {
+ base_suffix = base_file.substr (pos);
+ base_file = base_file.substr (0, pos);
+ }
+
+ // 3. Build the combinations to try for this platform.
+ // Try these combinations:
+ // - name with decorator and platform's suffix appended (if not supplied)
+ // - name with platform's suffix appended (if not supplied)
+ // - name with platform's dll prefix (if it has one) and suffix
+ // - name with platform's dll prefix, decorator, and suffix.
+ // - name as originally given
+ // We first try to find the file using the decorator so that when a
+ // filename with and without decorator is used, we get the file with
+ // the same decorator as the ACE dll has and then as last resort
+ // the one without. For example with msvc, the debug build has a "d"
+ // decorator, but the release build has none and we really want to get
+ // the debug version of the library in a debug application instead
+ // of the release one.
+ // So we need room for 5 entries in try_names.
+ try_names.size (0);
+ if ((try_names.max_size () - try_names.size ()) < 5)
+ try_names.max_size (try_names.max_size () + 5);
+#if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ ACE_TString decorator (ACE_LD_DECORATOR_STR);
+#endif
+ ACE_TString suffix (ACE_DLL_SUFFIX);
+ ACE_TString prefix (ACE_DLL_PREFIX);
+
+ for (size_t i = 0; i < 5 && try_names.size () < try_names.max_size (); ++i)
+ {
+ ACE_TString try_this;
+ size_t j = try_names.size ();
+ switch (i)
+ {
+ case 0: // Name + decorator + suffix
+ case 1: // Name + suffix
+ case 2: // Prefix + name + decorator + suffix
+ case 3: // Prefix + name + suffix
+ if (
+ base_suffix.length () > 0
+#if !(defined(ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK))
+ || (i == 1 || i == 3) // No decorator desired; skip
+#endif
+ )
+ break;
+ try_this = base_dir;
+ if (i > 1)
+ try_this += prefix;
+ try_this += base_file;
+ if (base_suffix.length () > 0)
+ try_this += base_suffix;
+ else
+ {
+#if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ try_this += decorator;
+#endif
+ try_this += suffix;
+ }
+ break;
+ case 4:
+ try_this = dll_name;
+ break;
+ }
+
+ if (try_this.length ())
+ {
+ try_names.size (j + 1);
+ try_names.set (try_this, j);
+ }
+ }
+ return;
+}
+
+/******************************************************************/
+
+// Pointer to the Singleton instance.
+ACE_DLL_Manager *ACE_DLL_Manager::instance_ = 0;
+
+
+ACE_DLL_Manager *
+ACE_DLL_Manager::instance (int size)
+{
+ ACE_TRACE ("ACE_DLL_Manager::instance");
+
+ if (ACE_DLL_Manager::instance_ == 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_DLL_Manager::instance_ == 0)
+ {
+ ACE_NEW_RETURN (ACE_DLL_Manager::instance_,
+ ACE_DLL_Manager (size),
+ 0);
+ }
+ }
+
+ return ACE_DLL_Manager::instance_;
+}
+
+void
+ACE_DLL_Manager::close_singleton (void)
+{
+ ACE_TRACE ("ACE_DLL_Manager::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ delete ACE_DLL_Manager::instance_;
+ ACE_DLL_Manager::instance_ = 0;
+}
+
+ACE_DLL_Manager::ACE_DLL_Manager (int size)
+ : handle_vector_ (0),
+ current_size_ (0),
+ total_size_ (0),
+ unload_policy_ (ACE_DLL_UNLOAD_POLICY_PER_DLL)
+{
+ ACE_TRACE ("ACE_DLL_Manager::ACE_DLL_Manager");
+
+ if (this->open (size) != 0 && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_DLL_Manager ctor failed to allocate ")
+ ACE_TEXT ("handle_vector_.\n")));
+}
+
+ACE_DLL_Manager::~ACE_DLL_Manager (void)
+{
+ ACE_TRACE ("ACE_DLL_Manager::~ACE_DLL_Manager");
+
+ if (this->close () != 0 && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_DLL_Manager dtor failed to close ")
+ ACE_TEXT ("properly.\n")));
+}
+
+ACE_DLL_Handle *
+ACE_DLL_Manager::open_dll (const ACE_TCHAR *dll_name,
+ int open_mode,
+ ACE_SHLIB_HANDLE handle)
+{
+ ACE_TRACE ("ACE_DLL_Manager::open_dll");
+
+ ACE_DLL_Handle *temp_handle = 0;
+ ACE_DLL_Handle *dll_handle = 0;
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+ dll_handle = this->find_dll (dll_name);
+ if (!dll_handle)
+ {
+ if (this->current_size_ < this->total_size_)
+ {
+ ACE_NEW_RETURN (temp_handle,
+ ACE_DLL_Handle,
+ 0);
+
+ dll_handle = temp_handle;
+ }
+ }
+ }
+
+ if (dll_handle)
+ {
+ if (dll_handle->open (dll_name, open_mode, handle) != 0)
+ {
+ // Error while opening dll. Free temp handle
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_DLL_Manager::open_dll: Could not ")
+ ACE_TEXT ("open dll %s.\n"),
+ dll_name));
+
+ delete temp_handle;
+ return 0;
+ }
+
+ // Add the handle to the vector only if the dll is successfully
+ // opened.
+ if (temp_handle != 0)
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+ this->handle_vector_[this->current_size_] = dll_handle;
+ ++this->current_size_;
+ }
+ }
+
+ return dll_handle;
+}
+
+int
+ACE_DLL_Manager::close_dll (const ACE_TCHAR *dll_name)
+{
+ ACE_TRACE ("ACE_DLL_Manager::close_dll");
+ ACE_DLL_Handle *handle = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+ handle = this->find_dll (dll_name);
+ }
+
+ if (handle)
+ {
+ return this->unload_dll (handle, 0);
+ }
+
+ return -1;
+}
+
+u_long
+ACE_DLL_Manager::unload_policy (void) const
+{
+ ACE_TRACE ("ACE_DLL_Manager::unload_policy");
+ return this->unload_policy_;
+}
+
+void
+ACE_DLL_Manager::unload_policy (u_long unload_policy)
+{
+ ACE_TRACE ("ACE_DLL_Manager::unload_policy");
+ ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_));
+
+ u_long old_policy = this->unload_policy_;
+ this->unload_policy_ = unload_policy;
+
+ // If going from LAZY to EAGER or from PER_DLL to PER_PROCESS|EAGER,
+ // call close(1) on all the ACE_DLL_Handle objects with refcount == 0
+ // which will force those that are still loaded to be unloaded.
+ if (this->handle_vector_)
+ if (( ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_LAZY) &&
+ ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) ) ||
+ ( ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) &&
+ ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_PER_DLL) &&
+ ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_PER_DLL) ))
+ {
+ for (int i = this->current_size_ - 1; i >= 0; i--)
+ {
+ if (this->handle_vector_[i] &&
+ this->handle_vector_[i]->refcount () == 0)
+ this->handle_vector_[i]->close (1);
+ }
+ }
+}
+
+int
+ACE_DLL_Manager::open (int size)
+{
+ ACE_TRACE ("ACE_DLL_Manager::open");
+
+ ACE_DLL_Handle **temp = 0;
+
+ ACE_NEW_RETURN (temp,
+ ACE_DLL_Handle *[size],
+ -1);
+
+ this->handle_vector_ = temp;
+ this->total_size_ = size;
+ return 0;
+}
+
+int
+ACE_DLL_Manager::close (void)
+{
+ ACE_TRACE ("ACE_DLL_Manager::close");
+
+ int force_close = 1;
+
+ if (this->handle_vector_ != 0)
+ {
+ // Delete components in reverse order.
+ for (int i = this->current_size_ - 1; i >= 0; i--)
+ {
+ if (this->handle_vector_[i])
+ {
+ ACE_DLL_Handle *s =
+ const_cast<ACE_DLL_Handle *> (this->handle_vector_[i]);
+ this->handle_vector_[i] = 0;
+ this->unload_dll (s, force_close);
+ delete s;
+ }
+ }
+
+ delete [] this->handle_vector_;
+ this->handle_vector_ = 0;
+ this->current_size_ = 0;
+ }
+ return 0;
+}
+
+ACE_DLL_Handle *
+ACE_DLL_Manager::find_dll (const ACE_TCHAR *dll_name) const
+{
+ ACE_TRACE ("ACE_DLL_Manager::find_dll");
+
+ for (int i = 0; i < this->current_size_; i++)
+ if (this->handle_vector_[i] &&
+ ACE_OS::strcmp (this->handle_vector_[i]->dll_name (), dll_name) == 0)
+ {
+ return this->handle_vector_[i];
+ }
+
+ return 0;
+}
+
+int
+ACE_DLL_Manager::unload_dll (ACE_DLL_Handle *dll_handle, int force_unload)
+{
+ ACE_TRACE ("ACE_DLL_Manager::unload_dll");
+
+ if (dll_handle)
+ {
+ int unload = force_unload;
+ if (unload == 0)
+ {
+ // apply strategy
+ if (ACE_BIT_DISABLED (this->unload_policy_,
+ ACE_DLL_UNLOAD_POLICY_PER_DLL))
+ {
+ unload = ACE_BIT_DISABLED (this->unload_policy_,
+ ACE_DLL_UNLOAD_POLICY_LAZY);
+ }
+ else
+ {
+ // Declare the type of the symbol:
+ typedef int (*dll_unload_policy)(void);
+
+ void * const unload_policy_ptr =
+ dll_handle->symbol (ACE_TEXT ("_get_dll_unload_policy"), 1);
+#if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
+ int const temp_p =
+ reinterpret_cast<int> (unload_policy_ptr);
+#else
+ intptr_t const temp_p =
+ reinterpret_cast<intptr_t> (unload_policy_ptr);
+#endif
+
+ dll_unload_policy const the_policy =
+ reinterpret_cast<dll_unload_policy> (temp_p);
+
+ if (the_policy != 0)
+ unload = ACE_BIT_DISABLED (the_policy (),
+ ACE_DLL_UNLOAD_POLICY_LAZY);
+ else
+ unload = ACE_BIT_DISABLED (this->unload_policy_,
+ ACE_DLL_UNLOAD_POLICY_LAZY);
+ }
+ }
+
+ if (dll_handle->close (unload) != 0)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_DLL_Manager::unload error.\n")));
+
+ return -1;
+ }
+ }
+ else
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_DLL_Manager::unload_dll called with ")
+ ACE_TEXT ("null pointer.\n")));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/DLL_Manager.h b/ACE/ace/DLL_Manager.h
new file mode 100644
index 00000000000..a59636696ba
--- /dev/null
+++ b/ACE/ace/DLL_Manager.h
@@ -0,0 +1,269 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file DLL_Manager.h
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@ieee.org>
+ */
+//=============================================================================
+
+#ifndef ACE_DLL_MANAGER_H
+#define ACE_DLL_MANAGER_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Containers_T.h"
+#include "ace/SStringfwd.h"
+#include "ace/os_include/os_dlfcn.h"
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# include "ace/Thread_Mutex.h"
+#endif /* ACE_MT_SAFE */
+
+#define ACE_DEFAULT_DLL_MANAGER_SIZE 1024
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_DLL_Handle
+ *
+ * @brief Provides an abstract interface for handling various DLL
+ * operations.
+ *
+ * This class is an wrapper over the various methods for utilizing a
+ * dynamically linked library (DLL), which is called a shared library
+ * on some platforms. It is refcounted and managed by
+ * ACE_DLL_Manager, so there will only be a single instance of this
+ * class for each dll loaded, no matter how many instances of ACE_DLL
+ * an application has open. Operations <open>, <close>, and <symbol>
+ * have been implemented to help opening/closing and extracting symbol
+ * information from a DLL, respectively.
+ *
+ * Most of this class came from the original ACE_DLL class. ACE_DLL
+ * is now just an interface that passed all it's calls either directly
+ * or via ACE_DLL_Manager to this class for execution.
+ *
+ */
+class ACE_Export ACE_DLL_Handle
+{
+public:
+
+ /// Default construtor.
+ ACE_DLL_Handle (void);
+
+ /// Destructor.
+ ~ACE_DLL_Handle (void);
+
+ /// Returns the name of the shared library (without prefixes or suffixes).
+ const ACE_TCHAR *dll_name () const;
+
+ /**
+ * This method opens and dynamically links @a dll_name. The default
+ * mode is <RTLD_LAZY>, which loads identifier symbols but not the
+ * symbols for functions, which are loaded dynamically on-demand.
+ * Other supported modes include: <RTLD_NOW>, which performs all
+ * necessary relocations when @a dll_name is first loaded and
+ * <RTLD_GLOBAL>, which makes symbols available for relocation
+ * processing of any other DLLs. Returns -1 on failure and 0 on
+ * success.
+ */
+ int open (const ACE_TCHAR *dll_name,
+ int open_mode,
+ ACE_SHLIB_HANDLE handle);
+
+ /// Call to close the DLL object. If unload = 0, it only decrements
+ /// the refcount, but if unload = 1, then it will actually unload
+ /// the library when the refcount == 0;
+ int close (int unload = 0);
+
+ /// Return the current refcount.
+ sig_atomic_t refcount (void) const;
+
+ /// If @a symbol_name is in the symbol table of the DLL a pointer to
+ /// the @a symbol_name is returned. Otherwise, returns 0. Set the
+ /// ignore_errors flag to supress logging errors if symbol_name isn't
+ /// found. This is nice if you just want to probe a dll to see what's
+ /// available, since missing functions in that case aren't really errors.
+ void *symbol (const ACE_TCHAR *symbol_name, int ignore_errors = 0);
+
+ /**
+ * Return the handle to the caller. If @a become_owner is non-0 then
+ * caller assumes ownership of the handle so we decrement the retcount.
+ */
+ ACE_SHLIB_HANDLE get_handle (int become_owner = 0);
+
+private:
+
+ /// Returns a pointer to a string explaining why <symbol> or <open>
+ /// failed. This is used internal to print out the error to the log,
+ /// but since this object is shared, we can't store or return the error
+ /// to the caller.
+ auto_ptr <ACE_TString> error (void);
+
+ // Builds array of DLL names to try to dlopen, based on platform
+ // and configured DLL prefixes/suffixes.
+ // Returns the array of names to try in try_names.
+ void get_dll_names (const ACE_TCHAR *dll_name,
+ ACE_Array<ACE_TString> &try_names);
+
+ // Disallow copying and assignment since we don't handle them.
+ ACE_DLL_Handle (const ACE_DLL_Handle &);
+ void operator= (const ACE_DLL_Handle &);
+
+private:
+
+ // Keep track of how many ACE_DLL objects have a reference to this
+ // dll.
+ sig_atomic_t refcount_;
+
+ /// Name of the shared library.
+ ACE_TCHAR *dll_name_;
+
+ /// Handle to the actual library loaded by the OS.
+ ACE_SHLIB_HANDLE handle_;
+
+ /// Keeps track of whether or not open() has ever been called. This
+ /// helps get around problem on Linux, and perhaps other OS's, that
+ /// seg-fault if dlerror() is called before the ld library has been
+ /// initialized by a call to dlopen().
+ static sig_atomic_t open_called_;
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ /// Synchronization variable for the MT_SAFE Repository
+ ACE_Thread_Mutex lock_;
+#endif /* ACE_MT_SAFE */
+};
+
+class ACE_Framework_Repository;
+
+/**
+ * @class ACE_DLL_Manager
+ *
+ * @brief This class is a singleton and serves as a factory and
+ * repository for instances of ACE_DLL_Handle.
+ *
+ * This class is a singleton whose lifetime is managed by the
+ * ACE_Framework_Repository. Although it is normally meant to be
+ * used directly only by ACE_DLL, applications can call the unload_policy()
+ * methods in order get/set the the dll unload policy. Unload policies include
+ * per_process/per-dll and eager/lazy. Dlls can export set their own policy
+ * by using the ACE_DLL_UNLOAD_POLICY macro found in config-all.h. If a dll
+ * choses to set an unload policy, it will be used when the per-dll policy
+ * (the default) is in effect. If the per-dll policy is in effect and a dll
+ * has not chosen to set a policy, the current per-process policy will be
+ * used.
+ *
+ * The following policy macros are provided in config-all.h:
+ *
+ * ACE_DLL_UNLOAD_POLICY_PER_PROCESS - Per-process policy that unloads dlls
+ * eagerly.
+ *
+ * ACE_DLL_UNLOAD_POLICY_PER_DLL - Apply policy on a per-dll basis. If the
+ * dll doesn't use one of the macros below, the current per-process policy
+ * will be used.
+ *
+ * ACE_DLL_UNLOAD_POLICY_LAZY - Don't unload dll when refcount reaches
+ * zero, i.e., wait for either an explicit unload request or program exit.
+ *
+ * ACE_DLL_UNLOAD_POLICY_DEFAULT - Default policy allows dlls to control
+ * their own destinies, but will unload those that don't make a choice eagerly.
+ *
+ */
+class ACE_Export ACE_DLL_Manager
+{
+public:
+ friend class ACE_Framework_Repository;
+ friend class ACE_Object_Manager;
+
+ enum
+ {
+ DEFAULT_SIZE = ACE_DEFAULT_DLL_MANAGER_SIZE
+ };
+
+ /// Return a unique instance
+ static ACE_DLL_Manager *instance (int size = ACE_DLL_Manager::DEFAULT_SIZE);
+
+ /// Factory for ACE_DLL_Handle objects. If one already exits,
+ /// its refcount is incremented.
+ ACE_DLL_Handle *open_dll (const ACE_TCHAR *dll_name,
+ int openmode,
+ ACE_SHLIB_HANDLE handle);
+
+ /// Close the underlying dll. Decrements the refcount.
+ int close_dll (const ACE_TCHAR *dll_name);
+
+ /// Returns the current per-process UNLOAD_POLICY.
+ u_long unload_policy (void) const;
+
+ /// Set the per-process UNLOAD_POLICY. If the policy is changed from
+ /// LAZY to EAGER, then it will also unload any dlls with zero
+ /// refcounts.
+ void unload_policy (u_long unload_policy);
+
+protected:
+
+ /// Default constructor.
+ ACE_DLL_Manager (int size = ACE_DLL_Manager::DEFAULT_SIZE);
+
+ /// Destructor.
+ ~ACE_DLL_Manager (void);
+
+ // Allocate handle_vector_.
+ int open (int size);
+
+ // Close all open dlls and deallocate memory.
+ int close (void);
+
+ // Find dll in handle_vector_.
+ ACE_DLL_Handle *find_dll (const ACE_TCHAR *dll_name) const;
+
+ // Applies strategy for unloading dll.
+ int unload_dll (ACE_DLL_Handle *dll_handle, int force_unload = 0);
+
+private:
+
+ /// Close the singleton instance.
+ static void close_singleton (void);
+
+ // Disallow copying and assignment since we don't handle these.
+ ACE_DLL_Manager (const ACE_DLL_Manager &);
+ void operator= (const ACE_DLL_Manager &);
+
+private:
+
+ /// Vector containing all loaded handle objects.
+ ACE_DLL_Handle **handle_vector_;
+
+ /// Current number of handles.
+ int current_size_;
+
+ /// Maximum number of handles.
+ int total_size_;
+
+ /// Unload strategy.
+ u_long unload_policy_;
+
+ /// Pointer to a process-wide ACE_DLL_Manager.
+ static ACE_DLL_Manager *instance_;
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ /// Synchronization variable for the MT_SAFE Repository
+ ACE_Thread_Mutex lock_;
+#endif /* ACE_MT_SAFE */
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DLL_MANAGER_H */
diff --git a/ACE/ace/Date_Time.cpp b/ACE/ace/Date_Time.cpp
new file mode 100644
index 00000000000..85abf562c47
--- /dev/null
+++ b/ACE/ace/Date_Time.cpp
@@ -0,0 +1,10 @@
+// Date_Time.cpp
+// $Id$
+
+#include "ace/Date_Time.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Date_Time.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Date_Time, "$Id$")
diff --git a/ACE/ace/Date_Time.h b/ACE/ace/Date_Time.h
new file mode 100644
index 00000000000..9204e23a1b8
--- /dev/null
+++ b/ACE/ace/Date_Time.h
@@ -0,0 +1,125 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Date_Time.h
+ *
+ * $Id$
+ *
+ * @author Tim Harrison (harrison@cs.wustl.edu) (and he's darn proud of this ;-))
+ *
+ */
+//==========================================================================
+
+#ifndef ACE_DATE_TIME_H
+#define ACE_DATE_TIME_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Date_Time
+ *
+ * @brief System independent representation of date and time.
+ */
+class ACE_Export ACE_Date_Time
+{
+public:
+ /// Constructor initializes current time/date info.
+ ACE_Date_Time (void);
+
+ /// Constructor initializes with the given ACE_Time_Value
+ explicit ACE_Date_Time (const ACE_Time_Value& timevalue);
+
+ /// Constructor with init values, no check for validy
+ /// Set/get portions of ACE_Date_Time, no check for validity.
+ ACE_Date_Time (long day,
+ long month = 0,
+ long year = 0,
+ long hour = 0,
+ long minute = 0,
+ long second = 0,
+ long microsec = 0,
+ long wday = 0);
+
+ /// Update to the current time/date.
+ void update (void);
+
+ /// Update to the given ACE_Time_Value
+ void update (const ACE_Time_Value& timevalue);
+
+ /// Get day.
+ long day (void) const;
+
+ /// Set day.
+ void day (long day);
+
+ /// Get month.
+ long month (void) const;
+
+ /// Set month.
+ void month (long month);
+
+ /// Get year.
+ long year (void) const;
+
+ /// Set year.
+ void year (long year);
+
+ /// Get hour.
+ long hour (void) const;
+
+ /// Set hour.
+ void hour (long hour);
+
+ /// Get minute.
+ long minute (void) const;
+
+ /// Set minute.
+ void minute (long minute);
+
+ /// Get second.
+ long second (void) const;
+
+ /// Set second.
+ void second (long second);
+
+ /// Get microsec.
+ long microsec (void) const;
+
+ /// Set microsec.
+ void microsec (long microsec);
+
+ /// Get weekday.
+ long weekday (void) const;
+
+ /// Set weekday.
+ void weekday (long wday);
+
+private:
+ long day_;
+ long month_;
+ long year_;
+ long hour_;
+ long minute_;
+ long second_;
+ long microsec_;
+ long wday_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Date_Time.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DATE_TIME_H */
diff --git a/ACE/ace/Date_Time.inl b/ACE/ace/Date_Time.inl
new file mode 100644
index 00000000000..dfb0d239bc3
--- /dev/null
+++ b/ACE/ace/Date_Time.inl
@@ -0,0 +1,219 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_time.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_Date_Time::update (const ACE_Time_Value& timevalue)
+{
+#if defined (ACE_HAS_WINCE)
+ // CE doesn't do localtime().
+ FILETIME file_time = timevalue;
+ FILETIME local_file_time;
+ SYSTEMTIME sys_time;
+ ::FileTimeToLocalFileTime (&file_time, &local_file_time);
+ ::FileTimeToSystemTime (&local_file_time, &sys_time);
+ this->day_ = sys_time.wDay;
+ this->month_ = sys_time.wMonth;
+ this->year_ = sys_time.wYear;
+ this->hour_ = sys_time.wHour;
+ this->minute_ = sys_time.wMinute;
+ this->second_ = sys_time.wSecond;
+ this->microsec_ = sys_time.wMilliseconds * 1000;
+ this->wday_ = sys_time.wDayOfWeek;
+#else
+ time_t time = timevalue.sec ();
+ struct tm tm_time;
+ ACE_OS::localtime_r (&time, &tm_time);
+ this->day_ = tm_time.tm_mday;
+ this->month_ = tm_time.tm_mon + 1; // localtime's months are 0-11
+ this->year_ = tm_time.tm_year + 1900; // localtime reports years since 1900
+ this->hour_ = tm_time.tm_hour;
+ this->minute_ = tm_time.tm_min;
+ this->second_ = tm_time.tm_sec;
+ this->microsec_ = timevalue.usec ();
+ this->wday_ = tm_time.tm_wday;
+#endif /* ACE_HAS_WINCE */
+}
+
+ACE_INLINE void
+ACE_Date_Time::update (void)
+{
+ ACE_TRACE ("ACE_Date_Time::update");
+
+ update(ACE_OS::gettimeofday ());
+}
+
+ACE_INLINE
+ACE_Date_Time::ACE_Date_Time (void)
+{
+ ACE_TRACE ("ACE_Date_Time::ACE_Date_Time");
+ this->update ();
+}
+
+ACE_INLINE
+ACE_Date_Time::ACE_Date_Time (const ACE_Time_Value& timevalue)
+{
+ ACE_TRACE ("ACE_Date_Time::ACE_Date_Time: timevalue");
+ this->update (timevalue);
+}
+
+// Constructor with init values, no check for validy
+ACE_INLINE
+ACE_Date_Time::ACE_Date_Time (long day,
+ long month,
+ long year,
+ long hour,
+ long minute,
+ long second,
+ long microsec,
+ long wday)
+ : day_ (day),
+ month_ (month),
+ year_ (year),
+ hour_ (hour),
+ minute_ (minute),
+ second_ (second),
+ microsec_ (microsec),
+ wday_ (wday)
+{
+ ACE_TRACE ("ACE_Date_Time::ACE_Date_Time");
+}
+
+// set/get portions of ACE_Date_Time, no check for validy
+
+// get day
+ACE_INLINE long
+ACE_Date_Time::day (void) const
+{
+ ACE_TRACE ("ACE_Date_Time::day");
+ return day_;
+}
+
+// set day
+ACE_INLINE void
+ACE_Date_Time::day (long day)
+{
+ ACE_TRACE ("ACE_Date_Time::day");
+ day_ = day;
+}
+
+// get month
+ACE_INLINE long
+ACE_Date_Time::month (void) const
+{
+ ACE_TRACE ("ACE_Date_Time::month");
+ return month_;
+}
+
+// set month
+ACE_INLINE void
+ACE_Date_Time::month (long month)
+{
+ ACE_TRACE ("ACE_Date_Time::month");
+ month_ = month;
+}
+
+// get year
+ACE_INLINE long
+ACE_Date_Time::year (void) const
+{
+ ACE_TRACE ("ACE_Date_Time::year");
+ return year_;
+}
+
+// set year
+ACE_INLINE void
+ACE_Date_Time::year (long year)
+{
+ ACE_TRACE ("ACE_Date_Time::year");
+ year_ = year;
+}
+
+// get hour
+ACE_INLINE long
+ACE_Date_Time::hour (void) const
+{
+ ACE_TRACE ("ACE_Date_Time::hour");
+ return hour_;
+}
+
+// set hour
+ACE_INLINE void
+ACE_Date_Time::hour (long hour)
+{
+ ACE_TRACE ("ACE_Date_Time::hour");
+ hour_ = hour;
+}
+
+// get minute
+ACE_INLINE long
+ACE_Date_Time::minute (void) const
+{
+ ACE_TRACE ("ACE_Date_Time::minute");
+ return minute_;
+}
+
+// set minute
+ACE_INLINE void
+ACE_Date_Time::minute (long minute)
+{
+ ACE_TRACE ("ACE_Date_Time::minute");
+ minute_ = minute;
+}
+
+// get second
+ACE_INLINE long
+ACE_Date_Time::second (void) const
+{
+ ACE_TRACE ("ACE_Date_Time::second");
+ return second_;
+}
+
+// set second
+ACE_INLINE void
+ACE_Date_Time::second (long second)
+{
+ ACE_TRACE ("ACE_Date_Time::second");
+ second_ = second;
+}
+
+// get microsec
+ACE_INLINE long
+ACE_Date_Time::microsec (void) const
+{
+ ACE_TRACE ("ACE_Date_Time::microsec");
+ return microsec_;
+}
+
+// set microsec
+ACE_INLINE void
+ACE_Date_Time::microsec (long microsec)
+{
+ ACE_TRACE ("ACE_Date_Time::microsec");
+ microsec_ = microsec;
+}
+
+// get wday
+ACE_INLINE long
+ACE_Date_Time::weekday (void) const
+{
+ ACE_TRACE ("ACE_Date_Time::weekday");
+ return wday_;
+}
+
+// set wday
+ACE_INLINE void
+ACE_Date_Time::weekday (long wday)
+{
+ ACE_TRACE ("ACE_Date_Time::weekday");
+ wday_ = wday;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Default_Constants.h b/ACE/ace/Default_Constants.h
new file mode 100644
index 00000000000..ce435121681
--- /dev/null
+++ b/ACE/ace/Default_Constants.h
@@ -0,0 +1,573 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Default_Constants.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * This one is split from the famous OS.h
+ */
+//=============================================================================
+
+#ifndef ACE_DEFAULT_CONSTANTS_H
+#define ACE_DEFAULT_CONSTANTS_H
+#include /**/ "ace/pre.h"
+
+// Included just keep compilers that see #pragma dierctive first
+// happy.
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Define the default constants for ACE. Many of these are used for
+// the ACE tests and applications. You can change these values by
+// defining the macros in your config.h file.
+# if !defined (ACE_DEFAULT_CLOSE_ALL_HANDLES)
+# define ACE_DEFAULT_CLOSE_ALL_HANDLES true
+# endif /* ACE_DEFAULT_CLOSE_ALL_HANDLES */
+
+// The maximum length for a fully qualified Internet name.
+# if !defined(ACE_MAX_FULLY_QUALIFIED_NAME_LEN)
+# define ACE_MAX_FULLY_QUALIFIED_NAME_LEN 256
+# endif /* ACE_MAX_FULLY_QUALIFIED_NAME_LEN */
+
+#if !defined (ACE_DEFAULT_PAGEFILE_POOL_BASE)
+#define ACE_DEFAULT_PAGEFILE_POOL_BASE (void *) 0
+#endif /* ACE_DEFAULT_PAGEFILE_POOL_BASE */
+
+#if !defined (ACE_DEFAULT_PAGEFILE_POOL_SIZE)
+#define ACE_DEFAULT_PAGEFILE_POOL_SIZE (size_t) 0x01000000
+#endif /* ACE_DEFAULT_PAGEFILE_POOL_SIZE */
+
+#if !defined (ACE_DEFAULT_PAGEFILE_POOL_CHUNK)
+#define ACE_DEFAULT_PAGEFILE_POOL_CHUNK (size_t) 0x00010000
+#endif /* ACE_DEFAULT_PAGEFILE_POOL_CHUNK */
+
+#if !defined (ACE_DEFAULT_PAGEFILE_POOL_NAME)
+#define ACE_DEFAULT_PAGEFILE_POOL_NAME ACE_TEXT ("Default_ACE_Pagefile_Memory_Pool")
+#endif /* ACE_DEFAULT_PAGEFILE_POOL_NAME */
+
+#if !defined (ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY)
+#define ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY 0
+#endif /* ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY */
+
+#if !defined (ACE_DEFAULT_SERVICE_REPOSITORY_SIZE)
+#define ACE_DEFAULT_SERVICE_REPOSITORY_SIZE 1024
+#endif /* ACE_DEFAULT_SERVICE_REPOSITORY_SIZE */
+
+#if !defined (ACE_REACTOR_NOTIFICATION_ARRAY_SIZE)
+#define ACE_REACTOR_NOTIFICATION_ARRAY_SIZE 1024
+#endif /* ACE_REACTOR_NOTIFICATION_ARRAY_SIZE */
+
+# if !defined (ACE_DEFAULT_TIMEOUT)
+# define ACE_DEFAULT_TIMEOUT 5
+# endif /* ACE_DEFAULT_TIMEOUT */
+
+# if !defined (ACE_DEFAULT_BACKLOG)
+# define ACE_DEFAULT_BACKLOG 5
+# endif /* ACE_DEFAULT_BACKLOG */
+
+# if !defined (ACE_DEFAULT_ASYNCH_BACKLOG)
+# define ACE_DEFAULT_ASYNCH_BACKLOG 5
+# endif /* ACE_DEFAULT_ASYNCH_BACKLOG */
+
+# if !defined (ACE_DEFAULT_THREADS)
+# define ACE_DEFAULT_THREADS 1
+# endif /* ACE_DEFAULT_THREADS */
+
+// The following 3 defines are used in the IP multicast and broadcast tests.
+# if !defined (ACE_DEFAULT_BROADCAST_PORT)
+# define ACE_DEFAULT_BROADCAST_PORT 20000
+# endif /* ACE_DEFAULT_BROADCAST_PORT */
+
+# if !defined (ACE_DEFAULT_MULTICAST_PORT)
+# define ACE_DEFAULT_MULTICAST_PORT 20001
+# endif /* ACE_DEFAULT_MULTICAST_PORT */
+
+# if !defined (ACE_DEFAULT_MULTICAST_ADDR)
+// This address MUST be within the range for host group addresses:
+// 224.0.0.0 to 239.255.255.255.
+# define ACE_DEFAULT_MULTICAST_ADDR "224.9.9.2"
+# endif /* ACE_DEFAULT_MULTICAST_ADDR */
+
+# if defined (ACE_HAS_IPV6)
+# if !defined (ACE_DEFAULT_MULTICASTV6_ADDR)
+// This address should be within the range for site-local addresses:
+// ff05::0/16 .
+# define ACE_DEFAULT_MULTICASTV6_ADDR "ff05:0::ff01:1"
+# endif /* ACE_DEFAULT_MULTICASTV6_ADDR */
+# endif
+
+// Default port number for HTTP.
+# if !defined (ACE_DEFAULT_HTTP_SERVER_PORT)
+# define ACE_DEFAULT_HTTP_SERVER_PORT 80
+# endif /* ACE_DEFAULT_HTTP_SERVER_PORT */
+
+// Used in many IPC_SAP tests
+# if !defined (ACE_DEFAULT_SERVER_PORT)
+# define ACE_DEFAULT_SERVER_PORT 20002
+# endif /* ACE_DEFAULT_SERVER_PORT */
+
+# if !defined (ACE_DEFAULT_HTTP_PORT)
+# define ACE_DEFAULT_HTTP_PORT 80
+# endif /* ACE_DEFAULT_HTTP_PORT */
+
+# if !defined (ACE_DEFAULT_MAX_SOCKET_BUFSIZ)
+# define ACE_DEFAULT_MAX_SOCKET_BUFSIZ 65536
+# endif /* ACE_DEFAULT_MAX_SOCKET_BUFSIZ */
+
+# if !defined (ACE_DEFAULT_SERVER_PORT_STR)
+# define ACE_DEFAULT_SERVER_PORT_STR ACE_TEXT("20002")
+# endif /* ACE_DEFAULT_SERVER_PORT_STR */
+
+// Used for the Service_Directory test
+# if !defined (ACE_DEFAULT_SERVICE_PORT)
+# define ACE_DEFAULT_SERVICE_PORT 20003
+# endif /* ACE_DEFAULT_SERVICE_PORT */
+
+// Used for the ACE_Thread_Spawn test
+# if !defined (ACE_DEFAULT_THR_PORT )
+# define ACE_DEFAULT_THR_PORT 20004
+# endif /* ACE_DEFAULT_THR_PORT */
+
+// Used for <SOCK_Connect::connect> tests
+# if !defined (ACE_DEFAULT_LOCAL_PORT)
+# define ACE_DEFAULT_LOCAL_PORT 20005
+# endif /* ACE_DEFAULT_LOCAL_PORT */
+
+// Used for Connector tests
+# if !defined (ACE_DEFAULT_LOCAL_PORT_STR)
+# define ACE_DEFAULT_LOCAL_PORT_STR "20005"
+# endif /* ACE_DEFAULT_LOCAL_PORT_STR */
+
+// Used for the name server.
+# if !defined (ACE_DEFAULT_NAME_SERVER_PORT)
+# define ACE_DEFAULT_NAME_SERVER_PORT 20006
+# endif /* ACE_DEFAULT_NAME_SERVER_PORT */
+
+# if !defined (ACE_DEFAULT_NAME_SERVER_PORT_STR)
+# define ACE_DEFAULT_NAME_SERVER_PORT_STR "20006"
+# endif /* ACE_DEFAULT_NAME_SERVER_PORT_STR */
+
+// Used for the token server.
+# if !defined (ACE_DEFAULT_TOKEN_SERVER_PORT)
+# define ACE_DEFAULT_TOKEN_SERVER_PORT 20007
+# endif /* ACE_DEFAULT_TOKEN_SERVER_PORT */
+
+# if !defined (ACE_DEFAULT_TOKEN_SERVER_PORT_STR)
+# define ACE_DEFAULT_TOKEN_SERVER_PORT_STR "20007"
+# endif /* ACE_DEFAULT_TOKEN_SERVER_PORT_STR */
+
+// Used for the logging server.
+# if !defined (ACE_DEFAULT_LOGGING_SERVER_PORT)
+# define ACE_DEFAULT_LOGGING_SERVER_PORT 20008
+# endif /* ACE_DEFAULT_LOGGING_SERVER_PORT */
+
+# if !defined (ACE_DEFAULT_LOGGING_SERVER_PORT_STR)
+# define ACE_DEFAULT_LOGGING_SERVER_PORT_STR "20008"
+# endif /* ACE_DEFAULT_LOGGING_SERVER_PORT_STR */
+
+// Used for the logging server.
+# if !defined (ACE_DEFAULT_THR_LOGGING_SERVER_PORT)
+# define ACE_DEFAULT_THR_LOGGING_SERVER_PORT 20008
+# endif /* ACE_DEFAULT_THR_LOGGING_SERVER_PORT */
+
+# if !defined (ACE_DEFAULT_THR_LOGGING_SERVER_PORT_STR)
+# define ACE_DEFAULT_THR_LOGGING_SERVER_PORT_STR "20008"
+# endif /* ACE_DEFAULT_THR_LOGGING_SERVER_PORT_STR */
+
+// Used for the time server.
+# if !defined (ACE_DEFAULT_TIME_SERVER_PORT)
+# define ACE_DEFAULT_TIME_SERVER_PORT 20009
+# endif /* ACE_DEFAULT_TIME_SERVER_PORT */
+
+# if !defined (ACE_DEFAULT_TIME_SERVER_PORT_STR)
+# define ACE_DEFAULT_TIME_SERVER_PORT_STR "20009"
+# endif /* ACE_DEFAULT_TIME_SERVER_PORT_STR */
+
+# if !defined (ACE_DEFAULT_TIME_SERVER_STR)
+# define ACE_DEFAULT_TIME_SERVER_STR "ACE_TS_TIME"
+# endif /* ACE_DEFAULT_TIME_SERVER_STR */
+
+// Used by the FIFO tests and the Client_Logging_Handler netsvc.
+# if !defined (ACE_DEFAULT_RENDEZVOUS)
+# if defined (ACE_HAS_STREAM_PIPES)
+# define ACE_DEFAULT_RENDEZVOUS ACE_TEXT("/tmp/fifo.ace")
+# else
+# define ACE_DEFAULT_RENDEZVOUS ACE_TEXT("localhost:20010")
+# endif /* ACE_HAS_STREAM_PIPES */
+# endif /* ACE_DEFAULT_RENDEZVOUS */
+
+// Used for the UNIX syslog logging interface to ACE_Log_Msg.
+# ifndef ACE_DEFAULT_SYSLOG_FACILITY
+# define ACE_DEFAULT_SYSLOG_FACILITY LOG_USER
+# endif /* ACE_DEFAULT_SYSLOG_FACILITY */
+
+# if !defined (ACE_DEFAULT_LOGGER_KEY)
+
+# if defined (ACE_HAS_STREAM_PIPES)
+# define ACE_DEFAULT_LOGGER_KEY ACE_TEXT ("/tmp/server_daemon")
+# else
+# define ACE_DEFAULT_LOGGER_KEY ACE_TEXT ("localhost:20012")
+# endif /* ACE_HAS_STREAM_PIPES */
+# endif /* ACE_DEFAULT_LOGGER_KEY */
+
+// The way to specify the local host for loopback IP. This is usually
+// "localhost" but it may need changing on some platforms.
+# if !defined (ACE_LOCALHOST)
+# define ACE_LOCALHOST ACE_TEXT ("localhost")
+# endif
+
+// This specification for an IPv6 localhost should work on all platforms
+// supporting IPv6
+# if defined (ACE_HAS_IPV6)
+# if !defined (ACE_IPV6_LOCALHOST)
+# define ACE_IPV6_LOCALHOST ACE_TEXT ("::1")
+# endif /* ACE_IPV6_LOCALHOST*/
+#endif /* ACE_HAS_IPV6 */
+
+// This specification for an IPv6 ANY address should work on all platforms
+// supporting IPv6
+# if defined (ACE_HAS_IPV6)
+# if !defined (ACE_IPV6_ANY)
+# define ACE_IPV6_ANY ACE_TEXT ("::")
+# endif /* ACE_IPV6_ANY*/
+#endif /* ACE_HAS_IPV6 */
+
+# if !defined (ACE_DEFAULT_SERVER_HOST)
+# if defined (ACE_HAS_IPV6)
+# define ACE_DEFAULT_SERVER_HOST ACE_IPV6_LOCALHOST
+# else /*ACE_HAS_IPV6*/
+# define ACE_DEFAULT_SERVER_HOST ACE_LOCALHOST
+# endif /*ACE_HAS_IPV6*/
+# endif /* ACE_DEFAULT_SERVER_HOST */
+
+// Default shared memory key
+# if !defined (ACE_DEFAULT_SHM_KEY)
+# define ACE_DEFAULT_SHM_KEY 1234
+# endif /* ACE_DEFAULT_SHM_KEY */
+
+// Default address for shared memory mapped files and SYSV shared memory
+// (defaults to 64 M).
+# if !defined (ACE_DEFAULT_BASE_ADDR)
+# define ACE_DEFAULT_BASE_ADDR ((char *) (64 * 1024 * 1024))
+# endif /* ACE_DEFAULT_BASE_ADDR */
+
+// Default segment size used by SYSV shared memory (128 K)
+# if !defined (ACE_DEFAULT_SEGMENT_SIZE)
+# define ACE_DEFAULT_SEGMENT_SIZE 1024 * 128
+# endif /* ACE_DEFAULT_SEGMENT_SIZE */
+
+// Maximum number of SYSV shared memory segments
+// (does anyone know how to figure out the right values?!)
+# if !defined (ACE_DEFAULT_MAX_SEGMENTS)
+# define ACE_DEFAULT_MAX_SEGMENTS 6
+# endif /* ACE_DEFAULT_MAX_SEGMENTS */
+
+// Name of the map that's stored in shared memory.
+# if !defined (ACE_NAME_SERVER_MAP)
+# define ACE_NAME_SERVER_MAP "Name Server Map"
+# endif /* ACE_NAME_SERVER_MAP */
+
+// Default file permissions.
+# if !defined (ACE_DEFAULT_FILE_PERMS)
+# if defined (ACE_VXWORKS)
+# define ACE_DEFAULT_FILE_PERMS (S_IRUSR | S_IWUSR| S_IRGRP| S_IROTH)
+# else
+# define ACE_DEFAULT_FILE_PERMS 0644
+# endif /* ACE_VXWORKS */
+# endif /* ACE_DEFAULT_FILE_PERMS */
+
+// Default directory permissions.
+# if !defined (ACE_DEFAULT_DIR_PERMS)
+# define ACE_DEFAULT_DIR_PERMS 0755
+# endif /* ACE_DEFAULT_DIR_PERMS */
+
+# if !defined (ACE_DEFAULT_TIMEPROBE_TABLE_SIZE)
+# define ACE_DEFAULT_TIMEPROBE_TABLE_SIZE 8 * 1024
+# endif /* ACE_DEFAULT_TIMEPROBE_TABLE_SIZE */
+
+// Default size of the ACE Map_Manager.
+# if !defined (ACE_DEFAULT_MAP_SIZE)
+# define ACE_DEFAULT_MAP_SIZE 1024
+# endif /* ACE_DEFAULT_MAP_SIZE */
+
+// Defaults for ACE Timer Wheel
+# if !defined (ACE_DEFAULT_TIMER_WHEEL_SIZE)
+# define ACE_DEFAULT_TIMER_WHEEL_SIZE 1024
+# endif /* ACE_DEFAULT_TIMER_WHEEL_SIZE */
+
+# if !defined (ACE_DEFAULT_TIMER_WHEEL_RESOLUTION)
+# define ACE_DEFAULT_TIMER_WHEEL_RESOLUTION 100
+# endif /* ACE_DEFAULT_TIMER_WHEEL_RESOLUTION */
+
+// Default size for ACE Timer Hash table
+# if !defined (ACE_DEFAULT_TIMER_HASH_TABLE_SIZE)
+# define ACE_DEFAULT_TIMER_HASH_TABLE_SIZE 1024
+# endif /* ACE_DEFAULT_TIMER_HASH_TABLE_SIZE */
+
+// Defaults for the ACE Free List
+# if !defined (ACE_DEFAULT_FREE_LIST_PREALLOC)
+# define ACE_DEFAULT_FREE_LIST_PREALLOC 0
+# endif /* ACE_DEFAULT_FREE_LIST_PREALLOC */
+
+# if !defined (ACE_DEFAULT_FREE_LIST_LWM)
+# define ACE_DEFAULT_FREE_LIST_LWM 0
+# endif /* ACE_DEFAULT_FREE_LIST_LWM */
+
+# if !defined (ACE_DEFAULT_FREE_LIST_HWM)
+# define ACE_DEFAULT_FREE_LIST_HWM 25000
+# endif /* ACE_DEFAULT_FREE_LIST_HWM */
+
+# if !defined (ACE_DEFAULT_FREE_LIST_INC)
+# define ACE_DEFAULT_FREE_LIST_INC 100
+# endif /* ACE_DEFAULT_FREE_LIST_INC */
+
+# if !defined (ACE_UNIQUE_NAME_LEN)
+# define ACE_UNIQUE_NAME_LEN 100
+# endif /* ACE_UNIQUE_NAME_LEN */
+
+# if !defined (ACE_MAX_DGRAM_SIZE)
+ // This is just a guess. 8k is the normal limit on
+ // most machines because that's what NFS expects.
+# define ACE_MAX_DGRAM_SIZE 8192
+# endif /* ACE_MAX_DGRAM_SIZE */
+
+# if !defined (ACE_DEFAULT_ARGV_BUFSIZ)
+# define ACE_DEFAULT_ARGV_BUFSIZ 1024 * 4
+# endif /* ACE_DEFAULT_ARGV_BUFSIZ */
+
+// A free list which create more elements when there aren't enough
+// elements.
+# define ACE_FREE_LIST_WITH_POOL 1
+
+// A simple free list which doen't allocate/deallocate elements.
+# define ACE_PURE_FREE_LIST 2
+
+# if defined (ACE_WIN32)
+
+// This is necessary to work around bugs with Win32 non-blocking
+// connects...
+# if !defined (ACE_NON_BLOCKING_BUG_DELAY)
+# define ACE_NON_BLOCKING_BUG_DELAY 35000
+# endif /* ACE_NON_BLOCKING_BUG_DELAY */
+# endif /*ACE_WIN32*/
+
+// Max size of an ACE Log Record data buffer. This can be reset in
+// the config.h file if you'd like to increase or decrease the size.
+# if !defined (ACE_MAXLOGMSGLEN)
+# define ACE_MAXLOGMSGLEN 4 * 1024
+# endif /* ACE_MAXLOGMSGLEN */
+
+// Max size of an ACE Token.
+# define ACE_MAXTOKENNAMELEN 40
+
+// Max size of an ACE Token client ID.
+# define ACE_MAXCLIENTIDLEN MAXHOSTNAMELEN + 20
+
+/// Max udp packet size
+#if !defined (ACE_MAX_UDP_PACKET_SIZE)
+#define ACE_MAX_UDP_PACKET_SIZE 65536
+#endif
+
+/**
+ * @name Default values to control CDR classes memory allocation strategies
+ */
+//@{
+
+/// Control the initial size of all CDR buffers, application
+/// developers may want to optimize this value to fit their request
+/// size
+#if !defined (ACE_DEFAULT_CDR_BUFSIZE)
+# define ACE_DEFAULT_CDR_BUFSIZE 512
+#endif /* ACE_DEFAULT_CDR_BUFSIZE */
+
+#if (ACE_DEFAULT_CDR_BUFSIZE == 0)
+# error: ACE_DEFAULT_CDR_BUFSIZE should be bigger then 0
+#endif
+
+/// Stop exponential growth of CDR buffers to avoid overallocation
+#if !defined (ACE_DEFAULT_CDR_EXP_GROWTH_MAX)
+# define ACE_DEFAULT_CDR_EXP_GROWTH_MAX 65536
+#endif /* ACE_DEFAULT_CDR_EXP_GROWTH_MAX */
+
+/// Control CDR buffer growth after maximum exponential growth is
+/// reached
+#if !defined (ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK)
+# define ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK 65536
+#endif /* ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK */
+//@}
+
+/// Control the zero-copy optimizations for octet sequences
+/**
+ * Large octet sequences can be sent without any copies by chaining
+ * them in the list of message blocks that represent a single CDR
+ * stream. However, if the octet sequence is too small the zero copy
+ * optimizations actually hurt performance. Octet sequences smaller
+ * than this value will be copied.
+ */
+#if !defined (ACE_DEFAULT_CDR_MEMCPY_TRADEOFF)
+#define ACE_DEFAULT_CDR_MEMCPY_TRADEOFF 256
+#endif /* ACE_DEFAULT_CDR_MEMCPY_TRADEOFF */
+
+#if defined (ACE_WIN32)
+ // Define the pathname separator characters for Win32 (ugh).
+# define ACE_DIRECTORY_SEPARATOR_STR_A "\\"
+# define ACE_DIRECTORY_SEPARATOR_CHAR_A '\\'
+#else
+ // Define the pathname separator characters for UNIX.
+# define ACE_DIRECTORY_SEPARATOR_STR_A "/"
+# define ACE_DIRECTORY_SEPARATOR_CHAR_A '/'
+#endif /* ACE_WIN32 */
+
+// Define the Wide character and normal versions of some of the string macros
+#if defined (ACE_HAS_WCHAR)
+# define ACE_DIRECTORY_SEPARATOR_STR_W ACE_TEXT_WIDE(ACE_DIRECTORY_SEPARATOR_STR_A)
+# define ACE_DIRECTORY_SEPARATOR_CHAR_W ACE_TEXT_WIDE(ACE_DIRECTORY_SEPARATOR_CHAR_A)
+#endif /* ACE_HAS_WCHAR */
+
+#define ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT (ACE_DIRECTORY_SEPARATOR_STR_A)
+#define ACE_DIRECTORY_SEPARATOR_CHAR ACE_TEXT (ACE_DIRECTORY_SEPARATOR_CHAR_A)
+
+#if !defined (ACE_DEFAULT_THREAD_PRIORITY)
+# define ACE_DEFAULT_THREAD_PRIORITY (-0x7fffffffL - 1L)
+#endif /* ACE_DEFAULT_THREAD_PRIORITY */
+
+#if !defined (ACE_DEFAULT_THREAD_STACKSIZE)
+# define ACE_DEFAULT_THREAD_STACKSIZE 0
+#endif /* ACE_DEFAULT_THREAD_STACKSIZE */
+
+#if !defined (ACE_MAX_DEFAULT_PORT)
+# define ACE_MAX_DEFAULT_PORT 65535
+#endif /* ACE_MAX_DEFAULT_PORT */
+
+// Default number of ACE_Event_Handlers supported by
+// ACE_Timer_Heap.
+# if !defined (ACE_DEFAULT_TIMERS)
+# define ACE_DEFAULT_TIMERS _POSIX_TIMER_MAX
+# endif /* ACE_DEFAULT_TIMERS */
+
+#if defined (ACE_WIN32)
+# define ACE_PLATFORM_A "Win32"
+# define ACE_PLATFORM_EXE_SUFFIX_A ".exe"
+#elif defined (ACE_VXWORKS)
+# define ACE_PLATFORM_A "VxWorks"
+# if defined (__RTP__)
+# define ACE_PLATFORM_EXE_SUFFIX_A ".vxe"
+# else
+# define ACE_PLATFORM_EXE_SUFFIX_A ".out"
+# endif
+#else /* !ACE_WIN32 && !ACE_VXWORKS */
+# define ACE_PLATFORM_A "UNIX"
+# define ACE_PLATFORM_EXE_SUFFIX_A ""
+#endif /* ACE_WIN32 */
+
+// Define the Wide character and normal versions of some of the string macros
+#if defined (ACE_HAS_WCHAR)
+# define ACE_PLATFORM_W ACE_TEXT_WIDE(ACE_PLATFORM_A)
+# define ACE_PLATFORM_EXE_SUFFIX_W ACE_TEXT_WIDE(ACE_PLATFORM_EXE_SUFFIX_A)
+#endif /* ACE_HAS_WCHAR */
+
+#define ACE_PLATFORM ACE_TEXT (ACE_PLATFORM_A)
+#define ACE_PLATFORM_EXE_SUFFIX ACE_TEXT (ACE_PLATFORM_EXE_SUFFIX_A)
+
+#if defined (ACE_WIN32)
+# define ACE_LD_SEARCH_PATH ACE_TEXT ("PATH")
+# define ACE_LD_SEARCH_PATH_SEPARATOR_STR ACE_TEXT (";")
+# define ACE_DLL_SUFFIX ACE_TEXT (".dll")
+# if defined (__MINGW32__)
+# define ACE_DLL_PREFIX ACE_TEXT ("lib")
+# else /* __MINGW32__ */
+# define ACE_DLL_PREFIX ACE_TEXT ("")
+# endif /* __MINGW32__ */
+#else /* !ACE_WIN32 */
+# if !defined (ACE_LD_SEARCH_PATH)
+# define ACE_LD_SEARCH_PATH ACE_TEXT ("LD_LIBRARY_PATH")
+# endif /* ACE_LD_SEARCH_PATH */
+# if !defined (ACE_LD_SEARCH_PATH_SEPARATOR_STR)
+# define ACE_LD_SEARCH_PATH_SEPARATOR_STR ACE_TEXT (":")
+# endif /* ACE_LD_SEARCH_PATH_SEPARATOR_STR */
+#endif /* ACE_WIN32 */
+
+#if !defined (ACE_DLL_SUFFIX)
+# define ACE_DLL_SUFFIX ACE_TEXT (".so")
+#endif /* ACE_DLL_SUFFIX */
+
+#if !defined (ACE_DLL_PREFIX)
+# define ACE_DLL_PREFIX ACE_TEXT ("lib")
+#endif /* ACE_DLL_PREFIX */
+
+#if defined (ACE_WIN32)
+// Used for dynamic linking
+# if !defined (ACE_DEFAULT_SVC_CONF)
+# if (ACE_USES_CLASSIC_SVC_CONF == 1)
+# define ACE_DEFAULT_SVC_CONF ACE_TEXT (".\\svc.conf")
+# else
+# define ACE_DEFAULT_SVC_CONF ACE_TEXT (".\\svc.conf.xml")
+# endif /* ACE_USES_CLASSIC_SVC_CONF ==1 */
+# endif /* ACE_DEFAULT_SVC_CONF */
+#endif /* ACE_WIN32 */
+
+ // Used for dynamic linking.
+#if !defined (ACE_DEFAULT_SVC_CONF)
+# if (ACE_USES_CLASSIC_SVC_CONF == 1)
+# define ACE_DEFAULT_SVC_CONF ACE_TEXT ("./svc.conf")
+# else
+# define ACE_DEFAULT_SVC_CONF ACE_TEXT ("./svc.conf.xml")
+# endif /* ACE_USES_CLASSIC_SVC_CONF ==1 */
+#endif /* ACE_DEFAULT_SVC_CONF */
+
+#if !defined (ACE_LOGGER_KEY)
+# define ACE_LOGGER_KEY ACE_TEXT ("/tmp/server_daemon")
+#endif /* ACE_LOGGER_KEY */
+
+// Theses defines are used by the ACE Name Server.
+#if !defined (ACE_DEFAULT_LOCALNAME_A)
+# define ACE_DEFAULT_LOCALNAME_A "localnames"
+#endif /* ACE_DEFAULT_LOCALNAME_A */
+#if !defined (ACE_DEFAULT_GLOBALNAME_A)
+# define ACE_DEFAULT_GLOBALNAME_A "globalnames"
+#endif /* ACE_DEFAULT_GLOBALNAME_A */
+
+// ACE_DEFAULT_NAMESPACE_DIR is for legacy mode apps. A better
+// way of doing this is something like ACE_Lib_Find::get_temp_dir, since
+// this directory may not exist
+#if defined (ACE_LEGACY_MODE)
+# if defined (ACE_WIN32)
+# define ACE_DEFAULT_NAMESPACE_DIR_A "C:\\temp"
+# else /* ACE_WIN32 */
+# define ACE_DEFAULT_NAMESPACE_DIR_A "/tmp"
+# endif /* ACE_WIN32 */
+# if defined (ACE_HAS_WCHAR)
+# define ACE_DEFAULT_NAMESPACE_DIR_W ACE_TEXT_WIDE(ACE_DEFAULT_NAMESPACE_DIR_A)
+# endif /* ACE_HAS_WCHAR */
+# define ACE_DEFAULT_NAMESPACE_DIR ACE_TEXT(ACE_DEFAULT_NAMESPACE_DIR_A)
+#endif /* ACE_LEGACY_MODE */
+
+#if defined (ACE_HAS_WCHAR)
+# define ACE_DEFAULT_LOCALNAME_W ACE_TEXT_WIDE(ACE_DEFAULT_LOCALNAME_A)
+# define ACE_DEFAULT_GLOBALNAME_W ACE_TEXT_WIDE(ACE_DEFAULT_GLOBALNAME_A)
+#endif /* ACE_HAS_WCHAR */
+
+#define ACE_DEFAULT_LOCALNAME ACE_TEXT (ACE_DEFAULT_LOCALNAME_A)
+#define ACE_DEFAULT_GLOBALNAME ACE_TEXT (ACE_DEFAULT_GLOBALNAME_A)
+
+# if defined (ACE_WIN32)
+ // The "null" device on Win32.
+# define ACE_DEV_NULL "nul"
+# define ACE_SYSCALL_FAILED 0xFFFFFFFF
+# else /* !ACE_WIN32 */
+ // The "null" device on UNIX.
+# define ACE_DEV_NULL "/dev/null"
+# define ACE_SYSCALL_FAILED -1
+# endif /* ACE_WIN32 */
+
+#include /**/ "ace/post.h"
+#endif /*ACE_DEFAULT_CONSTANTS_H*/
diff --git a/ACE/ace/Dev_Poll_Reactor.cpp b/ACE/ace/Dev_Poll_Reactor.cpp
new file mode 100644
index 00000000000..cfa87d00650
--- /dev/null
+++ b/ACE/ace/Dev_Poll_Reactor.cpp
@@ -0,0 +1,2513 @@
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+#include "ace/Dev_Poll_Reactor.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+
+ACE_RCSID (ace,
+ Dev_Poll_Reactor,
+ "$Id$")
+
+#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
+
+# include "ace/OS_NS_unistd.h"
+# include "ace/OS_NS_fcntl.h"
+# include "ace/OS_NS_stropts.h"
+
+# if defined (ACE_HAS_EVENT_POLL) && defined (linux)
+# include /**/ <sys/epoll.h>
+# elif defined (ACE_HAS_DEV_POLL)
+# if defined (linux)
+# include /**/ <linux/devpoll.h>
+# elif defined (HPUX_VERS) && HPUX_VERS < 1123
+# include /**/ <devpoll.h>
+# else
+# include /**/ <sys/devpoll.h>
+# endif /* linux */
+# endif /* ACE_HAS_DEV_POLL */
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Dev_Poll_Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include "ace/Handle_Set.h"
+#include "ace/Reactor.h"
+#include "ace/Timer_Heap.h"
+#include "ace/Timer_Queue.h"
+#include "ace/ACE.h"
+#include "ace/Reverse_Lock_T.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Null_Mutex.h"
+#include "ace/os_include/os_poll.h"
+#include "ace/OS_NS_sys_mman.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Dev_Poll_Reactor_Notify::ACE_Dev_Poll_Reactor_Notify (void)
+ : dp_reactor_ (0)
+ , notification_pipe_ ()
+ , max_notify_iterations_ (-1)
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ , notification_queue_ ()
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+{
+}
+
+int
+ACE_Dev_Poll_Reactor_Notify::open (ACE_Reactor_Impl *r,
+ ACE_Timer_Queue * /* timer_queue */,
+ int disable_notify_pipe)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::open");
+
+ if (disable_notify_pipe == 0)
+ {
+ this->dp_reactor_ = dynamic_cast<ACE_Dev_Poll_Reactor *> (r);
+
+ if (this->dp_reactor_ == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (this->notification_pipe_.open () == -1)
+ return -1;
+
+#if defined (F_SETFD)
+ // close-on-exec
+ 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)
+ if (notification_queue_.open () == -1)
+ {
+ return -1;
+ }
+
+ if (ACE::set_flags (this->notification_pipe_.write_handle (),
+ ACE_NONBLOCK) == -1)
+ return -1;
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ // Set the read handle into non-blocking mode since we need to
+ // perform a "speculative" read when determining if there are
+ // notifications to dispatch.
+ if (ACE::set_flags (this->notification_pipe_.read_handle (),
+ ACE_NONBLOCK) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor_Notify::close (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::close");
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ notification_queue_.reset ();
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ return this->notification_pipe_.close ();
+}
+
+int
+ACE_Dev_Poll_Reactor_Notify::notify (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::notify");
+
+ // Just consider this method a "no-op" if there's no
+ // ACE_Dev_Poll_Reactor configured.
+ if (this->dp_reactor_ == 0)
+ return 0;
+
+ ACE_Notification_Buffer buffer (eh, mask);
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ ACE_UNUSED_ARG (timeout);
+ ACE_Dev_Poll_Handler_Guard eh_guard (eh);
+
+ int notification_required =
+ notification_queue_.push_new_notification (buffer);
+
+ if (notification_required == -1)
+ return -1; // Also decrement eh's reference count
+
+ // The notification has been queued, so it will be delivered at some
+ // point (and may have been already); release the refcnt guard.
+ eh_guard.release ();
+
+ if (notification_required == 0)
+ return 0;
+
+ // Now pop the pipe to force the callback for dispatching when ready. If
+ // the send fails due to a full pipe, don't fail - assume the already-sent
+ // pipe bytes will cause the entire notification queue to be processed.
+ ssize_t n = ACE::send (this->notification_pipe_.write_handle (),
+ (char *) &buffer,
+ 1, // Only need one byte to pop the pipe
+ &ACE_Time_Value::zero);
+ if (n == -1 && (errno != ETIME && errno != EAGAIN))
+ return -1;
+
+ return 0;
+#else
+
+ ACE_Dev_Poll_Handler_Guard eh_guard (eh);
+
+ ssize_t n = ACE::send (this->notification_pipe_.write_handle (),
+ (char *) &buffer,
+ sizeof buffer,
+ timeout);
+ if (n == -1)
+ return -1;
+
+ eh_guard.release ();
+
+ return 0;
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+}
+
+int
+ACE_Dev_Poll_Reactor_Notify::dispatch_notifications (
+ int & /* number_of_active_handles */,
+ ACE_Handle_Set & /* rd_mask */)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::dispatch_notifications");
+
+ // This method is unimplemented in the ACE_Dev_Poll_Reactor.
+ // Instead, the notification handler is invoked as part of the IO
+ // event set. Doing so alters the some documented semantics that
+ // state that the notifications are handled before IO events.
+ // Enforcing such semantics does not appear to be beneficial, and
+ // also serves to slow down event dispatching particularly with this
+ // ACE_Dev_Poll_Reactor.
+
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_Dev_Poll_Reactor_Notify::read_notify_pipe (ACE_HANDLE handle,
+ ACE_Notification_Buffer &buffer)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::read_notify_pipe");
+
+ // This is a (non-blocking) "speculative" read, i.e., we attempt to
+ // read even if no event was polled on the read handle. A
+ // speculative read is necessary since notifications must be
+ // dispatched before IO events. We can avoid the speculative read
+ // by "walking" the array of pollfd structures returned from
+ // `/dev/poll' or `/dev/epoll' but that is potentially much more
+ // expensive than simply checking for an EWOULDBLOCK.
+ size_t to_read;
+ char *read_p;
+ bool have_one = false;
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ // For the queued case, we'll try to read one byte (since that's what
+ // the notify () tried to put in) but we don't need it - notifications can
+ // be queued even if the pipe fills, so there may be more notifications
+ // queued than there are bytes in the pipe.
+ char b;
+ read_p = &b;
+ to_read = 1;
+
+ // Before reading the byte, pop a message from the queue and queue a
+ // new message unless the queue is now empty. The protocol is to
+ // keep a byte in the pipe as long as the queue is not empty.
+ bool more_messages_queued = false;
+ ACE_Notification_Buffer next;
+
+ int result = notification_queue_.pop_next_notification (buffer,
+ more_messages_queued,
+ next);
+
+ if (result == 0)
+ {
+ // remove the notification byte from the pipe, avoiding notification loop
+ ACE::recv (handle, read_p, to_read);
+ return 0;
+ }
+
+ if (result == -1)
+ return -1;
+
+ if (more_messages_queued)
+ (void) ACE::send (this->notification_pipe_.write_handle (),
+ (char *)&next,
+ 1 /* one byte is enough */,
+ &ACE_Time_Value::zero);
+#else
+ to_read = sizeof buffer;
+ read_p = (char *)&buffer;
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ ssize_t n = ACE::recv (handle, read_p, to_read);
+
+ if (n > 0)
+ {
+ // Check to see if we've got a short read.
+ if (static_cast<size_t> (n) != to_read)
+ {
+ size_t remainder = to_read - 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, &read_p[n], remainder) <= 0)
+ return -1;
+ }
+
+ return 1;
+ }
+
+ // Return -1 if things have gone seriously wrong.
+ if (n <= 0 && (errno != EWOULDBLOCK && errno != EAGAIN))
+ return -1;
+
+ return have_one ? 1 : 0;
+}
+
+
+int
+ACE_Dev_Poll_Reactor_Notify::handle_input (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::handle_input");
+
+ // @@ We may end up dispatching this event handler twice: once when
+ // performing the speculative read on the notification pipe
+ // handle, and once more when dispatching the IO events.
+
+ // 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 available notifications have been dispatched.
+ if (number_dispatched == this->max_notify_iterations_)
+ break;
+ }
+
+ if (result == -1)
+ {
+ // Reassign number_dispatched to -1 if things have gone
+ // seriously wrong.
+ 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;
+}
+
+ACE_HANDLE
+ACE_Dev_Poll_Reactor_Notify::notify_handle (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::notify_handle");
+
+ return this->notification_pipe_.read_handle ();
+}
+
+int
+ACE_Dev_Poll_Reactor_Notify::is_dispatchable (ACE_Notification_Buffer &)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::is_dispatchable");
+
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_Dev_Poll_Reactor_Notify::dispatch_notify (ACE_Notification_Buffer &buffer)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::dispatch_notify");
+
+ // If eh == 0 then another thread is unblocking the
+ // ACE_Dev_Poll_Reactor to update the ACE_Dev_Poll_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)
+ {
+ int result = 0;
+
+ // Guard the handler's refcount. Recall that when the notify
+ // was queued, the refcount was incremented, so it need not be
+ // now. The guard insures that it is decremented properly.
+ ACE_Dev_Poll_Handler_Guard eh_guard (buffer.eh_, false);
+
+ 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_TEXT ("dispatch_notify invalid mask = %d\n"),
+ buffer.mask_));
+ }
+ if (result == -1)
+ buffer.eh_->handle_close (ACE_INVALID_HANDLE, buffer.mask_);
+ }
+
+ return 1;
+}
+
+void
+ACE_Dev_Poll_Reactor_Notify::max_notify_iterations (int iterations)
+{
+ ACE_TRACE ("ACE_Dev_Poll_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_Dev_Poll_Reactor_Notify::max_notify_iterations (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::max_notify_iterations");
+
+ return this->max_notify_iterations_;
+}
+
+int
+ACE_Dev_Poll_Reactor_Notify::purge_pending_notifications (
+ ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::purge_pending_notifications");
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+
+ return notification_queue_.purge_pending_notifications (eh, mask);
+
+#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_Dev_Poll_Reactor_Notify::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("dp_reactor_ = %@"),
+ this->dp_reactor_));
+ this->notification_pipe_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// -----------------------------------------------------------------
+
+ACE_Dev_Poll_Reactor_Handler_Repository::
+ACE_Dev_Poll_Reactor_Handler_Repository (void)
+ : max_size_ (0),
+ handlers_ (0)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::ACE_Dev_Poll_Reactor_Handler_Repository");
+}
+
+int
+ACE_Dev_Poll_Reactor_Handler_Repository::invalid_handle (
+ ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::invalid_handle");
+
+ if (handle < 0 || handle >= this->max_size_)
+ {
+ errno = EINVAL;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor_Handler_Repository::handle_in_range (
+ ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::handle_in_range");
+
+ if (handle >= 0 && handle < this->max_size_)
+ return 1;
+ else
+ {
+ errno = EINVAL;
+ return 0;
+ }
+}
+
+int
+ACE_Dev_Poll_Reactor_Handler_Repository::open (size_t size)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::open");
+
+ this->max_size_ = size;
+
+ // Try to allocate the memory.
+ ACE_NEW_RETURN (this->handlers_,
+ ACE_Dev_Poll_Event_Tuple[size],
+ -1);
+
+ // Try to increase the number of handles if <size> is greater than
+ // the current limit.
+ return ACE::set_handle_limit (size);
+}
+
+int
+ACE_Dev_Poll_Reactor_Handler_Repository::unbind_all (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::unbind_all");
+
+ // Unbind all of the event handlers.
+ for (int handle = 0;
+ handle < this->max_size_;
+ ++handle)
+ this->unbind (handle);
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor_Handler_Repository::close (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::close");
+
+ if (this->handlers_ != 0)
+ {
+ this->unbind_all ();
+
+ delete [] this->handlers_;
+ this->handlers_ = 0;
+ }
+
+ return 0;
+}
+
+ACE_Event_Handler *
+ACE_Dev_Poll_Reactor_Handler_Repository::find (ACE_HANDLE handle,
+ size_t *index_p)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::find");
+
+ ACE_Event_Handler *eh = 0;
+
+ // Only bother to search for the <handle> if it's in range.
+ if (this->handle_in_range (handle))
+ {
+ eh = this->handlers_[handle].event_handler;
+ if (eh != 0)
+ {
+ if (index_p != 0)
+ *index_p = handle;
+ }
+ else
+ errno = ENOENT;
+ }
+
+ return eh;
+}
+
+int
+ACE_Dev_Poll_Reactor_Handler_Repository::bind (
+ ACE_HANDLE handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::bind");
+
+ if (event_handler == 0)
+ return -1;
+
+ if (handle == ACE_INVALID_HANDLE)
+ handle = event_handler->get_handle ();
+
+ if (this->invalid_handle (handle))
+ return -1;
+
+ this->handlers_[handle].event_handler = event_handler;
+ this->handlers_[handle].mask = mask;
+ event_handler->add_reference ();
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor_Handler_Repository::unbind (ACE_HANDLE handle,
+ bool decr_refcnt)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::unbind");
+
+ if (this->find (handle) == 0)
+ return -1;
+
+ if (decr_refcnt)
+ this->handlers_[handle].event_handler->remove_reference ();
+ this->handlers_[handle].event_handler = 0;
+ this->handlers_[handle].mask = ACE_Event_Handler::NULL_MASK;
+ this->handlers_[handle].suspended = 0;
+
+ return 0;
+}
+
+// -----------------------------------------------------------------
+
+ACE_Dev_Poll_Reactor::ACE_Dev_Poll_Reactor (ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int disable_notify_pipe,
+ ACE_Reactor_Notify *notify,
+ int mask_signals,
+ int s_queue)
+ : initialized_ (false)
+ , poll_fd_ (ACE_INVALID_HANDLE)
+ , size_ (0)
+ // , ready_set_ ()
+#if defined (ACE_HAS_EVENT_POLL)
+ , events_ (0)
+ , start_pevents_ (0)
+ , end_pevents_ (0)
+#else
+ , dp_fds_ (0)
+ , start_pfds_ (0)
+ , end_pfds_ (0)
+#endif /* ACE_HAS_EVENT_POLL */
+ , deactivated_ (0)
+ , token_ (*this, s_queue)
+ , lock_adapter_ (token_)
+ , timer_queue_ (0)
+ , delete_timer_queue_ (false)
+ , signal_handler_ (0)
+ , delete_signal_handler_ (false)
+ , notify_handler_ (0)
+ , delete_notify_handler_ (false)
+ , mask_signals_ (mask_signals)
+ , restart_ (0)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::ACE_Dev_Poll_Reactor");
+
+ if (this->open (ACE::max_handles (),
+ 0,
+ sh,
+ tq,
+ disable_notify_pipe,
+ notify) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Dev_Poll_Reactor::open ")
+ ACE_TEXT ("failed inside ")
+ ACE_TEXT ("ACE_Dev_Poll_Reactor::CTOR")));
+}
+
+ACE_Dev_Poll_Reactor::ACE_Dev_Poll_Reactor (size_t size,
+ int rs,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int disable_notify_pipe,
+ ACE_Reactor_Notify *notify,
+ int mask_signals,
+ int s_queue)
+ : initialized_ (false)
+ , poll_fd_ (ACE_INVALID_HANDLE)
+ , size_ (0)
+ // , ready_set_ ()
+#if defined (ACE_HAS_EVENT_POLL)
+ , events_ (0)
+ , start_pevents_ (0)
+ , end_pevents_ (0)
+#else
+ , dp_fds_ (0)
+ , start_pfds_ (0)
+ , end_pfds_ (0)
+#endif /* ACE_HAS_EVENT_POLL */
+ , deactivated_ (0)
+ , token_ (*this, s_queue)
+ , lock_adapter_ (token_)
+ , timer_queue_ (0)
+ , delete_timer_queue_ (false)
+ , signal_handler_ (0)
+ , delete_signal_handler_ (false)
+ , notify_handler_ (0)
+ , delete_notify_handler_ (false)
+ , mask_signals_ (mask_signals)
+ , restart_ (0)
+{
+ if (this->open (size,
+ rs,
+ sh,
+ tq,
+ disable_notify_pipe,
+ notify) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Dev_Poll_Reactor::open ")
+ ACE_TEXT ("failed inside ACE_Dev_Poll_Reactor::CTOR")));
+}
+
+ACE_Dev_Poll_Reactor::~ACE_Dev_Poll_Reactor (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::~ACE_Dev_Poll_Reactor");
+
+ (void) this->close ();
+}
+
+int
+ACE_Dev_Poll_Reactor::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_Dev_Poll_Reactor::open");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ // Can't initialize ourselves more than once.
+ if (this->initialized_)
+ return -1;
+
+ 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_ = true;
+ }
+
+ // 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_ = true;
+ }
+
+ // Allows the Notify_Handler to be overridden.
+ if (result != -1 && this->notify_handler_ == 0)
+ {
+ ACE_NEW_RETURN (this->notify_handler_,
+ ACE_Dev_Poll_Reactor_Notify,
+ -1);
+
+ if (this->notify_handler_ == 0)
+ result = -1;
+ else
+ this->delete_notify_handler_ = true;
+ }
+
+#if defined (ACE_HAS_EVENT_POLL)
+
+ // Allocating event table:
+ ACE_NEW_RETURN (this->events_, epoll_event[size], -1);
+
+ // Initializing epoll:
+ this->poll_fd_ = ::epoll_create (size);
+ if (this->poll_fd_ == -1)
+ result = -1;
+
+#else
+
+ // Allocate the array before opening the device to avoid a potential
+ // resource leak if allocation fails.
+ ACE_NEW_RETURN (this->dp_fds_,
+ pollfd[size],
+ -1);
+
+ // Open the `/dev/poll' character device.
+ this->poll_fd_ = ACE_OS::open ("/dev/poll", O_RDWR);
+ if (this->poll_fd_ == ACE_INVALID_HANDLE)
+ result = -1;
+
+#endif /* ACE_HAS_EVENT_POLL */
+
+ if (result != -1 && this->handler_rep_.open (size) == -1)
+ result = -1;
+
+ // Registration of the notification handler must be done after the
+ // /dev/poll device has been fully initialized.
+ else if (this->notify_handler_->open (this,
+ 0,
+ disable_notify_pipe) == -1
+ || (disable_notify_pipe == 0
+ && this->register_handler_i (
+ this->notify_handler_->notify_handle (),
+ this->notify_handler_,
+ ACE_Event_Handler::READ_MASK) == -1))
+ result = -1;
+
+ this->size_ = size;
+
+ if (result != -1)
+ // We're all set to go.
+ this->initialized_ = true;
+ else
+ // This will close down all the allocated resources properly.
+ (void) this->close ();
+
+ return result;
+}
+
+int
+ACE_Dev_Poll_Reactor::current_info (ACE_HANDLE, size_t & /* size */)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+
+int
+ACE_Dev_Poll_Reactor::set_sig_handler (ACE_Sig_Handler *signal_handler)
+{
+ if (this->delete_signal_handler_)
+ delete this->signal_handler_;
+
+ this->signal_handler_ = signal_handler;
+ this->delete_signal_handler_ = false;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::timer_queue (ACE_Timer_Queue *tq)
+{
+ if (this->delete_timer_queue_)
+ delete this->timer_queue_;
+
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = false;
+
+ return 0;
+
+}
+
+ACE_Timer_Queue *
+ACE_Dev_Poll_Reactor::timer_queue (void) const
+{
+ return this->timer_queue_;
+}
+
+int
+ACE_Dev_Poll_Reactor::close (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::close");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ int result = 0;
+
+ if (this->poll_fd_ != ACE_INVALID_HANDLE)
+ {
+ result = ACE_OS::close (this->poll_fd_);
+ }
+
+#if defined (ACE_HAS_EVENT_POLL)
+
+ delete [] this->events_;
+ this->events_ = 0;
+
+#else
+
+ delete [] this->dp_fds_;
+ this->dp_fds_ = 0;
+
+#endif /* ACE_HAS_EVENT_POLL */
+
+ if (this->delete_signal_handler_)
+ {
+ delete this->signal_handler_;
+ this->signal_handler_ = 0;
+ this->delete_signal_handler_ = false;
+ }
+
+ (void) this->handler_rep_.close ();
+
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->timer_queue_ = 0;
+ this->delete_timer_queue_ = false;
+ }
+
+ 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_ = false;
+ }
+
+ this->poll_fd_ = ACE_INVALID_HANDLE;
+
+#if defined (ACE_HAS_EVENT_POLL)
+ this->start_pevents_ = 0;
+ this->end_pevents_ = 0;
+#else
+ this->start_pfds_ = 0;
+ this->end_pfds_ = 0;
+#endif /* ACE_HAS_EVENT_POLL */
+
+ this->initialized_ = false;
+
+ return result;
+}
+
+int
+ACE_Dev_Poll_Reactor::work_pending (const ACE_Time_Value & max_wait_time)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::work_pending");
+
+ // Stash the current time
+ //
+ // The destructor of this object will automatically compute how much
+ // time elapsed since this method was called.
+ ACE_Time_Value mwt (max_wait_time);
+ ACE_MT (ACE_Countdown_Time countdown (&mwt));
+
+ Token_Guard guard (this->token_);
+ int const result = guard.acquire_quietly (&mwt);
+
+ // If the guard is NOT the owner just return the retval
+ if (!guard.is_owner ())
+ return result;
+
+ // Update the countdown to reflect time waiting for the mutex.
+ ACE_MT (countdown.update ());
+
+ return this->work_pending_i (&mwt);
+}
+
+int
+ACE_Dev_Poll_Reactor::work_pending_i (ACE_Time_Value * max_wait_time)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::work_pending_i");
+
+ if (this->deactivated_)
+ return 0;
+
+#if defined (ACE_HAS_EVENT_POLL)
+ if (this->start_pevents_ != this->end_pevents_)
+#else
+ if (this->start_pfds_ != this->end_pfds_)
+#endif /* ACE_HAS_EVENT_POLL */
+ return 1; // We still have work_pending (). Do not poll for
+ // additional events.
+
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value *this_timeout =
+ this->timer_queue_->calculate_timeout (max_wait_time, &timer_buf);
+
+ // Check if we have timers to fire.
+ int const timers_pending =
+ ((this_timeout != 0 && max_wait_time == 0)
+ || (this_timeout != 0 && max_wait_time != 0
+ && *this_timeout != *max_wait_time) ? 1 : 0);
+
+ long const timeout =
+ (this_timeout == 0
+ ? -1 /* Infinity */
+ : static_cast<long> (this_timeout->msec ()));
+
+#if defined (ACE_HAS_EVENT_POLL)
+
+ // Wait for events.
+ int const nfds = ::epoll_wait (this->poll_fd_,
+ this->events_,
+ this->size_,
+ static_cast<int> (timeout));
+
+ if (nfds > 0)
+ {
+ this->start_pevents_ = this->events_;
+ this->end_pevents_ = this->start_pevents_ + nfds;
+ }
+
+#else
+
+ struct dvpoll dvp;
+
+ dvp.dp_fds = this->dp_fds_;
+ dvp.dp_nfds = this->size_;
+ dvp.dp_timeout = timeout; // Milliseconds
+
+ // Poll for events
+ int const nfds = ACE_OS::ioctl (this->poll_fd_, DP_POLL, &dvp);
+
+ // Retrieve the results from the pollfd array.
+ this->start_pfds_ = dvp.dp_fds;
+
+ // If nfds == 0 then end_pfds_ == start_pfds_ meaning that there is
+ // no work pending. If nfds > 0 then there is work pending.
+ // Otherwise an error occurred.
+ if (nfds > -1)
+ this->end_pfds_ = this->start_pfds_ + nfds;
+#endif /* ACE_HAS_EVENT_POLL */
+
+ // If timers are pending, override any timeout from the poll.
+ return (nfds == 0 && timers_pending != 0 ? 1 : nfds);
+}
+
+
+int
+ACE_Dev_Poll_Reactor::handle_events (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::handle_events");
+
+ // Stash the current time
+ //
+ // The destructor of this object will automatically compute how much
+ // time elapsed since this method was called.
+ ACE_MT (ACE_Countdown_Time countdown (max_wait_time));
+
+ Token_Guard guard (this->token_);
+ int const result = guard.acquire_quietly (max_wait_time);
+
+ // If the guard is NOT the owner just return the retval
+ if (!guard.is_owner ())
+ return result;
+
+ if (this->deactivated_)
+ return -1;
+
+ // Update the countdown to reflect time waiting for the mutex.
+ ACE_MT (countdown.update ());
+
+ return this->handle_events_i (max_wait_time, guard);
+}
+
+int
+ACE_Dev_Poll_Reactor::handle_events_i (ACE_Time_Value *max_wait_time,
+ Token_Guard &guard)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::handle_events_i");
+
+ int result = 0;
+ // int active_handle_count = 0;
+
+ // Poll for events
+ //
+ // If the underlying ioctl () call was interrupted via the interrupt
+ // signal (i.e. returned -1 with errno == EINTR) then the loop will
+ // be restarted if so desired.
+ do
+ {
+ result = this->work_pending_i (max_wait_time);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR, "%t: %p\n", "work_pending_i"));
+ }
+ while (result == -1 && this->restart_ != 0 && errno == EINTR);
+
+ if (result == 0 || (result == -1 && errno == ETIME))
+ return 0;
+ else if (result == -1)
+ {
+ if (errno != EINTR)
+ return -1;
+
+ // Bail out -- we got here since the poll was interrupted.
+ // If it was due to a signal registered through our ACE_Sig_Handler,
+ // then it was dispatched, so we count it in the number of events
+ // handled rather than cause an error return.
+ if (ACE_Sig_Handler::sig_pending () != 0)
+ {
+ ACE_Sig_Handler::sig_pending (0);
+ return 1;
+ }
+ return -1;
+ }
+
+ // Dispatch an event.
+ return this->dispatch (guard);
+}
+
+// Dispatch an event. On entry, the token is held by the caller. If an
+// event is found to dispatch, the token is released before dispatching it.
+int
+ACE_Dev_Poll_Reactor::dispatch (Token_Guard &guard)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::dispatch");
+
+ // Perform the Template Method for dispatching the first located event.
+ // We dispatch only one to effectively dispatch events concurrently.
+ // As soon as an event is located, the token is released, allowing the
+ // next waiter to begin getting an event while we dispatch one here.
+ int result = 0;
+
+ // Handle timers early since they may have higher latency
+ // constraints than I/O handlers. Ideally, the order of
+ // dispatching should be a strategy...
+ if ((result = this->dispatch_timer_handler (guard)) != 0)
+ return result;
+
+ // Check to see if there are no more I/O handles left to
+ // dispatch AFTER we've handled the timers.
+
+ // Finally, dispatch the I/O handlers.
+ result = this->dispatch_io_event (guard);
+
+ return result;
+}
+
+int
+ACE_Dev_Poll_Reactor::dispatch_timer_handler (Token_Guard &guard)
+{
+ if (this->timer_queue_->is_empty ())
+ return 0; // Empty timer queue so cannot have any expired timers.
+
+ // 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))
+ {
+ const void *upcall_act = 0;
+
+ // Preinvoke (handles refcount if needed, etc.)
+ this->timer_queue_->preinvoke (info, cur_time, upcall_act);
+
+ // Release the token before expiration upcall.
+ guard.release_token ();
+
+ // call the functor
+ this->timer_queue_->upcall (info, cur_time);
+
+ // Postinvoke (undo refcount if needed, etc.)
+ this->timer_queue_->postinvoke (info, cur_time, upcall_act);
+
+ // We have dispatched a timer
+ return 1;
+ }
+
+ return 0;
+}
+
+#if 0
+int
+ACE_Dev_Poll_Reactor::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
+ // Dev_Poll_Reactor's notify hook is enabled. If so, it means that
+ // one or more other threads are trying to update the
+ // ACE_Dev_Poll_Reactor'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.
+
+ const 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;
+}
+#endif /* 0 */
+
+int
+ACE_Dev_Poll_Reactor::dispatch_io_event (Token_Guard &guard)
+{
+
+ // Define bits to check for while dispatching.
+#if defined (ACE_HAS_EVENT_POLL)
+ const __uint32_t out_event = EPOLLOUT;
+ const __uint32_t exc_event = EPOLLPRI;
+ const __uint32_t in_event = EPOLLIN;
+ const __uint32_t err_event = EPOLLHUP | EPOLLERR;
+#else
+ const short out_event = POLLOUT;
+ const short exc_event = POLLPRI;
+ const short in_event = POLLIN;
+ const short err_event = 0; // No known bits for this
+#endif /* ACE_HAS_EVENT_POLL */
+
+ // Since the underlying event demultiplexing mechansim (`/dev/poll'
+ // or '/dev/epoll') is stateful, and since only one result buffer is
+ // used, all pending events (i.e. those retrieved from a previous
+ // poll) must be dispatched before any additional event can be
+ // polled. As such, the Dev_Poll_Reactor keeps track of the
+ // progress of events that have been dispatched.
+
+ // Dispatch the events.
+ //
+ // Select the first available handle with event (s) pending. Check for
+ // event type in defined order of dispatch: output, exception, input.
+ // When an event is located, clear its bit in the dispatch set. If there
+ // are no more events for the handle, also increment the pfds pointer
+ // to move to the next handle ready.
+ //
+ // Notice that pfds only contains file descriptors that have
+ // received events.
+#if defined (ACE_HAS_EVENT_POLL)
+ struct epoll_event *& pfds = this->start_pevents_;
+ if (pfds < this->end_pevents_)
+#else
+ struct pollfd *& pfds = this->start_pfds_;
+ if (pfds < this->end_pfds_)
+#endif /* ACE_HAS_EVENT_POLL */
+ {
+#if defined (ACE_HAS_EVENT_POLL)
+ const ACE_HANDLE handle = pfds->data.fd;
+ __uint32_t &revents = pfds->events;
+#else
+ const ACE_HANDLE handle = pfds->fd;
+ short &revents = pfds->revents;
+#endif /* ACE_HAS_EVENT_POLL */
+
+ // Figure out what to do first in order to make it easier to manage
+ // the bit twiddling and possible pfds increment before releasing
+ // the token for dispatch.
+ // Note that if there's an error (such as the handle was closed
+ // without being removed from the event set) the EPOLLHUP and/or
+ // EPOLLERR bits will be set in revents.
+ bool disp_out = false;
+ bool disp_exc = false;
+ bool disp_in = false;
+ if (ACE_BIT_ENABLED (revents, out_event))
+ {
+ disp_out = true;
+ ACE_CLR_BITS (revents, out_event);
+ }
+ else if (ACE_BIT_ENABLED (revents, exc_event))
+ {
+ disp_exc = true;
+ ACE_CLR_BITS (revents, exc_event);
+ }
+ else if (ACE_BIT_ENABLED (revents, in_event))
+ {
+ disp_in = true;
+ ACE_CLR_BITS (revents, in_event);
+ }
+ else if (ACE_BIT_ENABLED (revents, err_event))
+ {
+ this->remove_handler_i (handle, ACE_Event_Handler::ALL_EVENTS_MASK);
+ ++pfds;
+ return 1;
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT (" (%t) dispatch_io h %d unknown events 0x%x\n"), handle, revents));
+ // ACE_ASSERT (0);
+ }
+
+ // Increment the pointer to the next element before we
+ // release the token. Otherwise event handlers end up being
+ // dispatched multiple times for the same poll.
+ if (revents == 0)
+ ++pfds;
+
+ /* When using sys_epoll, we can attach arbitrary user
+ data to the descriptor, so it can be delivered when
+ activity is detected. Perhaps we should store event
+ handler together with descriptor, instead of looking
+ it up in a repository ? Could it boost performance ?
+ */
+ ACE_Event_Handler *eh = this->handler_rep_.find (handle);
+
+ if (eh)
+ {
+ // Modify the reference count in an exception-safe way.
+ // Note that eh could be the notify handler. It's not strictly
+ // necessary to manage its refcount, but since we don't enable
+ // the counting policy, it won't do much. Management of the
+ // notified handlers themselves is done in the notify handler.
+ ACE_Dev_Poll_Handler_Guard eh_guard (eh);
+
+ // Release the reactor token before upcall.
+ guard.release_token ();
+
+ // Dispatch the detected event
+ if (disp_out)
+ {
+ const int status =
+ this->upcall (eh, &ACE_Event_Handler::handle_output, handle);
+
+ if (status < 0)
+ // Note that the token is reacquired in remove_handler ().
+ this->remove_handler (handle, ACE_Event_Handler::WRITE_MASK);
+ return 1;
+ }
+
+ if (disp_exc)
+ {
+ const int status =
+ this->upcall (eh, &ACE_Event_Handler::handle_exception, handle);
+
+ if (status < 0)
+ // Note that the token is reacquired in remove_handler ().
+ this->remove_handler (handle, ACE_Event_Handler::EXCEPT_MASK);
+ return 1;
+ }
+
+ if (disp_in)
+ {
+ const int status =
+ this->upcall (eh, &ACE_Event_Handler::handle_input, handle);
+
+ if (status < 0)
+ // Note that the token is reacquired in remove_handler ().
+ this->remove_handler (handle, ACE_Event_Handler::READ_MASK);
+ return 1;
+ }
+ } // The reactor token is reacquired upon leaving this scope.
+ }
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::alertable_handle_events (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::alertable_handle_events");
+
+ return this->handle_events (max_wait_time);
+}
+
+int
+ACE_Dev_Poll_Reactor::handle_events (ACE_Time_Value &max_wait_time)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::handle_events");
+
+ return this->handle_events (&max_wait_time);
+}
+
+int
+ACE_Dev_Poll_Reactor::alertable_handle_events (ACE_Time_Value &max_wait_time)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::alertable_handle_events");
+
+ return this->handle_events (max_wait_time);
+}
+
+int
+ACE_Dev_Poll_Reactor::deactivated (void)
+{
+ return this->deactivated_;
+}
+
+void
+ACE_Dev_Poll_Reactor::deactivate (int do_stop)
+{
+ this->deactivated_ = do_stop;
+ this->wakeup_all_threads ();
+}
+
+int
+ACE_Dev_Poll_Reactor::register_handler (ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::register_handler");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->register_handler_i (handler->get_handle (),
+ handler,
+ mask);
+}
+
+int
+ACE_Dev_Poll_Reactor::register_handler (ACE_HANDLE handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::register_handler");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->register_handler_i (handle,
+ event_handler,
+ mask);
+}
+
+int
+ACE_Dev_Poll_Reactor::register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::register_handler_i");
+
+ if (handle == ACE_INVALID_HANDLE
+ || mask == ACE_Event_Handler::NULL_MASK)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (this->handler_rep_.find (handle) == 0)
+ {
+ // Handler not present in the repository. Bind it.
+ if (this->handler_rep_.bind (handle, event_handler, mask) != 0)
+ return -1;
+
+#if defined (ACE_HAS_EVENT_POLL)
+
+ struct epoll_event epev;
+ ACE_OS::memset (&epev, 0, sizeof (epev));
+ static const int op = EPOLL_CTL_ADD;
+
+ epev.events = this->reactor_mask_to_poll_event (mask);
+ epev.data.fd = handle;
+
+ if (::epoll_ctl (this->poll_fd_, op, handle, &epev) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "epoll_ctl"));
+ (void) this->handler_rep_.unbind (handle);
+ return -1;
+ }
+
+#endif /* ACE_HAS_EVENT_POLL */
+ }
+ else
+ {
+ // Handler is already present in the repository, so register it
+ // again, possibly for different event. Add new mask to the
+ // current one.
+ if (this->mask_ops_i (handle, mask, ACE_Reactor::ADD_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "mask_ops_i"), -1);
+ }
+
+#ifndef ACE_HAS_EVENT_POLL
+
+ struct pollfd pfd;
+
+ pfd.fd = handle;
+ pfd.events = this->reactor_mask_to_poll_event (mask);
+ pfd.revents = 0;
+
+ // Add file descriptor to the "interest set."
+ if (ACE_OS::write (this->poll_fd_, &pfd, sizeof (pfd)) != sizeof (pfd))
+ {
+ (void) this->handler_rep_.unbind (handle);
+ return -1;
+ }
+#endif /*ACE_HAS_EVENT_POLL*/
+
+ // 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->state_changed_ = 1;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::register_handler (
+ ACE_HANDLE /* event_handle */,
+ ACE_HANDLE /* io_handle */,
+ ACE_Event_Handler * /* event_handler */,
+ ACE_Reactor_Mask /* mask */)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_Dev_Poll_Reactor::register_handler (const ACE_Handle_Set &handle_set,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::register_handler");
+
+ ACE_Handle_Set_Iterator handle_iter (handle_set);
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ // @@ It might be more efficient to construct a pollfd array and
+ // pass it to the write () call in register_handler_i () only once,
+ // instead of calling write () (a system call) once for each file
+ // descriptor.
+
+ for (ACE_HANDLE h = handle_iter ();
+ h != ACE_INVALID_HANDLE;
+ h = handle_iter ())
+ if (this->register_handler_i (h, event_handler, mask) == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_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)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::register_handler");
+
+ return this->signal_handler_->register_handler (signum,
+ new_sh,
+ new_disp,
+ old_sh,
+ old_disp);
+}
+
+int
+ACE_Dev_Poll_Reactor::register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::register_handler");
+
+ int result = 0;
+
+#if (ACE_NSIG > 0)
+
+ for (int s = 1; s < ACE_NSIG; ++s)
+ if ((sigset.is_member (s) == 1)
+ && this->signal_handler_->register_handler (s,
+ new_sh,
+ new_disp) == -1)
+ result = -1;
+
+#else /* ACE_NSIG <= 0 */
+
+ ACE_UNUSED_ARG (sigset);
+ ACE_UNUSED_ARG (new_sh);
+ ACE_UNUSED_ARG (new_disp);
+
+#endif /* ACE_NSIG <= 0 */
+
+ return result;
+}
+
+int
+ACE_Dev_Poll_Reactor::remove_handler (ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::remove_handler");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->remove_handler_i (handler->get_handle (), mask);
+}
+
+int
+ACE_Dev_Poll_Reactor::remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::remove_handler");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->remove_handler_i (handle, mask);
+}
+
+int
+ACE_Dev_Poll_Reactor::remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::remove_handler_i");
+
+ ACE_Event_Handler *eh = this->handler_rep_.find (handle);
+
+ if (eh == 0 ||
+ this->mask_ops_i (handle, mask, ACE_Reactor::CLR_MASK) == -1)
+ return -1;
+
+ // Check for ref counting now - handle_close () may delete eh.
+ bool const requires_reference_counting =
+ eh->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ if (ACE_BIT_DISABLED (mask, ACE_Event_Handler::DONT_CALL))
+ (void) eh->handle_close (handle, mask);
+
+ // If there are no longer any outstanding events on the given handle
+ // then remove it from the handler repository.
+ if (this->handler_rep_.mask (handle) == ACE_Event_Handler::NULL_MASK)
+ this->handler_rep_.unbind (handle, requires_reference_counting);
+
+ // Note the fact that we've changed the state of the wait_set,
+ // i.e. the "interest set," which is used by the dispatching loop to
+ // determine whether it can keep going or if it needs to reconsult
+ // /dev/poll or /dev/epoll.
+ // this->state_changed_ = 1;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::remove_handler (const ACE_Handle_Set &handle_set,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::remove_handler");
+
+ ACE_Handle_Set_Iterator handle_iter (handle_set);
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ // @@ It might be more efficient to construct a pollfd array and
+ // pass it to the write () call in register_handler_i () only once,
+ // instead of calling write () (a system call) once for each file
+ // descriptor.
+
+ for (ACE_HANDLE h = handle_iter ();
+ h != ACE_INVALID_HANDLE;
+ h = handle_iter ())
+ if (this->remove_handler_i (h, mask) == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp,
+ int sigkey)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::remove_handler");
+
+ return this->signal_handler_->remove_handler (signum,
+ new_disp,
+ old_disp,
+ sigkey);
+}
+
+int
+ACE_Dev_Poll_Reactor::remove_handler (const ACE_Sig_Set &sigset)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::remove_handler");
+
+ int result = 0;
+
+#if (ACE_NSIG > 0)
+
+ for (int s = 1; s < ACE_NSIG; ++s)
+ if ((sigset.is_member (s) == 1)
+ && this->signal_handler_->remove_handler (s) == -1)
+ result = -1;
+
+#else /* ACE_NSIG <= 0 */
+
+ ACE_UNUSED_ARG (sigset);
+
+#endif /* ACE_NSIG <= 0 */
+
+ return result;
+}
+
+int
+ACE_Dev_Poll_Reactor::suspend_handler (ACE_Event_Handler *event_handler)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::suspend_handler");
+
+ if (event_handler == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ACE_HANDLE handle = event_handler->get_handle ();
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->suspend_handler_i (handle);
+}
+
+int
+ACE_Dev_Poll_Reactor::suspend_handler (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::suspend_handler");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->suspend_handler_i (handle);
+}
+
+int
+ACE_Dev_Poll_Reactor::suspend_handler (const ACE_Handle_Set &handles)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::suspend_handler");
+
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ ACE_HANDLE h;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->suspend_handler_i (h) == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::suspend_handlers (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::suspend_handlers");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ size_t const len = this->handler_rep_.size ();
+
+ for (size_t i = 0; i < len; ++i)
+ if (this->handler_rep_.suspended (i) == 0
+ && this->suspend_handler_i (i) != 0)
+ return -1;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::suspend_handler_i (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::suspend_handler_i");
+
+ if (this->handler_rep_.find (handle) == 0)
+ return -1;
+
+ if (this->handler_rep_.suspended (handle))
+ return 0; // Already suspended. @@ Should this be an error?
+
+ // Remove the handle from the "interest set."
+ //
+ // Note that the associated event handler is still in the handler
+ // repository, but no events will be polled on the given handle thus
+ // no event will be dispatched to the event handler.
+
+#if defined (ACE_HAS_EVENT_POLL)
+
+ struct epoll_event epev;
+ ACE_OS::memset (&epev, 0, sizeof (epev));
+ static const int op = EPOLL_CTL_DEL;
+
+ epev.events = 0;
+ epev.data.fd = handle;
+
+ if (::epoll_ctl (this->poll_fd_, op, handle, &epev) == -1)
+ return -1;
+
+#else
+
+ struct pollfd pfd[1];
+
+ pfd[0].fd = handle;
+ pfd[0].events = POLLREMOVE;
+ pfd[0].revents = 0;
+
+ if (ACE_OS::write (this->poll_fd_, pfd, sizeof (pfd)) != sizeof (pfd))
+ return -1;
+
+#endif /* ACE_HAS_EVENT_POLL */
+
+ this->handler_rep_.suspend (handle);
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::resume_handler (ACE_Event_Handler *event_handler)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::resume_handler");
+
+ if (event_handler == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ACE_HANDLE handle = event_handler->get_handle ();
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->resume_handler_i (handle);
+}
+
+int
+ACE_Dev_Poll_Reactor::resume_handler (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::resume_handler");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->resume_handler_i (handle);
+}
+
+int
+ACE_Dev_Poll_Reactor::resume_handler (const ACE_Handle_Set &handles)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::resume_handler");
+
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ ACE_HANDLE h;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->resume_handler_i (h) == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::resume_handlers (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::resume_handlers");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ size_t const len = this->handler_rep_.size ();
+
+ for (size_t i = 0; i < len; ++i)
+ if (this->handler_rep_.suspended (i)
+ && this->resume_handler_i (i) != 0)
+ return -1;
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::resume_handler_i (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::resume_handler_i");
+
+ if (this->handler_rep_.find (handle) == 0
+ && this->handler_rep_.suspended (handle) == 0)
+ return -1;
+
+ ACE_Reactor_Mask mask = this->handler_rep_.mask (handle);
+
+ if (mask == ACE_Event_Handler::NULL_MASK)
+ return -1;
+
+ // Place the handle back in to the "interest set."
+ //
+ // Events for the given handle will once again be polled.
+
+#if defined (ACE_HAS_EVENT_POLL)
+
+ struct epoll_event epev;
+ ACE_OS::memset (&epev, 0, sizeof (epev));
+ static const int op = EPOLL_CTL_ADD;
+
+ epev.events = this->reactor_mask_to_poll_event (mask);
+ epev.data.fd = handle;
+
+ if (::epoll_ctl (this->poll_fd_, op, handle, &epev) == -1)
+ return -1;
+
+#else
+
+ struct pollfd pfd[1];
+
+ pfd[0].fd = handle;
+ pfd[0].events = this->reactor_mask_to_poll_event (mask);
+ pfd[0].revents = 0;
+
+ if (ACE_OS::write (this->poll_fd_, pfd, sizeof (pfd)) != sizeof (pfd))
+ return -1;
+
+#endif /* ACE_HAS_EVENT_POLL */
+
+ this->handler_rep_.resume (handle);
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::resumable_handler (void)
+{
+ // @@ Is this correct?
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::uses_event_associations (void)
+{
+ // Since the Dev_Poll_Reactor does not do any event associations,
+ // this method always return zero.
+ return 0;
+}
+
+long
+ACE_Dev_Poll_Reactor::schedule_timer (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::schedule_timer");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ if (0 != this->timer_queue_)
+ return this->timer_queue_->schedule
+ (event_handler,
+ arg,
+ this->timer_queue_->gettimeofday () + delay,
+ interval);
+
+ errno = ESHUTDOWN;
+ return -1;
+}
+
+int
+ACE_Dev_Poll_Reactor::reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::reset_timer_interval");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ if (0 != this->timer_queue_)
+ return this->timer_queue_->reset_interval (timer_id, interval);
+
+ errno = ESHUTDOWN;
+ return -1;
+}
+
+int
+ACE_Dev_Poll_Reactor::cancel_timer (ACE_Event_Handler *event_handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::cancel_timer");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return (this->timer_queue_ == 0
+ ? 0
+ : this->timer_queue_->cancel (event_handler,
+ dont_call_handle_close));
+}
+
+int
+ACE_Dev_Poll_Reactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::cancel_timer");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return (this->timer_queue_ == 0
+ ? 0
+ : this->timer_queue_->cancel (timer_id,
+ arg,
+ dont_call_handle_close));
+}
+
+int
+ACE_Dev_Poll_Reactor::schedule_wakeup (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::schedule_wakeup");
+
+ return this->mask_ops (eh->get_handle (), mask, ACE_Reactor::ADD_MASK);
+}
+
+int
+ACE_Dev_Poll_Reactor::schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::schedule_wakeup");
+
+ return this->mask_ops (handle, mask, ACE_Reactor::ADD_MASK);
+}
+
+int
+ACE_Dev_Poll_Reactor::cancel_wakeup (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::cancel_wakeup");
+
+ return this->mask_ops (eh->get_handle (), mask, ACE_Reactor::CLR_MASK);
+}
+
+int
+ACE_Dev_Poll_Reactor::cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::cancel_wakeup");
+
+ return this->mask_ops (handle, mask, ACE_Reactor::CLR_MASK);
+}
+
+int
+ACE_Dev_Poll_Reactor::notify (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::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;
+}
+
+void
+ACE_Dev_Poll_Reactor::max_notify_iterations (int iterations)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::max_notify_iterations");
+
+ ACE_MT (ACE_GUARD (ACE_Dev_Poll_Reactor_Token, mon, this->token_));
+
+ this->notify_handler_->max_notify_iterations (iterations);
+}
+
+int
+ACE_Dev_Poll_Reactor::max_notify_iterations (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::max_notify_iterations");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->notify_handler_->max_notify_iterations ();
+}
+
+int
+ACE_Dev_Poll_Reactor::purge_pending_notifications (ACE_Event_Handler * eh,
+ ACE_Reactor_Mask mask)
+{
+ if (this->notify_handler_ == 0)
+ return 0;
+
+ return this->notify_handler_->purge_pending_notifications (eh, mask);
+}
+
+ACE_Event_Handler *
+ACE_Dev_Poll_Reactor::find_handler (ACE_HANDLE handle)
+{
+ ACE_MT (ACE_READ_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, 0));
+
+ ACE_Event_Handler *event_handler = this->handler_rep_.find (handle);
+ if (event_handler)
+ event_handler->add_reference ();
+ return event_handler;
+}
+
+int
+ACE_Dev_Poll_Reactor::handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::handler");
+
+ ACE_MT (ACE_READ_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ ACE_Event_Handler *h = this->handler_rep_.find (handle);
+
+ if (h != 0
+ && ACE_BIT_CMP_MASK (this->handler_rep_.mask (handle),
+ mask, // Compare all bits in the mask
+ mask))
+ {
+ if (event_handler != 0)
+ *event_handler = h;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+ACE_Dev_Poll_Reactor::handler (int signum,
+ ACE_Event_Handler **eh)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::handler");
+
+ ACE_Event_Handler *handler = this->signal_handler_->handler (signum);
+
+ if (handler == 0)
+ return -1;
+ else if (eh != 0)
+ *eh = handler;
+
+ return 0;
+}
+
+bool
+ACE_Dev_Poll_Reactor::initialized (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::initialized");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, false));
+
+ return this->initialized_;
+}
+
+size_t
+ACE_Dev_Poll_Reactor::size (void) const
+{
+ return this->size_;
+}
+
+ACE_Lock &
+ACE_Dev_Poll_Reactor::lock (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::lock");
+
+ return this->lock_adapter_;
+}
+
+void
+ACE_Dev_Poll_Reactor::wakeup_all_threads (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::wakeup_all_threads");
+
+ // 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);
+}
+
+int
+ACE_Dev_Poll_Reactor::owner (ACE_thread_t /* new_owner */,
+ ACE_thread_t * /* old_owner */)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::owner");
+
+ // There is no need to set the owner of the event loop. Multiple
+ // threads may invoke the event loop simulataneously.
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::owner (ACE_thread_t * /* owner */)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::owner");
+
+ // There is no need to set the owner of the event loop. Multiple
+ // threads may invoke the event loop simulataneously.
+
+ return 0;
+}
+
+int
+ACE_Dev_Poll_Reactor::restart (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::restart");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->restart_;
+}
+
+int
+ACE_Dev_Poll_Reactor::restart (int r)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::restart");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ int current_value = this->restart_;
+ this->restart_ = r;
+ return current_value;
+}
+
+void
+ACE_Dev_Poll_Reactor::requeue_position (int)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::requeue_position");
+}
+
+int
+ACE_Dev_Poll_Reactor::requeue_position (void)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::requeue_position");
+
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_Dev_Poll_Reactor::mask_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::mask_ops");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->mask_ops_i (event_handler->get_handle (), mask, ops);
+}
+
+int
+ACE_Dev_Poll_Reactor::mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::mask_ops");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Dev_Poll_Reactor_Token, mon, this->token_, -1));
+
+ return this->mask_ops_i (handle, mask, ops);
+}
+
+int
+ACE_Dev_Poll_Reactor::mask_ops_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::mask_ops_i");
+
+ if (this->handler_rep_.handle_in_range (handle) == 0)
+ return -1;
+
+ // Block out all signals until method returns.
+ ACE_Sig_Guard sb;
+
+ ACE_Reactor_Mask const old_mask = this->handler_rep_.mask (handle);
+ ACE_Reactor_Mask new_mask = old_mask;
+
+ // Perform GET, CLR, SET, and ADD operations on the interest/wait
+ // set and the suspend set (if necessary).
+ //
+ // 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.
+
+ switch (ops)
+ {
+ case ACE_Reactor::GET_MASK:
+ // The work for this operation is done in all cases at the
+ // begining of the function.
+ return old_mask;
+
+ case ACE_Reactor::CLR_MASK:
+ ACE_CLR_BITS (new_mask, mask);
+ break;
+
+ case ACE_Reactor::SET_MASK:
+ new_mask = mask;
+ break;
+
+ case ACE_Reactor::ADD_MASK:
+ ACE_SET_BITS (new_mask, mask);
+ break;
+
+ default:
+ return -1;
+ }
+
+ /// Reset the mask for the given handle.
+ this->handler_rep_.mask (handle, new_mask);
+
+ if (this->handler_rep_.suspended (handle) == 0)
+ {
+ // Only attempt to alter events for the handle from the
+ // "interest set" if it hasn't been suspended.
+
+ short const events = this->reactor_mask_to_poll_event (new_mask);
+
+#if defined (sun)
+ // Apparently events cannot be updated on-the-fly on Solaris so
+ // remove the existing events, and then add the new ones.
+ struct pollfd pfd[2];
+
+ pfd[0].fd = handle;
+ pfd[0].events = POLLREMOVE;
+ pfd[0].revents = 0;
+ pfd[1].fd = (events == POLLREMOVE ? ACE_INVALID_HANDLE : handle);
+ pfd[1].events = events;
+ pfd[1].revents = 0;
+
+ // Change the events associated with the given file descriptor.
+ if (ACE_OS::write (this->poll_fd_,
+ pfd,
+ sizeof (pfd)) != sizeof (pfd))
+ return -1;
+#elif defined (ACE_HAS_EVENT_POLL)
+
+ struct epoll_event epev;
+ ACE_OS::memset (&epev, 0, sizeof (epev));
+ int op;
+
+ // ACE_Event_Handler::NULL_MASK ???
+ if (new_mask == 0)
+ {
+ op = EPOLL_CTL_DEL;
+ epev.events = 0;
+ }
+ else
+ {
+ op = EPOLL_CTL_MOD;
+ epev.events = events;
+ }
+
+ epev.data.fd = handle;
+
+ if (::epoll_ctl (this->poll_fd_, op, handle, &epev) == -1)
+ {
+ // If a handle is closed, epoll removes it from the poll set
+ // automatically - we may not know about it yet. If that's the
+ // case, a mod operation will fail with ENOENT. Retry it as
+ // an add.
+ if (op == EPOLL_CTL_MOD && errno == ENOENT &&
+ ::epoll_ctl (this->poll_fd_, EPOLL_CTL_ADD, handle, &epev) == -1)
+ return -1;
+ }
+
+#else
+ pollfd pfd[1];
+
+ pfd[0].fd = handle;
+ pfd[0].events = events;
+ pfd[0].revents = 0;
+
+ // Change the events associated with the given file descriptor.
+ if (ACE_OS::write (this->poll_fd_,
+ pfd,
+ sizeof (pfd)) != sizeof (pfd))
+ return -1;
+#endif /*ACE_HAS_EVENT_POLL */
+ }
+
+ return old_mask;
+}
+
+int
+ACE_Dev_Poll_Reactor::ready_ops (ACE_Event_Handler * /* event_handler */,
+ ACE_Reactor_Mask /* mask */,
+ int /* ops */)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::ready_ops");
+
+ // Since the Dev_Poll_Reactor uses the poll result buffer, the
+ // ready_set cannot be directly manipulated outside of the event
+ // loop.
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_Dev_Poll_Reactor::ready_ops (ACE_HANDLE /* handle */,
+ ACE_Reactor_Mask /* mask */,
+ int /* ops */)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::ready_ops");
+
+ // Since the Dev_Poll_Reactor uses the poll result buffer, the
+ // ready_set cannot be directly manipulated outside of the event
+ // loop.
+ ACE_NOTSUP_RETURN (-1);
+}
+
+void
+ACE_Dev_Poll_Reactor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("restart_ = %d\n"), this->restart_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("initialized_ = %d"),
+ this->initialized_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("poll_fd_ = %d"), this->poll_fd_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("size_ = %u"), this->size_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("deactivated_ = %d"),
+ this->deactivated_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+short
+ACE_Dev_Poll_Reactor::reactor_mask_to_poll_event (ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::reactor_mask_to_poll_event");
+
+ if (mask == ACE_Event_Handler::NULL_MASK)
+ // No event. Remove from interest set.
+#if defined (ACE_HAS_EVENT_POLL)
+ return EPOLL_CTL_DEL;
+#else
+ return POLLREMOVE;
+#endif /* ACE_HAS_EVENT_POLL */
+
+ short events = 0;
+
+ // 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))
+ {
+#if defined (ACE_HAS_EVENT_POLL)
+ ACE_SET_BITS (events, EPOLLIN);
+#else
+ ACE_SET_BITS (events, POLLIN);
+#endif /*ACE_HAS_EVENT_POLL*/
+ }
+
+ // 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))
+ {
+#if defined (ACE_HAS_EVENT_POLL)
+ ACE_SET_BITS (events, EPOLLOUT);
+#else
+ ACE_SET_BITS (events, POLLOUT);
+#endif /*ACE_HAS_EVENT_POLL*/
+ }
+
+ // EXCEPT flag will place the handle in the except set.
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ {
+#if defined (ACE_HAS_EVENT_POLL)
+ ACE_SET_BITS (events, EPOLLPRI);
+#else
+ ACE_SET_BITS (events, POLLPRI);
+#endif /*ACE_HAS_EVENT_POLL*/
+ }
+
+ return events;
+}
+
+namespace {
+ void polite_sleep_hook (void *) { }
+}
+
+int
+ACE_Dev_Poll_Reactor::Token_Guard::acquire_quietly (ACE_Time_Value *max_wait)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::Token_Guard::acquire_quietly");
+
+ // Acquire the token but don't ping any waiters; just queue up politely.
+ int result = 0;
+ if (max_wait)
+ {
+ ACE_Time_Value tv = ACE_OS::gettimeofday ();
+ tv += *max_wait;
+
+ ACE_MT (result = this->token_.acquire_read (&polite_sleep_hook,
+ 0,
+ &tv));
+ }
+ else
+ {
+ ACE_MT (result = this->token_.acquire_read (&polite_sleep_hook));
+ }
+
+ // Check for timeouts and errors.
+ if (result == -1)
+ {
+ if (errno == ETIME)
+ return 0;
+ else
+ {
+ ACE_ERROR ((LM_ERROR, "%t: %p\n", "token acquire_read"));
+ return -1;
+ }
+ }
+
+ // We got the token and so let us mark ourselves as owner
+ this->owner_ = 1;
+
+ return result;
+}
+
+int
+ACE_Dev_Poll_Reactor::Token_Guard::acquire (ACE_Time_Value *max_wait)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::Token_Guard::acquire");
+
+ // Try to grab the token. If someone if already there, don't wake
+ // them up, just queue up in the thread pool.
+ int result = 0;
+ if (max_wait)
+ {
+ ACE_Time_Value tv = ACE_OS::gettimeofday ();
+ tv += *max_wait;
+
+ ACE_MT (result = this->token_.acquire (0, 0, &tv));
+ }
+ else
+ {
+ ACE_MT (result = this->token_.acquire ());
+ }
+
+ // 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_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */
diff --git a/ACE/ace/Dev_Poll_Reactor.h b/ACE/ace/Dev_Poll_Reactor.h
new file mode 100644
index 00000000000..b6af574ae3e
--- /dev/null
+++ b/ACE/ace/Dev_Poll_Reactor.h
@@ -0,0 +1,1252 @@
+// -*- C++ -*-
+
+// =========================================================================
+/**
+ * @file Dev_Poll_Reactor.h
+ *
+ * $Id$
+ *
+ * @c /dev/poll (or Linux @c sys_epoll) based Reactor implementation.
+ *
+ * @author Ossama Othman <ossama@dre.vanderbilt.edu>
+ */
+// =========================================================================
+
+
+#ifndef ACE_DEV_POLL_REACTOR_H
+#define ACE_DEV_POLL_REACTOR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_EVENT_POLL) && defined (ACE_HAS_DEV_POLL)
+# error ACE_HAS_EVENT_POLL and ACE_HAS_DEV_POLL are mutually exclusive.
+#endif /* ACE_HAS_EVENT_POLL && defined ACE_HAS_DEV_POLL */
+
+#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
+
+#include "ace/Pipe.h"
+#include "ace/Lock_Adapter_T.h"
+#include "ace/Reactor_Impl.h"
+#include "ace/Reactor_Token_T.h"
+#include "ace/Token.h"
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+# include "ace/Notification_Queue.h"
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+#if defined (ACE_HAS_DEV_POLL)
+struct pollfd;
+#elif defined (ACE_HAS_EVENT_POLL)
+struct epoll_event;
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations
+class ACE_Sig_Handler;
+class ACE_Dev_Poll_Reactor;
+
+/**
+ * @class ACE_Dev_Poll_Event_Tuple
+ *
+ * @brief Class that associates specific event mask with a given event
+ * handler.
+ *
+ * This class merely provides a means to associate an event mask
+ * with an event handler. Such an association is needed since it is
+ * not possible to retrieve the event mask from the "interest set"
+ * stored in the `/dev/poll' or `/dev/epoll' driver. Without this
+ * external association, it would not be possible keep track of the
+ * event mask for a given event handler when suspending it or resuming
+ * it.
+ *
+ * @note An ACE_Handle_Set is not used since the number of handles may
+ * exceed its capacity (ACE_DEFAULT_SELECT_REACTOR_SIZE).
+ */
+class ACE_Dev_Poll_Event_Tuple
+{
+public:
+
+ /// Constructor.
+ ACE_Dev_Poll_Event_Tuple (void);
+
+public:
+
+ /// The event handler.
+ ACE_Event_Handler *event_handler;
+
+ /// The event mask for the above event handler.
+ ACE_Reactor_Mask mask;
+
+ /// Flag that states whether or not the event handler is suspended.
+ char suspended;
+};
+
+// ---------------------------------------------------------------------
+
+#if 0
+/**
+ * @class ACE_Dev_Poll_Ready_Set
+ *
+ * @brief Class that contains the list of "ready" file descriptors.
+ *
+ * This class points to an array of pollfd structures corresponding to
+ * "ready" file descriptors, such as those corresponding to event
+ * handlers that request an additional callback after being initially
+ * dispatched (i.e. return a value greater than zero).
+ * @par
+ * The idea is to store the "ready" set in an existing area of memory
+ * that already contains pollfd instances. Doing so is safe since the
+ * "ready" set is dispatched before polling for additional events,
+ * thus avoiding being potentially overwritten during the event poll.
+ * @par
+ * When the "ready" set is dispatched, all that needs to be done is to
+ * iterate over the contents of the array. There is no need to "walk"
+ * the array in search of ready file descriptors since the array by
+ * design only contains ready file descriptors. As such, this
+ * implementation of a ready set is much more efficient in the
+ * presence of a large number of file descriptors in terms of both
+ * time and space than the one used in the Select_Reactor, for
+ * example.
+ */
+class ACE_Dev_Poll_Ready_Set
+{
+public:
+
+ /// Constructor.
+ ACE_Dev_Poll_Ready_Set (void);
+
+public:
+
+ /// The array containing the pollfd structures corresponding to the
+ /// "ready" file descriptors.
+ struct pollfd *pfds;
+
+ /// The number of "ready" file descriptors in the above array.
+ int nfds;
+
+};
+#endif /* 0 */
+
+// ---------------------------------------------------------------------
+
+/**
+ * @class ACE_Dev_Poll_Reactor_Notify
+ *
+ * @brief Event handler used for unblocking the ACE_Dev_Poll_Reactor
+ * from its event loop.
+ *
+ * This event handler is used internally by the ACE_Dev_Poll_Reactor
+ * as a means to allow a thread other then the one running the event
+ * loop to unblock the event loop.
+ */
+class ACE_Dev_Poll_Reactor_Notify : public ACE_Reactor_Notify
+{
+public:
+
+ /// Constructor
+ ACE_Dev_Poll_Reactor_Notify (void);
+
+ /**
+ * @name Initialization and Termination Methods
+ *
+ * Methods called when initializing and terminating this event
+ * handler.
+ */
+ virtual int open (ACE_Reactor_Impl *,
+ ACE_Timer_Queue *timer_queue = 0,
+ int disable_notify = 0);
+ virtual int close (void);
+
+ /**
+ * Called by a thread when it wants to unblock the Reactor_Impl.
+ * This wakes up 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 block
+ * 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 int notify (ACE_Event_Handler *eh = 0,
+ ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value *timeout = 0);
+
+ /// Unimplemented method required by pure virtual method in abstract
+ /// base class.
+ /**
+ * This method's interface is not very compatibile with this
+ * Reactor's design. It's not clear why this method is pure virtual
+ * either.
+ */
+ 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 Reactor_Impl.
+ virtual ACE_HANDLE notify_handle (void);
+
+ /// Verify whether the buffer has dispatchable info or not.
+ virtual int is_dispatchable (ACE_Notification_Buffer &buffer);
+
+ /// Handle one notify call represented in @a buffer. This could be
+ /// because of a thread trying to unblock the Reactor_Impl.
+ virtual int dispatch_notify (ACE_Notification_Buffer &buffer);
+
+ /// Read one notify call on the handle into @a 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);
+
+ /// Called back by the ACE_Dev_Poll_Reactor when a thread wants to
+ /// unblock us.
+ virtual int handle_input (ACE_HANDLE handle);
+
+ /**
+ * 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);
+
+ /**
+ * 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);
+
+ /**
+ * 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);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+protected:
+
+ /**
+ * Keep a back pointer to the ACE_Dev_Poll_Reactor. If this value
+ * if NULL then the ACE_Dev_Poll_Reactor has been initialized with
+ * disable_notify_pipe.
+ */
+ ACE_Dev_Poll_Reactor *dp_reactor_;
+
+ /**
+ * Contains the ACE_HANDLE the ACE_Dev_Poll_Reactor is listening
+ * on, as well as the ACE_HANDLE that threads wanting the attention
+ * of the ACE_Dev_Poll_Reactor will write to.
+ */
+ ACE_Pipe notification_pipe_;
+
+ /**
+ * Keeps track of the maximum number of times that the
+ * ACE_Dev_Poll_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)
+ /**
+ * @brief A user-space queue to store the notifications.
+ *
+ * The notification pipe has OS-specific size restrictions. That
+ * is, no more than a certain number of bytes may be stored in the
+ * pipe without blocking. This limit may be too small for certain
+ * applications. In this case, ACE can be configured to store all
+ * the events in user-space. The pipe is still needed to wake up
+ * the reactor thread, but only one event is sent through the pipe
+ * at a time.
+ */
+ ACE_Notification_Queue notification_queue_;
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+};
+
+// ---------------------------------------------------------------------
+
+/**
+ * @class ACE_Dev_Poll_Reactor_Handler_Repository
+ *
+ * @internal
+
+ * @brief Used to map ACE_HANDLEs onto the appropriate
+ * ACE_Event_Handler *.
+ *
+ *
+ * This class is simply a container that maps a handle to its
+ * corresponding event handler. It is not meant for use outside of
+ * the Dev_Poll_Reactor.
+ */
+class ACE_Dev_Poll_Reactor_Handler_Repository
+{
+public:
+
+ /// Constructor.
+ ACE_Dev_Poll_Reactor_Handler_Repository (void);
+
+ /// Initialize a repository of the appropriate @a size.
+ int open (size_t size);
+
+ /// Close down the repository.
+ int close (void);
+
+ /**
+ * @name Repository Manipulation Operations
+ *
+ * Methods used to search and modify the handler repository.
+ */
+ //@{
+
+ /**
+ * Return the @c ACE_Event_Handler associated with @c ACE_HANDLE. If
+ * @a index_p is non-zero, then return the index location of the
+ * handle, if found.
+ */
+ ACE_Event_Handler *find (ACE_HANDLE handle, size_t *index_p = 0);
+
+ /// Set the event mask for event handler associated with the given
+ /// handle.
+ void mask (ACE_HANDLE handle, ACE_Reactor_Mask mask);
+
+ /// Retrieve the event mask for the event handler associated with
+ /// the given handle.
+ ACE_Reactor_Mask mask (ACE_HANDLE handle);
+
+ /// Mark the event handler associated with the given handle as
+ /// "suspended."
+ void suspend (ACE_HANDLE handle);
+
+ /// Mark the event handler associated with the given handle as
+ /// "resumed."
+ void resume (ACE_HANDLE handle);
+
+ /// Is the event handler for the given handle suspended?
+ int suspended (ACE_HANDLE handle) const;
+
+ /// Bind the ACE_Event_Handler to the @c ACE_HANDLE with the
+ /// appropriate ACE_Reactor_Mask settings.
+ int bind (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Remove the binding for @c ACE_HANDLE; optionally decrement the associated
+ /// handler's reference count.
+ int unbind (ACE_HANDLE handle, bool decr_refcnt = true);
+
+ /// Remove all the (@c ACE_HANDLE, @c ACE_Event_Handler) tuples.
+ int unbind_all (void);
+
+ /**
+ * @name Sanity Checking
+ *
+ * Methods used to prevent "out-of-range" errors when indexing the
+ * underlying handler array.
+ */
+ //@{
+
+ // Check the @a handle to make sure it's a valid @c ACE_HANDLE that
+ // within the range of legal handles (i.e., greater than or equal to
+ // zero and less than @c max_size_).
+ int invalid_handle (ACE_HANDLE handle) const;
+
+ // Check the handle to make sure it's a valid @c ACE_HANDLE that is
+ // within the range of currently registered handles (i.e., greater
+ // than or equal to zero and less than @c max_handlep1_).
+ int handle_in_range (ACE_HANDLE handle) const;
+
+ //@}
+
+ /// Returns the current table size.
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /// Maximum number of handles.
+ int max_size_;
+
+ /// The underlying array of event handlers.
+ /**
+ * The array of event handlers is directly indexed directly using
+ * an @c ACE_HANDLE value. This is Unix-specific.
+ */
+ ACE_Dev_Poll_Event_Tuple *handlers_;
+
+};
+
+// ---------------------------------------------------------------------
+
+/**
+ * @class ACE_Dev_Poll_Reactor
+ *
+ * @brief A `/dev/poll' or `/dev/epoll' based Reactor implemenatation.
+ *
+ * @attention The Linux epoll implementation works quite well and is
+ * fully supported; however, the /dev/poll implementation is @em experimental.
+ *
+ * The ACE_Dev_Poll_Reactor uses the `/dev/poll' or '/dev/epoll'
+ * character devices to demultiplex events on a given set of file
+ * descriptors. Unlike @c select(), `/dev/poll' and `/dev/epoll' have
+ * no hard-coded limit on the number of file descriptors that may be
+ * handled at any given time. As such, the ACE_Dev_Poll_Reactor can
+ * generally handle a much larger number of file descriptors than
+ * @c select() -based reactors. Furthermore, since `/dev/poll' and
+ * `/dev/epoll' both return a set of file descriptors that are active,
+ * there is no need to "walk" the set of file descriptors to determine
+ * which ones are active, such as what is done with the @c select() and
+ * @c poll() system calls. All returned file descriptors are active.
+ * This makes event dispatching very efficient.
+ *
+ * @note In general, this reactor may only be used to demultiplex
+ * events on sockets. Demultiplexing events on pipes, for
+ * example may not work. This is due to a limitation in the
+ * underlying `/dev/poll' device driver.
+ *
+ * @note It is only possible to achieve millisecond timeout
+ * resolutions with the @c ACE_Dev_Poll_Reactor. However, the
+ * timeout resolution for timers is independent of the reactors
+ * timeout resolution. As such, it may be possible to achieve
+ * sub-millisecond timeout resolutions for timers but that is
+ * entirely platform dependent.
+ */
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+typedef ACE_Token ACE_DEV_POLL_TOKEN;
+#else
+typedef ACE_Noop_Token ACE_DEV_POLL_TOKEN;
+#endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+typedef ACE_Reactor_Token_T<ACE_DEV_POLL_TOKEN> ACE_Dev_Poll_Reactor_Token;
+
+class ACE_Export ACE_Dev_Poll_Reactor : public ACE_Reactor_Impl
+{
+public:
+
+ /// Initialize @c ACE_Dev_Poll_Reactor with the default size.
+ /**
+ * The default size for the @c ACE_Dev_Poll_Reactor is the maximum
+ * number of open file descriptors for the process.
+ */
+ ACE_Dev_Poll_Reactor (ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = 0,
+ ACE_Reactor_Notify *notify = 0,
+ int mask_signals = 1,
+ int s_queue = ACE_DEV_POLL_TOKEN::FIFO);
+
+ /// Initialize ACE_Dev_Poll_Reactor with size @a size.
+ /**
+ * @note On Unix platforms, the @a 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. If the size
+ * parameter is less than the process maximum, the process
+ * maximum will be decreased in order to prevent potential
+ * access violations.
+ */
+ ACE_Dev_Poll_Reactor (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,
+ int s_queue = ACE_DEV_POLL_TOKEN::FIFO);
+
+ /// Close down and release all resources.
+ virtual ~ACE_Dev_Poll_Reactor (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);
+
+ /**
+ * @param handle allows the reactor to check if the caller is
+ * valid.
+ *
+ * @return 0 if the size of the current message has been put in
+ * size. -1 if not.
+ */
+ virtual int current_info (ACE_HANDLE handle, size_t & /* size */);
+
+ /// Use a user specified signal handler instead.
+ virtual int set_sig_handler (ACE_Sig_Handler *signal_handler);
+
+ /// Set a user-specified timer queue.
+ virtual int timer_queue (ACE_Timer_Queue *tq);
+
+ /// Get the timer queue
+ /// @return The current @c ACE_Timer_Queue.
+ 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".
+ *
+ * @note It is only possible to achieve millisecond timeout
+ * resolutions with the @c ACE_Dev_Poll_Reactor.
+ */
+ virtual int work_pending (
+ const ACE_Time_Value &max_wait_time = ACE_Time_Value::zero);
+
+ /**
+ * This event loop driver blocks for up to @a max_wait_time before
+ * returning. It will return earlier if events occur. Note that
+ * @a max_wait_time can be 0, in which case this method blocks
+ * indefinitely until events occur.
+ * @par
+ * @a 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 @c handle_events() and an event occurs after 2 seconds,
+ * @a max_wait_time will equal 1 second. This can be used if an
+ * application wishes to handle events for some fixed amount of
+ * time.
+ * @par
+ * The only difference between @c alertable_handle_events() and
+ * handle_events() is that in the alertable case, the event loop
+ * will return when the system queues an I/O completion routine or
+ * an Asynchronous Procedure Call.
+ *
+ * @return The total number of @c ACE_Event_Handlers that were
+ * dispatched, 0 if the @a max_wait_time elapsed without
+ * dispatching any handlers, or -1 if an error occurs.
+
+ * @note It is only possible to achieve millisecond timeout
+ * resolutions with the @c ACE_Dev_Poll_Reactor.
+ */
+ 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
+ * @a max_wait_time value is a reference and can therefore never be
+ * @c NULL.
+ *
+ * @note It is only possible to achieve millisecond timeout
+ * resolutions with the @c ACE_Dev_Poll_Reactor.
+ */
+ 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, @c handle_events() and
+ * @c handle_alertable_events() return -1 immediately.
+ */
+ virtual int deactivated (void);
+
+ /**
+ * Control whether the Reactor will handle any more incoming events
+ * or not. If @a do_stop == 1, the Reactor will be disabled. By
+ * default, a reactor is in active state and can be
+ * deactivated/reactived as desired.
+ */
+ virtual void deactivate (int do_stop);
+
+ // = Register and remove Handlers.
+
+ /// Register @a event_handler with @a 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 @a event_handler with @a mask. The I/O handle is
+ /// provided through the @a io_handle parameter.
+ virtual int register_handler (ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register an @a event_handler that will be notified when
+ * @a event_handle is signaled. @a mask specifies the network
+ * events that the @a 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 @a event_handler> with all the @a handles> in the @c
+ /// Handle_Set.
+ virtual int register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register @a new_sh to handle the signal @a signum using the
+ * @a new_disp. Returns the @a old_sh that was previously
+ * registered (if any), along with the @a 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 @a event_handler.
+ /**
+ * @note The I/O handle will be obtained using @c get_handle()
+ * method of @a event_handler . If @a mask ==
+ * @c ACE_Event_Handler::DONT_CALL then the @c handle_close()
+ * method of the @a event_handler is not invoked.
+ */
+ virtual int remove_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Removes @a handle. If @a 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);
+
+ /**
+ * Removes all handles in <handle_set>. If @a 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 @a signum.
+ * Install the new disposition (if given) and return the previous
+ * disposition (if desired by the caller). Returns 0 on success and
+ * -1 if @a 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, i.e., can it pass on the control of handle resumption to
+ /// the application.
+ 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.
+ 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 delay time interval after which the timer will expire.
+ * @param interval time interval for 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 @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a 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
+ /// @a 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 @a timer_id value
+ * (which was returned from the schedule method). If @a 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 @a 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 @a masks_to_be_added to the @a event_handler's entry.
+ /// @a event_handler must already have been registered.
+ virtual int schedule_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_added);
+
+ /// Add @a masks_to_be_added to the @a handle's entry. <event_handler>
+ /// associated with @a handle must already have been registered.
+ virtual int schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_added);
+
+ /// Clear @a masks_to_be_cleared from the @a event_handler's entry.
+ virtual int cancel_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_cleared);
+
+ /// Clear @a masks_to_be_cleared from the @a handle's entry.
+ virtual int cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_cleared);
+
+ // = Notification methods.
+
+ /**
+ * Notify @a event_handler of @a mask event. The ACE_Time_Value
+ * indicates how long to blocking trying to notify. If @a timeout ==
+ * 0, the caller will block until action is possible, else will wait
+ * until the relative time specified in @a timeout elapses).
+ */
+ virtual int notify (ACE_Event_Handler *event_handler = 0,
+ ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value * = 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);
+
+ /**
+ * 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);
+
+ /**
+ * 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);
+
+ /**
+ * Return the Event_Handler associated with @a handle. Return 0 if
+ * @a handle is not registered.
+ */
+ virtual ACE_Event_Handler *find_handler (ACE_HANDLE handle);
+
+ /**
+ * Check to see if @a handle is associated with a valid Event_Handler
+ * bound to @a mask. Return the @a event_handler associated with this
+ * @c handler if @a event_handler != 0.
+ */
+ virtual int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler = 0);
+
+ /**
+ * Check to see if @a signum is associated with a valid Event_Handler
+ * bound to a signal. Return the @a event_handler associated with
+ * this @c handler if @a event_handler != 0.
+ */
+ virtual int handler (int signum,
+ ACE_Event_Handler ** = 0);
+
+ /// Returns true if Reactor has been successfully initialized, else
+ /// false.
+ virtual bool 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 waiting in the event loop.
+ virtual void wakeup_all_threads (void);
+
+ /// Transfers ownership of Reactor_Impl to the new_owner.
+ /**
+ * @note There is no need to set the owner of the event loop for the
+ * ACE_Dev_Poll_Reactor. Multiple threads may invoke the
+ * event loop simulataneously. As such, this method is a
+ * no-op.
+ */
+ virtual int owner (ACE_thread_t new_owner, ACE_thread_t *old_owner = 0);
+
+ /// Return the ID of the "owner" thread.
+ /**
+ * @note There is no need to set the owner of the event loop for the
+ * ACE_Dev_Poll_Reactor. Multiple threads may invoke the
+ * event loop simulataneously. As such, this method is a
+ * no-op.
+ */
+ 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.
+ /**
+ * @param r If zero, then the event loop will not be automatically
+ * restarted if the underlying poll is interrupted via the
+ * INTR (interrupt) signal.
+ *
+ * @return Returns the previous "restart" value.
+ */
+ virtual int restart (int r);
+
+ /// Set position of the owner thread.
+ /**
+ * @note This is currently a no-op.
+ */
+ virtual void requeue_position (int);
+
+ /// Get position of the owner thread.
+ /**
+ * @note This is currently a no-op.
+ */
+ virtual int requeue_position (void);
+
+ /**
+ * @name Low-level wait_set mask manipulation methods
+ *
+ * Low-level methods to manipulate the event/reactor mask associated
+ * with a handle and event handler when polling for events.
+ * @par
+ * The "interest set," i.e. the wait set, can be directly
+ * manipulated with these methods.
+ */
+ //@{
+
+ /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the
+ /// event_handler and mask.
+ /**
+ * @return Old mask on success, -1 on error.
+ */
+ 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.
+ /**
+ * @return Old mask on success, -1 on error.
+ */
+ virtual int mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ //@}
+
+ /**
+ * @name Low-level ready_set mask manipulation methods
+ *
+ * These methods are unimplemented.
+ */
+ //@{
+
+ /// 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,
+ int ops);
+
+ //@}
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ class Token_Guard;
+
+ /// Non-locking version of wait_pending().
+ /**
+ * 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".
+ *
+ * @note It is only possible to achieve millisecond timeout
+ * resolutions with the ACE_Dev_Poll_Reactor.
+ */
+ int work_pending_i (ACE_Time_Value *max_wait_time);
+
+ /// Poll for events and return the number of event handlers that
+ /// were dispatched.
+ /**
+ * This is a helper method called by all handle_events() methods.
+ */
+ int handle_events_i (ACE_Time_Value *max_wait_time, Token_Guard &guard);
+
+ /// Perform the upcall with the given event handler method.
+ int upcall (ACE_Event_Handler *event_handler,
+ int (ACE_Event_Handler::*callback)(ACE_HANDLE),
+ ACE_HANDLE handle);
+
+ /**
+ * Dispatch ACE_Event_Handlers for time events, I/O events, and
+ * signal events. Returns the total number of ACE_Event_Handlers
+ * that were dispatched or -1 if something goes wrong.
+ */
+ int dispatch (Token_Guard &guard);
+
+ /// Dispatch a single timer, if ready.
+ /// Returns: 0 if no timers ready (token still held),
+ /// 1 if a timer was expired (token released),
+ /// -1 on error (token still held).
+ int dispatch_timer_handler (Token_Guard &guard);
+
+ /// Dispatch an IO event to the corresponding event handler. Returns
+ /// Returns: 0 if no events ready (token still held),
+ /// 1 if an event was expired (token released),
+ /// -1 on error (token still held).
+ int dispatch_io_event (Token_Guard &guard);
+
+ /// Register the given event handler with the reactor.
+ int register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /// Remove the event handler associated with the given handle and
+ /// event mask from the "interest set."
+ int remove_handler_i (ACE_HANDLE handle, ACE_Reactor_Mask mask);
+
+ /// Temporarily remove the given handle from the "interest set."
+ int suspend_handler_i (ACE_HANDLE handle);
+
+ /// Place the given handle that was temporarily removed from the
+ /// "interest set," i.e that was suspended, back in to the interest
+ /// set. The given handle will once again be polled for events.
+ int resume_handler_i (ACE_HANDLE handle);
+
+ /// GET/SET/ADD/CLR the dispatch MASK "bit" bound with the handle
+ /// and mask. This internal helper method acquires no lock.
+ /**
+ * @return Old mask on success, -1 on error.
+ */
+ int mask_ops_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// Convert a reactor mask to its corresponding poll() event mask.
+ short reactor_mask_to_poll_event (ACE_Reactor_Mask mask);
+
+protected:
+
+ /// Has the reactor been initialized.
+ bool initialized_;
+
+ /// The file descriptor associated with the open `/dev/poll' or
+ /// `/dev/epoll' device.
+ /**
+ * All interactions with the `/dev/poll' or `/dev/epoll' device are
+ * done through this file descriptor.
+ */
+ ACE_HANDLE poll_fd_;
+
+ /// The maximum number of file descriptors over which demultiplexing
+ /// will occur.
+ size_t size_;
+
+ /// Track HANDLES we are interested in for various events that must
+ /// be dispatched *without* polling.
+ /// ACE_Dev_Poll_Ready_Set ready_set_;
+
+#if defined (ACE_HAS_EVENT_POLL)
+ /// Table of event structures to be filled by epoll_wait:
+ struct epoll_event *events_;
+
+ /// Pointer to the next epoll_event array element that contains the next
+ /// event to be dispatched.
+ struct epoll_event *start_pevents_;
+
+ /// The last element in the event array plus one.
+ /**
+ * The loop that dispatches IO events stops when this->start_pevents_ ==
+ * this->end_pevents_.
+ */
+ struct epoll_event *end_pevents_;
+
+#else
+ /// The pollfd array that `/dev/poll' will feed its results to.
+ struct pollfd *dp_fds_;
+
+
+ /// Pointer to the next pollfd array element that contains the next
+ /// event to be dispatched.
+ struct pollfd *start_pfds_;
+
+ /// The last element in the pollfd array plus one.
+ /**
+ * The loop that dispatches IO events stops when this->start_pfds ==
+ * this->end_pfds_.
+ */
+ struct pollfd *end_pfds_;
+#endif /* ACE_HAS_EVENT_POLL */
+
+ /// This flag is used to keep track of whether we are actively handling
+ /// events or not.
+ sig_atomic_t deactivated_;
+
+ /// Lock used for synchronization of reactor state.
+ ACE_Dev_Poll_Reactor_Token token_;
+
+ /// Adapter used to return internal lock to outside world.
+ ACE_Lock_Adapter<ACE_Dev_Poll_Reactor_Token> lock_adapter_;
+
+ /// The repository that contains all registered event handlers.
+ ACE_Dev_Poll_Reactor_Handler_Repository handler_rep_;
+
+ /// 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).
+ bool 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).
+ bool 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).
+ bool delete_notify_handler_;
+
+ /// Flag that determines if signals are masked during event
+ /// dispatching.
+ /**
+ * 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_;
+
+ /// Restart the handle_events event loop method automatically when
+ /// polling function in use (ioctl() in this case) is interrupted
+ /// via an EINTR signal.
+ int restart_;
+
+protected:
+
+ /**
+ * @class Token_Guard
+ *
+ * @brief A helper class that helps grabbing, releasing and waiting
+ * on tokens for a thread that needs access to the reactor's token.
+ */
+ class ACE_Export Token_Guard
+ {
+ public:
+
+ /// Constructor that will grab the token for us
+ Token_Guard (ACE_Dev_Poll_Reactor_Token &token);
+
+ /// Destructor. This will release the token if it hasn't been
+ /// released till this point
+ ~Token_Guard (void);
+
+ /// Release the token ..
+ void release_token (void);
+
+ /// Returns whether the thread that created this object owns the
+ /// token or not.
+ int is_owner (void);
+
+ /// A helper method that acquires the token 1) at a low priority, and
+ /// 2) wait quietly for the token, not waking another thread. This
+ /// is appropriate for cases where a thread wants to wait for and
+ /// dispatch an event, not causing an existing waiter to relinquish the
+ /// token, and also queueing up behind other threads waiting to modify
+ /// event records.
+ int acquire_quietly (ACE_Time_Value *max_wait = 0);
+
+ /// A helper method that acquires the token at a high priority, and
+ /// does wake the current token holder.
+ int acquire (ACE_Time_Value *max_wait = 0);
+
+ private:
+
+ Token_Guard (void);
+
+ private:
+
+ /// The Reactor token.
+ ACE_Dev_Poll_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
+ /// hasn't got the token (and hence the thread) and a value of 1
+ /// vice-versa.
+ int owner_;
+
+ };
+
+};
+
+
+/**
+ * @class ACE_Dev_Poll_Handler_Guard
+ *
+ * @brief Class used to make event handler reference count
+ * manipulation exception-safe.
+ *
+ * This class makes the reference count manipulation that occurs
+ * during an upcall exception-safe. Prior to dispatching the event
+ * handler, the reference count is increased. Once the upcall for the
+ * given event handler is complete, its reference count will be decreased.
+ */
+class ACE_Dev_Poll_Handler_Guard
+{
+public:
+
+ /// Constructor
+ /**
+ * The constructor checks to see if @a eh is a reference-counted handler and
+ * remember that for later. If @a eh is reference counted, its reference
+ * count is incremented unless @a do_incr is false.
+ * @a do_incr should be false if the reference count was incremented
+ * independently of this guard, for example, on a notify handler since
+ * the reference count is incremented when the notify is queued.
+ */
+ ACE_Dev_Poll_Handler_Guard (ACE_Event_Handler *eh, bool do_incr = true);
+
+ /// Destructor
+ /**
+ * The destructor decrements the reference count on the event
+ * handler corresponding to the given handle.
+ */
+ ~ACE_Dev_Poll_Handler_Guard (void);
+
+ /// Release the event handler from this guard; when the destructor is
+ /// called, the handler's reference count will not be decremented.
+ void release (void);
+
+private:
+
+ /// The event handler being managed.
+ ACE_Event_Handler *eh_;
+
+ /// true if eh_ is a reference-counted handler.
+ bool refcounted_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Dev_Poll_Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_DEV_POLL_REACTOR_H */
diff --git a/ACE/ace/Dev_Poll_Reactor.inl b/ACE/ace/Dev_Poll_Reactor.inl
new file mode 100644
index 00000000000..b7034e07333
--- /dev/null
+++ b/ACE/ace/Dev_Poll_Reactor.inl
@@ -0,0 +1,228 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Dev_Poll_Event_Tuple::ACE_Dev_Poll_Event_Tuple (void)
+ : event_handler (0),
+ mask (ACE_Event_Handler::NULL_MASK),
+ suspended (0)
+{
+}
+
+// ---------------------------------------------------------------------
+
+#if 0
+ACE_INLINE
+ACE_Dev_Poll_Ready_Set::ACE_Dev_Poll_Ready_Set (void)
+ : pfds (0),
+ nfds (0)
+{
+}
+#endif /* 0 */
+
+// ---------------------------------------------------------------------
+
+ACE_INLINE void
+ACE_Dev_Poll_Reactor_Handler_Repository::mask (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::mask");
+
+ // Only bother to search for the handle if it's in range.
+ if (this->handle_in_range (handle))
+ this->handlers_[handle].mask = mask;
+}
+
+ACE_INLINE ACE_Reactor_Mask
+ACE_Dev_Poll_Reactor_Handler_Repository::mask (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::mask");
+
+ ACE_Reactor_Mask mask = ACE_Event_Handler::NULL_MASK;
+
+ // Only bother to search for the handle if it's in range.
+ if (this->handle_in_range (handle))
+ mask = this->handlers_[handle].mask;
+
+ if (mask == ACE_Event_Handler::NULL_MASK)
+ errno = ENOENT;
+
+ return mask;
+}
+
+ACE_INLINE void
+ACE_Dev_Poll_Reactor_Handler_Repository::suspend (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::suspend");
+
+ // Only bother to search for the handle if it's in range.
+ if (this->handle_in_range (handle))
+ this->handlers_[handle].suspended = 1;
+}
+
+ACE_INLINE void
+ACE_Dev_Poll_Reactor_Handler_Repository::resume (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::resume");
+
+ // Only bother to search for the handle if it's in range.
+ if (this->handle_in_range (handle))
+ this->handlers_[handle].suspended = 0;
+}
+
+ACE_INLINE int
+ACE_Dev_Poll_Reactor_Handler_Repository::suspended (ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::suspended");
+
+ if (this->handle_in_range (handle))
+ return this->handlers_[handle].suspended;
+
+ return -1;
+}
+
+ACE_INLINE size_t
+ACE_Dev_Poll_Reactor_Handler_Repository::size (void) const
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::size");
+
+ return this->max_size_;
+}
+
+// -----------------------------------------------------------------
+
+ACE_INLINE
+ACE_Dev_Poll_Handler_Guard::ACE_Dev_Poll_Handler_Guard
+ (ACE_Event_Handler *eh,
+ bool do_incr)
+ : eh_ (eh),
+ refcounted_ (false)
+{
+ if (eh == 0)
+ return;
+
+ this->refcounted_ =
+ eh->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ if (do_incr && this->refcounted_)
+ eh->add_reference ();
+
+ /**
+ * The below comments were here when I replaced the old refcount
+ * scheme was replaced. They may still need addressing. -Steve Huston
+ */
+
+ /**
+ * @todo Suspend the handler so that other threads will not cause
+ * an event that is already in an upcall from being dispatched
+ * again.
+ *
+ * @note The naive approach would be to simply call
+ * suspend_handler_i() on the reactor. However, that would
+ * cause a system call (write()) to occur. Obviously this
+ * can potentially have an adverse affect on performance.
+ * Ideally, the handler would only be marked as "suspended" in
+ * the handler repository. If an event arrives for a
+ * suspended handler that event can be "queued" in a
+ * "handle readiness queue." "Queued" is quoted since a real
+ * queue need not be used since duplicate events can be
+ * coalesced, thus avoiding unbounded queue growth. Event
+ * coalescing is already done by Linux's event poll driver
+ * (/dev/epoll) so Solaris' poll driver (/dev/poll) is the
+ * main concern here. The largest the queue can be is the
+ * same size as the number of handlers stored in the handler
+ * repository.
+ */
+}
+
+ACE_INLINE
+ACE_Dev_Poll_Handler_Guard::~ACE_Dev_Poll_Handler_Guard (void)
+{
+ if (this->refcounted_ && this->eh_ != 0)
+ this->eh_->remove_reference ();
+
+ /**
+ * The below comments were here when I replaced the old refcount
+ * scheme was replaced. They may still need addressing. -Steve Huston
+ */
+ /**
+ * @todo Resume the handler so that other threads will be allowed to
+ * dispatch the handler.
+ */
+}
+
+ACE_INLINE void
+ACE_Dev_Poll_Handler_Guard::release (void)
+{
+ this->eh_ = 0;
+}
+
+// ---------------------------------------------------------------------
+
+ACE_INLINE int
+ACE_Dev_Poll_Reactor::upcall (ACE_Event_Handler *event_handler,
+ int (ACE_Event_Handler::*callback)(ACE_HANDLE),
+ ACE_HANDLE handle)
+{
+ // If the handler returns positive value (requesting a reactor
+ // callback) just call back as many times as the handler requests
+ // it. Other threads are off handling other things.
+ int status = 0;
+
+ do
+ {
+ status = (event_handler->*callback) (handle);
+ }
+ while (status > 0);
+
+ return status;
+}
+
+
+/************************************************************************/
+// Methods for ACE_Dev_Poll_Reactor::Token_Guard
+/************************************************************************/
+
+ACE_INLINE
+ACE_Dev_Poll_Reactor::Token_Guard::Token_Guard (ACE_Dev_Poll_Reactor_Token &token)
+
+ : token_ (token),
+ owner_ (0)
+{
+}
+
+ACE_INLINE
+ACE_Dev_Poll_Reactor::Token_Guard::~Token_Guard (void)
+{
+ if (this->owner_ == 1)
+ {
+ ACE_MT (this->token_.release ());
+ this->owner_ = 0;
+ }
+}
+
+ACE_INLINE void
+ACE_Dev_Poll_Reactor::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_Dev_Poll_Reactor::Token_Guard::is_owner (void)
+{
+ return this->owner_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dirent.cpp b/ACE/ace/Dirent.cpp
new file mode 100644
index 00000000000..50aab1ac5f3
--- /dev/null
+++ b/ACE/ace/Dirent.cpp
@@ -0,0 +1,7 @@
+// $Id$
+
+#include "ace/Dirent.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Dirent.inl"
+#endif /* __ACE_INLINE__ */
diff --git a/ACE/ace/Dirent.h b/ACE/ace/Dirent.h
new file mode 100644
index 00000000000..823b28d747c
--- /dev/null
+++ b/ACE/ace/Dirent.h
@@ -0,0 +1,122 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Dirent.h
+ *
+ * $Id$
+ *
+ * Define a portable C++ interface to ACE_OS_Dirent directory-entry
+ * manipulation.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_DIRENT_H
+#define ACE_DIRENT_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_dirent.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Dirent
+ *
+ * @brief Define a portable C++ directory-entry iterator based on the POSIX API.
+ */
+class ACE_Export ACE_Dirent
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_Dirent (void);
+
+ /// Constructor calls <opendir>
+ explicit ACE_Dirent (const ACE_TCHAR *dirname);
+
+ /// Opens the directory named by filename and associates a directory
+ /// stream with it.
+ int open (const ACE_TCHAR *filename);
+
+ /// Destructor calls <closedir>.
+ ~ACE_Dirent (void);
+
+ /// Closes the directory stream and frees the <ACE_DIR> structure.
+ void close (void);
+
+ // = Iterator methods.
+ /**
+ * Returns a pointer to a structure representing the directory entry
+ * at the current position in the directory stream to which dirp
+ * refers, and positions the directory stream at the next entry,
+ * except on read-only filesystems. It returns a NULL pointer upon
+ * reaching the end of the directory stream, or upon detecting an
+ * invalid location in the directory. <readdir> shall not return
+ * directory entries containing empty names. It is unspecified
+ * whether entries are returned for dot or dot-dot. The pointer
+ * returned by <readdir> points to data that may be overwritten by
+ * another call to <readdir> on the same directory stream. This
+ * data shall not be overwritten by another call to <readdir> on a
+ * different directory stream. <readdir> may buffer several
+ * directory entries per actual read operation; <readdir> marks for
+ * update the st_atime field of the directory each time the
+ * directory is actually read.
+ */
+ ACE_DIRENT *read (void);
+
+ /**
+ * Has the equivalent functionality as <readdir> except that an
+ * @a entry and @a result buffer must be supplied by the caller to
+ * store the result.
+ */
+ int read (struct ACE_DIRENT *entry,
+ struct ACE_DIRENT **result);
+
+ // = Manipulators.
+ /// Returns the current location associated with the directory
+ /// stream.
+ long tell (void);
+
+ /**
+ * Sets the position of the next <readdir> operation on the
+ * directory stream. The new position reverts to the position
+ * associated with the directory stream at the time the <telldir>
+ * operation that provides loc was performed. Values returned by
+ * <telldir> are good only for the lifetime of the <ACE_DIR> pointer from
+ * which they are derived. If the directory is closed and then
+ * reopened, the <telldir> value may be invalidated due to
+ * undetected directory compaction. It is safe to use a previous
+ * <telldir> value immediately after a call to <opendir> and before
+ * any calls to readdir.
+ */
+ void seek (long loc);
+
+ /**
+ * Resets the position of the directory stream to the beginning of
+ * the directory. It also causes the directory stream to refer to
+ * the current state of the corresponding directory, as a call to
+ * <opendir> would.
+ */
+ void rewind (void);
+
+private:
+ /// Pointer to the directory stream.
+ ACE_DIR *dirp_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Dirent.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DIRENT_H */
diff --git a/ACE/ace/Dirent.inl b/ACE/ace/Dirent.inl
new file mode 100644
index 00000000000..5f6af5a3218
--- /dev/null
+++ b/ACE/ace/Dirent.inl
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Dirent::open (const ACE_TCHAR *dirname)
+{
+ // If the directory stream is already open, close it to prevent
+ // possible resource leaks.
+
+ if (this->dirp_ != 0)
+ {
+ ACE_OS::closedir (this->dirp_);
+ this->dirp_ = 0;
+ }
+
+ this->dirp_ = ACE_OS::opendir (dirname);
+
+ if (this->dirp_ == 0)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE
+ACE_Dirent::ACE_Dirent (void)
+ : dirp_ (0)
+{
+}
+
+ACE_INLINE
+ACE_Dirent::ACE_Dirent (const ACE_TCHAR *dirname)
+ : dirp_ (0)
+{
+ if (this->open (dirname) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Dirent::ACE_Dirent")));
+}
+
+ACE_INLINE
+ACE_Dirent::~ACE_Dirent (void)
+{
+ if (this->dirp_ != 0)
+ ACE_OS::closedir (this->dirp_);
+}
+
+ACE_INLINE ACE_DIRENT *
+ACE_Dirent::read (void)
+{
+ return this->dirp_ ? ACE_OS::readdir (this->dirp_) : 0;
+}
+
+ACE_INLINE int
+ACE_Dirent::read (struct ACE_DIRENT *entry,
+ struct ACE_DIRENT **result)
+{
+ return this->dirp_
+ ? ACE_OS::readdir_r (this->dirp_, entry, result)
+ : 0;
+}
+
+ACE_INLINE void
+ACE_Dirent::close (void)
+{
+ if (this->dirp_ != 0)
+ {
+ ACE_OS::closedir (this->dirp_);
+
+ // Prevent double closure
+ this->dirp_ = 0;
+ }
+}
+
+ACE_INLINE void
+ACE_Dirent::rewind (void)
+{
+ if (this->dirp_)
+ ACE_OS::rewinddir (this->dirp_);
+}
+
+ACE_INLINE void
+ACE_Dirent::seek (long loc)
+{
+ if (this->dirp_)
+ ACE_OS::seekdir (this->dirp_, loc);
+}
+
+ACE_INLINE long
+ACE_Dirent::tell (void)
+{
+ return this->dirp_ ? ACE_OS::telldir (this->dirp_) : 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dirent_Selector.cpp b/ACE/ace/Dirent_Selector.cpp
new file mode 100644
index 00000000000..288fc6deacf
--- /dev/null
+++ b/ACE/ace/Dirent_Selector.cpp
@@ -0,0 +1,59 @@
+// $Id$
+
+#include "ace/Dirent_Selector.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Dirent_Selector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/OS_NS_dirent.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID (ace,
+ Dirent_Selector,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Construction/Destruction
+
+ACE_Dirent_Selector::ACE_Dirent_Selector (void)
+ : namelist_ (0),
+ n_ (0)
+{
+}
+
+ACE_Dirent_Selector::~ACE_Dirent_Selector (void)
+{
+ // Free up any allocated resources.
+ this->close();
+}
+
+int
+ACE_Dirent_Selector::open (const ACE_TCHAR *dir,
+ ACE_SCANDIR_SELECTOR sel,
+ ACE_SCANDIR_COMPARATOR cmp)
+{
+ n_ = ACE_OS::scandir (dir, &this->namelist_, sel, cmp);
+ return n_;
+}
+
+int
+ACE_Dirent_Selector::close (void)
+{
+ for (--n_; n_ >= 0; --n_)
+ {
+#if defined (ACE_LACKS_STRUCT_DIR)
+ // Only the lacking-struct-dir emulation allocates this. Native
+ // scandir includes d_name in the dirent struct itself.
+ ACE_OS::free (this->namelist_[n_]->d_name);
+#endif
+ ACE_OS::free (this->namelist_[n_]);
+ }
+
+ ACE_OS::free (this->namelist_);
+ this->namelist_ = 0;
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dirent_Selector.h b/ACE/ace/Dirent_Selector.h
new file mode 100644
index 00000000000..72b1b176c03
--- /dev/null
+++ b/ACE/ace/Dirent_Selector.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Dirent_Selector.h
+ *
+ * $Id$
+ *
+ * Define a portable C++ interface to the <ACE_OS_Dirent::scandir> method.
+ *
+ * @author Rich Newman <RNewman@directv.com>
+ */
+//=============================================================================
+
+#ifndef ACE_DIRENT_SELECTOR_H
+#define ACE_DIRENT_SELECTOR_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_dirent.h" /* Need ACE_SCANDIR_SELECTOR, COMPARATOR */
+#include "ace/os_include/os_dirent.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Dirent_Selector
+ *
+ * @brief Define a portable C++ directory-entry iterator based on the
+ * POSIX scandir API.
+ */
+class ACE_Export ACE_Dirent_Selector
+{
+public:
+ /// Constructor
+ ACE_Dirent_Selector (void);
+
+ /// Destructor.
+ virtual ~ACE_Dirent_Selector (void);
+
+ /// Return the length of the list of matching directory entries.
+ int length (void) const;
+
+ /// Return the entry at @a index.
+ ACE_DIRENT *operator[] (const int index) const;
+
+ /// Free up resources.
+ int close (void);
+
+ /// Open the directory @a dir and populate the current list of names with
+ /// directory entries that match the @a selector and @a comparator.
+ int open (const ACE_TCHAR *dir,
+ ACE_SCANDIR_SELECTOR selector = 0,
+ ACE_SCANDIR_COMPARATOR comparator = 0);
+
+protected:
+ /// Ptr to the namelist array.
+ ACE_DIRENT **namelist_;
+
+ /// Number of entries in the array.
+ int n_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Dirent_Selector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DIRENT_SELECTOR_H */
diff --git a/ACE/ace/Dirent_Selector.inl b/ACE/ace/Dirent_Selector.inl
new file mode 100644
index 00000000000..7c42f46b9be
--- /dev/null
+++ b/ACE/ace/Dirent_Selector.inl
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Dirent_Selector::length (void) const
+{
+ return n_;
+}
+
+ACE_INLINE ACE_DIRENT *
+ACE_Dirent_Selector::operator[] (const int n) const
+{
+ return this->namelist_[n];
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dump.cpp b/ACE/ace/Dump.cpp
new file mode 100644
index 00000000000..b601496f3b6
--- /dev/null
+++ b/ACE/ace/Dump.cpp
@@ -0,0 +1,141 @@
+// $Id$
+
+#include "ace/Dump.h"
+#include "ace/Guard_T.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Dump, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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 const_cast <ACE_Dumpable *> (this->dumper_);
+ (const_cast<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;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dump.h b/ACE/ace/Dump.h
new file mode 100644
index 00000000000..97f0bac7966
--- /dev/null
+++ b/ACE/ace/Dump.h
@@ -0,0 +1,172 @@
+/* -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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
+ {
+ /// Pointer to the object that is registered.
+ const void *this_;
+
+ /// 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).
+ const ACE_Dumpable_Ptr dumper_;
+
+ 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Include the templates classes at this point.
+#include "ace/Dump_T.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DUMP_H */
diff --git a/ACE/ace/Dump_T.cpp b/ACE/ace/Dump_T.cpp
new file mode 100644
index 00000000000..3c789497eee
--- /dev/null
+++ b/ACE/ace/Dump_T.cpp
@@ -0,0 +1,48 @@
+// Dump_T.cpp
+//
+// $Id$
+
+#ifndef ACE_DUMP_T_CPP
+#define ACE_DUMP_T_CPP
+
+#include "ace/Dump_T.h"
+#include "ace/Global_Macros.h"
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Dumpable_Adapter<Concrete>::dump");
+ this->this_->dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_DUMP_T_CPP */
diff --git a/ACE/ace/Dump_T.h b/ACE/ace/Dump_T.h
new file mode 100644
index 00000000000..33249fb1fa9
--- /dev/null
+++ b/ACE/ace/Dump_T.h
@@ -0,0 +1,82 @@
+// -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @c this of <class Concrete>.
+ const Concrete *this_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// 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/ace/Dynamic.cpp b/ACE/ace/Dynamic.cpp
new file mode 100644
index 00000000000..adeae242579
--- /dev/null
+++ b/ACE/ace/Dynamic.cpp
@@ -0,0 +1,34 @@
+// $Id$
+
+#include "ace/Dynamic.h"
+#include "ace/Singleton.h"
+#include "ace/TSS_T.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Null_Mutex.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Dynamic.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Dynamic, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Dynamic::ACE_Dynamic (void)
+ : is_dynamic_ (false)
+{
+ ACE_TRACE ("ACE_Dynamic::ACE_Dynamic");
+}
+
+/* static */ ACE_Dynamic *
+ACE_Dynamic::instance (void)
+{
+ return ACE_TSS_Singleton<ACE_Dynamic, ACE_SYNCH_NULL_MUTEX>::instance ();
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_TSS_Singleton<ACE_Dynamic, ACE_Null_Mutex> *
+ ACE_TSS_Singleton<ACE_Dynamic, ACE_Null_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dynamic.h b/ACE/ace/Dynamic.h
new file mode 100644
index 00000000000..4d52b67673f
--- /dev/null
+++ b/ACE/ace/Dynamic.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Dynamic.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ * @author Irfan Pyarali.
+ */
+//==========================================================================
+
+#ifndef ACE_DYNAMIC_H
+#define ACE_DYNAMIC_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Dynamic
+ *
+ * @brief Checks to see if an object was dynamically allocated.
+ *
+ * This class holds the pointer in a thread-safe manner between
+ * the call to operator new and the call to the constructor.
+ */
+class ACE_Export ACE_Dynamic
+{
+public:
+ // = Initialization and termination method.
+ /// Constructor.
+ ACE_Dynamic (void);
+
+ /// Destructor.
+ ~ACE_Dynamic (void);
+
+ /**
+ * Sets a flag that indicates that the object was dynamically
+ * created. This method is usually called in operator new and then
+ * checked and reset in the constructor.
+ */
+ void set (void);
+
+ /// @c true if we were allocated dynamically, else @c false.
+ bool is_dynamic (void);
+
+ /// Resets state flag.
+ void reset (void);
+
+ static ACE_Dynamic *instance (void);
+
+private:
+ /**
+ * Flag that indicates that the object was dynamically created. This
+ * method is usually called in operator new and then checked and
+ * reset in the constructor.
+ */
+ bool is_dynamic_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Dynamic.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DYNAMIC_H */
diff --git a/ACE/ace/Dynamic.inl b/ACE/ace/Dynamic.inl
new file mode 100644
index 00000000000..3f506bc51f4
--- /dev/null
+++ b/ACE/ace/Dynamic.inl
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Dynamic::~ACE_Dynamic (void)
+{
+ // ACE_TRACE ("ACE_Dynamic::~ACE_Dynamic");
+}
+
+ACE_INLINE void
+ACE_Dynamic::set (void)
+{
+ // ACE_TRACE ("ACE_Dynamic::set");
+ this->is_dynamic_ = true;
+}
+
+ACE_INLINE bool
+ACE_Dynamic::is_dynamic (void)
+{
+ // ACE_TRACE ("ACE_Dynamic::is_dynamic");
+ return this->is_dynamic_;
+}
+
+ACE_INLINE void
+ACE_Dynamic::reset (void)
+{
+ // ACE_TRACE ("ACE_Dynamic::reset");
+ this->is_dynamic_ = false;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dynamic_Message_Strategy.cpp b/ACE/ace/Dynamic_Message_Strategy.cpp
new file mode 100644
index 00000000000..060aef6f5b5
--- /dev/null
+++ b/ACE/ace/Dynamic_Message_Strategy.cpp
@@ -0,0 +1,205 @@
+#include "ace/Dynamic_Message_Strategy.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Dynamic_Message_Strategy.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Malloc_Base.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ Dynamic_Message_Strategy,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// ctor
+
+ACE_Dynamic_Message_Strategy::ACE_Dynamic_Message_Strategy (unsigned long static_bit_field_mask,
+ unsigned long static_bit_field_shift,
+ unsigned long dynamic_priority_max,
+ unsigned long dynamic_priority_offset)
+ : static_bit_field_mask_ (static_bit_field_mask),
+ static_bit_field_shift_ (static_bit_field_shift),
+ dynamic_priority_max_ (dynamic_priority_max),
+ dynamic_priority_offset_ (dynamic_priority_offset),
+ max_late_ (0, dynamic_priority_offset - 1),
+ min_pending_ (0, dynamic_priority_offset),
+ pending_shift_ (0, dynamic_priority_max)
+{
+}
+
+// dtor
+
+ACE_Dynamic_Message_Strategy::~ACE_Dynamic_Message_Strategy (void)
+{
+}
+
+ACE_Dynamic_Message_Strategy::Priority_Status
+ACE_Dynamic_Message_Strategy::priority_status (ACE_Message_Block & mb,
+ const ACE_Time_Value & tv)
+{
+ // default the message to have pending priority status
+ Priority_Status status = ACE_Dynamic_Message_Strategy::PENDING;
+
+ // start with the passed absolute time as the message's priority, then
+ // call the polymorphic hook method to (at least partially) convert
+ // the absolute time and message attributes into the message's priority
+ ACE_Time_Value priority (tv);
+ convert_priority (priority, mb);
+
+ // if the priority is negative, the message is pending
+ if (priority < ACE_Time_Value::zero)
+ {
+ // priority for pending messages must be shifted
+ // upward above the late priority range
+ priority += pending_shift_;
+ if (priority < min_pending_)
+ priority = min_pending_;
+ }
+ // otherwise, if the priority is greater than the maximum late
+ // priority value that can be represented, it is beyond late
+ else if (priority > max_late_)
+ {
+ // all messages that are beyond late are assigned lowest priority (zero)
+ mb.msg_priority (0);
+ return ACE_Dynamic_Message_Strategy::BEYOND_LATE;
+ }
+ // otherwise, the message is late, but its priority is correct
+ else
+ status = ACE_Dynamic_Message_Strategy::LATE;
+
+ // use (fast) bitwise operators to isolate and replace
+ // the dynamic portion of the message's priority
+ mb.msg_priority((mb.msg_priority() & static_bit_field_mask_) |
+ ((priority.usec () +
+ ACE_ONE_SECOND_IN_USECS * (suseconds_t)(priority.sec())) <<
+ static_bit_field_shift_));
+
+ // returns the priority status of the message
+ return status;
+}
+
+
+// Dump the state of the strategy.
+
+void
+ACE_Dynamic_Message_Strategy::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Dynamic_Message_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("static_bit_field_mask_ = %u\n")
+ ACE_TEXT ("static_bit_field_shift_ = %u\n")
+ ACE_TEXT ("dynamic_priority_max_ = %u\n")
+ ACE_TEXT ("dynamic_priority_offset_ = %u\n")
+ ACE_TEXT ("max_late_ = [%d sec, %d usec]\n")
+ ACE_TEXT ("min_pending_ = [%d sec, %d usec]\n")
+ ACE_TEXT ("pending_shift_ = [%d sec, %d usec]\n"),
+ this->static_bit_field_mask_,
+ this->static_bit_field_shift_,
+ this->dynamic_priority_max_,
+ this->dynamic_priority_offset_,
+ this->max_late_.sec (),
+ this->max_late_.usec (),
+ this->min_pending_.sec (),
+ this->min_pending_.usec (),
+ this->pending_shift_.sec (),
+ this->pending_shift_.usec ()));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Deadline_Message_Strategy::ACE_Deadline_Message_Strategy (unsigned long static_bit_field_mask,
+ unsigned long static_bit_field_shift,
+ unsigned long dynamic_priority_max,
+ unsigned long dynamic_priority_offset)
+ : ACE_Dynamic_Message_Strategy (static_bit_field_mask,
+ static_bit_field_shift,
+ dynamic_priority_max,
+ dynamic_priority_offset)
+{
+}
+
+ACE_Deadline_Message_Strategy::~ACE_Deadline_Message_Strategy (void)
+{
+}
+
+void
+ACE_Deadline_Message_Strategy::convert_priority (ACE_Time_Value & priority,
+ const ACE_Message_Block & mb)
+{
+ // Convert absolute time passed in tv to negative time
+ // to deadline of mb with respect to that absolute time.
+ priority -= mb.msg_deadline_time ();
+}
+ // dynamic priority conversion function based on time to deadline
+
+void
+ACE_Deadline_Message_Strategy::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Deadline_Message_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Dynamic_Message_Strategy base class: \n")));
+ this->ACE_Dynamic_Message_Strategy::dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nderived class: ACE_Deadline_Message_Strategy\n")));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Laxity_Message_Strategy::ACE_Laxity_Message_Strategy (unsigned long static_bit_field_mask,
+ unsigned long static_bit_field_shift,
+ unsigned long dynamic_priority_max,
+ unsigned long dynamic_priority_offset)
+ : ACE_Dynamic_Message_Strategy (static_bit_field_mask,
+ static_bit_field_shift,
+ dynamic_priority_max,
+ dynamic_priority_offset)
+{
+}
+
+ACE_Laxity_Message_Strategy::~ACE_Laxity_Message_Strategy (void)
+{
+}
+
+void
+ACE_Laxity_Message_Strategy::convert_priority (ACE_Time_Value & priority,
+ const ACE_Message_Block & mb)
+{
+ // Convert absolute time passed in tv to negative
+ // laxity of mb with respect to that absolute time.
+ priority += mb.msg_execution_time ();
+ priority -= mb.msg_deadline_time ();
+}
+ // dynamic priority conversion function based on laxity
+
+void
+ACE_Laxity_Message_Strategy::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Laxity_Message_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Dynamic_Message_Strategy base class: \n")));
+ this->ACE_Dynamic_Message_Strategy::dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nderived class: ACE_Laxity_Message_Strategy\n")));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+ // Dump the state of the strategy.
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dynamic_Message_Strategy.h b/ACE/ace/Dynamic_Message_Strategy.h
new file mode 100644
index 00000000000..66448a8247b
--- /dev/null
+++ b/ACE/ace/Dynamic_Message_Strategy.h
@@ -0,0 +1,217 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Dynamic_Message_Strategy.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_DYNAMIC_MESSAGE_STRATEGY_H
+#define ACE_DYNAMIC_MESSAGE_STRATEGY_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Message_Block.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Dynamic_Message_Strategy
+ *
+ * @brief An abstract base class which provides dynamic priority
+ * evaluation methods for use by the ACE_Dynamic_Message_Queue
+ * class or any other class which needs to manage the priorities
+ * of a collection of ACE_Message_Blocks dynamically.
+ *
+ * Methods for deadline and laxity based priority evaluation are
+ * provided. These methods assume a specific partitioning of
+ * the message priority number into a higher order dynamic bit
+ * field and a lower order static priority bit field. The
+ * default partitioning assumes an unsigned dynamic message
+ * priority field of 22 bits and an unsigned static message
+ * priority field of 10 bits. This corresponds to the initial
+ * values of the static class members. To provide a different
+ * partitioning, assign a different set of values to the static
+ * class memebers before using the static member functions.
+ */
+class ACE_Export ACE_Dynamic_Message_Strategy
+{
+public:
+
+ // = Message priority status
+
+ // Values are defined as bit flags so that status combinations may
+ // be specified easily.
+
+ enum Priority_Status
+ {
+ /// Message can still make its deadline
+ PENDING = 0x01,
+ /// Message cannot make its deadline
+ LATE = 0x02,
+ /// Message is so late its priority is undefined
+ BEYOND_LATE = 0x04,
+ /// Mask to match any priority status
+ ANY_STATUS = 0x07
+ };
+
+ /// Constructor.
+ ACE_Dynamic_Message_Strategy (unsigned long static_bit_field_mask,
+ unsigned long static_bit_field_shift,
+ unsigned long dynamic_priority_max,
+ unsigned long dynamic_priority_offset);
+
+ /// Virtual destructor.
+ virtual ~ACE_Dynamic_Message_Strategy (void);
+
+ /// Updates the message's priority and returns its priority status.
+ Priority_Status priority_status (ACE_Message_Block &mb,
+ const ACE_Time_Value &tv);
+
+ /// Get static bit field mask.
+ unsigned long static_bit_field_mask (void) const;
+
+ /// Set static bit field mask.
+ void static_bit_field_mask (unsigned long);
+
+ /// Get left shift value to make room for static bit field.
+ unsigned long static_bit_field_shift (void) const;
+
+ /// Set left shift value to make room for static bit field.
+ void static_bit_field_shift (unsigned long);
+
+ /// Get maximum supported priority value.
+ unsigned long dynamic_priority_max (void) const;
+
+ /// Set maximum supported priority value.
+ void dynamic_priority_max (unsigned long);
+
+ /// Get offset to boundary between signed range and unsigned range.
+ unsigned long dynamic_priority_offset (void) const;
+
+ /// Set offset to boundary between signed range and unsigned range.
+ void dynamic_priority_offset (unsigned long);
+
+ /// Dump the state of the strategy.
+ virtual void dump (void) const;
+
+protected:
+ /// Hook method for dynamic priority conversion.
+ virtual void convert_priority (ACE_Time_Value &priority,
+ const ACE_Message_Block &mb) = 0;
+
+ /// This is a bit mask with all ones in the static bit field.
+ unsigned long static_bit_field_mask_;
+
+ /**
+ * This is a left shift value to make room for static bit field:
+ * this value should be the logarithm base 2 of
+ * (static_bit_field_mask_ + 1).
+ */
+ unsigned long static_bit_field_shift_;
+
+ /// Maximum supported priority value.
+ unsigned long dynamic_priority_max_;
+
+ /// Offset to boundary between signed range and unsigned range.
+ unsigned long dynamic_priority_offset_;
+
+ /// Maximum late time value that can be represented.
+ ACE_Time_Value max_late_;
+
+ /// Minimum pending time value that can be represented.
+ ACE_Time_Value min_pending_;
+
+ /// Time value by which to shift pending priority.
+ ACE_Time_Value pending_shift_;
+};
+
+/**
+ * @class ACE_Deadline_Message_Strategy
+ *
+ * @brief Deadline based message priority strategy.
+ *
+ * Assigns dynamic message priority according to time to deadline. The
+ * message priority is divided into high and low order bit fields. The
+ * high order bit field is used for dynamic message priority, which is
+ * updated whenever the convert_priority() method is called. The
+ * low order bit field is used for static message priority and is left
+ * unchanged. The partitioning of the priority value into high and low
+ * order bit fields is done according to the arguments passed to the
+ * strategy object's constructor.
+ */
+class ACE_Export ACE_Deadline_Message_Strategy : public ACE_Dynamic_Message_Strategy
+{
+public:
+ /// Ctor, with all arguments defaulted.
+ ACE_Deadline_Message_Strategy (unsigned long static_bit_field_mask = 0x3FFUL, // 2^(10) - 1
+ unsigned long static_bit_field_shift = 10, // 10 low order bits
+ unsigned long dynamic_priority_max = 0x3FFFFFUL, // 2^(22)-1
+ unsigned long dynamic_priority_offset = 0x200000UL); // 2^(22-1)
+
+ /// Virtual dtor.
+ virtual ~ACE_Deadline_Message_Strategy (void);
+
+ /// Dynamic priority conversion function based on time to deadline.
+ virtual void convert_priority (ACE_Time_Value &priority,
+ const ACE_Message_Block &mb);
+
+ /// Dump the state of the strategy.
+ virtual void dump (void) const;
+};
+
+/**
+ * @class ACE_Laxity_Message_Strategy
+ *
+ * @brief Laxity based message priority strategy.
+ *
+ * Assigns dynamic message priority according to laxity (time to
+ * deadline minus worst case execution time). The message priority is
+ * divided into high and low order bit fields. The high order
+ * bit field is used for dynamic message priority, which is
+ * updated whenever the convert_priority() method is called. The
+ * low order bit field is used for static message priority and is left
+ * unchanged. The partitioning of the priority value into high and low
+ * order bit fields is done according to the arguments passed to the
+ * strategy object's constructor.
+ */
+class ACE_Export ACE_Laxity_Message_Strategy : public ACE_Dynamic_Message_Strategy
+{
+public:
+ /// Ctor, with all arguments defaulted.
+ ACE_Laxity_Message_Strategy (unsigned long static_bit_field_mask = 0x3FFUL, // 2^(10) - 1
+ unsigned long static_bit_field_shift = 10, // 10 low order bits
+ unsigned long dynamic_priority_max = 0x3FFFFFUL, // 2^(22)-1
+ unsigned long dynamic_priority_offset = 0x200000UL); // 2^(22-1)
+
+ /// virtual dtor.
+ virtual ~ACE_Laxity_Message_Strategy (void);
+
+ /// Dynamic priority conversion function based on laxity.
+ virtual void convert_priority (ACE_Time_Value &priority,
+ const ACE_Message_Block &mb);
+
+ /// Dump the state of the strategy.
+ virtual void dump (void) const;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Dynamic_Message_Strategy.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_DYNAMIC_MESSAGE_STRATEGY_H */
diff --git a/ACE/ace/Dynamic_Message_Strategy.inl b/ACE/ace/Dynamic_Message_Strategy.inl
new file mode 100644
index 00000000000..b855acef597
--- /dev/null
+++ b/ACE/ace/Dynamic_Message_Strategy.inl
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE unsigned long
+ACE_Dynamic_Message_Strategy::static_bit_field_mask (void) const
+{
+ return static_bit_field_mask_;
+}
+ // get static bit field mask
+
+ACE_INLINE void
+ACE_Dynamic_Message_Strategy::static_bit_field_mask (unsigned long ul)
+{
+ static_bit_field_mask_ = ul;
+}
+ // set static bit field mask
+
+ACE_INLINE unsigned long
+ACE_Dynamic_Message_Strategy::static_bit_field_shift (void) const
+{
+ return static_bit_field_shift_;
+}
+ // get left shift value to make room for static bit field
+
+ACE_INLINE void
+ACE_Dynamic_Message_Strategy::static_bit_field_shift (unsigned long ul)
+{
+ static_bit_field_shift_ = ul;
+}
+ // set left shift value to make room for static bit field
+
+ACE_INLINE unsigned long
+ACE_Dynamic_Message_Strategy::dynamic_priority_max (void) const
+{
+ return dynamic_priority_max_;
+}
+ // get maximum supported priority value
+
+ACE_INLINE void
+ACE_Dynamic_Message_Strategy::dynamic_priority_max (unsigned long ul)
+{
+ // pending_shift_ depends on dynamic_priority_max_: for performance
+ // reasons, the value in pending_shift_ is (re)calculated only when
+ // dynamic_priority_max_ is initialized or changes, and is stored
+ // as a class member rather than being a derived value.
+ dynamic_priority_max_ = ul;
+ pending_shift_ = ACE_Time_Value (0, ul);
+}
+ // set maximum supported priority value
+
+ACE_INLINE unsigned long
+ACE_Dynamic_Message_Strategy::dynamic_priority_offset (void) const
+{
+ return dynamic_priority_offset_;
+}
+ // get offset for boundary between signed range and unsigned range
+
+ACE_INLINE void
+ACE_Dynamic_Message_Strategy::dynamic_priority_offset (unsigned long ul)
+{
+ // max_late_ and min_pending_ depend on dynamic_priority_offset_:
+ // for performance reasons, the values in max_late_ and min_pending_
+ // are (re)calculated only when dynamic_priority_offset_ is
+ // initialized or changes, and are stored as a class member rather
+ // than being derived each time one of their values is needed.
+ dynamic_priority_offset_ = ul;
+ max_late_ = ACE_Time_Value (0, ul - 1);
+ min_pending_ = ACE_Time_Value (0, ul);
+}
+ // set offset for boundary between signed range and unsigned range
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dynamic_Service.cpp b/ACE/ace/Dynamic_Service.cpp
new file mode 100644
index 00000000000..53d762dc364
--- /dev/null
+++ b/ACE/ace/Dynamic_Service.cpp
@@ -0,0 +1,63 @@
+// $Id$
+
+#ifndef ACE_DYNAMIC_SERVICE_CPP
+#define ACE_DYNAMIC_SERVICE_CPP
+
+#include "ace/Dynamic_Service.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Object.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Dynamic_Service.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+
+template <class TYPE> TYPE *
+ACE_Dynamic_Service<TYPE>::instance (const ACE_TCHAR *name)
+{
+ ACE_Service_Object * svc_obj =
+ static_cast<ACE_Service_Object *>
+ (ACE_Dynamic_Service_Base::instance (name,false));
+ return dynamic_cast<TYPE *> (svc_obj);
+}
+
+template <class TYPE> TYPE *
+ACE_Dynamic_Service<TYPE>::instance (const ACE_TCHAR *name,
+ bool no_global)
+{
+ ACE_Service_Object * svc_obj =
+ static_cast<ACE_Service_Object *>
+ (ACE_Dynamic_Service_Base::instance (name, no_global));
+ return dynamic_cast<TYPE *> (svc_obj);
+}
+
+template <class TYPE> TYPE *
+ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* conf,
+ const ACE_TCHAR *name)
+{
+ ACE_Service_Object * svc_obj =
+ static_cast<ACE_Service_Object *>
+ (ACE_Dynamic_Service_Base::instance (conf, name, false));
+ return dynamic_cast<TYPE *> (svc_obj);
+}
+
+template <class TYPE> TYPE *
+ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* conf,
+ const ACE_TCHAR *name,
+ bool no_global)
+{
+ ACE_Service_Object * svc_obj =
+ static_cast<ACE_Service_Object *>
+ (ACE_Dynamic_Service_Base::instance (conf, name, no_global));
+ return dynamic_cast<TYPE *> (svc_obj);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_DYNAMIC_SERVICE_CPP */
diff --git a/ACE/ace/Dynamic_Service.h b/ACE/ace/Dynamic_Service.h
new file mode 100644
index 00000000000..ed7317ef562
--- /dev/null
+++ b/ACE/ace/Dynamic_Service.h
@@ -0,0 +1,89 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Dynamic_Service.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_DYNAMIC_SERVICE_H
+#define ACE_DYNAMIC_SERVICE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include "ace/Global_Macros.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Dynamic_Service_Base.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Service_Object;
+
+/**
+ * @class ACE_Dynamic_Service
+ *
+ * @brief Provides a general interface to retrieve arbitrary objects
+ * from the ACE service repository.
+ *
+ * Uses "name" for lookup in the ACE service repository. Obtains
+ * the object and returns it as the appropriate type.
+ */
+template <class TYPE>
+class ACE_Dynamic_Service : public ACE_Dynamic_Service_Base
+{
+public:
+ /// Return instance using @a name to search the Service_Repository.
+ static TYPE* instance (const ACE_TCHAR *name);
+ static TYPE* instance (const ACE_TCHAR *name, bool no_global);
+
+ static TYPE* instance (const ACE_Service_Gestalt* repo,
+ const ACE_TCHAR *name);
+ static TYPE* instance (const ACE_Service_Gestalt* repo,
+ const ACE_TCHAR *name, bool no_global);
+
+#if defined (ACE_USES_WCHAR)
+
+ /// Return instance using @a name to search the Service_Repository.
+ static TYPE* instance (const ACE_ANTI_TCHAR *name);
+
+ static TYPE* instance (const ACE_ANTI_TCHAR *name, bool no_global);
+
+ static TYPE* instance (const ACE_Service_Gestalt* repo,
+ const ACE_ANTI_TCHAR *name);
+ static TYPE* instance (const ACE_Service_Gestalt* repo,
+ const ACE_ANTI_TCHAR *name, bool no_global);
+#endif // ACE_USES_WCHAR
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dynamic_Service ())
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dynamic_Service (const ACE_Dynamic_Service&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dynamic_Service& operator= (const ACE_Dynamic_Service&))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Dynamic_Service.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+# include "ace/Dynamic_Service.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+# pragma implementation ("Dynamic_Service.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_DYNAMIC_SERVICE_H */
diff --git a/ACE/ace/Dynamic_Service.inl b/ACE/ace/Dynamic_Service.inl
new file mode 100644
index 00000000000..48978c595ed
--- /dev/null
+++ b/ACE/ace/Dynamic_Service.inl
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_USES_WCHAR)
+
+template <class TYPE> ACE_INLINE TYPE *
+ACE_Dynamic_Service<TYPE>::instance (const ACE_ANTI_TCHAR *name)
+{
+ return instance (ACE_TEXT_CHAR_TO_TCHAR (name),false);
+}
+
+template <class TYPE> ACE_INLINE TYPE *
+ACE_Dynamic_Service<TYPE>::instance (const ACE_ANTI_TCHAR *name,
+ bool no_global)
+{
+ return instance (ACE_TEXT_CHAR_TO_TCHAR (name),no_global);
+}
+
+template <class TYPE> ACE_INLINE TYPE *
+ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* repo,
+ const ACE_ANTI_TCHAR *name)
+{
+ return instance (repo, ACE_TEXT_CHAR_TO_TCHAR (name),false);
+}
+
+template <class TYPE> ACE_INLINE TYPE *
+ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* repo,
+ const ACE_ANTI_TCHAR *name,
+ bool no_global)
+{
+ return instance (repo, ACE_TEXT_CHAR_TO_TCHAR (name),no_global);
+}
+
+
+#endif // ACE_USES_WCHAR
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dynamic_Service_Base.cpp b/ACE/ace/Dynamic_Service_Base.cpp
new file mode 100644
index 00000000000..e93dde6e905
--- /dev/null
+++ b/ACE/ace/Dynamic_Service_Base.cpp
@@ -0,0 +1,101 @@
+#include "ace/Dynamic_Service_Base.h"
+#include "ace/ACE.h"
+#include "ace/Service_Config.h"
+#include "ace/Service_Repository.h"
+#include "ace/Service_Types.h"
+#include "ace/Log_Msg.h"
+
+
+ACE_RCSID (ace,
+ Dynamic_Service_Base,
+ "$Id$")
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+
+void
+ACE_Dynamic_Service_Base::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Dynamic_Service_Base::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// Get the instance using <name> for the current global
+// service configuration repository.
+
+void *
+ACE_Dynamic_Service_Base::instance (const ACE_TCHAR *name, bool no_global)
+{
+ ACE_TRACE ("ACE_Dynamic_Service_Base::instance");
+ return instance (ACE_Service_Config::current (), name, no_global);
+}
+
+// Find a service registration
+
+const ACE_Service_Type *
+ACE_Dynamic_Service_Base::find_i (const ACE_Service_Gestalt* &repo,
+ const ACE_TCHAR *name,
+ bool no_global)
+{
+ ACE_TRACE ("ACE_Dynamic_Service_Base::find_i");
+ const ACE_Service_Type *svc_rec = 0;
+
+ ACE_Service_Gestalt* global = ACE_Service_Config::global ();
+
+ for ( ; (repo->find (name, &svc_rec) == -1) && !no_global; repo = global)
+ {
+ // Check the static repo, too if different
+ if (repo == global)
+ break;
+ }
+
+ return svc_rec;
+}
+
+
+// Get the instance using <name> for specific configuration repository.
+void *
+ACE_Dynamic_Service_Base::instance (const ACE_Service_Gestalt* repo,
+ const ACE_TCHAR *name,
+ bool no_global)
+{
+ ACE_TRACE ("ACE_Dynamic_Service_Base::instance");
+
+ void *obj = 0;
+ const ACE_Service_Type_Impl *type = 0;
+
+ const ACE_Service_Gestalt* repo_found = repo;
+ const ACE_Service_Type *svc_rec = find_i (repo_found, name, no_global);
+ if (svc_rec != 0)
+ {
+ type = svc_rec->type ();
+ if (type != 0)
+ obj = type->object ();
+ }
+
+ if (ACE::debug ())
+ {
+ ACE_Guard <ACE_Log_Msg> log_guard (*ACE_Log_Msg::instance ());
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) DSB::instance, repo=%@, name=%s")
+ ACE_TEXT (" type=%@ => %@"),
+ repo->repo_, name, type, obj));
+
+ if (repo->repo_ != repo_found->repo_)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT (" [in repo=%@]\n"),
+ repo_found->repo_));
+ else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ }
+
+ return obj;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dynamic_Service_Base.h b/ACE/ace/Dynamic_Service_Base.h
new file mode 100644
index 00000000000..7a039a1a6b2
--- /dev/null
+++ b/ACE/ace/Dynamic_Service_Base.h
@@ -0,0 +1,74 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Dynamic_Service_Base.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_DYNAMIC_SERVICE_BASE_H
+#define ACE_DYNAMIC_SERVICE_BASE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Service_Gestalt;
+class ACE_Service_Type;
+
+/**
+ * @class ACE_Dynamic_Service_Base
+ *
+ * @brief Base class for all ACE_Dynamic_Service instantiations.
+ *
+ * Factors out common code shared by all ACE_Dynamic_Service
+ * instantiations, this avoid code bloat.
+ */
+class ACE_Export ACE_Dynamic_Service_Base
+{
+
+public:
+ /// Dump the current static of the object
+ void dump (void) const;
+
+protected:
+ /// Perform the default repo search, but optionally skip searching the global
+ /// repo.
+ static void* instance (const ACE_TCHAR *name, bool no_global = false);
+
+ static void* instance (const ACE_Service_Gestalt* repo,
+ const ACE_TCHAR *name,
+ bool no_global = false);
+
+ /// No need to create, or assign instances of this class
+ ACE_Dynamic_Service_Base (void);
+ ~ACE_Dynamic_Service_Base (void);
+ const ACE_Dynamic_Service_Base& operator= (const ACE_Dynamic_Service_Base&);
+
+private:
+ /// Implement the service search policy, i.e. "look for the service first
+ /// locally and then globally"
+ static const ACE_Service_Type *find_i (const ACE_Service_Gestalt* &repo,
+ const ACE_TCHAR *name,
+ bool no_global);
+
+ /// The dependency declaration class needs access to the service search
+ /// policy, implemented by find_i()
+ friend class ACE_Dynamic_Service_Dependency;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_DYNAMIC_SERVICE_BASE_H */
diff --git a/ACE/ace/Dynamic_Service_Dependency.cpp b/ACE/ace/Dynamic_Service_Dependency.cpp
new file mode 100644
index 00000000000..f2a9b45d61c
--- /dev/null
+++ b/ACE/ace/Dynamic_Service_Dependency.cpp
@@ -0,0 +1,51 @@
+#include "ace/ACE.h"
+#include "ace/DLL_Manager.h"
+#include "ace/Dynamic_Service_Dependency.h"
+#include "ace/Service_Config.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID (ace,
+ Dynamic_Service_Dependency,
+ "$Id$")
+
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+
+ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_TCHAR *principal)
+{
+ this->init (ACE_Service_Config::current (), principal);
+}
+
+ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_Service_Gestalt *cfg,
+ const ACE_TCHAR *principal)
+{
+ this->init (cfg, principal);
+}
+
+
+ACE_Dynamic_Service_Dependency::~ACE_Dynamic_Service_Dependency (void)
+{
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) DSD, this=%@ - destroying\n"),
+ this));
+}
+
+void
+ACE_Dynamic_Service_Dependency::init (const ACE_Service_Gestalt *cfg,
+ const ACE_TCHAR *principal)
+{
+ const ACE_Service_Type* st =
+ ACE_Dynamic_Service_Base::find_i (cfg, principal,false);
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) DSD, this=%@ - creating dependency on "), this));
+ st->dump ();
+ }
+ this->tracker_ = st->dll ();
+}
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Dynamic_Service_Dependency.h b/ACE/ace/Dynamic_Service_Dependency.h
new file mode 100644
index 00000000000..3eb4e0df7c7
--- /dev/null
+++ b/ACE/ace/Dynamic_Service_Dependency.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Dynamic_Service_Dependency.h
+ *
+ * $Id$
+ *
+ * @author Iliyan Jeliazkov <iliyan@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef ACE_DYNAMIC_SERVICE_DEPENDENCY_H
+#define ACE_DYNAMIC_SERVICE_DEPENDENCY_H
+
+#include /**/ "ace/pre.h"
+
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Dynamic_Service_Base.h"
+#include "ace/Service_Object.h"
+#include "ace/DLL.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Dynamic_Service_Dependency
+ *
+ * @brief Provides a way to declare dependency on specific service,
+ * thus helping to avoid order of initialization issues with instances
+ * of an objects whose implementation code resides in dynamically loaded
+ * services.
+ *
+ * It is disastrous to have dynamically loadable services create and give away
+ * ownership of objects and then ending up being unloaded before all those
+ * instances have been deleted. Normally the code for such objects classes
+ * resides within the TEXT segment of the DLL, which implements the service.
+ * If a service gets removed, its DLL may be unmapped from memory and then
+ * any attempt to invoke a method on the said objects will cause SEGV.
+ *
+ * Such instances must contain a member of ACE_Dynamic_Service_Dependency
+ * initialized with the service they depend on.
+ * ACE_Dynamic_Service_Dependency's constructor and destructor are
+ * "magical" - they work by maintaining the underlying dynamic service's
+ * DLL reference count.
+ */
+class ACE_Export ACE_Dynamic_Service_Dependency
+{
+public:
+ ACE_Dynamic_Service_Dependency (const ACE_Service_Gestalt *cfg,
+ const ACE_TCHAR *principal);
+ ACE_Dynamic_Service_Dependency (const ACE_TCHAR *principal);
+ ~ACE_Dynamic_Service_Dependency (void);
+
+private:
+ void init (const ACE_Service_Gestalt *cfg, const ACE_TCHAR *principal);
+
+private:
+ ACE_DLL tracker_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_DYNAMIC_SERVICE_DEPENDENCY_H */
diff --git a/ACE/ace/Encoding_Converter.cpp b/ACE/ace/Encoding_Converter.cpp
new file mode 100644
index 00000000000..60e561ea534
--- /dev/null
+++ b/ACE/ace/Encoding_Converter.cpp
@@ -0,0 +1,12 @@
+// $Id$
+#include "ace/Encoding_Converter.h"
+
+#if defined (ACE_USES_WCHAR)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Encoding_Converter::~ACE_Encoding_Converter (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
diff --git a/ACE/ace/Encoding_Converter.h b/ACE/ace/Encoding_Converter.h
new file mode 100644
index 00000000000..7d5bd39b512
--- /dev/null
+++ b/ACE/ace/Encoding_Converter.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+
+//=========================================================================
+/**
+ * @file Encoding_Converter.h
+ *
+ * $Id$
+ *
+ * This class is the base class for all encoding converters that convert
+ * to and from UTF-8.
+ *
+ * @author Chad Elliott <elliott_c@ociweb.com>
+ */
+//=========================================================================
+
+#ifndef ACE_ENCODING_CONVERTER_H
+#define ACE_ENCODING_CONVERTER_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Basic_Types.h"
+
+#if defined (ACE_USES_WCHAR)
+#include /**/ "ace/ACE_export.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/** The base class for all ACE UTF Encoding Converters.
+ * This class provides a generic interface that is used to implement
+ * various UTF encoding conversion classes.
+ */
+class ACE_Export ACE_Encoding_Converter
+{
+public:
+ /// This enum describes the various states that can be returned
+ /// from the to_utf8() and from_utf8() methods which depends on
+ /// both the source buffer and the size of the target buffer.
+ enum Result {CONVERSION_OK,
+ SOURCE_EXHAUSTED,
+ TARGET_EXHAUSTED,
+ SOURCE_ILLEGAL
+ };
+
+ /// This destructor is here (and virtual) because we have virtual
+ /// functions.
+ virtual ~ACE_Encoding_Converter (void);
+
+ /// Convert the source (which can be in any encoding) to UTF-8 and
+ /// store it in the provided target buffer.
+ virtual Result to_utf8 (const void* source,
+ size_t source_size,
+ ACE_Byte* target,
+ size_t target_size,
+ bool strict = true) = 0;
+
+ /// Convert the UTF-8 source into an alternate encoding and store it
+ /// in the provided target buffer.
+ virtual Result from_utf8 (const ACE_Byte* source,
+ size_t source_size,
+ void* target,
+ size_t target_size,
+ bool strict = true) = 0;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ENCODING_CONVERTER_H */
diff --git a/ACE/ace/Encoding_Converter_Factory.cpp b/ACE/ace/Encoding_Converter_Factory.cpp
new file mode 100644
index 00000000000..8cf1ed22c3f
--- /dev/null
+++ b/ACE/ace/Encoding_Converter_Factory.cpp
@@ -0,0 +1,74 @@
+// $Id$
+#include "ace/Encoding_Converter_Factory.h"
+
+#if defined (ACE_USES_WCHAR)
+#include "ace/UTF32_Encoding_Converter.h"
+#include "ace/UTF16_Encoding_Converter.h"
+#include "ace/UTF8_Encoding_Converter.h"
+#include "ace/OS_Memory.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Encoding_Converter*
+ACE_Encoding_Converter_Factory::create (
+ const ACE_Byte* source,
+ size_t source_size,
+ ACE_Encoding_Converter_Factory::Encoding_Hint hint)
+{
+#if defined (ACE_BIG_ENDIAN)
+ bool const convert_for_bigendian = true;
+#else
+ bool const convert_for_bigendian = false;
+#endif /* ACE_BIG_ENDIAN */
+ ACE_Encoding_Converter* converter = 0;
+
+ switch (hint)
+ {
+ case ACE_UTF_32BE:
+ ACE_NEW_RETURN (converter,
+ ACE_UTF32_Encoding_Converter (!convert_for_bigendian),
+ 0);
+ break;
+ case ACE_UTF_32LE:
+ ACE_NEW_RETURN (converter,
+ ACE_UTF32_Encoding_Converter (convert_for_bigendian),
+ 0);
+ break;
+ case ACE_UTF_16BE:
+ ACE_NEW_RETURN (converter,
+ ACE_UTF16_Encoding_Converter (!convert_for_bigendian),
+ 0);
+ break;
+ case ACE_UTF_16LE:
+ ACE_NEW_RETURN (converter,
+ ACE_UTF16_Encoding_Converter (convert_for_bigendian),
+ 0);
+ break;
+ case ACE_UTF_8:
+ ACE_NEW_RETURN (converter,
+ ACE_UTF8_Encoding_Converter,
+ 0);
+ break;
+ default:
+ // First check for ASCII since much of ASCII text will appear to
+ // convert from UTF-16 to UTF-8.
+ converter = ACE_UTF8_Encoding_Converter::encoded (source, source_size);
+ if (converter != 0)
+ return converter;
+
+ // Check for UTF-32
+ converter = ACE_UTF32_Encoding_Converter::encoded (source, source_size);
+ if (converter != 0)
+ return converter;
+
+ // Check for UTF-16
+ converter = ACE_UTF16_Encoding_Converter::encoded (source, source_size);
+ if (converter != 0)
+ return converter;
+ }
+
+ return converter;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
diff --git a/ACE/ace/Encoding_Converter_Factory.h b/ACE/ace/Encoding_Converter_Factory.h
new file mode 100644
index 00000000000..11ec541ebae
--- /dev/null
+++ b/ACE/ace/Encoding_Converter_Factory.h
@@ -0,0 +1,54 @@
+// -*- C++ -*-
+
+//=========================================================================
+/**
+ * @file Encoding_Converter_Factory.h
+ *
+ * $Id$
+ *
+ * This class can be used to create encoding converters of various types.
+ *
+ * @author Chad Elliott <elliott_c@ociweb.com>
+ */
+//=========================================================================
+
+#ifndef ACE_ENCODING_CONVERTER_FACTORY_H
+#define ACE_ENCODING_CONVERTER_FACTORY_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Basic_Types.h"
+
+#if defined (ACE_USES_WCHAR)
+#include /**/ "ace/ACE_export.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Encoding_Converter;
+
+/** Create an encoding converter based on the source or hint.
+ * This class allows users to avoid knowing any concrete converter types.
+ */
+class ACE_Export ACE_Encoding_Converter_Factory
+{
+public:
+ /// This enum is used to tell what type of converter to create.
+ enum Encoding_Hint { ACE_UTF_32BE, ACE_UTF_32LE,
+ ACE_UTF_16BE, ACE_UTF_16LE,
+ ACE_UTF_8, ACE_NONE
+ };
+
+ /// Create an encoding converter based on the source. If a hint is
+ /// given, it just creates the specified type of converter without looking
+ /// at the source.
+ static ACE_Encoding_Converter* create (const ACE_Byte* source,
+ size_t source_size,
+ Encoding_Hint hint = ACE_NONE);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ENCODING_CONVERTER_FACTORY_H */
diff --git a/ACE/ace/Env_Value_T.cpp b/ACE/ace/Env_Value_T.cpp
new file mode 100644
index 00000000000..788bf125fc5
--- /dev/null
+++ b/ACE/ace/Env_Value_T.cpp
@@ -0,0 +1,12 @@
+// $Id$
+
+#ifndef ACE_ENV_VALUE_T_CPP
+#define ACE_ENV_VALUE_T_CPP
+
+#include "ace/Env_Value_T.h"
+
+#if ! defined (__ACE_INLINE__)
+#include "ace/Env_Value_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_ENV_VALUE_T_CPP */
diff --git a/ACE/ace/Env_Value_T.h b/ACE/ace/Env_Value_T.h
new file mode 100644
index 00000000000..01f4fcc5e8d
--- /dev/null
+++ b/ACE/ace/Env_Value_T.h
@@ -0,0 +1,166 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Env_Value_T.h
+ *
+ * $Id$
+ *
+ * Template to encapsulate getting a value from an environment variable
+ * and using a supplied default value if not in the environment.
+ *
+ *
+ * @author Chris Cleeland (derived from work by Carlos O'Ryan)
+ */
+//=============================================================================
+
+#ifndef ACE_ENV_VALUE_T_H
+#define ACE_ENV_VALUE_T_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include "ace/Global_Macros.h"
+#include "ace/OS_NS_stdlib.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Env_Value
+ *
+ * @brief Environment Variable Value
+ *
+ * Reads a variable from the user environment, providing a default
+ * value.
+ */
+template <class T>
+class ACE_Env_Value
+{
+public:
+ /**
+ * Default constructor which isn't bound to a specific environment
+ * variable name or a default value. Before being useful it must
+ * <open>'d.
+ */
+ ACE_Env_Value (void);
+
+ /// Constructor that calls <open>.
+ ACE_Env_Value (const ACE_TCHAR *varname,
+ const T &vardefault);
+
+ /// Destroy the value.
+ ~ACE_Env_Value (void);
+
+ /// Returns the value as type T.
+ operator T (void);
+
+ /// The constructor, read @a varname from the environment, using
+ /// @a defval as its value if it is not defined.
+ void open (const ACE_TCHAR *varname, const T &defval);
+
+ /// Returns the name of the variable being tracked.
+ const ACE_TCHAR *varname (void) const;
+
+private:
+ /// Disallow copying and assignment.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Env_Value(const ACE_Env_Value<T> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Env_Value<T> operator=(const ACE_Env_Value<T> &))
+
+ void fetch_value (void);
+
+ const ACE_TCHAR *varname_;
+ T value_;
+};
+
+/// Function to convert a string @a s into type @c T.
+template <class T> void ACE_Convert (const ACE_TCHAR *s, T &t);
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Env_Value_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Env_Value_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, ACE_TCHAR *&v)
+{
+ v = (ACE_TCHAR *) s;
+}
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, const ACE_TCHAR *&v)
+{
+ v = (const ACE_TCHAR *) s;
+}
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, short &si)
+{
+ si = static_cast<short> (ACE_OS::strtol (s, 0, 10));
+}
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, u_short &us)
+{
+ us = static_cast <u_short> (ACE_OS::strtol (s, 0, 10));
+}
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, u_int &i)
+{
+ i = static_cast<u_int> (ACE_OS::strtol (s, 0, 10));
+}
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, long &l)
+{
+ l = ACE_OS::strtol (s, 0, 10);
+}
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, int &i)
+{
+ i = static_cast<int> (ACE_OS::strtol (s, 0, 10));
+}
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, u_long &ul)
+{
+ ul = ACE_OS::strtoul (s, 0, 10);
+}
+
+template <> inline void
+ACE_Convert (const ACE_TCHAR *s, double &d)
+{
+ d = ACE_OS::strtod (s, 0);
+}
+
+// Default calls a CTOR on type T of the form 'T::T(const char*)', but
+// users can feel free to create their own specialized conversion
+// functions if necessary, as shown above. Note that for 'char*' the
+// default is used because a simple cast will be performed and no
+// conversion will be necessary.
+template <class T> inline void
+ACE_Convert (const ACE_TCHAR *s, T &t)
+{
+ t = T (s);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Env_Value_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_ENV_VALUE_T_H */
diff --git a/ACE/ace/Env_Value_T.inl b/ACE/ace/Env_Value_T.inl
new file mode 100644
index 00000000000..63fe8df1f29
--- /dev/null
+++ b/ACE/ace/Env_Value_T.inl
@@ -0,0 +1,60 @@
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> ACE_INLINE
+ACE_Env_Value<T>::operator T (void)
+{
+ return value_;
+}
+
+template <class T> ACE_INLINE
+ACE_Env_Value<T>::ACE_Env_Value (void)
+ : varname_ (0)
+{
+}
+
+template <class T> ACE_INLINE
+ACE_Env_Value<T>::ACE_Env_Value (const ACE_TCHAR *varname,
+ const T &defval)
+ : varname_ (varname),
+ value_(defval)
+{
+ this->fetch_value ();
+}
+
+template <class T> ACE_INLINE void
+ACE_Env_Value<T>::open (const ACE_TCHAR *varname,
+ const T &defval)
+{
+ this->varname_ = varname;
+ this->value_ = defval;
+ this->fetch_value ();
+}
+
+template <class T> ACE_INLINE void
+ACE_Env_Value<T>::fetch_value (void)
+{
+#if defined (ACE_WIN32)
+ const ACE_TCHAR *env = ACE_OS::getenv (this->varname_);
+ if (env != 0)
+ ACE_Convert (env, value_);
+#else
+ char *nenv = ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (this->varname_));
+ if (nenv != 0)
+ ACE_Convert (ACE_TEXT_CHAR_TO_TCHAR (nenv), this->value_);
+#endif
+}
+
+template <class T> ACE_INLINE const ACE_TCHAR*
+ACE_Env_Value<T>::varname (void) const
+{
+ return this->varname_;
+}
+
+template <class T> ACE_INLINE
+ACE_Env_Value<T>::~ACE_Env_Value (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Event.cpp b/ACE/ace/Event.cpp
new file mode 100644
index 00000000000..e185ec37117
--- /dev/null
+++ b/ACE/ace/Event.cpp
@@ -0,0 +1,93 @@
+// $Id$
+
+#include "ace/Event.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Event.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Event, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Event::ACE_Event (int manual_reset,
+ int initial_state,
+ int type,
+ const ACE_TCHAR *name,
+ void *arg,
+ LPSECURITY_ATTRIBUTES sa)
+ : removed_ (false)
+{
+ if (ACE_OS::event_init (&this->handle_,
+ manual_reset,
+ initial_state,
+ type,
+ name,
+ arg,
+ sa) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Event::ACE_Event")));
+}
+
+ACE_Event::~ACE_Event (void)
+{
+ this->remove ();
+}
+
+int
+ACE_Event::remove (void)
+{
+ int result = 0;
+ if (!this->removed_)
+ {
+ this->removed_ = true;
+ result = ACE_OS::event_destroy (&this->handle_);
+ }
+ return result;
+}
+
+int
+ACE_Event::wait (void)
+{
+ return ACE_OS::event_wait (&this->handle_);
+}
+
+int
+ACE_Event::wait (const ACE_Time_Value *abstime, int use_absolute_time)
+{
+ return ACE_OS::event_timedwait (&this->handle_,
+ const_cast <ACE_Time_Value *> (abstime),
+ use_absolute_time);
+}
+
+int
+ACE_Event::signal (void)
+{
+ return ACE_OS::event_signal (&this->handle_);
+}
+
+int
+ACE_Event::pulse (void)
+{
+ return ACE_OS::event_pulse (&this->handle_);
+}
+
+int
+ACE_Event::reset (void)
+{
+ return ACE_OS::event_reset (&this->handle_);
+}
+
+void
+ACE_Event::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Event.h b/ACE/ace/Event.h
new file mode 100644
index 00000000000..177c0039df1
--- /dev/null
+++ b/ACE/ace/Event.h
@@ -0,0 +1,143 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Event.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_EVENT_H
+#define ACE_EVENT_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Event
+ *
+ * @brief A wrapper around the Win32 event locking mechanism.
+ *
+ * Portable implementation of an Event mechanism, which is native to
+ * Win32, but must be emulated on UNIX. All platforms support
+ * process-scope locking support. However, only Win32 platforms
+ * support global naming and system-scope locking support.
+ */
+class ACE_Export ACE_Event
+{
+public:
+ /// Constructor that creates event.
+ ACE_Event (int manual_reset = 0,
+ int initial_state = 0,
+ int type = USYNC_THREAD,
+ const ACE_TCHAR *name = 0,
+ void *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Implicitly destroy the event variable.
+ ~ACE_Event (void);
+
+ /**
+ * Explicitly destroy the event variable. Note that only one thread
+ * should call this method since it doesn't protect against race
+ * conditions.
+ */
+ int remove (void);
+
+ /// Underlying handle to event.
+ ACE_event_t handle (void) const;
+
+ /**
+ * Set the underlying handle to event. Note that this method assumes
+ * ownership of the <handle> and will close it down in <remove>. If
+ * you want the <handle> to stay open when <remove> is called make
+ * sure to call <dup> on the <handle> before closing it. You are
+ * responsible for the closing the existing <handle> before
+ * overwriting it.
+ */
+ void handle (ACE_event_t new_handle);
+
+ /**
+ * if MANUAL reset
+ * sleep till the event becomes signaled
+ * event remains signaled after wait() completes.
+ * else AUTO reset
+ * sleep till the event becomes signaled
+ * event resets wait() completes.
+ */
+ int wait (void);
+
+ /// Same as wait() above, but this one can be timed
+ /// @a abstime is absolute time-of-day if if @a use_absolute_time
+ /// is non-0, else it is relative time.
+ int wait (const ACE_Time_Value *abstime,
+ int use_absolute_time = 1);
+
+ /**
+ * if MANUAL reset
+ * wake up all waiting threads
+ * set to signaled state
+ * else AUTO reset
+ * if no thread is waiting, set to signaled state
+ * if thread(s) are waiting, wake up one waiting thread and
+ * reset event
+ */
+ int signal (void);
+
+ /**
+ * if MANUAL reset
+ * wakeup all waiting threads and
+ * reset event
+ * else AUTO reset
+ * wakeup one waiting thread (if present) and
+ * reset event
+ */
+ int pulse (void);
+
+ /// Set to nonsignaled state.
+ int reset (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// The underlying handle.
+ ACE_event_t handle_;
+
+ /// Keeps track of whether <remove> has been called yet to avoid
+ /// multiple <remove> calls, e.g., explicitly and implicitly in the
+ /// destructor. This flag isn't protected by a lock, so make sure
+ /// that you don't have multiple threads simultaneously calling
+ /// <remove> on the same object, which is a bad idea anyway...
+ bool removed_;
+
+private:
+ // = Prevent copying.
+ ACE_Event (const ACE_Event& event);
+ const ACE_Event &operator= (const ACE_Event &rhs);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Event.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_EVENT_H */
diff --git a/ACE/ace/Event.inl b/ACE/ace/Event.inl
new file mode 100644
index 00000000000..188d7c202cf
--- /dev/null
+++ b/ACE/ace/Event.inl
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_event_t
+ACE_Event::handle (void) const
+{
+ return this->handle_;
+}
+
+ACE_INLINE void
+ACE_Event::handle (ACE_event_t new_handle)
+{
+ this->handle_ = new_handle;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Event_Handler.cpp b/ACE/ace/Event_Handler.cpp
new file mode 100644
index 00000000000..d4542b61349
--- /dev/null
+++ b/ACE/ace/Event_Handler.cpp
@@ -0,0 +1,396 @@
+// Event_Handler.cpp
+// $Id$
+
+#include "ace/Event_Handler.h"
+#include "ace/OS_Errno.h"
+#include "ace/Reactor.h"
+#include "ace/Thread_Manager.h"
+/* Need to see if ACE_HAS_BUILTIN_ATOMIC_OP defined */
+#include "ace/Atomic_Op.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Event_Handler.inl"
+#endif /* __ACE_INLINE__ */
+
+#include <algorithm>
+
+ACE_RCSID(ace, Event_Handler, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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)
+ : reference_count_ (1),
+ priority_ (p),
+ reactor_ (r),
+ reference_counting_policy_ (Reference_Counting_Policy::DISABLED)
+{
+ // ACE_TRACE ("ACE_Event_Handler::ACE_Event_Handler");
+}
+
+ACE_Event_Handler::~ACE_Event_Handler (void)
+{
+ // ACE_TRACE ("ACE_Event_Handler::~ACE_Event_Handler");
+}
+
+// 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 ACE_Event_Handler::ACE_REACTOR_RESUMES_HANDLER;
+}
+
+
+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_;
+}
+
+ACE_Reactor_Timer_Interface *
+ACE_Event_Handler::reactor_timer_interface (void) const
+{
+ ACE_TRACE ("ACE_Event_Handler::reactor_timer_interface");
+ return this->reactor_;
+}
+
+ACE_Event_Handler::Reference_Count
+ACE_Event_Handler::add_reference (void)
+{
+ bool const reference_counting_required =
+ this->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ if (reference_counting_required)
+ return ++this->reference_count_;
+ else
+ return 1;
+}
+
+ACE_Event_Handler::Reference_Count
+ACE_Event_Handler::remove_reference (void)
+{
+ bool const reference_counting_required =
+ this->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ if (reference_counting_required)
+ {
+ Reference_Count result =
+ --this->reference_count_;
+
+ if (result == 0)
+ delete this;
+
+ return result;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+ACE_Event_Handler::Policy::~Policy (void)
+{
+}
+
+ACE_Event_Handler::Reference_Counting_Policy::Reference_Counting_Policy (Reference_Counting_Policy::Value value)
+ : value_ (value)
+{
+}
+
+ACE_Event_Handler::Reference_Counting_Policy::Value
+ACE_Event_Handler::Reference_Counting_Policy::value (void) const
+{
+ return this->value_;
+}
+
+void
+ACE_Event_Handler::Reference_Counting_Policy::value (ACE_Event_Handler::Reference_Counting_Policy::Value value)
+{
+ this->value_ = value;
+}
+
+ACE_Event_Handler::Reference_Counting_Policy &
+ACE_Event_Handler::reference_counting_policy (void)
+{
+ return this->reference_counting_policy_;
+}
+
+//#if !defined (ACE_HAS_WINCE)
+
+ACE_THR_FUNC_RETURN
+ACE_Event_Handler::read_adapter (void *args)
+{
+ ACE_Event_Handler *this_ptr = static_cast<ACE_Event_Handler *> (args);
+ ACE_Reactor *r = this_ptr->reactor ();
+
+ while (this_ptr->handle_input (ACE_STDIN) != -1)
+ continue;
+
+ this_ptr->handle_close (ACE_STDIN, ACE_Event_Handler::READ_MASK);
+ // It's possible for handle_close() to "delete this" so we need to
+ // cache the reactor pointer and use it here.
+ r->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)
+ ACE_UNUSED_ARG (reactor);
+
+ eh->reactor (reactor);
+ return thr_mgr->spawn (&read_adapter, static_cast<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 */
+}
+
+int
+ACE_Event_Handler::remove_stdin_handler (ACE_Reactor *reactor,
+ ACE_Thread_Manager * /* thr_mgr */)
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (reactor);
+
+ // What should we do here?
+ ACE_NOTSUP_RETURN (-1);
+#else
+ return reactor->remove_handler (ACE_STDIN,
+ ACE_Event_Handler::READ_MASK);
+#endif /* ACE_WIN32 */
+}
+
+//#endif /* ACE_HAS_WINCE */
+
+// ---------------------------------------------------------------------
+
+ACE_Event_Handler_var::ACE_Event_Handler_var (void)
+ : ptr_ (0)
+{
+}
+
+ACE_Event_Handler_var::ACE_Event_Handler_var (ACE_Event_Handler *p)
+ : ptr_ (p)
+{
+}
+
+ACE_Event_Handler_var::ACE_Event_Handler_var (const ACE_Event_Handler_var &b)
+ : ptr_ (b.ptr_)
+{
+ if (this->ptr_ != 0)
+ {
+ this->ptr_->add_reference ();
+ }
+}
+
+ACE_Event_Handler_var::~ACE_Event_Handler_var (void)
+{
+ if (this->ptr_ != 0)
+ {
+ ACE_Errno_Guard eguard (errno);
+ this->ptr_->remove_reference ();
+ }
+}
+
+ACE_Event_Handler_var &
+ACE_Event_Handler_var::operator= (ACE_Event_Handler *p)
+{
+ if (this->ptr_ != p)
+ {
+ ACE_Event_Handler_var tmp (p);
+ std::swap (this->ptr_, tmp.ptr_);
+ }
+
+ return *this;
+}
+
+ACE_Event_Handler_var &
+ACE_Event_Handler_var::operator= (const ACE_Event_Handler_var &b)
+{
+ ACE_Event_Handler_var tmp (b);
+ std::swap (this->ptr_, tmp.ptr_);
+
+ return *this;
+}
+
+ACE_Event_Handler *
+ACE_Event_Handler_var::operator->() const
+{
+ return this->ptr_;
+}
+
+ACE_Event_Handler *
+ACE_Event_Handler_var::handler (void) const
+{
+ return this->ptr_;
+}
+
+ACE_Event_Handler *
+ACE_Event_Handler_var::release (void)
+{
+ ACE_Event_Handler * const old = this->ptr_;
+ this->ptr_ = 0;
+ return old;
+}
+
+void
+ACE_Event_Handler_var::reset (ACE_Event_Handler *p)
+{
+ *this = p;
+}
+
+// ---------------------------------------------------------------------
+
+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");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Event_Handler.h b/ACE/ace/Event_Handler.h
new file mode 100644
index 00000000000..3ccaf1d1aa0
--- /dev/null
+++ b/ACE/ace/Event_Handler.h
@@ -0,0 +1,388 @@
+/* -*- 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_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_signal.h"
+#include "ace/Atomic_Op.h"
+#include "ace/Synch_Traits.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration.
+class ACE_Message_Block;
+class ACE_Reactor;
+class ACE_Reactor_Timer_Interface;
+class ACE_Thread_Manager;
+class ACE_Process;
+
+typedef unsigned 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.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Set the I/O handle.
+ 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.
+ virtual int priority (void) const;
+
+ /// Set the priority of the Event_Handler.
+ 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. @a current_time represents the current
+ * time that the <Event_Handler> was selected for timeout
+ * dispatching and @a 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
+ /// @a close_mask indicates which event has triggered the
+ /// <handle_close> method callback on a particular @a 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);
+
+ enum
+ {
+ /// The handler is not resumed at all. Could lead to deadlock..
+ ACE_EVENT_HANDLER_NOT_RESUMED = -1,
+ /// The reactor takes responsibility of resuming the handler and
+ /// is the default
+ ACE_REACTOR_RESUMES_HANDLER = 0,
+ /// The application takes responsibility of resuming the handler
+ ACE_APPLICATION_RESUMES_HANDLER
+ };
+ /**
+ * 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.
+ *
+ * @note This method is only useful for the ACE_TP_Reactor. Sad
+ * that we have to have this method in a class that is supposed to
+ * be used across different components in ACE.
+ */
+ 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.
+ /// Set the event demultiplexors.
+ virtual void reactor (ACE_Reactor *reactor);
+
+ /// Get the event demultiplexors.
+ virtual ACE_Reactor *reactor (void) const;
+
+ /// Get only the reactor's timer related interface.
+ virtual ACE_Reactor_Timer_Interface *reactor_timer_interface (void) const;
+
+ /**
+ * 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 @a 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 ACE_THR_FUNC_RETURN 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);
+
+ /// Reference count type.
+ typedef long Reference_Count;
+
+ /// Increment reference count on the handler.
+ /**
+ * This method is called when the handler is registered with the
+ * Reactor and when the Reactor makes an upcall on the handler.
+ * Reference count is 1 when the handler is created.
+ *
+ * @return Current reference count.
+ */
+ virtual Reference_Count add_reference (void);
+
+ /// Decrement reference count on the handler.
+ /**
+ * This method is called when the handler is removed from the
+ * Reactor and when an upcall made on the handler by the Reactor
+ * completes. Handler is deleted when the reference count reaches
+ * 0.
+ *
+ * @return Current reference count.
+ */
+ virtual Reference_Count remove_reference (void);
+
+ /**
+ * @class Policy
+ *
+ * @brief Base class for all handler policies.
+ */
+ class ACE_Export Policy
+ {
+
+ public:
+
+ /// Virtual destructor.
+ virtual ~Policy (void);
+ };
+
+ /**
+ * @class Reference_Counting_Policy
+ *
+ * @brief This policy dictates the reference counting requirements
+ * for the handler.
+ *
+ * This policy allows applications to configure whether it wants the
+ * Reactor to call add_reference() and remove_reference() during
+ * registrations, removals, and upcalls.
+ *
+ * <B>Default:</B> DISABLED.
+ */
+ class ACE_Export Reference_Counting_Policy : public Policy
+ {
+ /// This policy can only be created by the handler.
+ friend class ACE_Event_Handler;
+
+ public:
+
+ enum Value
+ {
+ /// Perform reference counting.
+ ENABLED,
+ /// Don't perform reference counting.
+ DISABLED
+ };
+
+ /// Current Reference_Counting_Policy.
+ Value value (void) const;
+
+ /// Update Reference_Counting_Policy.
+ void value (Value value);
+
+ private:
+
+ /// Private constructor.
+ Reference_Counting_Policy (Value value);
+
+ /// The value of the policy.
+ Value value_;
+ };
+
+ /// Current Reference_Counting_Policy.
+ Reference_Counting_Policy &reference_counting_policy (void);
+
+protected:
+ /// Force ACE_Event_Handler to be an abstract base class.
+ ACE_Event_Handler (ACE_Reactor * = 0,
+ int priority = ACE_Event_Handler::LO_PRIORITY);
+
+ /// Typedef for implementation of reference counting.
+ typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, Reference_Count> Atomic_Reference_Count;
+
+ /// Reference count.
+ Atomic_Reference_Count reference_count_;
+
+private:
+
+ /// Priority of this Event_Handler.
+ int priority_;
+
+ /// Pointer to the various event demultiplexors.
+ ACE_Reactor *reactor_;
+
+ /// Reference counting requirements.
+ Reference_Counting_Policy reference_counting_policy_;
+};
+
+/**
+ * @class ACE_Event_Handler_var
+ *
+ * @brief Auto pointer like class for Event Handlers.
+ *
+ * Used to manage lifecycle of handlers. This class calls
+ * ACE_Event_Handler::remove_reference() in its destructor.
+ */
+class ACE_Export ACE_Event_Handler_var
+{
+
+public:
+
+ /// Default constructor.
+ ACE_Event_Handler_var (void);
+
+ /// Construct with a handler.
+ ACE_Event_Handler_var (ACE_Event_Handler *p);
+
+ /// Copy constructor.
+ ACE_Event_Handler_var (const ACE_Event_Handler_var &b);
+
+ /// Destructor.
+ ~ACE_Event_Handler_var (void);
+
+ /// Assignment to a handler.
+ ACE_Event_Handler_var &operator= (ACE_Event_Handler *p);
+
+ /// Assignment to a ACE_Event_Handler_var.
+ ACE_Event_Handler_var &operator= (const ACE_Event_Handler_var &b);
+
+ /// Overloaded "->".
+ ACE_Event_Handler *operator-> () const;
+
+ /// Access the handler.
+ ACE_Event_Handler *handler (void) const;
+
+ /// Release the handler.
+ ACE_Event_Handler *release (void);
+
+ /// Reset the handler.
+ void reset (ACE_Event_Handler *p = 0);
+
+private:
+
+ /// Handler.
+ ACE_Event_Handler *ptr_;
+};
+
+/**
+ * @class ACE_Notification_Buffer
+ *
+ * @brief Simple wrapper for passing <ACE_Event_Handler *>s and
+ * ACE_Reactor_Masks 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Event_Handler.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_EVENT_HANDLER_H */
diff --git a/ACE/ace/Event_Handler.inl b/ACE/ace/Event_Handler.inl
new file mode 100644
index 00000000000..75f2cd12aa5
--- /dev/null
+++ b/ACE/ace/Event_Handler.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Notification_Buffer::~ACE_Notification_Buffer (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Event_Handler_T.cpp b/ACE/ace/Event_Handler_T.cpp
new file mode 100644
index 00000000000..51a03f62310
--- /dev/null
+++ b/ACE/ace/Event_Handler_T.cpp
@@ -0,0 +1,125 @@
+// Event_Handler_T.cpp
+//
+// $Id$
+
+#ifndef ACE_EVENT_HANDLER_T_CPP
+#define ACE_EVENT_HANDLER_T_CPP
+
+#include "ace/Event_Handler_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Event_Handler_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Event_Handler_T)
+
+template <class T> void
+ACE_Event_Handler_T<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Event_Handler_T<T>::dump");
+#endif /* ACE_HAS_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");
+}
+
+template<class T> 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 ? ACE_INVALID_HANDLE : (this->op_handler_->*get_handle_) ();
+}
+
+template<class T> 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> 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> 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> 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> 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> 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> 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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+#endif /* ACE_EVENT_HANDLER_T_CPP */
diff --git a/ACE/ace/Event_Handler_T.h b/ACE/ace/Event_Handler_T.h
new file mode 100644
index 00000000000..71c97bcf4a8
--- /dev/null
+++ b/ACE/ace/Event_Handler_T.h
@@ -0,0 +1,191 @@
+/* -*- 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)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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) (int, 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 = ACE_INVALID_HANDLE);
+ virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+ virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+ 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Event_Handler_T.inl"
+#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/ace/Event_Handler_T.inl b/ACE/ace/Event_Handler_T.inl
new file mode 100644
index 00000000000..c3facd7e25f
--- /dev/null
+++ b/ACE/ace/Event_Handler_T.inl
@@ -0,0 +1,135 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 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 (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 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 (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 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 (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 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 (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 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 (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 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 (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 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 (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 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 (typename ACE_Event_Handler_T<T>::SIG_HANDLER h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::sig_handler");
+ this->sig_handler_ = h;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Exception_Macros.h b/ACE/ace/Exception_Macros.h
new file mode 100644
index 00000000000..7efc532f93a
--- /dev/null
+++ b/ACE/ace/Exception_Macros.h
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+
+// ============================================================================
+/**
+ * @file Exception_Macros.h
+ *
+ * $Id$
+ *
+ * Writing code that is portable between platforms with or without
+ * native C++ exceptions is hard. The following macros offer some
+ * help on this task.
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ * @author Aniruddha Gokhale <gokhale@sahyadri.research.bell-labs.com>
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ * @author Krishnakumar B <kitty@cs.wustl.edu>, et al.
+ */
+// ============================================================================
+
+// Macros for handling exceptions.
+
+#ifndef ACE_EXCEPTION_MACROS_H
+#define ACE_EXCEPTION_MACROS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// By default, if the compiler supports native exception handling, assume
+// CORBA also support native exception handling. But it can be disabled by
+// defining ACE_CORBA_HAS_EXCEPTIONS=0. If the compiler does not support
+// exceptions handling, make sure native exception handling is disabled.
+#if defined (ACE_HAS_EXCEPTIONS)
+# if defined (ACE_CORBA_HAS_EXCEPTIONS)
+# if (ACE_CORBA_HAS_EXCEPTIONS == 0)
+# undef ACE_USES_NATIVE_EXCEPTIONS
+# else /* ACE_CORBA_HAS_EXCEPTIONS != 0 */
+# define ACE_USES_NATIVE_EXCEPTIONS
+# endif /* ACE_CORBA_HAS_EXCEPTIONS == 0 */
+# else
+# define ACE_USES_NATIVE_EXCEPTIONS
+# define ACE_CORBA_HAS_EXCEPTIONS
+# endif /* ACE_CORBA_HAS_EXCEPTIONS */
+#else /* ! ACE_HAS_EXCEPTIONS */
+# undef ACE_CORBA_HAS_EXCEPTIONS
+# undef ACE_USES_NATIVE_EXCEPTIONS
+#endif /* ACE_HAS_EXCEPTIONS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_EXCEPTION_MACROS_H */
diff --git a/ACE/ace/FIFO.cpp b/ACE/ace/FIFO.cpp
new file mode 100644
index 00000000000..22172e376f7
--- /dev/null
+++ b/ACE/ace/FIFO.cpp
@@ -0,0 +1,78 @@
+// $Id$
+
+#include "ace/FIFO.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FIFO.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID(ace, FIFO, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO)
+
+void
+ACE_FIFO::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FIFO::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("rendezvous_ = %s"), this->rendezvous_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_FIFO::open (const ACE_TCHAR *r, int flags, mode_t perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO::open");
+ ACE_OS::strsncpy (this->rendezvous_, r, MAXPATHLEN);
+
+ if ((flags & O_CREAT) != 0
+ && ACE_OS::mkfifo (this->rendezvous_, perms) == -1
+ && !(errno == EEXIST))
+ return -1;
+
+ 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,
+ mode_t perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO::ACE_FIFO");
+ if (this->open (fifo_name, flags, perms, sa) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO.h b/ACE/ace/FIFO.h
new file mode 100644
index 00000000000..3866b0e4eb8
--- /dev/null
+++ b/ACE/ace/FIFO.h
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file FIFO.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//==========================================================================
+
+
+#ifndef ACE_FIFO_H
+#define ACE_FIFO_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/IPC_SAP.h"
+#include "ace/os_include/os_limits.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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, mode_t 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, mode_t perms,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+private:
+ /// Rendezvous point in the file system.
+ ACE_TCHAR rendezvous_[MAXPATHLEN + 1];
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FIFO.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FIFO_H */
diff --git a/ACE/ace/FIFO.inl b/ACE/ace/FIFO.inl
new file mode 100644
index 00000000000..149ed11318b
--- /dev/null
+++ b/ACE/ace/FIFO.inl
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 const result = this->close ();
+ return ACE_OS::unlink (this->rendezvous_) == -1 || result == -1 ? -1 : 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO_Recv.cpp b/ACE/ace/FIFO_Recv.cpp
new file mode 100644
index 00000000000..ca1305cf71a
--- /dev/null
+++ b/ACE/ace/FIFO_Recv.cpp
@@ -0,0 +1,88 @@
+// $Id$
+
+#include "ace/FIFO_Recv.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_fcntl.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FIFO_Recv.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FIFO_Recv, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Recv)
+
+void
+ACE_FIFO_Recv::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FIFO_Recv::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_FIFO::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("aux_handle_ = %d"), this->aux_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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,
+ mode_t 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,
+ mode_t 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_TEXT ("%p\n"), ACE_TEXT ("ACE_FIFO_Recv")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO_Recv.h b/ACE/ace/FIFO_Recv.h
new file mode 100644
index 00000000000..fa18cf291a5
--- /dev/null
+++ b/ACE/ace/FIFO_Recv.h
@@ -0,0 +1,85 @@
+// -*- 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 */
+
+#include "ace/os_include/os_fcntl.h"
+#include "ace/Default_Constants.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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,
+ mode_t 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,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS,
+ int persistent = 1,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Close down the named pipe.
+ int close (void);
+
+ /// Recv @a buf of up to @a len bytes.
+ ssize_t recv (void *buf, size_t len);
+
+ /// Recv @a buf of exactly @a 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FIFO_Recv.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_FIFO_RECV_H */
diff --git a/ACE/ace/FIFO_Recv.inl b/ACE/ace/FIFO_Recv.inl
new file mode 100644
index 00000000000..b5cf96cb56d
--- /dev/null
+++ b/ACE/ace/FIFO_Recv.inl
@@ -0,0 +1,24 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/ACE.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO_Recv_Msg.cpp b/ACE/ace/FIFO_Recv_Msg.cpp
new file mode 100644
index 00000000000..68d77af8a78
--- /dev/null
+++ b/ACE/ace/FIFO_Recv_Msg.cpp
@@ -0,0 +1,67 @@
+// $Id$
+
+#include "ace/FIFO_Recv_Msg.h"
+
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FIFO_Recv_Msg.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FIFO_Recv_Msg, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Recv_Msg)
+
+void
+ACE_FIFO_Recv_Msg::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::dump");
+ ACE_FIFO_Recv::dump ();
+#endif /* ACE_HAS_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,
+ mode_t 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,
+ mode_t 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_TEXT ("%p\n"), ACE_TEXT ("ACE_FIFO_Recv_Msg")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO_Recv_Msg.h b/ACE/ace/FIFO_Recv_Msg.h
new file mode 100644
index 00000000000..b1c7afe3eb3
--- /dev/null
+++ b/ACE/ace/FIFO_Recv_Msg.h
@@ -0,0 +1,138 @@
+// -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls
+class ACE_Str_Buf;
+
+/**
+ * @class ACE_FIFO_Recv_Msg
+ *
+ * @brief Receiver side for the record oriented C++ wrapper for UNIX FIFOs.
+ *
+ * This method works slightly differently on platforms with the
+ * @c ACE_HAS_STREAM_PIPES configuration setting than those without.
+ * With ACE_HAS_STREAM_PIPES, the @c getmsg() system function is used
+ * and it preserves message boundaries internally. Without
+ * @c ACE_HAS_STREAM_PIPES, the message boundaries are emulated by
+ * this class and ACE_FIFO_Send_Msg cooperating. The sending class
+ * first writes an integer number of bytes in the message, then the
+ * message. ACE_FIFO_Recv_Msg reads the count, then the data.
+ * The operational differences occur primarily when a message is larger
+ * than what a caller of this class requests. See recv() for details.
+ */
+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,
+ mode_t 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,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS,
+ int persistent = 1,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Receive a message based on attributes in an ACE_Str_Buf.
+ /**
+ * @param msg Reference to an ACE_Str_Buf whose @c buf member points
+ * to the memory to receive the data and @c maxlen member
+ * contains the maximum number of bytes to receive.
+ * On return after successfully reading data, the
+ * @c len member contains the number of bytes received and
+ * placed in the buffer pointed to by @c msg.buf.
+ *
+ * @retval -1 Error; consult @c errno for specific error number.
+ * @return If the @c ACE_HAS_STREAM_PIPES configuration setting is
+ * defined, the return value is the number of bytes received
+ * in the message and will be the same as @c buf.len.
+ * The return value from the @c getmsg() system function
+ * is discarded.
+ * If @c ACE_HAS_STREAM_PIPES is not defined, the number
+ * of bytes in the message read from the FIFO is returned.
+ * If the message is larger than the maximum length
+ * requested in @c msg.maxlen, the return value reflects
+ * the entire message length, and the @c msg.len member
+ * reflects how many bytes were actually placed in the
+ * caller's buffer. Any part of the message longer than
+ * @c msg.maxlen is discarded.
+ */
+ ssize_t recv (ACE_Str_Buf &msg);
+
+ /// Receive a message based on buffer pointer and maximum size.
+ /**
+ * @param buf Pointer to the memory to receive the data.
+ * @param len The maximum number of bytes to receive.
+ *
+ * @retval -1 Error; consult @c errno for specific error number.
+ * @return The number of bytes received in the message. For messages
+ * that are larger than the requested maximum size, the
+ * behavior is different depending on the @c ACE_HAS_STREAM_PIPES
+ * configuration setting. With @c ACE_HAS_STREAM_PIPES,
+ * the return value will be the same as @arg len (this is
+ * also possible if the message is exactly the same length
+ * as @arg len, and the two cases are indistinguishable).
+ * Without @c ACE_HAS_STREAM_PIPES, the return value is
+ * the total length of the message, including bytes in
+ * excess of @arg len. The excess bytes are discarded.
+ */
+ 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FIFO_Recv_Msg.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FIFO_RECV_MSG_H */
diff --git a/ACE/ace/FIFO_Recv_Msg.inl b/ACE/ace/FIFO_Recv_Msg.inl
new file mode 100644
index 00000000000..bab21a7e20e
--- /dev/null
+++ b/ACE/ace/FIFO_Recv_Msg.inl
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Min_Max.h"
+#include "ace/OS_NS_stropts.h"
+
+#if !defined (ACE_HAS_STREAM_PIPES)
+#include "ace/OS_NS_unistd.h"
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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
+ {
+ size_t remaining = static_cast<size_t> (recv_msg.len);
+ size_t requested = static_cast<size_t> (recv_msg.maxlen);
+ ssize_t recv_len = ACE_OS::read (this->get_handle (),
+ (char *) recv_msg.buf,
+ ACE_MIN (remaining, requested));
+ if (recv_len == -1)
+ return -1;
+ // Tell caller what's really in the buffer.
+ recv_msg.len = static_cast<int> (recv_len);
+
+ // If there are more bytes remaining in the message, read them and
+ // throw them away. Leaving them in the FIFO would make it difficult
+ // to find the start of the next message in the fifo.
+ // Since the ACE_HAS_STREAM_PIPES version of this method doesn't
+ // return getmsg()'s indication of "data remaining", don't worry about
+ // saving the indication here either to read the remainder later.
+ size_t total_msg_size = remaining;
+ remaining -= recv_len;
+ while (remaining > 0)
+ {
+ const size_t throw_away = 1024;
+ char dev_null[throw_away];
+ recv_len = ACE_OS::read (this->get_handle (),
+ dev_null,
+ ACE_MIN (remaining, throw_away));
+ if (recv_len == -1)
+ break;
+ remaining -= recv_len;
+ }
+ return total_msg_size;
+ }
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_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, static_cast<int> (max_len));
+
+ return this->recv (recv_msg);
+}
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ACE_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);
+}
+
+ACE_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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO_Send.cpp b/ACE/ace/FIFO_Send.cpp
new file mode 100644
index 00000000000..47a3c90e814
--- /dev/null
+++ b/ACE/ace/FIFO_Send.cpp
@@ -0,0 +1,58 @@
+// $Id$
+
+#include "ace/FIFO_Send.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FIFO_Send.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FIFO_Send, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Send)
+
+void
+ACE_FIFO_Send::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FIFO_Send::dump");
+ ACE_FIFO::dump ();
+#endif /* ACE_HAS_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,
+ mode_t 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,
+ mode_t 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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_FIFO_Send::ACE_FIFO_Send")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO_Send.h b/ACE/ace/FIFO_Send.h
new file mode 100644
index 00000000000..51a14508114
--- /dev/null
+++ b/ACE/ace/FIFO_Send.h
@@ -0,0 +1,75 @@
+// -*- 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 */
+
+#include "ace/os_include/os_fcntl.h"
+#include "ace/Default_Constants.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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,
+ mode_t 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,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Send @a buf of up to @a len bytes.
+ ssize_t send (const void *buf, size_t len);
+
+ /// Send @a buf of exactly @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FIFO_Send.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_FIFO_SEND_H */
diff --git a/ACE/ace/FIFO_Send.inl b/ACE/ace/FIFO_Send.inl
new file mode 100644
index 00000000000..12491058e2c
--- /dev/null
+++ b/ACE/ace/FIFO_Send.inl
@@ -0,0 +1,24 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/ACE.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO_Send_Msg.cpp b/ACE/ace/FIFO_Send_Msg.cpp
new file mode 100644
index 00000000000..c06b737a6bb
--- /dev/null
+++ b/ACE/ace/FIFO_Send_Msg.cpp
@@ -0,0 +1,80 @@
+// $Id$
+
+#include "ace/FIFO_Send_Msg.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_uio.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FIFO_Send_Msg.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FIFO_Send_Msg, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Send_Msg)
+
+void
+ACE_FIFO_Send_Msg::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FIFO_Send_Msg::dump");
+ ACE_FIFO_Send::dump ();
+#endif /* ACE_HAS_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 = static_cast<u_long> (send_msg.len);
+
+ ssize_t sent = ACE_OS::writev (this->get_handle (), iov, 2);
+ if (sent > 0)
+ sent -= iov[0].iov_len; // Don't count the length we added.
+ return sent;
+#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,
+ mode_t 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,
+ mode_t 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_TEXT ("%p\n"), ACE_TEXT ("ACE_FIFO_Send_Msg")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FIFO_Send_Msg.h b/ACE/ace/FIFO_Send_Msg.h
new file mode 100644
index 00000000000..a2e0affce8a
--- /dev/null
+++ b/ACE/ace/FIFO_Send_Msg.h
@@ -0,0 +1,91 @@
+/* -*- 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 */
+
+#if defined (ACE_HAS_STREAM_PIPES)
+# include "ace/OS_NS_stropts.h"
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward Decls
+class ACE_Str_Buf;
+
+/**
+ * @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,
+ mode_t 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,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Send @a buf of up to @a len bytes.
+ ssize_t send (const ACE_Str_Buf &msg);
+
+ /// Send @a buf of exactly @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FIFO_Send_Msg.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FIFO_SEND_MSG_H */
diff --git a/ACE/ace/FIFO_Send_Msg.inl b/ACE/ace/FIFO_Send_Msg.inl
new file mode 100644
index 00000000000..74392656597
--- /dev/null
+++ b/ACE/ace/FIFO_Send_Msg.inl
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_stropts.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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, static_cast<int> (len));
+
+ return this->send (send_msg);
+}
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ACE_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);
+}
+
+ACE_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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FILE.cpp b/ACE/ace/FILE.cpp
new file mode 100644
index 00000000000..8b3015524e3
--- /dev/null
+++ b/ACE/ace/FILE.cpp
@@ -0,0 +1,147 @@
+// $Id$
+
+/* Defines the member functions for the base class of the ACE_IO_SAP
+ ACE_FILE abstraction. */
+
+#include "ace/FILE.h"
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_stat.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FILE.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FILE, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FILE)
+
+void
+ACE_FILE::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FILE::dump");
+ ACE_IO_SAP::dump ();
+#endif /* ACE_HAS_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 = 0;
+
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ {
+ 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 const 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 (ACE_OFF_T length)
+{
+ ACE_TRACE ("ACE_FILE::truncate");
+ return ACE_OS::ftruncate (this->get_handle (), length);
+}
+
+ACE_OFF_T
+ACE_FILE::seek (ACE_OFF_T offset, int startpos)
+{
+ return ACE_OS::lseek (this->get_handle (), offset, startpos);
+}
+
+ACE_OFF_T
+ACE_FILE::tell (void)
+{
+ ACE_TRACE ("ACE_FILE::tell");
+ return ACE_OS::lseek (this->get_handle (), 0, SEEK_CUR);
+}
+
+// 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 =
+ 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 ());
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FILE.h b/ACE/ace/FILE.h
new file mode 100644
index 00000000000..bf8f4561d4f
--- /dev/null
+++ b/ACE/ace/FILE.h
@@ -0,0 +1,139 @@
+/* -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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
+ ACE_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 (ACE_OFF_T length);
+
+ /**
+ * Sets the file pointer as follows:
+ * o If <whence> is <SEEK_SET>, the pointer is set to @a offset
+ * bytes.
+ *
+ * o If <whence> is <SEEK_CUR>, the pointer is set to its
+ * current location plus @a offset.
+ *
+ * o If <whence> is <SEEK_END>, the pointer is set to the size
+ * of the file plus offset.
+ */
+ ACE_OFF_T seek (ACE_OFF_T offset,
+ int whence = SEEK_CUR);
+
+ /// Return an offset for the file handle.
+ ACE_OFF_T tell (void);
+
+ /**
+ * Disable signal @a 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FILE.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FILE_H */
diff --git a/ACE/ace/FILE.inl b/ACE/ace/FILE.inl
new file mode 100644
index 00000000000..fdd65029d3a
--- /dev/null
+++ b/ACE/ace/FILE.inl
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FILE_Addr.cpp b/ACE/ace/FILE_Addr.cpp
new file mode 100644
index 00000000000..79d9db6e296
--- /dev/null
+++ b/ACE/ace/FILE_Addr.cpp
@@ -0,0 +1,124 @@
+// $Id$
+
+#include "ace/FILE_Addr.h"
+#include "ace/Lib_Find.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/sys/os_socket.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FILE_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FILE_Addr, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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::get_temp_dir (this->filename_, MAXPATHLEN - 15) == -1)
+ // -15 for ace-file-XXXXXX
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Temporary path too long, ")
+ ACE_TEXT ("defaulting to current directory\n")));
+ this->filename_[0] = 0;
+ }
+
+ // Add the filename to the end
+ ACE_OS::strcat (this->filename_, ACE_TEXT ("ace-fileXXXXXX"));
+
+#endif /* ACE_DEFAULT_TEMP_FILE */
+
+ if (ACE_OS::mktemp (this->filename_) == 0)
+ return -1;
+ this->base_set (AF_FILE,
+ static_cast<int> (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,
+ static_cast<int> (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;
+}
+
+// Return the address.
+
+void *
+ACE_FILE_Addr::get_addr (void) const
+{
+ return (void *)&this->filename_;
+}
+
+void
+ACE_FILE_Addr::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FILE_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("filename_ = %s"), this->filename_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FILE_Addr.h b/ACE/ace/FILE_Addr.h
new file mode 100644
index 00000000000..2fa9e0f4ae4
--- /dev/null
+++ b/ACE/ace/FILE_Addr.h
@@ -0,0 +1,89 @@
+// -*- 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"
+#include "ace/os_include/os_dirent.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a 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.
+ 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.
+ bool operator == (const ACE_FILE_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ bool 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_[MAXPATHLEN + 1];
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FILE_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FILE_ADDR_H */
diff --git a/ACE/ace/FILE_Addr.inl b/ACE/ace/FILE_Addr.inl
new file mode 100644
index 00000000000..e03cd2ab156
--- /dev/null
+++ b/ACE/ace/FILE_Addr.inl
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#include "ace/SString.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Compare two addresses for equality.
+
+ACE_INLINE bool
+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 bool
+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_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FILE_Connector.cpp b/ACE/ace/FILE_Connector.cpp
new file mode 100644
index 00000000000..c136b0b47eb
--- /dev/null
+++ b/ACE/ace/FILE_Connector.cpp
@@ -0,0 +1,84 @@
+// $Id$
+
+#include "ace/FILE_Connector.h"
+#include "ace/Handle_Ops.h"
+#include "ace/OS_NS_stdlib.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FILE_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FILE_Connector, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FILE_Connector)
+
+void
+ACE_FILE_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FILE_Connector::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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 (reinterpret_cast<const ACE_Addr &> (
+ const_cast<ACE_FILE_Addr &> (remote_sap)) == ACE_Addr::sap_any)
+ {
+ // Create a new temporary file.
+ // 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 (ACE_TEXT_CHAR_TO_TCHAR (filename)) != 0)
+ return -1;
+
+ new_io.set_handle (handle);
+
+ return 0;
+ }
+ else
+ new_io.addr_ = remote_sap; // class copy.
+
+ handle = ACE::handle_timed_open (timeout,
+ new_io.addr_.get_path_name (),
+ flags,
+ perms);
+
+ new_io.set_handle (handle);
+ return handle == ACE_INVALID_HANDLE ? -1 : 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FILE_Connector.h b/ACE/ace/FILE_Connector.h
new file mode 100644
index 00000000000..b02b01e7dbb
--- /dev/null
+++ b/ACE/ace/FILE_Connector.h
@@ -0,0 +1,113 @@
+/* -*- 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"
+#include "ace/os_include/os_fcntl.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a new_io ACE_FILE_IO object
+ * if things go well. The @a 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::mkstemp>). The @a 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. If *timeout > {0, 0} then this is the
+ * maximum amount of time to wait before timing out. The
+ * @a local_sap and @a reuse_addr parameters are ignored. The @a flags
+ * and @a 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 @a new_io <ACE_FILE_IO> object
+ * if things go well. The @a 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::mkstemp>). The @a 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 @c errno == ETIME. The @a local_sap and
+ * @a reuse_addr parameters are ignored. The @a flags and @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FILE_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FILE_CONNECTOR_H */
diff --git a/ACE/ace/FILE_Connector.inl b/ACE/ace/FILE_Connector.inl
new file mode 100644
index 00000000000..d598341ba8d
--- /dev/null
+++ b/ACE/ace/FILE_Connector.inl
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// Creates a Local ACE_FILE.
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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_TEXT ("address %s, %p\n"),
+ remote_sap.get_path_name (),
+ ACE_TEXT ("ACE_FILE_IO")));
+}
+
+ACE_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FILE_IO.cpp b/ACE/ace/FILE_IO.cpp
new file mode 100644
index 00000000000..bf0c41bf418
--- /dev/null
+++ b/ACE/ace/FILE_IO.cpp
@@ -0,0 +1,142 @@
+// $Id$
+
+#include "ace/FILE_IO.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_Memory.h"
+#include "ace/Truncate.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FILE_IO.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FILE_IO, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FILE_IO)
+
+void
+ACE_FILE_IO::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_FILE_IO::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->addr_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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;
+ int total_tuples = ACE_Utils::truncate_cast<int> (n / 2);
+ iovec *iovp = 0;
+#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 (int 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;
+ int total_tuples = ACE_Utils::truncate_cast<int> (n / 2);
+ iovec *iovp = 0;
+#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 (int i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+ ssize_t const 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;
+ size_t const length = static_cast <size_t> (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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FILE_IO.h b/ACE/ace/FILE_IO.h
new file mode 100644
index 00000000000..e975c0cc2c9
--- /dev/null
+++ b/ACE/ace/FILE_IO.h
@@ -0,0 +1,170 @@
+/* -*- 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/os_include/os_stdio.h"
+#include "ace/os_include/sys/os_uio.h"
+
+#if defined (ACE_HAS_STREAM_PIPES)
+# include "ace/OS_NS_stropts.h"
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl.
+class ACE_Message_Block;
+class ACE_Time_Value;
+
+/**
+ * @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 @a n bytes in @a buf.
+ ssize_t send (const void *buf, size_t n) const;
+
+ /// Recv upto @a n bytes in @a 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 @a message_blocks 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[], int n) const;
+
+ /// Recv iovecs via <::readv>.
+ ssize_t recv (iovec iov[], int 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 @a n bytes via Win32 WriteFile using overlapped I/O.
+ ssize_t send (const void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Recv @a n bytes via Win32 ReadFile using overlapped I/O.
+ ssize_t recv (void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Send an @c iovec of size @a n to the file.
+ ssize_t sendv (const iovec iov[],
+ int 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 @a n to the file. Will block until all
+ /// bytes are sent or an error occurs.
+ ssize_t sendv_n (const iovec iov[],
+ int n) const;
+
+ /// Receive an <iovec> of size @a n to the file.
+ ssize_t recvv_n (iovec iov[],
+ int 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/FILE_IO.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FILE_IO_H */
diff --git a/ACE/ace/FILE_IO.inl b/ACE/ace/FILE_IO.inl
new file mode 100644
index 00000000000..7db33a0c717
--- /dev/null
+++ b/ACE/ace/FILE_IO.inl
@@ -0,0 +1,152 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/ACE.h"
+#include "ace/OS_NS_sys_uio.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ssize_t
+ACE_FILE_IO::sendv_n (const iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::sendv_n");
+ return ACE::writev_n (this->get_handle (),
+ iov,
+ n);
+}
+
+ACE_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.
+
+ACE_INLINE ssize_t
+ACE_FILE_IO::recvv_n (iovec iov[], int 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.
+
+ACE_INLINE ssize_t
+ACE_FILE_IO::sendv (const iovec iov[], int 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.
+
+ACE_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.
+
+ACE_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);
+}
+
+ACE_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 (), buf, n);
+}
+
+ACE_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 (), buf, n);
+}
+
+ACE_INLINE ssize_t
+ACE_FILE_IO::send (const iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::send");
+ return ACE_OS::writev (this->get_handle (), iov, n);
+}
+
+ACE_INLINE ssize_t
+ACE_FILE_IO::recv (iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recv");
+ return ACE_OS::readv (this->get_handle (), iov, n);
+}
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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 (),
+ buf, n,
+ overlapped);
+}
+
+ACE_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 (), buf, n,
+ overlapped);
+}
+
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/File_Lock.cpp b/ACE/ace/File_Lock.cpp
new file mode 100644
index 00000000000..88935c3a5d7
--- /dev/null
+++ b/ACE/ace/File_Lock.cpp
@@ -0,0 +1,72 @@
+// $Id$
+
+#include "ace/File_Lock.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/File_Lock.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, File_Lock, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_File_Lock)
+
+void
+ACE_File_Lock::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_File_Lock::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_File_Lock::ACE_File_Lock (ACE_HANDLE h,
+ int unlink_in_destructor)
+ : removed_ (0),
+ unlink_in_destructor_ (unlink_in_destructor)
+{
+// ACE_TRACE ("ACE_File_Lock::ACE_File_Lock");
+ if (ACE_OS::flock_init (&this->lock_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_File_Lock::ACE_File_Lock")));
+ this->set_handle (h);
+}
+
+ACE_File_Lock::ACE_File_Lock (const ACE_TCHAR *name,
+ int flags,
+ mode_t perms,
+ int unlink_in_destructor)
+ : unlink_in_destructor_ (unlink_in_destructor)
+{
+// ACE_TRACE ("ACE_File_Lock::ACE_File_Lock");
+
+ if (this->open (name, flags, perms) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p %s\n"),
+ ACE_TEXT ("ACE_File_Lock::ACE_File_Lock"),
+ name));
+}
+
+int
+ACE_File_Lock::open (const ACE_TCHAR *name,
+ int flags,
+ mode_t perms)
+{
+// ACE_TRACE ("ACE_File_Lock::open");
+ this->removed_ = 0;
+ return ACE_OS::flock_init (&this->lock_, flags, name, perms);
+}
+
+ACE_File_Lock::~ACE_File_Lock (void)
+{
+// ACE_TRACE ("ACE_File_Lock::~ACE_File_Lock");
+ this->remove (this->unlink_in_destructor_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/File_Lock.h b/ACE/ace/File_Lock.h
new file mode 100644
index 00000000000..eec103e1fe0
--- /dev/null
+++ b/ACE/ace/File_Lock.h
@@ -0,0 +1,170 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file File_Lock.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_FILE_LOCK_H
+#define ACE_FILE_LOCK_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_stdio.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_File_Lock
+ *
+ * @brief A wrapper around the UNIX file locking mechanism.
+ *
+ * Allows us to "adapt" the UNIX file locking mechanisms to work
+ * with all of our Guard stuff...
+ */
+class ACE_Export ACE_File_Lock
+{
+public:
+ /**
+ * Set the <handle_> of the File_Lock to @a handle. Note that this
+ * constructor assumes ownership of the @a handle and will close it
+ * down in <remove>. If you want the @a handle to stay open when
+ * <remove> is called make sure to call <dup> on the @a handle.
+ * If you don't want the file unlinked in the destructor pass a
+ * zero value for <unlink_in_destructor>.
+ */
+ ACE_File_Lock (ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ int unlink_in_destructor = 1);
+
+ /// Open the @a filename with @a flags and @a mode and set the result
+ /// to <handle_>. If you don't want the file unlinked in the
+ /// destructor pass a zero value for <unlink_in_destructor>.
+ ACE_File_Lock (const ACE_TCHAR *filename,
+ int flags,
+ mode_t mode = 0,
+ int unlink_in_destructor = 1);
+
+ /// Open the @a filename with @a flags and @a mode and set the result to
+ /// <handle_>.
+ int open (const ACE_TCHAR *filename,
+ int flags,
+ mode_t mode = 0);
+
+ /// Remove a File lock by releasing it and closing down the <handle_>.
+ ~ACE_File_Lock (void);
+
+ /// Remove a File lock by releasing it and closing down the
+ /// <handle_>. If <unlink_file> is non-0 then we unlink the file.
+ int remove (int unlink_file = 1);
+
+ /**
+ * Note, for interface uniformity with other synchronization
+ * wrappers we include the <acquire> method. This is implemented as
+ * a write-lock to be on the safe-side...
+ */
+ int acquire (short whence = 0, ACE_OFF_T start = 0, ACE_OFF_T len = 1);
+
+ /**
+ * Note, for interface uniformity with other synchronization
+ * wrappers we include the <tryacquire> method. This is implemented
+ * as a write-lock to be on the safe-side... Returns -1 on failure.
+ * If we "failed" because someone else already had the lock, @c errno
+ * is set to @c EBUSY.
+ */
+ int tryacquire (short whence = 0, ACE_OFF_T start = 0, ACE_OFF_T len = 1);
+
+ /// Unlock a readers/writer lock.
+ int release (short whence = 0, ACE_OFF_T start = 0, ACE_OFF_T len = 1);
+
+ /// Acquire a write lock, but block if any readers or a
+ /// writer hold the lock.
+ int acquire_write (short whence = 0, ACE_OFF_T start = 0, ACE_OFF_T len = 1);
+
+ /**
+ * Conditionally acquire a write lock (i.e., won't block). Returns
+ * -1 on failure. If we "failed" because someone else already had
+ * the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_write (short whence = 0, ACE_OFF_T start = 0, ACE_OFF_T len = 1);
+
+ /**
+ * Conditionally upgrade to a write lock (i.e., won't block). Returns
+ * -1 on failure. If we "failed" because someone else already had
+ * the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_write_upgrade (short whence = 0,
+ ACE_OFF_T start = 0,
+ ACE_OFF_T len = 1);
+
+ /**
+ * Acquire a read lock, but block if a writer hold the lock.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int acquire_read (short whence = 0, ACE_OFF_T start = 0, ACE_OFF_T len = 1);
+
+ /**
+ * Conditionally acquire a read lock (i.e., won't block). Returns
+ * -1 on failure. If we "failed" because someone else already had
+ * the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_read (short whence = 0, ACE_OFF_T start = 0, ACE_OFF_T len = 1);
+
+ /// Get underlying ACE_HANDLE for the file.
+ ACE_HANDLE get_handle (void) const;
+
+ /**
+ * Set underlying ACE_HANDLE. Note that this method assumes
+ * ownership of the <handle> and will close it down in <remove>. If
+ * you want the <handle> to stay open when <remove> is called make
+ * sure to call <dup> on the <handle> before closing it. You are
+ * responsible for the closing the existing <handle> before
+ * overwriting it.
+ */
+ void set_handle (ACE_HANDLE);
+
+ /// Dump state of the object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Locking structure for OS record locks.
+ ACE_OS::ace_flock_t lock_;
+
+ /// Keeps track of whether <remove> has been called yet to avoid
+ /// multiple <remove> calls, e.g., explicitly and implicitly in the
+ /// destructor. This flag isn't protected by a lock, so make sure
+ /// that you don't have multiple threads simultaneously calling
+ /// <remove> on the same object, which is a bad idea anyway...
+ int removed_;
+
+ /// Keeps track of whether to unlink the underlying file in the
+ /// destructor.
+ int unlink_in_destructor_;
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_File_Lock &);
+ ACE_File_Lock (const ACE_File_Lock &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/File_Lock.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FILE_LOCK_H */
diff --git a/ACE/ace/File_Lock.inl b/ACE/ace/File_Lock.inl
new file mode 100644
index 00000000000..bef9de9d063
--- /dev/null
+++ b/ACE/ace/File_Lock.inl
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_File_Lock::acquire_read (short whence, ACE_OFF_T start, ACE_OFF_T len)
+{
+// ACE_TRACE ("ACE_File_Lock::acquire_read");
+ return ACE_OS::flock_rdlock (&this->lock_, whence, start, len);
+}
+
+ACE_INLINE int
+ACE_File_Lock::tryacquire_read (short whence, ACE_OFF_T start, ACE_OFF_T len)
+{
+// ACE_TRACE ("ACE_File_Lock::tryacquire_read");
+ return ACE_OS::flock_tryrdlock (&this->lock_, whence, start, len);
+}
+
+ACE_INLINE int
+ACE_File_Lock::tryacquire_write (short whence, ACE_OFF_T start, ACE_OFF_T len)
+{
+// ACE_TRACE ("ACE_File_Lock::tryacquire_write");
+ return ACE_OS::flock_trywrlock (&this->lock_, whence, start, len);
+}
+
+ACE_INLINE int
+ACE_File_Lock::tryacquire_write_upgrade (short whence,
+ ACE_OFF_T start,
+ ACE_OFF_T len)
+{
+// ACE_TRACE ("ACE_File_Lock::tryacquire_write_upgrade");
+ return ACE_OS::flock_trywrlock (&this->lock_, whence, start, len);
+}
+
+ACE_INLINE int
+ACE_File_Lock::tryacquire (short whence, ACE_OFF_T start, ACE_OFF_T len)
+{
+// ACE_TRACE ("ACE_File_Lock::tryacquire");
+ return this->tryacquire_write (whence, start, len);
+}
+
+ACE_INLINE int
+ACE_File_Lock::acquire_write (short whence, ACE_OFF_T start, ACE_OFF_T len)
+{
+// ACE_TRACE ("ACE_File_Lock::acquire_write");
+ return ACE_OS::flock_wrlock (&this->lock_, whence, start, len);
+}
+
+ACE_INLINE int
+ACE_File_Lock::acquire (short whence, ACE_OFF_T start, ACE_OFF_T len)
+{
+// ACE_TRACE ("ACE_File_Lock::acquire");
+ return this->acquire_write (whence, start, len);
+}
+
+ACE_INLINE int
+ACE_File_Lock::release (short whence, ACE_OFF_T start, ACE_OFF_T len)
+{
+// ACE_TRACE ("ACE_File_Lock::release");
+ return ACE_OS::flock_unlock (&this->lock_, whence, start, len);
+}
+
+ACE_INLINE int
+ACE_File_Lock::remove (int unlink_file)
+{
+// ACE_TRACE ("ACE_File_Lock::remove");
+
+ int result = 0;
+
+ if (this->removed_ == 0)
+ {
+ this->removed_ = 1;
+ result = ACE_OS::flock_destroy (&this->lock_,
+ unlink_file);
+ }
+ return result;
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_File_Lock::get_handle (void) const
+{
+// ACE_TRACE ("ACE_File_Lock::get_handle");
+ return this->lock_.handle_;
+}
+
+ACE_INLINE void
+ACE_File_Lock::set_handle (ACE_HANDLE h)
+{
+// ACE_TRACE ("ACE_File_Lock::set_handle");
+ this->lock_.handle_ = h;
+ this->removed_ = 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Filecache.cpp b/ACE/ace/Filecache.cpp
new file mode 100644
index 00000000000..5122cb6fdc8
--- /dev/null
+++ b/ACE/ace/Filecache.cpp
@@ -0,0 +1,754 @@
+// $Id$
+
+#include "ace/Filecache.h"
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/Guard_T.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/Truncate.h"
+
+ACE_RCSID (ace,
+ Filecache,
+ "$Id$")
+
+#if defined (ACE_WIN32)
+// Specifies no sharing flags.
+#define R_MASK ACE_DEFAULT_OPEN_PERMS
+#define W_MASK 0
+#else
+#define R_MASK S_IRUSR|S_IRGRP|S_IROTH
+#define W_MASK S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_WIN32)
+// See if you can get rid of some of these.
+#define READ_FLAGS (FILE_FLAG_SEQUENTIAL_SCAN | \
+ FILE_FLAG_OVERLAPPED | \
+ O_RDONLY)
+// static const int RCOPY_FLAGS = (FILE_FLAG_SEQUENTIAL_SCAN |
+// O_RDONLY);
+#define WRITE_FLAGS (FILE_FLAG_SEQUENTIAL_SCAN | \
+ FILE_FLAG_OVERLAPPED | \
+ O_RDWR | O_CREAT | O_TRUNC)
+// static const int WCOPY_FLAGS = (FILE_FLAG_SEQUENTIAL_SCAN |
+// O_RDWR | O_CREAT | O_TRUNC);
+#else
+#define READ_FLAGS O_RDONLY
+// static const int RCOPY_FLAGS = O_RDONLY;
+#define WRITE_FLAGS (O_RDWR | O_CREAT | O_TRUNC)
+// static const int WCOPY_FLAGS = O_RDWR | O_CREAT | O_TRUNC;
+#endif /* ACE_WIN32 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// static data members
+ACE_Filecache *ACE_Filecache::cvf_ = 0;
+
+void
+ACE_Filecache_Handle::init (void)
+{
+ this->file_ = 0;
+ this->handle_ = ACE_INVALID_HANDLE;
+}
+
+ACE_Filecache_Handle::ACE_Filecache_Handle (void)
+ : file_ (0), handle_ (0), mapit_ (0)
+{
+ this->init ();
+}
+
+ACE_Filecache_Handle::ACE_Filecache_Handle (const ACE_TCHAR *filename,
+ ACE_Filecache_Flag mapit)
+ : file_ (0), handle_ (0), mapit_ (mapit)
+{
+ this->init ();
+ // Fetch the file from the Virtual_Filesystem let the
+ // Virtual_Filesystem do the work of cache coherency.
+
+ // Filecache will also do the acquire, since it holds the lock at
+ // that time.
+ this->file_ = ACE_Filecache::instance ()->fetch (filename, mapit);
+}
+
+ACE_Filecache_Handle::ACE_Filecache_Handle (const ACE_TCHAR *filename,
+ int size,
+ ACE_Filecache_Flag mapit)
+ : file_ (0), handle_ (0), mapit_ (mapit)
+{
+ this->init ();
+
+ if (size == 0)
+ ACE_Filecache::instance ()->remove (filename);
+ else
+ {
+ // Since this is being opened for a write, simply create a new
+ // ACE_Filecache_Object now, and let the destructor add it into CVF
+ // later
+
+ // Filecache will also do the acquire, since it holds the lock at
+ // that time.
+ this->file_ = ACE_Filecache::instance ()->create (filename, size);
+ }
+}
+
+ACE_Filecache_Handle::~ACE_Filecache_Handle (void)
+{
+ if (this->handle_ != ACE_INVALID_HANDLE)
+ // this was dup ()'d
+ ACE_OS::close (this->handle_);
+
+ ACE_Filecache::instance ()->finish (this->file_);
+}
+
+void *
+ACE_Filecache_Handle::address (void) const
+{
+ return this->file_ == 0 ? 0 : this->file_->address ();
+}
+
+ACE_HANDLE
+ACE_Filecache_Handle::handle (void) const
+{
+ if (this->handle_ == ACE_INVALID_HANDLE && this->file_ != 0)
+ {
+ ACE_Filecache_Handle *mutable_this =
+ const_cast<ACE_Filecache_Handle *> (this);
+ mutable_this->handle_ = ACE_OS::dup (this->file_->handle ());
+ }
+ return this->handle_;
+}
+
+int
+ACE_Filecache_Handle::error (void) const
+{
+ if (this->file_ == 0)
+ return -1;
+ else
+ return this->file_->error ();
+}
+
+ACE_OFF_T
+ACE_Filecache_Handle::size (void) const
+{
+ if (this->file_ == 0)
+ return -1;
+ else
+ return this->file_->size ();
+}
+
+// ------------------
+// ACE_Filecache_Hash
+// ------------------
+
+#define ACE_Filecache_Hash \
+ ACE_Hash_Map_Manager_Ex<const ACE_TCHAR *, ACE_Filecache_Object *, ACE_Hash<const ACE_TCHAR *>, ACE_Equal_To<const ACE_TCHAR *>, ACE_Null_Mutex>
+#define ACE_Filecache_Hash_Entry \
+ ACE_Hash_Map_Entry<const ACE_TCHAR *, ACE_Filecache_Object *>
+
+template <>
+ACE_Filecache_Hash_Entry::ACE_Hash_Map_Entry (
+ const ACE_TCHAR *const &ext_id,
+ ACE_Filecache_Object *const &int_id,
+ ACE_Filecache_Hash_Entry *next,
+ ACE_Filecache_Hash_Entry *prev)
+ : ext_id_ (ext_id
+ ? ACE_OS::strdup (ext_id)
+ : ACE_OS::strdup (ACE_TEXT (""))),
+ int_id_ (int_id),
+ next_ (next),
+ prev_ (prev)
+{
+}
+
+template <>
+ACE_Filecache_Hash_Entry::ACE_Hash_Map_Entry (ACE_Filecache_Hash_Entry *next,
+ ACE_Filecache_Hash_Entry *prev)
+ : ext_id_ (0),
+ next_ (next),
+ prev_ (prev)
+{
+}
+
+template <>
+ACE_Filecache_Hash_Entry::~ACE_Hash_Map_Entry (void)
+{
+ ACE_OS::free ((void *) ext_id_);
+}
+
+// We need these template specializations since KEY is defined as a
+// ACE_TCHAR*, which doesn't have a hash() or equal() method defined on it.
+
+template <>
+unsigned long
+ACE_Filecache_Hash::hash (const ACE_TCHAR *const &ext_id)
+{
+ return ACE::hash_pjw (ext_id);
+}
+
+template <>
+int
+ACE_Filecache_Hash::equal (const ACE_TCHAR *const &id1,
+ const ACE_TCHAR *const &id2)
+{
+ return ACE_OS::strcmp (id1, id2) == 0;
+}
+
+#undef ACE_Filecache_Hash
+#undef ACE_Filecache_Hash_Entry
+
+
+// -------------
+// ACE_Filecache
+// -------------
+
+ACE_Filecache *
+ACE_Filecache::instance (void)
+{
+ // Double check locking pattern.
+ if (ACE_Filecache::cvf_ == 0)
+ {
+ ACE_SYNCH_RW_MUTEX &lock =
+ *ACE_Managed_Object<ACE_SYNCH_RW_MUTEX>::get_preallocated_object
+ (ACE_Object_Manager::ACE_FILECACHE_LOCK);
+ ACE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX, ace_mon, lock, 0);
+
+ // @@ James, please check each of the ACE_NEW_RETURN calls to
+ // make sure that it is safe to return if allocation fails.
+ if (ACE_Filecache::cvf_ == 0)
+ ACE_NEW_RETURN (ACE_Filecache::cvf_,
+ ACE_Filecache,
+ 0);
+ }
+
+ return ACE_Filecache::cvf_;
+}
+
+ACE_Filecache::ACE_Filecache (void)
+ : size_ (ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE),
+ hash_ (size_)
+{
+}
+
+ACE_Filecache::~ACE_Filecache (void)
+{
+}
+
+ACE_Filecache_Object *
+ACE_Filecache::insert_i (const ACE_TCHAR *filename,
+ ACE_SYNCH_RW_MUTEX &filelock,
+ int mapit)
+{
+ ACE_Filecache_Object *handle = 0;
+
+ if (this->hash_.find (filename, handle) == -1)
+ {
+ ACE_NEW_RETURN (handle,
+ ACE_Filecache_Object (filename, filelock, 0, mapit),
+ 0);
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%t) CVF: creating %s\n"), filename));
+
+ if (this->hash_.bind (filename, handle) == -1)
+ {
+ delete handle;
+ handle = 0;
+ }
+ }
+ else
+ handle = 0;
+
+ return handle;
+}
+
+ACE_Filecache_Object *
+ACE_Filecache::remove_i (const ACE_TCHAR *filename)
+{
+ ACE_Filecache_Object *handle = 0;
+
+ // Disassociate file from the cache.
+ if (this->hash_.unbind (filename, handle) == 0)
+ {
+ handle->stale_ = 1;
+
+ // Try a lock. If it succeeds, we can delete it now.
+ // Otherwise, it will clean itself up later.
+ if (handle->lock_.tryacquire_write () == 0)
+ {
+ delete handle;
+ handle = 0;
+ }
+ }
+ else
+ handle = 0;
+
+ return handle;
+}
+
+ACE_Filecache_Object *
+ACE_Filecache::update_i (const ACE_TCHAR *filename,
+ ACE_SYNCH_RW_MUTEX &filelock,
+ int mapit)
+{
+ ACE_Filecache_Object *handle = 0;
+
+ handle = this->remove_i (filename);
+ handle = this->insert_i (filename, filelock, mapit);
+
+ return handle;
+}
+
+int
+ACE_Filecache::find (const ACE_TCHAR *filename)
+{
+ return this->hash_.find (filename);
+}
+
+
+ACE_Filecache_Object *
+ACE_Filecache::remove (const ACE_TCHAR *filename)
+{
+ ACE_Filecache_Object *handle = 0;
+
+ ACE_OFF_T loc = ACE::hash_pjw (filename) % this->size_;
+ ACE_SYNCH_RW_MUTEX &hashlock = this->hash_lock_[loc];
+ // ACE_SYNCH_RW_MUTEX &filelock = this->file_lock_[loc];
+
+ if (this->hash_.find (filename, handle) != -1)
+ {
+ ACE_WRITE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX,
+ ace_mon,
+ hashlock,
+ 0);
+
+ return this->remove_i (filename);
+ }
+
+ return 0;
+}
+
+
+ACE_Filecache_Object *
+ACE_Filecache::fetch (const ACE_TCHAR *filename, int mapit)
+{
+ ACE_Filecache_Object *handle = 0;
+
+ ACE_OFF_T loc = ACE::hash_pjw (filename) % this->size_;
+ ACE_SYNCH_RW_MUTEX &hashlock = this->hash_lock_[loc];
+ ACE_SYNCH_RW_MUTEX &filelock = this->file_lock_[loc];
+
+ filelock.acquire_read ();
+
+ if (this->hash_.find (filename, handle) == -1)
+ {
+ ACE_WRITE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX,
+ ace_mon,
+ hashlock,
+ 0);
+
+ // Second check in the method call
+ handle = this->insert_i (filename, filelock, mapit);
+
+ if (handle == 0)
+ filelock.release ();
+ }
+ else
+ {
+ if (handle->update ())
+ {
+ {
+ // Double check locking pattern
+ ACE_WRITE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX,
+ ace_mon,
+ hashlock,
+ 0);
+
+ // Second check in the method call
+ handle = this->update_i (filename, filelock, mapit);
+
+ if (handle == 0)
+ filelock.release ();
+ }
+ }
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%t) CVF: found %s\n"), filename));
+ }
+
+ return handle;
+}
+
+ACE_Filecache_Object *
+ACE_Filecache::create (const ACE_TCHAR *filename, int size)
+{
+ ACE_Filecache_Object *handle = 0;
+
+ ACE_OFF_T loc = ACE::hash_pjw (filename) % this->size_;
+ ACE_SYNCH_RW_MUTEX &filelock = this->file_lock_[loc];
+
+ ACE_NEW_RETURN (handle,
+ ACE_Filecache_Object (filename, size, filelock),
+ 0);
+ handle->acquire ();
+
+ return handle;
+}
+
+ACE_Filecache_Object *
+ACE_Filecache::finish (ACE_Filecache_Object *&file)
+{
+ if (file == 0)
+ return file;
+
+ ACE_OFF_T loc = ACE::hash_pjw (file->filename_) % this->size_;
+ ACE_SYNCH_RW_MUTEX &hashlock = this->hash_lock_[loc];
+
+ if (file != 0)
+ switch (file->action_)
+ {
+ case ACE_Filecache_Object::ACE_WRITING:
+ {
+ ACE_WRITE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX,
+ ace_mon,
+ hashlock,
+ 0);
+
+ file->release ();
+
+ this->remove_i (file->filename_);
+#if 0
+ int result = this->hash_.bind (file->filename (), file);
+
+ if (result == 0)
+ file->acquire ();
+#else
+ // Last one using a stale file is resposible for deleting it.
+ if (file->stale_)
+ {
+ // Try a lock. If it succeds, we can delete it now.
+ // Otherwise, it will clean itself up later.
+ if (file->lock_.tryacquire_write () == 0)
+ {
+ delete file;
+ file = 0;
+ }
+ }
+#endif
+ }
+
+ break;
+ default:
+ file->release ();
+
+ // Last one using a stale file is resposible for deleting it.
+ if (file->stale_)
+ {
+ // Try a lock. If it succeds, we can delete it now.
+ // Otherwise, it will clean itself up later.
+ if (file->lock_.tryacquire_write () == 0)
+ {
+ delete file;
+ file = 0;
+ }
+ }
+
+ break;
+ }
+
+ return file;
+}
+
+void
+ACE_Filecache_Object::init (void)
+{
+ this->filename_[0] = '\0';
+ this->handle_ = ACE_INVALID_HANDLE;
+ this->error_ = ACE_SUCCESS;
+ this->tempname_ = 0;
+ this->size_ = 0;
+
+ ACE_OS::memset (&(this->stat_), 0, sizeof (this->stat_));
+}
+
+ACE_Filecache_Object::ACE_Filecache_Object (void)
+ : tempname_ (0),
+ mmap_ (),
+ handle_ (0),
+ // stat_ (),
+ size_ (0),
+ action_ (0),
+ error_ (0),
+ stale_ (0),
+ // sa_ (),
+ junklock_ (),
+ lock_ (junklock_)
+{
+ this->init ();
+}
+
+ACE_Filecache_Object::ACE_Filecache_Object (const ACE_TCHAR *filename,
+ ACE_SYNCH_RW_MUTEX &lock,
+ LPSECURITY_ATTRIBUTES sa,
+ int mapit)
+ : tempname_ (0),
+ mmap_ (),
+ handle_ (0),
+ // stat_ (),
+ size_ (0),
+ action_ (0),
+ error_ (0),
+ stale_ (0),
+ sa_ (sa),
+ junklock_ (),
+ lock_ (lock)
+{
+ this->init ();
+
+ // ASSERT strlen(filename) < sizeof (this->filename_)
+ ACE_OS::strcpy (this->filename_, filename);
+ this->action_ = ACE_Filecache_Object::ACE_READING;
+ // place ourselves into the READING state
+
+ // Can we access the file?
+ if (ACE_OS::access (this->filename_, R_OK) == -1)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_ACCESS_FAILED);
+ return;
+ }
+
+ // Can we stat the file?
+ if (ACE_OS::stat (this->filename_, &this->stat_) == -1)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_STAT_FAILED);
+ return;
+ }
+
+ this->size_ = ACE_Utils::truncate_cast<ACE_OFF_T> (this->stat_.st_size);
+ this->tempname_ = this->filename_;
+
+ // Can we open the file?
+ this->handle_ = ACE_OS::open (this->tempname_,
+ READ_FLAGS, R_MASK, this->sa_);
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_OPEN_FAILED,
+ ACE_TEXT ("ACE_Filecache_Object::ctor: open"));
+ return;
+ }
+
+ if (mapit)
+ {
+ // Can we map the file?
+ if (this->mmap_.map (this->handle_, static_cast<size_t> (-1),
+ PROT_READ, ACE_MAP_PRIVATE, 0, 0, this->sa_) != 0)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_MEMMAP_FAILED,
+ ACE_TEXT ("ACE_Filecache_Object::ctor: map"));
+ ACE_OS::close (this->handle_);
+ this->handle_ = ACE_INVALID_HANDLE;
+ return;
+ }
+ }
+
+ // Ok, finished!
+ this->action_ = ACE_Filecache_Object::ACE_READING;
+}
+
+ACE_Filecache_Object::ACE_Filecache_Object (const ACE_TCHAR *filename,
+ ACE_OFF_T size,
+ ACE_SYNCH_RW_MUTEX &lock,
+ LPSECURITY_ATTRIBUTES sa)
+ : stale_ (0),
+ sa_ (sa),
+ lock_ (lock)
+{
+ this->init ();
+
+ this->size_ = size;
+ ACE_OS::strcpy (this->filename_, filename);
+ this->action_ = ACE_Filecache_Object::ACE_WRITING;
+
+ // Can we access the file?
+ if (ACE_OS::access (this->filename_, R_OK|W_OK) == -1
+ // Does it exist?
+ && ACE_OS::access (this->filename_, F_OK) != -1)
+ {
+ // File exists, but we cannot access it.
+ this->error_i (ACE_Filecache_Object::ACE_ACCESS_FAILED);
+ return;
+ }
+
+ this->tempname_ = this->filename_;
+
+ // Can we open the file?
+ this->handle_ = ACE_OS::open (this->tempname_, WRITE_FLAGS, W_MASK, this->sa_);
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_OPEN_FAILED,
+ ACE_TEXT ("ACE_Filecache_Object::acquire: open"));
+ return;
+ }
+
+ // Can we write?
+ if (ACE_OS::pwrite (this->handle_, "", 1, this->size_ - 1) != 1)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_WRITE_FAILED,
+ ACE_TEXT ("ACE_Filecache_Object::acquire: write"));
+ ACE_OS::close (this->handle_);
+ return;
+ }
+
+ // Can we map?
+ if (this->mmap_.map (this->handle_, this->size_, PROT_RDWR, MAP_SHARED,
+ 0, 0, this->sa_) != 0)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_MEMMAP_FAILED,
+ ACE_TEXT ("ACE_Filecache_Object::acquire: map"));
+ ACE_OS::close (this->handle_);
+ }
+
+ // Ok, done!
+}
+
+ACE_Filecache_Object::~ACE_Filecache_Object (void)
+{
+ if (this->error_ == ACE_SUCCESS)
+ {
+ this->mmap_.unmap ();
+ ACE_OS::close (this->handle_);
+ this->handle_ = ACE_INVALID_HANDLE;
+ }
+
+ this->lock_.release ();
+}
+
+int
+ACE_Filecache_Object::acquire (void)
+{
+ return this->lock_.tryacquire_read ();
+}
+
+int
+ACE_Filecache_Object::release (void)
+{
+ if (this->action_ == ACE_WRITING)
+ {
+ // We are safe since only one thread has a writable Filecache_Object
+
+#if 0
+ ACE_HANDLE original = ACE_OS::open (this->filename_, WRITE_FLAGS, W_MASK,
+ this->sa_);
+ if (original == ACE_INVALID_HANDLE)
+ this->error_ = ACE_Filecache_Object::ACE_OPEN_FAILED;
+ else if (ACE_OS::write (original, this->mmap_.addr (),
+ this->size_) == -1)
+ {
+ this->error_ = ACE_Filecache_Object::ACE_WRITE_FAILED;
+ ACE_OS::close (original);
+ ACE_OS::unlink (this->filename_);
+ }
+ else if (ACE_OS::stat (this->filename_, &this->stat_) == -1)
+ this->error_ = ACE_Filecache_Object::ACE_STAT_FAILED;
+#endif
+
+ this->mmap_.unmap ();
+ ACE_OS::close (this->handle_);
+ this->handle_ = ACE_INVALID_HANDLE;
+
+#if 0
+ // Leave the file in an acquirable state.
+ this->handle_ = ACE_OS::open (this->tempname_, READ_FLAGS, R_MASK);
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_OPEN_FAILED,
+ "ACE_Filecache_Object::acquire: open");
+ }
+ else if (this->mmap_.map (this->handle_, -1,
+ PROT_READ,
+ ACE_MAP_PRIVATE,
+ 0,
+ 0,
+ this->sa_) != 0)
+ {
+ this->error_i (ACE_Filecache_Object::ACE_MEMMAP_FAILED,
+ "ACE_Filecache_Object::acquire: map");
+ ACE_OS::close (this->handle_);
+ this->handle_ = ACE_INVALID_HANDLE;
+ }
+
+ this->action_ = ACE_Filecache_Object::ACE_READING;
+#endif
+ }
+
+ return this->lock_.release ();
+}
+
+int
+ACE_Filecache_Object::error (void) const
+{
+ // The existence of the object means a read lock is being held.
+ return this->error_;
+}
+
+int
+ACE_Filecache_Object::error_i (int error_value, const ACE_TCHAR *s)
+{
+ s = s;
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p.\n"), s));
+ this->error_ = error_value;
+ return error_value;
+}
+
+const ACE_TCHAR *
+ACE_Filecache_Object::filename (void) const
+{
+ // The existence of the object means a read lock is being held.
+ return this->filename_;
+}
+
+ACE_OFF_T
+ACE_Filecache_Object::size (void) const
+{
+ // The existence of the object means a read lock is being held.
+ return this->size_;
+}
+
+ACE_HANDLE
+ACE_Filecache_Object::handle (void) const
+{
+ // The existence of the object means a read lock is being held.
+ return this->handle_;
+}
+
+void *
+ACE_Filecache_Object::address (void) const
+{
+ // The existence of the object means a read lock is being held.
+ return this->mmap_.addr ();
+}
+
+int
+ACE_Filecache_Object::update (void) const
+{
+ // The existence of the object means a read lock is being held.
+ int result;
+ ACE_stat statbuf;
+
+ if (ACE_OS::stat (this->filename_, &statbuf) == -1)
+ result = 1;
+ else
+ // non-portable code may follow
+#if defined (ACE_HAS_WINCE)
+ // Yup, non-portable... there's probably a way to safely implement
+ // difftime() on WinCE, but for now, this will have to do. It flags
+ // every file as having changed since cached.
+ result = 1;
+#else
+ result = ACE_OS::difftime (this->stat_.st_mtime, statbuf.st_mtime) < 0;
+#endif /* ACE_HAS_WINCE */
+
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Filecache.h b/ACE/ace/Filecache.h
new file mode 100644
index 00000000000..df1835b9372
--- /dev/null
+++ b/ACE/ace/Filecache.h
@@ -0,0 +1,353 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Filecache.h
+ *
+ * $Id$
+ *
+ * @author James Hu
+ */
+//=============================================================================
+
+
+#ifndef ACE_FILECACHE_H
+#define ACE_FILECACHE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Mem_Map.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Synch_Traits.h"
+#include "ace/RW_Thread_Mutex.h"
+#include "ace/OS_NS_sys_stat.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+enum ACE_Filecache_Flag
+{
+ ACE_NOMAP = 0,
+ ACE_MAPIT = 1
+};
+
+class ACE_Filecache_Object;
+
+/**
+ * @class ACE_Filecache_Handle
+ *
+ * @brief Abstraction over a real file. This is meant to be the entry
+ * point into the Cached Virtual Filesystem.
+ *
+ * This is a cached filesystem implementation based loosely on the
+ * implementation of JAWS_File. The interfaces will be nearly the
+ * same. The under-the-hood implementation should hopefully be a
+ * much faster thing.
+ * These will be given their own implementations later. For now, we
+ * borrow the implementation provided by JAWS.
+ * On creation, the cache is checked, and reference count is
+ * incremented. On destruction, reference count is decremented. If
+ * the reference count is 0, the file is removed from the cache.
+ * E.g. 1,
+ * {
+ * ACE_Filecache_Handle foo("foo.html");
+ * this->peer ().send (foo.address (), foo.size ());
+ * }
+ * E.g. 2,
+ * {
+ * ACE_Filecache_Handle foo("foo.html");
+ * io->transmitfile (foo.handle (), this->peer ().handle ());
+ * }
+ * E.g. 3,
+ * {
+ * ACE_Filecache_Handle foo("foo.html", content_length);
+ * this->peer ().recv (foo.address (), content_length);
+ * }
+ * TODO:
+ */
+class ACE_Export ACE_Filecache_Handle
+{
+ // (1) Get rid of the useless copying of files when reading.
+ // Although it does make sure the file you send isn't being changed,
+ // it doesn't make sure the file is in a sensible state before
+ // sending it.
+ //
+ // Alternative: if the file get's trashed while it is being shipped,
+ // let the client request the file again. The cache should have an
+ // updated copy by that point.
+ //
+ // (2) Use hashing for locating files. This means I need a hastable
+ // implementation with buckets.
+ //
+ // (3) Only lock when absolutely necessary. JAWS_Virtual_Filesystem was
+ // rather conservative, but for some reason it still ran into problems.
+ // Since this design should be simpler, problems should be easier to spot.
+ //
+public:
+
+ /// Query cache for file, and acquire it. Assumes the file is being
+ /// opened for reading.
+ ACE_Filecache_Handle (const ACE_TCHAR *filename,
+ ACE_Filecache_Flag mapit = ACE_MAPIT);
+
+ /**
+ * Create new entry, and acquire it. Presence of SIZE assumes the
+ * file is being opened for writing. If SIZE is zero, assumes the
+ * file is to be removed from the cache.
+ */
+ ACE_Filecache_Handle (const ACE_TCHAR *filename,
+ int size,
+ ACE_Filecache_Flag mapit = ACE_MAPIT);
+
+ /// Closes any open handles, release acquired file.
+ ~ACE_Filecache_Handle (void);
+
+ /// Base address of memory mapped file.
+ void *address (void) const;
+
+ /// A handle (e.g., UNIX file descriptor, or NT file handle).
+ ACE_HANDLE handle (void) const;
+
+ /// Any associated error in handle creation and acquisition.
+ int error (void) const;
+
+ /// The size of the file.
+ ACE_OFF_T size (void) const;
+
+protected:
+ /// Default do nothing constructor. Prevent it from being called.
+ ACE_Filecache_Handle (void);
+
+ /// Common initializations for constructors.
+ void init (void);
+
+public:
+ /// These come from ACE_Filecache_Object, which is an internal class.
+ enum
+ {
+ ACE_SUCCESS = 0,
+ ACE_ACCESS_FAILED,
+ ACE_OPEN_FAILED,
+ ACE_COPY_FAILED,
+ ACE_STAT_FAILED,
+ ACE_MEMMAP_FAILED,
+ ACE_WRITE_FAILED
+ };
+
+private:
+ /// A reference to the low level instance.
+ ACE_Filecache_Object *file_;
+
+ /// A <dup>'d version of the one from <file_>.
+ ACE_HANDLE handle_;
+
+ int mapit_;
+};
+
+typedef ACE_Hash_Map_Manager_Ex<const ACE_TCHAR *, ACE_Filecache_Object *, ACE_Hash<const ACE_TCHAR *>, ACE_Equal_To<const ACE_TCHAR *>, ACE_Null_Mutex>
+ ACE_Filecache_Hash;
+
+typedef ACE_Hash_Map_Entry<const ACE_TCHAR *, ACE_Filecache_Object *> ACE_Filecache_Hash_Entry;
+
+/**
+ * @class ACE_Filecache
+ *
+ * @brief A hash table holding the information about entry point into
+ * the Cached Virtual Filesystem. On insertion, the reference
+ * count is incremented. On destruction, reference count is
+ * decremented.
+ */
+class ACE_Export ACE_Filecache
+{
+public:
+ /// Singleton pattern.
+ static ACE_Filecache *instance (void);
+
+ ~ACE_Filecache (void);
+
+ /// Returns 0 if the file associated with ``filename'' is in the cache,
+ /// or -1 if not.
+ int find (const ACE_TCHAR *filename);
+
+ /// Return the file associated with ``filename'' if it is in the cache,
+ /// or create if not.
+ ACE_Filecache_Object *fetch (const ACE_TCHAR *filename, int mapit = 1);
+
+ /// Remove the file associated with ``filename'' from the cache.
+ ACE_Filecache_Object *remove (const ACE_TCHAR *filename);
+
+ /// Create a new Filecache_Object, returns it.
+ ACE_Filecache_Object *create (const ACE_TCHAR *filename, int size);
+
+ /// Release an acquired Filecache_Object, returns it again or NULL if it
+ /// was deleted.
+ ACE_Filecache_Object *finish (ACE_Filecache_Object *&new_file);
+
+protected:
+ ACE_Filecache_Object *insert_i (const ACE_TCHAR *filename,
+ ACE_SYNCH_RW_MUTEX &filelock,
+ int mapit);
+ ACE_Filecache_Object *remove_i (const ACE_TCHAR *filename);
+ ACE_Filecache_Object *update_i (const ACE_TCHAR *filename,
+ ACE_SYNCH_RW_MUTEX &filelock,
+ int mapit);
+
+public:
+
+ enum
+ {
+ /// For this stupid implementation, use an array. Someday, use a
+ /// balanced search tree, or real hash table.
+ ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE = 512,
+
+ /// This determines the highwater mark in megabytes for the cache.
+ /// This will be ignored for now.
+ ACE_DEFAULT_VIRTUAL_FILESYSTEM_CACHE_SIZE = 20
+ };
+
+protected:
+ /// Prevent it from being called.
+ ACE_Filecache (void);
+
+private:
+ ACE_OFF_T size_;
+
+ /// The hash table
+ ACE_Filecache_Hash hash_;
+
+ /// The reference to the instance
+ static ACE_Filecache *cvf_;
+
+ // = Synchronization variables.
+ ACE_SYNCH_RW_MUTEX hash_lock_[ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE];
+ ACE_SYNCH_RW_MUTEX file_lock_[ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE];
+};
+
+/**
+ * @class ACE_Filecache_Object
+ *
+ * @brief Abstraction over a real file. This is what the Virtual
+ * Filesystem contains. This class is not intended for general
+ * consumption. Please consult a physician before attempting to
+ * use this class.
+ */
+class ACE_Export ACE_Filecache_Object
+{
+public:
+ friend class ACE_Filecache;
+
+ /// Creates a file for reading.
+ ACE_Filecache_Object (const ACE_TCHAR *filename,
+ ACE_SYNCH_RW_MUTEX &lock,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ int mapit = 1);
+
+ /// Creates a file for writing.
+ ACE_Filecache_Object (const ACE_TCHAR *filename,
+ ACE_OFF_T size,
+ ACE_SYNCH_RW_MUTEX &lock,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Only if reference count is zero should this be called.
+ ~ACE_Filecache_Object (void);
+
+ /// Increment the reference_count_.
+ int acquire (void);
+
+ /// Decrement the reference_count_.
+ int release (void);
+
+ // = error_ accessors
+ int error (void) const;
+ int error (int error_value,
+ const ACE_TCHAR *s = ACE_TEXT ("ACE_Filecache_Object"));
+
+ /// filename_ accessor
+ const ACE_TCHAR *filename (void) const;
+
+ /// handle_ accessor.
+ ACE_HANDLE handle (void) const;
+
+ /// Base memory address for memory mapped file.
+ void *address (void) const;
+
+ /// size_ accessor.
+ ACE_OFF_T size (void) const;
+
+ /// True if file on disk is newer than cached file.
+ int update (void) const;
+
+protected:
+ /// Prevent from being called.
+ ACE_Filecache_Object (void);
+
+ /// Common initialization code,
+ void init (void);
+
+private:
+ /// Internal error logging method, no locking.
+ int error_i (int error_value,
+ const ACE_TCHAR *s = ACE_TEXT ("ACE_Filecache_Object"));
+
+public:
+
+ enum Creation_States
+ {
+ ACE_READING = 1,
+ ACE_WRITING = 2
+ };
+
+ enum Error_Conditions
+ {
+ ACE_SUCCESS = 0,
+ ACE_ACCESS_FAILED,
+ ACE_OPEN_FAILED,
+ ACE_COPY_FAILED,
+ ACE_STAT_FAILED,
+ ACE_MEMMAP_FAILED,
+ ACE_WRITE_FAILED
+ };
+
+private:
+ /// The temporary file name and the real file name. The real file is
+ /// copied into the temporary file for safety reasons.
+ ACE_TCHAR *tempname_;
+ ACE_TCHAR filename_[MAXPATHLEN + 1];
+
+ /// Holds the memory mapped version of the temporary file.
+ ACE_Mem_Map mmap_;
+
+ /// The descriptor to the temporary file.
+ ACE_HANDLE handle_;
+
+ /// Used to compare against the real file to test if an update is needed.
+ ACE_stat stat_;
+ ACE_OFF_T size_;
+
+ /// Status indicators.
+ int action_;
+ int error_;
+
+ /// If set to 1, means the object is flagged for removal.
+ int stale_;
+
+ /// Security attribute object.
+ LPSECURITY_ATTRIBUTES sa_;
+
+ /// The default initializer
+ ACE_SYNCH_RW_MUTEX junklock_;
+
+ /// Provides a bookkeeping mechanism for users of this object.
+ ACE_SYNCH_RW_MUTEX &lock_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_FILECACHE_H */
diff --git a/ACE/ace/FlReactor/ACE_FlReactor.pc.in b/ACE/ace/FlReactor/ACE_FlReactor.pc.in
new file mode 100644
index 00000000000..c284481585d
--- /dev/null
+++ b/ACE/ace/FlReactor/ACE_FlReactor.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE_FlReactor
+Description: ACE FlReactor Library
+Requires: ACE
+Version: @VERSION@
+Libs: -L${libdir} -lACE_FlReactor
+Cflags: -I${includedir}
diff --git a/ACE/ace/FlReactor/ACE_FlReactor_export.h b/ACE/ace/FlReactor/ACE_FlReactor_export.h
new file mode 100644
index 00000000000..f46b66cb3f7
--- /dev/null
+++ b/ACE/ace/FlReactor/ACE_FlReactor_export.h
@@ -0,0 +1,58 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl -s ACE_FlReactor
+// ------------------------------
+#ifndef ACE_FLREACTOR_EXPORT_H
+#define ACE_FLREACTOR_EXPORT_H
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_FLREACTOR_HAS_DLL)
+# define ACE_FLREACTOR_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ACE_FLREACTOR_HAS_DLL */
+
+#if !defined (ACE_FLREACTOR_HAS_DLL)
+# define ACE_FLREACTOR_HAS_DLL 1
+#endif /* ! ACE_FLREACTOR_HAS_DLL */
+
+#if defined (ACE_FLREACTOR_HAS_DLL) && (ACE_FLREACTOR_HAS_DLL == 1)
+# if defined (ACE_FLREACTOR_BUILD_DLL)
+# define ACE_FlReactor_Export ACE_Proper_Export_Flag
+# define ACE_FLREACTOR_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define ACE_FLREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* ACE_FLREACTOR_BUILD_DLL */
+# define ACE_FlReactor_Export ACE_Proper_Import_Flag
+# define ACE_FLREACTOR_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define ACE_FLREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ACE_FLREACTOR_BUILD_DLL */
+#else /* ACE_FLREACTOR_HAS_DLL == 1 */
+# define ACE_FlReactor_Export
+# define ACE_FLREACTOR_SINGLETON_DECLARATION(T)
+# define ACE_FLREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* ACE_FLREACTOR_HAS_DLL == 1 */
+
+// Set ACE_FLREACTOR_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (ACE_FLREACTOR_NTRACE)
+# if (ACE_NTRACE == 1)
+# define ACE_FLREACTOR_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define ACE_FLREACTOR_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !ACE_FLREACTOR_NTRACE */
+
+#if (ACE_FLREACTOR_NTRACE == 1)
+# define ACE_FLREACTOR_TRACE(X)
+#else /* (ACE_FLREACTOR_NTRACE == 1) */
+# if !defined (ACE_HAS_TRACE)
+# define ACE_HAS_TRACE
+# endif /* ACE_HAS_TRACE */
+# define ACE_FLREACTOR_TRACE(X) ACE_TRACE_IMPL(X)
+# include "ace/Trace.h"
+#endif /* (ACE_FLREACTOR_NTRACE == 1) */
+
+#endif /* ACE_FLREACTOR_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/FlReactor/FlReactor.cpp b/ACE/ace/FlReactor/FlReactor.cpp
new file mode 100644
index 00000000000..611b9a14a19
--- /dev/null
+++ b/ACE/ace/FlReactor/FlReactor.cpp
@@ -0,0 +1,330 @@
+// $Id$
+
+#include "ace/FlReactor/FlReactor.h"
+
+ACE_RCSID(ace, FlReactor, "$Id$")
+
+#include /**/ <FL/Fl.h>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 = static_cast<ACE_FlReactor *> (reactor);
+ ACE_HANDLE handle = (ACE_HANDLE)fd; //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 = 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, // 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); // 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 *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ 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 (event_handler,
+ arg,
+ delay,
+ 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;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FlReactor/FlReactor.h b/ACE/ace/FlReactor/FlReactor.h
new file mode 100644
index 00000000000..c2e3c64df06
--- /dev/null
+++ b/ACE/ace/FlReactor/FlReactor.h
@@ -0,0 +1,110 @@
+/* -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/FlReactor/ACE_FlReactor_export.h"
+#include "ace/Select_Reactor.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_FlReactor_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 *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ 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 @a 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 @a 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 &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FLREACTOR_H */
diff --git a/ACE/ace/Flag_Manip.cpp b/ACE/ace/Flag_Manip.cpp
new file mode 100644
index 00000000000..ee074a2d10d
--- /dev/null
+++ b/ACE/ace/Flag_Manip.cpp
@@ -0,0 +1,95 @@
+// $Id$
+
+#include "ace/Flag_Manip.h"
+
+#if defined (ACE_LACKS_FCNTL)
+# include "ace/OS_NS_stropts.h"
+# include "ace/OS_NS_errno.h"
+#endif /* ACE_LACKS_FCNTL */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Flag_Manip.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (CYGWIN32)
+# include "ace/os_include/os_termios.h"
+#endif /* CYGWIN32 */
+
+ACE_RCSID (ace,
+ Flag_Manip,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Flags are file status flags to turn on.
+
+int
+ACE::set_flags (ACE_HANDLE handle, int flags)
+{
+ ACE_TRACE ("ACE::set_flags");
+#if defined (ACE_LACKS_FCNTL)
+ switch (flags)
+ {
+ case ACE_NONBLOCK:
+ // nonblocking argument (1)
+ // blocking: (0)
+ {
+ int nonblock = 1;
+ return ACE_OS::ioctl (handle, FIONBIO, &nonblock);
+ }
+ default:
+ ACE_NOTSUP_RETURN (-1);
+ }
+#else
+ int val = ACE_OS::fcntl (handle, F_GETFL, 0);
+
+ if (val == -1)
+ return -1;
+
+ // Turn on flags.
+ ACE_SET_BITS (val, flags);
+
+ if (ACE_OS::fcntl (handle, F_SETFL, val) == -1)
+ return -1;
+ else
+ return 0;
+#endif /* ACE_LACKS_FCNTL */
+}
+
+// Flags are the file status flags to turn off.
+
+int
+ACE::clr_flags (ACE_HANDLE handle, int flags)
+{
+ ACE_TRACE ("ACE::clr_flags");
+
+#if defined (ACE_LACKS_FCNTL)
+ switch (flags)
+ {
+ case ACE_NONBLOCK:
+ // nonblocking argument (1)
+ // blocking: (0)
+ {
+ int nonblock = 0;
+ return ACE_OS::ioctl (handle, FIONBIO, &nonblock);
+ }
+ default:
+ ACE_NOTSUP_RETURN (-1);
+ }
+#else
+ int val = ACE_OS::fcntl (handle, F_GETFL, 0);
+
+ if (val == -1)
+ return -1;
+
+ // Turn flags off.
+ ACE_CLR_BITS (val, flags);
+
+ if (ACE_OS::fcntl (handle, F_SETFL, val) == -1)
+ return -1;
+ else
+ return 0;
+#endif /* ACE_LACKS_FCNTL */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Flag_Manip.h b/ACE/ace/Flag_Manip.h
new file mode 100644
index 00000000000..02168ce6fee
--- /dev/null
+++ b/ACE/ace/Flag_Manip.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Flag_Manip.h
+ *
+ * $Id$
+ *
+ * This class includes the functions used for the Flag Manipulation.
+ *
+ * @author Priyanka Gontla <pgontla@doc.ece.uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_FLAG_MANIP_H
+#define ACE_FLAG_MANIP_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+#include "ace/os_include/os_fcntl.h" /* For values passed to these methods */
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE
+{
+ // = Set/get/clear various flags related to I/O HANDLE.
+ /// Set flags associated with @a handle.
+ extern ACE_Export int set_flags (ACE_HANDLE handle,
+ int flags);
+
+ /// Clear flags associated with @a handle.
+ extern ACE_Export int clr_flags (ACE_HANDLE handle,
+ int flags);
+
+ /// Return the current setting of flags associated with @a handle.
+ ACE_NAMESPACE_INLINE_FUNCTION int get_flags (ACE_HANDLE handle);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Flag_Manip.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FLAG_MANIP_H */
diff --git a/ACE/ace/Flag_Manip.inl b/ACE/ace/Flag_Manip.inl
new file mode 100644
index 00000000000..da24f2a1282
--- /dev/null
+++ b/ACE/ace/Flag_Manip.inl
@@ -0,0 +1,26 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_fcntl.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Return flags currently associated with handle.
+ACE_INLINE int
+ACE::get_flags (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE::get_flags");
+
+#if defined (ACE_LACKS_FCNTL)
+ // ACE_OS::fcntl is not supported. It
+ // would be better to store ACE's notion of the flags
+ // associated with the handle, but this works for now.
+ ACE_UNUSED_ARG (handle);
+ return 0;
+#else
+ return ACE_OS::fcntl (handle, F_GETFL, 0);
+#endif /* ACE_LACKS_FCNTL */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/FoxReactor/ACE_FoxReactor.pc.in b/ACE/ace/FoxReactor/ACE_FoxReactor.pc.in
new file mode 100644
index 00000000000..83d9e5fb965
--- /dev/null
+++ b/ACE/ace/FoxReactor/ACE_FoxReactor.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE_FoxReactor
+Description: ACE FoxReactor Library
+Requires: ACE
+Version: @VERSION@
+Libs: -L${libdir} -lACE_FoxReactor
+Cflags: -I${includedir}
diff --git a/ACE/ace/FoxReactor/ACE_FoxReactor_export.h b/ACE/ace/FoxReactor/ACE_FoxReactor_export.h
new file mode 100644
index 00000000000..bac41b4da97
--- /dev/null
+++ b/ACE/ace/FoxReactor/ACE_FoxReactor_export.h
@@ -0,0 +1,58 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl -s ACE_FoxReactor
+// ------------------------------
+#ifndef ACE_FOXREACTOR_EXPORT_H
+#define ACE_FOXREACTOR_EXPORT_H
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_FOXREACTOR_HAS_DLL)
+# define ACE_FOXREACTOR_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ACE_FOXREACTOR_HAS_DLL */
+
+#if !defined (ACE_FOXREACTOR_HAS_DLL)
+# define ACE_FOXREACTOR_HAS_DLL 1
+#endif /* ! ACE_FOXREACTOR_HAS_DLL */
+
+#if defined (ACE_FOXREACTOR_HAS_DLL) && (ACE_FOXREACTOR_HAS_DLL == 1)
+# if defined (ACE_FOXREACTOR_BUILD_DLL)
+# define ACE_FoxReactor_Export ACE_Proper_Export_Flag
+# define ACE_FOXREACTOR_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define ACE_FOXREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* ACE_FOXREACTOR_BUILD_DLL */
+# define ACE_FoxReactor_Export ACE_Proper_Import_Flag
+# define ACE_FOXREACTOR_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define ACE_FOXREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ACE_FOXREACTOR_BUILD_DLL */
+#else /* ACE_FOXREACTOR_HAS_DLL == 1 */
+# define ACE_FoxReactor_Export
+# define ACE_FOXREACTOR_SINGLETON_DECLARATION(T)
+# define ACE_FOXREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* ACE_FOXREACTOR_HAS_DLL == 1 */
+
+// Set ACE_FOXREACTOR_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (ACE_FOXREACTOR_NTRACE)
+# if (ACE_NTRACE == 1)
+# define ACE_FOXREACTOR_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define ACE_FOXREACTOR_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !ACE_FOXREACTOR_NTRACE */
+
+#if (ACE_FOXREACTOR_NTRACE == 1)
+# define ACE_FOXREACTOR_TRACE(X)
+#else /* (ACE_FOXREACTOR_NTRACE == 1) */
+# if !defined (ACE_HAS_TRACE)
+# define ACE_HAS_TRACE
+# endif /* ACE_HAS_TRACE */
+# define ACE_FOXREACTOR_TRACE(X) ACE_TRACE_IMPL(X)
+# include "ace/Trace.h"
+#endif /* (ACE_FOXREACTOR_NTRACE == 1) */
+
+#endif /* ACE_FOXREACTOR_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/FoxReactor/FoxReactor.cpp b/ACE/ace/FoxReactor/FoxReactor.cpp
new file mode 100644
index 00000000000..4eaa58bae0e
--- /dev/null
+++ b/ACE/ace/FoxReactor/FoxReactor.cpp
@@ -0,0 +1,337 @@
+// $Id$
+
+#include "ace/FoxReactor/FoxReactor.h"
+
+ACE_RCSID(ace, FoxReactor, "$Id$")
+
+#if defined (ACE_HAS_FOX)
+
+#include "ace/Synch_T.h"
+
+FXDEFMAP(ACE_FoxReactor) ACE_FoxReactorMap[]={
+ FXMAPFUNCS(SEL_IO_READ,0,MAXKEY,ACE_FoxReactor::onFileEvents),
+ FXMAPFUNCS(SEL_IO_WRITE,0,MAXKEY,ACE_FoxReactor::onFileEvents),
+ FXMAPFUNCS(SEL_IO_EXCEPT,0,MAXKEY,ACE_FoxReactor::onFileEvents),
+ FXMAPFUNCS(SEL_TIMEOUT,0,MAXKEY,ACE_FoxReactor::onTimerEvents),
+};
+
+FXIMPLEMENT(ACE_FoxReactor,FXObject,ACE_FoxReactorMap,ARRAYNUMBER(ACE_FoxReactorMap))
+
+ACE_ALLOC_HOOK_DEFINE (ACE_FoxReactor)
+
+// Must be called with lock held
+ACE_FoxReactor::ACE_FoxReactor (FXApp* a,
+ size_t size,
+ int restart,
+ ACE_Sig_Handler *h)
+ : ACE_Select_Reactor (size, restart, h), fxapp(a)
+{
+ // When the ACE_Select_Reactor is constructed it creates the notify
+ // pipe and registers it with the register_handler_i() method. The
+ // FoxReactor 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 FoxReactor register_handler_i(). This means
+ // that the notify pipe is registered with the ACE_Select_Reactor
+ // event handling code not the FoxReactor and so notfications don't
+ // work. To get around this we simply close and re-opened the
+ // notification handler in the constructor of the FoxReactor.
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ this->notify_handler_->close ();
+ this->notify_handler_->open (this, 0);
+#endif /* ACE_MT_SAFE */
+}
+
+ACE_FoxReactor::~ACE_FoxReactor (void)
+{
+}
+
+void ACE_FoxReactor::fxapplication(FXApp *a)
+{
+ fxapp=a;
+}
+
+// This is just the <wait_for_multiple_events> from ace/Reactor.cpp
+// but we use the Fox functions to wait for an event, not <select>
+
+int
+ACE_FoxReactor::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &handle_set,
+ ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE( "ACE_FoxReactor::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 = FoxWaitForMultipleEvents (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
+}
+
+int
+ACE_FoxReactor::FoxWaitForMultipleEvents (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->fxapp->runOneEvent () ;
+
+ // 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);
+}
+
+
+long ACE_FoxReactor::onFileEvents(FXObject* ob, FXSelector se, void* handle){
+ FXSelector sel=FXSELTYPE(se);
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+ bool f=false;
+ if(sel==SEL_IO_READ){
+ dispatch_set.rd_mask_.set_bit(ACE_HANDLE(handle));
+ f=true;
+ }
+ else
+ if(sel==SEL_IO_WRITE){
+ dispatch_set.wr_mask_.set_bit(ACE_HANDLE(handle));
+ f=true;
+ }
+ else
+ if(sel==SEL_IO_EXCEPT){
+ dispatch_set.ex_mask_.set_bit(ACE_HANDLE(handle));
+ f=true;
+ };
+ if(f) dispatch (1, dispatch_set);
+
+};
+
+long ACE_FoxReactor::onTimerEvents(FXObject* ob, FXSelector sel, void* handle){
+ // Deal with any timer events
+ ACE_Select_Reactor_Handle_Set handle_set;
+ this->dispatch (0, handle_set );
+
+ // Set next timeout signal
+ this->reset_timeout ();
+
+};
+
+int
+ACE_FoxReactor::register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_FoxReactor::register_handler_i");
+
+ int result = ACE_Select_Reactor::register_handler_i (handle,
+ handler, mask);
+ if (result == -1)
+ return -1;
+
+ unsigned long condition = 0;
+
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
+ ACE_SET_BITS (condition, FX::INPUT_READ);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
+ ACE_SET_BITS (condition, FX::INPUT_WRITE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_SET_BITS (condition, FX::INPUT_EXCEPT);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_SET_BITS (condition, FX::INPUT_READ);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK))
+ {
+ ACE_SET_BITS (condition, FX::INPUT_WRITE); // connected, you may write
+ ACE_SET_BITS (condition, FX::INPUT_READ); // connected, you have data/err
+ }
+
+ if (condition != 0)
+ {
+ fxapp->addInput(handle,condition,this,0);
+ }
+ return 0;
+}
+
+int
+ACE_FoxReactor::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_FoxReactor::remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_FoxReactor::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.
+
+ int condition = 0;
+
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
+ ACE_SET_BITS (condition, FX::INPUT_READ);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
+ ACE_SET_BITS (condition, FX::INPUT_WRITE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_SET_BITS (condition, FX::INPUT_EXCEPT);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_SET_BITS (condition, FX::INPUT_READ);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK))
+ {
+ ACE_SET_BITS (condition, FX::INPUT_WRITE); // connected, you may write
+ ACE_SET_BITS (condition, FX::INPUT_READ); // connected, you have data/err
+ }
+
+ // First clean up the corresponding X11Input.
+ fxapp->removeInput ((int)handle,condition); // ACE_reinterpret_cast(int,handle));
+
+ // Now let the reactor do its work.
+ return ACE_Select_Reactor::remove_handler_i (handle,
+ mask);
+}
+
+int
+ACE_FoxReactor::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 Fox timeout for the first
+// timeout in the Reactor's Timer_Queue.
+
+void
+ACE_FoxReactor::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;
+ fxapp->addTimeout (t*1000, this, 0);
+ }
+}
+
+int
+ACE_FoxReactor::reset_timer_interval
+ (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_FoxReactor::reset_timer_interval");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
+
+ int const result =
+ ACE_Select_Reactor::reset_timer_interval (timer_id,
+ interval);
+
+ if (result == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+long
+ACE_FoxReactor::schedule_timer (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_FoxReactor::schedule_timer");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
+
+ long result = ACE_Select_Reactor::schedule_timer (event_handler,
+ arg,
+ delay,
+ interval);
+ if (result == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+int
+ACE_FoxReactor::cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_FoxReactor::cancel_timer");
+
+ if (ACE_Select_Reactor::cancel_timer (handler,
+ dont_call_handle_close) == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return 0;
+ }
+}
+
+int
+ACE_FoxReactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_FoxReactor::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_FOX */
+
diff --git a/ACE/ace/FoxReactor/FoxReactor.h b/ACE/ace/FoxReactor/FoxReactor.h
new file mode 100644
index 00000000000..807d3981ed3
--- /dev/null
+++ b/ACE/ace/FoxReactor/FoxReactor.h
@@ -0,0 +1,115 @@
+/* -*- C-*- */
+
+//=============================================================================
+/**
+ * @file FoxReactor.h
+ *
+ * $Id$
+ *
+ * @author Dmitriy Nikitinskiy <nick@bel.ru>
+ * @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_FOXREACTOR_H
+#define ACE_FOXREACTOR_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_HAS_FOX)
+
+#include "ace/Select_Reactor.h"
+
+#include <fox/fx.h>
+
+/**
+ * @class ACE_FoxReactor
+ *
+ * @brief A Reactor implementation that uses the FOX toolkit (www.fox-toolkit.org)
+ * for event demultiplexing. This will let us integrate the FOX
+ * toolkit with ACE and/or TAO.
+ *
+ */
+class ACE_FoxReactor_Export ACE_FoxReactor : public FXObject , public ACE_Select_Reactor
+{
+ FXDECLARE(ACE_FoxReactor)
+public:
+ // = Initialization and termination methods.
+ ACE_FoxReactor (FXApp* a=0,
+ size_t size = DEFAULT_SIZE,
+ int restart = 0,
+ ACE_Sig_Handler * = 0);
+ virtual ~ACE_FoxReactor (void);
+
+ void fxapplication(FXApp* a);
+
+ // = Timer operations.
+ virtual long schedule_timer (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ 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);
+
+ // = Integrate with the Fox callback function mechanism.
+ long onFileEvents (FXObject*, FXSelector, void*);
+ long onTimerEvents (FXObject*, FXSelector, void*);
+
+
+protected:
+ // = Register timers/handles with Fox.
+ /// Register a single @a 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 @a 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 *);
+
+ int FoxWaitForMultipleEvents (int,ACE_Select_Reactor_Handle_Set &,ACE_Time_Value *);
+
+private:
+ /// This method ensures there's an Fox timeout for the first timeout
+ /// in the Reactor's Timer_Queue.
+ void reset_timeout (void);
+
+ FXApp *fxapp;
+
+ /// Deny access since member-wise won't work...
+ ACE_FoxReactor (const ACE_FoxReactor &);
+ ACE_FoxReactor &operator = (const ACE_FoxReactor &);
+};
+
+#endif /* ACE_HAS_FL */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FOXREACTOR_H */
+
diff --git a/ACE/ace/Framework_Component.cpp b/ACE/ace/Framework_Component.cpp
new file mode 100644
index 00000000000..95697c6e952
--- /dev/null
+++ b/ACE/ace/Framework_Component.cpp
@@ -0,0 +1,280 @@
+// Framework_Component.cpp
+// $Id$
+
+#include "ace/Framework_Component.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Framework_Component.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+#include "ace/DLL_Manager.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(ace, Framework_Component, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Framework_Component::~ACE_Framework_Component (void)
+{
+ ACE_TRACE ("ACE_Framework_Component::~ACE_Framework_Component");
+
+ ACE::strdelete (const_cast<ACE_TCHAR*> (this->dll_name_));
+ ACE::strdelete (const_cast<ACE_TCHAR*> (this->name_));
+}
+
+/***************************************************************/
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Framework_Repository)
+
+sig_atomic_t ACE_Framework_Repository::shutting_down_ = 0;
+
+// Pointer to the Singleton instance.
+ACE_Framework_Repository *ACE_Framework_Repository::repository_ = 0;
+
+ACE_Framework_Repository::~ACE_Framework_Repository (void)
+{
+ ACE_TRACE ("ACE_Framework_Repository::~ACE_Framework_Repository");
+ this->close ();
+}
+
+int
+ACE_Framework_Repository::open (int size)
+{
+ ACE_TRACE ("ACE_Framework_Repository::open");
+
+ ACE_Framework_Component **temp = 0;
+
+ ACE_NEW_RETURN (temp,
+ ACE_Framework_Component *[size],
+ -1);
+
+ this->component_vector_ = temp;
+ this->total_size_ = size;
+ return 0;
+}
+
+int
+ACE_Framework_Repository::close (void)
+{
+ ACE_TRACE ("ACE_Framework_Repository::close");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ this->shutting_down_ = 1;
+
+ if (this->component_vector_ != 0)
+ {
+ // Delete components in reverse order.
+ for (int i = this->current_size_ - 1; i >= 0; i--)
+ if (this->component_vector_[i])
+ {
+ ACE_Framework_Component *s =
+ const_cast<ACE_Framework_Component *> (
+ this->component_vector_[i]);
+
+ this->component_vector_[i] = 0;
+ delete s;
+ }
+
+ delete [] this->component_vector_;
+ this->component_vector_ = 0;
+ this->current_size_ = 0;
+ }
+
+ ACE_DLL_Manager::close_singleton ();
+ return 0;
+}
+
+ACE_Framework_Repository *
+ACE_Framework_Repository::instance (int size)
+{
+ ACE_TRACE ("ACE_Framework_Repository::instance");
+
+ if (ACE_Framework_Repository::repository_ == 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_Framework_Repository::repository_ == 0)
+ {
+ if (ACE_Object_Manager::starting_up () ||
+ !ACE_Object_Manager::shutting_down ())
+ {
+ ACE_NEW_RETURN (ACE_Framework_Repository::repository_,
+ ACE_Framework_Repository (size),
+ 0);
+ }
+ }
+ }
+
+ return ACE_Framework_Repository::repository_;
+}
+
+void
+ACE_Framework_Repository::close_singleton (void)
+{
+ ACE_TRACE ("ACE_Framework_Repository::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ delete ACE_Framework_Repository::repository_;
+ ACE_Framework_Repository::repository_ = 0;
+}
+
+int
+ACE_Framework_Repository::register_component (ACE_Framework_Component *fc)
+{
+ ACE_TRACE ("ACE_Framework_Repository::register_component");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+ int i;
+
+ // Check to see if it's already registered
+ for (i = 0; i < this->current_size_; i++)
+ if (this->component_vector_[i] &&
+ fc->this_ == this->component_vector_[i]->this_)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("AFR::register_component: error, ")
+ ACE_TEXT ("compenent already registered\n")),
+ -1);
+ }
+
+ if (i < this->total_size_)
+ {
+ this->component_vector_[i] = fc;
+ this->current_size_++;
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+ACE_Framework_Repository::remove_component (const ACE_TCHAR *name)
+{
+ ACE_TRACE ("ACE_Framework_Repository::remove_component");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+ int i;
+
+ for (i = 0; i < this->current_size_; i++)
+ if (this->component_vector_[i] &&
+ ACE_OS::strcmp (this->component_vector_[i]->name_, name) == 0)
+ {
+ delete this->component_vector_[i];
+ this->component_vector_[i] = 0;
+ this->compact ();
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+ACE_Framework_Repository::remove_dll_components (const ACE_TCHAR *dll_name)
+{
+ ACE_TRACE ("ACE_Framework_Repository::remove_dll_components");
+
+ if (this->shutting_down_)
+ return this->remove_dll_components_i (dll_name);
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ return this->remove_dll_components_i (dll_name);
+}
+
+int
+ACE_Framework_Repository::remove_dll_components_i (const ACE_TCHAR *dll_name)
+{
+ ACE_TRACE ("ACE_Framework_Repository::remove_dll_components_i");
+
+ int i;
+ int retval = -1;
+
+ for (i = 0; i < this->current_size_; i++)
+ if (this->component_vector_[i] &&
+ ACE_OS::strcmp (this->component_vector_[i]->dll_name_, dll_name) == 0)
+ {
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("AFR::remove_dll_components_i (%s) ")
+ ACE_TEXT ("component \"%s\"\n"),
+ dll_name, this->component_vector_[i]->name_));
+ delete this->component_vector_[i];
+ this->component_vector_[i] = 0;
+ ++retval;
+ }
+
+ this->compact ();
+
+ return retval == -1 ? -1 : 0;
+}
+
+void
+ACE_Framework_Repository::compact (void)
+{
+ ACE_TRACE ("ACE_Framework_Repository::compact");
+
+ int i;
+ int start_hole;
+ int end_hole;
+
+ do
+ {
+ start_hole = this->current_size_;
+ end_hole = this->current_size_;
+
+ // Find hole
+ for (i = 0; i < this->current_size_; ++i)
+ {
+ if (this->component_vector_[i] == 0)
+ {
+ if (start_hole == this->current_size_)
+ {
+ start_hole = i;
+ end_hole = i;
+ }
+ else
+ end_hole = i;
+ }
+ else if (end_hole != this->current_size_)
+ break;
+ }
+
+ if (start_hole != this->current_size_)
+ {
+ // move the contents and reset current_size_
+ while (end_hole + 1 < this->current_size_)
+ {
+ this->component_vector_[start_hole++] =
+ this->component_vector_[++end_hole];
+ }
+ // Since start_hole is now one past the last
+ // active slot.
+ this->current_size_ = start_hole;
+ }
+
+ } while (start_hole != this->current_size_);
+}
+
+void
+ACE_Framework_Repository::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Framework_Repository::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Framework_Repository::ACE_Framework_Repository (int size)
+ : current_size_ (0)
+{
+ ACE_TRACE ("ACE_Framework_Repository::ACE_Framework_Repository");
+
+ if (this->open (size) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Framework_Repository")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Framework_Component.h b/ACE/ace/Framework_Component.h
new file mode 100644
index 00000000000..0541626ad31
--- /dev/null
+++ b/ACE/ace/Framework_Component.h
@@ -0,0 +1,210 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Framework_Component.h
+ *
+ * $Id$
+ *
+ * A prototype mechanism that allows framework components, singletons
+ * such as ACE_Reactor, ACE_Proactor, etc, to be registered with a
+ * central repository managed by the ACE_Object_Manager or
+ * ACE_Service_Config that will handle destruction.
+ *
+ * This technique obviates changing ACE_Object_Manager and
+ * ACE_Service_Config everytime a new framework is added. Which also
+ * means that unused framework components don't need to linked into
+ * the final application which is important for applications with
+ * stringent footprint requirements.
+ *
+ * Framework components need only provide a static method,
+ * close_singleton() and add the ACE_REGISTER_FRAMEWORK_COMPONENT macro
+ * call to their instance() methods in order to participate. Components
+ * that don't have a close_singleton() method can also participate via
+ * template specialization of ACE_Framework_Component_T.
+ *
+ * This design uses the External Polymorphism pattern to avoid having
+ * to derive all framework components from a common base class that
+ * has virtual methods (this is crucial to avoid unnecessary overhead),
+ * and is based on the dump debugging implementation found in
+ * <ace/Dump.h>.
+ *
+ * @author Don Hinton <dhinton@ieee.org>.
+ */
+//=============================================================================
+
+#ifndef ACE_FRAMEWORK_COMPONENT_H
+#define ACE_FRAMEWORK_COMPONENT_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_signal.h"
+#include "ace/Thread_Mutex.h"
+
+#define ACE_DEFAULT_FRAMEWORK_REPOSITORY_SIZE 1024
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Framework_Component
+ *
+ * @brief Base class that defines a uniform interface for all managed
+ * framework components.
+ */
+class ACE_Export ACE_Framework_Component
+{
+public:
+ friend class ACE_Framework_Repository;
+
+ /// Constructor.
+ ACE_Framework_Component (void *_this,
+ const ACE_TCHAR *dll_name = 0,
+ const ACE_TCHAR *name = 0);
+
+ /// Close the contained singleton.
+ virtual void close_singleton (void) = 0;
+
+protected:
+ /// Destructor.
+ virtual ~ACE_Framework_Component (void);
+
+private:
+ // No copy possible
+ ACE_Framework_Component (const ACE_Framework_Component &);
+ void operator= (const ACE_Framework_Component &);
+
+private:
+ /// Pointer to the actual component.
+ const void *this_;
+
+ /// Library associated with this component
+ const ACE_TCHAR *dll_name_;
+
+ /// Component name
+ const ACE_TCHAR *name_;
+};
+
+/**
+ * @class ACE_Framework_Repository
+ *
+ * @brief Contains all framework components used by an application.
+ *
+ * This class contains a vector of ACE_Framework_Component *'s. On
+ * destruction, framework components are destroyed in the reverse order
+ * that they were added originally.
+ */
+class ACE_Export ACE_Framework_Repository
+{
+public:
+ // This is just to silence a compiler warning about no public ctors
+ friend class ACE_Framework_Component;
+
+ enum
+ {
+ DEFAULT_SIZE = ACE_DEFAULT_FRAMEWORK_REPOSITORY_SIZE
+ };
+
+ /// Close down the repository and free up dynamically allocated
+ /// resources.
+ ~ACE_Framework_Repository (void);
+
+ /// Initialize the repository.
+ int open (int size = DEFAULT_SIZE);
+
+ /// Close down the repository and free up dynamically allocated
+ /// resources, also called by dtor.
+ int close (void);
+
+ /// Get pointer to a process-wide ACE_Framework_Repository.
+ static ACE_Framework_Repository *instance
+ (int size = ACE_Framework_Repository::DEFAULT_SIZE);
+
+ /// Delete the dynamically allocated Singleton.
+ static void close_singleton (void);
+
+ // = Search structure operations (all acquire locks as necessary).
+
+ /// Insert a new component. Returns -1 when the repository is full
+ /// and 0 on success.
+ int register_component (ACE_Framework_Component *fc);
+
+ /// Remove a component. Returns -1 on error or if component not found
+ /// and 0 on success.
+ int remove_component (const ACE_TCHAR *name);
+
+ /// Remove all components associated with a particular dll.
+ int remove_dll_components (const ACE_TCHAR *dll_name);
+
+ /// Return the current size of the repository.
+ int current_size (void) const;
+
+ /// Return the total size of the repository.
+ int total_size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ /// Initialize the repository.
+ ACE_Framework_Repository (int size = ACE_Framework_Repository::DEFAULT_SIZE);
+
+private:
+
+ /// Actually removes the dll components, must be called with locks held.
+ int remove_dll_components_i (const ACE_TCHAR *dll_name);
+
+ /// Compact component_vector_ after components have been removed__maintains
+ /// order.
+ void compact (void);
+
+ /// Disallow copying and assignment.
+ ACE_Framework_Repository (const ACE_Framework_Repository &);
+ ACE_Framework_Repository &operator= (const ACE_Framework_Repository &);
+
+private:
+
+ /// Contains all the framework components.
+ ACE_Framework_Component **component_vector_;
+
+ /// Current number of components.
+ int current_size_;
+
+ /// Maximum number of components.
+ int total_size_;
+
+ /// Pointer to a process-wide ACE_Framework_Repository.
+ static ACE_Framework_Repository *repository_;
+
+ /// Flag set when repository is the process of shutting down. This
+ /// is necessary to keep from self-deadlocking since some of
+ /// the components might make calls back to the repository to
+ /// unload their components, e.g., ACE_DLL_Manager.
+ static sig_atomic_t shutting_down_;
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ /// Synchronization variable for the MT_SAFE Repository
+ ACE_Thread_Mutex lock_;
+#endif /* ACE_MT_SAFE */
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Framework_Component.inl"
+#endif /* __ACE_INLINE__ */
+
+// Include the templates classes at this point.
+#include "ace/Framework_Component_T.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FRAMEWORK_COMPONENT_H */
diff --git a/ACE/ace/Framework_Component.inl b/ACE/ace/Framework_Component.inl
new file mode 100644
index 00000000000..2c3c2130a53
--- /dev/null
+++ b/ACE/ace/Framework_Component.inl
@@ -0,0 +1,39 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/ACE.h"
+#include "ace/Guard_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Framework_Component::ACE_Framework_Component (void *_this,
+ const ACE_TCHAR *dll_name,
+ const ACE_TCHAR *name)
+ : this_ (_this),
+ dll_name_ (ACE::strnew (dll_name ? dll_name : ACE_TEXT (""))),
+ name_ (ACE::strnew (name ? name : ACE_TEXT ("")))
+{
+ ACE_TRACE ("ACE_Framework_Component::ctor");
+}
+
+/***************************************************************/
+
+ACE_INLINE int
+ACE_Framework_Repository::current_size (void) const
+{
+ ACE_TRACE ("ACE_Framework_Repository::current_size");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, (ACE_Thread_Mutex &) this->lock_, -1));
+ return this->current_size_;
+}
+
+ACE_INLINE int
+ACE_Framework_Repository::total_size (void) const
+{
+ ACE_TRACE ("ACE_Framework_Repository::total_size");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, (ACE_Thread_Mutex &) this->lock_, -1));
+ return this->total_size_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Framework_Component_T.cpp b/ACE/ace/Framework_Component_T.cpp
new file mode 100644
index 00000000000..509d6609daf
--- /dev/null
+++ b/ACE/ace/Framework_Component_T.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+#ifndef ACE_FRAMEWORK_COMPONENT_T_CPP
+#define ACE_FRAMEWORK_COMPONENT_T_CPP
+
+#include "ace/Framework_Component_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class Concrete>
+ACE_Framework_Component_T<Concrete>::ACE_Framework_Component_T (Concrete *concrete)
+ : ACE_Framework_Component ((void *) concrete, concrete->dll_name (), concrete->name ())
+{
+ ACE_TRACE ("ACE_Framework_Component_T<Concrete>::ctor");
+}
+
+template <class Concrete>
+ACE_Framework_Component_T<Concrete>::~ACE_Framework_Component_T (void)
+{
+ ACE_TRACE ("ACE_Framework_Component_T<Concrete>::~ACE_Framework_Component_T");
+ Concrete::close_singleton ();
+}
+
+template <class Concrete> void
+ACE_Framework_Component_T<Concrete>::close_singleton (void)
+{
+ ACE_TRACE ("ACE_Framework_Component_T<Concrete>::close_singleton");
+ Concrete::close_singleton ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_FRAMEWORK_COMPONENT_T_CPP */
diff --git a/ACE/ace/Framework_Component_T.h b/ACE/ace/Framework_Component_T.h
new file mode 100644
index 00000000000..4dacfe77dd9
--- /dev/null
+++ b/ACE/ace/Framework_Component_T.h
@@ -0,0 +1,71 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Framework_Component_T.h
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@ieee.org>
+ */
+//=============================================================================
+
+#ifndef ACE_FRAMEWORK_COMPONENT_T_H
+#define ACE_FRAMEWORK_COMPONENT_T_H
+#include /**/ "ace/pre.h"
+#include "ace/Framework_Component.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Framework_Component_T
+ *
+ * @brief This class inherits the interface of the abstract
+ * ACE_Framework_Component class and is instantiated with the
+ * implementation of the concrete component class @c class Concrete.
+ *
+ * This design is similar to the Adapter and Decorator patterns
+ * from the ``Gang of Four'' book. Note that @c class Concrete
+ * need not inherit from a common class since ACE_Framework_Component
+ * provides the uniform virtual interface! (implementation based on
+ * ACE_Dumpable_Adapter in <ace/Dump_T.h>.
+ */
+template <class Concrete>
+class ACE_Framework_Component_T : public ACE_Framework_Component
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Constructor.
+ ACE_Framework_Component_T (Concrete *concrete);
+
+ /// Destructor.
+ ~ACE_Framework_Component_T (void);
+
+ /// Close the contained singleton.
+ void close_singleton (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// This macro should be called in the instance() method
+// of the Concrete class that will be managed. Along
+// with the appropriate template instantiation.
+#define ACE_REGISTER_FRAMEWORK_COMPONENT(CLASS, INSTANCE) \
+ ACE_Framework_Repository::instance ()->register_component \
+ (new ACE_Framework_Component_T<CLASS> (INSTANCE));
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Framework_Component_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Framework_Component_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FRAMEWORK_COMPONENT_T_H */
diff --git a/ACE/ace/Free_List.cpp b/ACE/ace/Free_List.cpp
new file mode 100644
index 00000000000..60dfabafb1c
--- /dev/null
+++ b/ACE/ace/Free_List.cpp
@@ -0,0 +1,157 @@
+// $Id$
+
+#ifndef ACE_FREE_LIST_CPP
+#define ACE_FREE_LIST_CPP
+
+#include "ace/Free_List.h"
+#include "ace/Guard_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T>
+ACE_Free_List<T>::~ACE_Free_List (void)
+{
+}
+
+// Default constructor that takes in a preallocation number
+// (<prealloc>), a low and high water mark (<lwm> and <hwm>) and an
+// increment value (<inc>)
+
+template <class T, class ACE_LOCK>
+ACE_Locked_Free_List<T, ACE_LOCK>::ACE_Locked_Free_List (int mode,
+ size_t prealloc,
+ size_t lwm,
+ size_t hwm,
+ size_t inc)
+ : mode_ (mode),
+ free_list_ (0),
+ lwm_ (lwm),
+ hwm_ (hwm),
+ inc_ (inc),
+ size_ (0)
+{
+ this->alloc (prealloc);
+}
+
+// Destructor - removes all the elements from the free_list
+
+template <class T, class ACE_LOCK>
+ACE_Locked_Free_List<T, ACE_LOCK>::~ACE_Locked_Free_List (void)
+{
+ if (this->mode_ != ACE_PURE_FREE_LIST)
+ while (this->free_list_ != 0)
+ {
+ T *temp = this->free_list_;
+ this->free_list_ = this->free_list_->get_next ();
+ delete temp;
+ }
+}
+
+// Inserts an element onto the free list (if we are allowed to manage
+// elements withing and it pasts the high water mark, delete the
+// element)
+
+template <class T, class ACE_LOCK> void
+ACE_Locked_Free_List<T, ACE_LOCK>::add (T *element)
+{
+ ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
+
+ // Check to see that we not at the high water mark.
+ if (this->mode_ == ACE_PURE_FREE_LIST
+ || this->size_ < this->hwm_)
+ {
+ element->set_next (this->free_list_);
+ this->free_list_ = element;
+ this->size_++;
+ }
+ else
+ delete element;
+}
+
+// Takes a element off the freelist and returns it. It creates <inc>
+// new elements if we are allowed to do it and the size is at the low
+// water mark.
+
+template <class T, class ACE_LOCK> T *
+ACE_Locked_Free_List<T, ACE_LOCK>::remove (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, 0));
+
+ // If we are at the low water mark, add some nodes
+ if (this->mode_ != ACE_PURE_FREE_LIST && this->size_ <= this->lwm_)
+ this->alloc (this->inc_);
+
+ // Remove a node
+ T *temp = this->free_list_;
+
+ if (temp != 0)
+ {
+ this->free_list_ = this->free_list_->get_next ();
+ this->size_--;
+ }
+
+ return temp;
+}
+
+
+// Returns the current size of the free list
+
+template <class T, class ACE_LOCK> size_t
+ACE_Locked_Free_List<T, ACE_LOCK>::size (void)
+{
+ return this->size_;
+}
+
+// Resizes the free list to <newsize>
+
+template <class T, class ACE_LOCK> void
+ACE_Locked_Free_List<T, ACE_LOCK>::resize (size_t newsize)
+{
+ ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
+
+ // Check if we are allowed to resize
+ if (this->mode_ != ACE_PURE_FREE_LIST)
+ // Check to see if we grow or shrink
+ if (newsize < this->size_)
+ this->dealloc (this->size_ - newsize);
+ else
+ this->alloc (newsize - this->size_);
+}
+
+// Allocates <n> extra nodes for the freelist
+
+template <class T, class ACE_LOCK> void
+ACE_Locked_Free_List<T, ACE_LOCK>::alloc (size_t n)
+{
+ for (; n > 0; n--)
+ {
+ T *temp = 0;
+ ACE_NEW (temp, T);
+ temp->set_next (this->free_list_);
+ this->free_list_ = temp;
+ this->size_++;
+ }
+}
+
+// Removes and frees <n> nodes from the freelist.
+
+template <class T, class ACE_LOCK> void
+ACE_Locked_Free_List<T, ACE_LOCK>::dealloc (size_t n)
+{
+ for (; this->free_list_ != 0 && n > 0;
+ n--)
+ {
+ T *temp = this->free_list_;
+ this->free_list_ = this->free_list_->get_next ();
+ delete temp;
+ this->size_--;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_FREE_LIST_CPP */
diff --git a/ACE/ace/Free_List.h b/ACE/ace/Free_List.h
new file mode 100644
index 00000000000..b77931fc45b
--- /dev/null
+++ b/ACE/ace/Free_List.h
@@ -0,0 +1,150 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Free_List.h
+ *
+ * $Id$
+ *
+ * @author Darrell Brunsch (brunsch@cs.wustl.edu)
+ */
+//=============================================================================
+
+#ifndef ACE_FREE_LIST_H
+#define ACE_FREE_LIST_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/Global_Macros.h"
+#include "ace/Default_Constants.h"
+#include "ace/os_include/os_stddef.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Free_List
+ *
+ * @brief Implements a free list.
+ *
+ * This class maintains a free list of nodes of type T.
+ */
+template <class T>
+class ACE_Free_List
+{
+public:
+ /// Destructor - removes all the elements from the free_list.
+ virtual ~ACE_Free_List (void);
+
+ /// Inserts an element onto the free list (if it isn't past the high
+ /// water mark).
+ virtual void add (T *element) = 0;
+
+ /// Takes a element off the freelist and returns it. It creates
+ /// <inc> new elements if the size is at or below the low water mark.
+ virtual T *remove (void) = 0;
+
+ /// Returns the current size of the free list.
+ virtual size_t size (void) = 0;
+
+ /// Resizes the free list to @a newsize.
+ virtual void resize (size_t newsize) = 0;
+};
+
+/**
+ * @class ACE_Locked_Free_List
+ *
+ * @brief Implements a free list.
+ *
+ * This class maintains a free list of nodes of type T. It
+ * depends on the type T having a <get_next> and <set_next>
+ * method. It maintains a mutex so the freelist can be used in
+ * a multithreaded program .
+ */
+template <class T, class ACE_LOCK>
+class ACE_Locked_Free_List : public ACE_Free_List<T>
+{
+public:
+ // = Initialization and termination.
+ /**
+ * Constructor takes a @a mode (i.e., ACE_FREE_LIST_WITH_POOL or
+ * ACE_PURE_FREE_LIST), a count of the number of nodes to
+ * <prealloc>, a low and high water mark (<lwm> and <hwm>) that
+ * indicate when to allocate more nodes, an increment value (<inc>)
+ * that indicates how many nodes to allocate when the list must
+ * grow.
+ */
+ ACE_Locked_Free_List (int mode = ACE_FREE_LIST_WITH_POOL,
+ size_t prealloc = ACE_DEFAULT_FREE_LIST_PREALLOC,
+ size_t lwm = ACE_DEFAULT_FREE_LIST_LWM,
+ size_t hwm = ACE_DEFAULT_FREE_LIST_HWM,
+ size_t inc = ACE_DEFAULT_FREE_LIST_INC);
+
+ /// Destructor - removes all the elements from the free_list.
+ virtual ~ACE_Locked_Free_List (void);
+
+ /// Inserts an element onto the free list (if it isn't past the high
+ /// water mark).
+ virtual void add (T *element);
+
+ /// Takes a element off the freelist and returns it. It creates
+ /// <inc> new elements if the size is at or below the low water mark.
+ virtual T *remove (void);
+
+ /// Returns the current size of the free list.
+ virtual size_t size (void);
+
+ /// Resizes the free list to @a newsize.
+ virtual void resize (size_t newsize);
+
+protected:
+ /// Allocates @a n extra nodes for the freelist.
+ virtual void alloc (size_t n);
+
+ /// Removes and frees @a n nodes from the freelist.
+ virtual void dealloc (size_t n);
+
+ /// Free list operation mode, either ACE_FREE_LIST_WITH_POOL or
+ /// ACE_PURE_FREE_LIST.
+ int mode_;
+
+ /// Pointer to the first node in the freelist.
+ T *free_list_;
+
+ /// Low water mark.
+ size_t lwm_;
+
+ /// High water mark.
+ size_t hwm_;
+
+ /// Increment value.
+ size_t inc_;
+
+ /// Keeps track of the size of the list.
+ size_t size_;
+
+ /// Synchronization variable for ACE_Timer_Queue.
+ ACE_LOCK mutex_;
+
+private:
+ // = Don't allow these operations for now.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Locked_Free_List (const ACE_Locked_Free_List<T, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Locked_Free_List<T, ACE_LOCK> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Free_List.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Free_List.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FREE_LIST_H */
diff --git a/ACE/ace/Functor.cpp b/ACE/ace/Functor.cpp
new file mode 100644
index 00000000000..9fc3b3400c0
--- /dev/null
+++ b/ACE/ace/Functor.cpp
@@ -0,0 +1,43 @@
+
+//=============================================================================
+/**
+ * @file Functor.cpp
+ *
+ * $Id$
+ *
+ * Non-inlinable method definitions for non-templatized classes
+ * and template specializations implementing the GOF Command Pattern,
+ * and STL-style functors.
+ *
+ *
+ * @author Chris Gill <cdgill@cs.wustl.edu>
+ *
+ * Based on Command Pattern implementations originally done by
+ *
+ * Carlos O'Ryan <coryan@cs.wustl.edu>
+ * Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+ *
+ * and on STL-style functor implementations originally done by
+ *
+ * Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#include "ace/Functor_T.h"
+#include "ace/Functor.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Functor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Functor, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Command_Base::~ACE_Command_Base (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Functor.h b/ACE/ace/Functor.h
new file mode 100644
index 00000000000..f303bc09c97
--- /dev/null
+++ b/ACE/ace/Functor.h
@@ -0,0 +1,593 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Functor.h
+ *
+ * $Id$
+ *
+ * Non-templatized classes and class template specializations for
+ * implementing function objects that are used in various places
+ * in ACE. There are currently two major categories of function
+ * objects in ACE: GoF Command Pattern objects, and STL-style
+ * functors for comparison of container elements. The command objects
+ * are invoked via an execute () method, while the STL-style functors are
+ * invoked via an operator() () method.
+ * Non-templatized classes for implementing the GoF Command Pattern,
+ * also known as functors or function objects.
+ *
+ *
+ * @author Chris Gill <cdgill@cs.wustl.edu>
+ * @author Based on Command Pattern implementations originally done by
+ * @author Carlos O'Ryan <coryan@cs.wustl.edu>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+ * @author and on STL-style functor implementations originally done by
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//==========================================================================
+
+
+#ifndef ACE_FUNCTOR_H
+#define ACE_FUNCTOR_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/ACE_export.h"
+#include "ace/Basic_Types.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//////////////////////////////////////////////////////////////
+// GOF Command Pattern Classes and Template Specializations //
+//////////////////////////////////////////////////////////////
+
+/**
+ * @class ACE_Command_Base
+ *
+ * @brief Defines an abstract class that allows us to invoke commands
+ * without knowing anything about the implementation.
+ *
+ * This class declares an interface to execute a command
+ * independent of the effect of the command, or the objects used
+ * to implement it.
+ */
+class ACE_Export ACE_Command_Base
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_Command_Base (void);
+
+ /// Virtual destructor.
+ virtual ~ACE_Command_Base (void);
+
+ /**
+ * Invokes the method encapsulated by the command, passing along the
+ * passed argument (if any). Users of classes derived from this
+ * class must ensure that the resulting invocation can tolerate a
+ * null void pointer being passed, or otherwise ensure that this
+ * will never occur.
+ */
+ virtual int execute (void *arg = 0) = 0;
+};
+
+////////////////////////////////////////////////////////////
+// STL-style Functor Classes and Template Specializations //
+////////////////////////////////////////////////////////////
+
+// Forward declaration since we are going to specialize that template
+// here. The template itself requires this file so every user of the
+// template should also see the specialization.
+template <class TYPE> class ACE_Hash;
+template <class TYPE> class ACE_Equal_To;
+template <class TYPE> class ACE_Less_Than;
+
+/**
+ * @class ACE_Hash<char>
+ *
+ * @brief Function object for hashing a char
+ */
+template<>
+class ACE_Export ACE_Hash<char>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (char t) const;
+};
+
+/**
+ * @class ACE_Hash<signed char>
+ *
+ * @brief Function object for hashing a signed char
+ */
+template<>
+class ACE_Export ACE_Hash<signed char>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (signed char t) const;
+};
+
+/**
+ * @class ACE_Hash<unsigned char>
+ *
+ * @brief Function object for hashing an unsigned char
+ */
+template<>
+class ACE_Export ACE_Hash<unsigned char>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (unsigned char t) const;
+};
+
+#if 0
+// @@ ADD HASHES FOR ACE TYPES
+
+/**
+ * @class ACE_Hash<ACE_INT16>
+ *
+ * @brief Function object for hashing a 16-bit signed number
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_INT16>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (ACE_INT16 t) const;
+};
+
+/**
+ * @class ACE_Hash<ACE_UINT16>
+ *
+ * @brief Function object for hashing a 16-bit unsigned number
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_UINT16>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (ACE_UINT16 t) const;
+};
+
+/**
+ * @class ACE_Hash<ACE_INT32>
+ *
+ * @brief Function object for hashing a 32-bit signed number
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_INT32>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (ACE_INT32 t) const;
+};
+
+/**
+ * @class ACE_Hash<ACE_UINT32>
+ *
+ * @brief Function object for hashing a 32-bit unsigned number
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_UINT32>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (ACE_UINT32 t) const;
+};
+
+/**
+ * @class ACE_Hash<ACE_UINT64>
+ *
+ * @brief Function object for hashing a 64-bit unsigned number
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_UINT64>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (ACE_UINT64 t) const;
+};
+
+// @@ DONE ADDING HASHES FOR ACE TYPES
+#endif
+
+/**
+ * @class ACE_Hash<short>
+ *
+ * @brief Function object for hashing a short number
+ */
+template<>
+class ACE_Export ACE_Hash<short>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (short t) const;
+};
+
+/**
+ * @class ACE_Hash<unsigned short>
+ *
+ * @brief Function object for hashing an unsigned short number
+ */
+template<>
+class ACE_Export ACE_Hash<unsigned short>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (unsigned short t) const;
+};
+
+/**
+ * @class ACE_Hash<int>
+ *
+ * @brief Function object for hashing an int number
+ */
+template<>
+class ACE_Export ACE_Hash<int>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (int t) const;
+};
+
+/**
+ * @class ACE_Hash<unsigned int>
+ *
+ * @brief Function object for hashing an unsigned int number
+ */
+template<>
+class ACE_Export ACE_Hash<unsigned int>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (unsigned int t) const;
+};
+
+/**
+ * @class ACE_Hash<long>
+ *
+ * @brief Function object for hashing a long number
+ */
+template<>
+class ACE_Export ACE_Hash<long>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (long t) const;
+};
+
+/**
+ * @class ACE_Hash<unsigned long>
+ *
+ * @brief Function object for hashing an unsigned long number
+ */
+template<>
+class ACE_Export ACE_Hash<unsigned long>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (unsigned long t) const;
+};
+
+#if !defined (ACE_LACKS_LONGLONG_T) && (ACE_SIZEOF_LONG < 8)
+/**
+ * @class ACE_Hash<ACE_INT64>
+ *
+ * @brief Function object for hashing a signed 64-bit number
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_INT64>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (ACE_INT64 t) const;
+};
+#endif /* !ACE_LACKS_LONGLONG_T && ACE_SIZEOF_LONG < 8 */
+
+// We can do this even if ACE_LACKS_UNSIGNEDLONGLONG_T because there's an
+// emulation for it in ACE_U_LongLong.
+#if (ACE_SIZEOF_LONG < 8)
+/**
+ * @class ACE_Hash<ACE_UINT64>
+ *
+ * @brief Function object for hashing an unsigned 64-bit number
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_UINT64>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (const ACE_UINT64 &t) const;
+};
+#endif /* ACE_SIZEOF_LONG < 8 */
+
+/**
+ * @class ACE_Hash<const char *>
+ *
+ * @brief Function object for hashing a const string
+ */
+template<>
+class ACE_Export ACE_Hash<const char *>
+{
+public:
+ /// Calls ACE::hash_pjw
+ unsigned long operator () (const char *t) const;
+};
+
+/**
+ * @class ACE_Hash<char *>
+ *
+ * @brief Function object for hashing a string
+ */
+template<>
+class ACE_Export ACE_Hash<char *>
+{
+public:
+ /// Calls ACE::hash_pjw
+ unsigned long operator () (const char *t) const;
+};
+
+/**
+ * @class ACE_Hash<void *>
+ *
+ * @brief Function object for hashing a void *
+ */
+template<>
+class ACE_Export ACE_Hash<void *>
+{
+public:
+ unsigned long operator () (const void *) const;
+};
+
+/**
+ * @class ACE_Equal_To<const char *>
+ *
+ * @brief Function object for determining whether two const strings are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<const char *>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const char *lhs,
+ const char *rhs) const;
+};
+
+/**
+ * @class ACE_Equal_To<char *>
+ *
+ * @brief Function object for determining whether two non-const
+ * strings are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<char *>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const char *lhs,
+ const char *rhs) const;
+};
+
+/**
+ * @class ACE_Equal_To<ACE_UINT16>
+ *
+ * @brief Function object for determining whether two unsigned
+ * 16 bit ints are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<ACE_UINT16>
+{
+public:
+ /// Simply calls built-in operators
+ int operator () (const ACE_UINT16 lhs,
+ const ACE_UINT16 rhs) const;
+};
+
+/**
+ * @class ACE_Equal_To<ACE_INT16>
+ *
+ * @brief Function object for determining whether two
+ * 16 bit ints are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<ACE_INT16>
+{
+public:
+ /// Simply calls built-in operators
+ int operator () (const ACE_INT16 lhs,
+ const ACE_INT16 rhs) const;
+};
+
+/**
+ * @class ACE_Equal_To<ACE_UINT32>
+ *
+ * @brief Function object for determining whether two unsigned
+ * 32 bit ints are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<ACE_UINT32>
+{
+public:
+ /// Simply calls built-in operators
+ int operator () (const ACE_UINT32 lhs,
+ const ACE_UINT32 rhs) const;
+};
+
+/**
+ * @class ACE_Equal_To<ACE_INT32>
+ *
+ * @brief Function object for determining whether two
+ * 32 bit ints are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<ACE_INT32>
+{
+public:
+ /// Simply calls built-in operators
+ int operator () (const ACE_INT32 lhs,
+ const ACE_INT32 rhs) const;
+};
+
+/**
+ * @class ACE_Equal_To<ACE_UINT64>
+ *
+ * @brief Function object for determining whether two unsigned
+ * 64 bit ints are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<ACE_UINT64>
+{
+public:
+ /// Simply calls built-in operators
+ int operator () (const ACE_UINT64 lhs,
+ const ACE_UINT64 rhs) const;
+};
+
+/**
+ * @class ACE_Less_Than<const char*>
+ *
+ * @brief Function object for determining whether the first const string
+ * is less than the second const string.
+ */
+template<>
+class ACE_Export ACE_Less_Than<const char *>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const char *lhs,
+ const char *rhs) const;
+};
+
+/**
+ * @class ACE_Less_Than<char *>
+ *
+ * @brief Function object for determining whether the first string
+ * is less than the second string.
+ */
+template<>
+class ACE_Export ACE_Less_Than<char *>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const char *lhs,
+ const char *rhs) const;
+};
+
+#if defined (ACE_HAS_WCHAR)
+
+# if ! defined (ACE_LACKS_NATIVE_WCHAR_T)
+/**
+ * @class ACE_Hash<wchar_t>
+ *
+ * @brief Function object for hashing a wchar_t
+ */
+template<>
+class ACE_Export ACE_Hash<wchar_t>
+{
+public:
+ /// Simply returns t
+ unsigned long operator () (wchar_t t) const;
+};
+# endif /* ACE_LACKS_NATIVE_WCHAR_T */
+/**
+ * @class ACE_Hash<const wchar_t *>
+ *
+ * @brief Function object for hashing a const string
+ */
+template<>
+class ACE_Export ACE_Hash<const wchar_t *>
+{
+public:
+ /// Calls ACE::hash_pjw
+ unsigned long operator () (const wchar_t *t) const;
+};
+
+/**
+ * @class ACE_Hash<wchar_t *>
+ *
+ * @brief Function object for hashing a string
+ */
+template<>
+class ACE_Export ACE_Hash<wchar_t *>
+{
+public:
+ /// Calls ACE::hash_pjw
+ unsigned long operator () (const wchar_t *t) const;
+};
+
+/**
+ * @class ACE_Equal_To<const wchar_t *>
+ *
+ * @brief Function object for determining whether two const strings are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<const wchar_t *>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const wchar_t *lhs,
+ const wchar_t *rhs) const;
+};
+
+/**
+ * @class ACE_Equal_To<wchar_t *>
+ *
+ * @brief Function object for determining whether two non-const
+ * strings are equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<wchar_t *>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const wchar_t *lhs,
+ const wchar_t *rhs) const;
+};
+
+/**
+ * @class ACE_Less_Than<const wchar_t *>
+ *
+ * @brief Function object for determining whether the first const string
+ * is less than the second const string.
+ */
+template<>
+class ACE_Export ACE_Less_Than<const wchar_t *>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const wchar_t *lhs,
+ const wchar_t *rhs) const;
+};
+
+/**
+ * @class ACE_Less_Than<wchar_t *>
+ *
+ * @brief Function object for determining whether the first string
+ * is less than the second string.
+ */
+template<>
+class ACE_Export ACE_Less_Than<wchar_t *>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const wchar_t *lhs,
+ const wchar_t *rhs) const;
+};
+
+#endif // ACE_HAS_WCHAR
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Functor.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FUNCTOR_H */
diff --git a/ACE/ace/Functor.inl b/ACE/ace/Functor.inl
new file mode 100644
index 00000000000..65da8feec6d
--- /dev/null
+++ b/ACE/ace/Functor.inl
@@ -0,0 +1,284 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Functor.inl
+ *
+ * $Id$
+ *
+ * Inlinable method definitions for non-templatized classes
+ * and template specializations implementing the GOF Command Pattern,
+ * and STL-style functors.
+ *
+ *
+ * @author Chris Gill <cdgill@cs.wustl.edu>
+ *
+ * Based on Command Pattern implementations originally done by
+ *
+ * Carlos O'Ryan <coryan@cs.wustl.edu>
+ * Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+ *
+ * and on STL-style functor implementations originally done by
+ * Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//////////////////////////////////////////////////////////////
+// GOF Command Pattern Classes and Template Specializations //
+//////////////////////////////////////////////////////////////
+
+// Default constructor.
+
+ACE_INLINE
+ACE_Command_Base::ACE_Command_Base (void)
+{
+}
+
+////////////////////////////////////////////////////////////
+// STL-style Functor Classes and Template Specializations //
+////////////////////////////////////////////////////////////
+
+ACE_INLINE unsigned long
+ACE_Hash<char>::operator () (char t) const
+{
+ return t;
+}
+
+#if defined (ACE_HAS_WCHAR) && ! defined (ACE_LACKS_NATIVE_WCHAR_T)
+ACE_INLINE unsigned long
+ACE_Hash<wchar_t>::operator () (wchar_t t) const
+{
+ return t;
+}
+#endif /* ACE_HAS_WCHAR && ! ACE_LACKS_NATIVE_WCHAR_T */
+
+ACE_INLINE unsigned long
+ACE_Hash<signed char>::operator () (signed char t) const
+{
+ return t;
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<unsigned char>::operator () (unsigned char t) const
+{
+ return t;
+}
+
+#if 0
+ACE_INLINE unsigned long
+ACE_Hash<ACE_INT16>::operator () (ACE_INT16 t) const
+{
+ return t;
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<ACE_UINT16>::operator () (ACE_UINT16 t) const
+{
+ return t;
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<ACE_INT32>::operator () (ACE_INT32 t) const
+{
+ return static_cast<unsigned long> (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<ACE_UINT32>::operator () (ACE_UINT32 t) const
+{
+ return t;
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<ACE_UINT64>::operator () (ACE_UINT64 t) const
+{
+#if (ACE_SIZEOF_LONG == 4)
+ return ACE_U64_TO_U32 (t);
+#else
+ return static_cast<unsigned long> (t);
+#endif /* ACE_SIZEOF_LONG */
+}
+#endif
+
+ACE_INLINE unsigned long
+ACE_Hash<short>::operator () (short t) const
+{
+ return static_cast<unsigned long> (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<unsigned short>::operator () (unsigned short t) const
+{
+ return static_cast<unsigned long> (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<int>::operator () (int t) const
+{
+ return static_cast<unsigned long> (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<unsigned int>::operator () (unsigned int t) const
+{
+ return static_cast<unsigned long> (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<long>::operator () (long t) const
+{
+ return static_cast<unsigned long> (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<unsigned long>::operator () (unsigned long t) const
+{
+ return t;
+}
+
+// This #if needs to match the one in Functor.h
+#if !defined (ACE_LACKS_LONGLONG_T) && (ACE_SIZEOF_LONG < 8)
+ACE_INLINE unsigned long
+ACE_Hash<ACE_INT64>::operator () (ACE_INT64 t) const
+{
+ return static_cast<unsigned long> (t);
+}
+#endif /* !ACE_LACKS_LONGLONG_T && ACE_SIZEOF_LONG < 8 */
+
+#if (ACE_SIZEOF_LONG < 8)
+ACE_INLINE unsigned long
+ACE_Hash<ACE_UINT64>::operator () (const ACE_UINT64 &t) const
+{
+#if (ACE_SIZEOF_LONG == 4)
+ return ACE_U64_TO_U32 (t);
+#else
+ return static_cast<unsigned long> (t);
+#endif /* ACE_SIZEOF_LONG */
+}
+#endif /* !ACE_LACKS_UNSIGNEDLONGLONG_T */
+
+ACE_INLINE unsigned long
+ACE_Hash<const char *>::operator () (const char *t) const
+{
+ return ACE::hash_pjw (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<char *>::operator () (const char *t) const
+{
+ return ACE::hash_pjw (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<void *>::operator () (const void *t) const
+{
+ return static_cast<unsigned long> (reinterpret_cast<uintptr_t> (t));
+}
+
+/***********************************************************************/
+ACE_INLINE int
+ACE_Equal_To<const char *>::operator () (const char *lhs, const char *rhs) const
+{
+ return !ACE_OS::strcmp (lhs, rhs);
+}
+
+ACE_INLINE int
+ACE_Equal_To<char *>::operator () (const char *lhs, const char *rhs) const
+{
+ return !ACE_OS::strcmp (lhs, rhs);
+}
+
+ACE_INLINE int
+ACE_Equal_To<ACE_UINT16>::operator () (const ACE_UINT16 lhs, const ACE_UINT16 rhs) const
+{
+ return (lhs == rhs);
+}
+
+ACE_INLINE int
+ACE_Equal_To<ACE_INT16>::operator () (const ACE_INT16 lhs, const ACE_INT16 rhs) const
+{
+ return (lhs == rhs);
+}
+
+ACE_INLINE int
+ACE_Equal_To<ACE_UINT32>::operator () (const ACE_UINT32 lhs, const ACE_UINT32 rhs) const
+{
+ return (lhs == rhs);
+}
+
+ACE_INLINE int
+ACE_Equal_To<ACE_INT32>::operator () (const ACE_INT32 lhs, const ACE_INT32 rhs) const
+{
+ return (lhs == rhs);
+}
+
+ACE_INLINE int
+ACE_Equal_To<ACE_UINT64>::operator () (const ACE_UINT64 lhs, const ACE_UINT64 rhs) const
+{
+ return (lhs == rhs);
+}
+
+/****************************************************************************/
+ACE_INLINE int
+ACE_Less_Than<const char *>::operator () (const char *lhs, const char *rhs) const
+{
+ return (ACE_OS::strcmp (lhs, rhs) < 0) ? 1 : 0;
+}
+
+ACE_INLINE int
+ACE_Less_Than<char *>::operator () (const char *lhs, const char *rhs) const
+{
+ return (ACE_OS::strcmp (lhs, rhs) < 0) ? 1 : 0;
+}
+
+
+#if defined (ACE_HAS_WCHAR)
+
+ACE_INLINE unsigned long
+ACE_Hash<const wchar_t *>::operator () (const wchar_t *t) const
+{
+ return ACE::hash_pjw (t);
+}
+
+ACE_INLINE unsigned long
+ACE_Hash<wchar_t *>::operator () (const wchar_t *t) const
+{
+ return ACE::hash_pjw (t);
+}
+
+ACE_INLINE int
+ACE_Equal_To<const wchar_t *>::operator () (const wchar_t *lhs,
+ const wchar_t *rhs) const
+{
+ return !ACE_OS::strcmp (lhs, rhs);
+}
+
+ACE_INLINE int
+ACE_Equal_To<wchar_t *>::operator () (const wchar_t *lhs,
+ const wchar_t *rhs) const
+{
+ return !ACE_OS::strcmp (lhs, rhs);
+}
+
+ACE_INLINE int
+ACE_Less_Than<const wchar_t *>::operator () (const wchar_t *lhs, const wchar_t *rhs) const
+{
+ return (ACE_OS::strcmp (lhs, rhs) < 0) ? 1 : 0;
+}
+
+ACE_INLINE int
+ACE_Less_Than<wchar_t *>::operator () (const wchar_t *lhs, const wchar_t *rhs) const
+{
+ return (ACE_OS::strcmp (lhs, rhs) < 0) ? 1 : 0;
+}
+
+#endif // ACE_HAS_WCHAR
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Functor_String.cpp b/ACE/ace/Functor_String.cpp
new file mode 100644
index 00000000000..5ba0fb8f4eb
--- /dev/null
+++ b/ACE/ace/Functor_String.cpp
@@ -0,0 +1,7 @@
+#include "ace/Functor_String.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Functor_String.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Functor, "$Id$")
diff --git a/ACE/ace/Functor_String.h b/ACE/ace/Functor_String.h
new file mode 100644
index 00000000000..1e742251a98
--- /dev/null
+++ b/ACE/ace/Functor_String.h
@@ -0,0 +1,141 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Functor_String.h
+ *
+ * $Id$
+ *
+ * Class template specializations for ACE_*String types implementing
+ * function objects that are used in various places in ATC. They
+ * could be placed in Functor.h. But we don't want to couple string
+ * types to the rest of ACE+TAO. Hence they are placed in a seperate
+ * file.
+ */
+//==========================================================================
+#ifndef ACE_FUNCTOR_STRING_H
+#define ACE_FUNCTOR_STRING_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/ACE_export.h"
+#include "ace/SStringfwd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+////////////////////////////////////////////////////////////
+// STL-style Functor Classes and Template Specializations //
+////////////////////////////////////////////////////////////
+
+// Forward declaration since we are going to specialize that template
+// here. The template itself requires this file so every user of the
+// template should also see the specialization.
+template <class TYPE> class ACE_Hash;
+template <class TYPE> class ACE_Equal_To;
+template <class TYPE> class ACE_Less_Than;
+
+/**
+ * @class ACE_Equal_To<ACE_CString>
+ *
+ * @brief Function object for determining whether two ACE_CStrings are
+ * equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<ACE_CString>
+{
+public:
+ int operator () (const ACE_CString &lhs,
+ const ACE_CString &rhs) const;
+};
+
+
+/**
+ * @class ACE_Hash<ACE_CString>
+ *
+ * @brief Function object for hashing a ACE_CString
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_CString>
+{
+public:
+ /// Calls ACE::hash_pjw
+ unsigned long operator () (const ACE_CString &lhs) const;
+};
+
+
+/**
+ * @class ACE_Less_Than<ACE_CString>
+ *
+ * @brief Function object for determining whether the first const string
+ * is less than the second const string.
+ */
+template<>
+class ACE_Export ACE_Less_Than<ACE_CString>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const ACE_CString &lhs,
+ const ACE_CString &rhs) const;
+};
+
+
+#if defined (ACE_USES_WCHAR)
+
+/**
+ * @class ACE_Equal_To<ACE_WString>
+ *
+ * @brief Function object for determining whether two ACE_CStrings are
+ * equal.
+ */
+template<>
+class ACE_Export ACE_Equal_To<ACE_WString>
+{
+public:
+ int operator () (const ACE_WString &lhs,
+ const ACE_WString &rhs) const;
+};
+
+
+/**
+ * @class ACE_Hash<ACE_WString>
+ *
+ * @brief Function object for hashing a ACE_WString
+ */
+template<>
+class ACE_Export ACE_Hash<ACE_WString>
+{
+public:
+ /// Calls ACE::hash_pjw
+ unsigned long operator () (const ACE_WString &lhs) const;
+};
+
+/**
+ * @class ACE_Less_Than<ACE_WString>
+ *
+ * @brief Function object for determining whether the first const string
+ * is less than the second const string.
+ */
+template<>
+class ACE_Export ACE_Less_Than<ACE_WString>
+{
+public:
+ /// Simply calls ACE_OS::strcmp
+ int operator () (const ACE_WString &lhs,
+ const ACE_WString &rhs) const;
+};
+
+#endif /*ACE_USES_WCHAR*/
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Functor_String.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /*ACE_FUNCTOR_STRING_H*/
diff --git a/ACE/ace/Functor_String.inl b/ACE/ace/Functor_String.inl
new file mode 100644
index 00000000000..82e8775a718
--- /dev/null
+++ b/ACE/ace/Functor_String.inl
@@ -0,0 +1,56 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/ACE.h"
+#include "ace/String_Base.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE unsigned long
+ACE_Hash<ACE_CString>::operator () (const ACE_CString &t) const
+{
+ return t.hash ();
+}
+
+
+ACE_INLINE int
+ACE_Equal_To<ACE_CString>::operator () (const ACE_CString &lhs,
+ const ACE_CString &rhs) const
+{
+ return lhs == rhs;
+}
+
+ACE_INLINE int
+ACE_Less_Than<ACE_CString>::operator () (const ACE_CString &lhs,
+ const ACE_CString &rhs) const
+{
+ return (lhs < rhs);
+}
+
+
+#if defined (ACE_USES_WCHAR)
+ACE_INLINE unsigned long
+ACE_Hash<ACE_WString>::operator () (const ACE_WString &t) const
+{
+ return t.hash ();
+}
+
+
+ACE_INLINE int
+ACE_Equal_To<ACE_WString>::operator () (const ACE_WString &lhs,
+ const ACE_WString &rhs) const
+{
+ return lhs == rhs;
+}
+
+ACE_INLINE int
+ACE_Less_Than<ACE_WString>::operator () (const ACE_WString &lhs,
+ const ACE_WString &rhs) const
+{
+ return (lhs < rhs);
+}
+
+#endif /*ACE_USES_WCHAR*/
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Functor_T.cpp b/ACE/ace/Functor_T.cpp
new file mode 100644
index 00000000000..53e8f170fc1
--- /dev/null
+++ b/ACE/ace/Functor_T.cpp
@@ -0,0 +1,49 @@
+// $Id$
+
+#ifndef ACE_FUNCTOR_T_CPP
+#define ACE_FUNCTOR_T_CPP
+
+#include "ace/Functor_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Functor_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Command_Callback)
+
+///////////////////////////////////
+// GOF Command Pattern Templates //
+///////////////////////////////////
+
+// Constructor.
+
+template <class RECEIVER, class ACTION>
+ACE_Command_Callback<RECEIVER, ACTION>::ACE_Command_Callback (RECEIVER &recvr,
+ ACTION action)
+ : receiver_ (recvr),
+ action_ (action)
+{
+}
+
+template <class RECEIVER, class ACTION>
+ACE_Command_Callback<RECEIVER, ACTION>::~ACE_Command_Callback (void)
+{
+}
+
+// Invokes an operation.
+
+template <class RECEIVER, class ACTION> int
+ACE_Command_Callback<RECEIVER, ACTION>::execute (void *arg)
+{
+ return (receiver_.*action_) (arg);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_FUNCTOR_T_CPP */
diff --git a/ACE/ace/Functor_T.h b/ACE/ace/Functor_T.h
new file mode 100644
index 00000000000..554820e3c0b
--- /dev/null
+++ b/ACE/ace/Functor_T.h
@@ -0,0 +1,158 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Functor_T.h
+ *
+ * $Id$
+ *
+ * Templatized classes for implementing function objects that are
+ * used in various places in ACE. There are currently two major
+ * categories of function objects in ACE: GOF Command Pattern
+ * objects, and STL-style functors for comparison of container
+ * elements. The command objects are invoked via an <execute>
+ * method, while the STL-style functors are invoked via an
+ * <operator()> method.
+ *
+ *
+ * @author Chris Gill <cdgill@cs.wustl.edu>
+ * @author Based on Command Pattern implementations originally done by
+ * @author Carlos O'Ryan <coryan@cs.wustl.edu>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+ * @author and on STL-style functor implementations originally done by
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_FUNCTOR_T_H
+#define ACE_FUNCTOR_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Functor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Functor_String.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+///////////////////////////////////
+// GOF Command Pattern Templates //
+///////////////////////////////////
+
+/**
+ * @class ACE_Command_Callback
+ *
+ * @brief Defines a class template that allows us to invoke a GOF
+ * command style callback to an object without knowing anything
+ * about the object except its type.
+ *
+ * This class declares an interface to execute operations,
+ * binding a RECEIVER object with an ACTION. The RECEIVER knows
+ * how to implement the operation. A class can invoke operations
+ * without knowing anything about it, or how it was implemented.
+ */
+template <class RECEIVER, class ACTION>
+class ACE_Command_Callback : public ACE_Command_Base
+{
+public:
+ /// Constructor: sets the <receiver_> of the Command to recvr, and the
+ /// <action_> of the Command to <action>.
+ ACE_Command_Callback (RECEIVER &recvr, ACTION action);
+
+ /// Virtual destructor.
+ virtual ~ACE_Command_Callback (void);
+
+ /// Invokes the method <action_> from the object <receiver_>.
+ virtual int execute (void *arg = 0);
+
+private:
+ /// Object where the method resides.
+ RECEIVER &receiver_;
+
+ /// Method that is going to be invoked.
+ ACTION action_;
+};
+
+/////////////////////////////////
+// STL-style Functor Templates //
+/////////////////////////////////
+
+/**
+ * @class ACE_Hash
+ *
+ * @brief Function object for hashing
+ */
+template <class TYPE>
+class ACE_Hash
+{
+public:
+ /// Simply calls t.hash ()
+ unsigned long operator () (const TYPE &t) const;
+};
+
+/**
+ * @class ACE_Pointer_Hash
+ *
+ * @brief Function object for hashing pointers
+ */
+template <class TYPE>
+class ACE_Pointer_Hash
+{
+public:
+ /// Simply returns t.
+ unsigned long operator () (TYPE t) const;
+};
+
+/**
+ * @class ACE_Equal_To
+ *
+ * @brief Function object for comparing two objects of
+ * the given type for equality.
+ */
+template <class TYPE>
+class ACE_Equal_To
+{
+public:
+ /// Simply calls operator==
+ bool operator () (const TYPE &lhs,
+ const TYPE &rhs) const;
+};
+
+/**
+ * @class ACE_Less_Than
+ *
+ * @brief Function object for determining whether the first object of
+ * the given type is less than the second object of the same
+ * type.
+ */
+template <class TYPE>
+class ACE_Less_Than
+{
+public:
+ /// Simply calls operator<
+ bool operator () (const TYPE &lhs,
+ const TYPE &rhs) const;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Functor_T.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Functor_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Functor_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_FUNCTOR_T_H */
diff --git a/ACE/ace/Functor_T.inl b/ACE/ace/Functor_T.inl
new file mode 100644
index 00000000000..6441c091b76
--- /dev/null
+++ b/ACE/ace/Functor_T.inl
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TYPE> ACE_INLINE unsigned long
+ACE_Hash<TYPE>::operator () (const TYPE &t) const
+{
+ return t.hash ();
+}
+
+template <class TYPE> ACE_INLINE unsigned long
+ACE_Pointer_Hash<TYPE>::operator () (TYPE t) const
+{
+#if defined (ACE_WIN64)
+ // The cast below is legit... we only want a hash, and need not convert
+ // the hash back to a pointer.
+# pragma warning(push)
+# pragma warning(disable : 4311) /* Truncate pointer to unsigned long */
+#endif /* ACE_WIN64 */
+ return reinterpret_cast<unsigned long> (t);
+#if defined (ACE_WIN64)
+# pragma warning(pop)
+#endif /* ACE_WIN64 */
+}
+
+template <class TYPE> ACE_INLINE bool
+ACE_Equal_To<TYPE>::operator () (const TYPE &lhs,
+ const TYPE &rhs) const
+{
+ return lhs == rhs;
+}
+
+template <class TYPE> ACE_INLINE bool
+ACE_Less_Than<TYPE>::operator () (const TYPE &lhs,
+ const TYPE &rhs) const
+{
+ return lhs < rhs;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Future.cpp b/ACE/ace/Future.cpp
new file mode 100644
index 00000000000..97358b7f834
--- /dev/null
+++ b/ACE/ace/Future.cpp
@@ -0,0 +1,436 @@
+ // $Id$
+
+#ifndef ACE_FUTURE_CPP
+#define ACE_FUTURE_CPP
+
+#include "ace/Future.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_RCSID (ace, Future, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+# include "ace/Guard_T.h"
+# include "ace/Recursive_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T>
+ACE_Future_Holder<T>::ACE_Future_Holder (void)
+{
+}
+
+template <class T>
+ACE_Future_Holder<T>::ACE_Future_Holder (const ACE_Future<T> &item)
+ : item_ (item)
+{
+}
+
+template <class T>
+ACE_Future_Holder<T>::~ACE_Future_Holder (void)
+{
+}
+
+template <class T>
+ACE_Future_Observer<T>::ACE_Future_Observer (void)
+{
+}
+
+template <class T>
+ACE_Future_Observer<T>::~ACE_Future_Observer (void)
+{
+}
+
+// Dump the state of an object.
+
+template <class T> void
+ACE_Future_Rep<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG,
+ "ref_count_ = %d\n",
+ (int) this->ref_count_));
+ ACE_DEBUG ((LM_INFO,"value_: \n"));
+ if (this->value_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (NON-NULL)\n")));
+ else
+ //FUZZ: disable check_for_NULL
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (NULL)\n")));
+ //FUZZ: enable check_for_NULL
+
+ ACE_DEBUG ((LM_INFO,"value_ready_: \n"));
+ this->value_ready_.dump ();
+ ACE_DEBUG ((LM_INFO,"value_ready_mutex_: \n"));
+ this->value_ready_mutex_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T> ACE_Future_Rep<T> *
+ACE_Future_Rep<T>::internal_create (void)
+{
+ ACE_Future_Rep<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_Future_Rep<T> (),
+ 0);
+ return temp;
+}
+
+template <class T> ACE_Future_Rep<T> *
+ACE_Future_Rep<T>::create (void)
+{
+ // Yes set ref count to zero.
+ ACE_Future_Rep<T> *temp = internal_create ();
+#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 T> ACE_Future_Rep<T> *
+ACE_Future_Rep<T>::attach (ACE_Future_Rep<T>*& rep)
+{
+ ACE_ASSERT (rep != 0);
+ // Use value_ready_mutex_ for both condition and ref count management
+ ACE_MT (ACE_Guard<ACE_Recursive_Thread_Mutex> r_mon (rep->value_ready_mutex_));
+ ++rep->ref_count_;
+ return rep;
+}
+
+template <class T> void
+ACE_Future_Rep<T>::detach (ACE_Future_Rep<T>*& rep)
+{
+ ACE_ASSERT (rep != 0);
+ // Use value_ready_mutex_ for both condition and ref count management
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, r_mon, rep->value_ready_mutex_));
+
+ if (rep->ref_count_-- == 0)
+ {
+ ACE_MT (r_mon.release ());
+ // We do not need the lock when deleting the representation.
+ // There should be no side effects from deleting rep and we don
+ // not want to release a deleted mutex.
+ delete rep;
+ }
+}
+
+template <class T> void
+ACE_Future_Rep<T>::assign (ACE_Future_Rep<T>*& rep, ACE_Future_Rep<T>* new_rep)
+{
+ ACE_ASSERT (rep != 0);
+ ACE_ASSERT (new_rep != 0);
+ // Use value_ready_mutex_ for both condition and ref count management
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, r_mon, rep->value_ready_mutex_));
+
+ ACE_Future_Rep<T>* old = rep;
+ rep = new_rep;
+
+ // detached old last for exception safety
+ if (old->ref_count_-- == 0)
+ {
+ ACE_MT (r_mon.release ());
+ // We do not need the lock when deleting the representation.
+ // There should be no side effects from deleting rep and we don
+ // not want to release a deleted mutex.
+ delete old;
+ }
+}
+
+template <class T>
+ACE_Future_Rep<T>::ACE_Future_Rep (void)
+ : value_ (0),
+ ref_count_ (0),
+ value_ready_ (value_ready_mutex_)
+{
+}
+
+template <class T>
+ACE_Future_Rep<T>::~ACE_Future_Rep (void)
+{
+ delete this->value_;
+}
+
+template <class T> int
+ACE_Future_Rep<T>::ready (void) const
+{
+ return this->value_ != 0;
+}
+
+template <class T> int
+ACE_Future_Rep<T>::set (const T &r,
+ ACE_Future<T> &caller)
+{
+ // If the value is already produced, ignore it...
+ if (this->value_ == 0)
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon,
+ this->value_ready_mutex_,
+ -1));
+ // Otherwise, create a new result value. Note the use of the
+ // Double-checked locking pattern to avoid multiple allocations.
+
+ if (this->value_ == 0) // Still no value, so proceed
+ {
+ ACE_NEW_RETURN (this->value_,
+ T (r),
+ -1);
+
+ // Remove and notify all subscribed observers.
+ typename OBSERVER_COLLECTION::iterator iterator =
+ this->observer_collection_.begin ();
+
+ typename OBSERVER_COLLECTION::iterator end =
+ this->observer_collection_.end ();
+
+ while (iterator != end)
+ {
+ OBSERVER *observer = *iterator++;
+ observer->update (caller);
+ }
+
+ // Signal all the waiting threads.
+ return this->value_ready_.broadcast ();
+ }
+ // Destructor releases the lock.
+ }
+ return 0;
+}
+
+template <class T> int
+ACE_Future_Rep<T>::get (T &value,
+ ACE_Time_Value *tv) const
+{
+ // If the value is already produced, return it.
+ if (this->value_ == 0)
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ this->value_ready_mutex_,
+ -1));
+ // If the value is not yet defined we must block until the
+ // producer writes to it.
+
+ while (this->value_ == 0)
+ // Perform a timed wait.
+ if (this->value_ready_.wait (tv) == -1)
+ return -1;
+
+ // Destructor releases the lock.
+ }
+
+ value = *this->value_;
+ return 0;
+}
+
+template <class T> int
+ACE_Future_Rep<T>::attach (ACE_Future_Observer<T> *observer,
+ ACE_Future<T> &caller)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->value_ready_mutex_, -1));
+
+ // Otherwise, create a new result value. Note the use of the
+ // Double-checked locking pattern to avoid corrupting the list.
+
+ int result = 1;
+
+ // If the value is already produced, then notify observer
+ if (this->value_ == 0)
+ result = this->observer_collection_.insert (observer);
+ else
+ observer->update (caller);
+
+ return result;
+}
+
+template <class T> int
+ACE_Future_Rep<T>::detach (ACE_Future_Observer<T> *observer)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->value_ready_mutex_, -1));
+
+ // Remove all occurrences of the specified observer from this
+ // objects hash map.
+ return this->observer_collection_.remove (observer);
+}
+
+template <class T>
+ACE_Future_Rep<T>::operator T ()
+{
+ // If the value is already produced, return it.
+ if (this->value_ == 0)
+ {
+ // Constructor of ace_mon acquires the mutex.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->value_ready_mutex_, 0));
+
+ // If the value is not yet defined we must block until the
+ // producer writes to it.
+
+ // Wait ``forever.''
+
+ while (this->value_ == 0)
+ if (this->value_ready_.wait () == -1)
+ // What to do in this case since we've got to indicate
+ // failure somehow? Exceptions would be nice, but they're
+ // not portable...
+ return 0;
+
+ // Destructor releases the mutex
+ }
+
+ return *this->value_;
+}
+
+template <class T>
+ACE_Future<T>::ACE_Future (void)
+ : future_rep_ (FUTURE_REP::create ())
+{
+}
+
+template <class T>
+ACE_Future<T>::ACE_Future (const ACE_Future<T> &r)
+ : future_rep_ (FUTURE_REP::attach (((ACE_Future<T> &) r).future_rep_))
+{
+}
+
+template <class T>
+ACE_Future<T>::ACE_Future (const T &r)
+ : future_rep_ (FUTURE_REP::create ())
+{
+ this->future_rep_->set (r, *this);
+}
+
+template <class T>
+ACE_Future<T>::~ACE_Future (void)
+{
+ FUTURE_REP::detach (future_rep_);
+}
+
+template <class T> bool
+ACE_Future<T>::operator== (const ACE_Future<T> &r) const
+{
+ return r.future_rep_ == this->future_rep_;
+}
+
+template <class T> bool
+ACE_Future<T>::operator!= (const ACE_Future<T> &r) const
+{
+ return r.future_rep_ != this->future_rep_;
+}
+
+template <class T> int
+ACE_Future<T>::cancel (const T &r)
+{
+ this->cancel ();
+ return this->future_rep_->set (r,
+ *this);
+}
+
+template <class T> int
+ACE_Future<T>::cancel (void)
+{
+ // If this ACE_Future is already attached to a ACE_Future_Rep,
+ // detach it (maybe delete the ACE_Future_Rep).
+ FUTURE_REP::assign (this->future_rep_,
+ FUTURE_REP::create ());
+ return 0;
+}
+
+template <class T> int
+ACE_Future<T>::set (const T &r)
+{
+ // Give the pointer to the result to the ACE_Future_Rep.
+ return this->future_rep_->set (r,
+ *this);
+}
+
+template <class T> int
+ACE_Future<T>::ready (void) const
+{
+ // We're ready if the ACE_Future_rep is ready...
+ return this->future_rep_->ready ();
+}
+
+template <class T> int
+ACE_Future<T>::get (T &value,
+ ACE_Time_Value *tv) const
+{
+ // We return the ACE_Future_rep.
+ return this->future_rep_->get (value, tv);
+}
+
+template <class T> int
+ACE_Future<T>::attach (ACE_Future_Observer<T> *observer)
+{
+ return this->future_rep_->attach (observer, *this);
+}
+
+template <class T> int
+ACE_Future<T>::detach (ACE_Future_Observer<T> *observer)
+{
+ return this->future_rep_->detach (observer);
+}
+
+template <class T>
+ACE_Future<T>::operator T ()
+{
+ // note that this will fail (and COREDUMP!)
+ // if future_rep_ == 0 !
+ //
+ // but...
+ // this is impossible unless somebody is so stupid to
+ // try something like this:
+ //
+ // Future<T> futT;
+ // T t;
+ // t = futT;
+
+ // perform type conversion on Future_Rep.
+ return *future_rep_;
+}
+
+template <class T> void
+ACE_Future<T>::operator = (const ACE_Future<T> &rhs)
+{
+ // assignment:
+ //
+ // bind <this> to the same <ACE_Future_Rep> as <r>.
+
+ // This will work if &r == this, by first increasing the ref count
+ ACE_Future<T> &r = (ACE_Future<T> &) rhs;
+ FUTURE_REP::assign (this->future_rep_,
+ FUTURE_REP::attach (r.future_rep_));
+}
+
+template <class T> void
+ACE_Future<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_BEGIN_DUMP, this));
+
+ if (this->future_rep_)
+ this->future_rep_->dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T> ACE_Future_Rep<T> *
+ACE_Future<T>::get_rep ()
+{
+ return this->future_rep_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
+
+#endif /* ACE_FUTURE_CPP */
diff --git a/ACE/ace/Future.h b/ACE/ace/Future.h
new file mode 100644
index 00000000000..c172b0fd9ac
--- /dev/null
+++ b/ACE/ace/Future.h
@@ -0,0 +1,387 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Future.h
+ *
+ * $Id$
+ *
+ * @author Andres Kruse <Andres.Kruse@cern.ch>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Per Andersson <Per.Andersson@hfera.ericsson.se> and
+ * @author John Tucker <johnny_tucker@yahoo.com>
+ */
+//=============================================================================
+
+#ifndef ACE_FUTURE_H
+#define ACE_FUTURE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Unbounded_Set.h"
+#include "ace/Strategies_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Condition_Recursive_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl.
+template <class T> class ACE_Future_Holder;
+template <class T> class ACE_Future_Observer;
+template <class T> class ACE_Future_Rep;
+template <class T> class ACE_Future;
+
+/**
+ * @class ACE_Future_Holder
+ *
+ * @brief Implementation of object that holds an ACE_Future.
+ */
+template <class T>
+class ACE_Future_Holder
+{
+public:
+ ACE_Future_Holder (const ACE_Future<T> &future);
+ ~ACE_Future_Holder (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ ACE_Future<T> item_;
+
+protected:
+ ACE_Future_Holder (void);
+};
+
+/**
+ * @class ACE_Future_Observer
+ *
+ * @brief ACE_Future_Observer<T>
+ *
+ * An ACE_Future_Observer object implements an object that is
+ * subscribed with an ACE_Future object so that it may be notified
+ * when the value of the ACE_Future object is written to by a writer
+ * thread. It uses the Observer pattern.
+ */
+template <class T>
+class ACE_Future_Observer
+{
+public:
+ /// Destructor
+ virtual ~ACE_Future_Observer (void);
+
+ /// Called by the ACE_Future in which we are subscribed to when
+ /// its value is written to.
+ virtual void update (const ACE_Future<T> &future) = 0;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+protected:
+
+ /// Constructor
+ ACE_Future_Observer (void);
+};
+
+/**
+ * @class ACE_Future_Rep
+ *
+ * @internal
+ *
+ * @brief ACE_Future_Rep<T>
+ *
+ * An ACE_Future_Rep<T> object encapsules a pointer to an object
+ * of class T which is the result of an asynchronous method
+ * invocation. It is pointed to by ACE_Future<T> object[s] and
+ * only accessible through them.
+ */
+template <class T>
+class ACE_Future_Rep
+{
+private:
+ friend class ACE_Future<T>;
+
+ /**
+ * Set the result value. The specified <caller> represents the
+ * future that invoked this <set> method, which is used to notify
+ * the list of future observers. Returns 0 for success, -1 on error.
+ * This function only has an effect the first time it is called for
+ * the object. Subsequent calls return 0 (success) but have no effect.
+ */
+ int set (const T &r,
+ ACE_Future<T> &caller);
+
+ /// Wait up to @a tv time to get the @a value. Note that @a tv must be
+ /// specified in absolute time rather than relative time.
+ int get (T &value,
+ ACE_Time_Value *tv) const;
+
+ /**
+ * Attaches the specified observer to a subject (i.e., the ACE_Future_Rep).
+ * The update method of the specified subject will be invoked with a copy of
+ * the written-to ACE_Future as input when the result gets set.
+ *
+ * Returns 0 if the observer is successfully attached, 1 if the
+ * observer is already attached, and -1 if failures occur.
+ */
+ int attach (ACE_Future_Observer<T> *observer,
+ ACE_Future<T> &caller);
+
+ /**
+ * Detaches the specified observer from a subject (i.e., the ACE_Future_Rep).
+ * The update method of the specified subject will not be invoked when the
+ * ACE_Future_Reps result gets set. Returns 1 if the specified observer was
+ * actually attached to the subject prior to this call and 0 if was not.
+ *
+ * Returns 0 if the observer was successfully detached, and -1 if the
+ * observer was not attached in the first place.
+ */
+ int detach (ACE_Future_Observer<T> *observer);
+
+ /**
+ * Type conversion. will block forever until the result is
+ * available. Note that this method is going away in a subsequent
+ * release since it doesn't distinguish between failure results and
+ * success results (exceptions should be used, but they aren't
+ * portable...). The <get> method should be used instead since it
+ * separates the error value from the result, and also permits
+ * timeouts.
+ */
+ operator T ();
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // = Encapsulate reference count and object lifetime of instances.
+
+ // These methods must go after the others to work around a bug with
+ // Borland's C++ Builder...
+
+ /// Allocate a new ACE_Future_Rep<T> instance, returning NULL if it
+ /// cannot be created.
+ static ACE_Future_Rep<T> *internal_create (void);
+
+ /// Create a ACE_Future_Rep<T> and initialize the reference count.
+ static ACE_Future_Rep<T> *create (void);
+
+ /**
+ * Increase the reference count and return argument. Uses the
+ * attribute "value_ready_mutex_" to synchronize reference count
+ * updating.
+ *
+ * Precondition (rep != 0).
+ */
+ static ACE_Future_Rep<T> *attach (ACE_Future_Rep<T> *&rep);
+
+ /**
+ * Decreases the reference count and deletes rep if there are no
+ * more references to rep.
+ *
+ * Precondition (rep != 0)
+ */
+ static void detach (ACE_Future_Rep<T> *&rep);
+
+ /**
+ * Decreases the rep's reference count and deletes rep if there
+ * are no more references to rep. Then assigns new_rep to rep.
+ *
+ * Precondition (rep != 0 && new_rep != 0)
+ */
+ static void assign (ACE_Future_Rep<T> *&rep, ACE_Future_Rep<T> *new_rep);
+
+ /// Is result available?
+ int ready (void) const;
+
+ /// Pointer to the result.
+ T *value_;
+
+ /// Reference count.
+ int ref_count_;
+
+ typedef ACE_Future_Observer<T> OBSERVER;
+
+ typedef ACE_Unbounded_Set<OBSERVER *> OBSERVER_COLLECTION;
+
+ /// Keep a list of ACE_Future_Observers unread by client's reader thread.
+ OBSERVER_COLLECTION observer_collection_;
+
+ // = Condition variable and mutex that protect the <value_>.
+ mutable ACE_Recursive_Thread_Mutex value_ready_mutex_;
+ mutable ACE_Condition_Recursive_Thread_Mutex value_ready_;
+
+private:
+
+ ACE_Future_Rep (void);
+
+protected:
+
+ ~ACE_Future_Rep (void);
+
+};
+
+/**
+ * @class ACE_Future
+ *
+ * @brief This class implements a ``single write, multiple read''
+ * pattern that can be used to return results from asynchronous
+ * method invocations.
+ */
+template <class T>
+class ACE_Future
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Future (void);
+
+ /// Copy constructor binds @a this and @a r to the same
+ /// ACE_Future_Rep. An ACE_Future_Rep is created if necessary.
+ ACE_Future (const ACE_Future<T> &r);
+
+ /// Constructor that initialises an ACE_Future to point to the
+ /// result @a r immediately.
+ ACE_Future (const T &r);
+
+ /// Destructor.
+ ~ACE_Future (void);
+
+ /// Assignment operator that binds @a this and @a r to the same
+ /// ACE_Future_Rep. An ACE_Future_Rep is created if necessary.
+ void operator = (const ACE_Future<T> &r);
+
+ /// Cancel an ACE_Future and assign the value @a r. It is used if a
+ /// client does not want to wait for the value to be produced.
+ int cancel (const T &r);
+
+ /**
+ * Cancel an ACE_Future. Put the future into its initial
+ * state. Returns 0 on succes and -1 on failure. It is now possible
+ * to reuse the ACE_Future. But remember, the ACE_Future
+ * is now bound to a new ACE_Future_Rep.
+ */
+ int cancel (void);
+
+ /**
+ * Equality operator that returns @c true if both ACE_Future objects
+ * point to the same ACE_Future_Rep object.
+ *
+ * @note It also returns @c true if both objects have just been
+ * instantiated and not used yet.
+ */
+ bool operator == (const ACE_Future<T> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ bool operator != (const ACE_Future<T> &r) const;
+
+ /**
+ * Make the result available. Is used by the server thread to give
+ * the result to all waiting clients. Returns 0 for success, -1 on failure.
+ * This function only has an effect the first time it is called for
+ * the object (actually, the first time the underlying ACE_Future_Rep has a
+ * value assigned to it). Subsequent calls return 0 (success) but have no
+ * effect.
+ */
+ int set (const T &r);
+
+ /**
+ * Wait to get the object's value.
+ *
+ * @param value Receives the value of this ACE_Future when it is set.
+ * @param tv Pointer to an ACE_Time_Value containing the absolute
+ * time to wait until for the value to be set. If @a tv
+ * is 0, the call waits indefinitely for the value to be
+ * set, unless an error occurs.
+ *
+ * @retval 0 Success; @a value contains the value of the ACE_Future.
+ * @retval -1 Error; check ACE_OS::last_error() for an error code.
+ */
+ int get (T &value,
+ ACE_Time_Value *tv = 0) const;
+
+ /**
+ * @deprecated Note that this method is going away in a subsequent
+ * release since it doesn't distinguish between failure
+ * results and success results (exceptions should be
+ * used, but they aren't portable...).
+ * Type conversion, which obtains the result of the asynchronous
+ * method invocation. Will block forever. The get() method should be
+ * used instead since it separates the error value from the result,
+ * and also permits timeouts.
+ */
+ operator T ();
+
+ /// Check if the result is available.
+ int ready (void) const;
+
+ /**
+ * Attaches the specified observer to a subject (this ACE_Future).
+ * The update method of the specified subject will be invoked with a copy of
+ * the associated ACE_Future as input when the result gets set. If the
+ * result is already set when this method gets invoked, then the update
+ * method of the specified subject will be invoked immediately.
+ *
+ * @param observer The observer to attach to the subject.
+ *
+ * @retval 0 Success.
+ * @retval 1 The observer was already attached.
+ * @retval -1 Error; check ACE_OS::last_error() for an error code.
+ */
+ int attach (ACE_Future_Observer<T> *observer);
+
+ /**
+ * Detaches the specified observer from a subject (this ACE_Future).
+ * The update method of the specified subject will not be invoked when the
+ * ACE_Future_Rep result gets set.
+ *
+ * @param observer The observer to attach to the subject.
+ *
+ * @retval 0 The observer was successfully detached.
+ * @retval -1 Error, including the observer not attached prior
+ * to calling this method.
+ */
+ int detach (ACE_Future_Observer<T> *observer);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /**
+ * Get the underlying ACE_Future_Rep pointer. Note that this method should
+ * rarely, if ever, be used and that modifying the underlying
+ * ACE_Future_Rep should be done with extreme caution.
+ */
+ ACE_Future_Rep<T> *get_rep (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ // the ACE_Future_Rep
+ /// Protect operations on the <Future>.
+ typedef ACE_Future_Rep<T> FUTURE_REP;
+ FUTURE_REP *future_rep_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Future.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Future.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_FUTURE_H */
diff --git a/ACE/ace/Future_Set.cpp b/ACE/ace/Future_Set.cpp
new file mode 100644
index 00000000000..3d04fe9ed5d
--- /dev/null
+++ b/ACE/ace/Future_Set.cpp
@@ -0,0 +1,136 @@
+// $Id$
+
+#ifndef ACE_FUTURE_SET_CPP
+#define ACE_FUTURE_SET_CPP
+
+#include "ace/Future_Set.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_THREADS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T>
+ACE_Future_Set<T>::ACE_Future_Set (ACE_Message_Queue<ACE_SYNCH> *new_queue)
+ : delete_queue_ (false)
+{
+ if (new_queue)
+ this->future_notification_queue_ = new_queue;
+ else
+ {
+ ACE_NEW (this->future_notification_queue_,
+ ACE_Message_Queue<ACE_SYNCH>);
+ this->delete_queue_ = true;
+ }
+}
+
+template <class T>
+ACE_Future_Set<T>::~ACE_Future_Set (void)
+{
+ // Detach ourselves from all remaining futures, if any, in our map.
+ typename FUTURE_HASH_MAP::iterator iterator =
+ this->future_map_.begin ();
+
+ typename FUTURE_HASH_MAP::iterator end =
+ this->future_map_.end ();
+
+ for (;
+ iterator != end;
+ ++iterator)
+ {
+ FUTURE_HOLDER *future_holder = (*iterator).int_id_;
+ future_holder->item_.detach (this);
+ delete future_holder;
+ }
+
+ if (this->delete_queue_)
+ delete this->future_notification_queue_;
+}
+
+template <class T> int
+ACE_Future_Set<T>::is_empty () const
+{
+ return (((ACE_Future_Set<T>*)this)->future_map_.current_size () == 0 );
+}
+
+template <class T> int
+ACE_Future_Set<T>::insert (ACE_Future<T> &future)
+{
+ FUTURE_HOLDER *future_holder;
+ ACE_NEW_RETURN (future_holder,
+ FUTURE_HOLDER (future),
+ -1);
+
+ FUTURE_REP *future_rep = future.get_rep ();
+ int result = this->future_map_.bind (future_rep,
+ future_holder);
+
+ // If a new map entry was created, then attach to the future,
+ // otherwise we were already attached to the future or some error
+ // occurred so just delete the future holder.
+ if ( result == 0 )
+ // Attach ourself to the ACE_Futures list of observer
+ future.attach (this);
+ else
+ delete future_holder;
+
+ return result;
+}
+
+template <class T> void
+ACE_Future_Set<T>::update (const ACE_Future<T> &future)
+{
+ ACE_Message_Block *mb;
+ FUTURE &local_future = const_cast<ACE_Future<T> &> (future);
+
+ ACE_NEW (mb,
+ ACE_Message_Block ((char *) local_future.get_rep (), 0));
+
+ // Enqueue in priority order.
+ this->future_notification_queue_->enqueue (mb, 0);
+}
+
+template <class T> int
+ACE_Future_Set<T>::next_readable (ACE_Future<T> &future,
+ ACE_Time_Value *tv)
+{
+ if (this->is_empty ())
+ return 0;
+
+ ACE_Message_Block *mb = 0;
+ FUTURE_REP *future_rep = 0;
+
+ // Wait for a "readable future" signal from the message queue.
+ if (this->future_notification_queue_->dequeue_head (mb,
+ tv) != -1)
+ {
+ // Extract future rep from the message block.
+ future_rep = reinterpret_cast<FUTURE_REP *> (mb->base ());
+
+ // Delete the message block.
+ mb->release ();
+ }
+ else
+ return 0;
+
+ // Remove the hash map entry with the specified future rep from our map.
+ FUTURE_HOLDER *future_holder;
+ if (this->future_map_.find (future_rep,
+ future_holder) != -1)
+ {
+ future = future_holder->item_;
+ this->future_map_.unbind (future_rep);
+ delete future_holder;
+ return 1;
+ }
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
+#endif /* ACE_FUTURE_SET_CPP */
diff --git a/ACE/ace/Future_Set.h b/ACE/ace/Future_Set.h
new file mode 100644
index 00000000000..6e804248021
--- /dev/null
+++ b/ACE/ace/Future_Set.h
@@ -0,0 +1,146 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Future_Set.h
+ *
+ * $Id$
+ *
+ * @author John Tucker <jtucker@infoglide.com>
+ */
+//=============================================================================
+
+#ifndef ACE_FUTURE_SET_H
+#define ACE_FUTURE_SET_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Thread.h"
+#include "ace/Message_Queue.h"
+#include "ace/Future.h"
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Null_Mutex.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_THREADS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Future_Set
+ *
+ * @brief This class implements a mechanism which allows the values of
+ * a collection of ACE_Future objects to be accessed by reader threads
+ * as they become available. The caller(s) provide the ACE_Future_Set
+ * (i.e. the observer...) with the collection of ACE_Future objects
+ * (i.e. the subjects...) that are to be observed using the
+ * the ACE_Future_Set::insert() method. The caller(s) may then iterate
+ * over the collection in the order in which they become readable using
+ * the ACE_Future_Set::next_readable() method.
+ */
+template <class T>
+class ACE_Future_Set : public ACE_Future_Observer<T>
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Constructor.
+ ACE_Future_Set (ACE_Message_Queue<ACE_SYNCH> *future_notification_queue_ = 0);
+
+ /// Destructor.
+ ~ACE_Future_Set (void);
+
+ /**
+ * Return 1 if their are no ACE_Future objects left on its queue and
+ * 0 otherwise.
+ *
+ * When an ACE_Future_Set has no ACE_Future>subjects to observe it is
+ * empty. The ACE_Future_Set is in the empty state when either the caller(s)
+ * have retrieved every readable ACE_Future subject assigned the
+ * ACE_Future_Set via the ACE_Future_Set::next_readable() method,
+ * or when the ACE_Future_Set has not been assigned any subjects.
+ */
+ int is_empty (void) const;
+
+ /**
+ * Enqueus the given ACE_Future into this objects queue when it is
+ * readable.
+ *
+ * Returns 0 if the future is successfully inserted, 1 if the
+ * future is already inserted, and -1 if failures occur.
+ */
+ int insert (ACE_Future<T> &future);
+
+ /**
+ * Wait up to @a tv time to get the @a value. Note that @a tv must be
+ * specified in absolute time rather than relative time.); get the
+ * next ACE_Future that is readable. If @a tv = 0, the will block
+ * forever.
+ *
+ * If a readable future becomes available, then the input
+ * ACE_Future object param will be assigned with it and 1 will
+ * be returned. If the ACE_Future_Set is empty (i.e. see definition
+ * of ACE_Future_Set::is_empty()), then 0 is returned.
+ *
+ * When a readable ACE_Future object is retrieved via the
+ * ACE_Future_Set::next_readable() method, the ACE_Future_Set will
+ * remove that ACE_Future object from its list of subjects.
+ */
+ int next_readable (ACE_Future<T> &result,
+ ACE_Time_Value *tv = 0);
+
+ /// Called by the ACE_Future subject in which we are subscribed to
+ /// when its value is written to.
+ virtual void update (const ACE_Future<T> &future);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Future_Set<T> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Future_Set (const ACE_Future_Set<T> &))
+
+ typedef ACE_Future<T> FUTURE;
+
+ typedef ACE_Future_Rep<T> FUTURE_REP;
+
+ typedef ACE_Future_Holder<T> FUTURE_HOLDER;
+
+ typedef ACE_Pointer_Hash<FUTURE_REP *> FUTURE_REP_HASH;
+
+ typedef ACE_Equal_To<FUTURE_REP *> FUTURE_REP_COMPARE;
+
+ typedef ACE_Hash_Map_Manager_Ex<FUTURE_REP *,
+ FUTURE_HOLDER *,
+ FUTURE_REP_HASH,
+ FUTURE_REP_COMPARE,
+ ACE_Null_Mutex> FUTURE_HASH_MAP;
+
+ /// Map of <ACE_Futures>, subjects, which have not been written to by
+ /// client's writer thread.
+ FUTURE_HASH_MAP future_map_;
+
+ /// Message queue for notifying the reader thread of <ACE_Futures> which
+ /// have been written to by client's writer thread.
+ ACE_Message_Queue<ACE_SYNCH> *future_notification_queue_;
+
+ /// Keeps track of whether we need to delete the message queue.
+ bool delete_queue_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Future_Set.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Future_Set.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_HAS_THREADS */
+#include /**/ "ace/post.h"
+#endif /* ACE_FUTURE_SET_H */
diff --git a/ACE/ace/Get_Opt.cpp b/ACE/ace/Get_Opt.cpp
new file mode 100644
index 00000000000..be7be6fc8af
--- /dev/null
+++ b/ACE/ace/Get_Opt.cpp
@@ -0,0 +1,730 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Get_Opt.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/ACE.h"
+#include "ace/Log_Msg.h"
+#include "ace/SString.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID (ace,
+ Get_Opt,
+ "$Id$")
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Get_Opt)
+
+ACE_Get_Opt::ACE_Get_Opt (int argc,
+ ACE_TCHAR **argv,
+ const ACE_TCHAR *optstring,
+ int skip,
+ int report_errors,
+ int ordering,
+ int long_only)
+ : argc_ (argc),
+ argv_ (argv),
+ optind (skip),
+ opterr (report_errors),
+ optarg (0),
+ optstring_ (0),
+ long_only_ (long_only),
+ has_colon_ (0),
+ last_option_ (0),
+ nextchar_ (0),
+ optopt_ (0),
+ ordering_ (ordering),
+ nonopt_start_ (optind),
+ nonopt_end_ (optind),
+ long_option_ (0)
+{
+ ACE_TRACE ("ACE_Get_Opt::ACE_Get_Opt");
+
+ ACE_NEW (this->optstring_, ACE_TString (optstring));
+ ACE_NEW (this->last_option_, ACE_TString (ACE_TEXT ("")));
+
+ // First check to see if POSIXLY_CORRECT was set.
+ // Win32 is the only platform capable of wide-char env var.
+#if defined (ACE_WIN32)
+ const ACE_TCHAR *env_check = ACE_TEXT ("POSIXLY_CORRECT");
+#else
+ const char *env_check = "POSIXLY_CORRECT";
+#endif
+ if (ACE_OS::getenv (env_check) != 0)
+ this->ordering_ = REQUIRE_ORDER;
+
+ // Now, check to see if any or the following were passed at
+ // the begining of optstring: '+' same as POSIXLY_CORRECT;
+ // '-' turns off POSIXLY_CORRECT; or ':' which signifies we
+ // should return ':' if a parameter is missing for an option.
+ // We use a loop here, since a combination of "{+|-}:" in any
+ // order should be legal.
+ int done = 0;
+ int offset = 0;
+ while (!done)
+ {
+ switch (optstring[offset++])
+ {
+ case '+':
+ this->ordering_ = REQUIRE_ORDER;
+ break;
+ case '-':
+ this->ordering_ = RETURN_IN_ORDER;
+ break;
+ case ':':
+ this->has_colon_ = 1;
+ break;
+ default:
+ // Quit as soon as we see something else...
+ done = 1;
+ break;
+ }
+ }
+}
+
+ACE_Get_Opt::~ACE_Get_Opt (void)
+{
+ ACE_TRACE ("ACE_Get_Opt::~ACE_Get_Opt");
+
+ size_t i = 0;
+ size_t size = this->long_opts_.size ();
+ ACE_Get_Opt_Long_Option *option = 0;
+ for (i = 0; i < size; ++i)
+ {
+ int retval = this->long_opts_.get (option, i);
+ if (retval != 0)
+ {
+ // Should never happen.
+ retval = 0;
+ continue;
+ }
+ if (option)
+ {
+ delete option;
+ option = 0;
+ }
+ }
+ delete this->optstring_;
+ delete this->last_option_;
+}
+
+int
+ACE_Get_Opt::nextchar_i (void)
+{
+ ACE_TRACE ("ACE_Get_Opt::nextchar_i");
+
+ if (this->ordering_ == PERMUTE_ARGS)
+ if (this->permute () == EOF)
+ return EOF;
+
+ // Update scanning pointer.
+ if (this->optind >= this->argc_)
+ {
+ // We're done...
+ this->nextchar_ = 0;
+ return EOF;
+ }
+ else if (*(this->nextchar_ = this->argv_[this->optind]) != '-'
+ || this->nextchar_[1] == '\0')
+ {
+ // We didn't get an option.
+
+ if (this->ordering_ == REQUIRE_ORDER
+ || this->ordering_ == PERMUTE_ARGS)
+ // If we permuted or require the options to be in order, we're done.
+ return EOF;
+
+ // It must be RETURN_IN_ORDER...
+ this->optarg = this->argv_[this->optind++];
+ this->nextchar_ = 0;
+ return 1;
+ }
+ else if (this->nextchar_[1] != 0
+ && *++this->nextchar_ == '-'
+ && this->nextchar_[1] == 0)
+ {
+ // Found "--" so we're done...
+ ++this->optind;
+ this->nextchar_ = 0;
+ return EOF;
+ }
+
+ // If it's a long option, and we allow long options advance nextchar_.
+ if (*this->nextchar_ == '-' && this->long_opts_.size () != 0)
+ this->nextchar_++;
+
+ return 0;
+}
+
+int
+ACE_Get_Opt::long_option_i (void)
+{
+ ACE_TRACE ("ACE_Get_Opt::long_option_i");
+
+ ACE_Get_Opt_Long_Option *p;
+ ACE_TCHAR *s = this->nextchar_;
+ int hits = 0;
+ int exact = 0;
+ ACE_Get_Opt_Long_Option *pfound = 0;
+ int indfound = 0;
+
+ // Advance to the end of the long option name so we can use
+ // it to get the length for a string compare.
+ while (*s && *s != '=')
+ s++;
+
+ size_t len = s - this->nextchar_;
+ // set last_option_ to nextchar_, up to the '='.
+ this->last_option (ACE_TString (this->nextchar_, len));
+
+ size_t size = this->long_opts_.size ();
+ u_int option_index = 0;
+ for (option_index = 0; option_index < size ; option_index++)
+ {
+ p = this->long_opts_[option_index];
+ ACE_ASSERT (p);
+
+ if (!ACE_OS::strncmp (p->name_, this->nextchar_, len))
+ {
+ // Got at least a partial match.
+ pfound = p;
+ indfound = option_index;
+ hits += 1;
+ if (len == ACE_OS::strlen(p->name_))
+ {
+ // And in fact, it's an exact match, so let's use it.
+ exact = 1;
+ break;
+ }
+ }
+ }
+
+ if ((hits > 1) && !exact)
+ {
+ // Great, we found a match, but unfortunately we found more than
+ // one and it wasn't exact.
+ if (this->opterr)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%s: option `%s' is ambiguous\n"),
+ this->argv_[0], this->argv_[this->optind]));
+ this->nextchar_ = 0;
+ this->optind++;
+ return '?';
+ }
+
+ if (pfound != 0)
+ {
+ // Okay, we found a good one (either a single hit or an exact match).
+ option_index = indfound;
+ this->optind++;
+ if (*s)
+ {
+ // s must point to '=' which means there's an argument (well
+ // close enough).
+ if (pfound->has_arg_ != NO_ARG)
+ // Good, we want an argument and here it is.
+ this->optarg = ++s;
+ else
+ {
+ // Whoops, we've got what looks like an argument, but we
+ // don't want one.
+ if (this->opterr)
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%s: long option `--%s' doesn't allow ")
+ ACE_TEXT ("an argument\n"),
+ this->argv_[0], pfound->name_));
+ // The spec doesn't cover this, so we keep going and the program
+ // doesn't know we ignored an argument if opt_err is off!!!
+ }
+ }
+ else if (pfound->has_arg_ == ARG_REQUIRED)
+ {
+ // s didn't help us, but we need an argument. Note that
+ // optional arguments for long options must use the "=" syntax,
+ // so we won't get here in that case.
+ if (this->optind < this->argc_)
+ // We still have some elements left, so use the next one.
+ this->optarg = this->argv_[this->optind++];
+ else
+ {
+ // All out of elements, so we have to punt...
+ if (this->opterr)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%s: long option '--%s' requires ")
+ ACE_TEXT ("an argument\n"),
+ this->argv_[0], pfound->name_));
+ this->nextchar_ = 0;
+ this->optopt_ = pfound->val_; // Remember matching short equiv
+ return this->has_colon_ ? ':' : '?';
+ }
+ }
+ this->nextchar_ = 0;
+ this->long_option_ = pfound;
+ // Since val_ has to be either a valid short option or 0, this works
+ // great. If the user really wants to know if a long option was passed.
+ this->optopt_ = pfound->val_;
+ return pfound->val_;
+ }
+ if (!this->long_only_ || this->argv_[this->optind][1] == '-'
+ || this->optstring_->find (*this->nextchar_) == ACE_TString::npos)
+ {
+ // Okay, we couldn't find a long option. If it isn't long_only (which
+ // means try the long first, and if not found try the short) or a long
+ // signature was passed, e.g. "--", or it's not a short (not sure when
+ // this could happen) it's an error.
+ if (this->opterr)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%s: illegal long option '--%s'\n"),
+ this->argv_[0], this->nextchar_));
+ this->nextchar_ = 0;
+ this->optind++;
+ return '?';
+ }
+ return this->short_option_i ();
+}
+
+int
+ACE_Get_Opt::short_option_i (void)
+{
+ ACE_TRACE ("ACE_Get_Opt::short_option_i");
+
+ /* Look at and handle the next option-character. */
+ ACE_TCHAR opt = *this->nextchar_++;
+ // Set last_option_ to opt
+ this->last_option (opt);
+
+ ACE_TCHAR *oli = 0;
+ oli =
+ const_cast<ACE_TCHAR*> (ACE_OS::strchr (this->optstring_->c_str (), opt));
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*this->nextchar_ == '\0')
+ ++this->optind;
+
+ if (oli == 0 || opt == ':')
+ {
+ if (this->opterr)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%s: illegal short option -- %c\n"),
+ this->argv_[0], opt));
+ return '?';
+ }
+ if (opt == 'W' && oli[1] == ';')
+ {
+ if (this->nextchar_[0] == 0)
+ this->nextchar_ = this->argv_[this->optind];
+ return long_option_i ();
+ }
+ this->optopt_ = oli[0]; // Remember the option that matched
+ if (oli[1] == ':')
+ {
+ if (oli[2] == ':')
+ {
+ // Takes an optional argument, and since short option args must
+ // must follow directly in the same argument, a NULL nextchar_
+ // means we didn't get one.
+ if (*this->nextchar_ != '\0')
+ {
+ this->optarg = this->nextchar_;
+ this->optind++;
+ }
+ else
+ this->optarg = 0;
+ this->nextchar_ = 0;
+ }
+ else
+ {
+ // Takes a required argument.
+ if (*this->nextchar_ != '\0')
+ {
+ // Found argument in same argv-element.
+ this->optarg = this->nextchar_;
+ this->optind++;
+ }
+ else if (this->optind == this->argc_)
+ {
+ // Ran out of arguments before finding required argument.
+ if (this->opterr)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%s: short option requires ")
+ ACE_TEXT ("an argument -- %c\n"),
+ this->argv_[0], opt));
+ opt = this->has_colon_ ? ':' : '?';
+ }
+ else
+ // Use the next argv-element as the argument.
+ this->optarg = this->argv_[this->optind++];
+ this->nextchar_ = 0;
+ }
+ }
+ return opt;
+}
+
+int
+ACE_Get_Opt::operator () (void)
+{
+ ACE_TRACE ("ACE_Get_Opt_Long::operator");
+
+ // First of all, make sure we reinitialize any pointers..
+ this->optarg = 0;
+ this->long_option_ = 0;
+
+ if (this->argv_ == 0)
+ {
+ // It can happen, e.g., on VxWorks.
+ this->optind = 0;
+ return -1;
+ }
+
+ // We check this because we can string short options together if the
+ // preceding one doesn't take an argument.
+ if (this->nextchar_ == 0 || *this->nextchar_ == '\0')
+ {
+ int retval = this->nextchar_i ();
+ if (retval != 0)
+ return retval;
+ }
+
+ if (((this->argv_[this->optind][0] == '-')
+ && (this->argv_[this->optind][1] == '-')) || this->long_only_)
+ return this->long_option_i ();
+
+ return this->short_option_i ();
+}
+
+int
+ACE_Get_Opt::long_option (const ACE_TCHAR *name,
+ OPTION_ARG_MODE has_arg)
+{
+ ACE_TRACE ("ACE_Get_Opt::long_option (const ACE_TCHAR *name, OPTION_ARG_MODE has_arg)");
+ return this->long_option (name, 0, has_arg);
+}
+
+int
+ACE_Get_Opt::long_option (const ACE_TCHAR *name,
+ int short_option,
+ OPTION_ARG_MODE has_arg)
+{
+ ACE_TRACE ("ACE_Get_Opt::long_option (const ACE_TCHAR *name, int short_option, OPTION_ARG_MODE has_arg)");
+
+ // We only allow valid alpha-numeric characters as short options.
+ // If short_options is not a valid alpha-numeric, we can still return it
+ // when the long option is found, but won't allow the caller to pass it on
+ // the command line (how could they?). The special case is 0, but since
+ // we always return it, we let the caller worry about that.
+ if (ACE_OS::ace_isalnum (short_option) != 0)
+ {
+ // If the short_option already exists, make sure it matches, otherwise
+ // add it.
+ ACE_TCHAR *s = 0;
+ if ((s = const_cast<ACE_TCHAR*> (
+ ACE_OS::strchr (this->optstring_->c_str (),
+ short_option))) != 0)
+ {
+ // Short option exists, so verify the argument options
+ if (s[1] == ':')
+ {
+ if (s[2] == ':')
+ {
+ if (has_arg != ARG_OPTIONAL)
+ {
+ if (this->opterr)
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("Existing short option '%c' takes ")
+ ACE_TEXT ("optional argument; adding %s ")
+ ACE_TEXT ("requires ARG_OPTIONAL\n"),
+ short_option, name));
+ return -1;
+ }
+ }
+ else
+ if (has_arg != ARG_REQUIRED)
+ {
+ if (this->opterr)
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("Existing short option '%c' requires ")
+ ACE_TEXT ("an argument; adding %s ")
+ ACE_TEXT ("requires ARG_REQUIRED\n"),
+ short_option, name));
+ return -1;
+ }
+ }
+ else if (has_arg != NO_ARG)
+ {
+ if (this->opterr)
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("Existing short option '%c' does not ")
+ ACE_TEXT ("accept an argument; adding %s ")
+ ACE_TEXT ("requires NO_ARG\n"),
+ short_option, name));
+ return -1;
+ }
+ }
+ else
+ {
+ // Didn't find short option, so add it...
+ *this->optstring_ += (ACE_TCHAR) short_option;
+ if (has_arg == ARG_REQUIRED)
+ *this->optstring_ += ACE_TEXT (":");
+ else if (has_arg == ARG_OPTIONAL)
+ *this->optstring_ += ACE_TEXT ("::");
+ }
+ }
+
+ ACE_Get_Opt_Long_Option *option =
+ new ACE_Get_Opt_Long_Option (name, has_arg, short_option);
+
+ if (!option)
+ return -1;
+
+ // Add to array
+ size_t size = this->long_opts_.size ();
+ if (this->long_opts_.size (size + 1) != 0
+ || this->long_opts_.set (option, size) != 0)
+ {
+ delete option;
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("Could not add long option to array.\n")),
+ -1);
+ }
+ return 0;
+}
+
+const ACE_TCHAR*
+ACE_Get_Opt::long_option (void) const
+{
+ ACE_TRACE ("ACE_Get_Opt::long_option (void)");
+ if (this->long_option_)
+ return this->long_option_->name_;
+ return 0;
+}
+
+const ACE_TCHAR*
+ACE_Get_Opt::last_option (void) const
+{
+ return this->last_option_->c_str ();
+}
+
+void
+ACE_Get_Opt::last_option (const ACE_TString &last_option)
+{
+ *this->last_option_ = last_option;
+}
+
+void
+ACE_Get_Opt::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Get_Opt::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")
+ ACE_TEXT ("opstring_ = %s\n")
+ ACE_TEXT ("long_only_ = %d\n")
+ ACE_TEXT ("has_colon_ = %d\n")
+ ACE_TEXT ("last_option_ = %s\n")
+ ACE_TEXT ("nextchar_ = %s\n")
+ ACE_TEXT ("optopt_ = %c\n")
+ ACE_TEXT ("ordering_ = %d\n"),
+ this->optstring_->c_str (),
+ this->long_only_,
+ this->has_colon_,
+ this->last_option_->c_str (),
+ this->nextchar_,
+ this->optopt_,
+ this->ordering_));
+
+ // now loop through the
+ size_t size = this->long_opts_.size ();
+ for (u_int i = 0; i < size ; ++i)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")
+ ACE_TEXT ("long_option name_ = %s\n")
+ ACE_TEXT ("has_arg_ = %d\n")
+ ACE_TEXT ("val_ = %d\n"),
+ this->long_opts_[i]->name_,
+ this->long_opts_[i]->has_arg_,
+ this->long_opts_[i]->val_));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Get_Opt::permute_args (void)
+{
+ ACE_TRACE ("ACE_Get_Opt::permute_args");
+
+ u_long cyclelen, i, j, ncycle, nnonopts, nopts;
+ u_long opt_end = this->optind;
+ int cstart, pos = 0;
+ ACE_TCHAR *swap = 0;
+
+ nnonopts = this->nonopt_end_ - this->nonopt_start_;
+ nopts = opt_end - this->nonopt_end_;
+ ncycle = ACE::gcd (nnonopts, nopts);
+ cyclelen = (opt_end - this->nonopt_start_) / ncycle;
+
+ this->optind = this->optind - nnonopts;
+
+ for (i = 0; i < ncycle; i++)
+ {
+ cstart = this->nonopt_end_ + i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++)
+ {
+ if (pos >= this->nonopt_end_)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = this->argv_[pos];
+
+ ((ACE_TCHAR **)this->argv_)[pos] = argv_[cstart];
+
+ ((ACE_TCHAR **)this->argv_)[cstart] = swap;
+ }
+ }
+}
+
+int
+ACE_Get_Opt::permute (void)
+{
+ ACE_TRACE ("ACE_Get_Opt::permute");
+
+ if (this->nonopt_start_ != this->nonopt_end_
+ && this->nonopt_start_ != this->optind)
+ this->permute_args ();
+
+ this->nonopt_start_ = this->optind;
+
+ // Skip over args untill we find the next option.
+ while (this->optind < this->argc_
+ && (this->argv_[this->optind][0] != '-'
+ || this->argv_[this->optind][1] == '\0'))
+ this->optind++;
+
+ // Got an option, so mark this as the end of the non options.
+ this->nonopt_end_ = this->optind;
+
+ if (this->optind != this->argc_
+ && ACE_OS::strcmp (this->argv_[this->optind],
+ ACE_TEXT ("--")) == 0)
+ {
+ // We found the marker for the end of the options.
+ ++this->optind;
+
+ if (this->nonopt_start_ != this->nonopt_end_
+ && this->nonopt_end_ != this->optind)
+ this->permute_args ();
+ }
+
+ if (this->optind == this->argc_)
+ {
+ if (this->nonopt_start_ != this->nonopt_end_)
+ this->optind = this->nonopt_start_;
+ return EOF;
+ }
+ return 0;
+}
+
+const ACE_TCHAR *
+ACE_Get_Opt::optstring (void) const
+{
+ return this->optstring_->c_str ();
+}
+
+ACE_Get_Opt::ACE_Get_Opt_Long_Option::ACE_Get_Opt_Long_Option (
+ const ACE_TCHAR *name,
+ int has_arg,
+ int val)
+ : name_ (ACE::strnew (name)),
+ has_arg_ (has_arg),
+ val_ (val)
+{}
+
+ACE_Get_Opt::ACE_Get_Opt_Long_Option::~ACE_Get_Opt_Long_Option (void)
+{
+ delete [] this->name_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Get_Opt.h b/ACE/ace/Get_Opt.h
new file mode 100644
index 00000000000..990b656202a
--- /dev/null
+++ b/ACE/ace/Get_Opt.h
@@ -0,0 +1,474 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Get_Opt.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Don Hinton <dhinton@gmx.net> (added long option support)
+ */
+//==========================================================================
+
+#ifndef ACE_GET_OPT_H
+#define ACE_GET_OPT_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SStringfwd.h"
+#include "ace/Containers.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#undef optind
+#undef optarg
+#undef opterr
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/*
+ * These definitions are for backward compatibility with previous versions.
+ * of ACE_Get_Opt.
+ */
+
+/**
+ * @class ACE_Get_Opt
+ *
+ * @brief Iterator for parsing command-line arguments.
+ *
+ * This is a C++ wrapper for getopt(3c) and getopt_long(3c).
+ */
+
+class ACE_Export ACE_Get_Opt
+{
+public:
+ /// Mutually exclusive ordering values.
+ enum
+ {
+ /**
+ * REQUIRE_ORDER means that processing stops and @c EOF is
+ * returned as soon as a non-option argument is found. @c opt_ind()
+ * will return the index of the next @a argv element so the program
+ * can continue processing the rest of the @a argv elements.
+ */
+ REQUIRE_ORDER = 1,
+
+ /**
+ * PERMUTE_ARGS means the @a argv elements are reordered dynamically
+ * (permuted) so that all options appear first. When the elements are
+ * permuted, the order of the options and the following arguments are
+ * maintained. When the last option has been processed, @c EOF is
+ * returned and @c opt_ind() returns the index into the next non-option
+ * element.
+ */
+ PERMUTE_ARGS = 2,
+
+ /**
+ * RETURN_IN_ORDER means each @a argv element is processed in the
+ * order is it seen. If the element is not recognized as an option, '1'
+ * is returned and @c opt_arg() refers to the @a argv element found.
+ */
+ RETURN_IN_ORDER = 3
+ };
+
+ /// Mutually exclusive option argument mode used by long options.
+ enum OPTION_ARG_MODE
+ {
+ /// Doesn't take an argument.
+ NO_ARG = 0,
+
+ /// Requires an argument, same as passing ":" after a short option
+ /// character in @a optstring.
+ ARG_REQUIRED = 1,
+
+ /// Argument is optional, same as passing "::" after a short
+ /// option character in @a optstring.
+ ARG_OPTIONAL = 2
+ };
+
+ /**
+ * Constructor initializes the command line to be parsed. All information
+ * for parsing must be supplied to this constructor.
+ *
+ * @param argc The number of @a argv elements to parse.
+ * @param argv Command line tokens, such as would be passed
+ * to @c main().
+ * @param optstring Nul-terminated string containing the legitimate
+ * short option characters. A single colon ":"
+ * following an option character means the option
+ * requires an argument. A double colon "::" following
+ * an option character means the argument is optional.
+ * The argument is taken from the rest of the current
+ * @a argv element, or from the following @a argv
+ * element (only valid for required arguments;
+ * optional arguments must always reside in the same
+ * @a argv element). The argument value, if any is
+ * returned by the @c opt_arg() method.
+ * @a optstring can be extended by adding long options
+ * with corresponding short options via the
+ * @c long_option() method. If the short option
+ * already appears in @a optstring, the argument
+ * characteristics must match, otherwise it is added.
+ * See @c long_option() for more information.
+ * If 'W', followed by a semi-colon ';' appears in
+ * @a optstring, then any time a 'W' appears on the
+ * command line, the following argument is treated as
+ * a long option. For example, if the command line
+ * contains "program -W foo", "foo" is treated as a
+ * long option, that is, as if "program --foo" had
+ * been passed.
+ * The following characters can appear in @a optstring
+ * before any option characters, with the described
+ * effect:
+ * - '+' changes the @a ordering to @a REQUIRE_ORDER.
+ * - '-' changes the @a ordering to @a RETURN_IN_ORDER.
+ * - ':' changes the return value from @c operator()
+ * and get_opt() from '?' to ':' when an option
+ * requires an argument but none is specified.
+ *
+ * @param skip_args Optional (default 1). The specified number of
+ * initial elements in @a argv are skipped before
+ * parsing begins. Thus, the default prevents
+ * @a argv[0] (usually the command name) from being
+ * parsed. @a argc includes all @a argv elements,
+ * including any skipped elements.
+ * @param report_errors Optional, if non-zero then parsing errors cause
+ * an error message to be displayed from the
+ * @c operator() method before it returns. The
+ * error message is suppressed if this argument is 0.
+ * This setting also controls whether or not an error
+ * message is displayed in @c long_option() encounters
+ * an error.
+ * @param ordering Optional (default is @c PERMUTE_ARGS); determines
+ * how the @a argv elements are processed. This argument
+ * is overridden by two factors:
+ * -# The @c POSIXLY_CORRECT environment variable. If
+ * this environment variable is set, the ordering
+ * is changed to @c REQUIRE_ORDER.
+ * -# Leading characters in @a optstring (see above).
+ * Any leading ordering characters override both
+ * the @a ordering argument and any effect of the
+ * @c POSIXLY_CORRECT environment variable.
+ * @param long_only Optional. If non-zero, then long options can be
+ * specified using a single '-' on the command line.
+ * If the token is not a long option, it is processed
+ * as usual, that is, as a short option or set of
+ * short options.
+ *
+ * Multiple short options can be combined as long as only the last
+ * one can takes an argument. For example, if @a optstring is defined as
+ * @c "abc:" or @c "abc::" then the command line @e "program -abcxxx" short
+ * options @e a, @e b, and @e c are found with @e "xxx" as the argument for
+ * @e c.
+ * However, if the command line is specified as @e "program -acb" only
+ * options @e a and @e c are found with @e "b" as the argument for @e c.
+ * Also, for options with optional arguments, that is, those followed by
+ * "::", the argument must be in the same @a argv element, so "program -abc
+ * xxx" will only find "xxx" as the argument for @e c if @a optstring is
+ * specified as @c "abc:" not @c "abc::".
+ */
+ ACE_Get_Opt (int argc,
+ ACE_TCHAR **argv,
+ const ACE_TCHAR *optstring = ACE_TEXT (""),
+ int skip_args = 1,
+ int report_errors = 0,
+ int ordering = PERMUTE_ARGS,
+ int long_only = 0);
+
+ /// Default dtor.
+ ~ACE_Get_Opt (void);
+
+ /**
+ * Scan elements of @a argv (whose length is @a argc) for short option
+ * characters given in @a optstring or long options (with no short
+ * option equivalents).
+ *
+ * If an element of @a argv starts with '-', and is not exactly "-"
+ * or "--", then it is a short option element. The characters of this
+ * element (aside from the initial '-') are option characters. If
+ * it starts with "--" followed by other characters it is treated as
+ * a long option. If @c operator() is called repeatedly, it returns
+ * each of the option characters from each of the option elements.
+ *
+ * @return The parsed option character. The following characters have
+ * special significance.
+ * @retval 0 A long option was found
+ * @retval '\?' Either an unknown option character was found, or the
+ * option is known but requires an argument, none was
+ * specified, and @a optstring did not contain a leading
+ * colon.
+ * @retval ':' A known option character was found but it requires an
+ * argument and none was supplied, and the first character
+ * of @a optstring was a colon. @c opt_opt() indicates
+ * which option was specified.
+ * @retval '1' @c RETURN_IN_ORDER was specified and a non-option argument
+ * was found.
+ * @retval EOF No more option characters were found. @c opt_ind() will
+ * return the index in @a argv of the first @a argv element
+ * that is not an option. If @c PERMUTE_ARGS was
+ * specified, the @a argv elements have been permuted so that
+ * those that are not options now come last.
+ *
+ * @note The standards are unclear with respect to the conditions under
+ * which '?' and ':' are returned, so we scan the initial characters of
+ * @a optstring up unto the first short option character for '+', '-',
+ * and ':' in order to determine ordering and missing argument behavior.
+ */
+ int operator () (void);
+
+ /**
+ * For communication from @c operator() to the caller. When
+ * @c operator() finds an option that takes an argument, the argument
+ * value is returned from this method, otherwise it returns 0.
+ */
+ ACE_TCHAR *opt_arg (void) const;
+
+ /**
+ * Returns the most recently matched option character. Especially
+ * useful when operator() returns ':' for an unspecified argument
+ * that's required, since this allows the caller to learn what option
+ * was specified without its required argument.
+ */
+ int opt_opt (void);
+
+ /**
+ * Index in @a argv of the next element to be scanned. This is used
+ * for communication to and from the caller and for communication
+ * between successive calls to @c operator(). On entry to
+ * @c operator(), zero means this is the first call; initialize.
+ *
+ * When @c operator() returns @c EOF, this is the index of the first of
+ * the non-option elements that the caller should itself scan.
+ *
+ * Otherwise, @c opt_ind() communicates from one call to the next how
+ * much of @a argv has been scanned so far.
+ */
+ int &opt_ind (void);
+
+ /// Adds a long option with no corresponding short option.
+ /**
+ * If the @a name option is seen, @c operator() returns 0.
+ *
+ * @param name The long option to add.
+ * @param has_arg Defines the argument requirements for
+ * the new option.
+ *
+ * @retval 0 Success
+ * @retval -1 The long option can not be added.
+ */
+ int long_option (const ACE_TCHAR *name,
+ OPTION_ARG_MODE has_arg = NO_ARG);
+
+ /// Adds a long option with a corresponding short option.
+ /**
+ * @param name The long option to add.
+ * @param short_option A character, the short option that corresponds
+ * to @a name.
+ * @param has_arg Defines the argument requirements for
+ * the new option. If the short option has already
+ * been supplied in the @a optstring, @a has_arg
+ * must match or an error is returned; otherwise, the
+ * new short option is added to the @a optstring.
+ *
+ * @retval 0 Success
+ * @retval -1 The long option can not be added.
+ */
+ int long_option (const ACE_TCHAR *name,
+ int short_option,
+ OPTION_ARG_MODE has_arg = NO_ARG);
+
+ /// Returns the name of the long option found on the last call to
+ /// @c operator() or 0 if none was found.
+ const ACE_TCHAR *long_option (void) const;
+
+ /// The number of arguments in the internal @c argv_.
+ int argc (void) const;
+
+ /// Accessor for the internal @c argv_ pointer.
+ ACE_TCHAR **argv (void) const;
+
+ /// Accessor for the @c last_option that was processed. This allows
+ /// applications to know if the found option was a short or long
+ /// option, and is especially useful in cases where it was invalid
+ /// and the caller wants to print out the invalid value.
+ const ACE_TCHAR *last_option (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Return the @a optstring. This is handy to verify that calls to
+ /// long_option added short options as expected.
+ const ACE_TCHAR *optstring (void) const;
+
+public:
+ /*
+ * The following five data members should be private, but that
+ * would break backwards compatibility. However, we recommend not
+ * writing code that uses these fields directly.
+ */
+
+ /// Holds the @a argc count.
+ /**
+ * @deprecated This is public for backwards compatibility only.
+ * It will be made private in a release of ACE past 5.3. Do not
+ * write code that relies on this member being public; use the
+ * @c argc() accessor method instead.
+ */
+ int argc_;
+
+ /// Holds the @a argv pointer.
+ /**
+ * @deprecated This is public for backwards compatibility only.
+ * It will be made private in a release of ACE past 5.3. Do not
+ * write code that relies on this member being public; use the
+ * @c argv() accessor method instead.
+ */
+ ACE_TCHAR **argv_;
+
+ /// Index in @c argv_ of the next element to be scanned.
+ /**
+ * @deprecated This is public for backwards compatibility only.
+ * It will be made private in a release of ACE past 5.3. Do not
+ * write code that relies on this member being public; use the
+ * @c opt_ind() accessor method instead.
+ */
+ int optind;
+
+ /// Callers store zero here to inhibit the error message for
+ /// unrecognized options.
+ /**
+ * @deprecated This is public for backwards compatibility only.
+ * It will be made private in a release of ACE past 5.3. Do not
+ * write code that relies on this member being public; use the
+ * @a report_errors argument to this class's constructor instead.
+ */
+ int opterr;
+
+ /// Points to the option argument when one is found on last call to
+ /// @c operator().
+ /**
+ * @deprecated This is public for backwards compatibility only.
+ * It will be made private in a release of ACE past 5.3. Do not
+ * write code that relies on this member being public; use the
+ * @c opt_arg() accessor method instead.
+ */
+ ACE_TCHAR *optarg;
+
+private:
+ /**
+ * @class ACE_Get_Opt_Long_Option This class is for internal use
+ * in the ACE_Get_Opt class, and is inaccessible to users.
+ */
+ class ACE_Get_Opt_Long_Option
+ {
+ public:
+ /// ctor
+ ACE_Get_Opt_Long_Option (const ACE_TCHAR *name,
+ int has_arg,
+ int val = 0);
+
+ /// Dtor.
+ ~ACE_Get_Opt_Long_Option (void);
+
+ bool operator < (const ACE_Get_Opt_Long_Option &rhs);
+
+ /// Long option name.
+ const ACE_TCHAR *name_;
+
+ /// Contains value for <OPTION_ARG_MODE>.
+ int has_arg_;
+
+ /// Contains a valid short option character or zero if it doesn't
+ /// have a corresponding short option. It can also contain a
+ /// non-printable value that cannot be passed to <optstring> but
+ /// will be returned by <operator()>. This is handy for
+ /// simplifying long option handling, see tests/Get_Opt_Test.cpp
+ /// for an example of this technique.
+ int val_;
+ };
+
+ /// Updates nextchar_.
+ int nextchar_i (void);
+
+ /// Handles long options.
+ int long_option_i (void);
+
+ /// Handles short options.
+ int short_option_i (void);
+
+ /// If permuting args, this functions manages the nonopt_start_ and
+ /// nonopt_end_ indexes and makes calls to permute to actually
+ /// reorder the <argv>-elements.
+ void permute_args (void);
+
+ /// Handles reordering <argv>-elements.
+ int permute (void);
+
+ /// Set last_option.
+ void last_option (const ACE_TString &s);
+
+ // Disallow copying and assignment.
+ ACE_Get_Opt (const ACE_Get_Opt &);
+ ACE_Get_Opt &operator= (const ACE_Get_Opt &);
+
+private:
+
+ /// Holds the option string.
+ ACE_TString *optstring_;
+
+ /// Treat all options as long options.
+ int long_only_;
+
+ /// Keeps track of whether or not a colon was passed in <optstring>.
+ /// This is used to determine the return value when required
+ /// arguments are missing.
+ int has_colon_;
+
+ /// This is the last option, short or long, that was processed. This
+ /// is handy to have in cases where the option passed was invalid.
+ ACE_TString *last_option_;
+
+ /**
+ * The next char to be scanned in the option-element in which the
+ * last option character we returned was found. This allows us to
+ * pick up the scan where we left off *
+ * If this is zero, or a null string, it means resume the scan
+ * by advancing to the next <argv>-element.
+ */
+ ACE_TCHAR *nextchar_;
+
+ /// Most recently matched short option character.
+ int optopt_;
+
+ /// Keeps track of ordering mode (default <PERMUTE_ARGS>).
+ int ordering_;
+
+ /// Index of the first non-option <argv>-element found (only valid
+ /// when permuting).
+ int nonopt_start_;
+
+ /// Index of the <argv>-element following the last non-option element
+ /// (only valid when permuting).
+ int nonopt_end_;
+
+ /// Points to the long_option found on last call to <operator()>.
+ ACE_Get_Opt_Long_Option *long_option_;
+
+ /// Array of long options.
+ ACE_Array<ACE_Get_Opt_Long_Option*> long_opts_;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Get_Opt.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_GET_OPT_H */
diff --git a/ACE/ace/Get_Opt.inl b/ACE/ace/Get_Opt.inl
new file mode 100644
index 00000000000..cbe5f167e55
--- /dev/null
+++ b/ACE/ace/Get_Opt.inl
@@ -0,0 +1,43 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE bool
+ACE_Get_Opt::ACE_Get_Opt_Long_Option::operator < (const ACE_Get_Opt_Long_Option &rhs)
+{
+ return this->name_ < rhs.name_;
+}
+
+ACE_INLINE int
+ACE_Get_Opt::argc (void) const
+{
+ return this->argc_;
+}
+
+ACE_INLINE ACE_TCHAR **
+ACE_Get_Opt::argv (void) const
+{
+ return this->argv_;
+}
+
+ACE_INLINE ACE_TCHAR*
+ACE_Get_Opt::opt_arg (void) const
+{
+ return this->optarg;
+}
+
+ACE_INLINE int
+ACE_Get_Opt::opt_opt (void)
+{
+ return this->optopt_;
+}
+
+ACE_INLINE int &
+ACE_Get_Opt::opt_ind (void)
+{
+ return this->optind;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Global_Macros.h b/ACE/ace/Global_Macros.h
new file mode 100644
index 00000000000..e607d812750
--- /dev/null
+++ b/ACE/ace/Global_Macros.h
@@ -0,0 +1,1133 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Global_Macros.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * This one is split from the famous OS.h
+ */
+//=============================================================================
+
+#ifndef ACE_GLOBAL_MACROS_H
+#define ACE_GLOBAL_MACROS_H
+
+#include /**/ "ace/pre.h"
+
+// Included just keep compilers that see #pragma dierctive first
+// happy.
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/config-lite.h"
+#include "ace/Assert.h" // For ACE_ASSERT
+
+// Start Global Macros
+# define ACE_BEGIN_DUMP ACE_TEXT ("\n====\n(%P|%t|%x)\n")
+# define ACE_END_DUMP ACE_TEXT ("====\n")
+
+# if defined (ACE_NDEBUG)
+# define ACE_DB(X)
+# else
+# define ACE_DB(X) X
+# endif /* ACE_NDEBUG */
+
+// ACE_NO_HEAP_CHECK macro can be used to suppress false report of
+// memory leaks. It turns off the built-in heap checking until the
+// block is left. The old state will then be restored Only used for
+// Win32 (in the moment).
+# if defined (ACE_WIN32)
+
+# if defined (_DEBUG) && !defined (ACE_HAS_WINCE) && !defined (__BORLANDC__)
+# include /**/ <crtdbg.h>
+
+// Open versioned namespace, if enabled by the user.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Export ACE_No_Heap_Check
+{
+public:
+ ACE_No_Heap_Check (void)
+ : old_state (_CrtSetDbgFlag (_CRTDBG_REPORT_FLAG))
+ { _CrtSetDbgFlag (old_state & ~_CRTDBG_ALLOC_MEM_DF);}
+ ~ACE_No_Heap_Check (void) { _CrtSetDbgFlag (old_state);}
+private:
+ int old_state;
+};
+
+// Close versioned namespace, if enabled by the user.
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# define ACE_NO_HEAP_CHECK ACE_No_Heap_Check ____no_heap;
+# else /* !_DEBUG */
+# define ACE_NO_HEAP_CHECK
+# endif /* _DEBUG */
+# else /* !ACE_WIN32 */
+# define ACE_NO_HEAP_CHECK
+# endif /* ACE_WIN32 */
+
+// Turn a number into a string.
+# define ACE_ITOA(X) #X
+
+// Create a string of a server address with a "host:port" format.
+# define ACE_SERVER_ADDRESS(H,P) H ACE_TEXT(":") P
+
+// A couple useful inline functions for checking whether bits are
+// enabled or disabled.
+
+// Efficiently returns the least power of two >= X...
+# define ACE_POW(X) (((X) == 0)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X)))
+# define ACE_EVEN(NUM) (((NUM) & 1) == 0)
+# define ACE_ODD(NUM) (((NUM) & 1) == 1)
+# define ACE_BIT_ENABLED(WORD, BIT) (((WORD) & (BIT)) != 0)
+# define ACE_BIT_DISABLED(WORD, BIT) (((WORD) & (BIT)) == 0)
+# define ACE_BIT_CMP_MASK(WORD, BIT, MASK) (((WORD) & (BIT)) == MASK)
+# define ACE_SET_BITS(WORD, BITS) (WORD |= (BITS))
+# define ACE_CLR_BITS(WORD, BITS) (WORD &= ~(BITS))
+
+# if !defined (ACE_ENDLESS_LOOP)
+# define ACE_ENDLESS_LOOP
+# endif /* ! ACE_ENDLESS_LOOP */
+
+# if defined (ACE_NEEDS_FUNC_DEFINITIONS)
+ // It just evaporated ;-) Not pleasant.
+# define ACE_UNIMPLEMENTED_FUNC(f)
+# else
+# define ACE_UNIMPLEMENTED_FUNC(f) f;
+# endif /* ACE_NEEDS_FUNC_DEFINITIONS */
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+ // Easy way to designate that a class is used as a pseudo-namespace.
+ // Insures that g++ "friendship" anamolies are properly handled.
+ # define ACE_CLASS_IS_NAMESPACE(CLASSNAME) \
+ private: \
+ CLASSNAME (void); \
+ CLASSNAME (const CLASSNAME&); \
+ friend class ace_dewarn_gplusplus
+#endif /* ACE_LACKS_DEPRECATED_MACROS */
+
+// ----------------------------------------------------------------
+
+//FUZZ: disable check_for_exception_sepc
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+ #if defined (ACE_HAS_NO_THROW_SPEC)
+ # define ACE_THROW_SPEC(X)
+ #else
+ # if defined (ACE_HAS_EXCEPTIONS)
+ # if defined (ACE_WIN32) && defined (_MSC_VER) && \
+ (_MSC_VER >= 1400) && (_MSC_VER <= 1500)
+ # define ACE_THROW_SPEC(X) throw(...)
+ # else
+ # define ACE_THROW_SPEC(X) throw X
+ # endif /* ACE_WIN32 && VC8 */
+ # else /* ! ACE_HAS_EXCEPTIONS */
+ # define ACE_THROW_SPEC(X)
+ # endif /* ! ACE_HAS_EXCEPTIONS */
+ #endif /*ACE_HAS_NO_THROW_SPEC*/
+#endif /* ACE_LACKS_DEPRECATED_MACROS */
+//FUZZ: enable check_for_exception_sepc
+
+// ----------------------------------------------------------------
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+ /**
+ * This macro is deprecated
+ */
+ #define ACE_NESTED_CLASS(TYPE, NAME) TYPE::NAME
+#endif /* ACE_LACKS_DEPRECATED_MACROS */
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+ /**
+ * @name CORBA namespace macros.
+ *
+ * CORBA namespace macros.
+ *
+ * @deprecated These macros were formerly used by TAO but are now
+ * deprecated, and only remain to retain some backward
+ * compatibility. They will be removed in a future ACE
+ * release.
+ */
+ //@{
+ #define ACE_CORBA_1(NAME) CORBA::NAME
+ #define ACE_CORBA_2(TYPE, NAME) CORBA::TYPE::NAME
+ #define ACE_CORBA_3(TYPE, NAME) CORBA::TYPE::NAME
+ //@}
+#endif /* ACE_LACKS_DEPRECATED_MACROS */
+
+// ----------------------------------------------------------------
+
+// Convenient macro for testing for deadlock, as well as for detecting
+// when mutexes fail.
+#define ACE_GUARD_ACTION(MUTEX, OBJ, LOCK, ACTION, REACTION) \
+ ACE_Guard< MUTEX > OBJ (LOCK); \
+ if (OBJ.locked () != 0) { ACTION; } \
+ else { REACTION; }
+#define ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, REACTION) \
+ ACE_GUARD_ACTION(MUTEX, OBJ, LOCK, ;, REACTION)
+#define ACE_GUARD(MUTEX, OBJ, LOCK) \
+ ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, return)
+#define ACE_GUARD_RETURN(MUTEX, OBJ, LOCK, RETURN) \
+ ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, return RETURN)
+# define ACE_WRITE_GUARD(MUTEX,OBJ,LOCK) \
+ ACE_Write_Guard< MUTEX > OBJ (LOCK); \
+ if (OBJ.locked () == 0) return;
+# define ACE_WRITE_GUARD_RETURN(MUTEX,OBJ,LOCK,RETURN) \
+ ACE_Write_Guard< MUTEX > OBJ (LOCK); \
+ if (OBJ.locked () == 0) return RETURN;
+# define ACE_READ_GUARD(MUTEX,OBJ,LOCK) \
+ ACE_Read_Guard< MUTEX > OBJ (LOCK); \
+ if (OBJ.locked () == 0) return;
+# define ACE_READ_GUARD_RETURN(MUTEX,OBJ,LOCK,RETURN) \
+ ACE_Read_Guard< MUTEX > OBJ (LOCK); \
+ if (OBJ.locked () == 0) return RETURN;
+
+// ----------------------------------------------------------------
+
+# define ACE_DES_NOFREE(POINTER,CLASS) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~CLASS (); \
+ } \
+ } \
+ while (0)
+
+# define ACE_DES_ARRAY_NOFREE(POINTER,SIZE,CLASS) \
+ do { \
+ if (POINTER) \
+ { \
+ for (size_t i = 0; \
+ i < SIZE; \
+ ++i) \
+ { \
+ (&(POINTER)[i])->~CLASS (); \
+ } \
+ } \
+ } \
+ while (0)
+
+# define ACE_DES_FREE(POINTER,DEALLOCATOR,CLASS) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+
+# define ACE_DES_ARRAY_FREE(POINTER,SIZE,DEALLOCATOR,CLASS) \
+ do { \
+ if (POINTER) \
+ { \
+ for (size_t i = 0; \
+ i < SIZE; \
+ ++i) \
+ { \
+ (&(POINTER)[i])->~CLASS (); \
+ } \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+
+# if defined (ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR)
+# define ACE_DES_NOFREE_TEMPLATE(POINTER,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS (); \
+ } \
+ } \
+ while (0)
+# define ACE_DES_ARRAY_NOFREE_TEMPLATE(POINTER,SIZE,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ for (size_t i = 0; \
+ i < SIZE; \
+ ++i) \
+ { \
+ (&(POINTER)[i])->~T_CLASS (); \
+ } \
+ } \
+ } \
+ while (0)
+
+#if defined (ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS)
+# define ACE_DES_FREE_TEMPLATE(POINTER,DEALLOCATOR,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS T_PARAMETER (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#else
+# define ACE_DES_FREE_TEMPLATE(POINTER,DEALLOCATOR,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#endif /* defined(ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS) */
+# define ACE_DES_ARRAY_FREE_TEMPLATE(POINTER,SIZE,DEALLOCATOR,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ for (size_t i = 0; \
+ i < SIZE; \
+ ++i) \
+ { \
+ (&(POINTER)[i])->~T_CLASS (); \
+ } \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#if defined(ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS)
+# define ACE_DES_FREE_TEMPLATE2(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS <T_PARAM1, T_PARAM2> (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#else
+# define ACE_DES_FREE_TEMPLATE2(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#endif /* defined(ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS) */
+#if defined(ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS)
+# define ACE_DES_FREE_TEMPLATE3(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS <T_PARAM1, T_PARAM2, T_PARAM3> (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#else
+# define ACE_DES_FREE_TEMPLATE3(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#endif /* defined(ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS) */
+#if defined(ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS)
+# define ACE_DES_FREE_TEMPLATE4(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3, T_PARAM4) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS <T_PARAM1, T_PARAM2, T_PARAM3, T_PARAM4> (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#else
+# define ACE_DES_FREE_TEMPLATE4(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3, T_PARAM4) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->~T_CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+#endif /* defined(ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS) */
+# define ACE_DES_ARRAY_FREE_TEMPLATE2(POINTER,SIZE,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \
+ do { \
+ if (POINTER) \
+ { \
+ for (size_t i = 0; \
+ i < SIZE; \
+ ++i) \
+ { \
+ (&(POINTER)[i])->~T_CLASS (); \
+ } \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+# else /* ! ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR */
+# define ACE_DES_NOFREE_TEMPLATE(POINTER,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ (POINTER)->T_CLASS T_PARAMETER::~T_CLASS (); \
+ } \
+ } \
+ while (0)
+# define ACE_DES_ARRAY_NOFREE_TEMPLATE(POINTER,SIZE,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ for (size_t i = 0; \
+ i < SIZE; \
+ ++i) \
+ { \
+ (POINTER)[i].T_CLASS T_PARAMETER::~T_CLASS (); \
+ } \
+ } \
+ } \
+ while (0)
+# define ACE_DES_FREE_TEMPLATE(POINTER,DEALLOCATOR,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ POINTER->T_CLASS T_PARAMETER::~T_CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+# define ACE_DES_ARRAY_FREE_TEMPLATE(POINTER,SIZE,DEALLOCATOR,T_CLASS,T_PARAMETER) \
+ do { \
+ if (POINTER) \
+ { \
+ for (size_t i = 0; \
+ i < SIZE; \
+ ++i) \
+ { \
+ POINTER[i].T_CLASS T_PARAMETER::~T_CLASS (); \
+ } \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+# define ACE_DES_FREE_TEMPLATE2(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \
+ do { \
+ if (POINTER) \
+ { \
+ POINTER->T_CLASS <T_PARAM1, T_PARAM2>::~T_CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+# define ACE_DES_FREE_TEMPLATE3(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3) \
+ do { \
+ if (POINTER) \
+ { \
+ POINTER->T_CLASS <T_PARAM1, T_PARAM2, T_PARAM3>::~T_CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+# define ACE_DES_FREE_TEMPLATE4(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3,T_PARAM4) \
+ do { \
+ if (POINTER) \
+ { \
+ POINTER->T_CLASS <T_PARAM1, T_PARAM2, T_PARAM3, T_PARAM4>::~T_CLASS (); \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+# define ACE_DES_ARRAY_FREE_TEMPLATE2(POINTER,SIZE,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \
+ do { \
+ if (POINTER) \
+ { \
+ for (size_t i = 0; \
+ i < SIZE; \
+ ++i) \
+ { \
+ POINTER[i].T_CLASS <T_PARAM1, T_PARAM2>::~T_CLASS (); \
+ } \
+ DEALLOCATOR (POINTER); \
+ } \
+ } \
+ while (0)
+# endif /* defined ! ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR */
+
+
+/*******************************************************************/
+
+/// Service Objects, i.e., objects dynamically loaded via the service
+/// configurator, must provide a destructor function with the
+/// following prototype to perform object cleanup.
+typedef void (*ACE_Service_Object_Exterminator)(void *);
+
+/** @name Service Configurator macros
+ *
+ * The following macros are used to define helper objects used in
+ * ACE's Service Configurator framework, which is described in
+ * Chapter 5 of C++NPv2 <www.cs.wustl.edu/~schmidt/ACE/book2/>. This
+ * framework implements the Component Configurator pattern, which is
+ * described in Chapter 2 of POSA2 <www.cs.wustl.edu/~schmidt/POSA/>.
+ * The intent of this pattern is to allow developers to dynamically
+ * load and configure services into a system. With a little help from
+ * this macros statically linked services can also be dynamically
+ * configured.
+ *
+ * More details about this component are available in the documentation
+ * of the ACE_Service_Configurator class and also
+ * ACE_Dynamic_Service.
+ *
+ * Notice that in all the macros the SERVICE_CLASS parameter must be
+ * the name of a class derived from ACE_Service_Object.
+ */
+//@{
+/// Declare a the data structure required to register a statically
+/// linked service into the service configurator.
+/**
+ * The macro should be used in the header file where the service is
+ * declared, its only argument is usually the name of the class that
+ * implements the service.
+ *
+ * @param SERVICE_CLASS The name of the class implementing the
+ * service.
+ */
+# define ACE_STATIC_SVC_DECLARE(SERVICE_CLASS) \
+extern ACE_Static_Svc_Descriptor ace_svc_desc_##SERVICE_CLASS ;
+
+/// As ACE_STATIC_SVC_DECLARE, but using an export macro for NT
+/// compilers.
+/**
+ * NT compilers require the use of explicit directives to export and
+ * import symbols from a DLL. If you need to define a service in a
+ * dynamic library you should use this version instead.
+ * Normally ACE uses a macro to inject the correct export/import
+ * directives on NT. Naturally it also the macro expands to a blank
+ * on platforms that do not require such directives.
+ * The first argument (EXPORT_NAME) is the prefix for this export
+ * macro, the full name is formed by appending _Export.
+ * ACE provides tools to generate header files that define the macro
+ * correctly on all platforms, please see
+ * $ACE_ROOT/bin/generate_export_file.pl
+ *
+ * @param EXPORT_NAME The export macro name prefix.
+ * @param SERVICE_CLASS The name of the class implementing the service.
+ */
+#define ACE_STATIC_SVC_DECLARE_EXPORT(EXPORT_NAME,SERVICE_CLASS) \
+extern EXPORT_NAME##_Export ACE_Static_Svc_Descriptor ace_svc_desc_##SERVICE_CLASS;
+
+/// Define the data structure used to register a statically linked
+/// service into the Service Configurator.
+/**
+ * The service configurator requires several arguments to build and
+ * control an statically linked service, including its name, the
+ * factory function used to construct the service, and some flags.
+ * All those parameters are configured in a single structure, an
+ * instance of this structure is statically initialized using the
+ * following macro.
+ *
+ * @param SERVICE_CLASS The name of the class that implements the
+ * service, must be derived (directly or indirectly) from
+ * ACE_Service_Object.
+ * @param NAME The name for this service, this name is used by the
+ * service configurator to match configuration options provided in
+ * the svc.conf file.
+ * @param TYPE The type of object. Objects can be streams or service
+ * objects. Please read the ACE_Service_Configurator and ASX
+ * documentation for more details.
+ * @param FN The name of the factory function, usually the
+ * ACE_SVC_NAME macro can be used to generate the name. The
+ * factory function is often defined using ACE_FACTORY_DECLARE and
+ * ACE_FACTORY_DEFINE.
+ * @param FLAGS Flags to control the ownership and lifecycle of the
+ * object. Please read the ACE_Service_Configurator documentation
+ * for more details.
+ * @param ACTIVE If not zero then a thread will be dedicate to the
+ * service. Please read the ACE_Service_Configurator documentation
+ * for more details.
+ */
+# define ACE_STATIC_SVC_DEFINE(SERVICE_CLASS, NAME, TYPE, FN, FLAGS, ACTIVE) \
+ACE_Static_Svc_Descriptor ace_svc_desc_##SERVICE_CLASS = { NAME, TYPE, FN, FLAGS, ACTIVE };
+
+/// Automatically register a service with the service configurator
+/**
+ * In some applications the services must be automatically registered
+ * with the service configurator, before main() starts.
+ * The ACE_STATIC_SVC_REQUIRE macro defines a class whose constructor
+ * register the service, it also defines a static instance of that
+ * class to ensure that the service is registered before main.
+ *
+ * On platforms that lack adequate support for static C++ objects the
+ * macro ACE_STATIC_SVC_REGISTER can be used to explicitly register
+ * the service.
+ *
+ * @todo One class per-Service_Object seems wasteful. It should be
+ * possible to define a single class and re-use it for all the
+ * service objects, just by passing the Service_Descriptor as an
+ * argument to the constructor.
+ */
+#if defined(ACE_LACKS_STATIC_CONSTRUCTORS)
+# define ACE_STATIC_SVC_REQUIRE(SERVICE_CLASS)\
+class ACE_Static_Svc_##SERVICE_CLASS {\
+public:\
+ ACE_Static_Svc_##SERVICE_CLASS() { \
+ ACE_Service_Config::insert (\
+ &ace_svc_desc_##SERVICE_CLASS); \
+ } \
+};
+#define ACE_STATIC_SVC_REGISTER(SERVICE_CLASS)\
+ACE_Static_Svc_##SERVICE_CLASS ace_static_svc_##SERVICE_CLASS
+
+#else /* !ACE_LACKS_STATIC_CONSTRUCTORS */
+
+# define ACE_STATIC_SVC_REQUIRE(SERVICE_CLASS)\
+class ACE_Static_Svc_##SERVICE_CLASS {\
+public:\
+ ACE_Static_Svc_##SERVICE_CLASS() { \
+ ACE_Service_Config::insert (\
+ &ace_svc_desc_##SERVICE_CLASS); \
+ } \
+};\
+static ACE_Static_Svc_##SERVICE_CLASS ace_static_svc_##SERVICE_CLASS;
+#define ACE_STATIC_SVC_REGISTER(SERVICE_CLASS) do {} while (0)
+
+#endif /* !ACE_LACKS_STATIC_CONSTRUCTORS */
+
+// Preprocessor symbols will not be expanded if they are
+// concatenated. Force the preprocessor to expand them during the
+// argument prescan by calling a macro that itself calls another that
+// performs the actual concatenation.
+#define ACE_PREPROC_CONCATENATE_IMPL(A,B) A ## B
+#define ACE_PREPROC_CONCATENATE(A,B) ACE_PREPROC_CONCATENATE_IMPL(A,B)
+
+#if defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1
+// Preprocessor symbols will not be expanded if they are
+// concatenated. Force the preprocessor to expand them during the
+// argument prescan by calling a macro that itself calls another that
+// performs the actual concatenation.
+# define ACE_MAKE_SVC_CONFIG_FUNCTION_NAME(PREFIX,VERSIONED_NAMESPACE,SERVICE_CLASS) PREFIX ## _ ## VERSIONED_NAMESPACE ## _ ## SERVICE_CLASS
+#else
+# define ACE_MAKE_SVC_CONFIG_FUNCTION_NAME(PREFIX,VERSIONED_NAMESPACE,SERVICE_CLASS) PREFIX ## _ ## SERVICE_CLASS
+#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+#define ACE_MAKE_SVC_CONFIG_FACTORY_NAME(VERSIONED_NAMESPACE,SERVICE_CLASS) ACE_MAKE_SVC_CONFIG_FUNCTION_NAME(_make,VERSIONED_NAMESPACE,SERVICE_CLASS)
+#define ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(VERSIONED_NAMESPACE,SERVICE_CLASS) ACE_MAKE_SVC_CONFIG_FUNCTION_NAME(_gobble,VERSIONED_NAMESPACE,SERVICE_CLASS)
+
+
+/// Declare the factory method used to create dynamically loadable
+/// services.
+/**
+ * Once the service implementation is dynamically loaded the Service
+ * Configurator uses a factory method to create the object.
+ * This macro declares such a factory function with the proper
+ * interface and export macros.
+ * Normally used in the header file that declares the service
+ * implementation.
+ *
+ * @param CLS must match the prefix of the export macro used for this
+ * service.
+ * @param SERVICE_CLASS must match the name of the class that
+ * implements the service.
+ *
+ */
+# define ACE_FACTORY_DECLARE(CLS,SERVICE_CLASS) \
+extern "C" CLS##_Export ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object * \
+ACE_MAKE_SVC_CONFIG_FACTORY_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (ACE_Service_Object_Exterminator *);
+
+/// Define the factory method (and destructor) for a dynamically
+/// loadable service.
+/**
+ * Use with arguments matching ACE_FACTORY_DECLARE.
+ * Normally used in the .cpp file that defines the service
+ * implementation.
+ *
+ * This macro defines both the factory method and the function used to
+ * cleanup the service object.
+ *
+ * If this macro is used to define a factory function that need not be
+ * exported (for example, in a static service situation), CLS can be
+ * specified as ACE_Local_Service.
+ */
+# define ACE_Local_Service_Export
+
+#if defined (ACE_OPENVMS)
+# define ACE_PREPROC_STRINGIFY(A) #A
+# define ACE_MAKE_SVC_REGISTRAR_ARG(A) ACE_PREPROC_STRINGIFY(A), (void*)&A
+# define ACE_FACTORY_DEFINE(CLS,SERVICE_CLASS) \
+void ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (void *p) { \
+ ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object * _p = \
+ static_cast< ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object *> (p); \
+ ACE_ASSERT (_p != 0); \
+ delete _p; } \
+extern "C" CLS##_Export ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object *\
+ACE_MAKE_SVC_CONFIG_FACTORY_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (ACE_Service_Object_Exterminator *gobbler) \
+{ \
+ ACE_TRACE (#SERVICE_CLASS); \
+ if (gobbler != 0) \
+ *gobbler = (ACE_Service_Object_Exterminator) ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS); \
+ return new SERVICE_CLASS; \
+} \
+ACE_Dynamic_Svc_Registrar ace_svc_reg_##SERVICE_CLASS \
+ (ACE_MAKE_SVC_REGISTRAR_ARG(ACE_MAKE_SVC_CONFIG_FACTORY_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS)));
+#else
+# define ACE_FACTORY_DEFINE(CLS,SERVICE_CLASS) \
+void ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (void *p) { \
+ ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object * _p = \
+ static_cast< ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object *> (p); \
+ ACE_ASSERT (_p != 0); \
+ delete _p; } \
+extern "C" CLS##_Export ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object *\
+ACE_MAKE_SVC_CONFIG_FACTORY_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (ACE_Service_Object_Exterminator *gobbler) \
+{ \
+ ACE_TRACE (#SERVICE_CLASS); \
+ if (gobbler != 0) \
+ *gobbler = (ACE_Service_Object_Exterminator) ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS); \
+ return new SERVICE_CLASS; \
+}
+#endif
+
+/**
+ * For service classes scoped within namespaces, use this macro in
+ * place of ACE_FACTORY_DEFINE. The third argument in this case is
+ * the fully scoped name of the class as it is to be
+ * instantiated. For example, given:
+ * namespace ACE
+ * {
+ * namespace Foo
+ * {
+ * class Bar : public ACE_Service_Object
+ * {};
+ * };
+ * };
+ *
+ * ACE_FACTORY_DECLARE(ACE,ACE_Foo_Bar)
+ *
+ * you would then use:
+ *
+ * ACE_FACTORY_NAMESPACE_DEFINE(ACE,ACE_Foo_Bar,ACE::Foo::Bar)
+ *
+ * Note that in this example, the ACE_FACTORY_DECLARE is done outside
+ * the namespace scope. Then, the SERVICE_CLASS name is the same as
+ * the fully scoped class name, but with '::' replaced with '_'. Doing
+ * this will ensure unique generated signatures for the various C
+ * style functions.
+ */
+#if defined (ACE_OPENVMS)
+# define ACE_PREPROC_STRINGIFY(A) #A
+# define ACE_MAKE_SVC_REGISTRAR_ARG(A) ACE_PREPROC_STRINGIFY(A), (void*)&A
+# define ACE_FACTORY_NAMESPACE_DEFINE(CLS,SERVICE_CLASS,NAMESPACE_CLASS) \
+void ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (void *p) { \
+ ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object * _p = \
+ static_cast< ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object *> (p); \
+ ACE_ASSERT (_p != 0); \
+ delete _p; } \
+extern "C" CLS##_Export ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object *\
+ACE_MAKE_SVC_CONFIG_FACTORY_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (ACE_Service_Object_Exterminator *gobbler) \
+{ \
+ ACE_TRACE (#SERVICE_CLASS); \
+ if (gobbler != 0) \
+ *gobbler = (ACE_Service_Object_Exterminator) ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS); \
+ return new NAMESPACE_CLASS; \
+} \
+ACE_Dynamic_Svc_Registrar ace_svc_reg_##SERVICE_CLASS \
+ (ACE_MAKE_SVC_REGISTRAR_ARG(ACE_MAKE_SVC_CONFIG_FACTORY_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS)));
+#else
+# define ACE_FACTORY_NAMESPACE_DEFINE(CLS,SERVICE_CLASS,NAMESPACE_CLASS) \
+void ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (void *p) { \
+ ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object * _p = \
+ static_cast< ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object *> (p); \
+ ACE_ASSERT (_p != 0); \
+ delete _p; } \
+extern "C" CLS##_Export ACE_VERSIONED_NAMESPACE_NAME::ACE_Service_Object *\
+ACE_MAKE_SVC_CONFIG_FACTORY_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS) (ACE_Service_Object_Exterminator *gobbler) \
+{ \
+ ACE_TRACE (#SERVICE_CLASS); \
+ if (gobbler != 0) \
+ *gobbler = (ACE_Service_Object_Exterminator) ACE_MAKE_SVC_CONFIG_GOBBLER_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS); \
+ return new NAMESPACE_CLASS; \
+}
+#endif
+
+/// The canonical name for a service factory method
+# define ACE_SVC_NAME(SERVICE_CLASS) ACE_MAKE_SVC_CONFIG_FACTORY_NAME(ACE_VERSIONED_NAMESPACE_NAME,SERVICE_CLASS)
+
+/// The canonical way to invoke (i.e. construct) a service factory
+/// method.
+#define ACE_SVC_INVOKE(SERVICE_CLASS) ACE_SVC_NAME(SERVICE_CLASS) (0)
+
+//@}
+
+/** @name Helper macros for services defined in the netsvcs library.
+ *
+ * The ACE services defined in netsvcs use this helper macros for
+ * simplicity.
+ *
+ */
+//@{
+# define ACE_SVC_FACTORY_DECLARE(X) ACE_FACTORY_DECLARE (ACE_Svc, X)
+# define ACE_SVC_FACTORY_DEFINE(X) ACE_FACTORY_DEFINE (ACE_Svc, X)
+//@}
+
+#if defined (ACE_WIN32)
+// These are used in SPIPE_Acceptor/Connector, but are ignored at runtime.
+# if defined (ACE_HAS_WINCE)
+# if !defined (PIPE_TYPE_MESSAGE)
+# define PIPE_TYPE_MESSAGE 0
+# endif
+# if !defined (PIPE_READMODE_MESSAGE)
+# define PIPE_READMODE_MESSAGE 0
+# endif
+# if !defined (PIPE_WAIT)
+# define PIPE_WAIT 0
+# endif
+# endif /* ACE_HAS_WINCE */
+#else /* !ACE_WIN32 */
+// Add some typedefs and macros to enhance Win32 conformance...
+# if !defined (LPSECURITY_ATTRIBUTES)
+# define LPSECURITY_ATTRIBUTES int
+# endif /* !defined LPSECURITY_ATTRIBUTES */
+# if !defined (GENERIC_READ)
+# define GENERIC_READ 0
+# endif /* !defined GENERIC_READ */
+# if !defined (FILE_SHARE_READ)
+# define FILE_SHARE_READ 0
+# endif /* !defined FILE_SHARE_READ */
+# if !defined (OPEN_EXISTING)
+# define OPEN_EXISTING 0
+# endif /* !defined OPEN_EXISTING */
+# if !defined (FILE_ATTRIBUTE_NORMAL)
+# define FILE_ATTRIBUTE_NORMAL 0
+# endif /* !defined FILE_ATTRIBUTE_NORMAL */
+# if !defined (MAXIMUM_WAIT_OBJECTS)
+# define MAXIMUM_WAIT_OBJECTS 0
+# endif /* !defined MAXIMUM_WAIT_OBJECTS */
+# if !defined (FILE_FLAG_OVERLAPPED)
+# define FILE_FLAG_OVERLAPPED 0
+# endif /* !defined FILE_FLAG_OVERLAPPED */
+# if !defined (FILE_FLAG_SEQUENTIAL_SCAN)
+# define FILE_FLAG_SEQUENTIAL_SCAN 0
+# endif /* FILE_FLAG_SEQUENTIAL_SCAN */
+# if !defined(FILE_FLAG_WRITE_THROUGH)
+# define FILE_FLAG_WRITE_THROUGH 0
+# endif /* !defined FILE_FLAG_WRITE_THROUGH */
+# if !defined(PIPE_WAIT)
+# define PIPE_WAIT 0
+# endif /* !defined PIPE_WAIT */
+# if !defined(PIPE_NOWAIT)
+# define PIPE_NOWAIT 0
+# endif /* !defined PIPE_WAIT */
+# if !defined(PIPE_READMODE_BYTE)
+# define PIPE_READMODE_BYTE 0
+# endif /* !defined PIPE_READMODE_BYTE */
+# if !defined(PIPE_READMODE_MESSAGE)
+# define PIPE_READMODE_MESSAGE 0
+# endif /* !defined PIPE_READMODE_MESSAGE */
+# if !defined(PIPE_TYPE_BYTE)
+# define PIPE_TYPE_BYTE 0
+# endif /* !defined PIPE_TYPE_BYTE */
+# if !defined(PIPE_TYPE_MESSAGE)
+# define PIPE_TYPE_MESSAGE 0
+# endif /* !defined PIPE_TYPE_MESSAGE */
+#endif /* ACE_WIN32 */
+
+
+// Some useful abstrations for expressions involving
+// ACE_Allocator.malloc (). The difference between ACE_NEW_MALLOC*
+// with ACE_ALLOCATOR* is that they call constructors also.
+
+#include "ace/OS_Errno.h" /* Need errno and ENOMEM */
+
+# define ACE_ALLOCATOR_RETURN(POINTER,ALLOCATOR,RET_VAL) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \
+ } while (0)
+# define ACE_ALLOCATOR(POINTER,ALLOCATOR) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; return; } \
+ } while (0)
+# define ACE_ALLOCATOR_NORETURN(POINTER,ALLOCATOR) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; } \
+ } while (0)
+
+# define ACE_NEW_MALLOC_RETURN(POINTER,ALLOCATOR,CONSTRUCTOR,RET_VAL) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; return RET_VAL;} \
+ else { (void) new (POINTER) CONSTRUCTOR; } \
+ } while (0)
+# define ACE_NEW_MALLOC(POINTER,ALLOCATOR,CONSTRUCTOR) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; return;} \
+ else { (void) new (POINTER) CONSTRUCTOR; } \
+ } while (0)
+# define ACE_NEW_MALLOC_NORETURN(POINTER,ALLOCATOR,CONSTRUCTOR) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM;} \
+ else { (void) new (POINTER) CONSTRUCTOR; } \
+ } while (0)
+
+/* ACE_Metrics */
+#if defined ACE_LACKS_ARRAY_PLACEMENT_NEW
+# define ACE_NEW_MALLOC_ARRAY_RETURN(POINTER,ALLOCATOR,CONSTRUCTOR,COUNT,RET_VAL) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; return RET_VAL;} \
+ else { for (u_int i = 0; i < COUNT; ++i) \
+ {(void) new (POINTER) CONSTRUCTOR; ++POINTER;} \
+ POINTER -= COUNT;} \
+ } while (0)
+# define ACE_NEW_MALLOC_ARRAY(POINTER,ALLOCATOR,CONSTRUCTOR,COUNT) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; return;} \
+ else { for (u_int i = 0; i < COUNT; ++i) \
+ {(void) new (POINTER) CONSTRUCTOR; ++POINTER;} \
+ POINTER -= COUNT;} \
+ } while (0)
+#else /* ! defined ACE_LACKS_ARRAY_PLACEMENT_NEW */
+# define ACE_NEW_MALLOC_ARRAY_RETURN(POINTER,ALLOCATOR,CONSTRUCTOR,COUNT,RET_VAL) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; return RET_VAL;} \
+ else { (void) new (POINTER) CONSTRUCTOR [COUNT]; } \
+ } while (0)
+# define ACE_NEW_MALLOC_ARRAY(POINTER,ALLOCATOR,CONSTRUCTOR,COUNT) \
+ do { POINTER = ALLOCATOR; \
+ if (POINTER == 0) { errno = ENOMEM; return;} \
+ else { (void) new (POINTER) CONSTRUCTOR [COUNT]; } \
+ } while (0)
+#endif /* defined ACE_LACKS_ARRAY_PLACEMENT_NEW */
+
+// This is being placed here temporarily to help stablelize the builds, but will
+// be moved out along with the above macros as part of the subsetting. dhinton
+#if !defined (ACE_LACKS_NEW_H)
+# if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+# include /**/ <new>
+# else
+# include /**/ <new.h>
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+#endif /* ! ACE_LACKS_NEW_H */
+
+# define ACE_NOOP(x)
+
+#if defined (ACE_WIN32)
+# if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+# define ACE_SEH_TRY if (1)
+# define ACE_SEH_EXCEPT(X) while (0)
+# define ACE_SEH_FINALLY if (1)
+# elif defined(__BORLANDC__)
+# define ACE_SEH_TRY try
+# define ACE_SEH_EXCEPT(X) __except(X)
+# define ACE_SEH_FINALLY __finally
+# else
+# define ACE_SEH_TRY __try
+# define ACE_SEH_EXCEPT(X) __except(X)
+# define ACE_SEH_FINALLY __finally
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+# else /* !ACE_WIN32 */
+# define ACE_SEH_TRY if (1)
+# define ACE_SEH_EXCEPT(X) while (0)
+# define ACE_SEH_FINALLY if (1)
+#endif /* ACE_WIN32 */
+
+
+// These should probably be put into a seperate header.
+
+// 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)
+
+// Handle ACE_Message_Queue.
+# define ACE_SYNCH_DECL class _ACE_SYNCH
+# define ACE_SYNCH_USE _ACE_SYNCH
+# define ACE_SYNCH_MUTEX_T typename _ACE_SYNCH::MUTEX
+# define ACE_SYNCH_CONDITION_T typename _ACE_SYNCH::CONDITION
+# define ACE_SYNCH_SEMAPHORE_T typename _ACE_SYNCH::SEMAPHORE
+
+// Handle ACE_Malloc*
+# define ACE_MEM_POOL_1 class _ACE_MEM_POOL
+# define ACE_MEM_POOL_2 _ACE_MEM_POOL
+# define ACE_MEM_POOL _ACE_MEM_POOL
+# define ACE_MEM_POOL_OPTIONS typename _ACE_MEM_POOL::OPTIONS
+
+// Handle ACE_Svc_Handler
+# define ACE_PEER_STREAM_1 class _ACE_PEER_STREAM
+# define ACE_PEER_STREAM_2 _ACE_PEER_STREAM
+# define ACE_PEER_STREAM _ACE_PEER_STREAM
+# define ACE_PEER_STREAM_ADDR typename _ACE_PEER_STREAM::PEER_ADDR
+
+// Handle ACE_Acceptor
+# define ACE_PEER_ACCEPTOR_1 class _ACE_PEER_ACCEPTOR
+# define ACE_PEER_ACCEPTOR_2 _ACE_PEER_ACCEPTOR
+# define ACE_PEER_ACCEPTOR _ACE_PEER_ACCEPTOR
+# define ACE_PEER_ACCEPTOR_ADDR typename _ACE_PEER_ACCEPTOR::PEER_ADDR
+
+// Handle ACE_Connector
+# define ACE_PEER_CONNECTOR_1 class _ACE_PEER_CONNECTOR
+# define ACE_PEER_CONNECTOR_2 _ACE_PEER_CONNECTOR
+# define ACE_PEER_CONNECTOR _ACE_PEER_CONNECTOR
+# define ACE_PEER_CONNECTOR_ADDR typename ACE_PEER_CONNECTOR::PEER_ADDR
+# define ACE_PEER_CONNECTOR_ADDR_ANY ACE_PEER_ADDR_TYPEDEF::sap_any
+
+// Handle ACE_SOCK_*
+# define ACE_SOCK_ACCEPTOR ACE_SOCK_Acceptor
+# define ACE_SOCK_CONNECTOR ACE_SOCK_Connector
+# define ACE_SOCK_STREAM ACE_SOCK_Stream
+# define ACE_SOCK_DGRAM ACE_SOCK_Dgram
+# define ACE_SOCK_DGRAM_BCAST ACE_SOCK_Dgram_Bcast
+# define ACE_SOCK_DGRAM_MCAST ACE_SOCK_Dgram_Mcast
+
+// Handle ACE_SOCK_SEQPACK_*
+# define ACE_SOCK_SEQPACK_ACCEPTOR ACE_SOCK_SEQPACK_Acceptor
+# define ACE_SOCK_SEQPACK_CONNECTOR ACE_SOCK_SEQPACK_Connector
+# define ACE_SOCK_SEQPACK_ASSOCIATION ACE_SOCK_SEQPACK_Association
+
+// Handle ACE_MEM_*
+# define ACE_MEM_ACCEPTOR ACE_MEM_Acceptor
+# define ACE_MEM_CONNECTOR ACE_MEM_Connector
+# define ACE_MEM_STREAM ACE_MEM_Stream
+
+// Handle ACE_LSOCK_*
+# define ACE_LSOCK_ACCEPTOR ACE_LSOCK_Acceptor
+# define ACE_LSOCK_CONNECTOR ACE_LSOCK_Connector
+# define ACE_LSOCK_STREAM ACE_LSOCK_Stream
+
+// Handle ACE_TLI_*
+# define ACE_TLI_ACCEPTOR ACE_TLI_Acceptor
+# define ACE_TLI_CONNECTOR ACE_TLI_Connector
+# define ACE_TLI_STREAM ACE_TLI_Stream
+
+// Handle ACE_SPIPE_*
+# define ACE_SPIPE_ACCEPTOR ACE_SPIPE_Acceptor
+# define ACE_SPIPE_CONNECTOR ACE_SPIPE_Connector
+# define ACE_SPIPE_STREAM ACE_SPIPE_Stream
+
+// Handle ACE_UPIPE_*
+# define ACE_UPIPE_ACCEPTOR ACE_UPIPE_Acceptor
+# define ACE_UPIPE_CONNECTOR ACE_UPIPE_Connector
+# define ACE_UPIPE_STREAM ACE_UPIPE_Stream
+
+// Handle ACE_FILE_*
+# define ACE_FILE_CONNECTOR ACE_FILE_Connector
+# define ACE_FILE_STREAM ACE_FILE_IO
+
+// Handle ACE_*_Memory_Pool.
+# define ACE_MMAP_MEMORY_POOL ACE_MMAP_Memory_Pool
+# define ACE_LITE_MMAP_MEMORY_POOL ACE_Lite_MMAP_Memory_Pool
+# define ACE_SBRK_MEMORY_POOL ACE_Sbrk_Memory_Pool
+# define ACE_SHARED_MEMORY_POOL ACE_Shared_Memory_Pool
+# define ACE_LOCAL_MEMORY_POOL ACE_Local_Memory_Pool
+# define ACE_PAGEFILE_MEMORY_POOL ACE_Pagefile_Memory_Pool
+
+# else /* TEMPLATES are broken in some form or another (i.e., most C++ compilers) */
+
+// Handle ACE_Message_Queue.
+# if defined (ACE_HAS_OPTIMIZED_MESSAGE_QUEUE)
+# define ACE_SYNCH_DECL class _ACE_SYNCH_MUTEX_T, class _ACE_SYNCH_CONDITION_T, class _ACE_SYNCH_SEMAPHORE_T
+# define ACE_SYNCH_USE _ACE_SYNCH_MUTEX_T, _ACE_SYNCH_CONDITION_T, _ACE_SYNCH_SEMAPHORE_T
+# else
+# define ACE_SYNCH_DECL class _ACE_SYNCH_MUTEX_T, class _ACE_SYNCH_CONDITION_T
+# define ACE_SYNCH_USE _ACE_SYNCH_MUTEX_T, _ACE_SYNCH_CONDITION_T
+# endif /* ACE_HAS_OPTIMIZED_MESSAGE_QUEUE */
+# define ACE_SYNCH_MUTEX_T _ACE_SYNCH_MUTEX_T
+# define ACE_SYNCH_CONDITION_T _ACE_SYNCH_CONDITION_T
+# define ACE_SYNCH_SEMAPHORE_T _ACE_SYNCH_SEMAPHORE_T
+
+// Handle ACE_Malloc*
+# define ACE_MEM_POOL_1 class _ACE_MEM_POOL, class _ACE_MEM_POOL_OPTIONS
+# define ACE_MEM_POOL_2 _ACE_MEM_POOL, _ACE_MEM_POOL_OPTIONS
+# define ACE_MEM_POOL _ACE_MEM_POOL
+# define ACE_MEM_POOL_OPTIONS _ACE_MEM_POOL_OPTIONS
+
+// Handle ACE_Svc_Handler
+# define ACE_PEER_STREAM_1 class _ACE_PEER_STREAM, class _ACE_PEER_ADDR
+# define ACE_PEER_STREAM_2 _ACE_PEER_STREAM, _ACE_PEER_ADDR
+# define ACE_PEER_STREAM _ACE_PEER_STREAM
+# define ACE_PEER_STREAM_ADDR _ACE_PEER_ADDR
+
+// Handle ACE_Acceptor
+# define ACE_PEER_ACCEPTOR_1 class _ACE_PEER_ACCEPTOR, class _ACE_PEER_ADDR
+# define ACE_PEER_ACCEPTOR_2 _ACE_PEER_ACCEPTOR, _ACE_PEER_ADDR
+# define ACE_PEER_ACCEPTOR _ACE_PEER_ACCEPTOR
+# define ACE_PEER_ACCEPTOR_ADDR _ACE_PEER_ADDR
+
+// Handle ACE_Connector
+# define ACE_PEER_CONNECTOR_1 class _ACE_PEER_CONNECTOR, class _ACE_PEER_ADDR
+# define ACE_PEER_CONNECTOR_2 _ACE_PEER_CONNECTOR, _ACE_PEER_ADDR
+# define ACE_PEER_CONNECTOR _ACE_PEER_CONNECTOR
+# define ACE_PEER_CONNECTOR_ADDR _ACE_PEER_ADDR
+# define ACE_PEER_CONNECTOR_ADDR_ANY ACE_PEER_CONNECTOR_ADDR::sap_any
+
+// Handle ACE_SOCK_*
+# define ACE_SOCK_ACCEPTOR ACE_SOCK_Acceptor, ACE_INET_Addr
+# define ACE_SOCK_CONNECTOR ACE_SOCK_Connector, ACE_INET_Addr
+# define ACE_SOCK_STREAM ACE_SOCK_Stream, ACE_INET_Addr
+# define ACE_SOCK_DGRAM ACE_SOCK_Dgram, ACE_INET_Addr
+# define ACE_SOCK_DGRAM_BCAST ACE_SOCK_Dgram_Bcast, ACE_INET_Addr
+# define ACE_SOCK_DGRAM_MCAST ACE_SOCK_Dgram_Mcast, ACE_INET_Addr
+
+// Handle ACE_SOCK_SEQPACK_*
+# define ACE_SOCK_SEQPACK_ACCEPTOR ACE_SOCK_SEQPACK_Acceptor, ACE_Multihomed_INET_Addr
+# define ACE_SOCK_SEQPACK_CONNECTOR ACE_SOCK_SEQPACK_Connector, ACE_Multihomed_INET_Addr
+# define ACE_SOCK_SEQPACK_ASSOCIATION ACE_SOCK_SEQPACK_Association, ACE_Multihomed_INET_Addr
+
+// Handle ACE_MEM_*
+# define ACE_MEM_ACCEPTOR ACE_MEM_Acceptor, ACE_MEM_Addr
+# define ACE_MEM_CONNECTOR ACE_MEM_Connector, ACE_INET_Addr
+# define ACE_MEM_STREAM ACE_MEM_Stream, ACE_INET_Addr
+
+// Handle ACE_LSOCK_*
+# define ACE_LSOCK_ACCEPTOR ACE_LSOCK_Acceptor, ACE_UNIX_Addr
+# define ACE_LSOCK_CONNECTOR ACE_LSOCK_Connector, ACE_UNIX_Addr
+# define ACE_LSOCK_STREAM ACE_LSOCK_Stream, ACE_UNIX_Addr
+
+// Handle ACE_TLI_*
+# define ACE_TLI_ACCEPTOR ACE_TLI_Acceptor, ACE_INET_Addr
+# define ACE_TLI_CONNECTOR ACE_TLI_Connector, ACE_INET_Addr
+# define ACE_TLI_STREAM ACE_TLI_Stream, ACE_INET_Addr
+
+// Handle ACE_SPIPE_*
+# define ACE_SPIPE_ACCEPTOR ACE_SPIPE_Acceptor, ACE_SPIPE_Addr
+# define ACE_SPIPE_CONNECTOR ACE_SPIPE_Connector, ACE_SPIPE_Addr
+# define ACE_SPIPE_STREAM ACE_SPIPE_Stream, ACE_SPIPE_Addr
+
+// Handle ACE_UPIPE_*
+# define ACE_UPIPE_ACCEPTOR ACE_UPIPE_Acceptor, ACE_SPIPE_Addr
+# define ACE_UPIPE_CONNECTOR ACE_UPIPE_Connector, ACE_SPIPE_Addr
+# define ACE_UPIPE_STREAM ACE_UPIPE_Stream, ACE_SPIPE_Addr
+
+// Handle ACE_FILE_*
+# define ACE_FILE_CONNECTOR ACE_FILE_Connector, ACE_FILE_Addr
+# define ACE_FILE_STREAM ACE_FILE_IO, ACE_FILE_Addr
+
+// Handle ACE_*_Memory_Pool.
+# define ACE_MMAP_MEMORY_POOL ACE_MMAP_Memory_Pool, ACE_MMAP_Memory_Pool_Options
+# define ACE_LITE_MMAP_MEMORY_POOL ACE_Lite_MMAP_Memory_Pool, ACE_MMAP_Memory_Pool_Options
+# define ACE_SBRK_MEMORY_POOL ACE_Sbrk_Memory_Pool, ACE_Sbrk_Memory_Pool_Options
+# define ACE_SHARED_MEMORY_POOL ACE_Shared_Memory_Pool, ACE_Shared_Memory_Pool_Options
+# define ACE_LOCAL_MEMORY_POOL ACE_Local_Memory_Pool, ACE_Local_Memory_Pool_Options
+# define ACE_PAGEFILE_MEMORY_POOL ACE_Pagefile_Memory_Pool, ACE_Pagefile_Memory_Pool_Options
+# endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+// Work around compilers that don't like in-class static integral
+// constants. Constants in this case are meant to be compile-time
+// constants so that they may be used as template arguments, for
+// example. BOOST provides a similar macro.
+#ifndef ACE_LACKS_STATIC_IN_CLASS_CONSTANTS
+# define ACE_STATIC_CONSTANT(TYPE, ASSIGNMENT) static TYPE const ASSIGNMENT
+#else
+# define ACE_STATIC_CONSTANT(TYPE, ASSIGNMENT) enum { ASSIGNMENT }
+#endif /* !ACE_LACKS_STATIC_IN_CLASS_CONSTANTS */
+
+
+#include /**/ "ace/post.h"
+
+#endif /*ACE_GLOBAL_MACROS_H*/
diff --git a/ACE/ace/Guard_T.cpp b/ACE/ace/Guard_T.cpp
new file mode 100644
index 00000000000..d9c72e30be1
--- /dev/null
+++ b/ACE/ace/Guard_T.cpp
@@ -0,0 +1,61 @@
+// $Id$
+
+#ifndef ACE_GUARD_T_CPP
+#define ACE_GUARD_T_CPP
+
+#include "ace/Guard_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Guard_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_HAS_DUMP)
+# include "ace/Log_Msg.h"
+#endif /* ACE_HAS_DUMP */
+
+// ****************************************************************
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// ACE_ALLOC_HOOK_DEFINE(ACE_Guard)
+
+template <class ACE_LOCK> void
+ACE_Guard<ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Guard<ACE_LOCK>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("mutex_ = %x\n"), this->lock_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("owner_ = %d\n"), this->owner_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// ACE_ALLOC_HOOK_DEFINE(ACE_Write_Guard)
+
+template <class ACE_LOCK> void
+ACE_Write_Guard<ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Write_Guard<ACE_LOCK>::dump");
+ ACE_Guard<ACE_LOCK>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+// ACE_ALLOC_HOOK_DEFINE(ACE_Read_Guard)
+
+template <class ACE_LOCK> void
+ACE_Read_Guard<ACE_LOCK>::dump (void) const
+{
+// ACE_TRACE ("ACE_Read_Guard<ACE_LOCK>::dump");
+ ACE_Guard<ACE_LOCK>::dump ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_GUARD_T_CPP */
diff --git a/ACE/ace/Guard_T.h b/ACE/ace/Guard_T.h
new file mode 100644
index 00000000000..d7eedef2715
--- /dev/null
+++ b/ACE/ace/Guard_T.h
@@ -0,0 +1,365 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Guard_T.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_GUARD_T_H
+#define ACE_GUARD_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Lock.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Guard
+ *
+ * @brief This data structure is meant to be used within a method or
+ * function... It performs automatic aquisition and release of
+ * a parameterized synchronization object <ACE_LOCK>.
+ *
+ * The <ACE_LOCK> class given as an actual parameter must provide at
+ * the very least the <acquire>, <tryacquire>, <release>, and
+ * <remove> methods.
+ */
+template <class ACE_LOCK>
+class ACE_Guard
+{
+public:
+
+ // = Initialization and termination methods.
+ ACE_Guard (ACE_LOCK &l);
+
+ /// Implicitly and automatically acquire (or try to acquire) the
+ /// lock. If @a block is non-0 then <acquire> the <ACE_LOCK>, else
+ /// <tryacquire> it.
+ ACE_Guard (ACE_LOCK &l, int block);
+
+ /// Initialise the guard without implicitly acquiring the lock. The
+ /// <become_owner> parameter indicates whether the guard should release
+ /// the lock implicitly on destruction. The <block> parameter is
+ /// ignored and is used here to disambiguate with the preceding
+ /// constructor.
+ ACE_Guard (ACE_LOCK &l, int block, int become_owner);
+
+ /// Implicitly release the lock.
+ ~ACE_Guard (void);
+
+ // = Lock accessors.
+
+ /// Explicitly acquire the lock.
+ int acquire (void);
+
+ /// Conditionally acquire the lock (i.e., won't block).
+ int tryacquire (void);
+
+ /// Explicitly release the lock, but only if it is held!
+ int release (void);
+
+ /// Relinquish ownership of the lock so that it is not released
+ /// implicitly in the destructor.
+ void disown (void);
+
+ // = Utility methods.
+ /// 1 if locked, 0 if couldn't acquire the lock
+ /// (errno will contain the reason for this).
+ int locked (void) const;
+
+ /// Explicitly remove the lock.
+ int remove (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+protected:
+
+ /// Helper, meant for subclass only.
+ ACE_Guard (ACE_LOCK *lock): lock_ (lock) {}
+
+ /// Pointer to the ACE_LOCK we're guarding.
+ ACE_LOCK *lock_;
+
+ /// Keeps track of whether we acquired the lock or failed.
+ int owner_;
+
+private:
+ // = Prevent assignment and initialization.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Guard<ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Guard (const ACE_Guard<ACE_LOCK> &))
+};
+
+/**
+ * @class ACE_Write_Guard
+ *
+ * @brief This class is similar to class ACE_Guard, though it
+ * acquires/releases a write lock automatically (naturally, the
+ * <ACE_LOCK> it is instantiated with must support the appropriate
+ * API).
+ */
+template <class ACE_LOCK>
+class ACE_Write_Guard : public ACE_Guard<ACE_LOCK>
+{
+public:
+ // = Initialization method.
+
+ /// Implicitly and automatically acquire a write lock.
+ ACE_Write_Guard (ACE_LOCK &m);
+
+ /// Implicitly and automatically acquire (or try to acquire) a write
+ /// lock.
+ ACE_Write_Guard (ACE_LOCK &m, int block);
+
+ // = Lock accessors.
+
+ /// Explicitly acquire the write lock.
+ int acquire_write (void);
+
+ /// Explicitly acquire the write lock.
+ int acquire (void);
+
+ /// Conditionally acquire the write lock (i.e., won't block).
+ int tryacquire_write (void);
+
+ /// Conditionally acquire the write lock (i.e., won't block).
+ int tryacquire (void);
+
+ // = Utility methods.
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+};
+
+/**
+ * @class ACE_Read_Guard
+ *
+ * @brief This class is similar to class ACE_Guard, though it
+ * acquires/releases a read lock automatically (naturally, the
+ * <ACE_LOCK> it is instantiated with must support the appropriate
+ * API).
+ */
+template <class ACE_LOCK>
+class ACE_Read_Guard : public ACE_Guard<ACE_LOCK>
+{
+public:
+ // = Initialization methods.
+
+ /// Implicitly and automatically acquire a read lock.
+ ACE_Read_Guard (ACE_LOCK& m);
+
+ /// Implicitly and automatically acquire (or try to acquire) a read
+ /// lock.
+ ACE_Read_Guard (ACE_LOCK &m, int block);
+
+ // = Lock accessors.
+
+ /// Explicitly acquire the read lock.
+ int acquire_read (void);
+
+ /// Explicitly acquire the read lock.
+ int acquire (void);
+
+ /// Conditionally acquire the read lock (i.e., won't block).
+ int tryacquire_read (void);
+
+ /// Conditionally acquire the read lock (i.e., won't block).
+ int tryacquire (void);
+
+ // = Utility methods.
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+};
+
+#if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)))
+
+#define ACE_TSS_Guard ACE_Guard
+#define ACE_TSS_Write_GUARD ACE_Write_Guard
+#define ACE_TSS_Read_GUARD ACE_Read_Guard
+
+#else
+ /* ACE platform supports some form of threading and
+ thread-specific storage. */
+
+/**
+ * @class ACE_TSS_Guard
+ *
+ * @brief This data structure is meant to be used within a method or
+ * function... It performs automatic aquisition and release of
+ * a synchronization object. Moreover, it ensures that the lock
+ * is released even if a thread exits via <thr_exit>!
+ */
+template <class ACE_LOCK>
+class ACE_TSS_Guard
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Implicitly and automatically acquire the thread-specific lock.
+ ACE_TSS_Guard (ACE_LOCK &lock, int block = 1);
+
+ /// Implicitly release the thread-specific lock.
+ ~ACE_TSS_Guard (void);
+
+ // = Lock accessors.
+
+ /// Explicitly acquire the thread-specific lock.
+ int acquire (void);
+
+ /// Conditionally acquire the thread-specific lock (i.e., won't
+ /// block).
+ int tryacquire (void);
+
+ /// Explicitly release the thread-specific lock.
+ int release (void);
+
+ // = Utility methods.
+ /// Explicitly release the thread-specific lock.
+ int remove (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+protected:
+ /// Helper, meant for subclass only.
+ ACE_TSS_Guard (void);
+
+ /// Initialize the key.
+ void init_key (void);
+
+ /// Called when thread exits to clean up the lock.
+ static void cleanup (void *ptr);
+
+ /// Thread-specific key...
+ ACE_thread_key_t key_;
+
+private:
+ // = Prevent assignment and initialization.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS_Guard<ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_TSS_Guard (const ACE_TSS_Guard<ACE_LOCK> &))
+};
+
+/**
+ * @class ACE_TSS_Write_Guard
+ *
+ * @brief This class is similar to class ACE_TSS_Guard, though it
+ * acquires/releases a write-lock automatically (naturally, the
+ * ACE_LOCK it is instantiated with must support the appropriate
+ * API).
+ */
+template <class ACE_LOCK>
+class ACE_TSS_Write_Guard : public ACE_TSS_Guard<ACE_LOCK>
+{
+public:
+ // = Initialization method.
+
+ /// Implicitly and automatically acquire the thread-specific write lock.
+ ACE_TSS_Write_Guard (ACE_LOCK &lock, int block = 1);
+
+ // = Lock accessors.
+
+ /// Explicitly acquire the thread-specific write lock.
+ int acquire_write (void);
+
+ /// Explicitly acquire the thread-specific write lock.
+ int acquire (void);
+
+ /// Conditionally acquire the thread-specific write lock (i.e., won't block).
+ int tryacquire_write (void);
+
+ /// Conditionally acquire the thread-specific write lock (i.e., won't block).
+ int tryacquire (void);
+
+ // = Utility methods.
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+};
+
+/**
+ * @class ACE_TSS_Read_Guard
+ *
+ * @brief This class is similar to class <ACE_TSS_Guard>, though it
+ * acquires/releases a read lock automatically (naturally, the
+ * <ACE_LOCK> it is instantiated with must support the
+ * appropriate API).
+ */
+template <class ACE_LOCK>
+class ACE_TSS_Read_Guard : public ACE_TSS_Guard<ACE_LOCK>
+{
+public:
+ // = Initialization method.
+ /// Implicitly and automatically acquire the thread-specific read lock.
+ ACE_TSS_Read_Guard (ACE_LOCK &lock, int block = 1);
+
+ // = Lock accessors.
+ /// Explicitly acquire the thread-specific read lock.
+ int acquire_read (void);
+
+ /// Explicitly acquire the thread-specific read lock.
+ int acquire (void);
+
+ /// Conditionally acquire the thread-specific read lock (i.e., won't
+ /// block).
+ int tryacquire_read (void);
+
+ /// Conditionally acquire the thread-specific read lock (i.e., won't
+ /// block).
+ int tryacquire (void);
+
+ // = Utility methods.
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+};
+
+#endif /* !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))) */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Guard_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Guard_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Guard_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_GUARD_T_H */
diff --git a/ACE/ace/Guard_T.inl b/ACE/ace/Guard_T.inl
new file mode 100644
index 00000000000..c9dbcc3d5e8
--- /dev/null
+++ b/ACE/ace/Guard_T.inl
@@ -0,0 +1,170 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/RW_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Guard<ACE_LOCK>::acquire (void)
+{
+ return this->owner_ = this->lock_->acquire ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Guard<ACE_LOCK>::tryacquire (void)
+{
+ return this->owner_ = this->lock_->tryacquire ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Guard<ACE_LOCK>::release (void)
+{
+ if (this->owner_ == -1)
+ return -1;
+ else
+ {
+ this->owner_ = -1;
+ return this->lock_->release ();
+ }
+}
+
+template <class ACE_LOCK> ACE_INLINE
+ACE_Guard<ACE_LOCK>::ACE_Guard (ACE_LOCK &l)
+ : lock_ (&l),
+ owner_ (0)
+{
+ this->acquire ();
+}
+
+template <class ACE_LOCK> ACE_INLINE
+ACE_Guard<ACE_LOCK>::ACE_Guard (ACE_LOCK &l, int block)
+ : lock_ (&l),
+ owner_ (0)
+{
+ if (block)
+ this->acquire ();
+ else
+ this->tryacquire ();
+}
+
+template <class ACE_LOCK> ACE_INLINE
+ACE_Guard<ACE_LOCK>::ACE_Guard (ACE_LOCK &l, int /* block */, int become_owner)
+ : lock_ (&l),
+ owner_ (become_owner == 0 ? -1 : 0)
+{
+}
+
+// Implicitly and automatically acquire (or try to acquire) the
+// lock.
+
+template <class ACE_LOCK> ACE_INLINE
+ACE_Guard<ACE_LOCK>::~ACE_Guard (void)
+{
+ this->release ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Guard<ACE_LOCK>::locked (void) const
+{
+ return this->owner_ != -1;
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Guard<ACE_LOCK>::remove (void)
+{
+ return this->lock_->remove ();
+}
+
+template <class ACE_LOCK> ACE_INLINE void
+ACE_Guard<ACE_LOCK>::disown (void)
+{
+ this->owner_ = -1;
+}
+
+template <class ACE_LOCK> ACE_INLINE
+ACE_Write_Guard<ACE_LOCK>::ACE_Write_Guard (ACE_LOCK &m)
+ : ACE_Guard<ACE_LOCK> (&m)
+{
+ this->acquire_write ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Write_Guard<ACE_LOCK>::acquire_write (void)
+{
+ return this->owner_ = this->lock_->acquire_write ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Write_Guard<ACE_LOCK>::acquire (void)
+{
+ return this->owner_ = this->lock_->acquire_write ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Write_Guard<ACE_LOCK>::tryacquire_write (void)
+{
+ return this->owner_ = this->lock_->tryacquire_write ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Write_Guard<ACE_LOCK>::tryacquire (void)
+{
+ return this->owner_ = this->lock_->tryacquire_write ();
+}
+
+template <class ACE_LOCK> ACE_INLINE
+ACE_Write_Guard<ACE_LOCK>::ACE_Write_Guard (ACE_LOCK &m,
+ int block)
+ : ACE_Guard<ACE_LOCK> (&m)
+{
+ if (block)
+ this->acquire_write ();
+ else
+ this->tryacquire_write ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Read_Guard<ACE_LOCK>::acquire_read (void)
+{
+ return this->owner_ = this->lock_->acquire_read ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Read_Guard<ACE_LOCK>::acquire (void)
+{
+ return this->owner_ = this->lock_->acquire_read ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Read_Guard<ACE_LOCK>::tryacquire_read (void)
+{
+ return this->owner_ = this->lock_->tryacquire_read ();
+}
+
+template <class ACE_LOCK> ACE_INLINE int
+ACE_Read_Guard<ACE_LOCK>::tryacquire (void)
+{
+ return this->owner_ = this->lock_->tryacquire_read ();
+}
+
+template <class ACE_LOCK> ACE_INLINE
+ACE_Read_Guard<ACE_LOCK>::ACE_Read_Guard (ACE_LOCK &m)
+ : ACE_Guard<ACE_LOCK> (&m)
+{
+ this->acquire_read ();
+}
+
+template <class ACE_LOCK> ACE_INLINE
+ACE_Read_Guard<ACE_LOCK>::ACE_Read_Guard (ACE_LOCK &m,
+ int block)
+ : ACE_Guard<ACE_LOCK> (&m)
+{
+ if (block)
+ this->acquire_read ();
+ else
+ this->tryacquire_read ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Handle_Gobbler.h b/ACE/ace/Handle_Gobbler.h
new file mode 100644
index 00000000000..8d1fb52b580
--- /dev/null
+++ b/ACE/ace/Handle_Gobbler.h
@@ -0,0 +1,68 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Handle_Gobbler.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_HANDLE_GOBBLER_H
+#define ACE_HANDLE_GOBBLER_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Handle_Set.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Handle_Gobbler
+ *
+ * @brief This class gobbles up handles.
+ *
+ * This is useful when we need to control the number of handles
+ * available for a process. This class is mostly used for
+ * testing purposes.
+ */
+class ACE_Handle_Gobbler
+{
+public:
+
+ /// Destructor. Cleans up any remaining handles.
+ inline ~ACE_Handle_Gobbler (void);
+
+ /**
+ * Handles are opened continously until the process runs out of
+ * them, and then <n_handles_to_keep_available> handles are closed
+ * (freed) thereby making them usable in the future.
+ */
+ inline int consume_handles (size_t n_handles_to_keep_available);
+
+ /// Free up @a n_handles.
+ inline int free_handles (size_t n_handles);
+
+ /// All remaining handles are closed.
+ inline void close_remaining_handles (void);
+
+private:
+ typedef ACE_Handle_Set HANDLE_SET;
+
+ /// The container which holds the open descriptors.
+ HANDLE_SET handle_set_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include "ace/Handle_Gobbler.inl"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HANDLE_GOBBLER_H */
diff --git a/ACE/ace/Handle_Gobbler.inl b/ACE/ace/Handle_Gobbler.inl
new file mode 100644
index 00000000000..e44035a7aed
--- /dev/null
+++ b/ACE/ace/Handle_Gobbler.inl
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// Since this is only included in Handle_Gobbler.h, these should be
+// inline, not ACE_INLINE.
+// FUZZ: disable check_for_inline
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+inline void
+ACE_Handle_Gobbler::close_remaining_handles (void)
+{
+ ACE_Handle_Set_Iterator iter (this->handle_set_);
+ for (ACE_HANDLE h = iter (); h != ACE_INVALID_HANDLE; h = iter ())
+ ACE_OS::close (h);
+}
+
+inline
+ACE_Handle_Gobbler::~ACE_Handle_Gobbler (void)
+{
+ this->close_remaining_handles ();
+}
+
+inline int
+ACE_Handle_Gobbler::free_handles (size_t n_handles)
+{
+ ACE_Handle_Set_Iterator iter (this->handle_set_);
+ for (ACE_HANDLE h = iter ();
+ h != ACE_INVALID_HANDLE && n_handles > 0;
+ --n_handles, h = iter ())
+ ACE_OS::close (h);
+
+ return 0;
+}
+
+inline int
+ACE_Handle_Gobbler::consume_handles (size_t n_handles_to_keep_available)
+{
+ int result = 0;
+
+#if defined(ACE_WIN32)
+ // On Win32, this style of gobbling doesn't seem to work.
+ ACE_UNUSED_ARG(n_handles_to_keep_available);
+
+#else
+
+ while (1)
+ {
+ ACE_HANDLE handle = ACE_OS::open (ACE_DEV_NULL, O_WRONLY);
+
+ if (handle == ACE_INVALID_HANDLE)
+ {
+ if (ACE::out_of_handles (errno))
+ {
+ result = this->free_handles (n_handles_to_keep_available);
+ break;
+ }
+ else
+ {
+ result = -1;
+ break;
+ }
+ }
+ if (handle >= FD_SETSIZE)
+ break;
+ this->handle_set_.set_bit (handle);
+ }
+
+#endif /* ACE_WIN32 */
+
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Handle_Ops.cpp b/ACE/ace/Handle_Ops.cpp
new file mode 100644
index 00000000000..2b9db431aef
--- /dev/null
+++ b/ACE/ace/Handle_Ops.cpp
@@ -0,0 +1,48 @@
+// $Id$
+
+#include "ace/Handle_Ops.h"
+
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/Time_Value.h"
+
+ACE_RCSID (ace,
+ Handle_Ops,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_HANDLE
+ACE::handle_timed_open (ACE_Time_Value *timeout,
+ const ACE_TCHAR *name,
+ int flags,
+ int perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE::handle_timed_open");
+
+ if (timeout != 0)
+ {
+#if !defined (ACE_WIN32)
+ // On Win32, ACE_NONBLOCK gets recognized as O_WRONLY so we
+ // don't use it there
+ flags |= ACE_NONBLOCK;
+#endif /* ACE_WIN32 */
+
+ // Open the named pipe or file using non-blocking mode...
+ ACE_HANDLE const handle = ACE_OS::open (name, flags, perms, sa);
+
+ if (handle == ACE_INVALID_HANDLE
+ && (errno == EWOULDBLOCK
+ && (timeout->sec () > 0 || timeout->usec () > 0)))
+ // This expression checks if we were polling.
+ errno = ETIMEDOUT;
+
+ return handle;
+ }
+ else
+ return ACE_OS::open (name, flags, perms, sa);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Handle_Ops.h b/ACE/ace/Handle_Ops.h
new file mode 100644
index 00000000000..233c161fb03
--- /dev/null
+++ b/ACE/ace/Handle_Ops.h
@@ -0,0 +1,50 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Handle_Ops.h
+ *
+ * $Id$
+ *
+ * Handle operations.
+ */
+//=============================================================================
+
+#ifndef ACE_HANDLE_OPS_H
+#define ACE_HANDLE_OPS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+// = Operations on HANDLEs.
+namespace ACE
+{
+ /**
+ * Wait up to @a timeout amount of time to actively open a device.
+ * This method doesn't perform the @c connect, it just does the
+ * timed wait.
+ */
+ extern ACE_Export ACE_HANDLE handle_timed_open (
+ ACE_Time_Value *timeout,
+ const ACE_TCHAR *name,
+ int flags,
+ int perms,
+ LPSECURITY_ATTRIBUTES sa = 0);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_HANDLE_OPS_H */
diff --git a/ACE/ace/Handle_Set.cpp b/ACE/ace/Handle_Set.cpp
new file mode 100644
index 00000000000..05a85cb338a
--- /dev/null
+++ b/ACE/ace/Handle_Set.cpp
@@ -0,0 +1,570 @@
+// Handle_Set.cpp
+// $Id$
+
+#include "ace/Handle_Set.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Handle_Set.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(ace, Handle_Set, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set)
+
+ // ACE_MSB_MASK is only used here.
+ // This needs to go here to avoid overflow problems on some compilers.
+#if defined (ACE_WIN32)
+ // Does ACE_WIN32 have an fd_mask?
+# define ACE_MSB_MASK (~(1 << (NFDBITS - 1)))
+#else /* ! ACE_WIN32 */
+# define ACE_MSB_MASK (~((fd_mask) 1 << (NFDBITS - 1)))
+#endif /* ! ACE_WIN32 */
+
+#if defined (__BORLANDC__) && !defined (ACE_WIN32)
+// The Borland C++ compiler on Linux also doesn't have fds_bits, but has __fds_bits.
+#define fds_bits __fds_bits
+#endif
+
+#if defined (linux) && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1 && !defined (_XOPEN_SOURCE)
+ // XPG4.2 requires the fds_bits member name, so it is not enabled by
+ // default on Linux/glibc-2.1.x systems. Instead use "__fds_bits."
+ // Ugly, but "what are you going to do?" 8-)
+#define fds_bits __fds_bits
+#endif /* linux && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1 && !_XOPEN_SOURCE */
+
+void
+ACE_Handle_Set::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Handle_Set::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nsize_ = %d"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmax_handle_ = %d"), this->max_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n[ ")));
+
+#if defined (ACE_WIN32)
+ for (size_t i = 0; i < (size_t) this->mask_.fd_count + 1; i++)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" %x "), this->mask_.fd_array[i]));
+#else /* !ACE_WIN32 */
+ for (ACE_HANDLE i = 0; i < this->max_handle_ + 1; i++)
+ if (this->is_set (i))
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" %d "), i));
+#endif /* ACE_WIN32 */
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" ]\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// Table that maps bytes to counts of the enabled bits in each value
+// from 0 to 255,
+//
+// nbits_[0] == 0
+//
+// because there are no bits enabled for the value 0.
+//
+// nbits_[5] == 2
+//
+// because there are 2 bits enabled in the value 5, i.e., it's
+// 101 in binary.
+
+const char ACE_Handle_Set::nbits_[256] =
+{
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
+
+// Constructor, initializes the bitmask to all 0s.
+
+ACE_Handle_Set::ACE_Handle_Set (void)
+{
+ ACE_TRACE ("ACE_Handle_Set::ACE_Handle_Set");
+ this->reset ();
+}
+
+ACE_Handle_Set::ACE_Handle_Set (const fd_set &fd_mask)
+{
+ ACE_TRACE ("ACE_Handle_Set::ACE_Handle_Set");
+ this->reset ();
+ ACE_OS::memcpy ((void *) &this->mask_,
+ (void *) &fd_mask,
+ sizeof this->mask_);
+#if !defined (ACE_WIN32)
+ this->sync (ACE_Handle_Set::MAXSIZE);
+#if defined (ACE_HAS_BIG_FD_SET)
+ this->min_handle_ = 0;
+#endif /* ACE_HAS_BIG_FD_SET */
+#endif /* !ACE_WIN32 */
+}
+
+// Counts the number of bits enabled in N. Uses a table lookup to
+// speed up the count.
+
+int
+ACE_Handle_Set::count_bits (u_long n)
+{
+
+ ACE_TRACE ("ACE_Handle_Set::count_bits");
+#if defined (ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT)
+ register int rval = 0;
+
+ // Count the number of enabled bits in <n>. This algorithm is very
+ // fast, i.e., O(enabled bits in n).
+
+ for (register u_long m = n;
+ m != 0;
+ m &= m - 1)
+ rval++;
+
+ return rval;
+#else
+ return (ACE_Handle_Set::nbits_[n & 0xff]
+ + ACE_Handle_Set::nbits_[(n >> 8) & 0xff]
+ + ACE_Handle_Set::nbits_[(n >> 16) & 0xff]
+ + ACE_Handle_Set::nbits_[(n >> 24) & 0xff]);
+#endif /* ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT */
+}
+
+#if defined (ACE_HAS_BIG_FD_SET)
+// Find the bit position counting from right to left worst case
+// (1<<31) is 8.
+
+int
+ACE_Handle_Set::bitpos (u_long bit)
+{
+ register int l = 0;
+ register u_long n = bit - 1;
+
+ // This is a fast count method when have the most significative bit.
+
+ while (n >> 8)
+ {
+ n >>= 8;
+ l += 8;
+ }
+
+ // Is greater than 15?
+ if (n & 16)
+ {
+ n >>= 4;
+ l += 4;
+ }
+
+ // Count number remaining bits.
+ while (n != 0)
+ {
+ n &= n - 1;
+ l++;
+ }
+ return l;
+}
+#endif /* ACE_HAS_BIG_FD_SET */
+
+// Synchronize the underlying FD_SET with the MAX_FD and the SIZE.
+
+#if defined (ACE_USE_SHIFT_FOR_EFFICIENCY)
+// These don't work because shifting right 3 bits is not the same as
+// dividing by 3, e.g., dividing by 8 requires shifting right 3 bits.
+// In order to do the shift, we need to calculate the number of bits
+// at some point.
+#define ACE_DIV_BY_WORDSIZE(x) ((x) >> ((int) ACE_Handle_Set::WORDSIZE))
+#define ACE_MULT_BY_WORDSIZE(x) ((x) << ((int) ACE_Handle_Set::WORDSIZE))
+#else
+#define ACE_DIV_BY_WORDSIZE(x) ((x) / ((int) ACE_Handle_Set::WORDSIZE))
+#define ACE_MULT_BY_WORDSIZE(x) ((x) * ((int) ACE_Handle_Set::WORDSIZE))
+#endif /* ACE_USE_SHIFT_FOR_EFFICIENCY */
+
+void
+ACE_Handle_Set::sync (ACE_HANDLE max)
+{
+ ACE_TRACE ("ACE_Handle_Set::sync");
+#if !defined (ACE_WIN32)
+ fd_mask *maskp = (fd_mask *)(this->mask_.fds_bits);
+ this->size_ = 0;
+
+ for (int i = ACE_DIV_BY_WORDSIZE (max - 1);
+ i >= 0;
+ i--)
+ this->size_ += ACE_Handle_Set::count_bits (maskp[i]);
+
+ this->set_max (max);
+#else
+ ACE_UNUSED_ARG (max);
+#endif /* !ACE_WIN32 */
+}
+
+// Resets the MAX_FD after a clear of the original MAX_FD.
+
+void
+ACE_Handle_Set::set_max (ACE_HANDLE current_max)
+{
+ ACE_TRACE ("ACE_Handle_Set::set_max");
+#if !defined(ACE_WIN32)
+ fd_mask * maskp = (fd_mask *)(this->mask_.fds_bits);
+
+ if (this->size_ == 0)
+ this->max_handle_ = ACE_INVALID_HANDLE;
+ else
+ {
+ int i;
+
+ for (i = ACE_DIV_BY_WORDSIZE (current_max - 1);
+ maskp[i] == 0;
+ i--)
+ continue;
+#if defined (ACE_TANDEM_NSK_BIT_ORDER)
+ // bits are in reverse order, MSB (sign bit) = bit 0.
+ this->max_handle_ = ACE_MULT_BY_WORDSIZE (i);
+ for (fd_mask val = maskp[i];
+ (val & ACE_MSB_MASK) != 0;
+ val = (val << 1))
+ ++this->max_handle_;
+#elif 1 /* !defined(ACE_HAS_BIG_FD_SET) */
+ this->max_handle_ = ACE_MULT_BY_WORDSIZE (i);
+ for (fd_mask val = maskp[i];
+ (val & ~1) != 0; // This obscure code is needed since "bit 0" is in location 1...
+ val = (val >> 1) & ACE_MSB_MASK)
+ ++this->max_handle_;
+#else
+ register u_long val = this->mask_.fds_bits[i];
+ this->max_handle_ = ACE_MULT_BY_WORDSIZE (i)
+ + ACE_Handle_Set::bitpos(val & ~(val - 1));
+#endif /* 1 */
+ }
+
+ // Do some sanity checking...
+ if (this->max_handle_ >= ACE_Handle_Set::MAXSIZE)
+ this->max_handle_ = ACE_Handle_Set::MAXSIZE - 1;
+#else
+ ACE_UNUSED_ARG (current_max);
+#endif /* !ACE_WIN32 */
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set_Iterator)
+
+void
+ACE_Handle_Set_Iterator::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Handle_Set_Iterator::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+#if defined(ACE_WIN32) || !defined(ACE_HAS_BIG_FD_SET)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhandle_index_ = %d"), this->handle_index_));
+#elif defined(ACE_HAS_BIG_FD_SET)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nword_max_ = %d"), this->word_max_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nword_val_ = %d"), this->word_val_));
+#endif
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nword_num_ = %d"), this->word_num_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_HANDLE
+ACE_Handle_Set_Iterator::operator () (void)
+{
+ ACE_TRACE ("ACE_Handle_Set_Iterator::operator");
+#if defined (ACE_WIN32)
+ if (this->handle_index_ < this->handles_.mask_.fd_count)
+ // Return the handle and advance the iterator.
+ return (ACE_HANDLE) this->handles_.mask_.fd_array[this->handle_index_++];
+ else
+ return ACE_INVALID_HANDLE;
+
+#elif !defined (ACE_HAS_BIG_FD_SET) /* !ACE_WIN32 */
+ // No sense searching further than the max_handle_ + 1;
+ ACE_HANDLE maxhandlep1 = this->handles_.max_handle_ + 1;
+
+ // HP-UX 11 plays some games with the fd_mask type - fd_mask is
+ // defined as an int_32t, but the fds_bits is an array of longs.
+ // This makes plainly indexing through the array by hand tricky,
+ // since the FD_* macros treat the array as int32_t. So the bits
+ // are in the right place for int32_t, even though the array is
+ // long. This, they say, is to preserve the same in-memory layout
+ // for 32-bit and 64-bit processes. So, we play the same game as
+ // the FD_* macros to get the bits right. On all other systems,
+ // this amounts to practically a NOP, since this is what would have
+ // been done anyway, without all this type jazz.
+ fd_mask * maskp = (fd_mask *)(this->handles_.mask_.fds_bits);
+
+ if (this->handle_index_ >= maxhandlep1)
+ // We've seen all the handles we're interested in seeing for this
+ // iterator.
+ return ACE_INVALID_HANDLE;
+ else
+ {
+ ACE_HANDLE result = this->handle_index_;
+
+ // Increment the iterator and advance to the next bit in this
+ // word.
+ this->handle_index_++;
+#if defined (ACE_TANDEM_NSK_BIT_ORDER)
+ // bits are in reverse order, MSB (sign bit) = bit 0.
+ this->word_val_ = (this->word_val_ << 1);
+# else
+ this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK;
+# endif /* ACE_TANDEM_NSK_BIT_ORDER */
+
+ // If we've examined all the bits in this word, we'll go onto
+ // the next word.
+
+ if (this->word_val_ == 0)
+ {
+ // Start the handle_index_ at the beginning of the next word
+ // and then loop until we've found the first non-zero bit or
+ // we run past the <maxhandlep1> of the bitset.
+
+ for (this->handle_index_ = ACE_MULT_BY_WORDSIZE(++this->word_num_);
+ this->handle_index_ < maxhandlep1
+ && maskp[this->word_num_] == 0;
+ this->word_num_++)
+ this->handle_index_ += ACE_Handle_Set::WORDSIZE;
+
+ // If the bit index becomes >= the maxhandlep1 that means
+ // there weren't any more bits set that we want to consider.
+ // Therefore, we'll just store the maxhandlep1, which will
+ // cause <operator()> to return <ACE_INVALID_HANDLE>
+ // immediately next time it's called.
+ if (this->handle_index_ >= maxhandlep1)
+ {
+ this->handle_index_ = maxhandlep1;
+ return result;
+ }
+ else
+ // Load the bits of the next word.
+ this->word_val_ = maskp[this->word_num_];
+ }
+
+ // Loop until we get <word_val_> to have its least significant
+ // bit enabled, keeping track of which <handle_index> this
+ // represents (this information is used by subsequent calls to
+ // <operator()>).
+
+#if defined (ACE_TANDEM_NSK_BIT_ORDER)
+ // bits are in reverse order, MSB (sign bit) = bit 0.
+ for (;
+ this->word_val_ > 0;
+ this->word_val_ = (this->word_val_ << 1))
+ this->handle_index_++;
+# else
+ for (;
+ ACE_BIT_DISABLED (this->word_val_, 1);
+ this->handle_index_++)
+ this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK;
+# endif /* ACE_TANDEM_NSK_BIT_ORDER */
+
+ return result;
+ }
+#else /* !ACE_HAS_BIG_FD_SET */
+ // Find the first word in fds_bits with bit on
+ register u_long lsb = this->word_val_;
+
+ if (lsb == 0)
+ {
+ do
+ {
+ // We have exceeded the word count in Handle_Set?
+ if (++this->word_num_ >= this->word_max_)
+ return ACE_INVALID_HANDLE;
+
+ lsb = this->handles_.mask_.fds_bits[this->word_num_];
+ }
+ while (lsb == 0);
+
+ // Set index to word boundary.
+ this->handle_index_ = ACE_MULT_BY_WORDSIZE (this->word_num_);
+
+ // Put new word_val.
+ this->word_val_ = lsb;
+
+ // Find the least significative bit.
+ lsb &= ~(lsb - 1);
+
+ // Remove least significative bit.
+ this->word_val_ ^= lsb;
+
+ // Save to calculate bit distance.
+ this->oldlsb_ = lsb;
+
+ // Move index to least significative bit.
+ while (lsb >>= 1)
+ this->handle_index_++;
+ }
+ else
+ {
+ // Find the least significative bit.
+ lsb &= ~(lsb - 1);
+
+ // Remove least significative bit.
+ this->word_val_ ^= lsb;
+
+ register u_long n = lsb - this->oldlsb_;
+
+ // Move index to bit distance between new lsb and old lsb.
+ do
+ {
+ this->handle_index_++;
+ n &= n >> 1;
+ }
+ while (n != 0);
+
+ this->oldlsb_ = lsb;
+ }
+
+ return this->handle_index_;
+#endif /* ACE_WIN32 */
+}
+
+ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator (const ACE_Handle_Set &hs)
+ : handles_ (hs),
+#if !defined (ACE_HAS_BIG_FD_SET) || defined (ACE_WIN32)
+ handle_index_ (0),
+ word_num_ (-1)
+#elif defined (ACE_HAS_BIG_FD_SET)
+ oldlsb_ (0),
+ word_max_ (hs.max_handle_ == ACE_INVALID_HANDLE
+ ? 0
+ : ((ACE_DIV_BY_WORDSIZE (hs.max_handle_)) + 1))
+#endif /* ACE_HAS_BIG_FD_SET */
+{
+ ACE_TRACE ("ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator");
+#if !defined (ACE_WIN32) && !defined (ACE_HAS_BIG_FD_SET)
+ // No sense searching further than the max_handle_ + 1;
+ ACE_HANDLE maxhandlep1 =
+ this->handles_.max_handle_ + 1;
+
+ fd_mask *maskp =
+ (fd_mask *)(this->handles_.mask_.fds_bits);
+
+ // Loop until we've found the first non-zero bit or we run past the
+ // <maxhandlep1> of the bitset.
+ while (this->handle_index_ < maxhandlep1
+ && maskp[++this->word_num_] == 0)
+ this->handle_index_ += ACE_Handle_Set::WORDSIZE;
+
+ // If the bit index becomes >= the maxhandlep1 that means there
+ // weren't any bits set. Therefore, we'll just store the
+ // maxhandlep1, which will cause <operator()> to return
+ // <ACE_INVALID_HANDLE> immediately.
+ if (this->handle_index_ >= maxhandlep1)
+ this->handle_index_ = maxhandlep1;
+ else
+ // Loop until we get <word_val_> to have its least significant bit
+ // enabled, keeping track of which <handle_index> this represents
+ // (this information is used by <operator()>).
+#if defined (ACE_TANDEM_NSK_BIT_ORDER)
+ // bits are in reverse order, MSB (sign bit) = bit 0.
+ for (this->word_val_ = maskp[this->word_num_];
+ this->word_val_ > 0;
+ this->word_val_ = (this->word_val_ << 1))
+ this->handle_index_++;
+# else
+ for (this->word_val_ = maskp[this->word_num_];
+ ACE_BIT_DISABLED (this->word_val_, 1)
+ && this->handle_index_ < maxhandlep1;
+ this->handle_index_++)
+ this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK;
+# endif /* ACE_TANDEM_NSK_BIT_ORDER */
+#elif !defined (ACE_WIN32) && defined (ACE_HAS_BIG_FD_SET)
+ if (this->word_max_==0)
+ {
+ this->word_num_ = -1;
+ this->word_val_ = 0;
+ }
+ else
+ {
+ this->word_num_ =
+ ACE_DIV_BY_WORDSIZE (this->handles_.min_handle_) - 1;
+ this->word_val_ = 0;
+ }
+#endif /* !ACE_WIN32 && !ACE_HAS_BIG_FD_SET */
+}
+
+
+void
+ACE_Handle_Set_Iterator::reset_state (void)
+{
+ ACE_TRACE ("ACE_Handle_Set_Iterator::reset_state");
+
+#if !defined (ACE_HAS_BIG_FD_SET) || defined (ACE_WIN32)
+ this->handle_index_ = 0;
+ this->word_num_ = -1;
+#elif defined (ACE_HAS_BIG_FD_SET)
+ this->oldlsb_ = 0;
+ this->word_max_ =
+ this->handles_.max_handle_ == ACE_INVALID_HANDLE ? 0
+ : ((ACE_DIV_BY_WORDSIZE (this->handles_.max_handle_)) + 1);
+#endif /* ACE_HAS_BIG_FD_SET */
+
+#if !defined (ACE_WIN32) && !defined (ACE_HAS_BIG_FD_SET)
+ // No sense searching further than the max_handle_ + 1;
+ ACE_HANDLE maxhandlep1 =
+ this->handles_.max_handle_ + 1;
+
+ fd_mask *maskp =
+ (fd_mask *)(this->handles_.mask_.fds_bits);
+
+ // Loop until we've found the first non-zero bit or we run past the
+ // <maxhandlep1> of the bitset.
+ while (this->handle_index_ < maxhandlep1
+ && maskp[++this->word_num_] == 0)
+ this->handle_index_ += ACE_Handle_Set::WORDSIZE;
+
+ // If the bit index becomes >= the maxhandlep1 that means there
+ // weren't any bits set. Therefore, we'll just store the
+ // maxhandlep1, which will cause <operator()> to return
+ // <ACE_INVALID_HANDLE> immediately.
+ if (this->handle_index_ >= maxhandlep1)
+ this->handle_index_ = maxhandlep1;
+ else
+ // Loop until we get <word_val_> to have its least significant bit
+ // enabled, keeping track of which <handle_index> this represents
+ // (this information is used by <operator()>).
+#if defined (ACE_TANDEM_NSK_BIT_ORDER)
+ // bits are in reverse order, MSB (sign bit) = bit 0.
+ for (this->word_val_ = maskp[this->word_num_];
+ this->word_val_ > 0;
+ this->word_val_ = (this->word_val_ << 1))
+ this->handle_index_++;
+# else
+ for (this->word_val_ = maskp[this->word_num_];
+ ACE_BIT_DISABLED (this->word_val_, 1)
+ && this->handle_index_ < maxhandlep1;
+ this->handle_index_++)
+ this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK;
+# endif /* ACE_TANDEM_NSK_BIT_ORDER */
+#elif !defined (ACE_WIN32) && defined (ACE_HAS_BIG_FD_SET)
+ if (this->word_max_==0)
+ {
+ this->word_num_ = -1;
+ this->word_val_ = 0;
+ }
+ else
+ {
+ this->word_num_ =
+ ACE_DIV_BY_WORDSIZE (this->handles_.min_handle_) - 1;
+ this->word_val_ = 0;
+ }
+#endif /* !ACE_WIN32 && !ACE_HAS_BIG_FD_SET */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Handle_Set.h b/ACE/ace/Handle_Set.h
new file mode 100644
index 00000000000..845c332526a
--- /dev/null
+++ b/ACE/ace/Handle_Set.h
@@ -0,0 +1,240 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Handle_Set.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_HANDLE_SET_H
+#define ACE_HANDLE_SET_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_select.h"
+#include "ace/os_include/os_limits.h"
+
+#if defined (__QNX__)
+ typedef long fd_mask;
+#endif /* __QNX__ */
+
+// Default size of the ACE Reactor.
+#if defined (FD_SETSIZE)
+ int const ACE_FD_SETSIZE = FD_SETSIZE;
+#else /* !FD_SETSIZE */
+# define ACE_FD_SETSIZE FD_SETSIZE
+#endif /* ACE_FD_SETSIZE */
+
+#if !defined (ACE_DEFAULT_SELECT_REACTOR_SIZE)
+# define ACE_DEFAULT_SELECT_REACTOR_SIZE ACE_FD_SETSIZE
+#endif /* ACE_DEFAULT_SELECT_REACTOR_SIZE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Handle_Set
+ *
+ * @brief C++ wrapper facade for the socket @c fd_set abstraction.
+ *
+ * This abstraction is a very efficient wrapper facade over
+ * @c fd_set. In particular, no range checking is performed, so
+ * it's important not to set or clear bits that are outside the
+ * @c ACE_DEFAULT_SELECT_REACTOR_SIZE.
+ */
+class ACE_Export ACE_Handle_Set
+{
+public:
+ friend class ACE_Handle_Set_Iterator;
+
+ // = Initialization and termination.
+
+ enum
+ {
+ MAXSIZE = ACE_DEFAULT_SELECT_REACTOR_SIZE
+ };
+
+ // = Initialization methods.
+ /// Constructor, initializes the bitmask to all 0s.
+ ACE_Handle_Set (void);
+
+ /**
+ * Constructor, initializes the handle set from a given mask.
+ */
+ ACE_Handle_Set (const fd_set &mask);
+
+ // = Methods for manipulating bitsets.
+ /// Initialize the bitmask to all 0s and reset the associated fields.
+ void reset (void);
+
+ /**
+ * Checks whether @a handle is enabled. No range checking is
+ * performed so @a handle must be less than
+ * @c ACE_DEFAULT_SELECT_REACTOR_SIZE.
+ */
+ int is_set (ACE_HANDLE handle) const;
+
+ /// Enables the @a handle. No range checking is performed so @a handle
+ /// must be less than @c ACE_DEFAULT_SELECT_REACTOR_SIZE.
+ void set_bit (ACE_HANDLE handle);
+
+ /// Disables the @a handle. No range checking is performed so
+ /// @a handle must be less than @c ACE_DEFAULT_SELECT_REACTOR_SIZE.
+ void clr_bit (ACE_HANDLE handle);
+
+ /// Returns a count of the number of enabled bits.
+ int num_set (void) const;
+
+ /// Returns the number of the large bit.
+ ACE_HANDLE max_set (void) const;
+
+ /**
+ * Rescan the underlying @c fd_set up to handle @a max to find the new
+ * <max_handle> (highest bit set) and <size> (how many bits set) values.
+ * This is useful for evaluating the changes after the handle set has
+ * been manipulated in some way other than member functions; for example,
+ * after <select> modifies the @c fd_set.
+ */
+ void sync (ACE_HANDLE max);
+
+ /// Returns a pointer to the underlying @c fd_set. Returns 0 if
+ /// there are no handle bits set (<size_> == 0).
+ operator fd_set *();
+
+ /// Returns a pointer to the underlying @c fd_set. Returns 0 if
+ /// there are no handle bits set (<size_> == 0).
+ fd_set *fdset (void);
+
+#if defined (ACE_HAS_BIG_FD_SET)
+ /// Assignment operator optimizes for cases where <size_> == 0.
+ ACE_Handle_Set & operator= (const ACE_Handle_Set &);
+#endif /* ACE_HAS_BIG_FD_SET */
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Size of the set, i.e., a count of the number of enabled bits.
+ int size_;
+
+ /// Current max handle.
+ ACE_HANDLE max_handle_;
+
+#if defined (ACE_HAS_BIG_FD_SET)
+ /// Current min handle.
+ ACE_HANDLE min_handle_;
+#endif /* ACE_HAS_BIG_FD_SET */
+
+ /// Bitmask.
+ fd_set mask_;
+
+ enum
+ {
+ WORDSIZE = NFDBITS,
+#if !defined (ACE_WIN32)
+ NUM_WORDS = howmany (MAXSIZE, NFDBITS),
+#endif /* ACE_WIN32 */
+ NBITS = 256
+ };
+
+ /// Counts the number of bits enabled in N. Uses a table lookup to
+ /// speed up the count.
+ static int count_bits (u_long n);
+
+#if defined (ACE_HAS_BIG_FD_SET)
+ /// Find the position of the bit counting from right to left.
+ static int bitpos (u_long bit);
+#endif /* ACE_HAS_BIG_FD_SET */
+
+ /// Resets the <max_handle_> after a clear of the original
+ /// <max_handle_>.
+ void set_max (ACE_HANDLE max);
+
+ /// Table that maps bytes to counts of the enabled bits in each value
+ /// from 0 to 255.
+ static const char nbits_[NBITS];
+};
+
+/**
+ * @class ACE_Handle_Set_Iterator
+ *
+ * @brief Iterator for the ACE_Handle_Set abstraction.
+ */
+class ACE_Export ACE_Handle_Set_Iterator
+{
+public:
+ /// Constructor.
+ ACE_Handle_Set_Iterator (const ACE_Handle_Set &hs);
+
+ /// Default dtor.
+ ~ACE_Handle_Set_Iterator (void);
+
+ /// Reset the state of the iterator by reinitializing the state
+ /// that we maintain.
+ void reset_state (void);
+
+ /**
+ * "Next" operator. Returns the next unseen ACE_HANDLE in the
+ * <Handle_Set> up to <handle_set_.max_handle_>). When all the
+ * handles have been seen returns <ACE_INVALID_HANDLE>. Advances
+ * the iterator automatically, so you need not call <operator++>
+ * (which is now obsolete).
+ */
+ ACE_HANDLE operator () (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// The <Handle_Set> we are iterating through.
+ const ACE_Handle_Set &handles_;
+
+ /// Index of the bit we're examining in the current <word_num_> word.
+#if defined (ACE_WIN32)
+ u_int handle_index_;
+#elif !defined (ACE_HAS_BIG_FD_SET)
+ int handle_index_;
+#elif defined (ACE_HAS_BIG_FD_SET)
+ int handle_index_;
+ u_long oldlsb_;
+#endif /* ACE_WIN32 */
+
+ /// Number of the word we're iterating over (typically between 0..7).
+ int word_num_;
+
+#if defined (ACE_HAS_BIG_FD_SET)
+ /// Number max of the words with a possible bit on.
+ int word_max_;
+#endif /* ACE_HAS_BIG_FD_SET */
+
+#if !defined (ACE_WIN32) && !defined (ACE_HAS_BIG_FD_SET)
+ /// Value of the bits in the word we're iterating on.
+ fd_mask word_val_;
+#elif !defined (ACE_WIN32) && defined (ACE_HAS_BIG_FD_SET)
+ /// Value of the bits in the word we're iterating on.
+ u_long word_val_;
+#endif /* !ACE_WIN32 && !ACE_HAS_BIG_FD_SET */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Handle_Set.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HANDLE_SET */
diff --git a/ACE/ace/Handle_Set.inl b/ACE/ace/Handle_Set.inl
new file mode 100644
index 00000000000..a4b1fccaebb
--- /dev/null
+++ b/ACE/ace/Handle_Set.inl
@@ -0,0 +1,193 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+// todo: This should be cleaned up a bit.
+// memset for FD_ZERO on OpenBSD and Solaris w/ gcc 2.95.3
+#include "ace/os_include/os_string.h"
+
+// FreeBSD 4.8-RC? for bzero() used by FD_ZERO
+#include "ace/os_include/os_strings.h"
+
+// IRIX5 defines bzero() in this odd file... used by FD_ZERO
+#if defined (ACE_HAS_BSTRING)
+# include /**/ <bstring.h>
+#endif /* ACE_HAS_BSTRING */
+
+// AIX defines bzero() in this odd file... used by FD_ZERO
+#if defined (ACE_HAS_STRINGS)
+# include "ace/os_include/os_strings.h"
+#endif /* ACE_HAS_STRINGS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Initialize the bitmask to all 0s and reset the associated fields.
+
+ACE_INLINE void
+ACE_Handle_Set::reset (void)
+{
+ ACE_TRACE ("ACE_Handle_Set::reset");
+ this->max_handle_ =
+ ACE_INVALID_HANDLE;
+#if defined (ACE_HAS_BIG_FD_SET)
+ this->min_handle_ =
+ NUM_WORDS * WORDSIZE;
+#endif /* ACE_HAS_BIG_FD_SET */
+ this->size_ = 0;
+ // #if !defined (ACE_HAS_BIG_FD_SET) Why is this here? -Steve Huston
+ FD_ZERO (&this->mask_);
+ // #endif /* ACE_HAS_BIG_FD_SET */
+}
+
+#if defined (ACE_HAS_BIG_FD_SET)
+ACE_INLINE ACE_Handle_Set &
+ACE_Handle_Set::operator = (const ACE_Handle_Set &rhs)
+{
+ ACE_TRACE ("ACE_Handle_Set::operator =");
+
+ if (rhs.size_ > 0)
+ {
+ this->size_ =
+ rhs.size_;
+ this->max_handle_ =
+ rhs.max_handle_;
+ this->min_handle_ =
+ rhs.min_handle_;
+ this->mask_ =
+ rhs.mask_;
+ }
+ else
+ this->reset ();
+
+ return *this;
+}
+#endif /* ACE_HAS_BIG_FD_SET */
+
+// Returns the number of the large bit.
+
+ACE_INLINE ACE_HANDLE
+ACE_Handle_Set::max_set (void) const
+{
+ ACE_TRACE ("ACE_Handle_Set::max_set");
+ return this->max_handle_;
+}
+
+// Checks whether handle is enabled.
+
+ACE_INLINE int
+ACE_Handle_Set::is_set (ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_Handle_Set::is_set");
+#if defined (ACE_HAS_BIG_FD_SET)
+ return FD_ISSET (handle,
+ &this->mask_)
+ && this->size_ > 0;
+#elif defined (ACE_HAS_NONCONST_FD_ISSET)
+ return FD_ISSET (handle,
+ const_cast<fd_set*> (&this->mask_));
+#else
+ return FD_ISSET (handle,
+ &this->mask_);
+#endif /* ACE_HAS_BIG_FD_SET */
+}
+
+// Enables the handle.
+
+ACE_INLINE void
+ACE_Handle_Set::set_bit (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Handle_Set::set_bit");
+ if ((handle != ACE_INVALID_HANDLE)
+ && (!this->is_set (handle)))
+ {
+#if defined (ACE_WIN32)
+ FD_SET ((SOCKET) handle,
+ &this->mask_);
+ ++this->size_;
+#else /* ACE_WIN32 */
+#if defined (ACE_HAS_BIG_FD_SET)
+ if (this->size_ == 0)
+ FD_ZERO (&this->mask_);
+
+ if (handle < this->min_handle_)
+ this->min_handle_ = handle;
+#endif /* ACE_HAS_BIG_FD_SET */
+
+ FD_SET (handle,
+ &this->mask_);
+ ++this->size_;
+
+ if (handle > this->max_handle_)
+ this->max_handle_ = handle;
+#endif /* ACE_WIN32 */
+ }
+}
+
+// Disables the handle.
+
+ACE_INLINE void
+ACE_Handle_Set::clr_bit (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Handle_Set::clr_bit");
+
+ if ((handle != ACE_INVALID_HANDLE) &&
+ (this->is_set (handle)))
+ {
+ FD_CLR ((ACE_SOCKET) handle,
+ &this->mask_);
+ --this->size_;
+
+#if !defined (ACE_WIN32)
+ if (handle == this->max_handle_)
+ this->set_max (this->max_handle_);
+#endif /* !ACE_WIN32 */
+ }
+}
+
+// Returns a count of the number of enabled bits.
+
+ACE_INLINE int
+ACE_Handle_Set::num_set (void) const
+{
+ ACE_TRACE ("ACE_Handle_Set::num_set");
+#if defined (ACE_WIN32)
+ return this->mask_.fd_count;
+#else /* !ACE_WIN32 */
+ return this->size_;
+#endif /* ACE_WIN32 */
+}
+
+// Returns a pointer to the underlying fd_set.
+
+ACE_INLINE
+ACE_Handle_Set::operator fd_set *()
+{
+ ACE_TRACE ("ACE_Handle_Set::operator fd_set *");
+
+ if (this->size_ > 0)
+ return (fd_set *) &this->mask_;
+ else
+ return (fd_set *) 0;
+}
+
+// Returns a pointer to the underlying fd_set.
+
+ACE_INLINE fd_set *
+ACE_Handle_Set::fdset (void)
+{
+ ACE_TRACE ("ACE_Handle_Set::fdset");
+
+ if (this->size_ > 0)
+ return (fd_set *) &this->mask_;
+ else
+ return (fd_set *) 0;
+}
+
+ACE_INLINE
+ACE_Handle_Set_Iterator::~ACE_Handle_Set_Iterator (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Hash_Cache_Map_Manager_T.cpp b/ACE/ace/Hash_Cache_Map_Manager_T.cpp
new file mode 100644
index 00000000000..86af4960a85
--- /dev/null
+++ b/ACE/ace/Hash_Cache_Map_Manager_T.cpp
@@ -0,0 +1,232 @@
+// $Id$
+
+#ifndef ACE_HASH_CACHE_MAP_MANAGER_T_CPP
+#define ACE_HASH_CACHE_MAP_MANAGER_T_CPP
+
+#include "ace/Hash_Cache_Map_Manager_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Hash_Cache_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Cache_Map_Manager)
+
+#define ACE_T1 class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class CACHING_STRATEGY, class ATTRIBUTES
+#define ACE_T2 KEY, VALUE, HASH_KEY, COMPARE_KEYS, CACHING_STRATEGY, ATTRIBUTES
+
+template <ACE_T1>
+ACE_Hash_Cache_Map_Manager<ACE_T2>::ACE_Hash_Cache_Map_Manager (CACHING_STRATEGY &caching_s,
+ size_t size,
+ ACE_Allocator *alloc)
+ : ACE_HCMM_BASE (caching_s,
+ size,
+ alloc)
+{
+}
+
+template <ACE_T1>
+ACE_Hash_Cache_Map_Manager<ACE_T2>::~ACE_Hash_Cache_Map_Manager (void)
+{
+}
+
+template <ACE_T1> int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::bind (const KEY &key,
+ const VALUE &value,
+ CACHE_ENTRY *&entry)
+{
+ // Insert a entry which has the <key> and the <cache_value> which is
+ // the combination of the <value> and the attributes of the caching
+ // strategy.
+ CACHE_VALUE cache_value (value,
+ this->caching_strategy_.attributes ());
+
+ int bind_result = this->map_.bind (key,
+ cache_value,
+ entry);
+
+ if (bind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_bind (bind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ {
+
+ this->map_.unbind (key);
+
+ // Unless the notification goes thru the bind operation is
+ // not complete.
+ bind_result = -1;
+
+ }
+ }
+
+ return bind_result;
+}
+
+template <ACE_T1> int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::rebind (const KEY &key,
+ const VALUE &value,
+ CACHE_ENTRY *&entry)
+{
+ CACHE_VALUE cache_value (value,
+ this->caching_strategy_.attributes ());
+
+ int rebind_result = this->map_.rebind (key,
+ cache_value,
+ entry);
+
+ if (rebind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_rebind (rebind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ {
+
+ // Make sure the unbind operation is done only when the
+ // notification fails after a bind which is denoted by
+ // rebind_result = 0
+ if (rebind_result == 0)
+ this->map_.unbind (key);
+
+ // Unless the notification goes thru the rebind operation is
+ // not complete.
+ rebind_result = -1;
+
+ }
+
+ }
+
+ return rebind_result;
+}
+
+template <ACE_T1> int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::trybind (const KEY &key,
+ VALUE &value,
+ CACHE_ENTRY *&entry)
+{
+ CACHE_VALUE cache_value (value,
+ this->caching_strategy_.attributes ());
+
+ int trybind_result = this->map_.trybind (key,
+ cache_value,
+ entry);
+
+ if (trybind_result != -1)
+ {
+ int result = this->caching_strategy_.notify_trybind (trybind_result,
+ cache_value.second ());
+
+ if (result == -1)
+ {
+
+ // If the entry has got inserted into the map, it is removed
+ // due to failure.
+ if (trybind_result == 0)
+ this->map_.unbind (key);
+
+ trybind_result = -1;
+
+ }
+ else
+ {
+
+ // If an attempt is made to bind an existing entry the value
+ // is overwritten with the value from the map.
+ if (trybind_result == 1)
+ value = cache_value.first ();
+
+ }
+
+ }
+
+ return trybind_result;
+}
+
+template <ACE_T1> int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::find (const KEY &key,
+ CACHE_ENTRY *&entry)
+{
+ // Lookup the key and populate the <value>.
+ int find_result = this->map_.find (key,
+ entry);
+
+ if (find_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_find (find_result,
+ entry->int_id_.second ());
+
+ // Unless the find and notification operations go thru, this
+ // method is not successful.
+ if (result == -1)
+ find_result = -1;
+ else
+ find_result = 0;
+
+ }
+
+ return find_result;
+}
+
+template <ACE_T1> int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::find (const KEY &key,
+ VALUE &value)
+{
+ CACHE_ENTRY *entry = 0;
+
+ int result = this->find (key,
+ entry);
+
+ if (result != -1)
+ {
+ value = entry->int_id_.first ();
+ }
+
+ return result;
+}
+
+template <ACE_T1> int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::find (const KEY &key)
+{
+ CACHE_ENTRY *entry = 0;
+
+ return this->find (key,
+ entry);
+}
+
+template <ACE_T1> int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::unbind (CACHE_ENTRY *entry)
+{
+ // Remove the entry from the cache.
+ int unbind_result = this->map_.unbind (entry);
+
+ if (unbind_result != -1)
+ {
+
+ int result = this->caching_strategy_.notify_unbind (unbind_result,
+ entry->int_id_.second ());
+
+ if (result == -1)
+ unbind_result = -1;
+
+ }
+
+ return unbind_result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#undef ACE_T1
+#undef ACE_T2
+
+#endif /* ACE_HASH_CACHE_MAP_MANAGER_T_CPP */
diff --git a/ACE/ace/Hash_Cache_Map_Manager_T.h b/ACE/ace/Hash_Cache_Map_Manager_T.h
new file mode 100644
index 00000000000..66cc3b83b53
--- /dev/null
+++ b/ACE/ace/Hash_Cache_Map_Manager_T.h
@@ -0,0 +1,214 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Hash_Cache_Map_Manager_T.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef HASH_CACHE_MAP_MANAGER_T_H
+#define HASH_CACHE_MAP_MANAGER_T_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Cache_Map_Manager_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Null_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration.
+class ACE_Allocator;
+
+#define ACE_CACHE_MAP_MANAGER \
+ ACE_Cache_Map_Manager<KEY, \
+ VALUE, \
+ ACE_Hash_Map_Manager_Ex<KEY, ACE_Pair<VALUE, ATTRIBUTES>, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex>, \
+ ACE_Hash_Map_Iterator_Ex<KEY, ACE_Pair<VALUE, ATTRIBUTES>, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex>, \
+ ACE_Hash_Map_Reverse_Iterator_Ex<KEY, ACE_Pair<VALUE, ATTRIBUTES>, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex>, \
+ CACHING_STRATEGY, \
+ ATTRIBUTES>
+
+// For linkers that cant grok long names.
+#define ACE_Hash_Cache_Map_Manager AHCMM
+
+ /**
+ * @class ACE_Hash_Cache_Map_Manager
+ *
+ * @brief Defines a abstraction which will purge entries from a map.
+ * The map considered is the ACE_Hash_Map_Manager_Ex.
+ *
+ * The Hash_Cache_Map_Manager will manage the map it contains
+ * and provide purging on demand from the map. The strategy for
+ * caching is decided by the user and provided to the Cache
+ * Manager. The Cache Manager acts as a agent and communicates
+ * between the Map and the Strategy for purging entries from the
+ * map. To tap the optimal methods like find(key,value,entry)
+ * present in the ACE_Hash_Map_Manager,
+ * Hash_Cache_Map_Manager provides extra functionality on top
+ * of the Cache_Map_Manager.
+ * No locking mechanism provided since locking at this level
+ * isnt efficient. Locking has to be provided by the
+ * application.
+ */
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class CACHING_STRATEGY, class ATTRIBUTES>
+class ACE_Hash_Cache_Map_Manager : public ACE_CACHE_MAP_MANAGER
+{
+ public:
+
+ /**
+ * The actual value mapped to the key in the map. The <attributes>
+ * are used by the strategy and is transparent to the user of this
+ * class.
+ */
+ typedef ACE_Pair<VALUE, ATTRIBUTES> CACHE_VALUE;
+ typedef ACE_Hash_Map_Manager_Ex<KEY, CACHE_VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> HASH_MAP;
+ typedef ACE_Hash_Map_Entry<KEY, CACHE_VALUE> CACHE_ENTRY;
+ typedef KEY key_type;
+ typedef VALUE mapped_type;
+
+ // = Initialization and termination methods.
+ /// Initialize a <Hash_Cache_Map_Manager> with @a size entries.
+ ACE_Hash_Cache_Map_Manager (CACHING_STRATEGY &caching_s,
+ size_t size = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a <Cache_Map_Manager> and release dynamically allocated
+ /// resources.
+ ~ACE_Hash_Cache_Map_Manager (void);
+
+ /**
+ * Associate @a key with @a value. If @a key is already in the
+ * MAP then the ENTRY is not changed. Returns 0 if a new entry is
+ * bound successfully, returns 1 if an attempt is made to bind an
+ * existing entry, and returns -1 if failures occur.
+ */
+ int bind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Same as a normal bind, except the cache entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int bind (const KEY &key,
+ const VALUE &value,
+ CACHE_ENTRY *&entry);
+
+ /// Loopkup entry<key,value> in the cache.
+ int find (const KEY &key,
+ VALUE &value);
+
+ /// Is @a key in the cache?
+ int find (const KEY &key);
+
+ /// Obtain the entry when the find succeeds.
+ int find (const KEY &key,
+ CACHE_ENTRY *&entry);
+
+ /**
+ * Reassociate the @a key with @a value. If the @a key already exists
+ * in the cache then returns 1, on a new bind returns 0 and returns
+ * -1 in case of any failures.
+ */
+ int rebind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old value into the
+ * "out" parameter @a old_value. The function fails if @a key is not
+ * in the cache for caches that do not allow user specified keys.
+ * However, for caches that allow user specified keys, if the key is
+ * not in the cache, a new @a key / @a value association is created.
+ */
+ int rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old key and value
+ * into the "out" parameters @a old_key and @a old_value. The
+ * function fails if @a key is not in the cache for caches that do not
+ * allow user specified keys. However, for caches that allow user
+ * specified keys, if the key is not in the cache, a new @a key / @a value
+ * association is created.
+ */
+ int rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value);
+
+ /**
+ * Same as a normal rebind, except the cache entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const KEY &key,
+ const VALUE &value,
+ CACHE_ENTRY *&entry);
+
+ /**
+ * Associate @a key with @a value if and only if @a key is not in the
+ * cache. If @a key is already in the cache, then the @a value parameter
+ * is overwritten with the existing value in the cache. Returns 0 if a
+ * new @a key / @a value association is created. Returns 1 if an
+ * attempt is made to bind an existing entry. This function fails
+ * for maps that do not allow user specified keys.
+ */
+ int trybind (const KEY &key,
+ VALUE &value);
+
+ /**
+ * Same as a normal trybind, except the cache entry is also passed
+ * back to the caller. The entry in this case will either be the
+ * newly created entry, or the existing one.
+ */
+ int trybind (const KEY &key,
+ VALUE &value,
+ CACHE_ENTRY *&entry);
+
+ /// Remove @a key from the cache.
+ int unbind (const KEY &key);
+
+ /// Remove @a key from the cache, and return the @a value associated with
+ /// @a key.
+ int unbind (const KEY &key,
+ VALUE &value);
+
+ /// Remove entry from map.
+ int unbind (CACHE_ENTRY *entry);
+
+protected:
+
+ /// Base class.
+ typedef ACE_CACHE_MAP_MANAGER ACE_HCMM_BASE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#if defined (__ACE_INLINE__)
+#include "ace/Hash_Cache_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Hash_Cache_Map_Manager_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Hash_Cache_Map_Manager_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* HASH_CACHE_MAP_MANAGER_T_H */
diff --git a/ACE/ace/Hash_Cache_Map_Manager_T.inl b/ACE/ace/Hash_Cache_Map_Manager_T.inl
new file mode 100644
index 00000000000..0388abd6c6e
--- /dev/null
+++ b/ACE/ace/Hash_Cache_Map_Manager_T.inl
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#define ACE_T1 class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class CACHING_STRATEGY, class ATTRIBUTES
+#define ACE_T2 KEY, VALUE, HASH_KEY, COMPARE_KEYS, CACHING_STRATEGY, ATTRIBUTES
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <ACE_T1> ACE_INLINE int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::bind (const KEY &key,
+ const VALUE &value)
+{
+ return ACE_HCMM_BASE::bind (key,
+ value);
+}
+
+template <ACE_T1> ACE_INLINE int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::rebind (const KEY &key,
+ const VALUE &value)
+{
+ return ACE_HCMM_BASE::rebind (key,
+ value);
+}
+
+template <ACE_T1> ACE_INLINE int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value)
+{
+ return ACE_HCMM_BASE::rebind (key,
+ value,
+ old_value);
+}
+
+template <ACE_T1> ACE_INLINE int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value)
+{
+ return ACE_HCMM_BASE::rebind (key,
+ value,
+ old_key,
+ old_value);
+}
+
+template <ACE_T1> ACE_INLINE int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::trybind (const KEY &key,
+ VALUE &value)
+{
+ return ACE_HCMM_BASE::trybind (key,
+ value);
+}
+
+template <ACE_T1> ACE_INLINE int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::unbind (const KEY &key)
+{
+ return ACE_HCMM_BASE::unbind (key);
+}
+
+template <ACE_T1> ACE_INLINE int
+ACE_Hash_Cache_Map_Manager<ACE_T2>::unbind (const KEY &key,
+ VALUE &value)
+{
+ return ACE_HCMM_BASE::unbind (key,
+ value);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#undef ACE_T1
+#undef ACE_T2
diff --git a/ACE/ace/Hash_Map_Manager.h b/ACE/ace/Hash_Map_Manager.h
new file mode 100644
index 00000000000..ed34b24f5b5
--- /dev/null
+++ b/ACE/ace/Hash_Map_Manager.h
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Hash_Map_Manager.h
+ *
+ * $Id$
+ *
+ * Backward compatibility header.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_HASH_MAP_MANAGER_H
+#define ACE_HASH_MAP_MANAGER_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Include the templates here.
+#include "ace/Hash_Map_Manager_T.h"
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_HASH_MAP_MANAGER_H */
diff --git a/ACE/ace/Hash_Map_Manager_T.cpp b/ACE/ace/Hash_Map_Manager_T.cpp
new file mode 100644
index 00000000000..3119c109cd2
--- /dev/null
+++ b/ACE/ace/Hash_Map_Manager_T.cpp
@@ -0,0 +1,530 @@
+
+//=============================================================================
+/**
+ * @file Hash_Map_Manager_T.cpp
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cse.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_HASH_MAP_MANAGER_T_CPP
+#define ACE_HASH_MAP_MANAGER_T_CPP
+
+#include "ace/Hash_Map_Manager_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Hash_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Malloc_Base.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class EXT_ID, class INT_ID>
+ACE_Hash_Map_Entry<EXT_ID, INT_ID>::ACE_Hash_Map_Entry (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *next,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *prev)
+ : next_ (next),
+ prev_ (prev)
+{
+}
+
+template <class EXT_ID, class INT_ID>
+ACE_Hash_Map_Entry<EXT_ID, INT_ID>::ACE_Hash_Map_Entry (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *next,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *prev)
+ : ext_id_ (ext_id),
+ int_id_ (int_id),
+ next_ (next),
+ prev_ (prev)
+{
+}
+
+template <class EXT_ID, class INT_ID>
+ACE_Hash_Map_Entry<EXT_ID, INT_ID>::~ACE_Hash_Map_Entry (void)
+{
+}
+
+template <class EXT_ID, class INT_ID> EXT_ID &
+ACE_Hash_Map_Entry<EXT_ID, INT_ID>::key ()
+{
+ return ext_id_;
+}
+
+template <class EXT_ID, class INT_ID> INT_ID &
+ACE_Hash_Map_Entry<EXT_ID, INT_ID>::item ()
+{
+ return int_id_;
+}
+
+template <class EXT_ID, class INT_ID> void
+ACE_Hash_Map_Entry<EXT_ID, INT_ID>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %d"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("prev_ = %d"), this->prev_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("total_size_ = %d"), this->total_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_));
+ this->table_allocator_->dump ();
+ this->entry_allocator_->dump ();
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::create_buckets (size_t size)
+{
+ size_t bytes = size * sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>);
+ void *ptr;
+
+ ACE_ALLOCATOR_RETURN (ptr,
+ this->table_allocator_->malloc (bytes),
+ -1);
+
+ this->table_ = (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *) ptr;
+
+ this->total_size_ = size;
+
+ // Initialize each entry in the hash table to be a circular linked
+ // list with the dummy node in the front serving as the anchor of
+ // the list.
+ for (size_t i = 0; i < size; i++)
+ new (&this->table_[i]) ACE_Hash_Map_Entry<EXT_ID, INT_ID> (&this->table_[i],
+ &this->table_[i]);
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::open (size_t size,
+ ACE_Allocator *table_alloc,
+ ACE_Allocator *entry_alloc)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ // Calling this->close_i () to ensure we release previous allocated
+ // memory before allocating new one.
+ this->close_i ();
+
+ if (table_alloc == 0)
+ table_alloc = ACE_Allocator::instance ();
+
+ this->table_allocator_ = table_alloc;
+
+ if (entry_alloc == 0)
+ entry_alloc = table_alloc;
+
+ this->entry_allocator_ = entry_alloc;
+
+ // This assertion is here to help track a situation that shouldn't
+ // happen, but did with Sun C++ 4.1 (before a change to this class
+ // was made: it used to have an enum that was supposed to be defined
+ // to be ACE_DEFAULT_MAP_SIZE, but instead was defined to be 0).
+ if (size == 0)
+ return -1;
+
+ return this->create_buckets (size);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::close_i (void)
+{
+ // Protect against "double-deletion" in case the destructor also
+ // gets called.
+ if (this->table_ != 0)
+ {
+ // Remove all the entries.
+ this->unbind_all_i ();
+
+ // Iterate through the buckets cleaning up the sentinels.
+ for (size_t i = 0; i < this->total_size_; i++)
+ {
+ // Destroy the dummy entry.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *entry = &this->table_[i];
+
+ // The second argument results in a no-op instead of
+ // deallocation.
+ ACE_DES_FREE_TEMPLATE2 (entry, ACE_NOOP,
+ ACE_Hash_Map_Entry, EXT_ID, INT_ID);
+ }
+
+ // Reset size.
+ this->total_size_ = 0;
+
+ // Free table memory.
+ this->table_allocator_->free (this->table_);
+
+ // Should be done last...
+ this->table_ = 0;
+ }
+
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_all_i (void)
+{
+ // Iterate through the entire map calling the destuctor of each
+ // <ACE_Hash_Map_Entry>.
+ for (size_t i = 0; i < this->total_size_; i++)
+ {
+ for (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *temp_ptr = this->table_[i].next_;
+ temp_ptr != &this->table_[i];
+ )
+ {
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *hold_ptr = temp_ptr;
+ temp_ptr = temp_ptr->next_;
+
+ // Explicitly call the destructor.
+ ACE_DES_FREE_TEMPLATE2 (hold_ptr, this->entry_allocator_->free,
+ ACE_Hash_Map_Entry, EXT_ID, INT_ID);
+ }
+
+ // Restore the sentinel.
+ this->table_[i].next_ = &this->table_[i];
+ this->table_[i].prev_ = &this->table_[i];
+ }
+
+ this->cur_size_ = 0;
+
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t loc;
+ int result = this->shared_find (ext_id, entry, loc);
+
+ if (result == -1)
+ {
+ void *ptr;
+ // Not found.
+ ACE_ALLOCATOR_RETURN (ptr,
+ this->entry_allocator_->malloc (sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>)),
+ -1);
+
+ entry = new (ptr) ACE_Hash_Map_Entry<EXT_ID, INT_ID> (ext_id,
+ int_id,
+ this->table_[loc].next_,
+ &this->table_[loc]);
+ this->table_[loc].next_ = entry;
+ entry->next_->prev_ = entry;
+ this->cur_size_++;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::trybind_i (const EXT_ID &ext_id,
+ INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t loc;
+ int result = this->shared_find (ext_id, entry, loc);
+
+ if (result == -1)
+ {
+ // Not found.
+ void *ptr;
+ ACE_ALLOCATOR_RETURN (ptr,
+ this->entry_allocator_->malloc (sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>)),
+ -1);
+
+ entry = new (ptr) ACE_Hash_Map_Entry<EXT_ID, INT_ID> (ext_id,
+ int_id,
+ this->table_[loc].next_,
+ &this->table_[loc]);
+ this->table_[loc].next_ = entry;
+ entry->next_->prev_ = entry;
+ this->cur_size_++;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_i (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *temp;
+
+ size_t loc;
+ int result = this->shared_find (ext_id, temp, loc);
+
+ if (result == -1)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ int_id = temp->int_id_;
+
+ return this->unbind_i (temp);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_i (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *entry)
+{
+ entry->next_->prev_ = entry->prev_;
+ entry->prev_->next_ = entry->next_;
+
+ // Explicitly call the destructor.
+ ACE_DES_FREE_TEMPLATE2 (entry, this->entry_allocator_->free,
+ ACE_Hash_Map_Entry, EXT_ID, INT_ID);
+
+ this->cur_size_--;
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::shared_find (const EXT_ID &ext_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry,
+ size_t &loc)
+{
+ loc = this->hash (ext_id) % this->total_size_;
+
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *temp = this->table_[loc].next_;
+
+ while (temp != &this->table_[loc] && this->equal (temp->ext_id_, ext_id) == 0)
+ temp = temp->next_;
+
+ if (temp == &this->table_[loc])
+ {
+ errno = ENOENT;
+ return -1;
+ }
+ else
+ {
+ entry = temp;
+ return 0;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return this->bind_i (ext_id, int_id);
+ else
+ {
+ entry->ext_id_ = ext_id;
+ entry->int_id_ = int_id;
+ return 1;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return this->bind_i (ext_id, int_id);
+ else
+ {
+ old_int_id = entry->int_id_;
+ entry->ext_id_ = ext_id;
+ entry->int_id_ = int_id;
+ return 1;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return this->bind_i (ext_id, int_id);
+ else
+ {
+ old_ext_id = entry->ext_id_;
+ old_int_id = entry->int_id_;
+ entry->ext_id_ = ext_id;
+ entry->int_id_ = int_id;
+ return 1;
+ }
+}
+
+// ------------------------------------------------------------
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Iterator_Base_Ex)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("index_ = %d "), this->index_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %x"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i");
+
+ if (this->map_man_->table_ == 0)
+ return -1;
+ // Handle initial case specially.
+ else if (this->index_ == -1)
+ {
+ this->index_++;
+ return this->forward_i ();
+ }
+ else if (this->index_ >= static_cast<ssize_t> (this->map_man_->total_size_))
+ return 0;
+
+ this->next_ = this->next_->next_;
+ if (this->next_ == &this->map_man_->table_[this->index_])
+ {
+ while (++this->index_ < static_cast<ssize_t> (this->map_man_->total_size_))
+ {
+ this->next_ = this->map_man_->table_[this->index_].next_;
+ if (this->next_ != &this->map_man_->table_[this->index_])
+ break;
+ }
+ }
+
+ return this->index_ < static_cast<ssize_t> (this->map_man_->total_size_);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i");
+
+ if (this->map_man_->table_ == 0)
+ return -1;
+ else if (this->index_ == static_cast<ssize_t> (this->map_man_->total_size_))
+ {
+ this->index_--;
+ return this->reverse_i ();
+ }
+ else if (this->index_ < 0)
+ return 0;
+
+ this->next_ = this->next_->prev_;
+ if (this->next_ == &this->map_man_->table_[this->index_])
+ {
+ while (--this->index_ >= 0)
+ {
+ this->next_ = this->map_man_->table_[this->index_].prev_;
+ if (this->next_ != &this->map_man_->table_[this->index_])
+ break;
+ }
+ }
+
+ return this->index_ >= 0;
+}
+
+// ------------------------------------------------------------
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Const_Iterator_Base_Ex)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("index_ = %d "), this->index_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %x"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i");
+
+ if (this->map_man_->table_ == 0)
+ return -1;
+ // Handle initial case specially.
+ else if (this->index_ == -1)
+ {
+ this->index_++;
+ return this->forward_i ();
+ }
+ else if (this->index_ >= (ssize_t) this->map_man_->total_size_)
+ return 0;
+
+ this->next_ = this->next_->next_;
+ if (this->next_ == &this->map_man_->table_[this->index_])
+ {
+ while (++this->index_ < (ssize_t) this->map_man_->total_size_)
+ {
+ this->next_ = this->map_man_->table_[this->index_].next_;
+ if (this->next_ != &this->map_man_->table_[this->index_])
+ break;
+ }
+ }
+
+ return this->index_ < (ssize_t) this->map_man_->total_size_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i");
+
+ if (this->map_man_->table_ == 0)
+ return -1;
+ else if (this->index_ == (ssize_t) this->map_man_->total_size_)
+ {
+ this->index_--;
+ return this->reverse_i ();
+ }
+ else if (this->index_ < 0)
+ return 0;
+
+ this->next_ = this->next_->prev_;
+ if (this->next_ == &this->map_man_->table_[this->index_])
+ {
+ while (--this->index_ >= 0)
+ {
+ this->next_ = this->map_man_->table_[this->index_].prev_;
+ if (this->next_ != &this->map_man_->table_[this->index_])
+ break;
+ }
+ }
+
+ return this->index_ >= 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HASH_MAP_MANAGER_T_CPP */
diff --git a/ACE/ace/Hash_Map_Manager_T.h b/ACE/ace/Hash_Map_Manager_T.h
new file mode 100644
index 00000000000..7d4f270584f
--- /dev/null
+++ b/ACE/ace/Hash_Map_Manager_T.h
@@ -0,0 +1,1274 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Hash_Map_Manager_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_HASH_MAP_MANAGER_T_H
+#define ACE_HASH_MAP_MANAGER_T_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/Default_Constants.h"
+#include "ace/Functor_T.h"
+#include "ace/Log_Msg.h"
+#include <iterator>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Hash_Map_Entry
+ *
+ * @brief Define an entry in the hash table.
+ */
+template <class EXT_ID, class INT_ID>
+class ACE_Hash_Map_Entry
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Hash_Map_Entry (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *next = 0,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *prev = 0);
+
+ /// Constructor.
+ ACE_Hash_Map_Entry (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *next,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *prev);
+
+ /// Destructor.
+ ~ACE_Hash_Map_Entry (void);
+
+ /// Key accessor.
+ EXT_ID& key (void);
+
+ /// Item accessor.
+ INT_ID& item (void);
+
+ /// Key used to look up an entry.
+ /// @deprecated Use key()
+ EXT_ID ext_id_;
+
+ /// The contents of the entry itself.
+ /// @deprecated Use item()
+ INT_ID int_id_;
+
+ /// Pointer to the next item in the bucket of overflow nodes.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *next_;
+
+ /// Pointer to the prev item in the bucket of overflow nodes.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *prev_;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+};
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Iterator_Base_Ex;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Const_Iterator_Base_Ex;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Iterator_Ex;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Const_Iterator_Ex;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Reverse_Iterator_Ex;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Const_Reverse_Iterator_Ex;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Bucket_Iterator;
+
+// Forward decl.
+class ACE_Allocator;
+
+/**
+ * @class ACE_Hash_Map_Manager_Ex
+ *
+ * @brief Define a map abstraction that efficiently associates
+ * @c EXT_ID type objects with @c INT_ID type objects.
+ *
+ * This implementation of a map uses a hash table. Key hashing
+ * is achieved through the @c HASH_KEY object and key comparison is
+ * achieved through the @c COMPARE_KEYS object.
+ * This class uses an ACE_Allocator to allocate memory. The
+ * user can make this a persistent class by providing an
+ * ACE_Allocator with a persistable memory pool.
+ */
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Manager_Ex
+{
+public:
+ friend class ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+
+ typedef EXT_ID
+ KEY;
+ typedef INT_ID
+ VALUE;
+ typedef ACE_LOCK lock_type;
+ typedef ACE_Hash_Map_Entry<EXT_ID, INT_ID>
+ ENTRY;
+
+ // = ACE-style iterator typedefs.
+ typedef ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ ITERATOR;
+ typedef ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ CONST_ITERATOR;
+ typedef ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ REVERSE_ITERATOR;
+ typedef ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ CONST_REVERSE_ITERATOR;
+
+ // = STL-style iterator typedefs.
+ typedef ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ iterator;
+ typedef ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ const_iterator;
+ typedef ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ reverse_iterator;
+ typedef ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ const_reverse_iterator;
+
+ // = STL-style typedefs/traits.
+ typedef EXT_ID key_type;
+ typedef INT_ID data_type;
+ typedef ACE_Hash_Map_Entry<EXT_ID, INT_ID> value_type;
+ typedef value_type & reference;
+ typedef value_type const & const_reference;
+ typedef value_type * pointer;
+ typedef value_type const * const_pointer;
+ typedef ptrdiff_t difference_type;
+ typedef size_t size_type;
+
+ // = Initialization and termination methods.
+
+ /**
+ * Initialize an ACE_Hash_Map_Manager_Ex with a default number of elements.
+ *
+ * @param table_alloc is a pointer to a memory allocator used for
+ * table_, so it should supply size*sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>).
+ * If @a table_alloc is 0 it defaults to ACE_Allocator::instance().
+ * @param entry_alloc is a pointer to an additional allocator for
+ * entries, so it should be able to allocate 'size' / chunks
+ * of sizeof(ACE_Hash_Map_Entry<EXT_ID, INT_ID>) bytes each.
+ * If @a entry_alloc is 0 it defaults to the same allocator as
+ * @a table_alloc.
+ */
+ ACE_Hash_Map_Manager_Ex (ACE_Allocator *table_alloc = 0,
+ ACE_Allocator *entry_alloc = 0);
+
+ /**
+ * Initialize an ACE_Hash_Map_Manager_Ex with @a size elements.
+ *
+ * @param table_alloc is a pointer to a memory allocator used for
+ * table_, so it should supply size*sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>).
+ * If @a table_alloc is 0 it defaults to ACE_Allocator::instance().
+ * @param entry_alloc is a pointer to an additional allocator for
+ * entries, so it should be able to allocate 'size' / chunks
+ * of sizeof(ACE_Hash_Map_Entry<EXT_ID, INT_ID>) bytes each.
+ * If @a entry_alloc is 0 it defaults to the same allocator as
+ * @a table_alloc.
+ */
+ ACE_Hash_Map_Manager_Ex (size_t size,
+ ACE_Allocator *table_alloc = 0,
+ ACE_Allocator *entry_alloc = 0);
+
+ /**
+ * Initialize an ACE_Hash_Map_Manager_Ex with @a size elements.
+ * @param table_alloc is a pointer to a memory allocator used for
+ * table_, so it should supply size*sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>).
+ * If @a table_alloc is 0 it defaults to ACE_Allocator::instance().
+ * @param entry_alloc is a pointer to an additional allocator for
+ * entries, so it should be able to allocate 'size' / chunks
+ * of sizeof(ACE_Hash_Map_Entry<EXT_ID, INT_ID>) bytes each.
+ * If @a entry_alloc is 0 then it defaults to the same allocator as
+ * @a table_alloc.
+ * @return -1 on failure, 0 on success
+ */
+
+ int open (size_t size = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *table_alloc = 0,
+ ACE_Allocator *entry_alloc = 0);
+
+ /// Close down the ACE_Hash_Map_Manager_Ex and release dynamically allocated
+ /// resources.
+ int close (void);
+
+ /// Removes all the entries in the ACE_Hash_Map_Manager_Ex.
+ int unbind_all (void);
+
+ /// Cleanup the ACE_Hash_Map_Manager_Ex.
+ ~ACE_Hash_Map_Manager_Ex (void);
+
+ /**
+ * Associate @a item with @a int_id. If @a item is already in the
+ * map then the map is not changed.
+ *
+ * @retval 0 if a new entry is bound successfully.
+ * @retval 1 if an attempt is made to bind an existing entry.
+ * @retval -1 if a failure occurs; check @c errno for more information.
+ */
+ int bind (const EXT_ID &item,
+ const INT_ID &int_id);
+
+ /**
+ * Same as a normal bind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int bind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id if and only if @a ext_id is not
+ * in the map. If @a ext_id is already in the map then the @a int_id
+ * parameter is assigned the existing value in the map. Returns 0
+ * if a new entry is bound successfully, returns 1 if an attempt is
+ * made to bind an existing entry, and returns -1 if failures occur.
+ */
+ int trybind (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /**
+ * Same as a normal trybind, except the map entry is also passed
+ * back to the caller. The entry in this case will either be the
+ * newly created entry, or the existing one.
+ */
+ int trybind (const EXT_ID &ext_id,
+ INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Reassociate @a ext_id with @a int_id. If @a ext_id is not in the
+ * map then behaves just like <bind>. Returns 0 if a new entry is
+ * bound successfully, returns 1 if an existing entry was rebound,
+ * and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /**
+ * Same as a normal rebind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id. If @a ext_id is not in the map
+ * then behaves just like <bind>. Otherwise, store the old value of
+ * @a int_id into the "out" parameter and rebind the new parameters.
+ * Returns 0 if a new entry is bound successfully, returns 1 if an
+ * existing entry was rebound, and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id);
+
+ /**
+ * Same as a normal rebind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id. If @a ext_id is not in the map
+ * then behaves just like <bind>. Otherwise, store the old values
+ * of @a ext_id and @a int_id into the "out" parameters and rebind the
+ * new parameters. This is very useful if you need to have an
+ * atomic way of updating ACE_Hash_Map_Entrys and you also need
+ * full control over memory allocation. Returns 0 if a new entry is
+ * bound successfully, returns 1 if an existing entry was rebound,
+ * and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id);
+
+ /**
+ * Same as a normal rebind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Locate @a ext_id and pass out parameter via @a int_id.
+ /// Return 0 if found, returns -1 if not found.
+ int find (const EXT_ID &ext_id,
+ INT_ID &int_id) const;
+
+ /// Returns 0 if the @a ext_id is in the mapping, otherwise -1.
+ int find (const EXT_ID &ext_id) const;
+
+ /// Locate @a ext_id and pass out parameter via @a entry. If found,
+ /// return 0, returns -1 if not found.
+ int find (const EXT_ID &ext_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry) const;
+
+ /// Locate @a ext_id and pass out an iterator that points to its
+ /// corresponding value.
+ /**
+ * @param pos @a pos will be set to @c end() if not found.
+ */
+ void find (EXT_ID const & ext_id, iterator & pos) const;
+
+ /**
+ * Unbind (remove) the @a ext_id from the map. Don't return the
+ * @a int_id to the caller (this is useful for collections where the
+ * @a int_ids are *not* dynamically allocated...)
+ */
+ int unbind (const EXT_ID &ext_id);
+
+ /// Break any association of @a ext_id. Returns the value of @a int_id
+ /// in case the caller needs to deallocate memory. Return 0 if the
+ /// unbind was successful, and returns -1 if failures occur.
+ int unbind (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /// Remove entry from map.
+ /**
+ * This unbind operation is fast relative to those that accept an
+ * external ID parameter since no map lookup is performed.
+ *
+ * @return 0 if the unbind was successful, and -1 if failures
+ * occur.
+ */
+ int unbind (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *entry);
+
+ /// Remove entry from map pointed to by @c iterator @a pos.
+ /**
+ * This unbind operation is fast relative to those that accept an
+ * external ID parameter since no map lookup is performed.
+ *
+ * @return 0 if the unbind was successful, and -1 if failures
+ * occur.
+ */
+ int unbind (iterator pos);
+
+ /// Returns the current number of ACE_Hash_Map_Entry objects in the
+ /// hash table.
+ size_t current_size (void) const;
+
+ /// Return the size of the array that's used to point to the
+ /// linked lists of ACE_Hash_Map_Entry objects in the hash table.
+ size_t total_size (void) const;
+
+ /**
+ * Returns a reference to the underlying <ACE_LOCK>. This makes it
+ * possible to acquire the lock explicitly, which can be useful in
+ * some cases if you instantiate the ACE_Atomic_Op with an
+ * ACE_Recursive_Mutex or ACE_Process_Mutex, or if you need to
+ * guard the state of an iterator.
+ * @note The right name would be <lock>, but HP/C++ will choke on that!
+ */
+ ACE_LOCK &mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ iterator begin (void);
+ iterator end (void);
+ const_iterator begin (void) const;
+ const_iterator end (void) const;
+
+ /// Return reverse iterator.
+ reverse_iterator rbegin (void);
+ reverse_iterator rend (void);
+ const_reverse_iterator rbegin (void) const;
+ const_reverse_iterator rend (void) const;
+
+protected:
+ // = The following methods do the actual work.
+
+ /// Returns 1 if <id1> == <id2>, else 0. This is defined as a
+ /// separate method to facilitate template specialization.
+ int equal (const EXT_ID &id1, const EXT_ID &id2);
+
+ /// Compute the hash value of the @a ext_id. This is defined as a
+ /// separate method to facilitate template specialization.
+ u_long hash (const EXT_ID &ext_id);
+
+ // = These methods assume locks are held by private methods.
+
+ /// Performs bind. Must be called with locks held.
+ int bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Performs bind. Must be called with locks held.
+ int bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs trybind. Must be called with locks held.
+ int trybind_i (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /// Performs trybind. Must be called with locks held.
+ int trybind_i (const EXT_ID &ext_id,
+ INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs a find of @a int_id using @a ext_id as the key. Must be
+ /// called with locks held.
+ int find_i (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /// Performs a find using @a ext_id as the key. Must be called with
+ /// locks held.
+ int find_i (const EXT_ID &ext_id);
+
+ /// Performs a find using @a ext_id as the key. Must be called with
+ /// locks held.
+ int find_i (const EXT_ID &ext_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs unbind. Must be called with locks held.
+ int unbind_i (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /// Performs unbind. Must be called with locks held.
+ int unbind_i (const EXT_ID &ext_id);
+
+ /// Performs unbind. Must be called with locks held.
+ int unbind_i (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *entry);
+
+ /**
+ * Resize the map. Must be called with locks held.
+ * @note This method should never be called more than once or else all the
+ * hashing will get screwed up as the size will change.
+ */
+ int create_buckets (size_t size);
+
+ /// Close down a <Map_Manager_Ex>. Must be called with
+ /// locks held.
+ int close_i (void);
+
+ /// Removes all the entries in <Map_Manager_Ex>. Must be called with
+ /// locks held.
+ int unbind_all_i (void);
+
+ /// Pointer to a memory allocator used for table_, so it should
+ /// supply size*sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>),
+ ACE_Allocator *table_allocator_;
+
+ /// Addidtional allocator for entries, so it should be able to
+ /// allocate 'size' / chunks of sizeof(ACE_Hash_Map_Entry<EXT_ID,
+ /// INT_ID>) bytes each.
+ ACE_Allocator *entry_allocator_;
+
+ /// Synchronization variable for the MT_SAFE
+ /// @c ACE_Hash_Map_Manager_Ex.
+ mutable ACE_LOCK lock_;
+
+ /// Function object used for hashing keys.
+ HASH_KEY hash_key_;
+
+ /// Function object used for comparing keys.
+ COMPARE_KEYS compare_keys_;
+
+protected:
+ /// Returns the <ACE_Hash_Map_Entry> that corresponds to @a ext_id.
+ int shared_find (const EXT_ID &ext_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry,
+ size_t &loc);
+
+ /// Accessor of the underlying table
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *table (void);
+
+ /// Accessor of the current size attribute
+ size_t cur_size (void) const;
+
+private:
+ /**
+ * Array of <ACE_Hash_Map_Entry> *s, each of which points to an
+ * <ACE_Hash_Map_Entry> that serves as the beginning of a linked
+ * list of <EXT_ID>s that hash to that bucket.
+ */
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *table_;
+
+ /// Total size of the hash table.
+ size_t total_size_;
+
+ /// Current number of entries in the table
+ /// @note That this can be larger than <total_size_> due to the
+ /// bucket chaining).
+ size_t cur_size_;
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Hash_Map_Manager_Ex (const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &))
+};
+
+/**
+ * @class ACE_Hash_Map_Iterator_Base_Ex
+ *
+ * @brief Base iterator for the ACE_Hash_Map_Manager_Ex
+ *
+ * This class factors out common code from its templatized
+ * subclasses.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Iterator_Base_Ex
+{
+public:
+ // = STL-style typedefs/traits.
+ typedef ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ container_type;
+
+ // = std::iterator_traits typedefs/traits.
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ /// Contructor.
+ /**
+ * If @a head != @c false, the iterator constructed is positioned
+ * at the head of the map. It is positioned at the end otherwise.
+ * @par
+ */
+ ACE_Hash_Map_Iterator_Base_Ex (
+ ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK> &mm,
+ bool head);
+
+ /// Contructor.
+ /**
+ * This constructor positions the iterator to the given @a entry.
+ */
+ ACE_Hash_Map_Iterator_Base_Ex (
+ ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK> & mm,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> * entry,
+ size_t index);
+
+ // = ITERATION methods.
+
+ /// Pass back the next <entry> that hasn't been seen in the Set.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&next_entry) const;
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Returns a reference to the interal element @c this is pointing to.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID>& operator* (void) const;
+
+ /// Returns a pointer to the interal element @c this is pointing to.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID>* operator-> (void) const;
+
+ /// Returns reference the Hash_Map_Manager_Ex that is being iterated
+ /// over.
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>& map (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+ bool operator!= (const ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Move forward by one element in the set. Returns 0 when there's
+ /// no more item in the set after the current items, else 1.
+ int forward_i (void);
+
+ /// Move backward by one element in the set. Returns 0 when there's
+ /// no more item in the set before the current item, else 1.
+ int reverse_i (void);
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ /// Map we are iterating over.
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *map_man_;
+
+ /// Keeps track of how far we've advanced in the table.
+ ssize_t index_;
+
+ /// Keeps track of how far we've advanced in a linked list in each
+ /// table slot.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *next_;
+};
+
+/**
+ * @class ACE_Hash_Map_Const_Iterator_Base_Ex
+ *
+ * @brief Base const iterator for the ACE_Hash_Map_Manager_Ex
+ *
+ * This class factors out common code from its templatized
+ * subclasses.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Const_Iterator_Base_Ex
+{
+public:
+ // = STL-style typedefs/traits.
+ typedef ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ container_type;
+
+ // = std::iterator_traits typedefs/traits.
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::const_reference reference;
+ typedef typename container_type::const_pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ /// Contructor. If head != 0, the iterator constructed is positioned
+ /// at the head of the map, it is positioned at the end otherwise.
+ ACE_Hash_Map_Const_Iterator_Base_Ex (const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head);
+
+ // = ITERATION methods.
+
+ /// Pass back the next <entry> that hasn't been seen in the Set.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&next_entry) const;
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Returns a reference to the interal element @c this is pointing to.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID>& operator* (void) const;
+
+ /// Returns a pointer to the interal element @c this is pointing to.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID>* operator-> (void) const;
+
+ /// Returns reference the Hash_Map_Manager_Ex that is being iterated
+ /// over.
+ const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>& map (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+ bool operator!= (const ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Move forward by one element in the set. Returns 0 when there's
+ /// no more item in the set after the current items, else 1.
+ int forward_i (void);
+
+ /// Move backward by one element in the set. Returns 0 when there's
+ /// no more item in the set before the current item, else 1.
+ int reverse_i (void);
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ /// Map we are iterating over.
+ const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *map_man_;
+
+ /// Keeps track of how far we've advanced in the table.
+ ssize_t index_;
+
+ /// Keeps track of how far we've advanced in a linked list in each
+ /// table slot.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *next_;
+};
+
+/**
+ * @class ACE_Hash_Map_Iterator_Ex
+ *
+ * @brief Forward iterator for the ACE_Hash_Map_Manager_Ex.
+ *
+ * This class does not perform any internal locking of the
+ * ACE_Hash_Map_Manager_Ex it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * ACE_Guard or ACE_Read_Guard on the ACE_Hash_Map_Manager_Ex's
+ * internal lock, which is accessible via its <mutex> method.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Iterator_Ex : public ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+{
+public:
+ // = STL-style traits/typedefs
+ typedef typename ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::container_type
+ container_type;
+
+ // = STL-style traits/typedefs
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ ACE_Hash_Map_Iterator_Ex (ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int tail = 0);
+
+ /// Contructor.
+ /**
+ * This constructor positions the iterator to the given @a entry.
+ */
+ ACE_Hash_Map_Iterator_Ex (
+ ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK> & mm,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> * entry,
+ size_t index);
+
+ // = Iteration methods.
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance.
+ ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Hash_Map_Const_Iterator_Ex
+ *
+ * @brief Const forward iterator for the ACE_Hash_Map_Manager_Ex.
+ *
+ * This class does not perform any internal locking of the
+ * ACE_Hash_Map_Manager_Ex it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * ACE_Guard or ACE_Read_Guard on the ACE_Hash_Map_Manager_Ex's
+ * internal lock, which is accessible via its <mutex> method.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Const_Iterator_Ex : public ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+{
+public:
+ // = STL-style traits/typedefs
+ typedef typename ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::container_type
+ container_type;
+
+ // = std::iterator_trait traits/typedefs
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ ACE_Hash_Map_Const_Iterator_Ex (const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int tail = 0);
+
+ // = Iteration methods.
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance.
+ ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Hash_Map_Bucket_Iterator
+ *
+ * @brief Forward iterator for the ACE_Hash_Map_Manager_Ex which
+ * only traverses a particular bucket. The particular bucket is
+ * specified by the <EXT_ID> parameter specified in the constructor.
+ *
+ * This class does not perform any internal locking of the
+ * ACE_Hash_Map_Manager_Ex it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * ACE_Guard or ACE_Read_Guard on the ACE_Hash_Map_Manager_Ex's
+ * internal lock, which is accessible via its <mutex> method.
+ *
+ * Note that a creation method for this new iterator cannot be added
+ * to the hash map, since this would require adding explicit template
+ * instantiations for bucket iterators on platforms with broken
+ * templates.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Bucket_Iterator
+{
+public:
+ // = STL-style traits/typedefs
+ typedef ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ container_type;
+
+ // = std::iterator traits/typedefs
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ ACE_Hash_Map_Bucket_Iterator (ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ const EXT_ID &ext_id,
+ int tail = 0);
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance.
+ ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Returns a reference to the interal element @c this is pointing to.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID>& operator* (void) const;
+
+ /// Returns a pointer to the interal element @c this is pointing to.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID>* operator-> (void) const;
+
+ /// Returns reference the Hash_Map_Manager_Ex that is being iterated
+ /// over.
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>& map (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+ bool operator!= (const ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+
+protected:
+ /// Move forward by one element in the set. Returns 0 when there's
+ /// no more item in the set after the current items, else 1.
+ int forward_i (void);
+
+ /// Move backward by one element in the set. Returns 0 when there's
+ /// no more item in the set before the current item, else 1.
+ int reverse_i (void);
+
+ /// Map we are iterating over.
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *map_man_;
+
+ /// Keeps track of how far we've advanced in the table.
+ ssize_t index_;
+
+ /// Keeps track of how far we've advanced in a linked list in each
+ /// table slot.
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *next_;
+};
+
+/**
+ * @class ACE_Hash_Map_Reverse_Iterator_Ex
+ *
+ * @brief Reverse iterator for the ACE_Hash_Map_Manager_Ex.
+ *
+ * This class does not perform any internal locking of the
+ * ACE_Hash_Map_Manager_Ex it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * ACE_Guard or ACE_Read_Guard on the ACE_Hash_Map_Manager_Ex's
+ * internal lock, which is accessible via its <mutex> method.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Reverse_Iterator_Ex : public ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+{
+public:
+ // = STL-style traits/typedefs
+ typedef typename ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::container_type
+ container_type;
+
+ // = std::iterator_traits typedefs
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ ACE_Hash_Map_Reverse_Iterator_Ex (ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head = 0);
+
+ // = Iteration methods.
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix reverse.
+ ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix advance.
+ ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix advance.
+ ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Hash_Map_Const_Reverse_Iterator_Ex
+ *
+ * @brief Const reverse iterator for the ACE_Hash_Map_Manager_Ex.
+ *
+ * This class does not perform any internal locking of the
+ * ACE_Hash_Map_Manager_Ex it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * ACE_Guard or ACE_Read_Guard on the ACE_Hash_Map_Manager_Ex's
+ * internal lock, which is accessible via its <mutex> method.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Map_Const_Reverse_Iterator_Ex : public ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+{
+public:
+ // = STL-style traits/typedefs
+ typedef typename ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::container_type
+ container_type;
+
+ // = std::iterator_traits typedefs
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ ACE_Hash_Map_Const_Reverse_Iterator_Ex (const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head = 0);
+
+ // = Iteration methods.
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix reverse.
+ ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix advance.
+ ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix advance.
+ ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Hash_Map_Manager
+ *
+ * @brief Wrapper for backward compatibility.
+ *
+ * This implementation of a map uses a hash table. This class
+ * expects that the <EXT_ID> contains a method called <hash>.
+ * In addition, the <EXT_ID> must support <operator==>. Both of
+ * these constraints can be alleviated via template
+ * specialization, as shown in the $ACE_ROOT/tests/Conn_Test.cpp
+ * test.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Hash Table
+ * - Duplicates allowed?
+ * No
+ * - Random access allowed?
+ * Yes
+ * - Search speed
+ * O(1)
+ * - Insert/replace speed
+ * O(1), can be longer if the hash map has to resize
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * Yes
+ * - Items inserted by
+ * Value
+ * - Requirements for key type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator==
+ * - Requirements for object type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator<
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Hash_Map_Manager : public ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>
+{
+public:
+
+ /**
+ * Initialize a @c Hash_Map_Manager with default size elements.
+ * @param table_alloc is a pointer to a memory allocator used for
+ * table_, so it should supply size*sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>).
+ * @param entry_alloc is a pointer to an additional allocator for
+ * entries, so it should be able to allocate 'size' / chunks
+ * of sizeof(ACE_Hash_Map_Entry<EXT_ID, INT_ID>) bytes each.
+ * If @c table_alloc is 0 it defaults to @c ACE_Allocator::instance().
+ * If @c entry_alloc is 0 then it defaults to the same allocator as
+ * @c table_alloc.
+ */
+ ACE_Hash_Map_Manager (ACE_Allocator *table_alloc = 0,
+ ACE_Allocator *entry_alloc = 0);
+
+ /**
+ * Initialize a @c Hash_Map_Manager with @c size elements.
+ * @param table_alloc is a pointer to a memory allocator used for
+ * table_, so it should supply size*sizeof (ACE_Hash_Map_Entry<EXT_ID, INT_ID>).
+ * @param entry_alloc is a pointer to an additional allocator for
+ * entries, so it should be able to allocate 'size' / chunks
+ * of sizeof(ACE_Hash_Map_Entry<EXT_ID, INT_ID>) bytes each.
+ * If @c table_alloc is 0 it defaults to @c ACE_Allocator::instance().
+ * If @c entry_alloc is 0 then it defaults to the same allocator as
+ * @c table_alloc.
+ */
+ ACE_Hash_Map_Manager (size_t size,
+ ACE_Allocator *table_alloc = 0,
+ ACE_Allocator *entry_alloc = 0);
+
+ // = The following two are necessary for template specialization of
+ // ACE_Hash_Map_Manager to work.
+ int equal (const EXT_ID &id1, const EXT_ID &id2);
+ u_long hash (const EXT_ID &ext_id);
+};
+
+/**
+ * @class ACE_Hash_Map_Iterator
+ *
+ * @brief Wrapper for backward compatibility.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Hash_Map_Iterator : public ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>
+{
+public:
+#if defined (ACE_HAS_STL_ITERATOR_TRAITS)
+ typedef typename ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::iterator_category iterator_category;
+ typedef typename ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::value_type value_type;
+ typedef typename ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::reference reference;
+ typedef typename ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::pointer pointer;
+ typedef typename ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::difference_type difference_type;
+#endif
+
+ // = Initialization method.
+ /// Construct from map
+ ACE_Hash_Map_Iterator (ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int tail = 0);
+
+ /// Construct from base
+ ACE_Hash_Map_Iterator (const ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base);
+
+ /// Assignment from base
+ ACE_Hash_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ operator= (const ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base);
+};
+
+/**
+ * @class ACE_Hash_Map_Const_Iterator
+ *
+ * @brief Wrapper for backward compatibility.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Hash_Map_Const_Iterator : public ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>
+{
+public:
+ // = STL-style traits/typedefs
+ typedef typename ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::container_type
+ container_type;
+
+ // = std::iterator_traits typedefs
+ typedef typename container_type::iterator_category iterator_category;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ /// Construct from map
+ ACE_Hash_Map_Const_Iterator (const ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int tail = 0);
+
+ /// Construct from base
+ ACE_Hash_Map_Const_Iterator (const ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base);
+
+ /// Assignment from base
+ ACE_Hash_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ operator= (const ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base);
+};
+
+/**
+ * @class ACE_Hash_Map_Reverse_Iterator
+ *
+ * @brief Wrapper for backward compatibility.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Hash_Map_Reverse_Iterator : public ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>
+{
+public:
+ // = STL-style traits/typedefs
+ typedef typename ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::container_type
+ container_type;
+
+ // = std::iterator_traits typedefs
+ typedef typename container_type::iterator_category iterator_category;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::difference_type difference_type;
+
+ // = Initialization method.
+ ACE_Hash_Map_Reverse_Iterator (ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int head = 0);
+
+ /// Construct from base
+ ACE_Hash_Map_Reverse_Iterator (const ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base);
+
+ /// Assignment from base
+ ACE_Hash_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ operator= (const ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Hash_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Hash_Map_Manager_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Hash_Map_Manager_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HASH_MAP_MANAGER_T_H */
diff --git a/ACE/ace/Hash_Map_Manager_T.inl b/ACE/ace/Hash_Map_Manager_T.inl
new file mode 100644
index 00000000000..1385ea3e5b2
--- /dev/null
+++ b/ACE/ace/Hash_Map_Manager_T.inl
@@ -0,0 +1,1253 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Guard_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Manager_Ex (size_t size,
+ ACE_Allocator *table_alloc,
+ ACE_Allocator *entry_alloc)
+ : table_allocator_ (table_alloc),
+ entry_allocator_ (entry_alloc),
+ table_ (0),
+ total_size_ (0),
+ cur_size_ (0)
+{
+ if (this->open (size, table_alloc, entry_alloc) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("ACE_Hash_Map_Manager_Ex\n")));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Manager_Ex (ACE_Allocator *table_alloc,
+ ACE_Allocator *entry_alloc)
+ : table_allocator_ (table_alloc),
+ entry_allocator_ (entry_alloc),
+ table_ (0),
+ total_size_ (0),
+ cur_size_ (0)
+{
+ if (this->open (ACE_DEFAULT_MAP_SIZE, table_alloc, entry_alloc) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Hash_Map_Manager_Ex open")));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::close (void)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->close_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_all (void)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_all_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::~ACE_Hash_Map_Manager_Ex (void)
+{
+ this->close ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE size_t
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::current_size (void) const
+{
+ return this->cur_size_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE size_t
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::total_size (void) const
+{
+ return this->total_size_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE ACE_LOCK &
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::mutex (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Manager_Ex::mutex");
+ return this->lock_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE u_long
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::hash (const EXT_ID &ext_id)
+{
+ return this->hash_key_ (ext_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::equal (const EXT_ID &id1,
+ const EXT_ID &id2)
+{
+ return this->compare_keys_ (id1, id2);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *temp;
+
+ return this->bind_i (ext_id, int_id, temp);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->bind_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->bind_i (ext_id, int_id, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::trybind_i (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *temp;
+
+ int result = this->trybind_i (ext_id, int_id, temp);
+ if (result == 1)
+ int_id = temp->int_id_;
+ return result;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::trybind (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->trybind_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::trybind (const EXT_ID &ext_id,
+ INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->trybind_i (ext_id, int_id, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_i (const EXT_ID &ext_id)
+{
+ INT_ID int_id;
+
+ return this->unbind_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_i (ext_id, int_id);
+}
+
+template <class EXT_ID,
+ class INT_ID,
+ class HASH_KEY,
+ class COMPARE_KEYS,
+ class ACE_LOCK>
+ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK>::unbind (
+ typename ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK>::iterator pos)
+{
+ return this->unbind (&(*pos));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind (const EXT_ID &ext_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_i (ext_id) == -1 ? -1 : 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_i (entry) == -1 ? -1 : 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *entry;
+
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return -1;
+ else
+ {
+ int_id = entry->int_id_;
+ return 0;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &ext_id)
+{
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *entry;
+
+ size_t dummy;
+ return this->shared_find (ext_id, entry, dummy);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id,
+ INT_ID &int_id) const
+{
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *nc_this =
+ const_cast <ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *>
+ (this);
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return nc_this->find_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id) const
+{
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *nc_this =
+ const_cast <ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *>
+ (this);
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return nc_this->find_i (ext_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &ext_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t dummy;
+ return this->shared_find (ext_id, entry, dummy);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry) const
+{
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *nc_this =
+ const_cast <ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *>
+ (this);
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return nc_this->find_i (ext_id, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *node;
+
+ return this->rebind_i (ext_id,
+ int_id,
+ node);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id)
+{
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *node;
+
+ return this->rebind_i (ext_id,
+ int_id,
+ old_int_id,
+ node);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id)
+{
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *node;
+
+ return this->rebind_i (ext_id,
+ int_id,
+ old_ext_id,
+ old_int_id,
+ node);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id, old_int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id, old_int_id, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id, old_ext_id, old_int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id, old_ext_id, old_int_id, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+typename ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::iterator
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::begin (void)
+{
+ return iterator (*this);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+typename ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::iterator
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::end (void)
+{
+ return iterator (*this, 1);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+typename ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::const_iterator
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::begin (void) const
+{
+ return const_iterator (*this);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+typename ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::const_iterator
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::end (void) const
+{
+ return const_iterator (*this, 1);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+typename ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_iterator
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rbegin (void)
+{
+ return reverse_iterator (*this);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+typename ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_iterator
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rend (void)
+{
+ return reverse_iterator (*this, 1);
+}
+
+ template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ typename ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::const_reverse_iterator
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rbegin (void) const
+ {
+ return const_reverse_iterator (*this);
+ }
+
+ template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ typename ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::const_reverse_iterator
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rend (void) const
+ {
+ return const_reverse_iterator (*this, 1);
+ }
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Entry<EXT_ID, INT_ID> *
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::table (void)
+{
+ return this->table_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+size_t
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::cur_size (void) const
+{
+ return this->cur_size_;
+}
+
+template <class EXT_ID,
+ class INT_ID,
+ class HASH_KEY,
+ class COMPARE_KEYS,
+ class ACE_LOCK>
+ACE_INLINE void
+ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK>::find (
+ EXT_ID const &ext_id,
+ typename ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK>::iterator & pos) const
+{
+ ENTRY * entry = 0;
+ size_t index = 0;
+
+ ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *nc_this =
+ const_cast <ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *>
+ (this);
+
+ ACE_READ_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ if (nc_this->shared_find (ext_id, entry, index) != -1)
+ pos = iterator (*nc_this, entry, index);
+ else
+ pos = nc_this->end ();
+}
+
+// ---------------------------------------------------------------------
+
+template <class EXT_ID,
+ class INT_ID,
+ class HASH_KEY,
+ class COMPARE_KEYS,
+ class ACE_LOCK>
+ACE_INLINE
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK>::ACE_Hash_Map_Iterator_Base_Ex (
+ ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK> &mm,
+ bool head)
+ : map_man_ (&mm),
+ index_ (head ? -1 : (ssize_t) mm.total_size_),
+ next_ (0)
+{
+ if (mm.table_ != 0)
+ this->next_ = &mm.table_[head ? 0 : mm.total_size_ - 1];
+}
+
+template <class EXT_ID,
+ class INT_ID,
+ class HASH_KEY,
+ class COMPARE_KEYS,
+ class ACE_LOCK>
+ACE_INLINE
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK>::ACE_Hash_Map_Iterator_Base_Ex (
+ ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK> & mm,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> * entry,
+ size_t index)
+ : map_man_ (&mm)
+ , index_ (static_cast<ssize_t> (index))
+ , next_ (entry)
+{
+}
+
+template <class EXT_ID,
+ class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::next (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::next");
+
+ if (this->map_man_->table_ != 0
+ && this->index_ < static_cast<ssize_t> (this->map_man_->total_size_)
+ && this->index_ >= 0
+ && this->next_ != &this->map_man_->table_[this->index_])
+ {
+ entry = this->next_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::done (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::done");
+
+ return this->map_man_->table_ == 0
+ || this->index_ >= static_cast<ssize_t> (this->map_man_->total_size_)
+ || this->index_ < 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Entry<EXT_ID, INT_ID> &
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator* (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator*");
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+
+ ACE_UNUSED_ARG (result);
+ ACE_ASSERT (result != 0);
+
+ return *retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Entry<EXT_ID, INT_ID> *
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-> (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator->");
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+
+ ACE_UNUSED_ARG (result);
+ ACE_ASSERT (result != 0);
+
+ return retv;
+}
+
+// Returns the reference to the hash_map_manager_ex that is being
+// iterated over.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>&
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map");
+ return *this->map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator== (const ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator==");
+ return this->map_man_ == rhs.map_man_
+ && this->index_ == rhs.index_
+ && this->next_ == rhs.next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!= (const ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!=");
+ return this->next_ != rhs.next_
+ || this->index_ != rhs.index_
+ || this->map_man_ != rhs.map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Const_Iterator_Base_Ex (const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head)
+ : map_man_ (&mm),
+ index_ (head != 0 ? -1 : (ssize_t) mm.total_size_),
+ next_ (0)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Const_Iterator_Base_Ex");
+
+ if (mm.table_ != 0)
+ this->next_ = &mm.table_[head != 0 ? 0 : mm.total_size_ - 1];
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::next (ACE_Hash_Map_Entry<EXT_ID, INT_ID> *&entry) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::next");
+
+ if (this->map_man_->table_ != 0
+ && this->index_ < (ssize_t) this->map_man_->total_size_
+ && this->index_ >= 0
+ && this->next_ != &this->map_man_->table_[this->index_])
+ {
+ entry = this->next_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::done (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::done");
+
+ return this->map_man_->table_ == 0
+ || this->index_ >= (ssize_t) this->map_man_->total_size_
+ || this->index_ < 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Entry<EXT_ID, INT_ID> &
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator* (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator*");
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+
+ ACE_UNUSED_ARG (result);
+ ACE_ASSERT (result != 0);
+
+ return *retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Entry<EXT_ID, INT_ID> *
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-> (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator->");
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+
+ ACE_UNUSED_ARG (result);
+ ACE_ASSERT (result != 0);
+
+ return retv;
+}
+
+// Returns the reference to the hash_map_manager_ex that is being
+// iterated over.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>&
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map");
+ return *this->map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator== (const ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator==");
+ return this->map_man_ == rhs.map_man_
+ && this->index_ == rhs.index_
+ && this->next_ == rhs.next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!= (const ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!=");
+ return this->next_ != rhs.next_
+ || this->index_ != rhs.index_
+ || this->map_man_ != rhs.map_man_;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Iterator_Ex)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE void
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Iterator_Ex (ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int tail)
+ : ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (mm,
+ tail == 0 ? 1 : 0)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Iterator_Ex");
+ if (tail == 0)
+ this->forward_i ();
+}
+
+template <class EXT_ID,
+ class INT_ID,
+ class HASH_KEY,
+ class COMPARE_KEYS,
+ class ACE_LOCK>
+ACE_INLINE
+ACE_Hash_Map_Iterator_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK>::ACE_Hash_Map_Iterator_Ex (
+ ACE_Hash_Map_Manager_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK> & mm,
+ ACE_Hash_Map_Entry<EXT_ID, INT_ID> * entry,
+ size_t index)
+ : ACE_Hash_Map_Iterator_Base_Ex<EXT_ID,
+ INT_ID,
+ HASH_KEY,
+ COMPARE_KEYS,
+ ACE_LOCK> (mm,
+ entry,
+ index)
+{
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance");
+ return this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Const_Iterator_Ex)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE void
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Const_Iterator_Ex (const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int tail)
+ : ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (mm,
+ tail == 0 ? 1 : 0)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Const_Iterator_Ex");
+ if (tail == 0)
+ this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance");
+ return this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Bucket_Iterator (ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ const EXT_ID &ext_id,
+ int tail)
+ : map_man_ (&mm)
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Bucket_Iterator");
+
+ this->index_ = this->map_man_->hash (ext_id) % this->map_man_->total_size_;
+ this->next_ = &this->map_man_->table_[this->index_];
+
+ if (tail == 0)
+ this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i");
+
+ this->next_ = this->next_->next_;
+ return this->next_ != &this->map_man_->table_[this->index_];
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i");
+
+ this->next_ = this->next_->prev_;
+ return this->next_ != &this->map_man_->table_[this->index_];
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Entry<EXT_ID, INT_ID> &
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator* (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator*");
+
+ return *this->next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Entry<EXT_ID, INT_ID> *
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-> (void) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator->");
+
+ return this->next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map");
+ return *this->map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator== (const ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator==");
+ return this->map_man_ == rhs.map_man_
+ && this->index_ == rhs.index_
+ && this->next_ == rhs.next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!= (const ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!=");
+ return this->next_ != rhs.next_
+ || this->index_ != rhs.index_
+ || this->map_man_ != rhs.map_man_;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Reverse_Iterator_Ex)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE void
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Reverse_Iterator_Ex (ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm, int head)
+ : ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (mm, head)
+{
+ ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Reverse_Iterator_Ex");
+ if (head == 0)
+ this->reverse_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance");
+ return this->reverse_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Const_Reverse_Iterator_Ex)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE void
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Const_Reverse_Iterator_Ex (const ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm, int head)
+ : ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (mm, head)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Map_Const_Reverse_Iterator_Ex");
+ if (head == 0)
+ this->reverse_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance");
+ return this->reverse_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Map_Const_Reverse_Iterator_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::ACE_Hash_Map_Manager (ACE_Allocator *table_alloc,
+ ACE_Allocator *entry_alloc)
+ : ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> (table_alloc,
+ entry_alloc)
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::ACE_Hash_Map_Manager (size_t size,
+ ACE_Allocator *table_alloc,
+ ACE_Allocator *entry_alloc)
+ : ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> (size,
+ table_alloc,
+ entry_alloc)
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::equal (const EXT_ID &id1, const EXT_ID &id2)
+{
+ return ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::equal (id1, id2);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> u_long
+ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::hash (const EXT_ID &ext_id)
+{
+ return ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK>::hash (ext_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Hash_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Hash_Map_Iterator (ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int tail)
+ : ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> (mm,
+ tail)
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Hash_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Hash_Map_Iterator (const ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base)
+ : ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> (base)
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_Hash_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Hash_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator= (const ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &rhs)
+{
+ if (this != &rhs)
+ {
+ ACE_Hash_Map_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base = *this;
+
+ base = rhs;
+ }
+
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Hash_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Hash_Map_Const_Iterator (const ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int tail)
+ : ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> (mm,
+ tail)
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Hash_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Hash_Map_Const_Iterator (const ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base)
+ : ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> (base)
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_Hash_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Hash_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator= (const ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &rhs)
+{
+ if (this != &rhs)
+ {
+ ACE_Hash_Map_Const_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base = *this;
+
+ base = rhs;
+ }
+
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Hash_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Hash_Map_Reverse_Iterator (ACE_Hash_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int head)
+ : ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> (mm,
+ head)
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Hash_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Hash_Map_Reverse_Iterator (const ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base)
+ : ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> (base)
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_Hash_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Hash_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator= (const ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &rhs)
+{
+ ACE_Hash_Map_Reverse_Iterator_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_LOCK> &base = *this;
+
+ base = rhs;
+
+ return *this;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Hash_Map_With_Allocator_T.cpp b/ACE/ace/Hash_Map_With_Allocator_T.cpp
new file mode 100644
index 00000000000..9927147e865
--- /dev/null
+++ b/ACE/ace/Hash_Map_With_Allocator_T.cpp
@@ -0,0 +1,35 @@
+// $Id$
+
+#ifndef ACE_HASH_MAP_WITH_ALLOCATOR_T_CPP
+#define ACE_HASH_MAP_WITH_ALLOCATOR_T_CPP
+
+#include "ace/Hash_Map_With_Allocator_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Hash_Map_With_Allocator_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class EXT_ID, class INT_ID>
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::ACE_Hash_Map_With_Allocator (ACE_Allocator *alloc)
+ : ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_Null_Mutex> (alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::ACE_Hash_Map_With_Allocator");
+}
+
+template <class EXT_ID, class INT_ID>
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::ACE_Hash_Map_With_Allocator (size_t size,
+ ACE_Allocator *alloc)
+ : ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_Null_Mutex> (size, alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::ACE_Hash_Map_With_Allocator");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HASH_MAP_WITH_ALLOCATOR_T_CPP */
diff --git a/ACE/ace/Hash_Map_With_Allocator_T.h b/ACE/ace/Hash_Map_With_Allocator_T.h
new file mode 100644
index 00000000000..1c2413ba3f2
--- /dev/null
+++ b/ACE/ace/Hash_Map_With_Allocator_T.h
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Hash_Map_With_Allocator_T.h
+ *
+ * $Id$
+ *
+ * @author Marina Spivak <marina@cs.wustl.edu>
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_HASH_MAP_WITH_ALLOCATOR_T_H
+#define ACE_HASH_MAP_WITH_ALLOCATOR_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Null_Mutex.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Hash_Map_With_Allocator
+ *
+ * @brief This class is a thin wrapper around ACE_Hash_Map_Manager,
+ * which comes handy when ACE_Hash_Map_Manager is to be used with a
+ * non-nil ACE_Allocator. This wrapper insures that the appropriate
+ * allocator is in place for every operation that accesses or
+ * updates the hash map.
+ *
+ * If we use ACE_Hash_Map_Manager with a shared memory allocator
+ * (or memory-mapped file allocator, for example), the allocator
+ * pointer used by ACE_Hash_Map_Manager gets stored with it, in
+ * shared memory (or memory-mapped file). 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! That is why we need this wrapper, which
+ * insures that appropriate allocator pointer is in place for
+ * each call.
+ *
+ * At some point it would be a good idea to update this class to
+ * use the new "two allocator" technique provided by @c
+ * ACE_Hash_Map_Manager_Ex.
+ */
+template <class EXT_ID, class INT_ID>
+class ACE_Hash_Map_With_Allocator :
+ public ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID, ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_Null_Mutex>
+{
+public:
+ /// Constructor.
+ ACE_Hash_Map_With_Allocator (ACE_Allocator *alloc);
+
+ /// Constructor that specifies hash table size.
+ ACE_Hash_Map_With_Allocator (size_t size,
+ ACE_Allocator *alloc);
+
+ // = The following methods are Proxies to the corresponding methods
+ // in ACE_Hash_Map_Manager. Each method sets the allocator to
+ // the one specified by the invoking entity, and then calls the
+ // corresponding method in ACE_Hash_Map_Manager to do the
+ // actual work.
+
+ int bind (const EXT_ID &,
+ const INT_ID &,
+ ACE_Allocator *alloc);
+
+ int unbind (const EXT_ID &,
+ INT_ID &,
+ ACE_Allocator *alloc);
+
+ int unbind (const EXT_ID &,
+ ACE_Allocator *alloc);
+
+ int rebind (const EXT_ID &,
+ const INT_ID &,
+ EXT_ID &,
+ INT_ID &,
+ ACE_Allocator *alloc);
+
+ int find (const EXT_ID &,
+ INT_ID &,
+ ACE_Allocator *alloc);
+
+ /// Returns 0 if the @a ext_id is in the mapping, otherwise -1.
+ int find (const EXT_ID &ext_id,
+ ACE_Allocator *alloc);
+
+ int close (ACE_Allocator *alloc);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Hash_Map_With_Allocator_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Hash_Map_With_Allocator_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Hash_Map_With_Allocator_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HASH_MAP_WITH_ALLOCATOR_T_H */
diff --git a/ACE/ace/Hash_Map_With_Allocator_T.inl b/ACE/ace/Hash_Map_With_Allocator_T.inl
new file mode 100644
index 00000000000..4ba51437abf
--- /dev/null
+++ b/ACE/ace/Hash_Map_With_Allocator_T.inl
@@ -0,0 +1,82 @@
+// -*- C++ -*-
+
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class EXT_ID, class INT_ID> ACE_INLINE int
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::close (ACE_Allocator *alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::close");
+ this->table_allocator_ = alloc;
+ this->entry_allocator_ = alloc;
+ return this->close_i ();
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE int
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::bind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Allocator *alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::bind");
+ this->table_allocator_ = alloc;
+ this->entry_allocator_ = alloc;
+ return this->bind_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE int
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::unbind (const EXT_ID &ext_id,
+ INT_ID &int_id,
+ ACE_Allocator *alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::unbind");
+ this->table_allocator_ = alloc;
+ this->entry_allocator_ = alloc;
+ return this->unbind_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE int
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::unbind (const EXT_ID &ext_id,
+ ACE_Allocator *alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID>::unbind");
+ this->table_allocator_ = alloc;
+ this->entry_allocator_ = alloc;
+ return this->unbind_i (ext_id);
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE int
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id,
+ ACE_Allocator *alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::rebind");
+ this->table_allocator_ = alloc;
+ this->entry_allocator_ = alloc;
+ return this->rebind_i (ext_id, int_id, old_ext_id, old_int_id);
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE int
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::find (const EXT_ID &ext_id,
+ INT_ID &int_id,
+ ACE_Allocator *alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::find");
+ this->table_allocator_ = alloc;
+ this->entry_allocator_ = alloc;
+ return this->find_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE int
+ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::find (const EXT_ID &ext_id,
+ ACE_Allocator *alloc)
+{
+ ACE_TRACE ("ACE_Hash_Map_With_Allocator<EXT_ID, INT_ID>::find");
+ this->table_allocator_ = alloc;
+ this->entry_allocator_ = alloc;
+ return this->find_i (ext_id);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Hash_Multi_Map_Manager_T.cpp b/ACE/ace/Hash_Multi_Map_Manager_T.cpp
new file mode 100644
index 00000000000..34e8b0406be
--- /dev/null
+++ b/ACE/ace/Hash_Multi_Map_Manager_T.cpp
@@ -0,0 +1,605 @@
+
+//=============================================================================
+/**
+ * @file Hash_Multi_Map_Manager_T.cpp
+ *
+ * $Id$
+ *
+ * @author Shanshan Jiang <shanshan.jiang@vanderbilt.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_Hash_Multi_Map_Manager_T_CPP
+#define ACE_Hash_Multi_Map_Manager_T_CPP
+
+#include "ace/Hash_Multi_Map_Manager_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Hash_Multi_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Malloc_Base.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+
+template <class EXT_ID, class INT_ID>
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>::ACE_Hash_Multi_Map_Entry (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *next,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *prev)
+ : next_ (next),
+ prev_ (prev)
+{
+}
+
+template <class EXT_ID, class INT_ID>
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>::ACE_Hash_Multi_Map_Entry (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *next,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *prev)
+ : ext_id_ (ext_id),
+ int_id_set_ (int_id_set),
+ next_ (next),
+ prev_ (prev)
+{
+}
+
+# if ! defined (ACE_HAS_BROKEN_NOOP_DTORS)
+template <class EXT_ID, class INT_ID>
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>::~ACE_Hash_Multi_Map_Entry (void)
+{
+}
+# endif /* ! defined (ACE_HAS_BROKEN_NOOP_DTORS) */
+
+template <class EXT_ID, class INT_ID> EXT_ID &
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>::key ()
+{
+ return ext_id_;
+}
+
+template <class EXT_ID, class INT_ID> ACE_Unbounded_Set<INT_ID> &
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>::item ()
+{
+ return int_id_set_;
+}
+
+template <class EXT_ID, class INT_ID> void
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %d"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("prev_ = %d"), this->prev_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("total_size_ = %d"), this->total_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_));
+ this->table_allocator_->dump ();
+ this->entry_allocator_->dump ();
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::create_buckets (size_t size)
+{
+ size_t bytes = size * sizeof (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>);
+ void *ptr;
+
+ ACE_ALLOCATOR_RETURN (ptr,
+ this->table_allocator_->malloc (bytes),
+ -1);
+
+ this->table_ = (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *) ptr;
+
+ this->total_size_ = size;
+
+ // Initialize each entry in the hash table to be a circular linked
+ // list with the dummy node in the front serving as the anchor of
+ // the list.
+ for (size_t i = 0; i < size; i++)
+ new (&this->table_[i]) ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> (&this->table_[i],
+ &this->table_[i]);
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::open (size_t size,
+ ACE_Allocator *table_alloc,
+ ACE_Allocator *entry_alloc)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ // Calling this->close_i () to ensure we release previous allocated
+ // memory before allocating new one.
+ this->close_i ();
+
+ if (table_alloc == 0)
+ table_alloc = ACE_Allocator::instance ();
+
+ this->table_allocator_ = table_alloc;
+
+ if (entry_alloc == 0)
+ entry_alloc = table_alloc;
+
+ this->entry_allocator_ = entry_alloc;
+
+ // This assertion is here to help track a situation that shouldn't
+ // happen, but did with Sun C++ 4.1 (before a change to this class
+ // was made: it used to have an enum that was supposed to be defined
+ // to be ACE_DEFAULT_MAP_SIZE, but instead was defined to be 0).
+ if (size == 0)
+ return -1;
+
+ return this->create_buckets (size);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::close_i (void)
+{
+ // Protect against "double-deletion" in case the destructor also
+ // gets called.
+ if (this->table_ != 0)
+ {
+ // Remove all the entries.
+ this->unbind_all_i ();
+
+ // Iterate through the buckets cleaning up the sentinels.
+ for (size_t i = 0; i < this->total_size_; i++)
+ {
+ // Destroy the dummy entry.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *entry = &this->table_[i];
+
+ // The second argument results in a no-op instead of
+ // deallocation.
+ ACE_DES_FREE_TEMPLATE2 (entry, ACE_NOOP,
+ ACE_Hash_Multi_Map_Entry, EXT_ID, INT_ID);
+ }
+
+ // Reset size.
+ this->total_size_ = 0;
+
+ // Free table memory.
+ this->table_allocator_->free (this->table_);
+
+ // Should be done last...
+ this->table_ = 0;
+ }
+
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_all_i (void)
+{
+ // Iterate through the entire map calling the destuctor of each
+ // <ACE_Hash_Multi_Map_Entry>.
+ for (size_t i = 0; i < this->total_size_; i++)
+ {
+ for (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *temp_ptr = this->table_[i].next_;
+ temp_ptr != &this->table_[i];
+ )
+ {
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *hold_ptr = temp_ptr;
+ temp_ptr = temp_ptr->next_;
+
+ // Explicitly call the destructor.
+ ACE_DES_FREE_TEMPLATE2 (hold_ptr, this->entry_allocator_->free,
+ ACE_Hash_Multi_Map_Entry, EXT_ID, INT_ID);
+ }
+
+ // Restore the sentinel.
+ this->table_[i].next_ = &this->table_[i];
+ this->table_[i].prev_ = &this->table_[i];
+ }
+
+ this->cur_size_ = 0;
+
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t loc;
+ int result = this->shared_find (ext_id, entry, loc);
+
+ ACE_Unbounded_Set<INT_ID> int_id_set;
+ if (result == -1)
+ {
+ void *ptr;
+ // Not found.
+ ACE_ALLOCATOR_RETURN (ptr,
+ this->entry_allocator_->malloc (sizeof (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>)),
+ -1);
+
+ int_id_set.insert (int_id);
+
+ entry = new (ptr) ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> (ext_id,
+ int_id_set,
+ this->table_[loc].next_,
+ &this->table_[loc]);
+ this->table_[loc].next_ = entry;
+ entry->next_->prev_ = entry;
+ this->cur_size_++;
+ return 0;
+ }
+ else
+ {
+ int_id_set = (*entry).int_id_set_;
+
+ if (0 == int_id_set.insert (int_id))
+ {
+ this->unbind_i (entry);
+ return this->bind_i (ext_id, int_id_set);
+ }
+ else
+ return 1;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t loc;
+ int result = this->shared_find (ext_id, entry, loc);
+
+ if (result == -1)
+ {
+ void *ptr;
+ // Not found.
+ ACE_ALLOCATOR_RETURN (ptr,
+ this->entry_allocator_->malloc (sizeof (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>)),
+ -1);
+
+ entry = new (ptr) ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> (ext_id,
+ int_id_set,
+ this->table_[loc].next_,
+ &this->table_[loc]);
+ this->table_[loc].next_ = entry;
+ entry->next_->prev_ = entry;
+ this->cur_size_++;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::trybind_i (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t loc;
+ int result = this->shared_find (ext_id, entry, loc);
+
+ if (result == -1)
+ {
+ // Not found.
+ void *ptr;
+ ACE_ALLOCATOR_RETURN (ptr,
+ this->entry_allocator_->malloc (sizeof (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>)),
+ -1);
+
+ entry = new (ptr) ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> (ext_id,
+ int_id_set,
+ this->table_[loc].next_,
+ &this->table_[loc]);
+ this->table_[loc].next_ = entry;
+ entry->next_->prev_ = entry;
+ this->cur_size_++;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_i (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *temp;
+
+ size_t loc;
+ int result = this->shared_find (ext_id, temp, loc);
+
+ if (result == -1)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ int_id_set = temp->int_id_set_;
+
+ return this->unbind_i (temp);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_i (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *entry)
+{
+ entry->next_->prev_ = entry->prev_;
+ entry->prev_->next_ = entry->next_;
+
+ // Explicitly call the destructor.
+ ACE_DES_FREE_TEMPLATE2 (entry, this->entry_allocator_->free,
+ ACE_Hash_Multi_Map_Entry, EXT_ID, INT_ID);
+
+ this->cur_size_--;
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *temp;
+
+ size_t loc;
+ int result = this->shared_find (ext_id, temp, loc);
+
+ if (result == -1)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ ACE_Unbounded_Set<INT_ID> int_id_set = (*temp).int_id_set_;
+ if (0 == int_id_set.remove (int_id))
+ {
+ this->unbind_i (temp);
+
+ if (0 != int_id_set.size ())
+ return this->bind_i (ext_id, int_id_set);
+ else
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::shared_find (const EXT_ID &ext_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry,
+ size_t &loc)
+{
+ loc = this->hash (ext_id) % this->total_size_;
+
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *temp = this->table_[loc].next_;
+
+ while (temp != &this->table_[loc] && this->equal (temp->ext_id_, ext_id) == 0)
+ temp = temp->next_;
+
+ if (temp == &this->table_[loc])
+ {
+ errno = ENOENT;
+ return -1;
+ }
+ else
+ {
+ entry = temp;
+ return 0;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return this->bind_i (ext_id, int_id_set);
+ else
+ {
+ entry->ext_id_ = ext_id;
+ entry->int_id_set_ = int_id_set;
+ return 1;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return this->bind_i (ext_id, int_id_set);
+ else
+ {
+ old_int_id_set = entry->int_id_set_;
+ entry->ext_id_ = ext_id;
+ entry->int_id_set_ = int_id_set;
+ return 1;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ EXT_ID &old_ext_id,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return this->bind_i (ext_id, int_id_set);
+ else
+ {
+ old_ext_id = entry->ext_id_;
+ old_int_id_set = entry->int_id_set_;
+ entry->ext_id_ = ext_id;
+ entry->int_id_set_ = int_id_set;
+ return 1;
+ }
+}
+
+// ------------------------------------------------------------
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Multi_Map_Iterator_Base)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("index_ = %d "), this->index_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %x"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i");
+
+ if (this->map_man_->table_ == 0)
+ return -1;
+ // Handle initial case specially.
+ else if (this->index_ == -1)
+ {
+ this->index_++;
+ return this->forward_i ();
+ }
+ else if (this->index_ >= static_cast<ssize_t> (this->map_man_->total_size_))
+ return 0;
+
+ this->next_ = this->next_->next_;
+ if (this->next_ == &this->map_man_->table_[this->index_])
+ {
+ while (++this->index_ < static_cast<ssize_t> (this->map_man_->total_size_))
+ {
+ this->next_ = this->map_man_->table_[this->index_].next_;
+ if (this->next_ != &this->map_man_->table_[this->index_])
+ break;
+ }
+ }
+
+ return this->index_ < static_cast<ssize_t> (this->map_man_->total_size_);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i");
+
+ if (this->map_man_->table_ == 0)
+ return -1;
+ else if (this->index_ == static_cast<ssize_t> (this->map_man_->total_size_))
+ {
+ this->index_--;
+ return this->reverse_i ();
+ }
+ else if (this->index_ < 0)
+ return 0;
+
+ this->next_ = this->next_->prev_;
+ if (this->next_ == &this->map_man_->table_[this->index_])
+ {
+ while (--this->index_ >= 0)
+ {
+ this->next_ = this->map_man_->table_[this->index_].prev_;
+ if (this->next_ != &this->map_man_->table_[this->index_])
+ break;
+ }
+ }
+
+ return this->index_ >= 0;
+}
+
+// ------------------------------------------------------------
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Multi_Map_Const_Iterator_Base)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("index_ = %d "), this->index_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %x"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i");
+
+ if (this->map_man_->table_ == 0)
+ return -1;
+ // Handle initial case specially.
+ else if (this->index_ == -1)
+ {
+ this->index_++;
+ return this->forward_i ();
+ }
+ else if (this->index_ >= (ssize_t) this->map_man_->total_size_)
+ return 0;
+
+ this->next_ = this->next_->next_;
+ if (this->next_ == &this->map_man_->table_[this->index_])
+ {
+ while (++this->index_ < (ssize_t) this->map_man_->total_size_)
+ {
+ this->next_ = this->map_man_->table_[this->index_].next_;
+ if (this->next_ != &this->map_man_->table_[this->index_])
+ break;
+ }
+ }
+
+ return this->index_ < (ssize_t) this->map_man_->total_size_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i");
+
+ if (this->map_man_->table_ == 0)
+ return -1;
+ else if (this->index_ == (ssize_t) this->map_man_->total_size_)
+ {
+ this->index_--;
+ return this->reverse_i ();
+ }
+ else if (this->index_ < 0)
+ return 0;
+
+ this->next_ = this->next_->prev_;
+ if (this->next_ == &this->map_man_->table_[this->index_])
+ {
+ while (--this->index_ >= 0)
+ {
+ this->next_ = this->map_man_->table_[this->index_].prev_;
+ if (this->next_ != &this->map_man_->table_[this->index_])
+ break;
+ }
+ }
+
+ return this->index_ >= 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_Hash_Multi_Map_Manager_T_CPP */
diff --git a/ACE/ace/Hash_Multi_Map_Manager_T.h b/ACE/ace/Hash_Multi_Map_Manager_T.h
new file mode 100644
index 00000000000..11e54292477
--- /dev/null
+++ b/ACE/ace/Hash_Multi_Map_Manager_T.h
@@ -0,0 +1,967 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Hash_Multi_Map_Manager_T.h
+ *
+ * $Id$
+ *
+ * The code in Hash_Multi_Map_Manager_T.* was based on the code in
+ * Hash_Map_Manager_T.*.
+ *
+ * ACE_Hash_Multi_Map_Manager maps a key type to more than one value types.
+ * The template takes the key and value types as parameters. The bind and
+ * unbind operations can take a key and the value or the set of the values that
+ * is to be associated with that key. The find operation can take a key or a
+ * key and the value that is associated with the key.
+ *
+ * ACE_Hash_Multi_Map_Manager uses @c ACE_Unbounded_Set to store differet values
+ * with the same key.
+ *
+ * @author Shanshan Jiang <shanshan.jiang@vanderbilt.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_HASH_MULTI_MAP_MANAGER_T_H
+#define ACE_HASH_MULTI_MAP_MANAGER_T_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/Default_Constants.h"
+#include "ace/Functor_T.h"
+#include "ace/Log_Msg.h"
+
+#include "ace/Unbounded_Set.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Hash_Multi_Map_Entry
+ *
+ * @brief Define an entry in the hash table.
+ */
+template <class EXT_ID, class INT_ID>
+class ACE_Hash_Multi_Map_Entry
+{
+public:
+ friend class ACE_Unbounded_Set<INT_ID>;
+
+ typedef ACE_Unbounded_Set<INT_ID> VALUE_SET;
+ typedef ACE_Unbounded_Set_Iterator<INT_ID> VALUE_SET_ITERATOR;
+
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Hash_Multi_Map_Entry (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *next = 0,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *prev = 0);
+
+ /// Constructor.
+ ACE_Hash_Multi_Map_Entry (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *next,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *prev);
+
+ # if ! defined (ACE_HAS_BROKEN_NOOP_DTORS)
+ /// Destructor.
+ ~ACE_Hash_Multi_Map_Entry (void);
+ #endif /* ! defined (ACE_HAS_BROKEN_NOOP_DTORS) */
+
+ /// Key accessor.
+ EXT_ID& key (void);
+
+ /// Item accessor.
+ ACE_Unbounded_Set<INT_ID>& item (void);
+
+ /// Key used to look up an entry.
+ /// @deprecated Use key()
+ EXT_ID ext_id_;
+
+ /// The contents of the entry itself.
+ /// @deprecated Use item()
+ ACE_Unbounded_Set<INT_ID> int_id_set_;
+
+ /// Pointer to the next item in the bucket of overflow nodes.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *next_;
+
+ /// Pointer to the prev item in the bucket of overflow nodes.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *prev_;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+};
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Iterator_Base;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Const_Iterator_Base;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Iterator;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Const_Iterator;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Reverse_Iterator;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Bucket_Iterator;
+
+// Forward decl.
+class ACE_Allocator;
+
+/**
+ * @class ACE_Hash_Multi_Map_Manager
+ *
+ * @brief Define a multi-map abstraction that efficiently associates the keys
+ * with their different values.
+ *
+ * This implementation of a multi-map uses a hash table. Key hashing
+ * is achieved through the @c HASH_KEY object and key comparison is
+ * achieved through the @c COMPARE_KEYS object.
+ * This class uses an @c ACE_Allocator to allocate memory. The
+ * user can make this a persistent class by providing an
+ * @c ACE_Allocator with a persistable memory pool.
+ */
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Manager
+{
+public:
+ friend class ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>;
+
+ typedef EXT_ID
+ KEY;
+ typedef INT_ID
+ VALUE;
+ typedef ACE_LOCK lock_type;
+ typedef ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>
+ ENTRY;
+
+ // = ACE-style iterator typedefs.
+ typedef ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ ITERATOR;
+ typedef ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ CONST_ITERATOR;
+ typedef ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ REVERSE_ITERATOR;
+
+ // = STL-style iterator typedefs.
+ typedef ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ iterator;
+ typedef ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ const_iterator;
+ typedef ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ reverse_iterator;
+
+ // = Initialization and termination methods.
+
+ /**
+ * Initialize a @c Hash_Multi_Map_Manager with default size elements.
+ * @param table_alloc is a pointer to a memory allocator used for
+ * table_, so it should supply size*sizeof (
+ * ACE_Hash_Multi_Map_Entry<@c EXT_ID, @c INT_ID>).
+ * @param entry_alloc is a pointer to an additional allocator for
+ * entries, so it should be able to allocate 'size' / chunks
+ * of sizeof (ACE_Hash_Multi_Map_Entry<@c EXT_ID, @c INT_ID>) bytes
+ * each.
+ * If @a table_alloc is 0 it defaults to @c ACE_Allocator::instance().
+ * If @a entry_alloc is 0 then it defaults to the same allocator as
+ * @a table_alloc.
+ */
+ ACE_Hash_Multi_Map_Manager (ACE_Allocator *table_alloc = 0,
+ ACE_Allocator *entry_alloc = 0);
+
+ /**
+ * Initialize a @c Hash_Multi_Map_Manager with @a size elements.
+ * @param size is the number of elements in a Hash_Multi_Map_Manager.
+ * @param table_alloc is a pointer to a memory allocator used for
+ * table_, so it should supply size*sizeof (
+ * ACE_Hash_Multi_Map_Entry<@c EXT_ID, <@c INT_ID>).
+ * @param entry_alloc is a pointer to an additional allocator for
+ * entries, so it should be able to allocate 'size' / chunks
+ * of sizeof (ACE_Hash_Multi_Map_Entry<@c EXT_ID, @c INT_ID>) bytes
+ * each.
+ * If @a table_alloc is 0 it defaults to @c ACE_Allocator::instance().
+ * If @a entry_alloc is 0 then it defaults to the same allocator as
+ * @a table_alloc.
+ */
+ ACE_Hash_Multi_Map_Manager (size_t size,
+ ACE_Allocator *table_alloc = 0,
+ ACE_Allocator *entry_alloc = 0);
+
+ /**
+ * Initialize a @c Hash_Multi_Map_Manager with @a size elements.
+ * @param size is the number of elements in a Hash_Multi_Map_Manager.
+ * @param table_alloc is a pointer to a memory allocator used for
+ * table_, so it should supply size*sizeof
+ * (ACE_Hash_Multi_Map_Entry<@c EXT_ID, <@c INT_ID>).
+ * @param entry_alloc is a pointer to an additional allocator for
+ * entries, so it should be able to allocate 'size' / chunks
+ * of sizeof (ACE_Hash_Multi_Map_Entry<@c EXT_ID, <@c INT_ID>) bytes
+ * each.
+ * If @a table_alloc is 0 it defaults to @c ACE_Allocator::instance().
+ * If @a entry_alloc is 0 then it defaults to the same allocator as
+ * @a table_alloc.
+ * @return -1 on failure, 0 on success
+ */
+
+ int open (size_t size = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *table_alloc = 0,
+ ACE_Allocator *entry_alloc = 0);
+
+ /// Close down a Hash_Multi_Map_Manager and release dynamically allocated
+ /// resources.
+ int close (void);
+
+ /// Removes all the entries in Hash_Multi_Map_Manager.
+ int unbind_all (void);
+
+ /// Cleanup the Hash_Multi_Map_Manager.
+ ~ACE_Hash_Multi_Map_Manager (void);
+
+ /**
+ * Associate @a ext_id with @a int_id. If @a ext_id and @a int_id is already
+ * in the map then the @c ACE_Hash_Multi_Map_Entry is not changed. Returns 0 if
+ * a new entry is bound successfully, returns 1 if an attempt is made
+ * to bind an existing entry, and returns -1 if failures occur.
+ */
+ int bind (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /**
+ * Same as a normal bind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int bind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id_set. If @a ext_id is already in the
+ * map then the @c ACE_Hash_Multi_Map_Entry is not changed. Returns 0 if a
+ * new entry is bound successfully, returns 1 if an attempt is made
+ * to bind an existing entry, and returns -1 if failures occur.
+ */
+ int bind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /**
+ * Same as a normal bind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int bind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id_set if and only if @a ext_id is
+ * not in the map. If @a ext_id is already in the map then the @a int_id_set
+ * parameter is assigned the existing value in the map. Returns 0
+ * if a new entry is bound successfully, returns 1 if an attempt is
+ * made to bind an existing entry, and returns -1 if failures occur.
+ */
+ int trybind (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /**
+ * Same as a normal trybind, except the map entry is also passed
+ * back to the caller. The entry in this case will either be the
+ * newly created entry, or the existing one.
+ */
+ int trybind (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Reassociate @a ext_id with @a int_id_set. If @a ext_id is not in
+ * the map then behaves just like bind. Returns 0 if a new entry is
+ * bound successfully, returns 1 if an existing entry was rebound,
+ * and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /**
+ * Same as a normal rebind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id_set. If @a ext_id is not in the map
+ * then behaves just like bind. Otherwise, store the old value of
+ * @a int_id_set into the "out" parameter and rebind the new parameters.
+ * Returns 0 if a new entry is bound successfully, returns 1 if an
+ * existing entry was rebound, and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set);
+
+ /**
+ * Same as a normal rebind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id_set. If @a ext_id is not in the map
+ * then behaves just like bind. Otherwise, store the old values
+ * of @a ext_id and @a int_id_set into the "out" parameters and rebind the
+ * new parameters. This is very useful if you need to have an
+ * atomic way of updating @c ACE_Hash_Multi_Map_Entry objects and you also
+ * need full control over memory allocation. Returns 0 if a new entry
+ * is bound successfully, returns 1 if an existing entry was rebound,
+ * and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ EXT_ID &old_ext_id,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set);
+
+ /**
+ * Same as a normal rebind, except the map entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ EXT_ID &old_ext_id,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Locate @a ext_id and pass out parameter via @a int_id_set.
+ /// Return 0 if found, returns -1 if not found.
+ int find (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set) const;
+
+ /// Locate @a ext_id and @a int_id.
+ /// Return 0 if found, returns -1 if not found.
+ int find (const EXT_ID &ext_id,
+ const INT_ID &int_id) const;
+
+ /// Returns 0 if the @a ext_id is in the mapping, otherwise -1.
+ int find (const EXT_ID &ext_id) const;
+
+ /// Locate @a ext_id and pass out parameter via @a entry. If found,
+ /// return 0, returns -1 if not found.
+ int find (const EXT_ID &ext_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry) const;
+
+ /**
+ * Unbind (remove) the @a ext_id from the map. Don't return the
+ * int_id to the caller (this is useful for collections where the
+ * int_ids are *not* dynamically allocated...)
+ */
+ int unbind (const EXT_ID &ext_id);
+
+ /// Break any association of @a ext_id. Returns the value of @a int_id_set
+ /// in case the caller needs to deallocate memory. Return 0 if the
+ /// unbind was successfully, and returns -1 if failures occur.
+ int unbind (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /// Break any association of @a ext_id and @a int_id. Return 0 if the
+ /// unbind was successfully, and returns -1 if failures occur.
+ int unbind (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Remove @a entry from map. Return 0 if the unbind was successfully,
+ /// and returns -1 if failures occur.
+ int unbind (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *entry);
+
+ /// Returns the current number of @c ACE_Hash_Multi_Map_Entry objects in the
+ /// hash table.
+ size_t current_size (void) const;
+
+ /// Return the size of the array that's used to point to the
+ /// linked lists of @c ACE_Hash_Multi_Map_Entry objects in the hash table.
+ size_t total_size (void) const;
+
+ /**
+ * Returns a reference to the underlying @c ACE_LOCK. This makes it
+ * possible to acquire the lock explicitly, which can be useful in
+ * some cases if you instantiate the @c ACE_Atomic_Op with an
+ * @c ACE_Recursive_Mutex or @c ACE_Process_Mutex, or if you need to
+ * guard the state of an iterator.
+ * @note The right name would be lock, but HP/C++ will choke on that!
+ */
+ ACE_LOCK &mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> begin (void);
+ ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> end (void);
+
+ /// Return reverse iterator.
+ ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> rbegin (void);
+ ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> rend (void);
+
+protected:
+ // = The following methods do the actual work.
+
+ /// Returns 1 if @a id1 == @a id2, else 0. This is defined as a
+ /// separate method to facilitate template specialization.
+ int equal (const EXT_ID &id1, const EXT_ID &id2);
+
+ /// Compute the hash value of the @a ext_id. This is defined as a
+ /// separate method to facilitate template specialization.
+ u_long hash (const EXT_ID &ext_id);
+
+ // = These methods assume locks are held by private methods.
+
+ /// Performs bind. Must be called with locks held.
+ int bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Performs bind. Must be called with locks held.
+ int bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs bind. Must be called with locks held.
+ int bind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /// Performs bind. Must be called with locks held.
+ int bind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs trybind. Must be called with locks held.
+ int trybind_i (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /// Performs trybind. Must be called with locks held.
+ int trybind_i (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Unbounded_Set<INT_ID> &old_int_id);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ EXT_ID &old_ext_id,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set);
+
+ /// Performs rebind. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ EXT_ID &old_ext_id,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs a find of @a int_id_set using @a ext_id as the key. Must be
+ /// called with locks held.
+ int find_i (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /// Performs a find of @a ext_id and @a int_id. Must be
+ /// called with locks held.
+ int find_i (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Performs a find using @a ext_id as the key. Must be called with
+ /// locks held.
+ int find_i (const EXT_ID &ext_id);
+
+ /// Performs a find using @a ext_id as the key. Must be called with
+ /// locks held.
+ int find_i (const EXT_ID &ext_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry);
+
+ /// Performs unbind. Must be called with locks held.
+ int unbind_i (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set);
+
+ /// Performs unbind. Must be called with locks held.
+ int unbind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Performs unbind. Must be called with locks held.
+ int unbind_i (const EXT_ID &ext_id);
+
+ /// Performs unbind. Must be called with locks held.
+ int unbind_i (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *entry);
+
+ /**
+ * Resize the map. Must be called with locks held.
+ * @note This method should never be called more than once or else all the
+ * hashing will get screwed up as the size will change.
+ */
+ int create_buckets (size_t size);
+
+ /// Close down a Map_Manager. Must be called with
+ /// locks held.
+ int close_i (void);
+
+ /// Removes all the entries in Map_Manager. Must be called with
+ /// locks held.
+ int unbind_all_i (void);
+
+ /// Pointer to a memory allocator used for table_, so it should
+ /// supply size*sizeof (@c ACE_Hash_Multi_Map_Entry<@c EXT_ID, @c INT_ID>),
+ ACE_Allocator *table_allocator_;
+
+ /// Addidtional allocator for entries, so it should be able to
+ /// allocate 'size' / chunks of sizeof
+ /// (@c ACE_Hash_Multi_Map_Entry<@c EXT_ID, @c INT_ID>) bytes each.
+ ACE_Allocator *entry_allocator_;
+
+ /// Synchronization variable for the MT_SAFE
+ /// @c ACE_Hash_Multi_Map_Manager.
+ ACE_LOCK lock_;
+
+ /// Function object used for hashing keys.
+ HASH_KEY hash_key_;
+
+ /// Function object used for comparing keys.
+ COMPARE_KEYS compare_keys_;
+
+protected:
+ /// Returns the @c ACE_Hash_Multi_Map_Entry object that corresponds to
+ /// @a ext_id.
+ int shared_find (const EXT_ID &ext_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry,
+ size_t &loc);
+
+ /// Accessor of the underlying table
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *table (void);
+
+ /// Accessor of the current size attribute
+ size_t cur_size (void) const;
+
+private:
+ /**
+ * Array of the pointers to @c ACE_Hash_Multi_Map_Entry objects, each of
+ * which points to an @c ACE_Hash_Multi_Map_Entry that serves as the
+ * beginning of a linked list of @c EXT_ID that hash to that bucket.
+ */
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *table_;
+
+ /// Total size of the hash table.
+ size_t total_size_;
+
+ /// Current number of entries in the table
+ /// @note That this can be larger than total_size_ due to the
+ /// bucket chaining).
+ size_t cur_size_;
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Hash_Multi_Map_Manager (const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &))
+};
+
+/**
+ * @class ACE_Hash_Multi_Map_Iterator_Base
+ *
+ * @brief Base iterator for the @c ACE_Hash_Multi_Map_Manager
+ *
+ * This class factors out common code from its templatized
+ * subclasses.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Iterator_Base
+{
+public:
+ // = Initialization method.
+ /// Contructor. If @a head != 0, the iterator constructed is positioned
+ /// at the head of the map, it is positioned at the end otherwise.
+ ACE_Hash_Multi_Map_Iterator_Base (ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head);
+
+ // = ITERATION methods.
+
+ /// Pass back the @a next_entry that hasn't been seen in the Set.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&next_entry) const;
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Returns a reference to the interal element this object is pointing to.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>& operator* (void) const;
+
+ /// Returns a pointer to the interal element this object is pointing to.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>* operator-> (void) const;
+
+ /// Returns reference the @c Hash_Multi_Map_Manager that is being iterated
+ /// over.
+ ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>& map (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+ bool operator!= (const ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Move forward by one element in the set. Returns 0 when there's
+ /// no more item in the set after the current items, else 1.
+ int forward_i (void);
+
+ /// Move backward by one element in the set. Returns 0 when there's
+ /// no more item in the set before the current item, else 1.
+ int reverse_i (void);
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ /// Map we are iterating over.
+ ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *map_man_;
+
+ /// Keeps track of how far we've advanced in the table.
+ ssize_t index_;
+
+ /// Keeps track of how far we've advanced in a linked list in each
+ /// table slot.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *next_;
+};
+
+/**
+ * @class ACE_Hash_Multi_Map_Const_Iterator_Base
+ *
+ * @brief Base const iterator for the @c ACE_Hash_Multi_Map_Manager
+ *
+ * This class factors out common code from its templatized
+ * subclasses.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Const_Iterator_Base
+{
+public:
+ // = Initialization method.
+ /// Contructor. If @a head != 0, the iterator constructed is positioned
+ /// at the head of the map, it is positioned at the end otherwise.
+ ACE_Hash_Multi_Map_Const_Iterator_Base (const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head);
+
+ // = ITERATION methods.
+
+ /// Pass back the @a next_entry that hasn't been seen in the Set.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&next_entry) const;
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Returns a reference to the interal element this object is pointing to.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>& operator* (void) const;
+
+ /// Returns a pointer to the interal element this object is pointing to.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>* operator-> (void) const;
+
+ /// Returns reference the @c Hash_Multi_Map_Manager that is being iterated
+ /// over.
+ const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>& map (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+ bool operator!= (const ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Move forward by one element in the set. Returns 0 when there's
+ /// no more item in the set after the current items, else 1.
+ int forward_i (void);
+
+ /// Move backward by one element in the set. Returns 0 when there's
+ /// no more item in the set before the current item, else 1.
+ int reverse_i (void);
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ /// Map we are iterating over.
+ const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *map_man_;
+
+ /// Keeps track of how far we've advanced in the table.
+ ssize_t index_;
+
+ /// Keeps track of how far we've advanced in a linked list in each
+ /// table slot.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *next_;
+};
+
+/**
+ * @class ACE_Hash_Multi_Map_Iterator
+ *
+ * @brief Forward iterator for the @c ACE_Hash_Multi_Map_Manager.
+ *
+ * This class does not perform any internal locking of the
+ * @c ACE_Hash_Multi_Map_Manager it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * @c ACE_Guard or @c ACE_Read_Guard on the @c ACE_Hash_Multi_Map_Manager's
+ * internal lock, which is accessible via its @c mutex method.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Iterator : public ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+{
+public:
+ // = Initialization method.
+ ACE_Hash_Multi_Map_Iterator (ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int tail = 0);
+
+ // = Iteration methods.
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance.
+ ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Hash_Multi_Map_Const_Iterator
+ *
+ * @brief Const forward iterator for the @c ACE_Hash_Multi_Map_Manager.
+ *
+ * This class does not perform any internal locking of the
+ * @c ACE_Hash_Multi_Map_Manager it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * @c ACE_Guard or @c ACE_Read_Guard on the @c ACE_Hash_Multi_Map_Manager's
+ * internal lock, which is accessible via its @c mutex method.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Const_Iterator : public ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+{
+public:
+ // = Initialization method.
+ ACE_Hash_Multi_Map_Const_Iterator (const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int tail = 0);
+
+ // = Iteration methods.
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance.
+ ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Hash_Multi_Map_Bucket_Iterator
+ *
+ * @brief Forward iterator for the @c ACE_Hash_Multi_Map_Manager which
+ * only traverses a particular bucket. The particular bucket is
+ * specified by the @c EXT_ID parameter specified in the constructor.
+ *
+ * This class does not perform any internal locking of the
+ * @c ACE_Hash_Multi_Map_Manager it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * @c ACE_Guard or @c ACE_Read_Guard on the @c ACE_Hash_Multi_Map_Manager's
+ * internal lock, which is accessible via its @c mutex method.
+ *
+ * Note that a creation method for this new iterator cannot be added
+ * to the hash map, since this would require adding explicit template
+ * instantiations for bucket iterators on platforms with broken
+ * templates.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Bucket_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Hash_Multi_Map_Bucket_Iterator (ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ const EXT_ID &ext_id,
+ int tail = 0);
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance.
+ ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Returns a reference to the interal element this object is pointing to.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>& operator* (void) const;
+
+ /// Returns a pointer to the interal element this object is pointing to.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID>* operator-> (void) const;
+
+ /// Returns reference the Hash_Multi_Map_Manager that is being iterated
+ /// over.
+ ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>& map (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+ bool operator!= (const ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &) const;
+
+protected:
+ /// Move forward by one element in the set. Returns 0 when there's
+ /// no more item in the set after the current items, else 1.
+ int forward_i (void);
+
+ /// Move backward by one element in the set. Returns 0 when there's
+ /// no more item in the set before the current item, else 1.
+ int reverse_i (void);
+
+ /// Map we are iterating over.
+ ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *map_man_;
+
+ /// Keeps track of how far we've advanced in the table.
+ ssize_t index_;
+
+ /// Keeps track of how far we've advanced in a linked list in each
+ /// table slot.
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *next_;
+};
+
+/**
+ * @class ACE_Hash_Multi_Map_Reverse_Iterator
+ *
+ * @brief Reverse iterator for the @c ACE_Hash_Multi_Map_Manager.
+ *
+ * This class does not perform any internal locking of the
+ * @c ACE_Hash_Multi_Map_Manager it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * @c ACE_Guard or @c ACE_Read_Guard on the @c ACE_Hash_Multi_Map_Manager's
+ * internal lock, which is accessible via its @c mutex method.
+ */
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_Hash_Multi_Map_Reverse_Iterator : public ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+{
+public:
+ // = Initialization method.
+ ACE_Hash_Multi_Map_Reverse_Iterator (ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head = 0);
+
+ // = Iteration methods.
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix reverse.
+ ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator++ (void);
+
+ /// Postfix reverse.
+ ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix advance.
+ ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &operator-- (void);
+
+ /// Postfix advance.
+ ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Hash_Multi_Map_Manager_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Hash_Multi_Map_Manager_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Hash_Multi_Map_Manager_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HASH_MULTI_MAP_MANAGER_T_H */
diff --git a/ACE/ace/Hash_Multi_Map_Manager_T.inl b/ACE/ace/Hash_Multi_Map_Manager_T.inl
new file mode 100644
index 00000000000..f0cbcabe599
--- /dev/null
+++ b/ACE/ace/Hash_Multi_Map_Manager_T.inl
@@ -0,0 +1,994 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Guard_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Manager (size_t size,
+ ACE_Allocator *table_alloc,
+ ACE_Allocator *entry_alloc)
+ : table_allocator_ (table_alloc),
+ entry_allocator_ (entry_alloc),
+ table_ (0),
+ total_size_ (0),
+ cur_size_ (0)
+{
+ if (this->open (size, table_alloc, entry_alloc) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("ACE_Hash_Multi_Map_Manager\n")));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Manager (ACE_Allocator *table_alloc,
+ ACE_Allocator *entry_alloc)
+ : table_allocator_ (table_alloc),
+ entry_allocator_ (entry_alloc),
+ table_ (0),
+ total_size_ (0),
+ cur_size_ (0)
+{
+ if (this->open (ACE_DEFAULT_MAP_SIZE, table_alloc, entry_alloc) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("ACE_Hash_Multi_Map_Manager\n")));
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::close (void)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->close_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_all (void)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_all_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::~ACE_Hash_Multi_Map_Manager (void)
+{
+ this->close ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE size_t
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::current_size (void) const
+{
+ return this->cur_size_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE size_t
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::total_size (void) const
+{
+ return this->total_size_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE ACE_LOCK &
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::mutex (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Manager::mutex");
+ return this->lock_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE u_long
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::hash (const EXT_ID &ext_id)
+{
+ return this->hash_key_ (ext_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::equal (const EXT_ID &id1,
+ const EXT_ID &id2)
+{
+ return this->compare_keys_ (id1, id2);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *temp;
+
+ return this->bind_i (ext_id, int_id, temp);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *temp;
+
+ return this->bind_i (ext_id, int_id_set, temp);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->bind_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->bind_i (ext_id, int_id, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->bind_i (ext_id, int_id_set);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->bind_i (ext_id, int_id_set, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::trybind_i (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *temp;
+
+ int result = this->trybind_i (ext_id, int_id_set, temp);
+ if (result == 1)
+ int_id_set = temp->int_id_set_;
+ return result;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::trybind (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->trybind_i (ext_id, int_id_set);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::trybind (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->trybind_i (ext_id, int_id_set, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind_i (const EXT_ID &ext_id)
+{
+ ACE_Unbounded_Set<INT_ID> int_id_set;
+
+ return this->unbind_i (ext_id, int_id_set);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_i (ext_id, int_id_set);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind (const EXT_ID &ext_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_i (ext_id) == -1 ? -1 : 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::unbind (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_i (entry) == -1 ? -1 : 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *entry;
+
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return -1;
+ else
+ {
+ int_id_set = entry->int_id_set_;
+ return 0;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *entry;
+
+ size_t dummy;
+ if (this->shared_find (ext_id, entry, dummy) == -1)
+ return -1;
+ else
+ {
+ if (0 == entry->int_id_set_.find (int_id))
+ return 0;
+ else
+ return -1;
+ }
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &ext_id)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *entry;
+
+ size_t dummy;
+ return this->shared_find (ext_id, entry, dummy);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id,
+ ACE_Unbounded_Set<INT_ID> &int_id_set) const
+{
+ ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *nc_this =
+ const_cast <ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *>
+ (this);
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, nc_this->lock_, -1);
+
+ return nc_this->find_i (ext_id, int_id_set);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id,
+ const INT_ID &int_id) const
+{
+ ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *nc_this =
+ const_cast <ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *>
+ (this);
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, nc_this->lock_, -1);
+
+ return nc_this->find_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id) const
+{
+ ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *nc_this =
+ const_cast <ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *>
+ (this);
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, nc_this->lock_, -1);
+
+ return nc_this->find_i (ext_id);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &ext_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ size_t dummy;
+ return this->shared_find (ext_id, entry, dummy);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry) const
+{
+ ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *nc_this =
+ const_cast <ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> *>
+ (this);
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, nc_this->lock_, -1);
+
+ return nc_this->find_i (ext_id, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *node;
+
+ return this->rebind_i (ext_id,
+ int_id_set,
+ node);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *node;
+
+ return this->rebind_i (ext_id,
+ int_id_set,
+ old_int_id_set,
+ node);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ EXT_ID &old_ext_id,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set)
+{
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *node;
+
+ return this->rebind_i (ext_id,
+ int_id_set,
+ old_ext_id,
+ old_int_id_set,
+ node);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id_set);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id_set, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id_set, old_int_id_set);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id_set, old_int_id_set, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ EXT_ID &old_ext_id,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id_set, old_ext_id, old_int_id_set);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const ACE_Unbounded_Set<INT_ID> &int_id_set,
+ EXT_ID &old_ext_id,
+ ACE_Unbounded_Set<INT_ID> &old_int_id_set,
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id, int_id_set, old_ext_id, old_int_id_set, entry);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::begin (void)
+{
+ return ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (*this);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::end (void)
+{
+ return ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (*this, 1);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rbegin (void)
+{
+ return ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (*this);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::rend (void)
+{
+ return ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (*this, 1);
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::table (void)
+{
+ return this->table_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+size_t
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::cur_size (void) const
+{
+ return this->cur_size_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Iterator_Base (ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head)
+ : map_man_ (&mm),
+ index_ (head != 0 ? -1 : (ssize_t) mm.total_size_),
+ next_ (0)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Iterator_Base");
+
+ if (mm.table_ != 0)
+ this->next_ = &mm.table_[head != 0 ? 0 : mm.total_size_ - 1];
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::next (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::next");
+
+ if (this->map_man_->table_ != 0
+ && this->index_ < static_cast<ssize_t> (this->map_man_->total_size_)
+ && this->index_ >= 0
+ && this->next_ != &this->map_man_->table_[this->index_])
+ {
+ entry = this->next_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::done (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::done");
+
+ return this->map_man_->table_ == 0
+ || this->index_ >= static_cast<ssize_t> (this->map_man_->total_size_)
+ || this->index_ < 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> &
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator* (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator*");
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+
+ ACE_UNUSED_ARG (result);
+ ACE_ASSERT (result != 0);
+
+ return *retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-> (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator->");
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+
+ ACE_UNUSED_ARG (result);
+ ACE_ASSERT (result != 0);
+
+ return retv;
+}
+
+// Returns the reference to the Hash_Multi_Map_manager_ex that is being
+// iterated over.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>&
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map");
+ return *this->map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator== (const ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator==");
+ return this->map_man_ == rhs.map_man_
+ && this->index_ == rhs.index_
+ && this->next_ == rhs.next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!= (const ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!=");
+ return this->next_ != rhs.next_
+ || this->index_ != rhs.index_
+ || this->map_man_ != rhs.map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Const_Iterator_Base (const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int head)
+ : map_man_ (&mm),
+ index_ (head != 0 ? -1 : (ssize_t) mm.total_size_),
+ next_ (0)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Const_Iterator_Base");
+
+ if (mm.table_ != 0)
+ this->next_ = &mm.table_[head != 0 ? 0 : mm.total_size_ - 1];
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::next (ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *&entry) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::next");
+
+ if (this->map_man_->table_ != 0
+ && this->index_ < (ssize_t) this->map_man_->total_size_
+ && this->index_ >= 0
+ && this->next_ != &this->map_man_->table_[this->index_])
+ {
+ entry = this->next_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::done (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::done");
+
+ return this->map_man_->table_ == 0
+ || this->index_ >= (ssize_t) this->map_man_->total_size_
+ || this->index_ < 0;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> &
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator* (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator*");
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+
+ ACE_UNUSED_ARG (result);
+ ACE_ASSERT (result != 0);
+
+ return *retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-> (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator->");
+ ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+
+ ACE_UNUSED_ARG (result);
+ ACE_ASSERT (result != 0);
+
+ return retv;
+}
+
+// Returns the reference to the Hash_Multi_Map_manager_ex that is being
+// iterated over.
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>&
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map");
+ return *this->map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator== (const ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator==");
+ return this->map_man_ == rhs.map_man_
+ && this->index_ == rhs.index_
+ && this->next_ == rhs.next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!= (const ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!=");
+ return this->next_ != rhs.next_
+ || this->index_ != rhs.index_
+ || this->map_man_ != rhs.map_man_;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Multi_Map_Iterator)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE void
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Iterator (ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int tail)
+ : ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (mm,
+ tail == 0 ? 1 : 0)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Iterator");
+ if (tail == 0)
+ this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance");
+ return this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Multi_Map_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Multi_Map_Const_Iterator)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE void
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Const_Iterator (const ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ int tail)
+ : ACE_Hash_Multi_Map_Const_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (mm,
+ tail == 0 ? 1 : 0)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Const_Iterator");
+ if (tail == 0)
+ this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance");
+ return this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Multi_Map_Const_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Bucket_Iterator (ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm,
+ const EXT_ID &ext_id,
+ int tail)
+ : map_man_ (&mm)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Bucket_Iterator");
+
+ this->index_ = this->map_man_->hash (ext_id) % this->map_man_->total_size_;
+ this->next_ = &this->map_man_->table_[this->index_];
+
+ if (tail == 0)
+ this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i");
+
+ this->next_ = this->next_->next_;
+ return this->next_ != &this->map_man_->table_[this->index_];
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i");
+
+ this->next_ = this->next_->prev_;
+ return this->next_ != &this->map_man_->table_[this->index_];
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> &
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator* (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator*");
+
+ return *this->next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Entry<EXT_ID, INT_ID> *
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-> (void) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator->");
+
+ return this->next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::map");
+ return *this->map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator== (const ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator==");
+ return this->map_man_ == rhs.map_man_
+ && this->index_ == rhs.index_
+ && this->next_ == rhs.next_;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE bool
+ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!= (const ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &rhs) const
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Bucket_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator!=");
+ return this->next_ != rhs.next_
+ || this->index_ != rhs.index_
+ || this->map_man_ != rhs.map_man_;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Multi_Map_Reverse_Iterator)
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE void
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Reverse_Iterator (ACE_Hash_Multi_Map_Manager<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &mm, int head)
+ : ACE_Hash_Multi_Map_Iterator_Base<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> (mm, head)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::ACE_Hash_Multi_Map_Reverse_Iterator");
+ if (head == 0)
+ this->reverse_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE int
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::advance");
+ return this->reverse_i ();
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> &
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class HASH_KEY, class COMPARE_KEYS, class ACE_LOCK> ACE_INLINE
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>
+ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_Hash_Multi_Map_Reverse_Iterator<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Hashable.cpp b/ACE/ace/Hashable.cpp
new file mode 100644
index 00000000000..cab51f7aa26
--- /dev/null
+++ b/ACE/ace/Hashable.cpp
@@ -0,0 +1,36 @@
+//$Id$
+
+#include "ace/Hashable.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Hashable.inl"
+#endif /* __ACE_INLINE __ */
+
+
+ACE_RCSID (ace,
+ Hashable,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Hashable::~ACE_Hashable (void)
+{
+}
+
+unsigned long
+ACE_Hashable::hash (void) const
+{
+ // In doing the check below, we take chance of paying a performance
+ // price when the hash value is zero. But, that will (hopefully)
+ // happen far less often than a non-zero value, so this caching
+ // strategy should pay off, esp. if hash computation is expensive
+ // relative to the simple comparison.
+
+ if (this->hash_value_ == 0)
+ this->hash_value_ = this->hash_i ();
+
+ return this->hash_value_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Hashable.h b/ACE/ace/Hashable.h
new file mode 100644
index 00000000000..d20bb2da1aa
--- /dev/null
+++ b/ACE/ace/Hashable.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Hashable.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+#ifndef ACE_HASHABLE_H
+#define ACE_HASHABLE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Hashable
+ *
+ * @brief ACE_Hashable
+ */
+class ACE_Export ACE_Hashable
+{
+public:
+
+ /// Destructor.
+ virtual ~ACE_Hashable (void);
+
+ /// Computes and returns hash value. This "caches" the hash value to
+ /// improve performance.
+ virtual unsigned long hash (void) const;
+
+protected:
+ /// Protected constructor.
+ ACE_Hashable (void);
+
+ /// This is the method that actually performs the non-cached hash
+ /// computation.
+ virtual unsigned long hash_i (void) const = 0;
+
+protected:
+
+ /// Pre-computed hash-value.
+ mutable unsigned long hash_value_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Hashable.inl"
+#endif /* __ACE_INLINE __ */
+
+#include /**/ "ace/post.h"
+
+#endif /*ACE_HASHABLE_H*/
diff --git a/ACE/ace/Hashable.inl b/ACE/ace/Hashable.inl
new file mode 100644
index 00000000000..7ec54ea1337
--- /dev/null
+++ b/ACE/ace/Hashable.inl
@@ -0,0 +1,14 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Hashable::ACE_Hashable (void)
+ : hash_value_ (0)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/High_Res_Timer.cpp b/ACE/ace/High_Res_Timer.cpp
new file mode 100644
index 00000000000..f71b7ebc7d7
--- /dev/null
+++ b/ACE/ace/High_Res_Timer.cpp
@@ -0,0 +1,537 @@
+// $Id$
+
+// Be very carefull before changing the calculations inside
+// ACE_High_Res_Timer. The precision matters and we are using integer
+// calculations not floating point. Also look good at the emulated 64
+// bit int class (inside Basic_Types{h,i,cpp} before changing
+// anything. It's operator/ only returns 32 bits not 64 bits, among
+// other things.
+
+#include "ace/High_Res_Timer.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/High_Res_Timer.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Stats.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/Truncate.h"
+
+ACE_RCSID(ace, High_Res_Timer, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_High_Res_Timer)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// For Intel platforms, a scale factor is required for
+// ACE_OS::gethrtime. We'll still set this to one to prevent division
+// by zero errors.
+#if (defined (ACE_WIN32) || defined (ACE_HAS_POWERPC_TIMER) || \
+ defined (ACE_HAS_PENTIUM) || defined (ACE_HAS_ALPHA_TIMER)) && \
+ !defined (ACE_HAS_HI_RES_TIMER)
+
+# include "ace/Guard_T.h"
+# include "ace/Recursive_Thread_Mutex.h"
+# include "ace/Object_Manager.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ // Initialize the global_scale_factor_ to 1. The first
+ // ACE_High_Res_Timer instance construction will override this
+ // value.
+ /* static */
+ ACE_UINT32 ACE_High_Res_Timer::global_scale_factor_ = 1u;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#else /* ! (ACE_WIN32 || ACE_HAS_POWERPC_TIMER || \
+ ACE_HAS_PENTIUM || ACE_HAS_ALPHA_TIMER) ||
+ ACE_HAS_HI_RES_TIMER */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ // A scale_factor of 1000 converts nanosecond ticks to microseconds.
+ // That is, on these platforms, 1 tick == 1 nanosecond.
+ /* static */
+ ACE_UINT32 ACE_High_Res_Timer::global_scale_factor_ = 1000u;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ! (ACE_WIN32 || ACE_HAS_POWERPC_TIMER || \
+ ACE_HAS_PENTIUM || ACE_HAS_ALPHA_TIMER) ||
+ ACE_HAS_HI_RES_TIMER */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This is used to tell if the global_scale_factor_ has been
+// set, and if high resolution timers are supported.
+/* static */
+int ACE_High_Res_Timer::global_scale_factor_status_ = 0;
+
+
+#if defined (linux)
+// Determine the apparent CPU clock speed from /proc/cpuinfo
+ACE_UINT32
+ACE_High_Res_Timer::get_cpuinfo (void)
+{
+ ACE_UINT32 scale_factor = 1u;
+
+ // Get the BogoMIPS from /proc/cpuinfo. It works fine on Alpha and
+ // Pentium Pro. For other CPUs, it will be necessary to interpret
+ // the BogoMips, as described in the BogoMips mini-HOWTO. Note that
+ // this code assumes an order to the /proc/cpuinfo contents. The
+ // BogoMips rating had better come after CPU type and model info.
+#if !defined (__alpha__)
+ int supported = 0;
+#endif /* __alpha__ */
+
+ FILE *cpuinfo = ACE_OS::fopen (ACE_TEXT ("/proc/cpuinfo"),
+ ACE_TEXT ("r"));
+
+ if (cpuinfo != 0)
+ {
+ char buf[128];
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nReading /proc/cpuinfo...")));
+
+ while (ACE_OS::fgets (buf, sizeof buf, cpuinfo))
+ {
+#if defined (__alpha__)
+ ACE_UINT32 whole;
+ ACE_UINT32 fractional;
+ if (::sscanf (buf,
+ "BogoMIPS : %d.%d\n",
+ &whole,
+ &fractional) == 2
+ || ::sscanf (buf,
+ "bogomips : %d.%d\n",
+ &whole,
+ &fractional) == 2)
+ {
+ scale_factor = whole;
+ break;
+ }
+#else
+ double mhertz = 1;
+ double bmips = 1;
+ char arg[128];
+
+ // CPU type?
+ if (::sscanf (buf, "cpu : %s\n", arg) == 1)
+ {
+ // If this is an Alpha chip, then the BogoMips rating is
+ // usable...
+ if (ACE_OS::strncmp (arg,
+ "Alpha",
+ 5) == 0)
+ {
+ supported = 1;
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" recognized Alpha chip...")));
+ }
+ }
+ // Pentium CPU model?
+ else if (supported == 0
+ && ::sscanf (buf, "model name : Pentium %s\n", arg) == 1)
+ {
+ // But if we don't have the right kind of Intel chip,
+ // just quit.
+ if (ACE_OS::strcmp (arg, "II") == 0
+ || ACE_OS::strcmp (arg, "III") == 0
+ || ACE_OS::strcmp (arg, "IV") == 0
+ || ACE_OS::strcmp (arg, "Pro") == 0)
+ {
+ supported = 1;
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" recognized Pentium Pro/II chip...")));
+ }
+ }
+ else if (::sscanf (buf, "cpu MHz : %lf\n", &mhertz) == 1)
+ {
+ // If the line "cpu MHz : xxx" is present, then it's a
+ // reliable measure of the CPU speed - according to the
+ // kernel-source.
+ scale_factor = (ACE_UINT32) (mhertz + 0.5);
+ break;
+ }
+ else if (::sscanf (buf, "bogomips : %lf\n", &bmips) == 1
+ || ::sscanf (buf, "BogoMIPS : %lf\n", &bmips) == 1)
+ {
+ if (supported)
+ {
+ scale_factor = (ACE_UINT32) (bmips + 0.5);
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" setting the clock scale factor to %u"), scale_factor));
+ }
+#if 0
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\nThe BogoMIPS metric is not supported on this platform"
+ "\n\tReport the results of the clock calibration and"
+ "\n\tthe contents of /proc/cpuinfo to the ace-users mailing list")));
+ }
+#endif /* 0 */
+ break;
+ }
+#endif /* __alpha__ */
+ }
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (done)\n")));
+
+ ACE_OS::fclose (cpuinfo);
+ }
+
+ return scale_factor;
+}
+#endif /* linux */
+
+ACE_UINT32
+ACE_High_Res_Timer::global_scale_factor (void)
+{
+#if (defined (ACE_WIN32) || defined (ACE_HAS_POWERPC_TIMER) || \
+ defined (ACE_HAS_PENTIUM) || defined (ACE_HAS_ALPHA_TIMER)) && \
+ !defined (ACE_HAS_HI_RES_TIMER) && \
+ ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || \
+ defined (ghs) || defined (__GNUG__) || \
+ defined (__INTEL_COMPILER))
+ // Check if the global scale factor needs to be set, and do if so.
+ if (ACE_High_Res_Timer::global_scale_factor_status_ == 0)
+ {
+ // Grab ACE's static object lock. This doesn't have anything to
+ // do with static objects; it's just a convenient lock to use.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ // Double check
+ if (ACE_High_Res_Timer::global_scale_factor_status_ == 0)
+ {
+# if defined (ACE_WIN32)
+ LARGE_INTEGER freq;
+ if (::QueryPerformanceFrequency (&freq))
+ {
+ // We have a high-res timer
+# if defined (ACE_LACKS_LONGLONG_T)
+ ACE_UINT64 uint64_freq(freq.u.LowPart, (ACE_UINT32) freq.u.HighPart);
+ ACE_High_Res_Timer::global_scale_factor
+ (uint64_freq / (ACE_UINT32) ACE_ONE_SECOND_IN_USECS);
+# else
+ ACE_High_Res_Timer::global_scale_factor
+ (static_cast<unsigned int> (freq.QuadPart / ACE_HR_SCALE_CONVERSION));
+# endif // (ACE_LACKS_LONGLONG_T)
+
+ ACE_High_Res_Timer::global_scale_factor_status_ = 1;
+ }
+ else
+ // High-Res timers not supported
+ ACE_High_Res_Timer::global_scale_factor_status_ = -1;
+
+ return ACE_High_Res_Timer::global_scale_factor_;
+
+# elif defined (linux)
+ ACE_High_Res_Timer::global_scale_factor (ACE_High_Res_Timer::get_cpuinfo ());
+# endif /* ! ACE_WIN32 && ! (linux && __alpha__) */
+
+# if !defined (ACE_WIN32)
+ if (ACE_High_Res_Timer::global_scale_factor_ == 1u)
+ // Failed to retrieve CPU speed from system, so calculate it.
+ ACE_High_Res_Timer::calibrate ();
+# endif // (ACE_WIN32)
+ }
+ }
+
+ ACE_High_Res_Timer::global_scale_factor_status_ = 1;
+#endif /* (ACE_WIN32 || ACE_HAS_POWERPC_TIMER || \
+ ACE_HAS_PENTIUM || ACE_HAS_ALPHA_TIMER) && \
+ ! ACE_HAS_HI_RES_TIMER &&
+ ((WIN32 && ! WINCE) || ghs || __GNUG__) */
+
+ return ACE_High_Res_Timer::global_scale_factor_;
+}
+
+ACE_High_Res_Timer::ACE_High_Res_Timer (void)
+{
+ ACE_TRACE ("ACE_High_Res_Timer::ACE_High_Res_Timer");
+
+ this->reset ();
+
+ // Make sure that the global scale factor is set.
+ (void) global_scale_factor ();
+}
+
+ACE_UINT32
+ACE_High_Res_Timer::calibrate (const ACE_UINT32 usec,
+ const u_int iterations)
+{
+ const ACE_Time_Value sleep_time (0, usec);
+ ACE_Stats delta_hrtime;
+ // In units of 100 usec, to avoid overflow.
+ ACE_Stats actual_sleeps;
+
+ for (u_int i = 0;
+ i < iterations;
+ ++i)
+ {
+ const ACE_Time_Value actual_start =
+ ACE_OS::gettimeofday ();
+ const ACE_hrtime_t start =
+ ACE_OS::gethrtime ();
+ ACE_OS::sleep (sleep_time);
+ const ACE_hrtime_t stop =
+ ACE_OS::gethrtime ();
+ const ACE_Time_Value actual_delta =
+ ACE_OS::gettimeofday () - actual_start;
+
+ // Store the sample.
+ delta_hrtime.sample (ACE_Utils::truncate_cast<ACE_INT32> (stop - start));
+ actual_sleeps.sample (actual_delta.msec () * 100u);
+ }
+
+ // Calculate the mean value of the samples, with no fractional
+ // precision. Use it for the global scale factor.
+ ACE_Stats_Value ticks (0);
+ delta_hrtime.mean (ticks);
+
+ ACE_Stats_Value actual_sleep (0);
+ actual_sleeps.mean (actual_sleep);
+
+ // The addition of 5 below rounds instead of truncates.
+ const ACE_UINT32 scale_factor =
+ (ticks.whole () / actual_sleep.whole () + 5) /
+ 10u /* usec/100 usec */;
+ ACE_High_Res_Timer::global_scale_factor (scale_factor);
+
+ return scale_factor;
+}
+
+void
+ACE_High_Res_Timer::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_High_Res_Timer::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nglobal_scale_factor_: %u\n"),
+ global_scale_factor ()));
+#if defined (ACE_LACKS_LONGLONG_T)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT (":\nstart_.hi (): %8x; start_.lo (): %8x;\n")
+ ACE_TEXT ("end_.hi (): %8x; end_.lo (): %8x;\n")
+ ACE_TEXT ("total_.hi (): %8x; total_.lo (): %8x;\n")
+ ACE_TEXT ("start_incr_.hi () %8x; start_incr_.lo (): %8x;\n"),
+ start_.hi (), start_.lo (),
+ end_.hi (), end_.lo (),
+ total_.hi (), total_.lo (),
+ start_incr_.hi (), start_incr_.lo ()));
+#else /* ! ACE_LACKS_LONGLONG_T */
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT (":\nstart_.hi (): %8x; start_.lo (): %8x;\n")
+ ACE_TEXT ("end_.hi (): %8x; end_.lo (): %8x;\n")
+ ACE_TEXT ("total_.hi (): %8x; total_.lo (): %8x;\n")
+ ACE_TEXT ("start_incr_.hi () %8x; start_incr_.lo (): %8x;\n"),
+ static_cast<ACE_UINT32> (start_ >> 32),
+ static_cast<ACE_UINT32> (start_ & 0xfffffffful),
+ static_cast<ACE_UINT32> (end_ >> 32),
+ static_cast<ACE_UINT32> (end_ & 0xfffffffful),
+ static_cast<ACE_UINT32> (total_ >> 32),
+ static_cast<ACE_UINT32> (total_ & 0xfffffffful),
+ static_cast<ACE_UINT32> (start_incr_ >> 32),
+ static_cast<ACE_UINT32> (start_incr_ & 0xfffffffful)));
+#endif /* ! ACE_LACKS_LONGLONG_T */
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_High_Res_Timer::reset (void)
+{
+ ACE_TRACE ("ACE_High_Res_Timer::reset");
+
+ this->start_ = 0;
+ this->end_ = 0;
+ this->total_ = 0;
+ this->start_incr_ = 0;
+}
+
+void
+ACE_High_Res_Timer::elapsed_time (ACE_Time_Value &tv) const
+{
+ hrtime_to_tv (tv,
+ ACE_High_Res_Timer::elapsed_hrtime (this->end_, this->start_));
+}
+
+#if defined (ACE_HAS_POSIX_TIME)
+// Note... Win32 does not have ACE_HAS_POSIX_TIME, so the scale factor
+// does not need to take into account the different units on Win32.
+
+void
+ACE_High_Res_Timer::elapsed_time (struct timespec &elapsed_time) const
+{
+ // This implementation should be cleaned up.
+
+ // Just grab the nanoseconds. That is, leave off all values above
+ // microsecond. This equation is right! Don't mess with me! (It
+ // first strips off everything but the portion less than 1 usec.
+ // Then it converts that to nanoseconds by dividing by the scale
+ // factor to convert to usec, and multiplying by 1000.) The cast
+ // avoids a MSVC 4.1 compiler warning about narrowing.
+ ACE_hrtime_t elapsed =
+ ACE_High_Res_Timer::elapsed_hrtime (this->end_, this->start_);
+ u_long nseconds = static_cast<u_long> (elapsed %
+ global_scale_factor () * 1000u /
+ global_scale_factor ());
+
+ // Get just the microseconds (dropping any left over nanoseconds).
+ ACE_UINT32 useconds = (ACE_UINT32) (elapsed / global_scale_factor ());
+
+ elapsed_time.tv_sec = (time_t) (useconds / ACE_ONE_SECOND_IN_USECS);
+ // Transforms one second in microseconds into nanoseconds.
+ elapsed_time.tv_nsec = (time_t) ((useconds % ACE_ONE_SECOND_IN_USECS) * 1000u + nseconds);
+}
+#endif /* ACE_HAS_POSIX_TIME */
+
+void
+ACE_High_Res_Timer::elapsed_time_incr (ACE_Time_Value &tv) const
+{
+ hrtime_to_tv (tv, total_);
+}
+
+void
+ACE_High_Res_Timer::elapsed_time (ACE_hrtime_t &nanoseconds) const
+{
+ // Please do _not_ rearrange this equation. It is carefully
+ // designed and tested to avoid overflow on machines that don't have
+ // native 64-bit ints. In particular, division can be a problem.
+ // For more background on this, please see bugzilla #1024.
+ nanoseconds = ACE_High_Res_Timer::elapsed_hrtime (this->end_, this->start_)
+ * (1024000u / ACE_High_Res_Timer::global_scale_factor ());
+ // Caution - Borland has a problem with >>=, so resist the temptation.
+ nanoseconds = nanoseconds >> 10;
+ // Right shift is implemented for non native 64-bit ints
+ // operator/ only for a 32 bit result !
+}
+
+void
+ACE_High_Res_Timer::elapsed_time_incr (ACE_hrtime_t &nanoseconds) const
+{
+ // Same as above.
+ nanoseconds = this->total_
+ * (1024000u / ACE_High_Res_Timer::global_scale_factor ());
+ // Caution - Borland has a problem with >>=, so resist the temptation.
+ nanoseconds = nanoseconds >> 10;
+}
+
+#if !defined (ACE_HAS_WINCE)
+void
+ACE_High_Res_Timer::print_ave (const ACE_TCHAR *str,
+ const int count,
+ ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_High_Res_Timer::print_ave");
+
+ // Get the total number of nanoseconds elapsed.
+ ACE_hrtime_t total_nanoseconds;
+ this->elapsed_time (total_nanoseconds);
+
+ // Separate to seconds and nanoseconds.
+ u_long total_secs =
+ static_cast<u_long> (total_nanoseconds / (ACE_UINT32) ACE_ONE_SECOND_IN_NSECS);
+ ACE_UINT32 extra_nsecs =
+ static_cast<ACE_UINT32> (total_nanoseconds % (ACE_UINT32) ACE_ONE_SECOND_IN_NSECS);
+
+ ACE_TCHAR buf[100];
+ if (count > 1)
+ {
+ ACE_hrtime_t avg_nsecs = total_nanoseconds / (ACE_UINT32) count;
+ ACE_OS::sprintf (buf,
+ ACE_TEXT (" count = %d, total (secs %lu, usecs %u), avg usecs = %lu\n"),
+ count,
+ total_secs,
+ (extra_nsecs + 500u) / 1000u,
+ (u_long) ((avg_nsecs + 500u) / 1000u));
+ }
+ else
+ ACE_OS::sprintf (buf,
+ ACE_TEXT (" total %3lu.%06lu secs\n"),
+ total_secs,
+ (extra_nsecs + 500lu) / 1000lu);
+
+ ACE_OS::write (handle,
+ str,
+ ACE_OS::strlen (str));
+ ACE_OS::write (handle,
+ buf,
+ ACE_OS::strlen (buf));
+}
+
+void
+ACE_High_Res_Timer::print_total (const ACE_TCHAR *str,
+ const int count,
+ ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_High_Res_Timer::print_total");
+
+ // Get the total number of nanoseconds elapsed.
+ ACE_hrtime_t total_nanoseconds;
+ this->elapsed_time (total_nanoseconds);
+
+ // Separate to seconds and nanoseconds.
+ u_long total_secs =
+ (u_long) (total_nanoseconds / (ACE_UINT32) ACE_ONE_SECOND_IN_NSECS);
+ ACE_UINT32 extra_nsecs =
+ (ACE_UINT32) (total_nanoseconds % (ACE_UINT32) ACE_ONE_SECOND_IN_NSECS);
+
+ ACE_TCHAR buf[100];
+ if (count > 1)
+ {
+ ACE_hrtime_t avg_nsecs = this->total_ / (ACE_UINT32) count;
+
+ ACE_OS::sprintf (buf,
+ ACE_TEXT (" count = %d, total (secs %lu, usecs %u), avg usecs = %lu\n"),
+ count,
+ total_secs,
+ (extra_nsecs + 500u) / 1000u,
+ (u_long) ((avg_nsecs + 500u) / 1000u));
+ }
+ else
+ ACE_OS::sprintf (buf,
+ ACE_TEXT (" total %3lu.%06u secs\n"),
+ total_secs,
+ (extra_nsecs + 500u) / 1000u);
+
+ ACE_OS::write (handle,
+ str,
+ ACE_OS::strlen (str));
+ ACE_OS::write (handle,
+ buf,
+ ACE_OS::strlen (buf));
+}
+#endif /* !ACE_HAS_WINCE */
+
+int
+ACE_High_Res_Timer::get_env_global_scale_factor (const ACE_TCHAR *env)
+{
+#if !defined (ACE_HAS_WINCE)
+ if (env != 0)
+ {
+ const char *env_value = ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (env));
+ if (env_value != 0)
+ {
+ int const value = ACE_OS::atoi (env_value);
+ if (value > 0)
+ {
+ ACE_High_Res_Timer::global_scale_factor (value);
+ return 0;
+ }
+ }
+ }
+#else
+ ACE_UNUSED_ARG (env);
+#endif /* !ACE_HAS_WINCE */
+ return -1;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/High_Res_Timer.h b/ACE/ace/High_Res_Timer.h
new file mode 100644
index 00000000000..249d38078b9
--- /dev/null
+++ b/ACE/ace/High_Res_Timer.h
@@ -0,0 +1,315 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file High_Res_Timer.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_HIGH_RES_TIMER_H
+#define ACE_HIGH_RES_TIMER_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Basic_Types.h"
+#include "ace/OS_NS_time.h"
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_High_Res_Timer
+ *
+ * @brief A high resolution timer class wrapper that encapsulates
+ * OS-specific high-resolution timers, such as those found on
+ * Solaris, AIX, Win32/Pentium, and VxWorks.
+ *
+ * Most of the member functions don't return values. The only
+ * reason that one would fail is if high-resolution time isn't
+ * supported on the platform. To avoid impacting performance
+ * and complicating the interface, in that case,
+ * <ACE_OS::gettimeofday> is used instead.
+ * The global scale factor is required for platforms that have
+ * high-resolution timers that return units other than
+ * microseconds, such as clock ticks. It is represented as a
+ * static u_long, can only be accessed through static methods,
+ * and is used by all instances of High Res Timer. The member
+ * functions that return or print times use the global scale
+ * factor. They divide the "time" that they get from
+ * <ACE_OS::gethrtime> by global_scale_factor_ to obtain the
+ * time in microseconds. Its units are therefore 1/microsecond.
+ * On Windows the global_scale_factor_ units are 1/millisecond.
+ * There's a macro <ACE_HR_SCALE_CONVERSION> which gives the
+ * units/second. Because it's possible that the units/second
+ * changes in the future, it's recommended to use it instead
+ * of a "hard coded" solution.
+ * Dependend on the platform and used class members, there's a
+ * maximum elapsed period before overflow (which is not checked).
+ * Look at the documentation with some members functions.
+ * On some (most?) implementations it's not recommended to measure
+ * "long" timeperiods, because the error's can accumulate fast.
+ * This is probably not a problem profiling code, but could be
+ * on if the high resolution timer class is used to initiate
+ * actions after a "long" timeout.
+ * On Solaris, a scale factor of 1000 should be used because its
+ * high-resolution timer returns nanoseconds. However, on Intel
+ * platforms, we use RDTSC which returns the number of clock
+ * ticks since system boot. For a 200MHz cpu, each clock tick
+ * is 1/200 of a microsecond; the global_scale_factor_ should
+ * therefore be 200 or 200000 if it's in unit/millisecond.
+ * On Windows ::QueryPerformanceCounter() is used, which can be a
+ * different implementation depending on the used windows HAL
+ * (Hardware Abstraction Layer). On some it uses the PC "timer chip"
+ * while it uses RDTSC on others.
+ * @note The elapsed time calculations in the print methods use
+ * ACE_hrtime_t values. Those methods do _not_ check for overflow!
+ * @note Gabe <begeddov@proaxis.com> raises this issue regarding
+ * <ACE_OS::gethrtime>: on multi-processors, the processor that
+ * you query for your <timer.stop> value might not be the one
+ * you queried for <timer.start>. Its not clear how much
+ * divergence there would be, if any.
+ * This issue is not mentioned in the Solaris 2.5.1 gethrtime
+ * man page.
+ * A RDTSC NOTE: RDTSC is the Intel Pentium read-time stamp counter
+ * and is actualy a 64 bit clock cycle counter, which is increased
+ * with every cycle. It has a low overhead and can be read within
+ * 16 (pentium) or 32 (pentium II,III,...) cycles, but it doesn't
+ * serialize the processor, which could give wrong timings when
+ * profiling very short code fragments.
+ * Problematic is that some power sensitive devices
+ * (laptops for example, but probably also embedded devices),
+ * do change the cycle rate while running.
+ * Some pentiums can run on (at least) two clock frequency's.
+ * Another problem arises with multiprocessor computers, there
+ * are reports that the different RDTSC's are not always kept
+ * in sync.
+ * A windows "timer chip" NOTE: (8254-compatible real-time clock)
+ * When ::QueryPerformanceCounter() uses the 8254 it has a
+ * frequency off about 1.193 Mhz (or sometimes 3.579 Mhz?) and
+ * reading it requires some time (several thousand cycles).
+ */
+class ACE_Export ACE_High_Res_Timer
+{
+public:
+ // = Initialization method.
+
+ /**
+ * global_scale_factor_ is set to @a gsf. All High_Res_Timers use
+ * global_scale_factor_. This allows applications to set the scale
+ * factor just once for all High_Res_Timers. Check
+ * High_Res_Timer.cpp for the default global_scale_factors for
+ * several platforms. For many platforms (e.g., Solaris), the
+ * global_scale_factor_ is set to 1000 so that <scale_factor> need
+ * not be set. Careful, a <scale_factor> of 0 will cause division
+ * by zero exceptions.
+ * Depending on the platform its units are 1/microsecond or
+ * 1/millisecond. Use <ACE_HR_SCALE_CONVERSION> inside calculations
+ * instead a hardcoded value.
+ */
+ static void global_scale_factor (ACE_UINT32 gsf);
+
+ /// Returns the global_scale_factor.
+ static ACE_UINT32 global_scale_factor (void);
+
+#ifndef ACE_HR_SCALE_CONVERSION
+# define ACE_HR_SCALE_CONVERSION (ACE_ONE_SECOND_IN_USECS)
+#endif /* ACE_HR_SCALE_CONVERSION */
+
+ /**
+ * Sets the global_scale_factor to the value in the <env>
+ * environment variable. Returns 0 on success, -1 on failure.
+ * @note If @a env points to string "0" (value zero), this call will fail.
+ * This is basically a no-op on CE because there is no concept of
+ * environment variable on CE.
+ */
+ static int get_env_global_scale_factor (const ACE_TCHAR *env
+ = ACE_TEXT ("ACE_SCALE_FACTOR"));
+
+ /**
+ * Set (and return, for info) the global scale factor by sleeping
+ * for @a usec and counting the number of intervening clock cycles.
+ * Average over @a iterations of @a usec each. On some platforms,
+ * such as Pentiums, this is called automatically during the first
+ * ACE_High_Res_Timer construction with the default parameter
+ * values. An application can override that by calling calibrate
+ * with any desired parameter values _prior_ to constructing the
+ * first ACE_High_Res_Timer instance.
+ * Beware for platforms that can change the cycle rate on the fly.
+ */
+ static ACE_UINT32 calibrate (const ACE_UINT32 usec = 500000,
+ const u_int iterations = 10);
+
+ /// Initialize the timer.
+ ACE_High_Res_Timer (void);
+
+ /// Destructor.
+ ~ACE_High_Res_Timer (void);
+
+ /// Reinitialize the timer.
+ void reset (void);
+
+ /// Start timing.
+ void start (const ACE_OS::ACE_HRTimer_Op = ACE_OS::ACE_HRTIMER_GETTIME);
+
+ /// Stop timing.
+ void stop (const ACE_OS::ACE_HRTimer_Op = ACE_OS::ACE_HRTIMER_GETTIME);
+
+ /// Set @a tv to the number of microseconds elapsed.
+ /**
+ * Could overflow within hours on windows with emulated 64 bit int's
+ * and a fast counter. VC++ and Borland normaly use __int64 and
+ * so normaly don't have this problem.
+ */
+ void elapsed_time (ACE_Time_Value &tv) const;
+
+ /// Set @a nanoseconds to the number of nanoseconds elapsed.
+ /**
+ * Will overflow when measuring more than 194 day's.
+ */
+ void elapsed_time (ACE_hrtime_t &nanoseconds) const;
+
+#if defined (ACE_HAS_POSIX_TIME)
+ /// Returns the elapsed (stop - start) time in a struct timespec
+ /// (sec, nsec).
+ void elapsed_time (struct timespec &) const;
+#endif /* ACE_HAS_POSIX_TIME */
+
+ /// Sets @a usecs to the elapsed (stop - start) time in microseconds.
+ /**
+ * Will overflow on windows when measuring more than appox. 2^^54 ticks.
+ * Is still more than 48 days with a 4 Ghz counter.
+ */
+ void elapsed_microseconds (ACE_hrtime_t &usecs) const;
+
+ /// Start incremental timing.
+ void start_incr (const ACE_OS::ACE_HRTimer_Op = ACE_OS::ACE_HRTIMER_GETTIME);
+
+ /// Stop incremental timing.
+ void stop_incr (const ACE_OS::ACE_HRTimer_Op = ACE_OS::ACE_HRTIMER_GETTIME);
+
+ /// Set @a tv to the number of microseconds elapsed between all calls
+ /// to start_incr and stop_incr.
+ void elapsed_time_incr (ACE_Time_Value &tv) const;
+
+ /// Set <nsec> to the number of nanoseconds elapsed between all calls
+ /// to start_incr and stop_incr.
+ void elapsed_time_incr (ACE_hrtime_t &nanoseconds) const;
+
+#if !defined (ACE_HAS_WINCE)
+ // @@ WINCE These two functions are currently not supported on Windows CE.
+ // However, we should probably use the handle and ACE_Log_Msg to
+ // print out the result.
+ /// Print total time.
+ /// @note only use <print_total> if incremental timings had been used!
+ void print_total (const ACE_TCHAR *message,
+ const int iterations = 1,
+ ACE_HANDLE handle = ACE_STDOUT) const;
+
+ /// Print average time.
+ void print_ave (const ACE_TCHAR *message,
+ const int iterations = 1,
+ ACE_HANDLE handle = ACE_STDOUT) const;
+#endif /* !ACE_HAS_WINCE */
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /**
+ * Get the current "time" as the high resolution counter at this time.
+ * This is intended to be useful for supplying to a ACE_Timer_Queue
+ * as the gettimeofday function, thereby basing the timer calculations
+ * on the high res timer rather than wall clock time.
+ */
+ static ACE_Time_Value gettimeofday_hr (void);
+
+ /**
+ * @deprecated THIS FUNCTION IS DEPRECATED. PLEASE USE
+ * <ACE_OS::gettimeofday> INSTEAD! Calls <ACE_High_Res_Timer::hrtime_to_tv>
+ * passing <ACE_OS::gethrtime>. This function can be used to parameterize
+ * objects such as <ACE_Timer_Queue::gettimeofday>. If
+ * <global_scale_factor_> is not set, and we're on a platform that
+ * requires <global_scale_factor_> (e.g., Win32),
+ * ACE_OS::gettimeofday will be used instead of <ACE_OS::gethrtime>.
+ * This allows applications on Intel to use <High_Res_Timer> even
+ * when <global_scale_factor> is not set. However, setting the
+ * <global_scale_factor_> appropriately will result in the finest
+ * resolution possible.
+ */
+ static ACE_Time_Value gettimeofday (const ACE_OS::ACE_HRTimer_Op =
+ ACE_OS::ACE_HRTIMER_GETTIME);
+
+ /// Converts an <hrt> to @a tv using global_scale_factor_.
+ static void hrtime_to_tv (ACE_Time_Value &tv,
+ const ACE_hrtime_t hrt);
+
+#if defined (linux)
+ /**
+ * This is used to find out the Mhz of the machine for the scale
+ * factor. If there are any problems getting it, we just return 1
+ * (the default).
+ */
+ static ACE_UINT32 get_cpuinfo (void);
+#endif /* defined (linux) */
+
+private:
+ /**
+ * For internal use: gets the high-resolution time using
+ * <ACE_OS::gethrtime>. Except on platforms that require that the
+ * <global_scale_factor_> be set, such as ACE_WIN32, uses the
+ * low-resolution clock if the <global_scale_factor_> has not been
+ * set.
+ */
+ static ACE_hrtime_t gettime (const ACE_OS::ACE_HRTimer_Op =
+ ACE_OS::ACE_HRTIMER_GETTIME);
+
+ /// Calculate the difference between two ACE_hrtime_t values. It is assumed
+ /// that the end time is later than start time, so if end is a smaller
+ /// value, the time counter has wrapped around.
+ static ACE_hrtime_t elapsed_hrtime (const ACE_hrtime_t end,
+ const ACE_hrtime_t start);
+
+ /// Starting time.
+ ACE_hrtime_t start_;
+
+ /// Ending time.
+ ACE_hrtime_t end_;
+
+ /// Total elapsed time.
+ ACE_hrtime_t total_;
+
+ /// Start time of incremental timing.
+ ACE_hrtime_t start_incr_;
+
+ /// Converts ticks to microseconds. That is, ticks /
+ /// global_scale_factor_ == microseconds.
+ static ACE_UINT32 global_scale_factor_;
+
+ /**
+ * Indicates the status of the global scale factor,
+ * 0 = hasn't been set
+ * 1 = been set
+ * -1 = HR timer not supported
+ */
+ static int global_scale_factor_status_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/High_Res_Timer.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HIGH_RES_TIMER_H */
diff --git a/ACE/ace/High_Res_Timer.inl b/ACE/ace/High_Res_Timer.inl
new file mode 100644
index 00000000000..2d089d1520c
--- /dev/null
+++ b/ACE/ace/High_Res_Timer.inl
@@ -0,0 +1,154 @@
+// -*- C++ -*- */
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+
+#if defined (ACE_WIN32)
+# include "ace/OS_NS_sys_time.h"
+#endif /* ACE_WIN32 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Be very careful before changing the calculations inside
+// ACE_High_Res_Timer. The precision matters and we are using integer
+// calculations not floating point. Also look closely at the emulated 64
+// bit int class (inside Basic_Types{h,i,cpp} before changing
+// anything. It's operator/ only returns 32 bits not 64 bits, among
+// other things.
+
+ACE_INLINE void
+ACE_High_Res_Timer::hrtime_to_tv (ACE_Time_Value &tv,
+ const ACE_hrtime_t hrt)
+{
+ // The following are based on the units of global_scale_factor_
+ // being 1/microsecond. Therefore, dividing by it converts
+ // clock ticks to microseconds.
+ tv.sec ((long) (hrt / (ACE_UINT32) ACE_HR_SCALE_CONVERSION /
+ global_scale_factor ()));
+
+ // Calculate usec in a manner that's compatible with ACE_U_LongLong.
+ // hrt = (tv.sec * ACE_ONE_SECOND_IN_USECS + tv.usec) * global_scale_factor_
+ // tv.usec = hrt / global_scale_factor_ - tv.sec * ACE_ONE_SECOND_IN_USECS
+ // That first term will be lossy, so factor out global_scale_factor_:
+ // tv.usec = (hrt - tv.sec * ACE_ONE_SECOND_IN_USECS * global_scale_factor_)/
+ // global_scale_factor
+ ACE_hrtime_t tmp = tv.sec ();
+ tmp *= ((ACE_UINT32) ACE_HR_SCALE_CONVERSION * global_scale_factor ());
+ tv.usec ((long) ((hrt - tmp) / global_scale_factor ()));
+}
+
+
+ACE_INLINE ACE_Time_Value
+ACE_High_Res_Timer::gettimeofday (const ACE_OS::ACE_HRTimer_Op op)
+{
+#if defined (ACE_WIN32)
+ // Get the global scale factor if there isn't one yet.
+ if (ACE_High_Res_Timer::global_scale_factor_status_ == 0)
+ ACE_High_Res_Timer::global_scale_factor ();
+
+ // If there isn't a high-res timer, use gettimeofday ();
+ if (ACE_High_Res_Timer::global_scale_factor_status_ == -1)
+ return ACE_OS::gettimeofday ();
+#endif /* ACE_WIN32 */
+
+ ACE_Time_Value tv;
+ ACE_High_Res_Timer::hrtime_to_tv (tv,
+ ACE_OS::gethrtime (op));
+ return tv;
+}
+
+
+// Get the current high res timer as the time of day. This is intended
+// to be used for a gettimeofday replacement in ACE_Timer_Queue and
+// derived classes so the timers will bebased on high res timers rather
+// than wall clock time. It uses the ACE_High_Res_Timer::gettimeofday
+// function, which is deprecated. If it gets removed, please move the
+// code down here, intact.
+ACE_INLINE ACE_Time_Value
+ACE_High_Res_Timer::gettimeofday_hr (void)
+{
+ return ACE_High_Res_Timer::gettimeofday ();
+}
+
+
+ACE_INLINE ACE_hrtime_t
+ACE_High_Res_Timer::gettime (const ACE_OS::ACE_HRTimer_Op op)
+{
+#if defined (ACE_WIN32)
+ // Get the global scale factor if there isn't one yet.
+ if (ACE_High_Res_Timer::global_scale_factor_status_ == 0)
+ ACE_High_Res_Timer::global_scale_factor ();
+
+ // If there isn't a high-res timer, use gettimeofday ();
+ if (ACE_High_Res_Timer::global_scale_factor_status_ == -1)
+ {
+ ACE_Time_Value tv = ACE_OS::gettimeofday ();
+ // Return the time in microseconds because the global_scale_factor_
+ // is 1.
+ return tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec ();
+ }
+#endif /* ACE_WIN32 */
+
+ return ACE_OS::gethrtime (op);
+}
+
+ACE_INLINE ACE_hrtime_t
+ACE_High_Res_Timer::elapsed_hrtime (const ACE_hrtime_t end,
+ const ACE_hrtime_t start)
+{
+ if (end > start)
+ return end - start;
+ return (~start + 1 + end); // Wrapped-around counter diff
+}
+
+ACE_INLINE
+ACE_High_Res_Timer::~ACE_High_Res_Timer (void)
+{
+}
+
+ACE_INLINE void
+ACE_High_Res_Timer::start (const ACE_OS::ACE_HRTimer_Op op)
+{
+ ACE_TRACE ("ACE_High_Res_Timer::start");
+ this->start_ = ACE_High_Res_Timer::gettime (op);
+}
+
+ACE_INLINE void
+ACE_High_Res_Timer::stop (const ACE_OS::ACE_HRTimer_Op op)
+{
+ ACE_TRACE ("ACE_High_Res_Timer::stop");
+ this->end_ = ACE_High_Res_Timer::gettime (op);
+}
+
+ACE_INLINE void
+ACE_High_Res_Timer::start_incr (const ACE_OS::ACE_HRTimer_Op op)
+{
+ ACE_TRACE ("ACE_High_Res_Timer::start_incr");
+ this->start_incr_ = ACE_High_Res_Timer::gettime (op);
+}
+
+ACE_INLINE void
+ACE_High_Res_Timer::stop_incr (const ACE_OS::ACE_HRTimer_Op op)
+{
+ ACE_TRACE ("ACE_High_Res_Timer::stop_incr");
+ this->total_ +=
+ ACE_High_Res_Timer::elapsed_hrtime (ACE_High_Res_Timer::gettime (op),
+ this->start_incr_);
+}
+
+ACE_INLINE void
+ACE_High_Res_Timer::elapsed_microseconds (ACE_hrtime_t &usecs) const
+{
+ ACE_hrtime_t elapsed = ACE_High_Res_Timer::elapsed_hrtime (this->end_,
+ this->start_);
+ usecs = (ACE_hrtime_t) (elapsed / global_scale_factor ());
+}
+
+ACE_INLINE void
+ACE_High_Res_Timer::global_scale_factor (ACE_UINT32 gsf)
+{
+ global_scale_factor_ = gsf;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ICMP_Socket.cpp b/ACE/ace/ICMP_Socket.cpp
new file mode 100644
index 00000000000..d3d07c80f36
--- /dev/null
+++ b/ACE/ace/ICMP_Socket.cpp
@@ -0,0 +1,186 @@
+// $Id$
+
+#include "ace/ICMP_Socket.h"
+
+#if defined (ACE_HAS_ICMP_SUPPORT) && (ACE_HAS_ICMP_SUPPORT == 1)
+
+#include "ace/ACE.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/OS_NS_sys_socket.h"
+
+
+ACE_RCSID (ace,
+ ICMP_Socket,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_ICMP_Socket)
+
+
+void
+ACE_ICMP_Socket::dump (void) const
+{
+ ACE_TRACE ("ACE_ICMP_Socket::dump");
+}
+
+ACE_ICMP_Socket::ACE_ICMP_Socket (void)
+{
+ ACE_TRACE ("ACE_ICMP_Socket::ACE_ICMP_Socket");
+}
+
+ssize_t
+ACE_ICMP_Socket::send (void const * buf,
+ size_t n,
+ ACE_Addr const & addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_ICMP_Socket::send");
+
+ return ACE_OS::sendto (this->get_handle (),
+ (char const *) buf,
+ n,
+ flags,
+ (sockaddr const *) addr.get_addr (),
+ addr.get_size ());
+}
+
+ssize_t
+ACE_ICMP_Socket::recv (void * buf,
+ size_t n,
+ ACE_Addr & addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_ICMP_Socket::recv");
+
+ int addr_len = addr.get_size ();
+ ssize_t status = ACE_OS::recvfrom (this->get_handle (),
+ (char *) buf,
+ n,
+ flags,
+ (sockaddr *) addr.get_addr (),
+ (int*) &addr_len);
+ addr.set_size (addr_len);
+
+ return status;
+}
+
+ssize_t
+ACE_ICMP_Socket::recv (void * buf,
+ size_t n,
+ int flags,
+ ACE_Time_Value const * timeout) const
+{
+ ACE_TRACE ("ACE_ICMP_Socket::recv");
+
+ return ACE::recv (this->get_handle (),
+ buf,
+ n,
+ flags,
+ timeout);
+}
+
+int
+ACE_ICMP_Socket::open (ACE_Addr const & local,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_ICMP_Socket::open");
+
+ // Check if icmp protocol is supported on this host
+ int proto_number = -1;
+ protoent *proto;
+
+ if (! (proto = getprotobyname ("icmp")))
+ {
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_ICMP_Socket::open: %p; %s\n"),
+ ACE_TEXT ("getprotobyname"),
+ ACE_TEXT ("ICMP protocol is not properly configured ")
+ ACE_TEXT ("or not supported.")),
+ -1);
+ }
+ proto_number = proto->p_proto;
+
+ if (proto_number != IPPROTO_ICMP || proto_number != protocol)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE::ICMP_Socket::open - ")
+ ACE_TEXT ("only IPPROTO_ICMP protocol is ")
+ ACE_TEXT ("currently supported.\n")),
+ -1);
+ }
+
+ if (ACE_SOCK::open (SOCK_RAW,
+ AF_INET,
+ protocol,
+ reuse_addr) == -1)
+ {
+ return -1;
+ }
+
+ return this->shared_open (local);
+}
+
+int
+ACE_ICMP_Socket::shared_open (ACE_Addr const & local)
+{
+ ACE_TRACE ("ACE_ICMP_Socket::shared_open");
+
+ int error = 0;
+ if (local == ACE_Addr::sap_any)
+ {
+ if (ACE::bind_port (this->get_handle ()) == -1)
+ {
+ error = 1;
+ }
+ }
+ else if (ACE_OS::bind (this->get_handle (),
+ reinterpret_cast<sockaddr *> (local.get_addr ()),
+ local.get_size ()) == -1)
+ {
+ error = 1;
+ }
+
+ if (error != 0)
+ {
+ this->close ();
+ }
+
+ return error ? -1 : 0;
+}
+
+unsigned short
+ACE_ICMP_Socket::calculate_checksum (unsigned short * paddress,
+ int len)
+{
+ int nleft = len;
+ int sum = 0;
+ unsigned short * w = paddress;
+ unsigned short answer = 0;
+ while (nleft > 1)
+ {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ if (nleft == 1)
+ {
+ *((unsigned char *) &answer) = *((unsigned char *) w);
+ sum += answer;
+ }
+
+ // add back carry outs from top 16 bits to low 16 bits
+ sum = (sum >> 16) + (sum & 0xffff); // add hi 16 to low 16
+ sum += (sum >> 16); // add carry
+ answer = ~sum; // truncate to 16 bits
+
+ return (answer);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_ICMP_SUPPORT == 1 */
diff --git a/ACE/ace/ICMP_Socket.h b/ACE/ace/ICMP_Socket.h
new file mode 100644
index 00000000000..104ca3ccbc3
--- /dev/null
+++ b/ACE/ace/ICMP_Socket.h
@@ -0,0 +1,110 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file ICMP_Socket.h
+ *
+ * $Id$
+ *
+ * @author Robert S. Iakobashvili <coroberti@gmail.com> <coroberti@walla.co.il>
+ * @author Gonzalo A. Diethelm <gonzalo.diethelm@aditiva.com>
+ */
+//=============================================================================
+
+#ifndef ACE_ICMP_SOCKET_H
+#define ACE_ICMP_SOCKET_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_ICMP_SUPPORT) && (ACE_HAS_ICMP_SUPPORT == 1)
+
+#include "ace/SOCK.h"
+#include "ace/Time_Value.h"
+#include "ace/os_include/netinet/os_in.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_ICMP_Socket
+ *
+ * @brief An abstract class that forms the basis for usage of the ICMP
+ * protocol (that is, support for things such as ping).
+ */
+class ACE_Export ACE_ICMP_Socket : public ACE_SOCK
+{
+public:
+ // = Initialization methods.
+
+ /**
+ * @name Data transfer routines.
+ *
+ * Data transfer routines.
+ */
+ //@{
+
+ /// Send an @a n byte @a buf to the datagram socket (uses
+ /// @c sendto(3) ).
+ ssize_t send (void const * buf,
+ size_t n,
+ ACE_Addr const & addr,
+ int flags = 0) const;
+
+ /// Receive an @a n byte @a buf from the datagram socket
+ /// (uses @c recvfrom(3) ).
+ ssize_t recv (void * buf,
+ size_t n,
+ ACE_Addr & addr,
+ int flags = 0) const;
+
+ /// TODO: comment
+ ssize_t recv (void * buf,
+ size_t n,
+ int flags,
+ ACE_Time_Value const * timeout) const;
+
+ //@}
+
+ /// Wrapper around the BSD-style @c socket system call (no QoS).
+ int open (ACE_Addr const & local = ACE_Addr::sap_any,
+ int protocol = IPPROTO_ICMP,
+ int reuse_addr = 0);
+
+ /// Dump the state of object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ // Protected constructors, so the class can only be derived from.
+
+ /// Default constructor.
+ ACE_ICMP_Socket (void);
+
+ /// Constructor that takes a local listening address.
+ ACE_ICMP_Socket (ACE_Addr const & local,
+ int protocol = IPPROTO_ICMP,
+ int reuse_addr = 0);
+
+ /// Wrapper around BSD-style @c bind system call.
+ int shared_open (ACE_Addr const & local);
+
+ /// Calculates check-sum.
+ unsigned short calculate_checksum (unsigned short* paddress,
+ int len);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_ICMP_SUPPORT == 1 */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_ICMP_SOCKET_H */
diff --git a/ACE/ace/INET_Addr.cpp b/ACE/ace/INET_Addr.cpp
new file mode 100644
index 00000000000..76c64ce8b74
--- /dev/null
+++ b/ACE/ace/INET_Addr.cpp
@@ -0,0 +1,1168 @@
+// $Id$
+
+// Defines the Internet domain address family address format.
+
+#include "ace/INET_Addr.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/INET_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_arpa_inet.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_RCSID (ace,
+ INET_Addr,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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?
+ char hoststr[MAXHOSTNAMELEN+1];
+
+ bool result = false;
+ if (ipaddr_format == 0)
+ result = (this->get_host_name (hoststr, MAXHOSTNAMELEN+1) == 0);
+ else
+ result = (this->get_host_addr (hoststr, MAXHOSTNAMELEN+1) != 0);
+
+ if (!result)
+ return -1;
+
+ size_t total_len =
+ ACE_OS::strlen (hoststr)
+ + 5 // ACE_OS::strlen ("65535"), Assuming the max port number.
+ + 1 // sizeof (':'), addr/port sep
+ + 1; // sizeof ('\0'), terminating NUL
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_TCHAR const *format = ACE_TEXT("%ls:%d");
+#else
+ ACE_TCHAR const *format = ACE_TEXT("%s:%d");
+#endif /* !ACE_WIN32 && ACE_USES_WCHAR */
+#if defined (ACE_HAS_IPV6)
+ if (ACE_OS::strchr (hoststr, ACE_TEXT (':')) != 0)
+ {
+ total_len += 2; // ACE_OS::strlen ("[]") IPv6 addr frames
+# if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ format = ACE_TEXT("[%ls]:%d");
+# else
+ format = ACE_TEXT("[%s]:%d");
+# endif /* !ACE_WIN32 && ACE_USES_WCHAR */
+ }
+#endif // ACE_HAS_IPV6
+
+ if (size < total_len)
+ return -1;
+ else
+ ACE_OS::sprintf (s, format,
+ ACE_TEXT_CHAR_TO_TCHAR (hoststr),
+ this->get_port_number ());
+ return 0;
+}
+
+void
+ACE_INET_Addr::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("%s"), s));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// Compare two addresses for inequality.
+
+bool
+ACE_INET_Addr::operator != (const ACE_INET_Addr &sap) const
+{
+ ACE_TRACE ("ACE_INET_Addr::operator !=");
+ return !((*this) == sap);
+}
+
+// Compare two addresses for equality.
+
+bool
+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 false;
+
+ return (ACE_OS::memcmp (&this->inet_addr_,
+ &sap.inet_addr_,
+ this->get_size ()) == 0);
+}
+
+bool
+ACE_INET_Addr::is_ip_equal (const ACE_INET_Addr &sap) const
+{
+ if (this->get_type () != sap.get_type ()
+ || this->get_size () != sap.get_size ())
+ return false;
+
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == PF_INET6)
+ {
+ const unsigned int *addr =
+ reinterpret_cast<const unsigned int*>(this->ip_addr_pointer());
+ const unsigned int *saddr =
+ reinterpret_cast<const unsigned int*>(sap.ip_addr_pointer());
+ return (addr[0] == saddr[0] &&
+ addr[1] == saddr[1] &&
+ addr[2] == saddr[2] &&
+ addr[3] == saddr[3]);
+ }
+ else
+#endif /* ACE_HAS_IPV6 */
+ return this->get_ip_address () == sap.get_ip_address();
+}
+
+
+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_INET_Addr::ACE_INET_Addr (void)
+ : ACE_Addr (determine_type (), sizeof (inet_addr_))
+{
+ // ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->reset ();
+}
+
+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 ());
+
+ this->set_type (sa.get_type());
+ this->set_size (sa.get_size());
+ }
+
+ return 0;
+}
+
+// Transform the string into the current addressing format.
+
+int
+ACE_INET_Addr::string_to_addr (const char s[], int address_family)
+{
+ ACE_TRACE ("ACE_INET_Addr::string_to_addr");
+ int result;
+ char *ip_buf = 0;
+ char *ip_addr = 0;
+
+ // Need to make a duplicate since we'll be overwriting the string.
+ ACE_ALLOCATOR_RETURN (ip_buf,
+ ACE_OS::strdup (s),
+ -1);
+ ip_addr = ip_buf;
+ // We use strrchr because of IPv6 addresses.
+ char *port_p = ACE_OS::strrchr (ip_addr, ':');
+#if defined (ACE_HAS_IPV6)
+ // Check for extended IPv6 format : '[' <ipv6 address> ']' ':' <port>
+ if (ip_addr[0] == '[')
+ {
+ // find closing bracket
+ char *cp_pos = ACE_OS::strchr (ip_addr, ']');
+ // check for port separator after closing bracket
+ // if not found leave it, error will come later
+ if (cp_pos)
+ {
+ *cp_pos = '\0'; // blank out ']'
+ ++ip_addr; // skip over '['
+ if (cp_pos[1] == ':')
+ port_p = cp_pos + 1;
+ else
+ port_p = cp_pos; // leads to error on missing port
+ }
+ }
+#endif /* ACE_HAS_IPV6 */
+
+ if (port_p == 0) // Assume it's a port number.
+ {
+ char *endp = 0;
+ u_short port =
+ static_cast<u_short> (ACE_OS::strtol (ip_addr, &endp, 10));
+ if (*endp == '\0') // strtol scanned the entire string - all digits
+ 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 ':'
+
+ char *endp = 0;
+ u_short port = static_cast<u_short> (ACE_OS::strtol (port_p, &endp, 10));
+ if (*endp == '\0') // strtol scanned the entire string - all digits
+ result = this->set (port, ip_addr, 1, address_family);
+ else
+ result = this->set (port_p, ip_addr);
+ }
+
+ ACE_OS::free (ACE_MALLOC_T (ip_buf));
+ return result;
+}
+
+int
+ACE_INET_Addr::set (const char address[], int address_family)
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+ return this->string_to_addr (address, address_family);
+}
+
+ACE_INET_Addr::ACE_INET_Addr (const char address[], int address_family)
+ : ACE_Addr (determine_type (), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->reset ();
+ this->set (address, address_family);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INET_Addr::ACE_INET_Addr (const wchar_t address[], int address_family)
+ : ACE_Addr (determine_type (), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->reset ();
+ this->set (address, address_family);
+}
+
+#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->reset ();
+ 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,
+ int map)
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+ this->set_address (reinterpret_cast<const char *> (&inet_address),
+ sizeof inet_address,
+ encode, map);
+ 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::memset ((void *) &this->inet_addr_,
+ 0,
+ sizeof this->inet_addr_);
+
+#if defined (ACE_HAS_IPV6)
+ struct addrinfo hints;
+ struct addrinfo *res = 0;
+ int error = 0;
+ ACE_OS::memset (&hints, 0, sizeof (hints));
+# if defined (ACE_USES_IPV4_IPV6_MIGRATION)
+ if (address_family == AF_UNSPEC && !ACE::ipv6_enabled())
+ address_family = AF_INET;
+# endif /* ACE_USES_IPV4_IPV6_MIGRATION */
+ if (address_family == AF_UNSPEC || address_family == AF_INET6)
+ {
+ hints.ai_family = AF_INET6;
+ error = ::getaddrinfo (host_name, 0, &hints, &res);
+ if (error)
+ {
+ if (address_family == AF_INET6)
+ {
+ if (res)
+ ::freeaddrinfo(res);
+ errno = error;
+ return -1;
+ }
+ address_family = AF_INET;
+ }
+ }
+ if (address_family == AF_INET)
+ {
+ hints.ai_family = AF_INET;
+ error = ::getaddrinfo (host_name, 0, &hints, &res);
+ if (error)
+ {
+ if (res)
+ ::freeaddrinfo(res);
+ errno = error;
+ return -1;
+ }
+ }
+ this->set_type (res->ai_family);
+ this->set_addr (res->ai_addr, res->ai_addrlen);
+ this->set_port_number (port_number, encode);
+ ::freeaddrinfo (res);
+ return 0;
+#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 = static_cast<short> (address_family);
+#ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
+ this->inet_addr_.in4_.sin_len = sizeof (this->inet_addr_.in4_);
+#endif
+ struct in_addr addrv4;
+ if (ACE_OS::inet_aton (host_name,
+ &addrv4) == 1)
+ return this->set (port_number,
+ encode ? ACE_NTOHL (addrv4.s_addr) : addrv4.s_addr,
+ encode);
+ else
+ {
+# if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYNAME)
+ hostent *hp = ACE_OS::gethostbyname (host_name);
+# else
+ hostent hentry;
+ ACE_HOSTENT_DATA buf;
+ int h_error; // Not the same as errno!
+
+ hostent *hp = ACE_OS::gethostbyname_r (host_name, &hentry,
+ buf, &h_error);
+ if (hp == 0)
+ errno = h_error;
+# endif /* ACE_VXWORKS */
+
+ if (hp == 0)
+ {
+ return -1;
+ }
+ else
+ {
+ (void) ACE_OS::memcpy ((void *) &addrv4.s_addr,
+ hp->h_addr,
+ hp->h_length);
+ return this->set (port_number,
+ encode ? ACE_NTOHL (addrv4.s_addr) : addrv4.s_addr,
+ encode);
+ }
+ }
+#endif /* ACE_HAS_IPV6 */
+}
+
+// Helper function to get a port number from a port name.
+
+static int get_port_number_from_name (const char port_name[],
+ const char protocol[])
+{
+ // Maybe port_name is directly a port number?
+ char *endp = 0;
+ int port_number = static_cast<int> (ACE_OS::strtol (port_name, &endp, 10));
+
+ if (port_number >= 0 && *endp == '\0')
+ {
+ // Ok, port_name was really a number, and nothing else. We
+ // store that value as the port number. NOTE: this number must
+ // be returned in network byte order!
+ u_short n = static_cast<u_short> (port_number);
+ n = ACE_HTONS (n);
+ return n;
+ }
+
+ // We try to resolve port number from its name.
+
+#if defined (ACE_LACKS_GETSERVBYNAME)
+ port_number = 0;
+ ACE_UNUSED_ARG (port_name);
+ ACE_UNUSED_ARG (protocol);
+#else
+ port_number = -1;
+ servent sentry;
+ ACE_SERVENT_DATA buf;
+ servent *sp = ACE_OS::getservbyname_r (port_name,
+ protocol,
+ &sentry,
+ buf);
+ if (sp != 0)
+ port_number = sp->s_port;
+#endif /* ACE_LACKS_GETSERVBYNAME */
+
+ return port_number;
+}
+
+// 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");
+
+ int const port_number = get_port_number_from_name (port_name, protocol);
+ if (port_number == -1)
+ {
+ ACE_NOTSUP_RETURN (-1);
+ }
+
+ int address_family = PF_UNSPEC;
+# if defined (ACE_HAS_IPV6)
+ if (ACE_OS::strcmp (ACE_TEXT_CHAR_TO_TCHAR(protocol), ACE_TEXT ("tcp6")) == 0)
+ address_family = AF_INET6;
+# endif /* ACE_HAS_IPV6 */
+
+ return this->set (static_cast<u_short> (port_number),
+ host_name, 0, address_family);
+}
+
+// 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");
+
+ int const port_number = get_port_number_from_name (port_name, protocol);
+ if (port_number == -1)
+ {
+ ACE_NOTSUP_RETURN (-1);
+ }
+
+ return this->set (static_cast<u_short> (port_number),
+ inet_address, 0);
+}
+
+// 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 (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)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr: %p\n"),
+ ACE_TEXT_CHAR_TO_TCHAR ((host_name == 0) ?
+ "<unknown>" : host_name)));
+}
+
+#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 (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)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr: %p\n"),
+ ACE_TEXT_WCHAR_TO_TCHAR ((host_name == 0) ?
+ ACE_TEXT_WIDE ("<unknown>") :
+ host_name)));
+}
+#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)
+ {
+ int maxlen = static_cast<int> (sizeof (this->inet_addr_.in4_));
+ if (len > maxlen)
+ len = maxlen;
+ 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)
+ {
+ int maxlen = static_cast<int> (sizeof (this->inet_addr_.in6_));
+ if (len > maxlen)
+ len = maxlen;
+ 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;
+}
+
+// Return the address.
+
+void *
+ACE_INET_Addr::get_addr (void) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_addr");
+ return (void*)&this->inet_addr_;
+}
+
+void
+ACE_INET_Addr::set_addr (void *addr, int len)
+{
+ this->set_addr (addr, len, 0);
+}
+
+// Set a pointer to the address.
+void
+ACE_INET_Addr::set_addr (void *addr, int /* len */, int map)
+{
+ ACE_TRACE ("ACE_INET_Addr::set_addr");
+ struct sockaddr_in *getfamily = static_cast<struct sockaddr_in *> (addr);
+
+ if (getfamily->sin_family == AF_INET)
+ {
+#if defined (ACE_HAS_IPV6)
+ if (map)
+ this->set_type (AF_INET6);
+ else
+#endif /* ACE_HAS_IPV6 */
+ this->set_type (AF_INET);
+ this->set_port_number (getfamily->sin_port, 0);
+ this->set_address (reinterpret_cast<const char*> (&getfamily->sin_addr),
+ sizeof (getfamily->sin_addr),
+ 0, map);
+ }
+#if defined (ACE_HAS_IPV6)
+ else if (getfamily->sin_family == AF_INET6)
+ {
+ struct sockaddr_in6 *in6 = static_cast<struct sockaddr_in6*> (addr);
+ this->set_port_number (in6->sin6_port, 0);
+ this->set_address (reinterpret_cast<const char*> (&in6->sin6_addr),
+ sizeof (in6->sin6_addr),
+ 0);
+ this->inet_addr_.in6_.sin6_scope_id = in6->sin6_scope_id;
+ }
+#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 (determine_type (), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->reset ();
+ 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 (determine_type (), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->reset ();
+ if (this->set (port_number, inet_address) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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 (determine_type (), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->reset ();
+ if (this->set (port_name,
+ host_name,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_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 (determine_type (), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->reset ();
+ if (this->set (port_name,
+ host_name,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_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 (determine_type (), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+#if !defined (ACE_LACKS_HTONL)
+ this->reset ();
+ if (this->set (port_name,
+ htonl (inet_address),
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
+#else
+ ACE_UNUSED_ARG (port_name);
+ ACE_UNUSED_ARG (inet_address);
+ ACE_UNUSED_ARG (protocol);
+#endif
+}
+
+#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 (determine_type (), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+#if !defined (ACE_LACKS_HTONL)
+ this->reset ();
+ if (this->set (port_name,
+ htonl (inet_address),
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
+#else
+ ACE_UNUSED_ARG (port_name);
+ ACE_UNUSED_ARG (inet_address);
+ ACE_UNUSED_ARG (protocol);
+#endif
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INET_Addr::~ACE_INET_Addr (void)
+{
+}
+
+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 = this->get_host_name_i (hostname,len);
+ if (result < 0)
+ {
+ if (result == -2)
+ // We know that hostname is nul-terminated
+ result = -1;
+ 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::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 = ACE_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::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 (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYADDR)
+ 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
+ void* addr = this->ip_addr_pointer ();
+ int size = this->ip_addr_size ();
+ int type = this->get_type ();
+
+# if defined (ACE_HAS_IPV6) && defined (ACE_HAS_BROKEN_GETHOSTBYADDR_V4MAPPED)
+ // Most OS can not handle IPv6-mapped-IPv4 addresses (even
+ // though they are meant to) so map them back to IPv4 addresses
+ // before trying to resolve them
+ in_addr demapped_addr;
+ if (type == PF_INET6 &&
+ (this->is_ipv4_mapped_ipv6 () || this->is_ipv4_compat_ipv6 ()))
+ {
+ ACE_OS::memcpy (&demapped_addr.s_addr, &this->inet_addr_.in6_.sin6_addr.s6_addr[12], 4);
+ addr = &demapped_addr;
+ size = sizeof(demapped_addr);
+ type = PF_INET;
+ }
+# endif /* ACE_HAS_IPV6 */
+
+# if defined (DIGITAL_UNIX) && defined (__GNUC__)
+ hostent * const hp =
+ ACE_OS::gethostbyaddr (static_cast <char *> (addr), size, type);
+# else
+ int h_error; // Not the same as errno!
+ hostent hentry;
+ ACE_HOSTENT_DATA buf;
+ hostent * const hp =
+ ACE_OS::gethostbyaddr_r (static_cast <char *> (addr),
+ size,
+ type,
+ &hentry,
+ buf,
+ &h_error);
+# endif /* DIGITAL_UNIX */
+
+ if (hp == 0 || 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 /* ACE_VXWORKS */
+ }
+}
+
+int ACE_INET_Addr::set_address (const char *ip_addr,
+ int len,
+ int encode /* = 1 */,
+ int map /* = 0 */)
+{
+ 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 = *reinterpret_cast<const ACE_UINT32 *> (ip_addr);
+ if (encode)
+ ip4 = ACE_HTONL (ip4);
+
+
+ if (this->get_type () == AF_INET && map == 0) {
+ this->base_set (AF_INET, sizeof (this->inet_addr_.in4_));
+#ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
+ this->inet_addr_.in4_.sin_len = sizeof (this->inet_addr_.in4_);
+#endif
+ this->inet_addr_.in4_.sin_family = AF_INET;
+ this->set_size (sizeof (this->inet_addr_.in4_));
+ ACE_OS::memcpy (&this->inet_addr_.in4_.sin_addr,
+ &ip4,
+ len);
+ }
+#if defined (ACE_HAS_IPV6)
+ else if (map == 0)
+ {
+ // this->set_type (AF_INET);
+ this->base_set (AF_INET, sizeof (this->inet_addr_.in4_));
+#ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
+ this->inet_addr_.in4_.sin_len = sizeof (this->inet_addr_.in4_);
+#endif
+ this->inet_addr_.in4_.sin_family = AF_INET;
+ this->set_size (sizeof (this->inet_addr_.in4_));
+ ACE_OS::memcpy (&this->inet_addr_.in4_.sin_addr,
+ &ip4, len);
+ }
+ // 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_));
+#ifdef ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+ this->inet_addr_.in6_.sin6_len = sizeof (this->inet_addr_.in6_);
+#endif
+ this->inet_addr_.in6_.sin6_family = AF_INET6;
+ this->set_size (sizeof (this->inet_addr_.in6_));
+ if (ip4 == ACE_HTONL (INADDR_ANY))
+ {
+ in6_addr const ip6 = in6addr_any;
+ ACE_OS::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 */
+ ACE_OS::memset (&this->inet_addr_.in6_.sin6_addr, 0, 16);
+ this->inet_addr_.in6_.sin6_addr.s6_addr[10] =
+ this->inet_addr_.in6_.sin6_addr.s6_addr[11] = 0xff;
+ ACE_OS::memcpy
+ (&this->inet_addr_.in6_.sin6_addr.s6_addr[12], &ip4, 4);
+ }
+#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;
+#ifdef ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+ this->inet_addr_.in6_.sin6_len = sizeof (this->inet_addr_.in6_);
+#endif
+ ACE_OS::memcpy (&this->inet_addr_.in6_.sin6_addr, ip_addr, len);
+
+ return 0;
+ } /* end len == 16 */
+#endif /* ACE_HAS_IPV6 */
+
+ // Here with an unrecognized length.
+ errno = EAFNOSUPPORT;
+ return -1;
+
+}
+
+#if (defined (__linux__) || defined (ACE_WIN32)) && defined (ACE_HAS_IPV6)
+int
+ACE_INET_Addr::set_interface (const char *intf_name)
+{
+ if (this->get_type () == PF_INET6 &&
+ (IN6_IS_ADDR_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr)))
+ {
+#if defined (__linux__)
+ this->inet_addr_.in6_.sin6_scope_id =
+ ACE_OS::if_nametoindex (intf_name);
+#else
+ this->inet_addr_.in6_.sin6_scope_id =
+ intf_name ? ACE_OS::atoi (intf_name) : 0;
+#endif
+ // check to see if the interface lookup succeeded
+ if (this->inet_addr_.in6_.sin6_scope_id != 0)
+ return 0;
+ else
+ return -1;
+ }
+ else
+ return 0;
+
+}
+#endif /* __linux && ACE_HAS_IPV6 */
+
+const char *
+ACE_INET_Addr::get_host_addr (char *dst, int size) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == AF_INET6)
+ {
+ // mcorino@remedy.nl - Aug-26, 2005
+ // I don't think this should be done because it results in a decimal address
+ // representation which is not distinguishable from the IPv4 form which makes
+ // it impossible to resolve back to an IPv6 INET_Addr without prior knowledge
+ // that this was such an address to begin with.
+
+ //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);
+ //}
+
+# if defined (ACE_WIN32)
+ if (0 == ::getnameinfo (reinterpret_cast<const sockaddr*> (&this->inet_addr_.in6_),
+ this->get_size (),
+ dst,
+ size,
+ 0, 0, // Don't want service name
+ NI_NUMERICHOST))
+ return dst;
+ ACE_OS::set_errno_to_wsa_last_error ();
+ return 0;
+# else
+ const char *ch = ACE_OS::inet_ntop (AF_INET6,
+ &this->inet_addr_.in6_.sin6_addr,
+ dst,
+ size);
+#if defined (__linux__)
+ if ((IN6_IS_ADDR_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr)) &&
+ this->inet_addr_.in6_.sin6_scope_id != 0)
+ {
+ char scope_buf[32];
+ ACE_OS::sprintf (scope_buf, "%%%u", this->inet_addr_.in6_.sin6_scope_id);
+ if ((ACE_OS::strlen (ch)+ACE_OS::strlen (scope_buf)) < (size_t)size)
+ {
+ ACE_OS::strcat (dst, scope_buf);
+ }
+ }
+#endif
+ return ch;
+# endif /* ACE_WIN32 */
+ }
+#endif /* ACE_HAS_IPV6 */
+
+#if defined (ACE_VXWORKS)
+ ACE_UNUSED_ARG (dst);
+ ACE_UNUSED_ARG (size);
+
+ // 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 = const_cast<ACE_INET_Addr *> (this);
+ inet_ntoa_b(this->inet_addr_.in4_.sin_addr, ncthis->buf_);
+ ACE_OS::strsncpy (dst, &buf_[0], size);
+ return &buf_[0];
+#else /* ACE_VXWORKS */
+ char *ch = ACE_OS::inet_ntoa (this->inet_addr_.in4_.sin_addr);
+ ACE_OS::strsncpy (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 /* ACE_HAS_IPV6 */
+# if defined (ACE_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 = const_cast<ACE_INET_Addr *> (this);
+ inet_ntoa_b (this->inet_addr_.in4_.sin_addr, ncthis->buf_);
+ return &buf_[0];
+# else /* ACE_VXWORKS */
+ return ACE_OS::inet_ntoa (this->inet_addr_.in4_.sin_addr);
+# endif /* !ACE_VXWORKS */
+#endif /* !ACE_HAS_IPV6 */
+}
+
+// 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::memcpy (&addr, thisaddrptr, sizeof (addr));
+ return ACE_NTOHL (addr);
+ }
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_INET_Addr::get_ip_address: address is a IPv6 address not IPv4\n")));
+ errno = EAFNOSUPPORT;
+ return 0;
+ }
+#endif /* ACE_HAS_IPV6 */
+ return ACE_NTOHL (ACE_UINT32 (this->inet_addr_.in4_.sin_addr.s_addr));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/INET_Addr.h b/ACE/ace/INET_Addr.h
new file mode 100644
index 00000000000..7098314ad37
--- /dev/null
+++ b/ACE/ace/INET_Addr.h
@@ -0,0 +1,399 @@
+/* -*- 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/Sock_Connect.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Addr.h"
+
+#if defined(ACE_VXWORKS)
+ // Needed to get INET_ADDR_LEN
+# include /**/ "inetLib.h"
+#endif /* ACE_VXWORKS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 *addr, int len);
+
+ /// Creates an ACE_INET_Addr from a @a port_number and the remote
+ /// @a 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 @a 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 @a address it
+ * is assumed to be a port number, with the IP address being
+ * INADDR_ANY.
+ */
+ explicit ACE_INET_Addr (const char address[],
+ int address_family = AF_UNSPEC);
+
+ /**
+ * Creates an ACE_INET_Addr from a @a port_number and an Internet
+ * <ip_addr>. This method assumes that @a port_number and <ip_addr>
+ * are in host byte order. If you have addressing information in
+ * network byte order, @see set().
+ */
+ explicit 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 @a host_name, and the @a 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 @a 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);
+
+ explicit ACE_INET_Addr (const wchar_t address[],
+ int address_family = AF_UNSPEC);
+
+ 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 @a port_number and the
+ * remote @a host_name. If @a encode is non-zero then @a 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 @a port_number and an Internet
+ * @a ip_addr. If @a 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.
+ *
+ * If <map> is non-zero and IPv6 support has been compiled in,
+ * then this address will be set to the IPv4-mapped IPv6 address of it.
+ */
+ int set (u_short port_number,
+ ACE_UINT32 ip_addr = INADDR_ANY,
+ int encode = 1,
+ int map = 0);
+
+ /// Uses <getservbyname> to initialize an ACE_INET_Addr from a
+ /// <port_name>, the remote @a host_name, and the @a 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 @a 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 @a 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 @a address it
+ * is assumed to be a port number, with the IP address being
+ * INADDR_ANY.
+ */
+ int set (const char addr[], int address_family = AF_UNSPEC);
+
+ /// 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[], int address_family = AF_UNSPEC);
+#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);
+
+ /// Set a pointer to the address.
+ virtual void set_addr (void *, int len, int map);
+
+ /**
+ * 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 @a 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 @a 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 @a address it is assumed to be a port number,
+ * with the IP address being INADDR_ANY.
+ */
+ virtual int string_to_addr (const char address[],
+ int address_family = AF_UNSPEC);
+
+#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
+ * @a encode is enabled then @a 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
+ * @a 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 @a len parameter.
+ * If <map> is non-zero, IPv6 support has been compiled in, and
+ * <ip_addr> is an IPv4 address, then this address is set to the IPv4-mapped
+ * IPv6 address of it.
+ */
+ int set_address (const char *ip_addr,
+ int len,
+ int encode = 1,
+ int map = 0);
+
+#if (defined (__linux__) || defined (ACE_WIN32)) && defined (ACE_HAS_IPV6)
+ /**
+ * Sets the interface that should be used for this address. This only has
+ * an effect when the address is link local, otherwise it does nothing.
+ */
+ int set_interface (const char *intf_name);
+#endif /* (__linux__ || ACE_WIN32) && ACE_HAS_IPV6 */
+
+ /// 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. You should therefore either (1) do a "deep copy" of
+ * the address returned by get_host_name(), e.g., using strdup() or
+ * (2) use the "reentrant" version of get_host_name() described
+ * above.
+ */
+ const char *get_host_name (void) const;
+
+ /**
+ * Return the "dotted decimal" Internet address representation of
+ * the hostname storing it in the @a addr (which is assumed to be
+ * <addr_size> bytes long). This version is reentrant.
+ */
+ const char *get_host_addr (char *addr, int addr_size) const;
+
+ /**
+ * Return the "dotted decimal" Internet address representation of
+ * the hostname. This version is non-reentrant since it returns a
+ * pointer to a static data area. You should therefore either
+ * (1) do a "deep copy" of the address returned by get_host_addr(), e.g.,
+ * using strdup() or (2) use the "reentrant" version of
+ * get_host_addr() described above.
+ */
+ const char *get_host_addr (void) const;
+
+ /// Return the 4-byte IP address, converting it into host byte
+ /// order.
+ ACE_UINT32 get_ip_address (void) const;
+
+ /// Return @c true if the IP address is INADDR_ANY or IN6ADDR_ANY.
+ bool is_any (void) const;
+
+ /// Return @c true if the IP address is IPv4/IPv6 loopback address.
+ bool is_loopback (void) const;
+
+ /// Return @c true if the IP address is IPv4/IPv6 multicast address.
+ bool is_multicast (void) const;
+
+#if defined (ACE_HAS_IPV6)
+ /// Return @c true if the IP address is IPv6 linklocal address.
+ bool is_linklocal (void) const;
+
+ /// Return @c true if the IP address is IPv4-mapped IPv6 address.
+ bool is_ipv4_mapped_ipv6 (void) const;
+
+ /// Return @c true if the IP address is IPv4-compatible IPv6 address.
+ bool is_ipv4_compat_ipv6 (void) const;
+#endif /* ACE_HAS_IPV6 */
+
+ /**
+ * Returns @c true if @c this is less than @a rhs. In this context,
+ * "less than" is defined in terms of IP address and TCP port
+ * number. This operator makes it possible to use @c ACE_INET_Addrs
+ * in STL maps.
+ */
+ bool 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.
+ bool operator == (const ACE_INET_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ bool operator != (const ACE_INET_Addr &SAP) const;
+
+ /// A variation of the equality operator, this method only compares the
+ /// IP address and ignores the port number.
+ bool is_ip_equal (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 @a 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;
+ int ip_addr_size (void) const;
+ int determine_type (void) const;
+
+ /// Initialize underlying inet_addr_ to default values
+ void reset (void);
+
+ /// 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 (ACE_VXWORKS)
+ char buf_[INET_ADDR_LEN];
+#endif
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/INET_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_INET_ADDR_H */
diff --git a/ACE/ace/INET_Addr.inl b/ACE/ace/INET_Addr.inl
new file mode 100644
index 00000000000..a05a80db7fb
--- /dev/null
+++ b/ACE/ace/INET_Addr.inl
@@ -0,0 +1,257 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#include "ace/OS_NS_string.h"
+#include "ace/Global_Macros.h"
+#include "ace/OS_NS_arpa_inet.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_INET_Addr::reset (void)
+{
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ if (this->get_type() == AF_INET)
+ {
+#ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
+ this->inet_addr_.in4_.sin_len = sizeof (this->inet_addr_.in4_);
+#endif
+ this->inet_addr_.in4_.sin_family = AF_INET;
+ }
+#if defined (ACE_HAS_IPV6)
+ else if (this->get_type() == AF_INET6)
+ {
+#ifdef ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+ this->inet_addr_.in6_.sin6_len = sizeof (this->inet_addr_.in6_);
+#endif
+ this->inet_addr_.in6_.sin6_family = AF_INET6;
+ }
+#endif /* ACE_HAS_IPV6 */
+}
+
+ACE_INLINE int
+ACE_INET_Addr::determine_type (void) const
+{
+#if defined (ACE_HAS_IPV6)
+# if defined (ACE_USES_IPV4_IPV6_MIGRATION)
+ return ACE::ipv6_enabled () ? AF_INET6 : AF_INET;
+# else
+ return AF_INET6;
+# endif /* ACE_USES_IPV4_IPV6_MIGRATION */
+#else
+ return AF_INET;
+#endif /* ACE_HAS_IPV6 */
+}
+
+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 int
+ACE_INET_Addr::ip_addr_size (void) const
+{
+ // Since this size value is used to pass to other host db-type
+ // functions (gethostbyaddr, etc.) the length is of int type.
+ // Thus, cast all these sizes back to int. They're all well
+ // within the range of an int anyway.
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == PF_INET)
+ return static_cast<int> (sizeof this->inet_addr_.in4_.sin_addr);
+ else
+ return static_cast<int> (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 static_cast<int> (sizeof this->inet_addr_.in4_.sin_addr.s_addr);
+# else /* _UNICOS */
+ return static_cast<int> (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_LACKS_NTOHS)
+ ACE_NOTSUP_RETURN (0);
+#elif 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 */
+}
+
+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 bool
+ACE_INET_Addr::operator < (const ACE_INET_Addr &rhs) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type() != rhs.get_type())
+ {
+ return this->get_type() < rhs.get_type();
+ }
+
+ if (this->get_type() == PF_INET6)
+ {
+ int memval = ACE_OS::memcmp (this->ip_addr_pointer(),
+ rhs.ip_addr_pointer(),
+ this->ip_addr_size());
+
+ return memval < 0
+ || (memval == 0
+ && (this->get_port_number() < rhs.get_port_number()
+ || (this->get_port_number() == rhs.get_port_number()
+ && this->inet_addr_.in6_.sin6_scope_id <
+ rhs.inet_addr_.in6_.sin6_scope_id)));
+ }
+#endif
+
+ 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[], int address_family)
+{
+ return this->set (ACE_Wide_To_Ascii (addr).char_rep (), address_family);
+}
+
+#endif /* ACE_HAS_WCHAR */
+
+// Return @c true if the IP address is INADDR_ANY or IN6ADDR_ANY.
+ACE_INLINE bool
+ACE_INET_Addr::is_any (void) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == AF_INET6)
+ return IN6_IS_ADDR_UNSPECIFIED (&this->inet_addr_.in6_.sin6_addr);
+#endif /* ACE_HAS_IPV6 */
+
+ return (this->inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY);
+}
+
+// Return @c true if the IP address is IPv4/IPv6 loopback address.
+ACE_INLINE bool
+ACE_INET_Addr::is_loopback (void) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == AF_INET6)
+ return IN6_IS_ADDR_LOOPBACK (&this->inet_addr_.in6_.sin6_addr);
+#endif /* ACE_HAS_IPV6 */
+
+ // RFC 3330 defines loopback as any address with 127.x.x.x
+ return ((this->get_ip_address () & 0XFF000000) == (INADDR_LOOPBACK & 0XFF000000));
+}
+
+// Return @c true if the IP address is IPv4/IPv6 multicast address.
+ACE_INLINE bool
+ACE_INET_Addr::is_multicast (void) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type() == AF_INET6)
+ return this->inet_addr_.in6_.sin6_addr.s6_addr[0] == 0xFF;
+#endif /* ACE_HAS_IPV6 */
+ return
+ this->inet_addr_.in4_.sin_addr.s_addr >= 0xE0000000 && // 224.0.0.0
+ this->inet_addr_.in4_.sin_addr.s_addr <= 0xEFFFFFFF; // 239.255.255.255
+}
+
+#if defined (ACE_HAS_IPV6)
+// Return @c true if the IP address is IPv6 linklocal address.
+ACE_INLINE bool
+ACE_INET_Addr::is_linklocal (void) const
+{
+ if (this->get_type () == AF_INET6)
+ return IN6_IS_ADDR_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr);
+
+ return false;
+}
+
+// Return @c true if the IP address is IPv4 mapped IPv6 address.
+ACE_INLINE bool
+ACE_INET_Addr::is_ipv4_mapped_ipv6 (void) const
+{
+ if (this->get_type () == AF_INET6)
+ return IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr);
+
+ return false;
+}
+
+// Return @c true if the IP address is IPv4-compatible IPv6 address.
+ACE_INLINE bool
+ACE_INET_Addr::is_ipv4_compat_ipv6 (void) const
+{
+ if (this->get_type () == AF_INET6)
+ return IN6_IS_ADDR_V4COMPAT (&this->inet_addr_.in6_.sin6_addr);
+
+ return false;
+}
+#endif /* ACE_HAS_IPV6 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/IOStream.cpp b/ACE/ace/IOStream.cpp
new file mode 100644
index 00000000000..23790425eeb
--- /dev/null
+++ b/ACE/ace/IOStream.cpp
@@ -0,0 +1,665 @@
+// $Id$
+
+#ifndef ACE_IOSTREAM_CPP
+#define ACE_IOSTREAM_CPP
+
+#include "ace/IOStream.h"
+
+ACE_RCSID(ace, IOStream, "$Id$")
+
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
+# include "ace/OS_NS_errno.h"
+# include "ace/OS_Memory.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+/* 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_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_ = 0;
+
+ 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_ (0)
+{
+ (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 0;
+ 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 0;
+ 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_LACKS_ACE_IOSTREAM */
+#endif /* ACE_IOSTREAM_CPP */
diff --git a/ACE/ace/IOStream.h b/ACE/ace/IOStream.h
new file mode 100644
index 00000000000..c8b3f00c541
--- /dev/null
+++ b/ACE/ace/IOStream.h
@@ -0,0 +1,512 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Needed on Windows for streambuf
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+// 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)
+
+# if defined (ACE_HAS_STRING_CLASS)
+# if defined (ACE_WIN32) && defined (_MSC_VER)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef CString ACE_IOStream_String;
+ACE_END_VERSIONED_NAMESPACE_DECL
+# else
+# if !defined (ACE_HAS_STDCPP_STL_INCLUDES)
+#include /**/ <String.h>
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef String ACE_IOStream_String;
+ACE_END_VERSIONED_NAMESPACE_DECL
+# else
+# include /**/ <string>
+
+# if defined(ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef std::string ACE_IOStream_String;
+ACE_END_VERSIONED_NAMESPACE_DECL
+# else
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef string ACE_IOStream_String;
+ACE_END_VERSIONED_NAMESPACE_DECL
+# 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 bool 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) */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# endif /* ACE_HAS_STRING_CLASS */
+
+# include "ace/Time_Value.h"
+# include "ace/os_include/sys/os_types.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 = 0);
+
+ /**
+ * 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 = 0,
+ 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 = 0,
+ 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 c = 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 = 0) = 0;
+ virtual ssize_t recv (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value *tv = 0) = 0;
+ virtual ssize_t recv_n (char *buf,
+ ssize_t len,
+ int flags = 0,
+ ACE_Time_Value *tv = 0) = 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 */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+///////////////////////////////////////////////////////////////////////////
+
+// 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 (__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
+#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 (__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
+#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_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
+ #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)
+
+ #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/ace/IOStream_T.cpp b/ACE/ace/IOStream_T.cpp
new file mode 100644
index 00000000000..082274256fe
--- /dev/null
+++ b/ACE/ace/IOStream_T.cpp
@@ -0,0 +1,247 @@
+// $Id$
+
+#ifndef ACE_IOSTREAM_T_CPP
+#define ACE_IOSTREAM_T_CPP
+
+#include "ace/IOStream_T.h"
+#include "ace/OS_Memory.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/IOStream_T.inl"
+#endif /* !__ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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 */
+}
+
+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;
+}
+
+// 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_STRING_CLASS */
+#endif /* ACE_LACKS_ACE_IOSTREAM */
+#endif /* ACE_IOSTREAM_T_CPP */
diff --git a/ACE/ace/IOStream_T.h b/ACE/ace/IOStream_T.h
new file mode 100644
index 00000000000..9bf90cee122
--- /dev/null
+++ b/ACE/ace/IOStream_T.h
@@ -0,0 +1,297 @@
+/* -*- 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/Global_Macros.h"
+
+# if defined (ACE_LACKS_IOSTREAM_FX)
+# include "ace/os_include/os_ctype.h"
+# endif /**/
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# 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 = 0);
+
+ virtual ssize_t recv (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value * tv = 0);
+
+ virtual ssize_t recv_n (char *buf,
+ ssize_t len,
+ int flags = 0,
+ ACE_Time_Value *tv = 0);
+
+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 @a 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 = 0);
+ ssize_t recv (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value *tv = 0);
+ ssize_t recv_n (char *buf,
+ ssize_t len,
+ int flags = 0,
+ ACE_Time_Value *tv = 0);
+ int get_remote_addr (ACE_INET_Addr &addr) const;
+
+protected:
+ ACE_INET_Addr peer_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (__ACE_INLINE__)
+# include "ace/IOStream_T.inl"
+# 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/ace/IOStream_T.inl b/ACE/ace/IOStream_T.inl
new file mode 100644
index 00000000000..12cf0fcffbf
--- /dev/null
+++ b/ACE/ace/IOStream_T.inl
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Handle_Set.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_sys_select.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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)
+{
+ //FUZZ: disable check_for_lack_ACE_OS
+ return recv (buf, len, 0, tv);
+ //FUZZ: enable check_for_lack_ACE_OS
+}
+
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/IO_Cntl_Msg.cpp b/ACE/ace/IO_Cntl_Msg.cpp
new file mode 100644
index 00000000000..9d64f05dd66
--- /dev/null
+++ b/ACE/ace/IO_Cntl_Msg.cpp
@@ -0,0 +1,51 @@
+// $Id$
+
+#include "ace/IO_Cntl_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/IO_Cntl_Msg.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, IO_Cntl_Msg, "$Id$")
+
+#if 0
+// This is not meant to be used, it's just a place holder...
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Intrusive_List.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl
+template <class SYNCH> class ACE_Module;
+
+/**
+ * @class ACE_Module_Link
+ *
+ * @brief Data structure used to link two modules together
+ */
+class ACE_Module_Link
+{
+public:
+ ACE_Module_Link (ACE_Module *m1, ACE_Module *m2): mod_upper_ (m1), mod_lower_ (m2), count_ (0) {}
+
+ ACE_Module *upper (void) { return this->mod_upper_; }
+ void upper (ACE_Module *u) { this->mod_upper_ = u; }
+
+ ACE_Module *lower (void) { return this->mod_lower_; }
+ void lower (ACE_Module *l) { this->mod_lower_ = l; }
+
+ int count (void) const { return this->count_; }
+ void count (int c) { this->count_ = c; }
+
+private:
+ ACE_Module *mod_upper_;
+ ACE_Module *mod_lower_;
+ int count_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif
+
diff --git a/ACE/ace/IO_Cntl_Msg.h b/ACE/ace/IO_Cntl_Msg.h
new file mode 100644
index 00000000000..7101284c9f7
--- /dev/null
+++ b/ACE/ace/IO_Cntl_Msg.h
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file IO_Cntl_Msg.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//==========================================================================
+
+
+#ifndef ACE_IO_CNTL_MSG_H
+#define ACE_IO_CNTL_MSG_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/os_include/os_stddef.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_IO_Cntl_Msg
+ *
+ * @brief Data format for IOCTL messages
+ */
+class ACE_Export ACE_IO_Cntl_Msg
+{
+public:
+ enum
+ {
+ /// Set the low water mark.
+ SET_LWM = 1,
+ /// Get the low water mark.
+ GET_LWM = 2,
+ /// Set the high water mark.
+ SET_HWM = 3,
+ /// Get the high water mark.
+ GET_HWM = 4,
+ /// Link modules
+ MOD_LINK = 5,
+ /// Unlink modules
+ MOD_UNLINK = 6
+ };
+
+ typedef unsigned short ACE_IO_Cntl_Cmds;
+
+ // = Initialization method.
+ /// Initialize the control message.
+ ACE_IO_Cntl_Msg (ACE_IO_Cntl_Cmds c);
+
+ // = Get/set methods
+
+ /// Get command.
+ ACE_IO_Cntl_Cmds cmd (void);
+
+ /// Set command.
+ void cmd (ACE_IO_Cntl_Cmds c);
+
+ /// Get count.
+ size_t count (void);
+
+ /// Set count.
+ void count (size_t c);
+
+ /// Get error.
+ int error (void);
+
+ /// Set error.
+ void error (int e);
+
+ /// Get return value.
+ int rval (void);
+
+ /// Set return value.
+ void rval (int r);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Command.
+ ACE_IO_Cntl_Cmds cmd_;
+
+ /// Count.
+ size_t count_;
+
+ /// Error.
+ int error_;
+
+ /// Return value
+ int rval_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/IO_Cntl_Msg.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_IO_CNTL_MSG_H */
diff --git a/ACE/ace/IO_Cntl_Msg.inl b/ACE/ace/IO_Cntl_Msg.inl
new file mode 100644
index 00000000000..0fbf4190f35
--- /dev/null
+++ b/ACE/ace/IO_Cntl_Msg.inl
@@ -0,0 +1,61 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_IO_Cntl_Msg::ACE_IO_Cntl_Msg (ACE_IO_Cntl_Cmds c)
+{
+ this->cmd_ = c;
+}
+
+ACE_INLINE ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds
+ACE_IO_Cntl_Msg::cmd (void)
+{
+ return this->cmd_;
+}
+
+ACE_INLINE void
+ACE_IO_Cntl_Msg::cmd (ACE_IO_Cntl_Cmds c)
+{
+ this->cmd_ = c;
+}
+
+ACE_INLINE size_t
+ACE_IO_Cntl_Msg::count (void)
+{
+ return this->count_;
+}
+
+ACE_INLINE void
+ACE_IO_Cntl_Msg::count (size_t c)
+{
+ this->count_ = c;
+}
+
+ACE_INLINE int
+ACE_IO_Cntl_Msg::error (void)
+{
+ return this->error_;
+}
+
+ACE_INLINE void
+ACE_IO_Cntl_Msg::error (int e)
+{
+ this->error_ = e;
+}
+
+ACE_INLINE int
+ACE_IO_Cntl_Msg::rval (void)
+{
+ return this->rval_;
+}
+
+ACE_INLINE void
+ACE_IO_Cntl_Msg::rval (int r)
+{
+ this->rval_ = r;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/IO_SAP.cpp b/ACE/ace/IO_SAP.cpp
new file mode 100644
index 00000000000..0e3e2ea73dc
--- /dev/null
+++ b/ACE/ace/IO_SAP.cpp
@@ -0,0 +1,142 @@
+// $Id$
+
+#include "ace/IO_SAP.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/os_include/os_signal.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/IO_SAP.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, IO_SAP, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_IO_SAP::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("handle_ = %d"), this->handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\npid_ = %d"), this->pid_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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 ();
+
+ 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::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::set_flags (this->handle_,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_IO_SAP::disable (int value) const
+{
+ ACE_TRACE ("ACE_IO_SAP::disable");
+
+ 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::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::clr_flags (this->handle_,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/IO_SAP.h b/ACE/ace/IO_SAP.h
new file mode 100644
index 00000000000..cea8213e177
--- /dev/null
+++ b/ACE/ace/IO_SAP.h
@@ -0,0 +1,96 @@
+// -*- 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"
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a 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 @a 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/IO_SAP.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_IO_SAP_H */
diff --git a/ACE/ace/IO_SAP.inl b/ACE/ace/IO_SAP.inl
new file mode 100644
index 00000000000..9d7d244e4db
--- /dev/null
+++ b/ACE/ace/IO_SAP.inl
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_stropts.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_IO_SAP::~ACE_IO_SAP (void)
+{
+ ACE_TRACE ("ACE_IO_SAP::~ACE_IO_SAP");
+}
+
+// Used to return the underlying handle_.
+
+ACE_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_.
+
+ACE_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.
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/IPC_SAP.cpp b/ACE/ace/IPC_SAP.cpp
new file mode 100644
index 00000000000..b9ef15c6002
--- /dev/null
+++ b/ACE/ace/IPC_SAP.cpp
@@ -0,0 +1,193 @@
+// $Id$
+
+#include "ace/IPC_SAP.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/os_include/os_signal.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_fcntl.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/IPC_SAP.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, IPC_SAP, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_IPC_SAP)
+
+void
+ACE_IPC_SAP::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_IPC_SAP::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("handle_ = %d"), this->handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\npid_ = %d"), this->pid_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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 (ACE_VXWORKS)
+ switch (value)
+ {
+ case ACE_NONBLOCK:
+ {
+ // nonblocking argument (1)
+ // blocking: (0)
+ int nonblock = 1;
+ return ACE_OS::ioctl (this->handle_,
+ FIONBIO,
+ &nonblock);
+ }
+ default:
+ ACE_NOTSUP_RETURN (-1);
+ }
+#else /* ! ACE_WIN32 && ! ACE_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::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::set_flags (this->handle_,
+ ACE_NONBLOCK) == ACE_INVALID_HANDLE)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+#endif /* ! ACE_WIN32 && ! ACE_VXWORKS */
+
+ /* NOTREACHED */
+}
+
+int
+ACE_IPC_SAP::disable (int value) const
+{
+ ACE_TRACE ("ACE_IPC_SAP::disable");
+
+#if defined (ACE_WIN32) || defined (ACE_VXWORKS)
+ switch (value)
+ {
+ case ACE_NONBLOCK:
+ // nonblocking argument (1)
+ // blocking: (0)
+ {
+ int nonblock = 0;
+ return ACE_OS::ioctl (this->handle_,
+ FIONBIO,
+ &nonblock);
+ }
+ default:
+ ACE_NOTSUP_RETURN (-1);
+ }
+#else /* ! ACE_WIN32 && ! ACE_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::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::clr_flags (this->handle_,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+#endif /* ! ACE_WIN32 && ! ACE_VXWORKS */
+ /* NOTREACHED */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/IPC_SAP.h b/ACE/ace/IPC_SAP.h
new file mode 100644
index 00000000000..1fd38007e43
--- /dev/null
+++ b/ACE/ace/IPC_SAP.h
@@ -0,0 +1,96 @@
+// -*- 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"
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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:
+
+ /// 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 @a 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 @a 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);
+
+ /// Protected destructor.
+ /**
+ * Not a virtual destructor. Protected destructor to prevent
+ * operator delete() from being called through a base class
+ * ACE_IPC_SAP pointer/reference.
+ */
+ ~ACE_IPC_SAP (void);
+
+private:
+ /// Underlying I/O handle.
+ ACE_HANDLE handle_;
+
+ /// Cache the process ID.
+ static pid_t pid_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/IPC_SAP.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_IPC_SAP_H */
diff --git a/ACE/ace/IPC_SAP.inl b/ACE/ace/IPC_SAP.inl
new file mode 100644
index 00000000000..0adcb6e9b09
--- /dev/null
+++ b/ACE/ace/IPC_SAP.inl
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_stropts.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_IPC_SAP::~ACE_IPC_SAP (void)
+{
+ // ACE_TRACE ("ACE_IPC_SAP::~ACE_IPC_SAP");
+}
+
+ACE_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_.
+
+ACE_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.
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/If_Then_Else.h b/ACE/ace/If_Then_Else.h
new file mode 100644
index 00000000000..163219e206b
--- /dev/null
+++ b/ACE/ace/If_Then_Else.h
@@ -0,0 +1,89 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file If_Then_Else.h
+ *
+ * @c ACE::If_Then_Else traits template based on the @c IfThenElse
+ * template described in the book "C++ Templates" by Vandevoorde and
+ * Josuttis.
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@dre.vanderbilt.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_IF_THEN_ELSE_H
+#define ACE_IF_THEN_ELSE_H
+
+#include "ace/config-lite.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE
+{
+
+ /**
+ * @struct If_Then_Else
+ *
+ * @brief Compile-time selection of type based on a boolean value.
+ *
+ * This primary template selects the second or third argument based
+ * on the value of the boolean first argument.
+ *
+ * Usage example:
+ *
+ * \code
+ *
+ * template <typename T>
+ * class Foo
+ * {
+ * public:
+ * // Set "TheType" to be the larger of "T" and "int".
+ * typedef typename If_Then_Else<(sizeof (T) > sizeof (int)),
+ * T,
+ * int>::result_type TheType;
+ * };
+ *
+ * \endcode
+ *
+ * @note This merely a forward declaration since we really only care
+ * about the partial specializations below.
+ */
+ template <bool C, typename Ta, typename Tb>
+ struct If_Then_Else;
+
+ /**
+ * @struct If_Then_Else
+ *
+ * @brief Select of type @a Ta if boolean value is @c true.
+ *
+ * This partial specialization selects the type @a Ta if the boolean
+ * first argument is @c true.
+ */
+ template <typename Ta, typename Tb>
+ struct If_Then_Else<true, Ta, Tb>
+ {
+ typedef Ta result_type;
+ };
+
+ /**
+ * @struct If_Then_Else
+ *
+ * @brief Select of type @a Tb if boolean value is @c false.
+ *
+ * This partial specialization selects the type @a Tb if the boolean
+ * first argument is @c false.
+ */
+ template <typename Ta, typename Tb>
+ struct If_Then_Else<false, Ta, Tb>
+ {
+ typedef Tb result_type;
+ };
+
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_IF_THEN_ELSE_H */
diff --git a/ACE/ace/Init_ACE.cpp b/ACE/ace/Init_ACE.cpp
new file mode 100644
index 00000000000..f997c09d4f8
--- /dev/null
+++ b/ACE/ace/Init_ACE.cpp
@@ -0,0 +1,45 @@
+#include "ace/Init_ACE.h"
+
+#include "ace/Object_Manager.h"
+
+ACE_RCSID (ace,
+ Init_ACE,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+unsigned int ACE::init_fini_count_ = 0;
+
+int
+ACE::init (void)
+{
+ // Don't use ACE_TRACE, because Object_Manager might not have been
+ // instantiated yet.
+ // ACE_TRACE ("ACE::init");
+
+ ++ACE::init_fini_count_;
+
+ return ACE_Object_Manager::instance ()->init ();
+}
+
+int
+ACE::fini (void)
+{
+ ACE_TRACE ("ACE::fini");
+
+ if (ACE::init_fini_count_ > 0)
+ {
+ if (--ACE::init_fini_count_ == 0)
+ return ACE_Object_Manager::instance ()->fini ();
+ else
+ // Wait for remaining fini () calls.
+ return 1;
+ }
+ else
+ // More ACE::fini () calls than ACE::init () calls. Bad
+ // application!
+ return -1;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Init_ACE.h b/ACE/ace/Init_ACE.h
new file mode 100644
index 00000000000..164f61e1d70
--- /dev/null
+++ b/ACE/ace/Init_ACE.h
@@ -0,0 +1,62 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Init_ACE.h
+ *
+ * $Id$
+ *
+ * Initialize ACE library services. Can be called only once per
+ * program invocation.
+ */
+//=============================================================================
+
+
+#ifndef ACE_INIT_ACE_H
+#define ACE_INIT_ACE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE
+{
+ /**
+ * This class implements the functions for the initialization and
+ * shutting down ACE. These functions are called only once per ACE
+ * invokation.
+ * @return Returns 0 on success, -1 on failure, and 1 if it had already been
+ * called.
+ */
+ extern ACE_Export int init (void);
+
+ /**
+ * Shut down ACE library services. Can be called only once per
+ * program invocation.
+ * @return Returns 0 on success, -1 on failure, and 1 if it had already been
+ * called.
+ */
+ extern ACE_Export int fini (void);
+
+ // private:
+ // Used internally, so not exported.
+
+ /**
+ * Counter to match <init()>/<fini()> calls. <init()> must increment it;
+ * <fini()> must decrement it. <fini()> then does nothing until it
+ * reaches 0.
+ */
+ extern unsigned int init_fini_count_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_INIT_ACE_H */
diff --git a/ACE/ace/Intrusive_List.cpp b/ACE/ace/Intrusive_List.cpp
new file mode 100644
index 00000000000..c0006792ce4
--- /dev/null
+++ b/ACE/ace/Intrusive_List.cpp
@@ -0,0 +1,153 @@
+// $Id$
+
+#ifndef ACE_INTRUSIVE_LIST_CPP
+#define ACE_INTRUSIVE_LIST_CPP
+
+#include "ace/Intrusive_List.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Intrusive_List.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T>
+ACE_Intrusive_List<T>::ACE_Intrusive_List (void)
+ : head_ (0)
+ , tail_ (0)
+{
+}
+
+template<class T>
+ACE_Intrusive_List<T>::~ACE_Intrusive_List (void)
+{
+}
+
+template<class T> void
+ACE_Intrusive_List<T>::push_back (T *node)
+{
+ if (this->tail_ == 0)
+ {
+ this->tail_ = node;
+ this->head_ = node;
+ node->next (0);
+ node->prev (0);
+ return;
+ }
+
+ this->tail_->next (node);
+ node->prev (this->tail_);
+ node->next (0);
+ this->tail_ = node;
+}
+
+template<class T> void
+ACE_Intrusive_List<T>::push_front (T *node)
+{
+ if (this->head_ == 0)
+ {
+ this->tail_ = node;
+ this->head_ = node;
+ node->next (0);
+ node->prev (0);
+ return;
+ }
+
+ this->head_->prev (node);
+ node->next (this->head_);
+ node->prev (0);
+ this->head_ = node;
+}
+
+template<class T> T *
+ACE_Intrusive_List<T>::pop_front (void)
+{
+ T *node = this->head_;
+ if (node == 0)
+ return 0;
+ this->unsafe_remove (node);
+ return node;
+}
+
+template<class T> T *
+ACE_Intrusive_List<T>::pop_back (void)
+{
+ T *node = this->tail_;
+ if (node == 0)
+ return 0;
+ this->unsafe_remove (node);
+ return node;
+}
+
+template<class T> void
+ACE_Intrusive_List<T>::remove (T *node)
+{
+ for (T *i = this->head_; i != 0; i = i->next ())
+ {
+ if (node == i)
+ {
+ this->unsafe_remove (node);
+ return;
+ }
+ }
+}
+
+template<class T> void
+ACE_Intrusive_List<T>::unsafe_remove (T *node)
+{
+ if (node->prev () != 0)
+ node->prev ()->next (node->next ());
+ else
+ this->head_ = node->next ();
+
+ if (node->next () != 0)
+ node->next ()->prev (node->prev ());
+ else
+ this->tail_ = node->prev ();
+
+ node->next (0);
+ node->prev (0);
+}
+
+#if 0
+template<class T> void
+ACE_Intrusive_List_Node<T>::check_invariants (void)
+{
+ ACE_ASSERT ((this->next () == 0) || (this->next ()->prev () == this));
+ ACE_ASSERT ((this->prev () == 0) || (this->prev ()->next () == this));
+}
+
+template<class T> void
+ACE_Intrusive_List<T>::check_invariants (void)
+{
+ ACE_ASSERT ((this->tail_ == 0) || (this->tail_->next () == 0));
+ ACE_ASSERT ((this->head_ == 0) || (this->head_->prev () == 0));
+ ACE_ASSERT (!((this->head_ == 0) ^ (this->tail_ == 0)));
+
+ int found_tail = 0;
+ for (T *i = this->head_; i != 0; i = i->next ())
+ {
+ if (i == this->tail_)
+ found_tail = 1;
+ i->check_invariants ();
+ }
+ ACE_ASSERT (this->tail_ == 0 || found_tail == 1);
+
+ int found_head = 0;
+ for (T *j = this->tail_; j != 0; j = j->prev ())
+ {
+ if (j == this->head_)
+ found_head = 1;
+ j->check_invariants ();
+ }
+ ACE_ASSERT (this->head_ == 0 || found_head == 1);
+}
+#endif /* 0 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_INTRUSIVE_LIST_CPP */
diff --git a/ACE/ace/Intrusive_List.h b/ACE/ace/Intrusive_List.h
new file mode 100644
index 00000000000..59d0c9054a8
--- /dev/null
+++ b/ACE/ace/Intrusive_List.h
@@ -0,0 +1,144 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Intrusive_List.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_INTRUSIVE_LIST_H
+#define ACE_INTRUSIVE_LIST_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Intrusive_List
+ *
+ * @brief Implement an intrusive double linked list
+ *
+ * Intrusive lists assume that the elements they contain the pointers
+ * required to build the list. They are useful as light-weight
+ * containers and free-lists.
+ *
+ * The template argument T must implement the following methods:
+ *
+ * - T* T::next () const;
+ * - void T::next (T *);
+ * - T* T::prev () const;
+ * - void T::prev (T* );
+ *
+ * A simple way to satisfy the Intrusive_List requirements would be to
+ * implement a helper class:
+ *
+ * class My_Object : public ACE_Intrusive_List_Node<My_Object> {<BR>
+ * ....<BR>
+ * };<BR>
+ *
+ * typedef ACE_Intrusive_List<My_Object> My_Object_List;
+ *
+ * However, ACE is supported on platforms that would surely get
+ * confused using such templates.
+ *
+ * @todo The ACE_Message_Queue is an example of an intrusive list (or
+ * queue) but it is not implemented in terms of this class.
+ *
+ */
+template <class T>
+class ACE_Intrusive_List
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor. Use user specified allocation strategy
+ /// if specified.
+ ACE_Intrusive_List (void);
+
+ /// Destructor.
+ ~ACE_Intrusive_List (void);
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ int is_empty (void) const;
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ /// @deprecated Use is_empty() instead.
+ int empty (void) const;
+
+ /// Insert an element at the beginning of the list
+ void push_front (T *node);
+
+ /// Insert an element at the end of the list
+ void push_back (T *node);
+
+ /// Remove the element at the beginning of the list
+ T *pop_front (void);
+
+ /// Remove the element at the end of the list
+ T *pop_back (void);
+
+ /// Get the element at the head of the queue
+ T *head (void) const;
+
+ /// Get the element at the tail of the queue
+ T *tail (void) const;
+
+ /// Remove a element from the list
+ /**
+ * Verify that the element is still in the list before removing it.
+ */
+ void remove (T *node);
+
+ /// Swap two lists
+ void swap(ACE_Intrusive_List<T> & rhs);
+
+ /// Remove a element from the list without checking
+ /**
+ * No attempts are performed to check if T* really belongs to the
+ * list. The effects of removing an invalid element are unspecified
+ */
+ void unsafe_remove (T *node);
+
+private:
+ /** @name Disallow copying
+ *
+ */
+ //@{
+ ACE_Intrusive_List (const ACE_Intrusive_List<T> &);
+ ACE_Intrusive_List<T>& operator= (const ACE_Intrusive_List<T> &);
+ //@}
+
+private:
+ /// Head of the list
+ T *head_;
+
+ /// Tail of the list
+ T *tail_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Intrusive_List.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Intrusive_List.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Intrusive_List.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_INTRUSIVE_LIST_H */
diff --git a/ACE/ace/Intrusive_List.inl b/ACE/ace/Intrusive_List.inl
new file mode 100644
index 00000000000..f76370917e9
--- /dev/null
+++ b/ACE/ace/Intrusive_List.inl
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include <algorithm>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class T> ACE_INLINE int
+ACE_Intrusive_List<T>::is_empty (void) const
+{
+ return this->head_ == 0;
+}
+
+template<class T> ACE_INLINE int
+ACE_Intrusive_List<T>::empty (void) const
+{
+ return this->is_empty ();
+}
+
+template<class T> ACE_INLINE T *
+ACE_Intrusive_List<T>::head (void) const
+{
+ return this->head_;
+}
+
+template<class T> ACE_INLINE T *
+ACE_Intrusive_List<T>::tail (void) const
+{
+ return this->tail_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Intrusive_List<T>::swap(ACE_Intrusive_List<T> & rhs)
+{
+ std::swap(head_, rhs.head_);
+ std::swap(tail_, rhs.tail_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Intrusive_List_Node.cpp b/ACE/ace/Intrusive_List_Node.cpp
new file mode 100644
index 00000000000..cd39a0cc91e
--- /dev/null
+++ b/ACE/ace/Intrusive_List_Node.cpp
@@ -0,0 +1,27 @@
+// $Id$
+
+#ifndef ACE_INTRUSIVE_LIST_NODE_CPP
+#define ACE_INTRUSIVE_LIST_NODE_CPP
+
+#include "ace/Intrusive_List_Node.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Intrusive_List_Node.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class T>
+ACE_Intrusive_List_Node<T>::ACE_Intrusive_List_Node (void)
+ : prev_ (0)
+ , next_ (0)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_INTRUSIVE_LIST_NODE_CPP */
diff --git a/ACE/ace/Intrusive_List_Node.h b/ACE/ace/Intrusive_List_Node.h
new file mode 100644
index 00000000000..b62d681a047
--- /dev/null
+++ b/ACE/ace/Intrusive_List_Node.h
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Intrusive_List_Node.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_INTRUSIVE_LIST_NODE_H
+#define ACE_INTRUSIVE_LIST_NODE_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Intrusive_List_Node
+ *
+ * @brief Implement the requirements for ACE_Intrusive_List
+ *
+ * The class should be used as follows:
+ *
+ * class My_Object : public ACE_Intrusive_List_Node<My_Object> {<BR>
+ * ....<BR>
+ * };<BR>
+ *
+ * However, ACE is supported on platforms that would surely get
+ * confused using such templates, the class is provided as a helper
+ * for our lucky users that only need portability to modern C++
+ * compilers.
+ *
+ */
+template <class T>
+class ACE_Intrusive_List_Node
+{
+public:
+ /** @name Accesors and modifiers to the next and previous pointers
+ *
+ */
+ //@{
+ T *prev (void) const;
+ void prev (T *);
+ T *next (void) const;
+ void next (T *);
+ //@}
+
+protected:
+ /// Constructor
+ /**
+ * The constructor is protected, because only derived classes should
+ * be instantiated.
+ */
+ ACE_Intrusive_List_Node (void);
+
+private:
+ /// Head and tail of the list
+ T *prev_;
+ T *next_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Intrusive_List_Node.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Intrusive_List_Node.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Intrusive_List_Node.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_INTRUSIVE_LIST_NODE_H */
diff --git a/ACE/ace/Intrusive_List_Node.inl b/ACE/ace/Intrusive_List_Node.inl
new file mode 100644
index 00000000000..0672be2f345
--- /dev/null
+++ b/ACE/ace/Intrusive_List_Node.inl
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class T> ACE_INLINE T*
+ACE_Intrusive_List_Node<T>::prev (void) const
+{
+ return this->prev_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Intrusive_List_Node<T>::prev (T *x)
+{
+ this->prev_ = x;
+}
+
+template<class T> ACE_INLINE T*
+ACE_Intrusive_List_Node<T>::next (void) const
+{
+ return this->next_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Intrusive_List_Node<T>::next (T *x)
+{
+ this->next_ = x;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/LOCK_SOCK_Acceptor.cpp b/ACE/ace/LOCK_SOCK_Acceptor.cpp
new file mode 100644
index 00000000000..183338b7efa
--- /dev/null
+++ b/ACE/ace/LOCK_SOCK_Acceptor.cpp
@@ -0,0 +1,35 @@
+// $Id$
+
+#ifndef ACE_LOCK_SOCK_ACCEPTOR_CPP
+#define ACE_LOCK_SOCK_ACCEPTOR_CPP
+
+#include "ace/Guard_T.h"
+#include "ace/LOCK_SOCK_Acceptor.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LOCK_SOCK_ACCEPTOR_CPP */
diff --git a/ACE/ace/LOCK_SOCK_Acceptor.h b/ACE/ace/LOCK_SOCK_Acceptor.h
new file mode 100644
index 00000000000..cfca422e8d7
--- /dev/null
+++ b/ACE/ace/LOCK_SOCK_Acceptor.h
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#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/ace/LSOCK.cpp b/ACE/ace/LSOCK.cpp
new file mode 100644
index 00000000000..71f93fdde9c
--- /dev/null
+++ b/ACE/ace/LSOCK.cpp
@@ -0,0 +1,181 @@
+// $Id$
+
+#include "ace/LSOCK.h"
+
+ACE_RCSID(ace, LSOCK, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_socket.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/LSOCK.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK)
+
+void
+ACE_LSOCK::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_LSOCK::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("aux_handle_ = %d"), this->aux_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+#if defined (ACE_HAS_MSG)
+// This routine sends an open file descriptor to <this->handle_>.
+
+ssize_t
+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.
+
+ssize_t
+ACE_LSOCK::recv_handle (ACE_HANDLE &handle, char *pbuf, ssize_t *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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/ace/LSOCK.h b/ACE/ace/LSOCK.h
new file mode 100644
index 00000000000..994158f00d3
--- /dev/null
+++ b/ACE/ace/LSOCK.h
@@ -0,0 +1,84 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LSOCK.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCAL_SOCK_H
+#define ACE_LOCAL_SOCK_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/SOCK.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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.
+ ssize_t send_handle (const ACE_HANDLE handle) const;
+
+ /// Recv an open FD from another process.
+ ssize_t recv_handle (ACE_HANDLE &handles,
+ char *pbuf = 0,
+ ssize_t *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 @a 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/LSOCK.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_H */
diff --git a/ACE/ace/LSOCK.inl b/ACE/ace/LSOCK.inl
new file mode 100644
index 00000000000..5dbbb0626a1
--- /dev/null
+++ b/ACE/ace/LSOCK.inl
@@ -0,0 +1,43 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Simple-minded constructor.
+
+ACE_INLINE
+ACE_LSOCK::ACE_LSOCK (void)
+ : aux_handle_ (ACE_INVALID_HANDLE)
+{
+ ACE_TRACE ("ACE_LSOCK::ACE_LSOCK");
+}
+
+// Sets the underlying file descriptor.
+
+ACE_INLINE void
+ACE_LSOCK::set_handle (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_LSOCK::set_handle");
+ this->aux_handle_ = handle;
+}
+
+// Gets the underlying file descriptor.
+
+ACE_INLINE ACE_HANDLE
+ACE_LSOCK::get_handle (void) const
+{
+ ACE_TRACE ("ACE_LSOCK::get_handle");
+ return this->aux_handle_;
+}
+
+// Sets the underlying file descriptor.
+
+ACE_INLINE
+ACE_LSOCK::ACE_LSOCK (ACE_HANDLE handle)
+ : aux_handle_ (handle)
+{
+ ACE_TRACE ("ACE_LSOCK::ACE_LSOCK");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/LSOCK_Acceptor.cpp b/ACE/ace/LSOCK_Acceptor.cpp
new file mode 100644
index 00000000000..ee154e3e087
--- /dev/null
+++ b/ACE/ace/LSOCK_Acceptor.cpp
@@ -0,0 +1,143 @@
+// $Id$
+
+#include "ace/LSOCK_Acceptor.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_RCSID(ace, LSOCK_Acceptor, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 = dynamic_cast<ACE_UNIX_Addr &> (a);
+
+ target = this->local_addr_;
+
+ return 0;
+}
+
+void
+ACE_LSOCK_Acceptor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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));
+#endif /* ACE_HAS_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/ace/LSOCK_Acceptor.h b/ACE/ace/LSOCK_Acceptor.h
new file mode 100644
index 00000000000..a215736355e
--- /dev/null
+++ b/ACE/ace/LSOCK_Acceptor.h
@@ -0,0 +1,95 @@
+/* -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/LSOCK_Stream.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_ACCEPTOR_H */
diff --git a/ACE/ace/LSOCK_CODgram.cpp b/ACE/ace/LSOCK_CODgram.cpp
new file mode 100644
index 00000000000..e89607e06ac
--- /dev/null
+++ b/ACE/ace/LSOCK_CODgram.cpp
@@ -0,0 +1,62 @@
+// $Id$
+
+#include "ace/LSOCK_CODgram.h"
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, LSOCK_CODgram, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/LSOCK_CODgram.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_CODgram)
+
+void
+ACE_LSOCK_CODgram::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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));
+#endif /* ACE_HAS_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_TEXT ("%p\n"), ACE_TEXT ("ACE_LSOCK_CODgram")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/ace/LSOCK_CODgram.h b/ACE/ace/LSOCK_CODgram.h
new file mode 100644
index 00000000000..667fa210f0d
--- /dev/null
+++ b/ACE/ace/LSOCK_CODgram.h
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LSOCK_CODgram.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCAL_SOCK_CODGRAM_H
+#define ACE_LOCAL_SOCK_CODGRAM_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_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/LSOCK.h"
+#include "ace/SOCK_CODgram.h"
+#include "ace/Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/LSOCK_CODgram.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_CODGRAM_H */
diff --git a/ACE/ace/LSOCK_CODgram.inl b/ACE/ace/LSOCK_CODgram.inl
new file mode 100644
index 00000000000..d27ee2fd881
--- /dev/null
+++ b/ACE/ace/LSOCK_CODgram.inl
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Do nothing constructor.
+
+ACE_INLINE
+ACE_LSOCK_CODgram::ACE_LSOCK_CODgram (void)
+{
+ ACE_TRACE ("ACE_LSOCK_CODgram::ACE_LSOCK_CODgram");
+}
+
+ACE_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);
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_LSOCK_CODgram::get_handle (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_CODgram::get_handle");
+ return this->ACE_SOCK_CODgram::get_handle ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/LSOCK_Connector.cpp b/ACE/ace/LSOCK_Connector.cpp
new file mode 100644
index 00000000000..319670f903f
--- /dev/null
+++ b/ACE/ace/LSOCK_Connector.cpp
@@ -0,0 +1,59 @@
+// $Id$
+
+#include "ace/LSOCK_Connector.h"
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, LSOCK_Connector, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/LSOCK_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Connector)
+
+void
+ACE_LSOCK_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_LSOCK_Connector::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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)
+ : ACE_SOCK_Connector (new_stream,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms)
+{
+ 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 ());
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/ace/LSOCK_Connector.h b/ACE/ace/LSOCK_Connector.h
new file mode 100644
index 00000000000..336fc4a0e77
--- /dev/null
+++ b/ACE/ace/LSOCK_Connector.h
@@ -0,0 +1,91 @@
+// -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/SOCK_Connector.h"
+#include "ace/LSOCK_Stream.h"
+#include "ace/UNIX_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a new_stream if things go well.
+ * All arguments are relayed to the ACE_SOCK_Connector constructor
+ * for handling.
+ * @see ACE_SOCK_Connector().
+ */
+ 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);
+
+ /**
+ * Actively connect and produce a @a new_stream if things go well.
+ * The @c ACE_SOCK_Connector::connect() method is called to perform
+ * the actual connection attempt.
+ * @see ACE_SOCK_Connector::connect().
+ */
+ 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);
+
+ // = 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/LSOCK_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_CONNECTOR_H */
diff --git a/ACE/ace/LSOCK_Connector.inl b/ACE/ace/LSOCK_Connector.inl
new file mode 100644
index 00000000000..f9cdffbf6dc
--- /dev/null
+++ b/ACE/ace/LSOCK_Connector.inl
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Establish a connection.
+ACE_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)
+{
+ ACE_TRACE ("ACE_LSOCK_Connector::connect");
+ int result = ACE_SOCK_Connector::connect (new_stream, remote_sap,
+ timeout, local_sap,
+ reuse_addr, flags, perms);
+ 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/LSOCK_Dgram.cpp b/ACE/ace/LSOCK_Dgram.cpp
new file mode 100644
index 00000000000..268ce44eb36
--- /dev/null
+++ b/ACE/ace/LSOCK_Dgram.cpp
@@ -0,0 +1,71 @@
+// $Id$
+
+#include "ace/LSOCK_Dgram.h"
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, LSOCK_Dgram, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/LSOCK_Dgram.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Dgram)
+
+void
+ACE_LSOCK_Dgram::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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));
+#endif /* ACE_HAS_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_LSOCK_Dgram")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/ace/LSOCK_Dgram.h b/ACE/ace/LSOCK_Dgram.h
new file mode 100644
index 00000000000..d93face8cfb
--- /dev/null
+++ b/ACE/ace/LSOCK_Dgram.h
@@ -0,0 +1,74 @@
+// -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/SOCK_Dgram.h"
+#include "ace/LSOCK.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/LSOCK_Dgram.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_DGRAM_H */
diff --git a/ACE/ace/LSOCK_Dgram.inl b/ACE/ace/LSOCK_Dgram.inl
new file mode 100644
index 00000000000..2c29136e06d
--- /dev/null
+++ b/ACE/ace/LSOCK_Dgram.inl
@@ -0,0 +1,22 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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);
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_LSOCK_Dgram::get_handle (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_Dgram::get_handle");
+ return this->ACE_SOCK_Dgram::get_handle ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/LSOCK_Stream.cpp b/ACE/ace/LSOCK_Stream.cpp
new file mode 100644
index 00000000000..6ac123661cf
--- /dev/null
+++ b/ACE/ace/LSOCK_Stream.cpp
@@ -0,0 +1,137 @@
+// $Id$
+
+#include "ace/LSOCK_Stream.h"
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_RCSID(ace, LSOCK_Stream, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/LSOCK_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 = 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 = const_cast <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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/ace/LSOCK_Stream.h b/ACE/ace/LSOCK_Stream.h
new file mode 100644
index 00000000000..99d50e6dbaf
--- /dev/null
+++ b/ACE/ace/LSOCK_Stream.h
@@ -0,0 +1,82 @@
+/* -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/SOCK_Stream.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/LSOCK.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/LSOCK_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_STREAM_H */
diff --git a/ACE/ace/LSOCK_Stream.inl b/ACE/ace/LSOCK_Stream.inl
new file mode 100644
index 00000000000..bf7e45b376d
--- /dev/null
+++ b/ACE/ace/LSOCK_Stream.inl
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Sets both the file descriptors... Overrides handle from the base
+// classes.
+
+ACE_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);
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_LSOCK_Stream::get_handle (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_Stream::get_handle");
+ return this->ACE_SOCK_Stream::get_handle ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Lib_Find.cpp b/ACE/ace/Lib_Find.cpp
new file mode 100644
index 00000000000..6db6d78973b
--- /dev/null
+++ b/ACE/ace/Lib_Find.cpp
@@ -0,0 +1,769 @@
+// $Id$
+
+#include "ace/Lib_Find.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_fcntl.h"
+
+#if defined (ACE_WIN32)
+# include "ace/OS_NS_strings.h"
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_OPENVMS)
+#include "ace/RB_Tree.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Singleton.h"
+
+#include /**/ "descrip.h"
+#include /**/ "chfdef.h"
+#include /**/ "stsdef.h"
+#include /**/ "libdef.h"
+
+extern "C" int LIB$FIND_IMAGE_SYMBOL(...);
+
+class ACE_LD_Symbol_Registry
+{
+ // @internal
+ // = TITLE
+ // Implements a class to register symbols and addresses for use with DLL
+ // symbol retrieval.
+ //
+ // = DESCRIPTION
+ // OpenVMS restricts symbol length to 31 characters encoding any symbols
+ // longer than that. In these cases dlsym() only works with the encoded
+ // names.
+ // This creates serious problems for the service configurator framework
+ // where the factory method names often exceed 31 chars and where loading
+ // is based on retrieval of method pointers using the *full* name.
+ // For OpenVMS we therefor added this singleton class and the
+ // ACE_Dynamic_Svc_Registrar class which registers full names and function
+ // pointers with this singleton at the time the static ACE_Dynamic_Svc_Registrar
+ // object is created in a (service) DLL.
+ // By forcing the DLL to load using a common symbol ("NULL") we trigger static
+ // object creation *before* the full names are referenced.
+ // Symbol references will be resolved as follows on OpenVMS:
+ // - first try directly from DLL using the RTL dlsym() function and if that fails;
+ // - try to find symbol in singleton registry.
+public:
+
+ typedef ACE_RB_Tree<const ACE_TCHAR*,
+ void*,
+ ACE_Less_Than<const ACE_TCHAR*>,
+ ACE_Thread_Mutex>
+ TREE;
+
+ void register_symbol (const ACE_TCHAR* symname, void* symaddr);
+
+ void* find_symbol (const ACE_TCHAR* symname);
+
+ ACE_LD_Symbol_Registry () {}
+private:
+
+ TREE symbol_registry_;
+};
+
+void
+ACE_LD_Symbol_Registry::register_symbol (const ACE_TCHAR* symname,
+ void* symaddr)
+{
+ int const result = symbol_registry_.bind (symname, symaddr);
+ if (result == 1)
+ {
+ ACE_DEBUG((LM_INFO, ACE_TEXT ("ACE_LD_Symbol_Registry:")
+ ACE_TEXT (" duplicate symbol %s registered\n"),
+ ACE_TEXT_ALWAYS_CHAR (symname)));
+ }
+ else if (result == -1)
+ {
+ ACE_ERROR((LM_ERROR, ACE_TEXT ("ACE_LD_Symbol_Registry:")
+ ACE_TEXT (" failed to register symbol %s\n"),
+ ACE_TEXT_ALWAYS_CHAR (symname)));
+ }
+}
+
+void*
+ACE_LD_Symbol_Registry::find_symbol (const ACE_TCHAR* symname)
+{
+ void* symaddr = 0;
+ int const result = symbol_registry_.find (symname, symaddr);
+
+ return (result == 0 ? symaddr : 0);
+}
+
+/// Declare a process wide singleton
+ACE_SINGLETON_DECLARE (ACE_Singleton,
+ ACE_LD_Symbol_Registry,
+ ACE_Thread_Mutex)
+
+typedef ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex>
+ ACE_LD_SYMBOL_REGISTRY;
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex> *
+ ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+#endif
+
+ACE_RCSID(ace, Lib_Find, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE::ldfind (const ACE_TCHAR* filename,
+ ACE_TCHAR pathname[],
+ size_t maxpathnamelen)
+{
+ ACE_TRACE ("ACE::ldfind");
+#if defined (ACE_OPENVMS)
+ if (ACE_OS::strlen(filename) >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ dsc$descriptor nameDsc;
+ nameDsc.dsc$b_class = DSC$K_CLASS_S;
+ nameDsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ nameDsc.dsc$w_length = ACE_OS::strlen(filename);
+ nameDsc.dsc$a_pointer = (char*)filename;
+
+ char symbol[] = "NULL";
+ dsc$descriptor symbolDsc;
+ symbolDsc.dsc$b_class = DSC$K_CLASS_S;
+ symbolDsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ symbolDsc.dsc$w_length = ACE_OS::strlen(symbol);
+ symbolDsc.dsc$a_pointer = symbol;
+
+ int symbolValue;
+ int result;
+ try
+ {
+ result = LIB$FIND_IMAGE_SYMBOL(&nameDsc, &symbolDsc, &symbolValue, 0, 0);
+ }
+ catch (chf$signal_array& sig)
+ {
+ result = sig.chf$l_sig_name;
+ }
+
+ int severity = result & STS$M_SEVERITY;
+ int conditionId = result & STS$M_COND_ID;
+ if (severity == STS$K_SUCCESS || severity == STS$K_WARNING || severity == STS$K_INFO ||
+ (severity == STS$K_ERROR && conditionId == (LIB$_KEYNOTFOU & STS$M_COND_ID)))
+ {
+ ACE_OS::strcpy(pathname, filename);
+ return 0;
+ }
+
+ if (ACE_OS::strlen(filename) + ACE_OS::strlen(ACE_DLL_PREFIX) >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+
+ ACE_OS::strcpy(pathname, ACE_DLL_PREFIX);
+ ACE_OS::strcat(pathname, filename);
+ nameDsc.dsc$w_length = ACE_OS::strlen(pathname);
+ nameDsc.dsc$a_pointer = pathname;
+ try
+ {
+ result = LIB$FIND_IMAGE_SYMBOL(&nameDsc, &symbolDsc, &symbolValue, 0, 0);
+ }
+ catch (chf$signal_array& sig)
+ {
+ result = sig.chf$l_sig_name;
+ }
+
+ severity = result & STS$M_SEVERITY;
+ conditionId = result & STS$M_COND_ID;
+ if (severity == STS$K_SUCCESS || severity == STS$K_WARNING || severity == STS$K_INFO ||
+ (severity == STS$K_ERROR && conditionId == (LIB$_KEYNOTFOU & STS$M_COND_ID)))
+ {
+ return 0;
+ }
+ errno = ENOENT;
+ return -1;
+#endif /* ACE_OPENVMS */
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) && \
+ !defined (ACE_HAS_PHARLAP)
+ ACE_TCHAR expanded_filename[MAXPATHLEN];
+ if (ACE_TEXT_ExpandEnvironmentStrings (filename,
+ expanded_filename,
+ sizeof expanded_filename
+ / sizeof (ACE_TCHAR)))
+ filename = expanded_filename;
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE && !ACE_HAS_PHARLAP */
+
+ ACE_TCHAR tempcopy[MAXPATHLEN + 1];
+ ACE_TCHAR searchpathname[MAXPATHLEN + 1];
+#if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ ACE_TCHAR decorator[] = ACE_LD_DECORATOR_STR;
+ ACE_TCHAR searchfilename[MAXPATHLEN + sizeof(decorator) / sizeof (ACE_TCHAR)];
+#else
+ ACE_TCHAR searchfilename[MAXPATHLEN + 1];
+#endif /* ACE_WIN32 && ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
+
+ // Create a copy of filename to work with.
+ if (ACE_OS::strlen (filename) + 1
+ > (sizeof tempcopy / sizeof (ACE_TCHAR)))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else
+ ACE_OS::strcpy (tempcopy, filename);
+
+ // Insert canonical directory separators.
+ ACE_TCHAR *separator_ptr;
+
+#if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
+ // Make all the directory separators "canonical" to simplify
+ // subsequent code.
+ ACE::strrepl (tempcopy, ACE_DIRECTORY_SEPARATOR_CHAR, '/');
+#endif /* ACE_DIRECTORY_SEPARATOR_CHAR */
+
+ // Separate filename from pathname.
+ separator_ptr = ACE_OS::strrchr (tempcopy, '/');
+
+ // This is a relative path.
+ if (separator_ptr == 0)
+ {
+ searchpathname[0] = '\0';
+ ACE_OS::strcpy (searchfilename, tempcopy);
+ }
+ else // This is an absolute path.
+ {
+ ACE_OS::strcpy (searchfilename, separator_ptr + 1);
+ separator_ptr[1] = '\0';
+ ACE_OS::strcpy (searchpathname, tempcopy);
+ }
+
+ bool has_suffix = false;
+
+ // Check to see if this has an appropriate DLL suffix for the OS
+ // platform.
+ ACE_TCHAR *s = ACE_OS::strrchr (searchfilename, '.');
+
+ const ACE_TCHAR *dll_suffix = ACE_DLL_SUFFIX;
+
+ if (s != 0)
+ {
+ // If we have a dot, we have a suffix
+ has_suffix = true;
+
+ // Check whether this matches the appropriate platform-specific
+ // suffix.
+#if defined (ACE_WIN32)
+ // Use <ACE_OS::strcasecmp> on any platform with
+ // case-insensitive filenames.
+ if (ACE_OS::strcasecmp (s, dll_suffix) != 0)
+#else
+ if (ACE_OS::strcmp (s, dll_suffix) != 0)
+#endif /* ACE_WIN32 */
+ {
+ ACE_ERROR ((LM_WARNING,
+ ACE_TEXT ("Warning: improper suffix for a ")
+ ACE_TEXT ("shared library on this platform: %s\n"),
+ s));
+ }
+ }
+
+ // Make sure we've got enough space in searchfilename.
+ if (ACE_OS::strlen (searchfilename)
+ + ACE_OS::strlen (ACE_DLL_PREFIX)
+ + (has_suffix ? 0 : ACE_OS::strlen (dll_suffix))
+ >= (sizeof searchfilename / sizeof (ACE_TCHAR)))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+#if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ size_t len_searchfilename = ACE_OS::strlen (searchfilename);
+ if (! has_suffix)
+ ACE_OS::strcpy (searchfilename + len_searchfilename,
+ decorator);
+
+ for (int tag = 1; tag >= 0; tag --)
+ {
+ if (tag == 0)
+ searchfilename [len_searchfilename] = 0;
+
+#endif /* ACE_WIN32 && ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
+ // Use absolute pathname if there is one.
+ if (ACE_OS::strlen (searchpathname) > 0)
+ {
+ if (ACE_OS::strlen (searchfilename)
+ + ACE_OS::strlen (searchpathname) >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else
+ {
+#if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
+ // Revert to native path name separators.
+ ACE::strrepl (searchpathname,
+ '/',
+ ACE_DIRECTORY_SEPARATOR_CHAR);
+#endif /* ACE_DIRECTORY_SEPARATOR_CHAR */
+ // First, try matching the filename *without* adding a
+ // prefix.
+ ACE_OS::sprintf (pathname,
+ ACE_TEXT ("%s%s%s"),
+ searchpathname,
+ searchfilename,
+ has_suffix ? ACE_TEXT ("") : dll_suffix);
+ if (ACE_OS::access (pathname, F_OK) == 0)
+ return 0;
+
+ // Second, try matching the filename *with* adding a prefix.
+ ACE_OS::sprintf (pathname,
+ ACE_TEXT ("%s%s%s%s"),
+ searchpathname,
+ ACE_DLL_PREFIX,
+ searchfilename,
+ has_suffix ? ACE_TEXT ("") : dll_suffix);
+ if (ACE_OS::access (pathname, F_OK) == 0)
+ return 0;
+ }
+ }
+
+ // Use relative filenames via LD_LIBRARY_PATH or PATH (depending on
+ // OS platform).
+ else
+ {
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ ACE_TCHAR *file_component = 0;
+ DWORD pathlen =
+ ACE_TEXT_SearchPath (0,
+ searchfilename,
+ dll_suffix,
+ static_cast<DWORD> (maxpathnamelen),
+ pathname,
+ &file_component);
+ if (pathlen >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else if (pathlen > 0)
+ return 0;
+
+ // In case not found we should try again with the ACE_DLL_PREFIX
+ // prefixed
+ ACE_OS::strcpy (searchfilename, ACE_DLL_PREFIX);
+ ACE_OS::strcat (searchfilename, tempcopy);
+ pathlen =
+ ACE_TEXT_SearchPath (0,
+ searchfilename,
+ dll_suffix,
+ static_cast<DWORD> (maxpathnamelen),
+ pathname,
+ &file_component);
+ if (pathlen >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else if (pathlen > 0)
+ return 0;
+#else
+ ACE_TCHAR *ld_path;
+# if defined ACE_DEFAULT_LD_SEARCH_PATH
+ ld_path = ACE_DEFAULT_LD_SEARCH_PATH;
+# else
+# if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+ ld_path = ACE_OS::getenv (ACE_LD_SEARCH_PATH);
+# else
+ // Wide-char, non-Windows only offers char * getenv. So capture
+ // it, translate to wide-char, and continue.
+ ACE_Ascii_To_Wide wide_ldpath
+ (ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (ACE_LD_SEARCH_PATH)));
+ ld_path = wide_ldpath.wchar_rep ();
+# endif /* ACE_WIN32 || !ACE_USES_WCHAR */
+# endif /* ACE_DEFAULT_LD_SEARCH_PATH */
+
+#if defined (ACE_HAS_WINCE)
+ ACE_TCHAR *ld_path_temp = 0;
+ if (ld_path != 0)
+ {
+ ld_path_temp = (ACE_TCHAR *)
+ ACE_OS::malloc ((ACE_OS::strlen (ld_path) + 2)
+ * sizeof (ACE_TCHAR));
+ if (ld_path_temp != 0)
+ {
+ ACE_OS::strcpy (ld_path_temp,
+ ACE_LD_SEARCH_PATH_SEPARATOR_STR);
+
+ ACE_OS::strcat (ld_path_temp, ld_path);
+ ld_path = ld_path_temp;
+ }
+ else
+ {
+ ACE_OS::free ((void *) ld_path_temp);
+ ld_path = ld_path_temp = 0;
+ }
+ }
+#endif /* ACE_HAS_WINCE */
+
+ if (ld_path != 0
+ && (ld_path = ACE_OS::strdup (ld_path)) != 0)
+ {
+ // strtok has the strange behavior of not separating the
+ // string ":/foo:/bar" into THREE tokens. One would expect
+ // that the first iteration the token would be an empty
+ // string, the second iteration would be "/foo", and the
+ // third iteration would be "/bar". However, this is not
+ // the case; one only gets two iterations: "/foo" followed
+ // by "/bar".
+
+ // This is especially a problem in parsing Unix paths
+ // because it is permissible to specify 'the current
+ // directory' as an empty entry. So, we introduce the
+ // following special code to cope with this:
+
+ // Look at each dynamic lib directory in the search path.
+
+ ACE_TCHAR *nextholder = 0;
+ const ACE_TCHAR *path_entry =
+ ACE::strsplit_r (ld_path,
+ ACE_LD_SEARCH_PATH_SEPARATOR_STR,
+ nextholder);
+ int result = 0;
+
+ for (;;)
+ {
+ // Check if at end of search path.
+ if (path_entry == 0)
+ {
+ errno = ENOENT;
+ result = -1;
+ break;
+ }
+ else if (ACE_OS::strlen (path_entry)
+ + 1
+ + ACE_OS::strlen (searchfilename)
+ >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ result = -1;
+ break;
+ }
+ // This works around the issue where a path might have
+ // an empty component indicating 'current directory'.
+ // We need to do it here rather than anywhere else so
+ // that the loop condition will still work.
+ else if (path_entry[0] == '\0')
+ path_entry = ACE_TEXT (".");
+
+ // First, try matching the filename *without* adding a
+ // prefix.
+ ACE_OS::sprintf (pathname,
+ ACE_TEXT ("%s%c%s%s"),
+ path_entry,
+ ACE_DIRECTORY_SEPARATOR_CHAR,
+ searchfilename,
+ has_suffix ? ACE_TEXT ("") : dll_suffix);
+ if (ACE_OS::access (pathname, F_OK) == 0)
+ break;
+
+ // Second, try matching the filename *with* adding a
+ // prefix.
+ ACE_OS::sprintf (pathname,
+ ACE_TEXT ("%s%c%s%s%s"),
+ path_entry,
+ ACE_DIRECTORY_SEPARATOR_CHAR,
+ ACE_DLL_PREFIX,
+ searchfilename,
+ has_suffix ? ACE_TEXT ("") : dll_suffix);
+ if (ACE_OS::access (pathname, F_OK) == 0)
+ break;
+
+ // Fetch the next item in the path
+ path_entry =
+ ACE::strsplit_r (0,
+ ACE_LD_SEARCH_PATH_SEPARATOR_STR,
+ nextholder);
+ }
+
+#if defined (ACE_HAS_WINCE)
+ if (ld_path_temp != 0)
+ ACE_OS::free (ld_path_temp);
+#endif /* ACE_HAS_WINCE */
+ ACE_OS::free ((void *) ld_path);
+#if defined (ACE_HAS_WINCE) && defined (ACE_LD_DECORATOR_STR) && \
+ !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ if (result == 0 || tag == 0)
+#endif /* ACE_HAS_WINCE && ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
+ return result;
+ }
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+ }
+#if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ }
+#endif /* ACE_WIN32 && ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
+
+ errno = ENOENT;
+ return -1;
+}
+
+FILE *
+ACE::ldopen (const ACE_TCHAR *filename,
+ const ACE_TCHAR *type)
+{
+ ACE_TRACE ("ACE::ldopen");
+
+ ACE_TCHAR buf[MAXPATHLEN + 1];
+ if (ACE::ldfind (filename,
+ buf,
+ sizeof (buf) /sizeof (ACE_TCHAR)) == -1)
+ return 0;
+ else
+ return ACE_OS::fopen (buf, type);
+}
+
+ACE_TCHAR *
+ACE::ldname (const ACE_TCHAR *entry_point)
+{
+ ACE_TRACE ("ACE::ldname");
+
+#if defined(ACE_NEEDS_DL_UNDERSCORE)
+ size_t size =
+ 1 // leading '_'
+ + ACE_OS::strlen (entry_point)
+ + 1;
+
+ ACE_TCHAR *new_name;
+ ACE_NEW_RETURN (new_name,
+ ACE_TCHAR[size],
+ 0);
+
+ ACE_OS::strcpy (new_name, ACE_TEXT ("_"));
+ ACE_OS::strcat (new_name, entry_point);
+
+ return new_name;
+#else /* ACE_NEEDS_DL_UNDERSCORE */
+ size_t size =
+ ACE_OS::strlen (entry_point)
+ + 1;
+
+ ACE_TCHAR *new_name;
+ ACE_NEW_RETURN (new_name,
+ ACE_TCHAR[size],
+ 0);
+
+ ACE_OS::strcpy (new_name, entry_point);
+ return new_name;
+#endif /* ACE_NEEDS_DL_UNDERSCORE */
+}
+
+#if defined (ACE_OPENVMS)
+void
+ACE::ldregister (const ACE_TCHAR *entry_point,
+ void* entry_addr)
+{
+ ACE_LD_SYMBOL_REGISTRY::instance ()->register_symbol (entry_point,
+ entry_addr);
+}
+
+void *
+ACE::ldsymbol (ACE_SHLIB_HANDLE sh, const ACE_TCHAR *entry_point)
+{
+ void* symaddr = ACE_OS::dlsym (sh, entry_point);
+ // if not found through dlsym() try registry
+ if (symaddr == 0)
+ symaddr = ACE_LD_SYMBOL_REGISTRY::instance ()->find_symbol (entry_point);
+
+ return symaddr;
+}
+#endif
+
+int
+ACE::get_temp_dir (ACE_TCHAR *buffer, size_t buffer_len)
+{
+ int result;
+#if defined (ACE_WIN32)
+ result = ACE_TEXT_GetTempPath (static_cast<DWORD> (buffer_len),
+ buffer);
+
+ // Make sure to return -1 if there is an error
+ if (result == 0 && ::GetLastError () != ERROR_SUCCESS
+ || result > static_cast<int> (buffer_len))
+ result = -1;
+
+#else /* ACE_WIN32 */
+
+ // NOTE! Non-Windows platforms don't deal with wide chars for env.
+ // variables, so do this narrow-char and convert to wide for the
+ // caller if necessary.
+
+ // On non-win32 platforms, check to see what the TMPDIR environment
+ // variable is defined to be. If it doesn't exist, just use /tmp
+ const char *tmpdir = ACE_OS::getenv ("TMPDIR");
+
+ if (tmpdir == 0)
+ tmpdir = "/tmp";
+
+ size_t len = ACE_OS::strlen (tmpdir);
+
+ // Check to see if the buffer is large enough for the string,
+ // another /, and its null character (hence the + 2)
+ if ((len + 2) > buffer_len)
+ {
+ result = -1;
+ }
+ else
+ {
+ ACE_OS::strcpy (buffer, ACE_TEXT_CHAR_TO_TCHAR (tmpdir));
+
+ // Add a trailing slash because we cannot assume there is already one
+ // at the end. And having an extra one should not cause problems.
+ buffer[len] = ACE_TEXT ('/');
+ buffer[len + 1] = 0;
+ result = 0;
+ }
+#endif /* ACE_WIN32 */
+ return result;
+}
+
+ACE_HANDLE
+ACE::open_temp_file (const ACE_TCHAR *name, int mode, int perm)
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (perm);
+ ACE_HANDLE handle = ACE_OS::open (name,
+ mode,
+ FILE_SHARE_READ
+ | FILE_SHARE_WRITE
+ | FILE_SHARE_DELETE);
+#else
+ // Open it.
+ ACE_HANDLE handle = ACE_OS::open (name, mode, perm);
+#endif /* ACE_WIN32 */
+
+ if (handle == ACE_INVALID_HANDLE)
+ return ACE_INVALID_HANDLE;
+
+ // Unlink it so that the file will be removed automatically when the
+ // process goes away.
+ if (ACE_OS::unlink (name) == -1)
+ return ACE_INVALID_HANDLE;
+ else
+ // Return the handle.
+ return handle;
+}
+
+size_t
+ACE::strrepl (char *s, char search, char replace)
+{
+ ACE_TRACE ("ACE::strrepl");
+
+ size_t replaced = 0;
+
+ for (size_t i = 0; s[i] != '\0'; i++)
+ if (s[i] == search)
+ {
+ s[i] = replace;
+ ++replaced;
+ }
+
+ return replaced;
+}
+
+
+// Split a string up into 'token'-delimited pieces, ala Perl's
+// "split".
+
+char *
+ACE::strsplit_r (char *str,
+ const char *token,
+ char *&next_start)
+{
+ char *result = 0;
+
+ if (str != 0)
+ next_start = str;
+
+ if (next_start != 0)
+ {
+ char *tok_loc = ACE_OS::strstr (next_start, token);
+
+ if (tok_loc != 0)
+ {
+ // Return the beginning of the string.
+ result = next_start;
+
+ // Insure it's terminated.
+ *tok_loc = '\0';
+ next_start = tok_loc + ACE_OS::strlen (token);
+ }
+ else
+ {
+ result = next_start;
+ next_start = (char *) 0;
+ }
+ }
+
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+wchar_t *
+ACE::strsplit_r (wchar_t *str,
+ const wchar_t *token,
+ wchar_t *&next_start)
+{
+ wchar_t *result = 0;
+
+ if (str != 0)
+ next_start = str;
+
+ if (next_start != 0)
+ {
+ wchar_t *tok_loc = ACE_OS::strstr (next_start, token);
+
+ if (tok_loc != 0)
+ {
+ // Return the beginning of the string.
+ result = next_start;
+
+ // Insure it's terminated.
+ *tok_loc = '\0';
+ next_start = tok_loc + ACE_OS::strlen (token);
+ }
+ else
+ {
+ result = next_start;
+ next_start = (wchar_t *) 0;
+ }
+ }
+
+ return result;
+}
+
+size_t
+ACE::strrepl (wchar_t *s, wchar_t search, wchar_t replace)
+{
+ ACE_TRACE ("ACE::strrepl");
+
+ size_t replaced = 0;
+
+ for (size_t i = 0; s[i] != '\0'; i++)
+ if (s[i] == search)
+ {
+ s[i] = replace;
+ ++replaced;
+ }
+
+ return replaced;
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Lib_Find.h b/ACE/ace/Lib_Find.h
new file mode 100644
index 00000000000..ef146bb337d
--- /dev/null
+++ b/ACE/ace/Lib_Find.h
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Lib_Find.h
+ *
+ * All the static function calls needed to search and open shared
+ * libraries.
+ *
+ * $Id$
+ */
+//=============================================================================
+
+#ifndef ACE_LIB_FIND_H
+#define ACE_LIB_FIND_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include /**/ "ace/ACE_export.h"
+#include "ace/os_include/os_stdio.h"
+#if defined (ACE_OPENVMS)
+# include "ace/OS_NS_dlfcn.h"
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE
+{
+ // = Methods for searching and opening shared libraries.
+
+ /**
+ * Finds the file @a filename either using an absolute path or using
+ * a relative path in conjunction with ACE_LD_SEARCH_PATH (e.g.,
+ * $LD_LIBRARY_PATH on UNIX or the directories scaned by Win32 API
+ * SearchPath on Win32). This function will add appropriate suffix
+ * (e.g., .dll on Win32 or .so on UNIX) according to the OS
+ * platform. In addition, this function will apply the appropriate
+ * prefix (e.g., "lib" on UNIX and "" on Win32) if the @a filename
+ * doesn't match directly.
+ */
+ extern ACE_Export int ldfind (const ACE_TCHAR* filename,
+ ACE_TCHAR pathname[],
+ size_t maxpathnamelen);
+
+ /**
+ * Uses @c ldfind to locate and open the appropriate @a filename and
+ * returns a pointer to the file, else it returns a NULL
+ * pointer. @a type specifies how the file should be open.
+ */
+ extern ACE_Export FILE *ldopen (const ACE_TCHAR *filename,
+ const ACE_TCHAR *type);
+
+ /**
+ * Transforms @a entry_point into a form that can be located in a
+ * dynamic library using <dlsym>. For example, with Win32/Borland
+ * extern "C" functions which use the default calling convention
+ * have a '_' prepended. Always returns a buffer that has been
+ * dynamically allocated using <operator new>.
+ */
+ extern ACE_Export ACE_TCHAR *ldname (const ACE_TCHAR *entry_point);
+
+
+#if defined (ACE_OPENVMS)
+ /**
+ * Registers an @a entry_point and its address for later retrieval
+ * through the ACE::ldsymbol () method.
+ * For use in cases where the OS compiler encodes long symbolnames.
+ */
+ extern ACE_Export void ldregister (const ACE_TCHAR *entry_point,
+ void* entry_addr);
+
+ /**
+ * Looks up an @a entry_point address either from previously registered
+ * symbols or through ACE_OS::dlsym ().
+ * Returns 0 in case the entry_point is not found, otherwise nonzero.
+ * For use in cases where the OS compiler encodes long symbolnames.
+ */
+ extern ACE_Export void *ldsymbol (ACE_SHLIB_HANDLE sh,
+ const ACE_TCHAR *entry_point);
+#endif
+
+ /**
+ * Returns the temporary directory including the trailing slash in
+ * @a buffer. Returns -1 for an error or if the buffer_len is not
+ * long enough.
+ */
+ extern ACE_Export int get_temp_dir (ACE_TCHAR *buffer, size_t buffer_len);
+
+ /// Opening the temp file. File is automagically unlinked when it is
+ /// closed. This is useful for have temp files.
+ extern ACE_Export ACE_HANDLE open_temp_file (const ACE_TCHAR *name,
+ int mode,
+ int perm = 0);
+
+ // @@ Though the following functions dont come under the same category as
+ // above, these are used only in the functions in this class. So it makes
+ // more sense to move these functions too to this class.
+ //
+ /// Replace all instances of @a search in @a s with @a replace. Returns
+ /// the number of replacements made.
+ extern ACE_Export size_t strrepl (char *s, char search, char replace);
+
+ /**
+ * Splits string <s> into pieces separated by the string <token>.
+ * <next_start> is an opaque cookie handed back by the call to store
+ * its state for the next invocation, thus making it re-entrant.
+ * This operates very similar to Perl's <split> function except that
+ * it returns pieces one at a time instead of into an array.
+ */
+ extern ACE_Export char *strsplit_r (char *s,
+ const char *token,
+ char *&next_start);
+
+#if defined (ACE_HAS_WCHAR)
+ /// As strrepl, but for wide characters.
+ extern ACE_Export size_t strrepl (wchar_t *s,
+ wchar_t search,
+ wchar_t replace);
+
+ /// As strsplit_r, but for wide characters.
+ extern ACE_Export wchar_t *strsplit_r (wchar_t *s,
+ const wchar_t *token,
+ wchar_t *&next_start);
+#endif /* ACE_HAS_WCHAR */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LIB_FIND_H */
+
diff --git a/ACE/ace/Local_Memory_Pool.cpp b/ACE/ace/Local_Memory_Pool.cpp
new file mode 100644
index 00000000000..09dbb19000d
--- /dev/null
+++ b/ACE/ace/Local_Memory_Pool.cpp
@@ -0,0 +1,144 @@
+// $Id$
+
+// Local_Memory_Pool.cpp
+#include "ace/Local_Memory_Pool.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/OS_Memory.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Local_Memory_Pool, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Local_Memory_Pool)
+
+void
+ACE_Local_Memory_Pool::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Local_Memory_Pool::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Local_Memory_Pool::ACE_Local_Memory_Pool (const ACE_TCHAR *,
+ const OPTIONS *)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::ACE_Local_Memory_Pool");
+}
+
+ACE_Local_Memory_Pool::~ACE_Local_Memory_Pool (void)
+{
+ // Free up all memory allocated by this pool.
+ this->release ();
+}
+
+// Ask system for initial chunk of local memory.
+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);
+}
+
+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_TEXT ("(%P|%t) insertion into set failed\n")),
+ 0);
+
+ return cp.release ();
+}
+
+int
+ACE_Local_Memory_Pool::release (int)
+{
+ 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;
+}
+
+int
+ACE_Local_Memory_Pool::sync (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::sync");
+ return 0;
+}
+
+int
+ACE_Local_Memory_Pool::sync (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::sync");
+ return 0;
+}
+
+int
+ACE_Local_Memory_Pool::protect (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::protect");
+ return 0;
+}
+
+int
+ACE_Local_Memory_Pool::protect (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::protect");
+ 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.
+}
+
+void *
+ACE_Local_Memory_Pool::base_addr (void) const
+{
+ return 0;
+}
+
+// Let the underlying new operator figure out the alignment...
+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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Local_Memory_Pool.h b/ACE/ace/Local_Memory_Pool.h
new file mode 100644
index 00000000000..0a7abe4912a
--- /dev/null
+++ b/ACE/ace/Local_Memory_Pool.h
@@ -0,0 +1,133 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Local_Memory_Pool.h
+ *
+ * $Id$
+ *
+ * @author Dougls C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_LOCAL_MEMORY_POOL_H
+#define ACE_LOCAL_MEMORY_POOL_H
+#include /**/ "ace/pre.h"
+
+#include "ace/os_include/sys/os_mman.h" /* Need PROT_RDWR */
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Unbounded_Set.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a nbytes from the memory pool. @a 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 (int destroy = 1);
+
+ /**
+ * Sync @a len bytes of the memory region to the backing store
+ * starting at <this->base_addr_>. If @a len == -1 then sync the
+ * whole region.
+ */
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync @a len bytes of the memory region to the backing store
+ /// starting at @a add_.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to @a prot
+ * starting at <this->base_addr_> up to @a len bytes. If @a 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 @a prot
+ /// starting at @a addr up to @a 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 @a 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);
+
+ /// Return the base address of this memory pool, 0 if base_addr
+ /// never changes.
+ 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:
+ /// List of memory that we have allocated.
+ ACE_Unbounded_Set<char *> allocated_chunks_;
+
+ /// Implement the algorithm for rounding up the request to an
+ /// appropriate chunksize.
+ virtual size_t round_up (size_t nbytes);
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCAL_MEMORY_POOL_H */
diff --git a/ACE/ace/Local_Name_Space.cpp b/ACE/ace/Local_Name_Space.cpp
new file mode 100644
index 00000000000..7047c234095
--- /dev/null
+++ b/ACE/ace/Local_Name_Space.cpp
@@ -0,0 +1,169 @@
+#include "ace/Local_Name_Space.h"
+#include "ace/ACE.h"
+#include "ace/RW_Process_Mutex.h"
+#include "ace/SString.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Truncate.h"
+
+ACE_RCSID (ace,
+ Local_Name_Space,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_NS_String::~ACE_NS_String (void)
+{
+ if (this->delete_rep_)
+ delete [] this->rep_;
+}
+
+ACE_WCHAR_T *
+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_WCHAR_T)) - 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_WCHAR_T)) - 1);
+ return w_string.char_rep ();
+}
+
+ACE_NS_String::ACE_NS_String (void)
+ : len_ (0),
+ rep_ (0),
+ delete_rep_ (false)
+{
+ 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_WCHAR_T)),
+ rep_ (s.rep ()),
+ delete_rep_ (true)
+{
+ 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...
+ const size_t len = (this->len_ - s.len_) / sizeof (ACE_WCHAR_T);
+ const size_t pat_len = s.len_ / sizeof (ACE_WCHAR_T) - 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 ACE_Utils::truncate_cast<int> (i);
+ }
+
+ return -1;
+ }
+}
+
+bool
+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;
+}
+
+bool
+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_WCHAR_T *dst,
+ const ACE_WCHAR_T *src,
+ size_t bytes)
+ : len_ (bytes),
+ rep_ (dst),
+ delete_rep_ (false)
+{
+ ACE_TRACE ("ACE_NS_String::ACE_NS_String");
+ ACE_OS::memcpy (this->rep_, src, bytes);
+}
+
+u_long
+ACE_NS_String::hash (void) const
+{
+ return ACE::hash_pjw
+ (reinterpret_cast<char *> (const_cast<ACE_WCHAR_T *> (this->rep_)),
+ this->len_);
+}
+
+ACE_NS_Internal::ACE_NS_Internal (void)
+ : value_ (),
+ type_ ()
+{
+}
+
+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");
+}
+
+bool
+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_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Local_Name_Space.h b/ACE/ace/Local_Name_Space.h
new file mode 100644
index 00000000000..381d2d0d5a4
--- /dev/null
+++ b/ACE/ace/Local_Name_Space.h
@@ -0,0 +1,132 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Local_Name_Space.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain (pjain@cs.wustl.edu)
+ * @author Irfan Pyarali (irfan@wuerl.wustl.edu)
+ * @author 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/Malloc_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_NS_WString;
+
+/**
+ * @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>.
+ */
+class ACE_Export ACE_NS_String
+{
+public:
+ // = Initialization.
+ /// Default "no-op" constructor.
+ ACE_NS_String (void);
+
+ /// Initialization method.
+ ACE_NS_String (ACE_WCHAR_T *dst,
+ const ACE_WCHAR_T *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.
+ bool operator == (const ACE_NS_String &) const;
+
+ /// Compare an ACE_NS_String.
+ bool operator != (const ACE_NS_String &) const;
+
+ /// Returns length of the string
+ size_t len (void) const;
+
+ /// Returns the underlying representation.
+ ACE_WCHAR_T *fast_rep (void) const;
+
+ /// Returns a hash value for this string.
+ u_long hash (void) const;
+
+private:
+ /// Length of the string.
+ size_t len_;
+
+ /// This actually points into shared/persistent memory.
+ ACE_WCHAR_T *rep_;
+
+ /// Should rep_ be deleted when destructed (only used
+ /// for WString conversions)
+ bool 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
+ bool 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// 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/ace/Local_Name_Space_T.cpp b/ACE/ace/Local_Name_Space_T.cpp
new file mode 100644
index 00000000000..e59756dcb80
--- /dev/null
+++ b/ACE/ace/Local_Name_Space_T.cpp
@@ -0,0 +1,966 @@
+// $Id$
+
+#ifndef ACE_LOCAL_NAME_SPACE_T_CPP
+#define ACE_LOCAL_NAME_SPACE_T_CPP
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Local_Name_Space.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Guard_T.h"
+#include "ace/OS_NS_regex.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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->table_allocator_ = alloc;
+ this->entry_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->table_allocator_ = alloc;
+ this->entry_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->table_allocator_ = alloc;
+ this->entry_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->table_allocator_ = alloc;
+ this->entry_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->table_allocator_ = alloc;
+ this->entry_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");
+ const size_t name_len = (name.length () + 1) * sizeof (ACE_WCHAR_T);
+ const size_t value_len = (value.length () + 1) * sizeof (ACE_WCHAR_T);
+ const size_t type_len = ACE_OS::strlen (type) + 1;
+ const 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_WCHAR_T *value_rep = (ACE_WCHAR_T *) (ptr);
+ ACE_WCHAR_T *name_rep = (ACE_WCHAR_T *) (ptr + value_len);
+ char *new_type = (char *) (ptr + value_len + name_len);
+
+ ACE_Auto_Basic_Array_Ptr<ACE_WCHAR_T> name_urep (name.rep ());
+ ACE_Auto_Basic_Array_Ptr<ACE_WCHAR_T> value_urep (value.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_WCHAR_T
+ 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 = 0;
+ 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_TEXT ("%p\n"), ACE_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);
+
+ ACE_MEM_POOL_OPTIONS options (this->name_options_->base_address ());
+
+ 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_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_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_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_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_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_TEXT ("name_space_map_ = %@, ns_map = %@\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_TEXT ("name_space_map_ = %@, ns_map = %@\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_TEXT ("create_manager\n")), -1);
+ }
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("name_space_map_ = %@, ns_map = %@\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_WSTRING_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_MANAGER::ITERATOR map_iterator (*this->name_space_map_);
+ MAP_MANAGER::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_WSTRING_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_MANAGER::ITERATOR map_iterator (*this->name_space_map_);
+ MAP_MANAGER::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_WSTRING_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_MANAGER::ITERATOR map_iterator (*this->name_space_map_);
+ MAP_MANAGER::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_MANAGER::ITERATOR map_iterator (*this->name_space_map_);
+ MAP_MANAGER::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_MANAGER::ITERATOR map_iterator (*this->name_space_map_);
+ MAP_MANAGER::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_MANAGER::ITERATOR map_iterator (*this->name_space_map_);
+ MAP_MANAGER::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_MANAGER::ITERATOR map_iterator (*this->name_space_map_);
+ MAP_MANAGER::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_TEXT ("key=%s\nvalue=%s\ntype=%s\n"),
+ ACE_TEXT_CHAR_TO_TCHAR (key), ACE_TEXT_CHAR_TO_TCHAR (value), ACE_TEXT_CHAR_TO_TCHAR (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_WSTRING_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_WSTRING_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_WSTRING_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
+{
+#if defined (ACE_HAS_DUMP)
+ // 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_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LOCAL_NAME_SPACE_T_CPP */
diff --git a/ACE/ace/Local_Name_Space_T.h b/ACE/ace/Local_Name_Space_T.h
new file mode 100644
index 00000000000..14ed9377b30
--- /dev/null
+++ b/ACE/ace/Local_Name_Space_T.h
@@ -0,0 +1,280 @@
+// -*- 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"
+#include "ace/Null_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// 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;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Simplify later usage by defining typedefs.
+#if (1)
+# include "ace/Hash_Map_Manager_T.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef 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> MAP_MANAGER;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#else
+# include "ace/Map_Manager.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef ACE_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex> MAP_MANAGER;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* 0 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// @deprecated Deprecated typedefs. Use the map's traits instead.
+typedef MAP_MANAGER::ITERATOR MAP_ITERATOR;
+typedef MAP_MANAGER::ENTRY MAP_ENTRY;
+
+
+/**
+ * @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 @a 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#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/ace/Local_Tokens.cpp b/ACE/ace/Local_Tokens.cpp
new file mode 100644
index 00000000000..17330fe79dd
--- /dev/null
+++ b/ACE/ace/Local_Tokens.cpp
@@ -0,0 +1,1623 @@
+// $Id$
+
+#include "ace/Local_Tokens.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#include "ace/Thread.h"
+#include "ace/Token_Manager.h"
+#include "ace/OS_NS_unistd.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Local_Tokens.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Local_Tokens,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Tokens::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Tokens::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Tokens::dump:\n")
+ ACE_TEXT (" reference_cont_ = %d\n")
+ ACE_TEXT (" token_name_ = %s\n"),
+ reference_count_, token_name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("waiters_\n")));
+ this->waiters_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Tokens::ACE_Tokens (void)
+ : visited_ (0),
+ reference_count_ (0)
+{
+ ACE_TRACE ("ACE_Tokens::ACE_Tokens");
+}
+
+ACE_Tokens::~ACE_Tokens (void)
+{
+}
+
+void
+ACE_Tokens::make_owner (ACE_TPQ_Entry *caller)
+{
+ this->waiters_.remove (caller);
+ this->waiters_.enqueue (caller, 0);
+}
+
+ACE_Token_Proxy_Queue *
+ACE_Tokens::waiters ()
+{
+ ACE_TRACE ("ACE_Tokens::waiters");
+ return &this->waiters_;
+}
+
+int
+ACE_Tokens::no_of_waiters ()
+{
+ ACE_TRACE ("ACE_Tokens::no_of_waiters");
+ return this->waiters_.size ();
+}
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+ACE_Null_Token::ACE_Null_Token (void)
+{
+}
+
+ACE_Null_Token::~ACE_Null_Token (void)
+{
+}
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+void
+ACE_TPQ_Entry::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TPQ_Entry::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE_TPQ_Entry::dump:\n")
+ ACE_TEXT (" nesting_level_ = %d\n")
+ ACE_TEXT (" client_id_ = %s\n"),
+ nesting_level_,
+ client_id_));
+
+ if (next_ != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next:.\n")));
+ next_->dump ();
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_TPQ_Entry::dump end.\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_TPQ_Entry::ACE_TPQ_Entry (const ACE_Token_Proxy *new_proxy,
+ const ACE_TCHAR *client_id)
+ : cond_var_ (lock_),
+ next_ (0),
+ // This const typecast is safe.
+ proxy_ ((ACE_Token_Proxy *) new_proxy),
+ nesting_level_ (0),
+ sleep_hook_ (0)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry");
+
+ if (client_id != 0)
+ this->client_id (client_id);
+ else
+ {
+ // Just make sure we have enough space.
+ ACE_TCHAR host_name[MAXHOSTNAMELEN];
+ ACE_TCHAR name[(sizeof host_name / sizeof (ACE_TCHAR)) + 256];
+ ACE_OS::hostname (host_name, sizeof host_name);
+
+ ACE_thread_t thread_id = ACE_Thread::self ();
+
+ // The cast is an attempt to get this to compile (and run,
+ // hopefully) regardless of the type of ACE_thread_t.
+ ACE_OS::sprintf (name,
+ ACE_TEXT ("/%s/%u/%lu"),
+ host_name,
+ static_cast<u_int> (ACE_OS::getpid ()),
+ *reinterpret_cast<u_long *> (&thread_id));
+
+ this->client_id (name);
+ }
+}
+
+ACE_TPQ_Entry::ACE_TPQ_Entry (void)
+ : cond_var_ (lock_),
+ proxy_ (0),
+ nesting_level_ (0),
+ sleep_hook_ (0)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry null const.");
+}
+
+ACE_TPQ_Entry::ACE_TPQ_Entry (const ACE_TPQ_Entry &rhs)
+: cond_var_ (lock_)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry copy const.");
+ *this = rhs;
+}
+
+ACE_TPQ_Entry::~ACE_TPQ_Entry (void)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::~ACE_TPQ_Entry");
+}
+
+void
+ACE_TPQ_Entry::operator= (const ACE_TPQ_Entry& rhs)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::operator=");
+ if (&rhs == this)
+ return;
+ this->proxy_ = rhs.proxy ();
+ this->nesting_level_ = rhs.nesting_level ();
+ this->client_id (rhs.client_id ());
+ this->sleep_hook_ = rhs.sleep_hook ();
+}
+
+void
+ACE_TPQ_Entry::client_id (const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::client_id");
+
+ if (id == 0)
+ return;
+
+ ACE_OS::strsncpy (this->client_id_,
+ (ACE_TCHAR *) id,
+ ACE_MAXCLIENTIDLEN);
+}
+
+ACE_TSS_TPQ_Entry::~ACE_TSS_TPQ_Entry (void)
+{
+}
+
+void
+ACE_TSS_TPQ_Entry::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TSS_TPQ_Entry::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_TSS_TPQ_Entry::dump:\n")
+ ACE_TEXT (" client_id_ = %s\n"),
+ client_id_ == 0 ? ACE_TEXT ("0") : client_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_TPQ_ENTRY::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_TSS_TPQ_Entry::ACE_TSS_TPQ_Entry (const ACE_Token_Proxy *proxy,
+ const ACE_TCHAR *client_id)
+: proxy_ (proxy),
+ client_id_ (client_id)
+{
+ ACE_TRACE ("ACE_TSS_TPQ_Entry::ACE_TSS_TPQ_Entry");
+}
+
+ACE_TPQ_Entry *
+ACE_TSS_TPQ_Entry::make_TSS_TYPE (void) const
+{
+ ACE_TRACE ("ACE_TSS_TPQ_Entry::make_TSS_TYPE");
+ ACE_TPQ_Entry *temp;
+
+ ACE_NEW_RETURN (temp,
+ ACE_TPQ_Entry (this->proxy_,
+ this->client_id_),
+ 0);
+ return temp;
+}
+
+ACE_TSS_TPQ_Entry::operator ACE_TPQ_Entry * (void)
+{
+#if !defined (ACE_NO_TSS_TOKENS)
+ return (ACE_TPQ_Entry *) (*((ACE_TSS<ACE_TPQ_Entry> *) this));
+#else
+ // Not sure this is the right thing to do, but it seems to work.
+ // The base class ALSO has a proxy_ and client_id_ members (weird?)
+ // which don't get initialised. The following two lines make this
+ // the same as the subclass, so that the slicing works .
+ ACE_TPQ_ENTRY::proxy ((ACE_Token_Proxy *)(this->proxy_));
+ ACE_TPQ_ENTRY::client_id (this->client_id_);
+ return (ACE_TPQ_Entry *) this;;
+#endif /* !ACE_NO_TSS_TOKENS */
+}
+
+ACE_TPQ_Iterator::ACE_TPQ_Iterator (ACE_Token_Proxy_Queue &q)
+ : current_ (q.head_)
+{
+ ACE_TRACE ("ACE_TPQ_Iterator::ACE_TPQ_Iterator");
+}
+
+int
+ACE_TPQ_Iterator::next (ACE_TPQ_Entry *&next_item)
+{
+ ACE_TRACE ("ACE_TPQ_Iterator::next");
+
+ next_item = this->current_;
+
+ return current_ != 0;
+}
+
+int
+ACE_TPQ_Iterator::done (void) const
+{
+ ACE_TRACE ("ACE_TPQ_Iterator::done");
+
+ return this->current_ == 0;
+}
+
+void
+ACE_TPQ_Iterator::advance (void)
+{
+ ACE_TRACE ("ACE_TPQ_Iterator::advance");
+
+ if (current_ != 0)
+ this->current_ = this->current_->next_;
+}
+
+void
+ACE_TPQ_Iterator::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TPQ_Iterator::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_TPQ_Iterator::dump:\n")
+ ACE_TEXT (" current_ = %d\n"),
+ (long) this->current_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("head_ and tail_\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Token_Proxy_Queue::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Token_Proxy_Queue::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Token_Proxy_Queue::dump:\n")
+ ACE_TEXT (" size_ = %d\n"),
+ size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("head_ and tail_\n")));
+ if (this->head_ != 0)
+ this->head_->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Token_Proxy_Queue::dump end.\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Token_Proxy_Queue::ACE_Token_Proxy_Queue (void)
+ : head_ (0),
+ tail_ (0),
+ size_ (0)
+{
+ ACE_TRACE ("ACE_Token_Proxy_Queue::ACE_Token_Proxy_Queue");
+}
+
+void
+ACE_Token_Proxy_Queue::enqueue (ACE_TPQ_Entry *tpq,
+ int position)
+{
+ ACE_TRACE ("ACE_Token_Proxy_Queue::enqueue");
+ tpq->next_ = 0;
+
+ ++this->size_;
+
+ if (this->head_ == 0)
+ {
+ // make tpq the entire list
+ this->head_ = this->tail_ = tpq;
+ return;
+ }
+
+ if (position == 0)
+ {
+ // make head of list
+ tpq->next_ = this->head_;
+ this->head_ = tpq;
+ return;
+ }
+
+ if (position == -1)
+ {
+ // stick at back of list
+ this->tail_->next_ = tpq;
+ this->tail_ = tpq;
+ return;
+ }
+
+ // walk through list to insertion point
+ ACE_TPQ_Entry *temp = head_;
+
+ for (int x = position;
+ x > 1;
+ --x)
+ {
+ // end of queue?
+ if (temp->next_ == 0)
+ break;
+ // advance pointer
+ else
+ temp = temp->next_;
+ }
+
+ // insert new tpq after temp
+ tpq->next_ = temp->next_;
+ temp->next_ = tpq;
+}
+
+void
+ACE_Token_Proxy_Queue::dequeue (void)
+{
+ ACE_TRACE ("ACE_Token_Proxy_Queue::dequeue");
+
+ if (head_ == 0)
+ return;
+
+ ACE_TPQ_Entry *temp = this->head_;
+
+ this->head_ = this->head_->next_;
+
+ temp->next_ = 0;
+
+ --this->size_;
+
+ if (this->head_ == 0 && this->size_ != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("incorrect size = %d\n"),
+ this->size_));
+}
+
+/*
+int
+ACE_Token_Proxy_Queue::member (const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_Token_Proxy_Queue::member");
+
+ for (ACE_TPQ_Entry *temp = this->head_;
+ temp != 0;
+ temp = temp->next_)
+ if (ACE_OS::strcmp (temp->client_id (), id) == 0)
+ // We found it!
+ return 1;
+
+ // We didn't find it :-(
+ return 0;
+}
+*/
+
+void
+ACE_Token_Proxy_Queue::remove (const ACE_TPQ_Entry *remove_me)
+{
+ ACE_TRACE ("ACE_Token_Proxy_Queue::remove");
+ // sanity
+ if ((remove_me == 0) || (this->head_ == 0))
+ return;
+
+ // is it the head?
+ if (this->head_ == remove_me) // pointer comparison.
+ {
+ this->head_ = this->head_->next_;
+ if (this->head_ == 0)
+ this->tail_ = 0;
+
+ --this->size_;
+ return;
+ }
+
+ ACE_TPQ_Entry *temp = this->head_;
+ ACE_TPQ_Entry *previous = 0;
+
+ // is it in the middle or tail?
+ while (temp != 0)
+ {
+ if (temp == remove_me)
+ {
+ // previous should never be null since the first if
+ // conditional should always be false
+ previous->next_ = temp->next_;
+ // is it the tail?
+ if (this->tail_ == temp)
+ this->tail_ = previous;
+
+ --this->size_;
+ return;
+ }
+
+ previous = temp;
+ temp = temp->next_;
+ }
+
+ // it wasn't in the list.
+ return;
+}
+
+void
+ACE_Mutex_Token::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Mutex_Token::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Mutex_Token::dump:\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("lock_\n")));
+ lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_Tokens::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Mutex_Token::dump end.\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Mutex_Token::ACE_Mutex_Token (const ACE_TCHAR *name)
+{
+ ACE_TRACE ("ACE_Mutex_Token::ACE_Mutex_Token");
+
+ ACE_OS::strsncpy (this->token_name_,
+ name,
+ ACE_MAXTOKENNAMELEN);
+}
+
+ACE_Mutex_Token::~ACE_Mutex_Token (void)
+{
+ ACE_TRACE ("ACE_Mutex_Token::~ACE_Mutex_Token");
+}
+
+int
+ACE_Mutex_Token::acquire (ACE_TPQ_Entry *caller,
+ int ignore_deadlock,
+ int notify)
+{
+ ACE_TRACE ("ACE_Mutex_Token::acquire");
+ // We need to acquire two locks. This one to ensure that only one
+ // thread uses this token at a time.
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
+ // This one to ensure an atomic transaction across all tokens. Note
+ // that this order is crucial too. It's resource coloring for other
+ // threads which may be calling this same token.
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
+
+ // Does _anyone_ own the token?
+ if (this->owner () == 0)
+ {
+ // there are no waiters, so queue as the first waiter (the owner.)
+ this->waiters_.enqueue (caller, -1);
+ return 0; // success
+ }
+
+ // Does the caller already own it?
+ if (this->is_owner (caller->client_id ()))
+ {
+ // Recursive acquisition.
+ caller->nesting_level (1);
+ return 0; // success
+ }
+
+ // Check for deadlock.
+ if (!ignore_deadlock
+ && ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1)
+ {
+ errno = EDEADLK;
+ ACE_RETURN (-1);
+ }
+
+ // Someone owns it. Sorry, you're getting queued up at the end of
+ // the waiter queue.
+ this->waiters_.enqueue (caller, -1);
+
+ if (notify)
+ this->owner ()->call_sleep_hook ();
+
+ errno = EWOULDBLOCK;
+ ACE_RETURN (-1);
+
+ ACE_NOTREACHED (return -1);
+}
+
+int
+ACE_Mutex_Token::tryacquire (ACE_TPQ_Entry *caller)
+{
+ ACE_TRACE ("ACE_Mutex_Token::tryacquire");
+ // We need to acquire two locks. This one to ensure that only one
+ // thread uses this token at a time.
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
+ // This one to ensure an atomic transaction across all tokens. Note
+ // that this order is crucial too. It's resource coloring for other
+ // threads which may be calling this same token.
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
+
+ // Does _anyone_ own the token?
+ if (this->owner () == 0)
+ {
+ this->waiters_.enqueue (caller, -1);
+ return 0; // success
+ }
+ // Does the caller already own it?
+ if (this->is_owner (caller->client_id ()))
+ {
+ // recursive acquisition
+ caller->nesting_level (1);
+ return 0; // success
+ }
+ else
+ // Someone owns it. Fail.
+ {
+ errno = EWOULDBLOCK;
+ ACE_RETURN (-1);
+ }
+
+ ACE_NOTREACHED (return -1);
+}
+
+int
+ACE_Mutex_Token::renew (ACE_TPQ_Entry *caller,
+ int requeue_position)
+{
+ ACE_TRACE ("ACE_Mutex_Token::renew");
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
+
+ // Verify that the caller is the owner.
+ if (this->is_owner (caller->client_id ()) == 0)
+ {
+ errno = EACCES;
+ ACE_RETURN (-1);
+ }
+
+ // The caller is the owner, so check to see if there are any
+ // waiters. If not, we just keep the token. == 1 means that there
+ // is only the owner.
+ if (this->waiters_.size () == 1 || requeue_position == 0)
+ return 0;
+
+ // Requeue the caller.
+ this->waiters_.dequeue ();
+
+ this->waiters_.enqueue (caller, requeue_position);
+
+ // Notify new owner.
+ if (this->owner () != 0)
+ this->owner ()->proxy ()->token_acquired (this->owner ());
+
+ // Tell the caller that the operation would block.
+ errno = EWOULDBLOCK;
+ ACE_RETURN (-1);
+
+ ACE_NOTREACHED (return -1);
+}
+
+// Release the current holder of the token (which had
+// better be the caller's thread!).
+
+int
+ACE_Mutex_Token::release (ACE_TPQ_Entry *caller)
+{
+ ACE_TRACE ("ACE_Mutex_Token::release");
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
+
+ // Does anyone own the token?
+ if (this->owner () == 0)
+ {
+ errno = EACCES;
+ ACE_RETURN (-1);
+ }
+
+ // Is the caller the owner.
+ if (this->is_owner (caller->client_id ()))
+ {
+ // Check the nesting level.
+ if (caller->nesting_level () > 0)
+ caller->nesting_level (-1);
+ else
+ {
+ this->waiters_.dequeue ();
+ // Notify new owner.
+ if (this->owner () != 0)
+ this->owner ()->proxy ()->token_acquired (this->owner ());
+ }
+ }
+ else
+ this->remove (caller);
+
+ return 0;
+}
+
+int
+ACE_Mutex_Token::owners (OWNER_STACK &stack,
+ const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_Mutex_Token::owners");
+ if (this->owner () != 0)
+ {
+ stack.push (this->owner ());
+ // If an <id> is specified, return whether it is the owner being
+ // returned.
+ if (id != 0)
+ return this->owner ()->equal_client_id (id);
+ }
+
+ return 0;
+}
+
+int
+ACE_Mutex_Token::is_waiting_for (const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_Mutex_Token::is_waiting_for");
+ // If there is no owner, or <id> is the owner, return false.
+ if ((this->owner () == 0) || this->is_owner (id))
+ return 0;
+
+ // Step through each waiter looking for <id>.
+ ACE_TPQ_Iterator iterator (waiters_);
+ iterator.advance ();
+ for (ACE_TPQ_Entry *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (temp->equal_client_id (id))
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Mutex_Token::is_owner (const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_Mutex_Token::is_owner");
+ // If there is an owner, return whether it is <id>.
+ if ((this->owner () != 0) &&
+ this->owner ()->equal_client_id (id))
+ return 1;
+ else
+ return 0;
+}
+
+int
+ACE_Mutex_Token::type (void) const
+{
+ ACE_TRACE ("ACE_Mutex_Token::type");
+ return (int) ACE_Tokens::MUTEX;
+}
+
+// ************************************************************
+
+int
+ACE_RW_Token::type (void) const
+{
+ ACE_TRACE ("ACE_RW_Token::type");
+ return (int) ACE_Tokens::RWLOCK;
+}
+
+void
+ACE_RW_Token::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_RW_Token::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_RW_Token::dump:\n")
+ ACE_TEXT ("num_writers_ = %d\n"), num_writers_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("lock_\n")));
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_Tokens::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_RW_Token::dump end.\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_RW_Token::ACE_RW_Token (const ACE_TCHAR *name)
+: num_writers_ (0)
+{
+ ACE_TRACE ("ACE_RW_Token::ACE_RW_Token");
+
+ ACE_OS::strsncpy (this->token_name_,
+ name,
+ ACE_MAXTOKENNAMELEN);
+}
+
+ACE_RW_Token::~ACE_RW_Token (void)
+{
+ ACE_TRACE ("ACE_RW_Token::~ACE_RW_Token");
+}
+
+int
+ACE_RW_Token::acquire (ACE_TPQ_Entry *caller,
+ int ignore_deadlock,
+ int notify)
+{
+ ACE_TRACE ("ACE_RW_Token::acquire");
+ // We need to acquire two locks. This one to ensure that only one
+ // thread uses this token at a time.
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
+ // This one to ensure an atomic transaction across all tokens. Note
+ // that this order is crucial too. It's resource coloring for other
+ // threads which may be calling this same token.
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
+
+ if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
+ this->num_writers_++;
+
+ // Does _anyone_ own the token?
+ if (this->owner () == 0)
+ {
+ // There are no waiters, so queue as the first waiter (the owner).
+ this->waiters_.enqueue (caller, -1);
+ return 0;
+ }
+
+ // Check for recursive acquisition.
+ if (this->is_owner (caller->client_id ()))
+ {
+ caller->nesting_level (1);
+ return 0; // Success.
+ }
+
+ // Reader.
+ if (caller->proxy ()->type () == ACE_RW_Token::READER)
+ {
+ // Are there any writers?
+ if (this->num_writers_ == 0)
+ {
+ // Queue the caller at the end of the queue.
+ this->waiters_.enqueue (caller, -1);
+ return 0;
+ }
+ // Else failure.
+ }
+
+ // Failure code.
+
+ // Check for deadlock.
+ if (!ignore_deadlock &&
+ ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1)
+ {
+ if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
+ this->num_writers_--;
+ errno = EDEADLK;
+ ACE_RETURN (-1);
+ }
+
+ // Queue the caller at the end of the queue.
+ this->waiters_.enqueue (caller, -1);
+
+ if (notify)
+ {
+ // If it's a writer, just notify it.
+ if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER)
+ this->owner ()->call_sleep_hook ();
+ else
+ {
+ // Call back all reader owners.
+ ACE_TPQ_Entry *temp = this->owner ();
+ do
+ {
+ temp->call_sleep_hook ();
+ temp = temp->next_;
+ }
+ while (temp != 0 &&
+ temp->proxy ()->type () == ACE_RW_Token::READER);
+ }
+ }
+
+ errno = EWOULDBLOCK;
+ ACE_RETURN (-1);
+
+ ACE_NOTREACHED (return -1);
+}
+
+int
+ACE_RW_Token::tryacquire (ACE_TPQ_Entry *caller)
+{
+ ACE_TRACE ("ACE_RW_Token::tryacquire");
+ // We need to acquire two locks. This one to ensure that only one
+ // thread uses this token at a time.
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
+ // This one to ensure an atomic transaction across all tokens. Note
+ // that this order is crucial too. It's resource coloring for other
+ // threads which may be calling this same token.
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
+
+ if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
+ {
+ this->num_writers_++;
+ }
+
+ // Does _anyone_ own the token?
+ if (this->owner () == 0)
+ {
+ // There are no waiters, so queue as the first waiter (the owner).
+ this->waiters_.enqueue (caller, -1);
+ return 0;
+ }
+
+ // Check for recursive acquisition.
+ if (this->is_owner (caller->client_id ()))
+ {
+ caller->nesting_level (1);
+ return 0; // Success.
+ }
+
+ // Reader.
+ if (caller->proxy ()->type () == ACE_RW_Token::READER)
+ {
+ // Are there any writers?
+ if (this->num_writers_ == 0)
+ {
+ // queue the caller at the end of the queue.
+ this->waiters_.enqueue (caller, -1);
+ return 0;
+ }
+ // Else, fail.
+ }
+ else // Writer.
+ // We're going to fail, so decrement the num_writers.
+ {
+ this->num_writers_--;
+ }
+
+
+ errno = EWOULDBLOCK;
+ ACE_RETURN (-1);
+
+ ACE_NOTREACHED (return -1);
+}
+
+int
+ACE_RW_Token::renew (ACE_TPQ_Entry *caller,
+ int requeue_position)
+{
+ ACE_TRACE ("ACE_RW_Token::renew");
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
+
+ // Werify that the caller is the owner
+ if (this->is_owner (caller->client_id ()) == 0)
+ {
+ errno = EACCES;
+ ACE_RETURN (-1);
+ }
+
+ // The caller is the owner, so check to see if there are any
+ // waiters. If not, we just keep the token.
+ if (this->waiters_.size () == 1 || requeue_position == 0)
+ return 0;
+
+ // There are waiters, so remove the caller.
+ this->remove (caller);
+
+ // Requeue the caller.
+ this->waiters_.enqueue (caller, requeue_position);
+
+ if (caller->proxy ()->type () == ACE_RW_Token::READER)
+ {
+ // If the caller got queued before any writers, the caller is
+ // still the owner.
+ if (this->is_owner (caller->client_id ()))
+ return 0; // success
+ // else fallthrough and return would block.
+ }
+ // Writers will always have to block since waiters_.size () == 1 or
+ // requeue_position == 0.
+
+ // Get a new owner.
+ this->notify_new_owner (caller);
+
+ // Tell the caller that the operation would block.
+ errno = EWOULDBLOCK;
+ ACE_RETURN (-1);
+
+ ACE_NOTREACHED (return -1);
+}
+
+int
+ACE_RW_Token::release (ACE_TPQ_Entry *caller)
+{
+ ACE_TRACE ("ACE_RW_Token::release");
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
+
+ // Check for errors.
+ if ((this->owner () == 0) ||
+ (this->is_owner (caller->client_id ()) == 0))
+ {
+ errno = EACCES;
+ ACE_RETURN (-1);
+ }
+
+ if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
+ num_writers_--;
+
+ // Recursive release.
+ if (caller->nesting_level () > 0)
+ {
+ caller->nesting_level (-1);
+ return 0;
+ }
+
+ // Remove the caller and notify the new owner(s).
+ this->remove (caller);
+ this->notify_new_owner (caller);
+
+ return 0;
+}
+
+void
+ACE_RW_Token::notify_new_owner (ACE_TPQ_Entry *old_owner)
+{
+ ACE_TRACE ("ACE_RW_Token::notify_new_owner");
+
+ if (this->owner () == 0)
+ return;
+
+ if (this->owner ()->proxy ()->type () == ACE_RW_Token::READER)
+ {
+ if (old_owner->proxy ()->type () == ACE_RW_Token::READER)
+ // the owners already know that they're owners
+ return;
+
+ // The current owner is a reader and the previous owner was a
+ // writer, so notify all waiting readers up to the first writer.
+ // call back all reader owners.
+ ACE_TPQ_Iterator iterator (waiters_);
+ for (ACE_TPQ_Entry *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (temp->proxy ()->type () == WRITER)
+ // We've gone through all the readers.
+ break;
+
+ temp->proxy ()->token_acquired (temp);
+ }
+ }
+ else // writer
+ this->owner ()->proxy ()->token_acquired (this->owner ());
+}
+
+
+int
+ACE_RW_Token::owners (OWNER_STACK &stack,
+ const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_RW_Token::owners");
+
+ if (this->owner () == 0)
+ return 0;
+
+ int id_is_owner = 0;
+
+ // The first waiter is a writer, so there is only one owner.
+ if (this->owner ()->proxy ()->type () == WRITER)
+ {
+ stack.push (this->owner ());
+ // If an <id> is specified, return whether it is the owner being
+ // returned.
+ if ((id != 0) &&
+ (ACE_OS::strcmp (id, this->owner ()->client_id ()) == 0))
+ id_is_owner = 1;
+ }
+ // The first waiter is a reader, so there can be multiple owning
+ // readers.
+ else
+ {
+ ACE_TPQ_Iterator iterator (waiters_);
+ for (ACE_TPQ_Entry *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (temp->proxy ()->type () == WRITER)
+ // We've gone through all the readers.
+ break;
+
+ stack.push (temp);
+
+ if (!id_is_owner && (id != 0) &&
+ (ACE_OS::strcmp (id, temp->client_id ()) == 0))
+ id_is_owner = 1;
+ }
+ }
+
+ return id_is_owner;
+}
+
+int
+ACE_RW_Token::is_waiting_for (const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_RW_Token::is_waiting_for");
+ // If there is no owner, or <id> is the owner, return false.
+ if ((this->owner () == 0) ||
+ this->is_owner (id))
+ return 0;
+
+ // Step through each waiter looking for <id>.
+ ACE_TPQ_Iterator iterator (waiters_);
+ iterator.advance ();
+ for (ACE_TPQ_Entry *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (temp->equal_client_id (id))
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+ACE_RW_Token::is_owner (const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_RW_Token::is_owner");
+ // If there is no owner, return false.
+ if (this->owner () == 0)
+ return 0;
+
+ // A writer owns us.
+ if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER)
+ return this->owner ()->equal_client_id (id);
+
+ // Readers own us.
+ // Step through each owning reader looking for <id>.
+ ACE_TPQ_Iterator iterator (waiters_);
+ for (ACE_TPQ_Entry *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (temp->proxy ()->type () != ACE_RW_Token::READER)
+ break;
+
+ if (temp->equal_client_id (id))
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+ACE_Token_Proxy::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Token_Proxy::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Token_Proxy::dump:\n")
+ ACE_TEXT (" type = %d\n")
+ ACE_TEXT (" ignore_deadlock_ = %d\n")
+ ACE_TEXT (" debug_ = %d\n"),
+ (int) this->type (), ignore_deadlock_, debug_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("mutex_, and waiter_\n")));
+
+ if (this->token_ != 0)
+ this->token_->dump ();
+
+ this->waiter_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Token_Proxy::dump end.\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+const ACE_TCHAR *
+ACE_Token_Proxy::client_id (void) const
+{
+ ACE_TRACE ("ACE_Token_Proxy::client_id");
+ // Thread-specific.
+ const ACE_TPQ_Entry *temp = this->waiter_.operator->();
+ const ACE_TCHAR *id = temp->client_id ();
+
+ if (id == 0)
+ return ACE_TEXT ("ERROR NO CLIENT ID");
+ else
+ return id;
+}
+
+void
+ACE_Token_Proxy::client_id (const ACE_TCHAR *client_id)
+{
+ ACE_TRACE ("ACE_Token_Proxy::client_id");
+ this->waiter_->client_id (client_id);
+}
+
+const ACE_TCHAR *
+ACE_Token_Proxy::owner_id (void)
+{
+ ACE_TRACE ("ACE_Token_Proxy::owner_id");
+ return this->token_->owner_id ();
+}
+
+const ACE_TCHAR *
+ACE_Token_Proxy::name (void) const
+{
+ ACE_TRACE ("ACE_Token_Proxy::name");
+ return this->token_->name ();
+}
+
+#if defined (ACE_WIN32_VC8)
+# pragma warning (push)
+# pragma warning (disable:4355) /* Use of 'this' in initializer list */
+#endif
+ACE_Token_Proxy::ACE_Token_Proxy (void)
+: token_ (0),
+ waiter_ (this, 0)
+{
+ ACE_TRACE ("ACE_Token_Proxy::ACE_Token_Proxy");
+}
+
+// Notice the token_ (0). Do *not* copy the token pointer. This must
+// be obtained through the token manager. Also, we don't copy any
+// waiter info. A copied Proxy does *not* inherit client_id.
+
+ACE_Token_Proxy::ACE_Token_Proxy (const ACE_Token_Proxy &)
+ : token_ (0),
+ waiter_ (this, 0)
+{
+ ACE_TRACE ("ACE_Token_Proxy::ACE_Token_Proxy");
+}
+#if defined (ACE_WIN32_VC8)
+# pragma warning (pop)
+#endif
+
+// @@ should I do a mutex_->release ()?
+ACE_Token_Proxy::~ACE_Token_Proxy (void)
+{
+ ACE_TRACE ("ACE_Token_Proxy::~ACE_Token_Proxy");
+
+ if (token_ != 0)
+ // notify token manager that we are done with it so it can
+ // free it if necessary
+ ACE_Token_Manager::instance ()->release_token (token_);
+}
+
+int
+ACE_Token_Proxy::open (const ACE_TCHAR *token_name,
+ int ignore_deadlock,
+ int debug)
+{
+ ACE_TRACE ("ACE_Token_Proxy::open");
+
+ // Store some parameters.
+ this->ignore_deadlock_ = ignore_deadlock;
+ this->debug_ = debug;
+
+ // Used in case a name was not specified.
+ ACE_TCHAR name[BUFSIZ];
+
+ // We must have a name.
+ if (token_name == 0)
+ {
+ ACE_OS::sprintf (name, ACE_TEXT ("token %lx"),
+ reinterpret_cast<long> (this));
+ token_name = name;
+ }
+
+ // Get or create the underlying token. The Token Manager will call
+ // us back to set token_.
+ ACE_Token_Manager::instance ()->get_token (this, token_name);
+
+ // Check for failed get or failed new.
+ if (this->token_ == 0)
+ {
+ errno = ENOMEM;
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Can't allocate mutex")), -1);
+ }
+
+ return 0;
+}
+
+int
+ACE_Token_Proxy::acquire (int notify,
+ void (*sleep_hook)(void *),
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Token_Proxy::acquire");
+ if (this->token_ == 0)
+ {
+ errno = ENOENT;
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Not open.\n")), -1);
+ }
+
+ // Make sure no one calls our token_acquired until we have a chance
+ // to sleep first! If after we call an EWOULDBLOCK
+ // mutex_->acquire() below, but before we enter handle_options to
+ // wait on the cond_var, a thread tries to give take us off the
+ // waiter queue and signal us, IT WILL FIRST HAVE TO ACQUIRE THIS
+ // cond_var.mutex (). _This_ is why we acquire it.
+ this->waiter_->cond_var_.mutex ().acquire ();
+
+ this->waiter_->sleep_hook (sleep_hook);
+
+ if (this->token_->acquire (this->waiter_, this->ignore_deadlock_, notify) == -1)
+ // acquire failed
+ {
+ switch (errno)
+ {
+ case EDEADLK :
+ if (!ignore_deadlock_)
+ {
+ waiter_->cond_var_.mutex ().release ();
+ errno = EDEADLK;
+ ACE_RETURN (-1);
+ }
+ // Else, fallthrough and block!
+
+ case EWOULDBLOCK :
+ if (this->debug_)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) waiting for %s, owner is %s, ")
+ ACE_TEXT ("total waiters == %d\n"),
+ this->name (),
+ this->token_->owner_id (),
+ token_->no_of_waiters ()));
+
+ // no error, but would block, if error, return error (-1),
+ // otherwise, return whether we called the holder or not.
+ int return_value;
+ if (this->handle_options (options,
+ waiter_->cond_var_) == -1)
+ return_value = -1;
+ else
+ return_value = notify == 1;
+
+ errno = EWOULDBLOCK;
+ ACE_RETURN (return_value);
+
+ default :
+ waiter_->cond_var_.mutex ().release ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Token Proxy acquire.")),
+ -1);
+ }
+ }
+ else
+ // we have the token
+ {
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) acquired %s\n"),
+ this->name ()));
+ waiter_->cond_var_.mutex ().release ();
+ }
+
+ return 0;
+}
+
+int
+ACE_Token_Proxy::tryacquire (void (*sleep_hook)(void *))
+{
+ ACE_TRACE ("ACE_Token_Proxy::tryacquire");
+ if (this->token_ == 0)
+ {
+ errno = ENOENT;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Not open.\n")),
+ -1);
+ }
+
+ this->waiter_->sleep_hook (sleep_hook);
+
+ return this->token_->tryacquire (waiter_);
+}
+
+int
+ACE_Token_Proxy::renew (int requeue_position,
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Token_Proxy::renew");
+ if (this->token_ == 0)
+ {
+ errno = ENOENT;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Not open.\n")),
+ -1);
+ }
+
+ // Make sure no one calls our token_acquired until we have a chance
+ // to sleep first!
+ this->waiter_->cond_var_.mutex ().acquire ();
+
+ if (this->token_->renew (this->waiter_, requeue_position) == -1)
+ {
+ // check for error
+ if (errno != EWOULDBLOCK)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p renew failed\n"), ACE_TEXT ("ACE_Token_Proxy")), -1);
+
+ if (this->debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) renew blocking for %s, owner is %s\n"),
+ this->name (),
+ token_->owner_id ()));
+
+ // no error, but would block, so block or return
+ return this->handle_options (options, waiter_->cond_var_);
+ }
+ else
+ // we have the token
+ {
+ if (this->debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) renewed %s\n"),
+ this->name ()));
+ waiter_->cond_var_.mutex ().release ();
+ return 0;
+ }
+}
+
+int
+ACE_Token_Proxy::handle_options (ACE_Synch_Options &options,
+ ACE_TOKEN_CONST::COND_VAR &cv)
+{
+ // Some operation failed with EWOULDBLOCK.
+ ACE_TRACE ("ACE_Token_Proxy::handle_options");
+
+ if (options[ACE_Synch_Options::USE_REACTOR] == 1)
+ // Asynchronous.
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ cv.mutex ().release ();
+ ACE_RETURN (-1);
+ }
+ else
+ // Synchronous.
+ {
+ // Block on condition variable.
+ while (cv.wait ((ACE_Time_Value *) options.time_value ()) == -1)
+ {
+ // Note, this should obey whatever thread-specific
+ // interrupt policy is currently in place...
+ if (errno == EINTR)
+ continue;
+ // We come here if a timeout occurs or some serious
+ // ACE_Condition object error.
+ cv.mutex ().release ();
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("condition variable wait")
+ ACE_TEXT (" bombed.")), -1);
+ }
+
+ if (this->debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) unblocking %s.\n"),
+ this->client_id ()));
+ cv.mutex ().release ();
+ return 0; // operation succeeded
+ }
+}
+
+int
+ACE_Token_Proxy::release (ACE_Synch_Options &)
+{
+ ACE_TRACE ("ACE_Token_Proxy::release");
+
+ if (this->token_ == 0)
+ {
+ errno = ENOENT;
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Must open before releasing.\n")));
+ ACE_RETURN (-1);
+ }
+
+ if (this->token_->release (waiter_) != 0)
+ {
+ // Release failed.
+ this->token_->remove (this->waiter_);
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) %p.\n"), ACE_TEXT ("release failed")));
+ return -1;
+ }
+ else
+ {
+ if (this->debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) released %s, owner is %s\n"),
+ this->name (),
+ token_->owner_id ()));
+
+ return 0;
+ }
+}
+
+int
+ACE_Token_Proxy::remove (ACE_Synch_Options &)
+{
+ ACE_TRACE ("ACE_Token_Proxy::remove");
+ return 0;
+}
+
+void
+ACE_Token_Proxy::sleep_hook (void)
+{
+ ACE_TRACE ("ACE_Token_Proxy::sleep_hook");
+ // Somebody wants our token! (Let'em wait...)
+ return;
+}
+
+void
+ACE_Token_Proxy::token_acquired (ACE_TPQ_Entry *e)
+{
+ ACE_TRACE ("ACE_Token_Proxy::token_acquired");
+ e->cond_var_.mutex ().acquire ();
+ // We've been taken off the waiters list and given the token!
+ // This implementation signals the internal condition
+ // variable. Thus, if asynchronous acquires are used, this must be
+ // overriden to do something more useful!
+ e->cond_var_.signal ();
+ e->cond_var_.mutex ().release ();
+
+ return;
+}
+
+int
+ACE_Token_Proxy::type (void) const
+{
+ ACE_TRACE ("ACE_Token_Proxy::type");
+ return 0;
+}
+
+int
+ACE_Token_Proxy::acquire_read (int notify,
+ void (*sleep_hook)(void *),
+ ACE_Synch_Options &options)
+{
+ return this->acquire (notify,
+ sleep_hook,
+ options);
+}
+
+int
+ACE_Token_Proxy::acquire_write (int notify,
+ void (*sleep_hook)(void *),
+ ACE_Synch_Options &options)
+{
+ return this->acquire (notify,
+ sleep_hook,
+ options);
+}
+
+int
+ACE_Token_Proxy::tryacquire_read (void (*sleep_hook)(void *))
+{
+ return this->tryacquire (sleep_hook);
+}
+
+int
+ACE_Token_Proxy::tryacquire_write (void (*sleep_hook)(void *))
+{
+ return this->tryacquire (sleep_hook);
+}
+
+ACE_Token_Name::ACE_Token_Name (const ACE_TCHAR *token_name)
+{
+ ACE_TRACE ("ACE_Token_Name::ACE_Token_Name");
+ this->name (token_name);
+}
+
+ACE_Token_Name::ACE_Token_Name (const ACE_Token_Name &rhs)
+{
+ ACE_TRACE ("ACE_Token_Name::ACE_Token_Name");
+ this->name (rhs.name ());
+}
+
+ACE_Token_Name::~ACE_Token_Name ()
+{
+ ACE_TRACE ("ACE_Token_Name::~ACE_Token_Name");
+}
+
+void
+ACE_Token_Name::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Token_Name::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Token_Name::dump:\n")
+ ACE_TEXT (" token_name_ = %s\n"),
+ token_name_ == 0 ? ACE_TEXT ("no name") : token_name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// ************************************************************
+
+ACE_Token_Proxy *
+ACE_Local_Mutex::clone (void) const
+{
+ ACE_Token_Proxy *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_Local_Mutex (token_->name (),
+ ignore_deadlock_,
+ debug_),
+ 0);
+ return temp;
+}
+
+ACE_Tokens *
+ACE_Local_Mutex::create_token (const ACE_TCHAR *name)
+{
+ ACE_Tokens *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_Mutex_Token (name),
+ 0);
+ return temp;
+}
+
+ACE_Local_Mutex::~ACE_Local_Mutex (void)
+{
+}
+
+// ************************************************************
+
+ACE_Local_RLock::~ACE_Local_RLock (void)
+{
+}
+
+ACE_Tokens *
+ACE_Local_RLock::create_token (const ACE_TCHAR *name)
+{
+ ACE_Tokens *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_RW_Token (name),
+ 0);
+ return temp;
+}
+
+int
+ACE_Local_RLock::type (void) const
+{
+ return ACE_RW_Token::READER;
+}
+
+ACE_Token_Proxy *
+ACE_Local_RLock::clone (void) const
+{
+ ACE_Token_Proxy *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_Local_RLock (token_->name (),
+ ignore_deadlock_,
+ debug_),
+ 0);
+ return temp;
+}
+
+// ************************************************************
+
+ACE_Local_WLock::~ACE_Local_WLock (void)
+{
+}
+
+ACE_Tokens *
+ACE_Local_WLock::create_token (const ACE_TCHAR *name)
+{
+ ACE_Tokens *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_RW_Token (name),
+ 0);
+ return temp;
+}
+
+int
+ACE_Local_WLock::type (void) const
+{
+ return ACE_RW_Token::WRITER;
+}
+
+ACE_Token_Proxy *
+ACE_Local_WLock::clone (void) const
+{
+ ACE_Token_Proxy *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_Local_WLock (token_->name (),
+ ignore_deadlock_,
+ debug_),
+ 0);
+ return temp;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Local_Tokens.h b/ACE/ace/Local_Tokens.h
new file mode 100644
index 00000000000..cea51db5894
--- /dev/null
+++ b/ACE/ace/Local_Tokens.h
@@ -0,0 +1,1121 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Local_Tokens.h
+ *
+ * $Id$
+ *
+ * @author Karl-Heinz Dorn <kdorn@erlh.siemens.de>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ *
+ * This file contains definitions for the following classes:
+ *
+ * public:
+ * 7. ACE_Token_Proxy
+ * 8. ACE_Null_Token : public ACE_Token_Proxy
+ * 9. ACE_Local_Mutex : public ACE_Token_Proxy
+ * *. ACE_Local_RLock : public ACE_Local_Mutex
+ * &. ACE_Local_WLock : public ACE_Local_Mutex
+ * private:
+ * 1. ACE_TOKEN_CONST
+ * 3. ACE_TPQ_Entry
+ * b. ACE_TSS_TPQ_Entry
+ * c. ACE_TPQ_Iterator
+ * 4. ACE_Token_Proxy_Queue
+ * 5. ACE_Tokens
+ * 6. ACE_Mutex_Token : public ACE_Tokens
+ * 12. ACE_RW_Token : public ACE_Tokens
+ * a. ACE_Token_Name
+ *
+ * Note that the locking classes defined in this file are *not*
+ * intended to be used as general-purpose synchronization
+ * mechanisms, such as mutexes or semaphores. Instead, you should
+ * use the ACE_Recursive_Thread_Mutex, ACE_Thread_Mutex,
+ * ACE_Thread_Semaphore, etc., that are defined in
+ * $ACE_ROOT/ace/Synch.h and $ACE_ROOT/ace/Synch_T.h or the
+ * ACE_Token that's defined in $ACE_ROOT/ace/Token.h.
+ *
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_LOCAL_MUTEX_H
+#define ACE_LOCAL_MUTEX_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_HAS_TOKENS_LIBRARY)
+
+#include "ace/Synch_Traits.h"
+#include "ace/Condition_Thread_Mutex.h"
+#include "ace/TSS_T.h"
+#include "ace/Containers.h"
+#include "ace/Synch_Options.h"
+#include "ace/Map_Manager.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/os_netdb.h"
+
+#if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE))
+# define ACE_NO_TSS_TOKENS 1
+#endif /* !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 1.
+/**
+ * @class ACE_TOKEN_CONST
+ *
+ * @brief Not a public interface.
+ *
+ * Constant definitions and typedefs for Token library. Mostly,
+ * this class is necessary to fight the compiler with order of
+ * declaration errors.
+ */
+namespace ACE_TOKEN_CONST
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ // ACE platform supports some form of threading.
+ typedef ACE_Condition_Thread_Mutex COND_VAR;
+ typedef ACE_Thread_Mutex MUTEX;
+ typedef ACE_Guard<ACE_Thread_Mutex> GUARD;
+#else
+ typedef ACE_Null_Condition COND_VAR;
+ typedef ACE_Null_Mutex MUTEX;
+ typedef ACE_Guard<ACE_Null_Mutex> GUARD;
+#endif /* ACE_HAS_THREADS */
+}
+
+// Forward decl.
+class ACE_Token_Proxy;
+
+// 3..
+/**
+ * @class ACE_TPQ_Entry
+ *
+ * @brief Token Proxy Queue entry. Used in the ACE_Token_Proxy_Queue
+ *
+ * Not a public interface.
+ */
+class ACE_Export ACE_TPQ_Entry
+{
+ friend class ACE_Token_Manager;
+public:
+ typedef void (*PTVF) (void *);
+
+ /// Null constructor.
+ ACE_TPQ_Entry (void);
+
+ /// Constructor.
+ ACE_TPQ_Entry (const ACE_Token_Proxy *proxy,
+ const ACE_TCHAR *client_id);
+
+ /// Copy constructor.
+ ACE_TPQ_Entry (const ACE_TPQ_Entry &rhs);
+
+ /// Destructor.
+ ~ACE_TPQ_Entry (void);
+
+ /// Copy operator use by the queue.
+ void operator= (const ACE_TPQ_Entry &rhs);
+
+ /// Get top of the queue.
+ ACE_Token_Proxy *proxy (void) const;
+
+ /// Set top of the queue.
+ void proxy (ACE_Token_Proxy *);
+
+ /// Get nesting level of the entry.
+ int nesting_level (void) const;
+
+ /// Delta nesting level of the entry.
+ void nesting_level (int delta);
+
+ /// Get client_id of the entry.
+ const ACE_TCHAR *client_id (void) const;
+
+ /// Set client_id of the entry.
+ void client_id (const ACE_TCHAR *);
+
+ /// Returns 1 if @a id == client id. Does not check for @a id == 0.
+ int equal_client_id (const ACE_TCHAR *id);
+
+ /// One method for arg and sleep_hook.
+ void set (void (*sleep_hook)(void *));
+
+ /// Set sleep hook of the entry.
+ void sleep_hook (void (*sh)(void *));
+
+ /// Get sleep hook of the entry.
+ PTVF sleep_hook (void) const;
+
+ /// Call the sleep hook function or method passing arg.
+ void call_sleep_hook (void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ // = Used to block the thread if an acquire fails with EWOULDBLOCK.
+ ACE_TOKEN_CONST::COND_VAR cond_var_;
+ ACE_TOKEN_CONST::MUTEX lock_;
+
+ /// Pointer to next in list.
+ ACE_TPQ_Entry *next_;
+
+ /// Get whether this client is blocked waiting for a token.
+ int waiting (void) const;
+
+ /// Set whether this client is blocked waiting for a token.
+ void waiting (int w);
+
+private:
+ /// This client is waiting for a token.
+ int waiting_;
+
+ /// Proxy.
+ ACE_Token_Proxy *proxy_;
+
+ /// Nesting level.
+ int nesting_level_;
+
+ /// Arg.
+ void *arg_;
+
+ /// Client id.
+ ACE_TCHAR client_id_[ACE_MAXCLIENTIDLEN];
+
+ /// Sleep hook.
+ void (*sleep_hook_)(void *);
+};
+
+// b..
+#if defined (ACE_NO_TSS_TOKENS)
+typedef ACE_TPQ_Entry ACE_TPQ_ENTRY;
+#else
+typedef ACE_TSS<ACE_TPQ_Entry> ACE_TPQ_ENTRY;
+#endif /* ACE_NO_TSS_TOKENS */
+
+/**
+ * @class ACE_TSS_TPQ_Entry
+ *
+ * @brief ACE_TSS_TPQ_Entry
+ *
+ * Not a public interface.
+ */
+class ACE_Export ACE_TSS_TPQ_Entry : public ACE_TPQ_ENTRY
+{
+public:
+ /// These are passed to the constructor of ACE_TPQ_Entry in
+ /// make_TSS_TYPE
+ ACE_TSS_TPQ_Entry (const ACE_Token_Proxy *proxy,
+ const ACE_TCHAR *client_id);
+
+ /// Destructor.
+ virtual ~ACE_TSS_TPQ_Entry (void);
+
+ /// Allows us to pass args to the construction of the TSS object.
+ virtual ACE_TPQ_Entry *make_TSS_TYPE (void) const;
+
+ /// Operator overloading and inheritence don't mix.
+ operator ACE_TPQ_Entry *(void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+#if defined (ACE_NO_TSS_TOKENS)
+ ACE_TPQ_Entry *operator-> (void)
+ {
+ return (ACE_TPQ_Entry *) this;
+ }
+#endif /* ACE_NO_TSS_TOKENS */
+
+private:
+ /// Private: should not be used
+ ACE_TSS_TPQ_Entry (const ACE_TSS_TPQ_Entry &);
+ void operator= (const ACE_TSS_TPQ_Entry &);
+
+ // = These are passed to the constructor of ACE_TPQ_Entry in
+ // make_TSS_TYPE
+
+ /// Proxy.
+ const ACE_Token_Proxy *proxy_;
+
+ /// Client_id.
+ const ACE_TCHAR *client_id_;
+};
+
+class ACE_Token_Proxy_Queue;
+
+// c..
+/**
+ * @class ACE_TPQ_Iterator
+ *
+ * @brief Iterates through ACE_Token_Proxy_Queues.
+ *
+ * Not a public interface.
+ */
+class ACE_Export ACE_TPQ_Iterator
+{
+public:
+ /// Constructor.
+ ACE_TPQ_Iterator (ACE_Token_Proxy_Queue &q);
+
+ /// Destructor.
+ ~ACE_TPQ_Iterator (void);
+
+ /// Pass back the <next_item>.
+ int next (ACE_TPQ_Entry *&next_item);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Move forward by one element in the queue.
+ void advance (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+private:
+ ACE_TPQ_Entry *current_;
+};
+
+// 4..
+/**
+ * @class ACE_Token_Proxy_Queue
+ *
+ * @brief Token waiter list.
+ *
+ * Not a public interface.
+ * This queue holds all the token proxies waiting for ownership
+ * of a token. Along with the proxy reference, it also stores
+ * the nesting level, client id, and a magic cookie from the
+ * proxy. This queue stores the ACE_TPQ_Entries by pointer
+ * values. It DOES NOT make copies. Thus, the user is
+ * responsible to ensure that the TPQ's stick around. This is
+ * motivated by the need to reduce dynamic memory allocation.
+ */
+class ACE_Export ACE_Token_Proxy_Queue
+{
+public:
+ friend class ACE_TPQ_Iterator;
+
+ /// Constructor.
+ ACE_Token_Proxy_Queue (void);
+
+ /// Destructor.
+ ~ACE_Token_Proxy_Queue (void);
+
+ /**
+ * Enqueue a proxy, nesting level, client_id, and a magic cookie at
+ * the given position in the list. If the position is -1, we
+ * enqueue at the end of the list (I think).
+ */
+ void enqueue (ACE_TPQ_Entry* new_entry,
+ int position);
+
+ /// Top of the queue.
+ const ACE_TPQ_Entry* head (void);
+
+// int member (const ACE_TCHAR *id);
+ // Is this id in the waiter list?
+
+ /// Remove the top waiter.
+ void dequeue (void);
+
+ /// Remove the waiter whose proxy ref matches @a remove_me.
+ void remove (const ACE_TPQ_Entry *remove_me);
+
+ /// The number of waiters.
+ int size (void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+protected:
+ /// Head.
+ ACE_TPQ_Entry *head_;
+
+ /// Tail.
+ ACE_TPQ_Entry *tail_;
+
+ /// Size.
+ int size_;
+};
+
+// 5..
+/**
+ * @class ACE_Tokens
+ *
+ * @brief Abstract representation of ACE tokens.
+ *
+ * Not a public interface.
+ * Currently, I don't see a reason for providing an abstract
+ * interface at this level of the library. As of yet, no one
+ * uses ACE_Tokens derivatives through this abstract interface
+ * except for ACE_Token_Manager. It only uses the statistical
+ * methods which are shared by all Tokens. For that reason, it
+ * still makes since to have a common base class. However,
+ * acquire, renew, and release do not need to have matching
+ * interfaces throughout all Tokens.
+ * To add a new type of token (e.g. semaphore), this class must
+ * be subtyped to define the new semantics. See
+ * ACE_Token_Manager for details.
+ */
+class ACE_Export ACE_Tokens
+{
+public:
+
+ /// Null constructor.
+ ACE_Tokens (void);
+
+ /// Destructor
+ virtual ~ACE_Tokens (void);
+
+ /// No implementation.
+ virtual int acquire (ACE_TPQ_Entry *caller,
+ int ignore_deadlock,
+ int notify) = 0;
+
+ /// No implementation.
+ virtual int tryacquire (ACE_TPQ_Entry *caller) = 0;
+
+ /// No implementation.
+ virtual int renew (ACE_TPQ_Entry *caller,
+ int requeue_position) = 0;
+
+ /// No implementation.
+ virtual int release (ACE_TPQ_Entry *caller) = 0;
+
+ /// Move the caller to the front of the waiter list. This is for use
+ /// with remote mutexes and shadow mutexes.
+ void make_owner (ACE_TPQ_Entry *caller);
+
+ /// Remove the caller from the waiter list.
+ void remove (ACE_TPQ_Entry *caller);
+
+ // = Accessor methods.
+
+ /// Stack of owners.
+ typedef ACE_Unbounded_Stack<ACE_TPQ_Entry *> OWNER_STACK;
+
+ /// Returns a stack of the current owners. Returns -1 on error, 0 on
+ /// success. If <id> is non-zero, returns 1 if id is an owner.
+ virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id) = 0;
+
+ /// Returns 1 if <id> is waiting for this token. 0 otherwise.
+ virtual int is_waiting_for (const ACE_TCHAR *id) = 0;
+
+ /// Returns 1 if <id> is an owner of this token. 0 otherwise.
+ virtual int is_owner (const ACE_TCHAR *id) = 0;
+
+ /// Return the queue of waiters.
+ virtual ACE_Token_Proxy_Queue *waiters (void);
+
+ /// Return the number of proxies that are currently waiting to get
+ /// the token.
+ virtual int no_of_waiters (void);
+
+ /// The current owner.
+ const ACE_TCHAR *owner_id (void);
+
+ /// Token name.
+ const ACE_TCHAR* name (void);
+
+ // = Reference counting. These are only called by the
+ // Token_Manager.
+ void inc_reference (void);
+ int dec_reference (void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /**
+ * These are the Token types supported by the library at ship time.
+ * There is no restriction on the number of Token types added by
+ * "3rd parties." These are only necessary for the Token Server.
+ */
+ enum TOKEN_TYPES { MUTEX, RWLOCK };
+
+ /**
+ * Provides a manual RTTI mechanism. This method is used only by
+ * ACE_Token_Request so that the type of a token can be sent to a
+ * remote Token Server.
+ */
+ virtual int type (void) const = 0;
+
+ // = The following methods allow the deadlock detection algorithm to
+ // check if this token has been visited.
+
+ /// Mark or unmark the token as visited.
+ void visit (int v);
+
+ /// Check if the token has been visited.
+ int visited (void);
+
+ /// All the data of the current owner.
+ ACE_TPQ_Entry *owner (void);
+
+protected:
+
+ /// For the deadlock detection algorithm.
+ int visited_;
+
+ /// Reference count.
+ int reference_count_;
+
+ /// List of client's owning and waiting the token.
+ ACE_Token_Proxy_Queue waiters_;
+
+ /// Name of token.
+ ACE_TCHAR token_name_[ACE_MAXTOKENNAMELEN];
+};
+
+class ACE_Local_Mutex;
+
+// 6..
+/**
+ * @class ACE_Mutex_Token
+ *
+ * @brief Class that acquires, renews, and releases a process-local
+ * synchronization token.
+ *
+ * Not a public interface.
+ * This class is a more general-purpose synchronization mechanism
+ * than SunOS 5.x mutexes. For example, it implements "recursive
+ * mutex" semantics, where a thread that owns the token can
+ * reacquire it without deadlocking. In addition, threads that
+ * are blocked awaiting the token are serviced in strict FIFO
+ * order as other threads release the token (SunOS 5.x mutexes
+ * don't strictly enforce an acquisition order).
+ */
+class ACE_Export ACE_Mutex_Token : public ACE_Tokens
+{
+public:
+ /// Constructor
+ explicit ACE_Mutex_Token (const ACE_TCHAR* name);
+
+ /// Destructor
+ virtual ~ACE_Mutex_Token (void);
+
+ // = Synchronization operations.
+ // With acquire, renew, and release, the caller must be specified so
+ // that multiple proxies (e.g. ACE_Local_Mutex) can use the same
+ // token.
+
+ /**
+ * Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as
+ * the reason. If errnum == EWOULDBLOCK, and notify == 1,
+ * <ACE_Token_Proxy::sleep_hook> has been called on the current
+ * owner of the token. If ignore_deadlock is passed as 1 and errnum
+ * == EDEADLK, then deadlock was detected via ace_token_manager.
+ */
+ virtual int acquire (ACE_TPQ_Entry *caller,
+ int ignore_deadlock,
+ int notify);
+
+ /// Same as acquire, but fails if would block
+ virtual int tryacquire (ACE_TPQ_Entry *caller);
+
+ /**
+ * An optimized method that efficiently reacquires the token if no
+ * other threads are waiting. This is useful for situations where
+ * you don't want to degrade the quality of service if there are
+ * other threads waiting to get the token. If <requeue_position> ==
+ * -1 and there are other threads waiting to obtain the token we are
+ * queued at the end of the list of waiters. If <requeue_position>
+ * > -1 then it indicates how many entries to skip over before
+ * inserting our thread into the list of waiters (e.g.,
+ * <requeue_position> == 0 means "insert at front of the queue").
+ * Renew has the rather odd semantics such that if there are other
+ * waiting threads it will give up the token even if the
+ * nesting_level_ > 1. I'm not sure if this is really the right
+ * thing to do (since it makes it possible for shared data to be
+ * changed unexpectedly) so use with caution... Returns 0 on
+ * success, -1 on failure with <ACE_Log_Msg::errnum> as the reason.
+ * If errnum == EWOULDBLOCK, and notify == 1,
+ * <ACE_Token_Proxy::sleep_hook> has been called on the current
+ * owner of the token.
+ */
+ virtual int renew (ACE_TPQ_Entry *caller,
+ int requeue_position);
+
+ /**
+ * Relinquish the token. If there are any waiters then the next one
+ * in line gets it. If the caller is not the owner, caller is
+ * removed from the waiter list.
+ */
+ virtual int release (ACE_TPQ_Entry *caller);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Returns ACE_Tokens::MUTEX.
+ virtual int type (void) const;
+
+ /// Returns a stack of the current owners. Returns -1 on error, 0 on
+ /// success. If <id> is non-zero, returns 1 if id is an owner.
+ virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id);
+
+ /// Returns 1 if <id> is waiting for this token. 0 otherwise.
+ virtual int is_waiting_for (const ACE_TCHAR *id);
+
+ /// Returns 1 if <id> is an owner of this token. 0 otherwise.
+ virtual int is_owner (const ACE_TCHAR *id);
+
+private:
+ /// ACE_Mutex_Token used to lock internal data structures.
+ ACE_TOKEN_CONST::MUTEX lock_;
+};
+
+// 12..
+/**
+ * @class ACE_RW_Token
+ *
+ * @brief Class that acquires, renews, and releases a process-local
+ * synchronization token.
+ *
+ * Not a public interface.
+ * This class is a more general-purpose synchronization mechanism
+ * than SunOS 5.x mutexes. For example, it implements "recursive
+ * mutex" semantics, where a thread that owns the token can
+ * reacquire it without deadlocking. In addition, threads that are
+ * blocked awaiting the token are serviced in strict FIFO order as
+ * other threads release the token (SunOS 5.x mutexes don't strictly
+ * enforce an acquisition order).
+ */
+class ACE_Export ACE_RW_Token : public ACE_Tokens
+{
+public:
+ /// Constructor.
+ explicit ACE_RW_Token (const ACE_TCHAR* name);
+
+ /// Destructor.
+ virtual ~ACE_RW_Token (void);
+
+ // = Synchronization operations.
+ // With acquire, renew, and release, the caller must be specified so
+ // that multiple proxies (e.g. ACE_Local_Mutex) can use the same
+ // token.
+
+ /**
+ * Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as
+ * the reason. If errnum == EWOULDBLOCK, and notify == 1,
+ * <ACE_Token_Proxy::sleep_hook> has been called on the current
+ * owner of the token. If @a ignore_deadlock is passed as 1 and errnum
+ * == EDEADLK, then deadlock was detected via ACE_Token_Manager.
+ */
+ virtual int acquire (ACE_TPQ_Entry *caller,
+ int ignore_deadlock,
+ int notify);
+
+ /// Same as acquire except fails on would block
+ virtual int tryacquire (ACE_TPQ_Entry *caller);
+
+ /**
+ * An optimized method that efficiently reacquires the token if no
+ * other threads are waiting. This is useful for situations where
+ * you don't want to degrade the quality of service if there are
+ * other threads waiting to get the token. If <requeue_position> ==
+ * -1 and there are other threads waiting to obtain the token we are
+ * queued at the end of the list of waiters. If <requeue_position>
+ * > -1 then it indicates how many entries to skip over before
+ * inserting our thread into the list of waiters (e.g.,
+ * <requeue_position> == 0 means "insert at front of the queue").
+ * Renew has the rather odd semantics such that if there are other
+ * waiting threads it will give up the token even if the
+ * nesting_level_ > 1. I'm not sure if this is really the right
+ * thing to do (since it makes it possible for shared data to be
+ * changed unexpectedly) so use with caution... Returns 0 on
+ * success, -1 on failure with <ACE_Log_Msg::errnum> as the reason.
+ * If errnum == EWOULDBLOCK, and notify == 1,
+ * <ACE_Token_Proxy::sleep_hook> has been called on the current
+ * owner of the token.
+ */
+ virtual int renew (ACE_TPQ_Entry *caller,
+ int requeue_position);
+
+ /**
+ * Relinquish the token. If there are any waiters then the next one
+ * in line gets it. If the caller is not the owner, caller is
+ * removed from the waiter list.
+ */
+ virtual int release (ACE_TPQ_Entry *caller);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// These are the types that proxies can be.
+ enum PROXY_TYPE { READER, WRITER };
+
+ /// Returns READER or WRITER.
+ virtual int type (void) const;
+
+ /// Returns a stack of the current owners. Returns -1 on error, 0 on
+ /// success. If <id> is non-zero, returns 1 if id is an owner.
+ virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id);
+
+ /// Returns 1 if <id> is waiting for this token. 0 otherwise.
+ virtual int is_waiting_for (const ACE_TCHAR *id);
+
+ /// Returns 1 if <id> is an owner of this token. 0 otherwise.
+ virtual int is_owner (const ACE_TCHAR *id);
+
+protected:
+ /// The number of waiting writers.
+ int num_writers_;
+
+ /// ACE_Mutex_Token used to lock internal data structures.
+ ACE_TOKEN_CONST::MUTEX lock_;
+
+ /// Sets the new owner.
+ void notify_new_owner (ACE_TPQ_Entry *caller);
+};
+
+// a..
+/**
+ * @class ACE_Token_Name
+ *
+ * @brief Allows Token_Manger to identify tokens.
+ *
+ * For now, this is just a string. We need a string class
+ * anyway to use in ACE_Map_Manager. Having this class
+ * (instead of <ACE_SString>) allows us to easily change if
+ * needed. For instance, we may choose to identify tokens by
+ * name and *type* in the future.
+ */
+class ACE_Export ACE_Token_Name
+{
+public:
+ /// Construction.
+ ACE_Token_Name (const ACE_TCHAR *token_name = 0);
+
+ /// Copy construction.
+ ACE_Token_Name (const ACE_Token_Name &rhs);
+
+ /// Destructor.
+ virtual ~ACE_Token_Name (void);
+
+ /// Copy.
+ void operator= (const ACE_Token_Name &rhs);
+
+ /// Comparison.
+ bool operator== (const ACE_Token_Name &rhs) const;
+
+ /// Get the token name.
+ const ACE_TCHAR *name (void) const;
+
+ /// Set the token name.
+ void name (const ACE_TCHAR *new_name);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+private:
+ /// Name of the token.
+ ACE_TCHAR token_name_[ACE_MAXTOKENNAMELEN];
+};
+
+// 7..
+/**
+ * @class ACE_Token_Proxy
+ *
+ * @brief Abstract representation of ACE tokens.
+ *
+ * Interface for all Tokens in ACE. This class implements the
+ * synchronization needed for tokens (condition variables etc.)
+ * The algorithms for the operations (acquire, release, etc.)
+ * operate on the generic ACE_Tokens interface. Thus, the _type_
+ * of token (mutex, rwlock) can be set at construction of
+ * ACE_Token_Proxy. You can use all Tokens in ACE through the
+ * ACE_Token_Proxy by passing the proper values at construction.
+ * Alternatively, there are class definitions which "know" how to
+ * do this (ACE_Local_Mutex, ACE_Local_RLock, ACE_Local_WLock).
+ * To add a new type of token (e.g. semaphore), this class is not
+ * changed. See ACE_Token_Manager for details.
+ * Tokens (e.g. ACE_Mutex_Token) assume that it can always call
+ * <ACE_Token_Proxy::token_acquired> on a new token owner. This
+ * is not a problem for synchronous use of token proxies (that is,
+ * when acquires block until successful.) However, for
+ * implementations of the Token Server, which may use asynch
+ * operations, the proxy can not go away after an acquire until
+ * the token is acquired. This is not really a problem, but
+ * should be understood.
+ */
+class ACE_Export ACE_Token_Proxy
+{
+public:
+ friend class ACE_Token_Manager;
+ friend class ACE_Token_Invariant_Manager; // For testing.
+
+ // Initialization and termination methods.
+ /// Construction.
+ ACE_Token_Proxy (void);
+
+ /// Destructor.
+ virtual ~ACE_Token_Proxy (void);
+
+ /**
+ * Open the <ACE_Token>.
+ * @param name The string uniquely identifying the token.
+ * @param ignore_deadlock Can be 1 to disable deadlock notifications.
+ * @param debug Prints debug messages.
+ */
+ virtual int open (const ACE_TCHAR *name,
+ int ignore_deadlock = 0,
+ int debug = 0);
+
+ // = The following methods have implementations which are
+ // independent of the token semantics (mutex, rwlock, etc.) They
+ // forward operations to the underlying token and perform the
+ // necessary blocking semantics for operations (condition variables
+ // etc.) This allows reuse of the blocking code as well as having
+ // multiple proxies to the same token.
+
+ /// Calls acquire on the token. Blocks the calling thread if would
+ /// block.
+ virtual int acquire (int notify = 0,
+ void (*sleep_hook)(void *) = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /// Calls renew on the token. Blocks the calling thread if would block.
+ virtual int renew (int requeue_position = -1,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /// Calls renew on the token.
+ virtual int tryacquire (void (*sleep_hook)(void *) = 0);
+
+ /// Calls release on the token.
+ virtual int release (ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /// Calls remove on the token.
+ virtual int remove (ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /// Since the locking mechanism doesn't support read locks then this
+ /// just calls <acquire>.
+ virtual int acquire_read (int notify = 0,
+ void (*sleep_hook)(void *) = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /// Since the locking mechanism doesn't support write locks then this
+ /// just calls <acquire>.
+ virtual int acquire_write (int notify = 0,
+ void (*sleep_hook)(void *) = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /// Since the locking mechanism doesn't support read locks then this
+ /// just calls <tryacquire>.
+ virtual int tryacquire_read (void (*sleep_hook)(void *) = 0);
+
+ /// Since the locking mechanism doesn't support write locks then this
+ /// just calls <tryacquire>.
+ virtual int tryacquire_write (void (*sleep_hook)(void *) = 0);
+
+ // = Utility methods.
+
+ /// Get the client id of the proxy. This is implemented as
+ /// thread-specific data.
+ virtual const ACE_TCHAR *client_id (void) const;
+
+ /**
+ * Set the client_id for the calling thread. I strongly recommend
+ * that this not be used unless you really know what you're doing.
+ * I use this in the Token Server, and it caused many headaches.
+ */
+ virtual void client_id (const ACE_TCHAR *client_id);
+
+ /**
+ * Return the name of the token. This is important for use within
+ * the token servers (local and remote) as well as with token
+ * collections. So, all derivations of ACE_Token_Proxy must be able to
+ * stringify some name. The name must uniquely identify a token.
+ * So, for instance, the token within the reactor should probably be
+ * called "Reactor Token."
+ */
+ virtual const ACE_TCHAR *name (void) const;
+
+ /**
+ * This should really be called <someone_waiting>. This is called
+ * by ACE_Token_xx's when another proxy enters the waiting list and
+ * requests that the current token holder be notified.
+ */
+ virtual void sleep_hook (void);
+
+ /// This is called when a queued (waiting) proxy is removed from the
+ /// waiters list and given the token.
+ virtual void token_acquired (ACE_TPQ_Entry *);
+
+ /// The client id of the current token holder
+ virtual const ACE_TCHAR *owner_id (void);
+
+ /// Return a dynamically allocated clone of the derived class.
+ virtual ACE_Token_Proxy *clone (void) const = 0;
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /**
+ * This method can be used be Tokens (e.g. Readers/Writer Tokens) to
+ * distinguish between Proxy types. For instance a Reader proxy
+ * should return a different type value than a Writer proxy. The
+ * default implementation returns 0.
+ */
+ virtual int type (void) const;
+
+protected:
+ /// Duplication.
+ ACE_Token_Proxy (const ACE_Token_Proxy &);
+
+ /// If this is set, we ignore deadlock.
+ int ignore_deadlock_;
+
+ /// Print a bunch of debug messages.
+ int debug_;
+
+ /// Reference to the actual logical token. Many ACE_Local_Mutex
+ /// proxies can reference the same ACE_Mutex_Token.
+ ACE_Tokens *token_;
+
+ /// Handles cond_var waits.
+ int handle_options (ACE_Synch_Options &options,
+ ACE_TOKEN_CONST::COND_VAR &cv);
+
+ /// Waiter info used for asynchronous transactions.
+ ACE_TSS_TPQ_Entry waiter_;
+
+ /// Make the correct type of ACE_Tokens. This is called by the Token
+ /// Manager.
+ virtual ACE_Tokens *create_token (const ACE_TCHAR *name) = 0;
+};
+
+// 8..
+/**
+ * @class ACE_Null_Token
+ *
+ * @brief No op class for nonthreaded platform protocols.
+ */
+class ACE_Export ACE_Null_Token : public ACE_Token_Proxy
+{
+public:
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+ // @@ Hopefully, we can remove this ridicules ifdef when CE's compiler becomes more normal.
+ /// Construction.
+ ACE_Null_Token (void);
+
+ /// Destructor.
+ ~ACE_Null_Token (void);
+#endif /* ACE_LACKS_INLINE_FUNCTION */
+
+ /// Acquire.
+ virtual int acquire (int /* notify */ = 0,
+ void (* /* sleep_hook */ )(void *) = 0,
+ ACE_Synch_Options & /* options */ =
+ ACE_Synch_Options::defaults) { return 0; }
+
+ /// Renew.
+ virtual int renew (int /* requeue_position */ = -1,
+ ACE_Synch_Options & /* options */ =
+ ACE_Synch_Options::defaults) { return 0; }
+
+ /// Try acquire.
+ virtual int tryacquire (void (* /* sleep_hook */)(void *) = 0) { return 0; }
+
+ /// Release.
+ virtual int release (ACE_Synch_Options & /* options */ =
+ ACE_Synch_Options::defaults) { return 0; }
+
+ /// Remove.
+ virtual int remove (ACE_Synch_Options & /* options */ =
+ ACE_Synch_Options::defaults) { return 0; }
+
+ /// Return a dynamically allocated clone of the derived class.
+ virtual ACE_Token_Proxy *clone (void) const { return new ACE_Null_Token; }
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Do not allow the Token Manager to create us.
+ virtual ACE_Tokens *create_token (const ACE_TCHAR *) { return 0; }
+};
+
+// 9..
+/**
+ * @class ACE_Local_Mutex
+ *
+ * @brief Class that acquires, renews, and releases a synchronization
+ * token local to the process.
+ *
+ * This class is a more general-purpose synchronization mechanism
+ * than SunOS 5.x mutexes. For example, it implements "recursive
+ * mutex" semantics, where a thread that owns the token can
+ * reacquire it without deadlocking. In addition, threads that
+ * are blocked awaiting the token are serviced in strict FIFO
+ * order as other threads release the token (SunOS 5.x mutexes
+ * don't strictly enforce an acquisition order). Lastly,
+ * ACE_Local_Mutex performs deadlock detection on acquire calls.
+ * The interfaces for acquire, tryacquire, renew, release,
+ * etc. are defined in ACE_Token_Proxy. The semantics for
+ * ACE_Local_Mutex are that of a mutex.
+ */
+class ACE_Export ACE_Local_Mutex : public ACE_Token_Proxy
+{
+public:
+ /**
+ * Constructor.
+ * @param token_name Uniquely id's the token.
+ * @param ignore_deadlock Will allow deadlock to occur (useful for testing).
+ * @param debug Prints a bunch of messages.
+ */
+ ACE_Local_Mutex (const ACE_TCHAR *token_name = 0,
+ int ignore_deadlock = 0,
+ int debug = 0);
+
+ /// Destructor
+ ~ACE_Local_Mutex (void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Return deep copy.
+ virtual ACE_Token_Proxy *clone (void) const;
+
+protected:
+ /// Return a new ACE_Local_Mutex.
+ virtual ACE_Tokens *create_token (const ACE_TCHAR *name);
+};
+
+// *.
+/**
+ * @class ACE_Local_RLock
+ *
+ * @brief Class that acquires, renews, and releases a readers lock that
+ * is local to the process.
+ *
+ * This class implements the reader interface to canonical
+ * readers/writer locks. Multiple readers can hold the lock
+ * simultaneously when no writers have the lock. Alternatively,
+ * when a writer holds the lock, no other participants (readers
+ * or writers) may hold the lock. This class is a more
+ * general-purpose synchronization mechanism than SunOS 5.x
+ * RLocks. For example, it implements "recursive RLock"
+ * semantics, where a thread that owns the token can reacquire it
+ * without deadlocking. In addition, threads that are blocked
+ * awaiting the token are serviced in strict FIFO order as other
+ * threads release the token (SunOS 5.x RLockes don't strictly
+ * enforce an acquisition order).
+ * The interfaces for acquire, tryacquire, renew, release,
+ * etc. are defined in ACE_Token_Proxy. The semantics for
+ * ACE_Local_RLock are that of a readers/writers lock. Acquire
+ * for this class implies a reader acquisition. That is,
+ * multiple clients may acquire a lock for read only.
+ */
+class ACE_Export ACE_Local_RLock : public ACE_Token_Proxy
+{
+public:
+ // = Initialization and termination.
+
+ /**
+ * Constructor.
+ * @param token_name Uniquely id's the token.
+ * @param ignore_deadlock Will allow deadlock to occur (useful for testing).
+ * @param debug Prints a bunch of messages.
+ */
+ ACE_Local_RLock (const ACE_TCHAR *token_name = 0,
+ int ignore_deadlock = 0,
+ int debug = 0);
+
+ /// Destructor
+ ~ACE_Local_RLock (void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Returns ACE_RW_Token::RLOCK.
+ virtual int type (void) const;
+
+ /// Return deep copy.
+ virtual ACE_Token_Proxy *clone (void) const;
+
+protected:
+ /// Return a new ACE_Local_Mutex.
+ virtual ACE_Tokens *create_token (const ACE_TCHAR *name);
+};
+
+// *.
+/**
+ * @class ACE_Local_WLock
+ *
+ * @brief Class that acquires, renews, and releases a writer lock that
+ * is local to the process.
+ *
+ * This class implements the writer interface to canonical
+ * readers/writer locks. Multiple readers can hold the lock
+ * simultaneously when no writers have the lock. Alternatively,
+ * when a writer holds the lock, no other participants (readers
+ * or writers) may hold the lock. This class is a more
+ * general-purpose synchronization mechanism than SunOS 5.x
+ * WLock. For example, it implements "recursive WLock"
+ * semantics, where a thread that owns the token can reacquire it
+ * without deadlocking. In addition, threads that are blocked
+ * awaiting the token are serviced in strict FIFO order as other
+ * threads release the token (SunOS 5.x WLocks don't strictly
+ * enforce an acquisition order).
+ * The interfaces for acquire, tryacquire, renew, release,
+ * etc. are defined in ACE_Token_Proxy. The semantics for
+ * ACE_Local_WLock are that of a readers/writers lock. Acquire
+ * for this class implies a writer acquisition. That is, only
+ * one client may hold the lock for writing.
+ */
+class ACE_Export ACE_Local_WLock : public ACE_Token_Proxy
+{
+public:
+ // = Initialization and termination.
+
+ /**
+ * Constructor.
+ * @param token_name Uniquely id's the token.
+ * @param ignore_deadlock Will allow deadlock to occur (useful for testing).
+ * @param debug Prints a bunch of messages.
+ */
+ ACE_Local_WLock (const ACE_TCHAR *token_name = 0,
+ int ignore_deadlock = 0,
+ int debug = 0);
+
+ /// Destructor
+ ~ACE_Local_WLock (void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Returns ACE_RW_Token::WLOCK.
+ virtual int type (void) const;
+
+ /// Return deep copy.
+ virtual ACE_Token_Proxy *clone (void) const;
+
+protected:
+ /// Return a new ACE_Local_Mutex.
+ ACE_Tokens *create_token (const ACE_TCHAR *name);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Local_Tokens.inl"
+#endif /* __ACE_INLINE__ */
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCAL_MUTEX_H */
diff --git a/ACE/ace/Local_Tokens.inl b/ACE/ace/Local_Tokens.inl
new file mode 100644
index 00000000000..2e27ce4af04
--- /dev/null
+++ b/ACE/ace/Local_Tokens.inl
@@ -0,0 +1,289 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// ************************************************************
+
+ACE_INLINE int
+ACE_Token_Proxy_Queue::size (void)
+{
+ ACE_TRACE ("ACE_Token_Proxy_Queue::size");
+ return this->size_;
+}
+
+// ************************************************************
+
+ACE_INLINE int
+ACE_TPQ_Entry::waiting (void) const
+{
+ ACE_TRACE ("ACE_TPQ_Entry::waiting");
+ return waiting_;
+}
+
+ACE_INLINE void
+ACE_TPQ_Entry::waiting (int v)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::waiting");
+ waiting_ = v;
+}
+
+ACE_INLINE const ACE_TCHAR *
+ACE_TPQ_Entry::client_id (void) const
+{
+ ACE_TRACE ("ACE_TPQ_Entry::client_id");
+ return this->client_id_;
+}
+
+ACE_INLINE ACE_Token_Proxy *
+ACE_TPQ_Entry::proxy (void) const
+{
+ ACE_TRACE ("ACE_TPQ_Entry::proxy");
+ return this->proxy_;
+}
+
+ACE_INLINE void
+ACE_TPQ_Entry::proxy (ACE_Token_Proxy *proxy)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::proxy");
+ this->proxy_ = proxy;
+}
+
+ACE_INLINE
+ACE_TPQ_Iterator::~ACE_TPQ_Iterator (void)
+{
+}
+
+ACE_INLINE
+ACE_Token_Proxy_Queue::~ACE_Token_Proxy_Queue (void)
+{
+}
+
+ACE_INLINE void
+ACE_Tokens::remove (ACE_TPQ_Entry *caller)
+{
+ this->waiters_.remove (caller);
+}
+
+ACE_INLINE int
+ACE_Tokens::dec_reference (void)
+{
+ ACE_TRACE ("ACE_Tokens::dec_reference");
+ if (this->reference_count_ == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("dec_reference already zero")));
+ return 0;
+ }
+
+ return --this->reference_count_;
+}
+
+ACE_INLINE void
+ACE_Tokens::inc_reference (void)
+{
+ ACE_TRACE ("ACE_Tokens::inc_reference");
+ ++this->reference_count_;
+}
+
+ACE_INLINE const ACE_TPQ_Entry *
+ACE_Token_Proxy_Queue::head (void)
+{
+ ACE_TRACE ("ACE_Token_Proxy_Queue::head");
+ if (this->head_ == 0)
+ return 0;
+ else
+ return this->head_;
+}
+
+// **************************************************
+// **************************************************
+// **************************************************
+
+ACE_INLINE void
+ACE_Tokens::visit (int v)
+{
+ ACE_TRACE ("ACE_Tokens::visit");
+ visited_ = v;
+}
+
+ACE_INLINE int
+ACE_Tokens::visited (void)
+{
+ ACE_TRACE ("ACE_Tokens::visited");
+ return visited_;
+}
+
+ACE_INLINE ACE_TPQ_Entry *
+ACE_Tokens::owner (void)
+{
+ ACE_TRACE ("ACE_Tokens::owner");
+ return (ACE_TPQ_Entry *) this->waiters_.head ();
+}
+
+ACE_INLINE const ACE_TCHAR*
+ACE_Tokens::owner_id ()
+{
+ ACE_TRACE ("ACE_Tokens::owner_id");
+ if (this->owner () == 0)
+ return ACE_TEXT ("no owner");
+ else
+ return this->owner ()->client_id ();
+}
+
+ACE_INLINE const ACE_TCHAR*
+ACE_Tokens::name (void)
+{
+ ACE_TRACE ("ACE_Tokens::name");
+ return this->token_name_;
+}
+
+#if 0
+ACE_INLINE ACE_Token_Proxy *
+ACE_Tokens::current_owner (void)
+{
+ ACE_TRACE ("ACE_Tokens::current_owner");
+ // ACE_GUARD_RETURN ???
+
+ if (this->owner () == 0)
+ return 0;
+ else
+ return this->owner ()->proxy ();
+}
+#endif /* 0 */
+
+// ************************************************************
+
+ACE_INLINE int
+ACE_TPQ_Entry::nesting_level (void) const
+{
+ ACE_TRACE ("ACE_TPQ_Entry::nesting_level");
+ return this->nesting_level_;
+}
+
+ACE_INLINE void
+ACE_TPQ_Entry::nesting_level (int delta)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::nesting_level");
+ this->nesting_level_ += delta;
+}
+
+ACE_INLINE ACE_TPQ_Entry::PTVF
+ACE_TPQ_Entry::sleep_hook (void) const
+{
+ ACE_TRACE ("ACE_TPQ_Entry::sleep_hook");
+ return this->sleep_hook_;
+}
+
+ACE_INLINE void
+ACE_TPQ_Entry::sleep_hook (void (*sh)(void *))
+{
+ ACE_TRACE ("ACE_TPQ_Entry::sleep_hook");
+ this->sleep_hook_ = sh;
+}
+
+ACE_INLINE void
+ACE_TPQ_Entry::call_sleep_hook (void)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::call_sleep_hook");
+
+ // if a function has been registered, call it.
+ if (this->sleep_hook () != 0)
+ this->sleep_hook () ((void *) this->proxy ());
+ else
+ // otherwise, call back the sleep_hook method
+ this->proxy ()->sleep_hook ();
+}
+
+ACE_INLINE int
+ACE_TPQ_Entry::equal_client_id (const ACE_TCHAR *id)
+{
+ ACE_TRACE ("ACE_TPQ_Entry::equal_client_id");
+ return (ACE_OS::strcmp (this->client_id (), id) == 0);
+}
+
+// ************************************************************
+// ************************************************************
+// ************************************************************
+
+ACE_INLINE
+ACE_Local_Mutex::ACE_Local_Mutex (const ACE_TCHAR *token_name,
+ int ignore_deadlock,
+ int debug)
+{
+ ACE_TRACE ("ACE_Local_Mutex::ACE_Local_Mutex");
+ this->open (token_name, ignore_deadlock, debug);
+}
+
+ACE_INLINE void
+ACE_Token_Name::name (const ACE_TCHAR *new_name)
+{
+ ACE_TRACE ("ACE_Token_Name::name");
+
+ if (new_name == 0)
+ new_name = ACE_TEXT ("no name");
+
+ size_t n = ACE_OS::strlen (new_name) + 1;
+
+ if (n >= ACE_MAXTOKENNAMELEN)
+ n = ACE_MAXTOKENNAMELEN - 1;
+
+ ACE_OS::strsncpy (this->token_name_, (ACE_TCHAR *) new_name, n);
+}
+
+ACE_INLINE const ACE_TCHAR*
+ACE_Token_Name::name (void) const
+{
+ ACE_TRACE ("ACE_Token_Name::name");
+ return this->token_name_;
+}
+
+// ************************************************************
+
+ACE_INLINE
+ACE_Local_RLock::ACE_Local_RLock (const ACE_TCHAR *token_name,
+ int ignore_deadlock,
+ int debug)
+{
+ ACE_TRACE ("ACE_Local_RLock::ACE_Local_RLock");
+ this->open (token_name, ignore_deadlock, debug);
+}
+
+// ************************************************************
+
+ACE_INLINE
+ACE_Local_WLock::ACE_Local_WLock (const ACE_TCHAR *token_name,
+ int ignore_deadlock,
+ int debug)
+{
+ ACE_TRACE ("ACE_Local_WLock::ACE_Local_WLock");
+ this->open (token_name, ignore_deadlock, debug);
+}
+
+// ************************************************************
+
+
+ACE_INLINE void
+ACE_Token_Name::operator= (const ACE_Token_Name &rhs)
+{
+ ACE_TRACE ("ACE_Token_Name::operator=");
+ if (&rhs == this)
+ return;
+ else
+ this->name (rhs.name ());
+}
+
+ACE_INLINE bool
+ACE_Token_Name::operator== (const ACE_Token_Name &rhs) const
+{
+ ACE_TRACE ("ACE_Token_Name::operator==");
+
+ // the name and type must be the same
+ return (ACE_OS::strcmp (this->token_name_, rhs.name ()) == 0);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Lock.cpp b/ACE/ace/Lock.cpp
new file mode 100644
index 00000000000..dca934b8067
--- /dev/null
+++ b/ACE/ace/Lock.cpp
@@ -0,0 +1,88 @@
+// $Id$
+
+#include "ace/Lock.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Lock.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Lock, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Lock::~ACE_Lock (void)
+{
+}
+
+ACE_Adaptive_Lock::ACE_Adaptive_Lock (void)
+ : lock_ (0)
+{
+}
+
+ACE_Adaptive_Lock::~ACE_Adaptive_Lock (void)
+{
+}
+
+int
+ACE_Adaptive_Lock::remove (void)
+{
+ return this->lock_->remove ();
+}
+
+int
+ACE_Adaptive_Lock::acquire (void)
+{
+ return this->lock_->acquire ();
+}
+
+int
+ACE_Adaptive_Lock::tryacquire (void)
+{
+ return this->lock_->tryacquire ();
+}
+
+int
+ACE_Adaptive_Lock::release (void)
+{
+ return this->lock_->release ();
+}
+
+int
+ACE_Adaptive_Lock::acquire_read (void)
+{
+ return this->lock_->acquire_read ();
+}
+
+int
+ACE_Adaptive_Lock::acquire_write (void)
+{
+ return this->lock_->acquire_write ();
+}
+
+int
+ACE_Adaptive_Lock::tryacquire_read (void)
+{
+ return this->lock_->tryacquire_read ();
+}
+
+int
+ACE_Adaptive_Lock::tryacquire_write (void)
+{
+ return this->lock_->tryacquire_write ();
+}
+
+int
+ACE_Adaptive_Lock::tryacquire_write_upgrade (void)
+{
+ return this->lock_->tryacquire_write_upgrade ();
+}
+
+void
+ACE_Adaptive_Lock::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // return this->lock_->dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Lock.h b/ACE/ace/Lock.h
new file mode 100644
index 00000000000..2b95c1962da
--- /dev/null
+++ b/ACE/ace/Lock.h
@@ -0,0 +1,161 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Lock.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_LOCK_H
+#define ACE_LOCK_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Lock
+ *
+ * @brief This is the abstract base class that contains the uniform
+ * locking API that is supported by all the ACE synchronization
+ * mechanisms.
+ *
+ * This class is typically used in conjunction with the
+ * ACE_Lock_Adapter in order to provide a polymorphic
+ * interface to the ACE synchronization mechanisms (e.g.,
+ * ACE_Mutex, ACE_Semaphore, ACE_RW_Mutex, etc). Note that
+ * the reason that all of ACE doesn't use polymorphic locks is
+ * that (1) they add ~20% extra overhead for virtual function
+ * calls and (2) objects with virtual functions can't be placed
+ * into shared memory.
+ */
+class ACE_Export ACE_Lock
+{
+public:
+ /// CE needs a default ctor here.
+ ACE_Lock (void);
+
+ /// Noop virtual destructor
+ virtual ~ACE_Lock (void);
+
+ /**
+ * Explicitly destroy the lock. Note that only one thread should
+ * call this method since it doesn't protect against race
+ * conditions.
+ */
+ virtual int remove (void) = 0;
+
+ /// Block the thread until the lock is acquired. Returns -1 on
+ /// failure.
+ virtual int acquire (void) = 0;
+
+ /**
+ * Conditionally acquire the lock (i.e., won't block). Returns -1
+ * on failure. If we "failed" because someone else already had the
+ * lock, @c errno is set to @c EBUSY.
+ */
+ virtual int tryacquire (void) = 0;
+
+ /// Release the lock. Returns -1 on failure.
+ virtual int release (void) = 0;
+
+ /**
+ * Block until the thread acquires a read lock. If the locking
+ * mechanism doesn't support read locks then this just calls
+ * <acquire>. Returns -1 on failure.
+ */
+ virtual int acquire_read (void) = 0;
+
+ /**
+ * Block until the thread acquires a write lock. If the locking
+ * mechanism doesn't support read locks then this just calls
+ * <acquire>. Returns -1 on failure.
+ */
+ virtual int acquire_write (void) = 0;
+
+ /**
+ * Conditionally acquire a read lock. If the locking mechanism
+ * doesn't support read locks then this just calls <acquire>.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ virtual int tryacquire_read (void) = 0;
+
+ /**
+ * Conditionally acquire a write lock. If the locking mechanism
+ * doesn't support read locks then this just calls <acquire>.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ virtual int tryacquire_write (void) = 0;
+
+ /**
+ * Conditionally try to upgrade a lock held for read to a write lock.
+ * If the locking mechanism doesn't support read locks then this just
+ * calls <acquire>. Returns 0 on success, -1 on failure.
+ */
+ virtual int tryacquire_write_upgrade (void) = 0;
+};
+
+/**
+ * @class ACE_Adaptive_Lock
+ *
+ * @brief An adaptive general locking class that defers the decision of
+ * lock type to run time.
+ *
+ * This class, as ACE_Lock, provide a set of general locking APIs.
+ * However, it defers our decision of what kind of lock to use
+ * to the run time and delegates all locking operations to the actual
+ * lock. Users must define a constructor in their subclass to
+ * initialize <lock_>.
+ */
+class ACE_Export ACE_Adaptive_Lock : public ACE_Lock
+{
+public:
+ /// You must also override the destructor function to match with how
+ /// you construct the underneath <lock_>.
+ virtual ~ACE_Adaptive_Lock (void);
+
+ // = Lock/unlock operations.
+
+ virtual int remove (void);
+ virtual int acquire (void);
+ virtual int tryacquire (void);
+ virtual int release (void);
+ virtual int acquire_read (void);
+ virtual int acquire_write (void);
+ virtual int tryacquire_read (void);
+ virtual int tryacquire_write (void);
+ virtual int tryacquire_write_upgrade (void);
+ void dump (void) const;
+
+protected:
+ /**
+ * Create and initialize create the actual lcok used in the class.
+ * The default constructor simply set the <lock_> to 0 (null). You
+ * must overwrite this method for this class to work.
+ */
+ ACE_Adaptive_Lock (void);
+
+ ACE_Lock *lock_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Lock.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCK_H */
diff --git a/ACE/ace/Lock.inl b/ACE/ace/Lock.inl
new file mode 100644
index 00000000000..7e4842a0e33
--- /dev/null
+++ b/ACE/ace/Lock.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Lock::ACE_Lock (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Lock_Adapter_T.cpp b/ACE/ace/Lock_Adapter_T.cpp
new file mode 100644
index 00000000000..f26a79fdd4c
--- /dev/null
+++ b/ACE/ace/Lock_Adapter_T.cpp
@@ -0,0 +1,117 @@
+// $Id$
+
+#ifndef ACE_LOCK_ADAPTER_T_CPP
+#define ACE_LOCK_ADAPTER_T_CPP
+
+#include "ace/Lock_Adapter_T.h"
+#include "ace/OS_Memory.h" // for ACE_NEW
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Lock_Adapter_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This constructor isn't inlined, because SunPRO C++ 4.2 + patch
+// 104631-07 has trouble compiling TAO with it inline.
+template <class ACE_LOCKING_MECHANISM>
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::ACE_Lock_Adapter (void)
+ : lock_ (0),
+ delete_lock_ (true)
+{
+ ACE_NEW (this->lock_,
+ ACE_LOCKING_MECHANISM);
+}
+
+template <class ACE_LOCKING_MECHANISM>
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::~ACE_Lock_Adapter (void)
+{
+ if (this->delete_lock_)
+ delete this->lock_;
+}
+
+// Explicitly destroy the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::remove (void)
+{
+ return this->lock_->remove ();
+}
+
+// Block the thread until the lock is acquired.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::acquire (void)
+{
+ return this->lock_->acquire ();
+}
+
+// Conditionally acquire the lock (i.e., won't block).
+
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::tryacquire (void)
+{
+ return this->lock_->tryacquire ();
+}
+
+// Release the lock.
+
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::release (void)
+{
+ return this->lock_->release ();
+}
+
+// Block until the thread acquires a read lock. If the locking
+// mechanism doesn't support read locks then this just calls
+// <acquire>.
+
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::acquire_read (void)
+{
+ return this->lock_->acquire_read ();
+}
+
+// Block until the thread acquires a write lock. If the locking
+// mechanism doesn't support read locks then this just calls
+// <acquire>.
+
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::acquire_write (void)
+{
+ return this->lock_->acquire_write ();
+}
+
+// Conditionally acquire a read lock. If the locking mechanism
+// doesn't support read locks then this just calls <acquire>.
+
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::tryacquire_read (void)
+{
+ return this->lock_->tryacquire_read ();
+}
+
+// Conditionally acquire a write lock. If the locking mechanism
+// doesn't support write locks then this just calls <acquire>.
+
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::tryacquire_write (void)
+{
+ return this->lock_->tryacquire_write ();
+}
+
+// Conditionally try to upgrade a lock held for read to a write lock.
+// If the locking mechanism doesn't support read locks then this just
+// calls <acquire>. Returns 0 on success, -1 on failure.
+
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::tryacquire_write_upgrade (void)
+{
+ return this->lock_->tryacquire_write_upgrade ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LOCK_ADAPTER_T_CPP */
diff --git a/ACE/ace/Lock_Adapter_T.h b/ACE/ace/Lock_Adapter_T.h
new file mode 100644
index 00000000000..117684a1a2a
--- /dev/null
+++ b/ACE/ace/Lock_Adapter_T.h
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Lock_Adapter_T.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_LOCK_ADAPTER_T_H
+#define ACE_LOCK_ADAPTER_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Lock.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Lock_Adapter
+ *
+ * @brief This is an adapter that allows applications to transparently
+ * combine the <ACE_Lock> abstract base class (which contains
+ * pure virtual methods) with any of the other concrete ACE
+ * synchronization classes (e.g., ACE_Mutex, ACE_Semaphore,
+ * ACE_RW_Mutex, etc.).
+ *
+ * This class uses a form of the Adapter pattern.
+ */
+template <class ACE_LOCKING_MECHANISM>
+class ACE_Lock_Adapter : public ACE_Lock
+{
+public:
+ typedef ACE_LOCKING_MECHANISM ACE_LOCK;
+
+ // = Initialization/Finalization methods.
+
+ /// Constructor. All locking requests will be forwarded to <lock>.
+ ACE_Lock_Adapter (ACE_LOCKING_MECHANISM &lock);
+
+ /// Constructor. Since no lock is provided by the user, one will be
+ /// created internally.
+ ACE_Lock_Adapter (void);
+
+ /// Destructor. If <lock_> was not passed in by the user, it will be
+ /// deleted.
+ virtual ~ACE_Lock_Adapter (void);
+
+ // = Lock accessors.
+ /// Block the thread until the lock is acquired.
+ virtual int acquire (void);
+
+ /// Conditionally acquire the lock (i.e., won't block).
+ virtual int tryacquire (void);
+
+ /// Release the lock.
+ virtual int release (void);
+
+ /**
+ * Block until the thread acquires a read lock. If the locking
+ * mechanism doesn't support read locks then this just calls
+ * <acquire>.
+ */
+ virtual int acquire_read (void);
+
+ /**
+ * Block until the thread acquires a write lock. If the locking
+ * mechanism doesn't support read locks then this just calls
+ * <acquire>.
+ */
+ virtual int acquire_write (void);
+
+ /// Conditionally acquire a read lock. If the locking mechanism
+ /// doesn't support read locks then this just calls <acquire>.
+ virtual int tryacquire_read (void);
+
+ /// Conditionally acquire a write lock. If the locking mechanism
+ /// doesn't support read locks then this just calls <acquire>.
+ virtual int tryacquire_write (void);
+
+ /**
+ * Conditionally try to upgrade a lock held for read to a write lock.
+ * If the locking mechanism doesn't support read locks then this just
+ * calls <acquire>. Returns 0 on success, -1 on failure.
+ */
+ virtual int tryacquire_write_upgrade (void);
+
+ /// Explicitly destroy the lock.
+ virtual int remove (void);
+
+private:
+ /// The concrete locking mechanism that all the methods delegate to.
+ ACE_LOCKING_MECHANISM *lock_;
+
+ /// This flag keep track of whether we are responsible for deleting
+ /// the lock
+ bool delete_lock_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Lock_Adapter_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Lock_Adapter_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Lock_Adapter_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOCK_ADAPTER_T_H */
diff --git a/ACE/ace/Lock_Adapter_T.inl b/ACE/ace/Lock_Adapter_T.inl
new file mode 100644
index 00000000000..bc7899bffb3
--- /dev/null
+++ b/ACE/ace/Lock_Adapter_T.inl
@@ -0,0 +1,16 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_LOCKING_MECHANISM>
+ACE_INLINE
+ACE_Lock_Adapter<ACE_LOCKING_MECHANISM>::ACE_Lock_Adapter (
+ ACE_LOCKING_MECHANISM &lock)
+ : lock_ (&lock),
+ delete_lock_ (false)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Log_Msg.cpp b/ACE/ace/Log_Msg.cpp
new file mode 100644
index 00000000000..0f2bf798c25
--- /dev/null
+++ b/ACE/ace/Log_Msg.cpp
@@ -0,0 +1,2510 @@
+// $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/Guard_T.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_wchar.h"
+#include "ace/OS_NS_signal.h"
+
+#if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE != 0)
+# include "ace/Object_Manager_Base.h"
+#endif /* ! ACE_MT_SAFE */
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+// FUZZ: disable check_for_streams_include
+# include "ace/streams.h"
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+#if defined (ACE_HAS_TRACE)
+# include "ace/Trace.h"
+#endif /* ACE_HAS_TRACE */
+
+#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"
+#include "ace/Log_Record.h"
+#include "ace/Recursive_Thread_Mutex.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Log_Msg.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Log_Msg, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Log_Msg)
+
+// only used here... dhinton
+#if defined (ACE_HAS_SYS_SIGLIST)
+# if !defined (_sys_siglist)
+# define _sys_siglist sys_siglist
+# endif /* !defined (sys_siglist) */
+//extern char **_sys_siglist;
+#endif /* ACE_HAS_SYS_SIGLIST */
+
+#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)
+
+#if defined (ACE_MVS)
+ static ACE_thread_key_t the_log_msg_tss_key =
+ #if !defined(_LP64)
+ { '\0','\0','\0','\0' };
+ #else
+ { '\0','\0','\0','\0','\0','\0','\0','\0' };
+ #endif
+#else
+ static ACE_thread_key_t the_log_msg_tss_key = 0;
+#endif /* defined (ACE_MVS) */
+
+ACE_thread_key_t *log_msg_tss_key (void)
+{
+ return &the_log_msg_tss_key;
+}
+
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#else
+static ACE_Cleanup_Adapter<ACE_Log_Msg>* log_msg_cleanup = 0;
+class ACE_Msg_Log_Cleanup: public ACE_Cleanup_Adapter<ACE_Log_Msg>
+{
+public:
+ virtual ~ACE_Msg_Log_Cleanup (void) {
+ if (this == log_msg_cleanup)
+ log_msg_cleanup = 0;
+ }
+};
+#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 */
+
+// When doing ACE_OS::s[n]printf() calls in log(), we need to update
+// the space remaining in the output buffer based on what's returned from
+// the output function. If we could rely on more modern compilers, this
+// would be in an unnamed namespace, but it's a macro instead.
+// count is a size_t, len is an int and assumed to be non-negative.
+#define ACE_UPDATE_COUNT(COUNT, LEN) \
+ do { if (static_cast<size_t> (LEN) > COUNT) COUNT = 0; \
+ else COUNT -= static_cast<size_t> (LEN); \
+ } 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;
+
+/**
+ * @class ACE_Log_Msg_Manager
+ *
+ * @brief Synchronize output operations.
+ *
+ * Provides global point of contact for all ACE_Log_Msg instances
+ * in a process.
+ *
+ * For internal use by ACE, only!
+ */
+class ACE_Log_Msg_Manager
+{
+public:
+ static ACE_Log_Msg_Backend *log_backend_;
+ static ACE_Log_Msg_Backend *custom_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)
+ //FUZZ: disable check_for_lack_ACE_OS
+ static void close (void);
+ //FUZZ: enable check_for_lack_ACE_OS
+
+ 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;
+ACE_Log_Msg_Backend *ACE_Log_Msg_Manager::custom_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)
+ {
+ // Sanity check for custom backend.
+ if (ACE_BIT_ENABLED (*flags, ACE_Log_Msg::CUSTOM) &&
+ ACE_Log_Msg_Manager::custom_backend_ == 0)
+ {
+ return -1;
+ }
+
+ 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_LACKS_UNIX_SYSLOG)) && !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 (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;
+
+ // we are never responsible for custom backend
+ ACE_Log_Msg_Manager::custom_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_NAME (void *ptr)
+{
+ // 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
+ 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)
+ void *tss_log_msg = 0; // The actual type is ACE_Log_Msg*, but we need this
+ // void to keep G++ from complaining.
+
+ // Get the tss_log_msg from thread-specific storage.
+ return key_created_
+ && ACE_Thread::getspecific (*(log_msg_tss_key ()), &tss_log_msg) != -1
+ && tss_log_msg != 0;
+# 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 =
+ 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_NAME) != 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;
+ void *temp = 0;
+
+ // Get the tss_log_msg from thread-specific storage.
+ if (ACE_Thread::getspecific (*(log_msg_tss_key ()), &temp) == -1)
+ return 0; // This should not happen!
+
+ tss_log_msg = static_cast <ACE_Log_Msg *> (temp);
+
+ // 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 (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()),
+ 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.
+
+ if (log_msg_cleanup == 0)
+ {
+ ACE_NEW_RETURN (log_msg_cleanup, ACE_Msg_Log_Cleanup, 0);
+ // Register the instance for destruction at program termination.
+ ACE_Object_Manager::at_exit (log_msg_cleanup);
+ }
+
+ return &log_msg_cleanup->object ();
+#endif /* ! ACE_MT_SAFE */
+}
+
+// Not inlined to help prevent having to include OS.h just to
+// get ACE_DEBUG, et al, macros.
+int
+ACE_Log_Msg::last_error_adapter (void)
+{
+ return ACE_OS::last_error ();
+}
+
+// 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_ = -2;
+
+/// Current offset of msg_[].
+ptrdiff_t 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 =
+ 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;
+#ifdef ACE_HAS_BROKEN_THREAD_KEYFREE
+ // for some systems, e.g. LynxOS, we need to ensure that
+ // any registered thread destructor action for this thread
+ // is disabled. Otherwise in the event of a dynamic library
+ // unload of libACE, by a program not linked with libACE,
+ // ACE_TSS_cleanup will be invoked after libACE has been unloaded.
+ ACE_Log_Msg *tss_log_msg = 0;
+ void *temp = 0;
+
+ // Get the tss_log_msg from thread-specific storage.
+ if (ACE_Thread::getspecific (*(log_msg_tss_key ()), &temp) != -1
+ && temp)
+ {
+ tss_log_msg = static_cast <ACE_Log_Msg *> (temp);
+ // we haven't been cleaned up
+ ACE_TSS_CLEANUP_NAME(tss_log_msg);
+ if (ACE_Thread::setspecific(*(log_msg_tss_key()),
+ reinterpret_cast <void *>(0)) != 0)
+ {
+ ACE_OS::printf ("ACE_Log_Msg::close failed to ACE_Thread::setspecific to 0\n");
+ }
+ }
+#endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
+ }
+
+ 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;
+}
+
+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),
+ msg_ (0),
+ restart_ (1), // Restart by default...
+ ostream_ (0),
+ msg_callback_ (0),
+ trace_depth_ (0),
+ trace_active_ (false),
+ tracing_enabled_ (true), // On by default?
+ delete_ostream_(false),
+ thr_desc_ (0),
+ priority_mask_ (default_priority_mask_),
+ timestamp_ (0)
+{
+ // 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_ = false;
+
+ char *timestamp = ACE_OS::getenv ("ACE_LOG_TIMESTAMP");
+ if (timestamp != 0)
+ {
+ // If variable is set or is set to date tag so we print date and time.
+ if (ACE_OS::strcmp (timestamp, "TIME") == 0)
+ {
+ this->timestamp_ = 1;
+ }
+ else if (ACE_OS::strcmp (timestamp, "DATE") == 0)
+ {
+ this->timestamp_ = 2;
+ }
+ }
+
+ ACE_NEW_NORETURN (this->msg_, ACE_TCHAR[ACE_MAXLOGMSGLEN+1]);
+}
+
+ACE_Log_Msg::~ACE_Log_Msg (void)
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ int instance_count = 0;
+
+ // 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 ();
+
+ // Close down custom backend
+ if (ACE_Log_Msg_Manager::custom_backend_ != 0)
+ ACE_Log_Msg_Manager::custom_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_)
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ {
+ ACE_OS::fclose (this->ostream_);
+ }
+#else
+ {
+ delete ostream_;
+ ostream_ = 0;
+ }
+#endif
+
+ delete[] this->msg_;
+}
+
+// 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_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.
+ if (ACE_Log_Msg_Manager::log_backend_ != 0)
+ ACE_Log_Msg_Manager::log_backend_->reset ();
+
+ if (ACE_Log_Msg_Manager::custom_backend_ != 0)
+ ACE_Log_Msg_Manager::custom_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 - they will default to prog_name if
+ // logger key is 0.
+ 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
+ {
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER))
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER);
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::SYSLOG))
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG);
+ }
+ }
+ else if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER)
+ || ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG))
+ {
+ // If we are closing down logger, redirect logging to stderr.
+ ACE_CLR_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER);
+ ACE_CLR_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG);
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR);
+ }
+
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::CUSTOM))
+ {
+ status =
+ ACE_Log_Msg_Manager::custom_backend_->open (logger_key);
+
+ if (status != -1)
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::CUSTOM);
+ }
+
+ // 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!)
+ * 'b': print a ssize_t value
+ * 'B': print a size_t value
+ * '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
+ * 'q': print out the int64 number
+ * '@': print a void* pointer (in hexadecimal)
+ * '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': print as a hex number
+ * 'X': print as a hex number
+ * 'w': print a wide character
+ * 'W': print out a wide character string.
+ * 'z': print an ACE_OS::WChar character
+ * 'Z': print an ACE_OS::WChar character string
+ * ':': print a time_t value as an integral number
+ * '%': 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);
+
+ ssize_t const 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);
+
+ ssize_t const 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.
+
+ typedef void (*PTF)(...);
+
+ // Check if there were any conditional values set.
+ bool const conditional_values = this->conditional_values_.is_set_;
+
+ // Reset conditional values.
+ this->conditional_values_.is_set_ = false;
+
+ // 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 supposed to be a benign activity (i.e., not interfer
+ // with normal application operations), so don't inadvertently smash
+ // errno!
+ ACE_Errno_Guard guard (errno);
+
+ ACE_Log_Record log_record (log_priority,
+ ACE_OS::gettimeofday (),
+ this->getpid ());
+
+ // bp is pointer to where to put next part of logged message.
+ // bspace is the number of characters remaining in msg_.
+ ACE_TCHAR *bp = const_cast<ACE_TCHAR *> (this->msg ());
+ size_t bspace = ACE_Log_Record::MAXLOGMSGLEN; // Leave room for Nul term.
+ if (this->msg_off_ <= ACE_Log_Record::MAXLOGMSGLEN)
+ bspace -= static_cast<size_t> (this->msg_off_);
+
+ // If this platform has snprintf() capability to prevent overrunning the
+ // output buffer, use it. To avoid adding a maintenance-hassle compile-
+ // time couple between here and OS.cpp, don't try to figure this out at
+ // compile time. Instead, do a quick check now; if we get a -1 return,
+ // the platform doesn't support the length-limiting capability.
+ ACE_TCHAR test[2];
+ bool can_check = ACE_OS::snprintf (test, 1, ACE_TEXT ("x")) != -1;
+
+ bool abort_prog = false;
+ 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_;
+ bspace > 1 && (*bp = *s) != '\0';
+ ++s, --bspace)
+ bp++;
+
+ *bp++ = '|';
+ --bspace;
+ }
+ }
+
+ if (timestamp_ > 0)
+ {
+ ACE_TCHAR day_and_time[35];
+ const ACE_TCHAR *s;
+ if (timestamp_ == 1)
+ {
+ // Print just the time
+ s = ACE::timestamp (day_and_time, sizeof day_and_time, 1);
+ }
+ else
+ {
+ // Print time and date
+ ACE::timestamp (day_and_time, sizeof day_and_time);
+ s = day_and_time;
+ }
+
+ for (; bspace > 1 && (*bp = *s) != '\0'; ++s, --bspace)
+ ++bp;
+
+ *bp++ = '|';
+ --bspace;
+ }
+
+ while (*format_str != '\0' && bspace > 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++;
+ --bspace;
+ }
+ else if (format_str[1] == '%') // An "escaped" '%' (just print one '%').
+ {
+ *bp++ = *format_str++; // Store first %
+ ++format_str; // but skip second %
+ --bspace;
+ }
+ 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 *abort_str = ACE_TEXT ("Aborting...");
+ 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
+ bool done = false;
+ bool skip_nul_locate = false;
+ int this_len = 0; // How many chars s[n]printf wrote
+
+ fp = format;
+ *fp++ = *format_str++; // Copy in the %
+
+ // Initialization to satisfy VC6
+ int tmp_indent = 0;
+ // 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 = true; // 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 = false;
+ break;
+
+ case '*':
+ wp = va_arg (argp, int);
+ ACE_OS::sprintf (fp, ACE_TEXT ("%d"), wp);
+ fp += ACE_OS::strlen (fp);
+ done = false;
+ break;
+
+ case 'A': // ACE_timer_t
+ {
+ ACE_OS::strcpy (fp, ACE_TEXT ("f"));
+ double value = va_arg (argp, double);
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format, value);
+ else
+ this_len = ACE_OS::sprintf (bp, format, value);
+ ACE_UPDATE_COUNT (bspace, this_len);
+ }
+ break;
+
+ case 'a': // Abort program after handling all of format string.
+ abort_prog = true;
+ exit_value = va_arg (argp, int);
+ ACE_OS::strsncpy (bp, abort_str, bspace);
+ if (bspace > ACE_OS::strlen (abort_str))
+ bspace -= ACE_OS::strlen (abort_str);
+ else
+ bspace = 0;
+ break;
+
+ case 'l': // Source file line number
+ ACE_OS::strcpy (fp, ACE_TEXT ("d"));
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp,
+ bspace,
+ format,
+ this->linenum ());
+ else
+ this_len = ACE_OS::sprintf (bp, format, this->linenum ());
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'N': // Source file name
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
+#else
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format,
+ this->file () ?
+ ACE_TEXT_CHAR_TO_TCHAR (this->file ())
+ : ACE_TEXT ("<unknown file>"));
+ else
+ this_len = ACE_OS::sprintf (bp, format,
+ this->file () ?
+ ACE_TEXT_CHAR_TO_TCHAR (this->file ())
+ : ACE_TEXT ("<unknown file>"));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'n': // Program name
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format,
+ ACE_Log_Msg::program_name_ ?
+ ACE_Log_Msg::program_name_ :
+ ACE_TEXT ("<unknown>"));
+ else
+ this_len = ACE_OS::sprintf (bp, format,
+ ACE_Log_Msg::program_name_ ?
+ ACE_Log_Msg::program_name_ :
+ ACE_TEXT ("<unknown>"));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'P': // Process ID
+#if defined (ACE_OPENVMS)
+ // Print the process id in hex on OpenVMS.
+ ACE_OS::strcpy (fp, ACE_TEXT ("x"));
+#else
+ ACE_OS::strcpy (fp, ACE_TEXT ("d"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ static_cast<int> (this->getpid ()));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, static_cast<int> (this->getpid ()));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'p': // <errno> string, ala perror()
+ {
+ errno = 0;
+ char *msg = ACE_OS::strerror (ACE::map_errno (this->errnum ()));
+ // Windows can try to translate the errnum using
+ // system calls if strerror() doesn't get anything useful.
+#if defined (ACE_WIN32)
+ if (errno == 0)
+ {
+#endif
+
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls: %ls"));
+#else
+ ACE_OS::strcpy (fp, ACE_TEXT ("s: %s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, ACE_TCHAR *),
+ ACE_TEXT_CHAR_TO_TCHAR (msg));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, ACE_TCHAR *),
+ ACE_TEXT_CHAR_TO_TCHAR (msg));
+#if defined (ACE_WIN32)
+ }
+ else
+ {
+ errno = ACE::map_errno (this->errnum ());
+ 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,
+ 0,
+ errno,
+ MAKELANGID (LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ // Default language
+ (ACE_TCHAR *) &lpMsgBuf,
+ 0,
+ 0);
+# 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_TEXT ("s: %s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ va_arg (argp, const ACE_TCHAR *),
+ message);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format,
+ va_arg (argp, const ACE_TCHAR *),
+ message);
+ }
+ else
+ {
+ ACE_OS::strcpy (fp, ACE_TEXT ("s: %s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ va_arg (argp, ACE_TCHAR *),
+ lpMsgBuf);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format,
+ va_arg (argp, ACE_TCHAR *),
+ lpMsgBuf);
+ // Free the buffer.
+ ::LocalFree (lpMsgBuf);
+ }
+ }
+#endif /* ACE_WIN32 */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'M': // Print the name of the priority of the message.
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
+#else
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ ACE_Log_Record::priority_name (log_priority));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format,
+ ACE_Log_Record::priority_name (log_priority));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'm': // Format the string assocated with the errno value.
+ {
+ errno = 0;
+ char *msg = 0;
+ msg = ACE_OS::strerror (ACE::map_errno (this->errnum ()));
+ // Windows can try to translate the errnum using
+ // system calls if strerror() doesn't get anything useful.
+#if defined (ACE_WIN32)
+ if (errno == 0)
+ {
+#endif
+
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, ACE_TEXT_CHAR_TO_TCHAR (msg));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, ACE_TEXT_CHAR_TO_TCHAR (msg));
+#if defined (ACE_WIN32)
+ }
+ else
+ {
+ errno = ACE::map_errno (this->errnum ());
+ 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,
+ 0,
+ errno,
+ MAKELANGID (LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ // Default language
+ (ACE_TCHAR *) &lpMsgBuf,
+ 0,
+ 0);
+# 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_TEXT ("s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, message);
+ else
+ this_len = ACE_OS::sprintf (bp, format, message);
+ }
+ else
+ {
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, lpMsgBuf);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, lpMsgBuf);
+ // Free the buffer.
+ ::LocalFree (lpMsgBuf);
+ }
+ }
+#endif /* ACE_WIN32 */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'R': // Format the return status of the operation.
+ this->op_status (va_arg (argp, int));
+ ACE_OS::strcpy (fp, ACE_TEXT ("d"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, this->op_status ());
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, this->op_status ());
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case '{': // Increment the trace_depth, then indent
+ skip_nul_locate = true;
+ (void) this->inc ();
+ break;
+
+ case '}': // indent, then decrement trace_depth
+ skip_nul_locate = true;
+ (void) this->dec ();
+ break;
+
+ case '$': // insert a newline, then indent the next line
+ // according to %I
+ *bp++ = '\n';
+ --bspace;
+ /* 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 defined (ACE_HAS_TRACE)
+ if (0 == wp)
+ wp = ACE_Trace::get_nesting_indent ();
+#else
+ if (0 == wp)
+ wp = 4;
+#endif /* ACE_HAS_TRACE */
+ wp *= this->trace_depth_;
+ if (static_cast<size_t> (wp) > bspace)
+ wp = static_cast<int> (bspace);
+ for (tmp_indent = wp;
+ tmp_indent;
+ --tmp_indent)
+ *bp++ = ' ';
+
+ *bp = '\0';
+ bspace -= static_cast<size_t> (wp);
+ skip_nul_locate = true;
+ break;
+
+ case 'r': // Run (invoke) this subroutine.
+ {
+ ptrdiff_t const osave = ACE_Log_Msg::msg_off_;
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT) &&
+ bspace > 1)
+ {
+ *bp++ = '{';
+ --bspace;
+ }
+ ACE_Log_Msg::msg_off_ = bp - this->msg_;
+
+ (*va_arg (argp, PTF))();
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT) &&
+ bspace > (1 + ACE_OS::strlen (bp)))
+ {
+ bspace -= (ACE_OS::strlen (bp) + 1);
+ bp += ACE_OS::strlen (bp);
+ *bp++ = '}';
+ }
+ *bp = '\0';
+ skip_nul_locate = true;
+ 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_TEXT ("s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, _sys_siglist[sig]);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, _sys_siglist[sig]);
+ }
+ else
+ {
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace,
+ ACE_TEXT("<unknown signal> %d"), sig);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, ACE_TEXT ("<unknown signal> %d"), sig);
+ }
+#else
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, ACE_TEXT ("signal %d"), sig);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, ACE_TEXT ("signal %d"), sig);
+#endif /* ACE_HAS_SYS_SIGLIST */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'D': // Format the timestamp in format:
+ // Weekday Month day year hour:minute:sec.usec
+ {
+ ACE_TCHAR day_and_time[35];
+ ACE::timestamp (day_and_time,
+ sizeof day_and_time);
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
+#else
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, day_and_time);
+ else
+ this_len = ACE_OS::sprintf (bp, format, day_and_time);
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'T': // Format the timestamp in
+ // hour:minute:sec:usec format.
+ {
+ ACE_TCHAR day_and_time[35];
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ ACE::timestamp (day_and_time, sizeof day_and_time));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, ACE::timestamp (day_and_time,
+ sizeof day_and_time));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 't': // Format thread id.
+#if defined (ACE_WIN32)
+ ACE_OS::strcpy (fp, ACE_TEXT ("u"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ static_cast<unsigned> (ACE_Thread::self ()));
+ else
+ this_len =
+ ACE_OS::sprintf (bp,
+ format,
+ static_cast <unsigned> (ACE_Thread::self ()));
+#elif defined (DIGITAL_UNIX)
+ ACE_OS::strcpy (fp, ACE_TEXT ("u"));
+ {
+ int id =
+# if defined (ACE_HAS_THREADS)
+ pthread_getselfseq_np ();
+# else
+ ACE_Thread::self ();
+# endif /* ACE_HAS_THREADS */
+
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format, id);
+ else
+ this_len = ACE_OS::sprintf (bp, format, id);
+ }
+#else
+ ACE_hthread_t t_id;
+ ACE_Thread::self (t_id);
+
+# if defined (ACE_MVS) || defined (ACE_TANDEM_T1248_PTHREADS)
+ // MVS's pthread_t is a struct... yuck. So use the ACE 5.0
+ // code for it.
+ ACE_OS::strcpy (fp, ACE_TEXT ("u"));
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format, t_id);
+ else
+ this_len = 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_TEXT ("lu"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, (unsigned long)t_id);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, (unsigned long)t_id);
+# endif /* ACE_MWS || ACE_TANDEM_T1248_PTHREADS */
+
+#endif /* ACE_WIN32 */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 's': // String
+ {
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ wchar_t *str = va_arg (argp, wchar_t *);
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_TCHAR *str = va_arg (argp, ACE_TCHAR *);
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, str ? str : ACE_TEXT ("(null)"));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, str ? str : ACE_TEXT ("(null)"));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ }
+ break;
+
+ case 'C': // Char string, Unicode for Win32/WCHAR
+ {
+ ACE_TCHAR *cstr = va_arg (argp, ACE_TCHAR *);
+#if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("S"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, cstr ? cstr : ACE_TEXT ("(null)"));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, cstr ? cstr : ACE_TEXT ("(null)"));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ }
+ break;
+
+ case 'W':
+ {
+#if defined (ACE_HAS_WCHAR)
+ wchar_t *wchar_str = va_arg (argp, wchar_t *);
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_TEXT ("S"));
+# elif defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_TEXT ("S"));
+# endif /* ACE_USES_WCHAR */
+# else
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
+# endif /* HPUX */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, wchar_str ? wchar_str : ACE_TEXT_WIDE("(null)"));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, wchar_str ? wchar_str : ACE_TEXT_WIDE("(null)"));
+#endif /* ACE_HAS_WCHAR */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ }
+ break;
+
+ case 'w': // Wide character
+#if defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("c"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_TEXT ("C"));
+# endif /* ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, int));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, int));
+#elif defined (ACE_USES_WCHAR)
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_TEXT ("C"));
+# else
+ ACE_OS::strcpy (fp, ACE_TEXT ("lc"));
+# endif /* HPUX */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, wint_t));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, wint_t));
+#else /* ACE_WIN32 */
+ ACE_OS::strcpy (fp, ACE_TEXT ("u"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, int));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, int));
+#endif /* ACE_WIN32 */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'z': // ACE_OS::WChar character
+ {
+ // On some platforms sizeof (wchar_t) can be 2
+ // on the others 4 ...
+ wchar_t wtchar =
+ static_cast<wchar_t> (va_arg (argp, int));
+#if defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("c"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_TEXT ("C"));
+# endif /* ACE_USES_WCHAR */
+#elif defined (ACE_USES_WCHAR)
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_TEXT ("C"));
+# else
+ ACE_OS::strcpy (fp, ACE_TEXT ("lc"));
+# endif /* HPUX */
+#else /* ACE_WIN32 */
+ ACE_OS::strcpy (fp, ACE_TEXT ("u"));
+#endif /* ACE_WIN32 */
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format, wtchar);
+ else
+ this_len = ACE_OS::sprintf (bp, format, wtchar);
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'Z': // ACE_OS::WChar character string
+ {
+ ACE_OS::WChar *wchar_str = va_arg (argp, ACE_OS::WChar*);
+ if (wchar_str == 0)
+ break;
+
+ wchar_t *wchar_t_str = 0;
+ if (sizeof (ACE_OS::WChar) != sizeof (wchar_t))
+ {
+ size_t len = ACE_OS::wslen (wchar_str) + 1;
+ ACE_NEW_NORETURN(wchar_t_str, wchar_t[len]);
+ if (wchar_t_str == 0)
+ break;
+
+ for (size_t i = 0; i < len; ++i)
+ {
+ wchar_t_str[i] = wchar_str[i];
+ }
+ }
+
+ if (wchar_t_str == 0)
+ {
+ wchar_t_str = reinterpret_cast<wchar_t*> (wchar_str);
+ }
+#if defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("s"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_TEXT ("S"));
+# endif /* ACE_USES_WCHAR */
+#elif defined (ACE_HAS_WCHAR)
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_TEXT ("S"));
+# else
+ ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
+# endif /* HPUX */
+#endif /* ACE_WIN32 / ACE_HAS_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, wchar_t_str);
+ else
+ this_len = ACE_OS::sprintf (bp, format, wchar_t_str);
+ if(sizeof(ACE_OS::WChar) != sizeof(wchar_t))
+ {
+ delete [] wchar_t_str;
+ }
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'c':
+#if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_TEXT ("C"));
+#else
+ ACE_OS::strcpy (fp, ACE_TEXT ("c"));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, int));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, int));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'd': case 'i': case 'o':
+ case 'u': case 'x': case 'X':
+ fp[0] = *format_str;
+ fp[1] = '\0';
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, int));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, int));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'F': case 'f': case 'e': case 'E':
+ case 'g': case 'G':
+ fp[0] = *format_str;
+ fp[1] = '\0';
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, double));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, double));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'Q':
+#if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_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)
+ this_len = ACE_OS::sprintf (bp,
+ "0x%lx%0*lx",
+ hi,
+ 2 * sizeof lo,
+ lo);
+ else
+ this_len = 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 %
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace,
+ format,
+ va_arg (argp, ACE_UINT64));
+ else
+ this_len = ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, ACE_UINT64));
+ }
+#endif /* ! ACE_LACKS_LONGLONG_T || ACE_LACKS_UNSIGNEDLONGLONG_T */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'q':
+ #if defined (ACE_LACKS_LONGLONG_T)
+ // No implementation available yet, no ACE_INT64 emulation
+ // available yet
+ #else /* ! ACE_LACKS_LONGLONG_T */
+ {
+ const ACE_TCHAR *fmt = ACE_INT64_FORMAT_SPECIFIER;
+ ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace,
+ format,
+ va_arg (argp, ACE_INT64));
+ else
+ this_len = ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, ACE_INT64));
+ }
+ #endif /* ! ACE_LACKS_LONGLONG_T */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'b':
+ {
+ const ACE_TCHAR *fmt = ACE_SSIZE_T_FORMAT_SPECIFIER;
+ ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
+ }
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace,
+ format,
+ va_arg (argp, ssize_t));
+ else
+ this_len = ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, ssize_t));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'B':
+ {
+ const ACE_TCHAR *fmt = ACE_SIZE_T_FORMAT_SPECIFIER;
+ ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
+ }
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace,
+ format,
+ va_arg (argp, size_t));
+ else
+ this_len = ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, size_t));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case ':':
+ {
+ // Assume a 32 bit time_t and change if needed.
+ const ACE_TCHAR *fmt = ACE_TEXT ("%d");
+ if (sizeof (time_t) == 8)
+ fmt = ACE_INT64_FORMAT_SPECIFIER;
+
+ ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
+ }
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace,
+ format,
+ va_arg (argp, time_t));
+ else
+ this_len = ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, time_t));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case '@':
+ ACE_OS::strcpy (fp, ACE_TEXT ("p"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, void*));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, void*));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ 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 && bspace > 0)
+ {
+ *bp++ = *start_format++;
+ --bspace;
+ }
+ if (bspace > 0)
+ {
+ *bp++ = *format_str;
+ --bspace;
+ }
+ 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!
+
+ ssize_t result = 0;
+
+ // Check that memory was not corrupted, if it corrupted we can't log anything
+ // anymore because all our members could be corrupted.
+ if (bp >= (this->msg_ + ACE_MAXLOGMSGLEN+1))
+ {
+ abort_prog = true;
+ ACE_OS::fprintf (stderr,
+ "The following logged message is too long!\n");
+ }
+ else
+ {
+ // 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.
+ 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, stderr);
+ ACE_OS::abort ();
+ }
+
+ return result;
+}
+
+#if !defined (ACE_WIN32)
+/**
+ * @class ACE_Log_Msg_Sig_Guard
+ *
+ * @brief For use only by ACE_Log_Msg.
+ *
+ * Doesn't require the use of global variables or global
+ * functions in an application).
+ */
+class ACE_Log_Msg_Sig_Guard
+{
+private:
+ ACE_Log_Msg_Sig_Guard (void);
+ ~ACE_Log_Msg_Sig_Guard (void);
+
+ /// Original signal mask.
+ sigset_t omask_;
+
+ 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))
+ {
+ bool 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 */
+
+ // Do the callback, if needed, before acquiring the lock
+ // to avoid holding the lock during the callback so we don't
+ // have deadlock if the callback uses the logger.
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::MSG_CALLBACK)
+ && this->msg_callback () != 0)
+ this->msg_callback ()->log (log_record);
+
+ // 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_,
+ stderr);
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::CUSTOM) ||
+ ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG) ||
+ 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 ());
+ }
+
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER) ||
+ ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG))
+ {
+ result =
+ ACE_Log_Msg_Manager::log_backend_->log (log_record);
+ }
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::CUSTOM) &&
+ ACE_Log_Msg_Manager::custom_backend_ != 0)
+ {
+ result =
+ ACE_Log_Msg_Manager::custom_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)
+ static_cast<FILE *> (this->msg_ostream ())
+#else /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+ *this->msg_ostream ()
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+ );
+
+ 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,
+ size_t size,
+ const ACE_TCHAR *text)
+{
+ // 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;
+
+ ACE_TCHAR* buf = 0;
+ const size_t buf_sz =
+ ACE_Log_Record::MAXLOGMSGLEN - ACE_Log_Record::VERBOSE_LEN - 58;
+ ACE_NEW_RETURN (buf, ACE_TCHAR[buf_sz], -1);
+
+ ACE_TCHAR *msg_buf = 0;
+ const 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
+
+ const size_t len = ACE::format_hexdump
+ (buffer, size, buf, buf_sz / sizeof (ACE_TCHAR) - text_sz);
+
+ int sz = 0;
+
+ if (text)
+ sz = ACE_OS::sprintf (msg_buf,
+ ACE_TEXT ("%s - "),
+ text);
+
+ sz += ACE_OS::sprintf (msg_buf + sz,
+ ACE_TEXT ("HEXDUMP ")
+ ACE_SIZE_T_FORMAT_SPECIFIER
+ ACE_TEXT (" bytes"),
+ size);
+
+ if (len < size)
+ ACE_OS::sprintf (msg_buf + sz,
+ ACE_TEXT (" (showing first ")
+ ACE_SIZE_T_FORMAT_SPECIFIER
+ ACE_TEXT (" bytes)"),
+ len);
+
+ // Now print out the formatted buffer.
+ this->log (log_priority,
+ ACE_TEXT ("%s\n%s"),
+ msg_buf,
+ buf);
+
+ delete [] msg_buf;
+ delete [] 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_ = true;
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Log_Msg::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("status_ = %d\n"), this->status_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nerrnum_ = %d\n"), this->errnum_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nlinenum_ = %d\n"), this->linenum_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nfile_ = %C\n"), this->file_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmsg_ = %s\n"), this->msg_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nrestart_ = %d\n"), this->restart_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nostream_ = %@\n"), this->ostream_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmsg_callback_ = %@\n"),
+ this->msg_callback_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nprogram_name_ = %s\n"),
+ this->program_name_ ? this->program_name_
+ : ACE_TEXT ("<unknown>")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nlocal_host_ = %s\n"),
+ this->local_host_ ? this->local_host_
+ : ACE_TEXT ("<unknown>")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\npid_ = %d\n"), this->getpid ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags_ = 0x%x\n"), this->flags_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntrace_depth_ = %d\n"),
+ this->trace_depth_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntrace_active_ = %d\n"),
+ this->trace_active_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntracing_enabled_ = %d\n"),
+ this->tracing_enabled_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\npriority_mask_ = 0x%x\n"),
+ this->priority_mask_));
+ if (this->thr_desc_ != 0 && this->thr_desc_->state () != 0)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_state_ = %d\n"),
+ this->thr_desc_->state ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_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));
+#endif /* ACE_HAS_DUMP */
+}
+
+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 */
+
+ACE_Log_Msg_Backend *
+ACE_Log_Msg::msg_backend (ACE_Log_Msg_Backend *b)
+{
+ ACE_TRACE ("ACE_Log_Msg::msg_backend");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (), 0));
+
+ ACE_Log_Msg_Backend *tmp = ACE_Log_Msg_Manager::custom_backend_;
+ ACE_Log_Msg_Manager::custom_backend_ = b;
+ return tmp;
+}
+
+ACE_Log_Msg_Backend *
+ACE_Log_Msg::msg_backend (void)
+{
+ ACE_TRACE ("ACE_Log_Msg::msg_backend");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (), 0));
+
+ return ACE_Log_Msg_Manager::custom_backend_;
+}
+
+void
+ACE_Log_Msg::msg_ostream (ACE_OSTREAM_TYPE *m, bool delete_ostream)
+{
+ if (this->ostream_ == m)
+ return;
+
+ if (this->delete_ostream_)
+ {
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ ACE_OS::fclose (this->ostream_);
+#else
+ delete this->ostream_;
+#endif
+ }
+
+ this->delete_ostream_ = delete_ostream;
+ 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));
+ }
+ }
+}
+
+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 ();
+ }
+}
+
+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 (static_cast<ACE_Thread_Descriptor *> (thr_desc));
+ // Block the thread from proceeding until
+ // thread manager has thread descriptor ready.
+#endif /* ! ACE_THREADS_DONT_INHERIT_LOG_MSG && ! ACE_HAS_MINIMAL_ACE_OS */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Log_Msg.h b/ACE/ace/Log_Msg.h
new file mode 100644
index 00000000000..6084902bf30
--- /dev/null
+++ b/ACE/ace/Log_Msg.h
@@ -0,0 +1,746 @@
+// -*- 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"
+#include /**/ "ace/ACE_export.h"
+#include "ace/Global_Macros.h"
+#include "ace/Default_Constants.h"
+#include "ace/Log_Priority.h"
+#include "ace/os_include/os_limits.h"
+
+// The ACE_ASSERT macro used to be defined here, include ace/Assert.h
+// for backwards compatibility.
+#include "ace/Assert.h"
+
+#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
+#if !defined (ACE_HEX_DUMP)
+#define ACE_HEX_DUMP(X) \
+ do { \
+ int __ace_error = ACE_Log_Msg::last_error_adapter (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->conditional_set (__FILE__, __LINE__, 0, __ace_error); \
+ ace___->log_hexdump X; \
+ } while (0)
+#endif
+#if !defined (ACE_RETURN)
+#define ACE_RETURN(Y) \
+ do { \
+ int __ace_error = ACE_Log_Msg::last_error_adapter (); \
+ 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)
+#endif
+#if !defined (ACE_ERROR_RETURN)
+#define ACE_ERROR_RETURN(X, Y) \
+ do { \
+ int __ace_error = ACE_Log_Msg::last_error_adapter (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->conditional_set (__FILE__, __LINE__, Y, __ace_error); \
+ ace___->log X; \
+ return Y; \
+ } while (0)
+#endif
+#if !defined (ACE_ERROR)
+#define ACE_ERROR(X) \
+ do { \
+ int __ace_error = ACE_Log_Msg::last_error_adapter (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->conditional_set (__FILE__, __LINE__, -1, __ace_error); \
+ ace___->log X; \
+ } while (0)
+#endif
+#if !defined (ACE_DEBUG)
+#define ACE_DEBUG(X) \
+ do { \
+ int __ace_error = ACE_Log_Msg::last_error_adapter (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->conditional_set (__FILE__, __LINE__, 0, __ace_error); \
+ ace___->log X; \
+ } while (0)
+#endif
+#if !defined (ACE_ERROR_INIT)
+#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)
+#endif
+#if !defined (ACE_ERROR_BREAK)
+#define ACE_ERROR_BREAK(X) { ACE_ERROR (X); break; }
+#endif
+#endif /* ACE_NLOGGING */
+
+#include "ace/OS_Log_Msg_Attributes.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// These workarounds are necessary for nasty libraries or platforms
+// that #define STDERR or THREAD (e.g. LynxOS). We simply #undef
+// these macros as there is no way to save the macro definition using
+// the pre-processor. See Bugzilla Bug #299 for more info.
+
+#if defined (STDERR)
+# undef STDERR
+#endif /* STDERR */
+
+#if defined (THREAD)
+# undef THREAD
+#endif /* THREAD */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Log_Msg_Callback;
+class ACE_Log_Msg_Backend;
+
+// ****************************************************************
+
+#define ACE_LOG_MSG ACE_Log_Msg::instance ()
+
+// Forward declaration
+class ACE_Thread_Descriptor;
+class ACE_Log_Record;
+
+/**
+ * @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 stderr, cerr, a distributed logger, etc. The
+ * current message is also kept in a thread-specific storage location
+ * (threads spawned using ACE_Thread_Manager automatically get an
+ * ACE_Log_Msg object that inherits the spawning thread's settings),
+ * 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 @c priority_mask_ object attribute is
+ * thread- specific and specifies the priority levels logged by the
+ * thread. The @c 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 @c priority_mask_ and all levels are enabled for @c
+ * 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,
+ /// Write messages to the user provided backend
+ CUSTOM = 256
+ };
+
+ // = Initialization and termination routines.
+
+ /// Returns a pointer to the Singleton.
+ static ACE_Log_Msg *instance (void);
+
+ /// Returns last error.
+ static int last_error_adapter (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 options_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 if the LOGGER bit is set in the @a flags
+ * argument. If the SYSLOG bit is set in @a flags,
+ * @a logger_key is the source/program name specified
+ * in the syslog facility (UNIX/Linux) or the Windows
+ * event log (Windows). In the SYSLOG case, if
+ * @a logger_key is 0, @a prog_name is used.
+ */
+ 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.
+ */
+ void set_flags (u_long f);
+
+ /**
+ * Disable the bits in the logger's options flags.
+ */
+ void clr_flags (u_long f);
+
+ /**
+ * Return the bits in the logger's options flags.
+ */
+ 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 @c fork() to resynchronize the process id and
+ /// @c 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) const;
+
+ /// 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) const;
+
+ /// Set the line number where an error occurred.
+ void linenum (int);
+
+ /// Get the line number where an error occurred.
+ int linenum (void) const;
+
+ /// 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) const;
+
+ // = 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 == true, 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 *, bool 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 objects 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;
+
+ /**
+ * Set a new backend object and return the existing backend to
+ * allow "chaining". Note that as opposed to ACE_Log_Msg_Callback,
+ * ACE_Log_Msg_Backend is a per-process entity.
+ *
+ * @note Be aware that because of the current architecture there is
+ * no guarantee that open (), reset () and close () will be called
+ * on a backend object.
+ *
+ */
+ static ACE_Log_Msg_Backend *msg_backend (ACE_Log_Msg_Backend *b);
+ static ACE_Log_Msg_Backend *msg_backend (void);
+
+ /// Nesting depth increment.
+ int inc (void);
+
+ /// Nesting depth decrement.
+ int dec (void);
+
+ /// Get trace depth.
+ int trace_depth (void) const;
+
+ /// Set trace depth.
+ void trace_depth (int);
+
+ /// Set trace active status.
+ bool trace_active (void) const;
+
+ /// Get trace active status.
+ void trace_active (bool 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 TSS exception action.
+ /// @note The action is no longer TSS, they are global!
+ ACE_SEH_EXCEPT_HANDLER seh_except_selector (void);
+
+ /// Set TSS exception action.
+ /// @note The action is no longer TSS, they are global!
+ ACE_SEH_EXCEPT_HANDLER seh_except_selector (ACE_SEH_EXCEPT_HANDLER);
+
+ /// Get TSS exception handler.
+ /// @note The handler is no longer TSS, they are global!
+ ACE_SEH_EXCEPT_HANDLER seh_except_handler (void);
+
+ /// Set TSS exception handler.
+ /// @note The handler is no longer TSS, they are global!
+ ACE_SEH_EXCEPT_HANDLER seh_except_handler (ACE_SEH_EXCEPT_HANDLER);
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS && ACE_LEGACY_MODE */
+
+ /// Stop tracing status on a per-thread basis...
+ void stop_tracing (void);
+
+ /// Start tracing status on a per-thread basis...
+ void start_tracing (void);
+
+ /// Query tracing status on a per-thread basis...
+ bool tracing_enabled (void) const;
+
+ typedef enum
+ {
+ PROCESS = 0,
+ THREAD = 1
+ } MASK_TYPE;
+
+ // = Get/set the priority mask.
+ /// Get the current ACE_Log_Priority mask.
+ u_long priority_mask (MASK_TYPE = THREAD);
+
+ /// Set the ACE_Log_Priority mask, returns original mask.
+ 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;
+
+ /// Get the name of the local host.
+ const ACE_TCHAR *local_host (void) const;
+
+ /// Set the name of the local host.
+ 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.
+ * - 'b': print a ssize_t value
+ * - 'B': print a size_t value
+ * - '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
+ * - 'q': print out the int64 number
+ * - '@': print a void* pointer (in hexadecimal)
+ * - '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 as Weekday Month day year hour:minute:sec.usec
+ * - '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': print as a hex number
+ * - 'X': print as a hex number
+ * - 'z': print an ACE_OS::WChar character
+ * - 'Z': print an ACE_OS::WChar character string
+ * - ':': print a time_t value as an integral 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,
+ size_t 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
+ * @a attributes argument
+ */
+ );
+
+ /**
+ * Inherit hook, the @a attributes field is a ACE_OS_Log_Msg_Attributes
+ * object, invoke the inherit_log_msg() method on it, then destroy
+ * it and set the @a 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_; // 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?
+ bool trace_active_;
+
+ /// Are we allowing tracing in this thread?
+ bool tracing_enabled_;
+
+ /// Are we deleting this ostream?
+ bool 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_;
+
+ /// Always timestamp?
+ int timestamp_;
+
+ // = 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 used to hold the logger flag options, e.g.,
+ /// STDERR, LOGGER, OSTREAM, MSG_CALLBACK, etc.
+ static u_long flags_;
+
+ /// Offset of msg_[].
+ static ptrdiff_t msg_off_;
+
+ /**
+ * Number of existing ACE_Log_Msg instances; when 0, delete program/host
+ * names
+ */
+ static int instance_count_;
+
+ /**
+ * Priority mask to use for each new instance
+ */
+ 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
+ {
+ bool 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_;
+#endif /* ACE_MT_SAFE */
+
+ /// For cleanup, at program termination.
+ static void close (void);
+
+ /// Decouple the OS layer from the ACE_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 &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#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 */
+
+#if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
+# define ACE_TSS_CLEANUP_NAME ACE_PREPROC_CONCATENATE(ACE_,ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _TSS_cleanup))
+#else
+# define ACE_TSS_CLEANUP_NAME ACE_TSS_cleanup
+#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+
+LOCAL_EXTERN_PREFIX
+void
+ACE_TSS_CLEANUP_NAME (void *ptr);
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#endif /* ACE_MT_SAFE */
+
+#if defined(ACE_LEGACY_MODE)
+#include "ace/Log_Msg_Callback.h"
+#endif /* ACE_LEGACY_MODE */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Log_Msg.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOG_MSG_H */
diff --git a/ACE/ace/Log_Msg.inl b/ACE/ace/Log_Msg.inl
new file mode 100644
index 00000000000..677a6856d8f
--- /dev/null
+++ b/ACE/ace/Log_Msg.inl
@@ -0,0 +1,235 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+u_long
+ACE_Log_Msg::priority_mask (MASK_TYPE mask_type)
+{
+ return mask_type == THREAD
+ ? this->priority_mask_
+ : ACE_Log_Msg::process_priority_mask_;
+}
+
+ACE_INLINE
+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);
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::op_status (int status)
+{
+ this->status_ = status;
+}
+
+ACE_INLINE
+int
+ACE_Log_Msg::op_status (void) const
+{
+ return this->status_;
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::restart (int r)
+{
+ this->restart_ = r;
+}
+
+ACE_INLINE
+int
+ACE_Log_Msg::restart (void) const
+{
+ return this->restart_;
+}
+
+ACE_INLINE
+int
+ACE_Log_Msg::errnum (void) const
+{
+ return this->errnum_;
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::errnum (int e)
+{
+ this->errnum_ = e;
+}
+
+ACE_INLINE
+int
+ACE_Log_Msg::linenum (void) const
+{
+ return this->linenum_;
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::linenum (int l)
+{
+ this->linenum_ = l;
+}
+
+ACE_INLINE
+int
+ACE_Log_Msg::inc (void)
+{
+ return this->trace_depth_++;
+}
+
+ACE_INLINE
+int
+ACE_Log_Msg::dec (void)
+{
+ return this->trace_depth_ == 0 ? 0 : --this->trace_depth_;
+}
+
+ACE_INLINE
+int
+ACE_Log_Msg::trace_depth (void) const
+{
+ return this->trace_depth_;
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::trace_depth (int depth)
+{
+ this->trace_depth_ = depth;
+}
+
+ACE_INLINE
+bool
+ACE_Log_Msg::trace_active (void) const
+{
+ return this->trace_active_;
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::trace_active (bool value)
+{
+ this->trace_active_ = value;
+}
+
+ACE_INLINE
+ACE_Thread_Descriptor *
+ACE_Log_Msg::thr_desc (void) const
+{
+ return this->thr_desc_;
+}
+
+/// Enable the tracing facility on a per-thread basis.
+ACE_INLINE
+void
+ACE_Log_Msg::start_tracing (void)
+{
+ this->tracing_enabled_ = true;
+}
+
+/// Disable the tracing facility on a per-thread basis.
+ACE_INLINE
+void
+ACE_Log_Msg::stop_tracing (void)
+{
+ this->tracing_enabled_ = false;
+}
+
+ACE_INLINE
+bool
+ACE_Log_Msg::tracing_enabled (void) const
+{
+ return this->tracing_enabled_;
+}
+
+ACE_INLINE
+const char *
+ACE_Log_Msg::file (void)
+{
+ return this->file_;
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::file (const char *s)
+{
+ ACE_OS::strsncpy (this->file_, s, sizeof this->file_);
+}
+
+ACE_INLINE
+const ACE_TCHAR *
+ACE_Log_Msg::msg (void)
+{
+ return this->msg_ + ACE_Log_Msg::msg_off_;
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::msg (const ACE_TCHAR *m)
+{
+ ACE_OS::strsncpy (this->msg_, m,
+ ((ACE_MAXLOGMSGLEN+1) / sizeof (ACE_TCHAR)));
+}
+
+ACE_INLINE
+ACE_Log_Msg_Callback *
+ACE_Log_Msg::msg_callback (void) const
+{
+ return this->msg_callback_;
+}
+
+ACE_INLINE
+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_INLINE
+ACE_OSTREAM_TYPE *
+ACE_Log_Msg::msg_ostream (void) const
+{
+ return this->ostream_;
+}
+
+ACE_INLINE
+void
+ACE_Log_Msg::msg_ostream (ACE_OSTREAM_TYPE *m)
+{
+ this->ostream_ = m;
+}
+
+ACE_INLINE
+const ACE_TCHAR *
+ACE_Log_Msg::local_host (void) const
+{
+ return ACE_Log_Msg::local_host_;
+}
+
+ACE_INLINE
+pid_t
+ACE_Log_Msg::getpid (void) const
+{
+ if (ACE_Log_Msg::pid_ == -2)
+ ACE_Log_Msg::pid_ = ACE_OS::getpid ();
+
+ return ACE_Log_Msg::pid_;
+}
+
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
diff --git a/ACE/ace/Log_Msg_Backend.cpp b/ACE/ace/Log_Msg_Backend.cpp
new file mode 100644
index 00000000000..de9b9c22b7b
--- /dev/null
+++ b/ACE/ace/Log_Msg_Backend.cpp
@@ -0,0 +1,14 @@
+// $Id$
+
+#include "ace/Log_Msg_Backend.h"
+
+ACE_RCSID(ace, Log_Msg_Backend, "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Log_Msg_Backend::~ACE_Log_Msg_Backend (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Log_Msg_Backend.h b/ACE/ace/Log_Msg_Backend.h
new file mode 100644
index 00000000000..b98465987db
--- /dev/null
+++ b/ACE/ace/Log_Msg_Backend.h
@@ -0,0 +1,88 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Log_Record;
+
+/**
+ * @class ACE_Log_Msg_Backend
+ *
+ * @brief Defines the interface for ACE_Log_Msg back end processing.
+ *
+ * The ACE_Log_Msg class uses ACE_Log_Msg_Backend as the target interface
+ * for back end log record procesing. In addition to the classes ACE
+ * derives from this (ACE_Log_Msg_NT_Event_Log, ACE_Log_Msg_UNIX_Syslog, and
+ * ACE_Log_Msg_IPC) users can derive classes from ACE_Log_Msg_Backend for
+ * use as a custom logger back end.
+ */
+class ACE_Export ACE_Log_Msg_Backend
+{
+public:
+ /// No-op virtual destructor.
+ virtual ~ACE_Log_Msg_Backend (void);
+
+ /**
+ * Open the back end object. Perform any actions needed to prepare
+ * the object for later logging operations.
+ *
+ * @param logger_key The character string passed to ACE_Log_Msg::open().
+ * If the @c LOGGER logging destination is not being
+ * used, any string can be passed through to the back end.
+ *
+ * @retval 0 for success.
+ * @retval -1 for failure.
+ */
+ virtual int open (const ACE_TCHAR *logger_key) = 0;
+
+ /**
+ * Reset the backend. If ACE_Log_Msg is reopened during execution, this
+ * hook will be called. This method should perform any needed cleanup
+ * activity (similar to close()) because this object won't be reopened
+ * if the new open call does not specify use of this back end being reset.
+ *
+ * @retval Currently ignored, but to be safe, return 0 for success;
+ * -1 for failure.
+ */
+ virtual int reset (void) = 0;
+
+ /// Close the backend completely.
+ virtual int close (void) = 0;
+
+ /**
+ * Process a log record.
+ *
+ * @param log_record The ACE_Log_Record to process.
+ *
+ * @retval -1 for failure; else it is customarily the number of bytes
+ * processed, but can also be 0 to signify success.
+ */
+ virtual ssize_t log (ACE_Log_Record &log_record) = 0;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOG_MSG_BACKEND_H */
diff --git a/ACE/ace/Log_Msg_Callback.cpp b/ACE/ace/Log_Msg_Callback.cpp
new file mode 100644
index 00000000000..2fcf5206dd1
--- /dev/null
+++ b/ACE/ace/Log_Msg_Callback.cpp
@@ -0,0 +1,13 @@
+// $Id$
+
+#include "ace/Log_Msg_Callback.h"
+
+ACE_RCSID(ace, Log_Msg_Callback, "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Log_Msg_Callback::~ACE_Log_Msg_Callback (void)
+{
+}
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Log_Msg_Callback.h b/ACE/ace/Log_Msg_Callback.h
new file mode 100644
index 00000000000..ecd8641dbb3
--- /dev/null
+++ b/ACE/ace/Log_Msg_Callback.h
@@ -0,0 +1,69 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOG_MSG_CALLBACK_H */
diff --git a/ACE/ace/Log_Msg_IPC.cpp b/ACE/ace/Log_Msg_IPC.cpp
new file mode 100644
index 00000000000..82411a3cf92
--- /dev/null
+++ b/ACE/ace/Log_Msg_IPC.cpp
@@ -0,0 +1,111 @@
+// $Id$
+
+#include "ace/Log_Msg_IPC.h"
+#include "ace/Log_Record.h"
+#include "ace/CDR_Stream.h"
+#include "ace/Truncate.h"
+
+ACE_RCSID(ace, Log_Msg_IPC, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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!
+ return this->close ();
+ }
+ return 0;
+}
+
+int
+ACE_Log_Msg_IPC::close (void)
+{
+ return this->message_queue_.close ();
+}
+
+ssize_t
+ACE_Log_Msg_IPC::log (ACE_Log_Record &log_record)
+{
+ // Serialize the log record using a CDR stream, allocate enough
+ // space for the complete <ACE_Log_Record>.
+ size_t const max_payload_size =
+ 4 // type
+ + 4 // pid
+ + 12 // timestamp
+ + 4 // process id
+ + 4 // data length
+#if defined (ACE_USES_WCHAR)
+ + (log_record.msg_data_len () * ACE_OutputCDR::wchar_maxbytes()) // message
+#else
+ + log_record.msg_data_len () // message
+#endif
+ + ACE_CDR::MAX_ALIGNMENT; // padding;
+
+ // Insert contents of <log_record> into payload stream.
+ ACE_OutputCDR payload (max_payload_size);
+ payload << log_record;
+
+ // Get the number of bytes used by the CDR stream. If it becomes desireable
+ // to support payloads more than 4GB, this field will need to be changed
+ // to a 64-bit value.
+ ACE_CDR::ULong length =
+ ACE_Utils::truncate_cast<ACE_CDR::ULong> (payload.total_length ());
+
+ // Send a header so the receiver can determine the byte order and
+ // size of the incoming CDR stream.
+ ACE_OutputCDR header (ACE_CDR::MAX_ALIGNMENT + 8);
+ header << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);
+
+ // Store the size of the payload that follows
+ header << ACE_CDR::ULong (length);
+
+ // Use an iovec to send both buffer and payload simultaneously.
+ iovec iov[2];
+ iov[0].iov_base = header.begin ()->rd_ptr ();
+ iov[0].iov_len = 8;
+ iov[1].iov_base = payload.begin ()->rd_ptr ();
+ iov[1].iov_len = length;
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ // Use the <putpmsg> API if supported to ensure correct message
+ // queueing according to priority.
+
+ ACE_Str_Buf header_msg (static_cast<void *> (header.begin ()->rd_ptr ()),
+ static_cast<int> (8));
+
+ ACE_Str_Buf payload_msg (static_cast<void *> (payload.begin ()->rd_ptr ()),
+ static_cast<int> (length));
+
+ return this->message_queue_.send (&header_msg,
+ &payload_msg,
+ static_cast<int> (log_record.priority ()),
+ MSG_BAND);
+#else
+ // We're running over sockets, so send header and payload
+ // efficiently using "gather-write".
+ return this->message_queue_.sendv_n (iov, 2);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Log_Msg_IPC.h b/ACE/ace/Log_Msg_IPC.h
new file mode 100644
index 00000000000..8b39b9ec551
--- /dev/null
+++ b/ACE/ace/Log_Msg_IPC.h
@@ -0,0 +1,79 @@
+// -*- 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"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+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;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#else
+# include "ace/SOCK_Connector.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+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;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// 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);
+
+ /**
+ * 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);
+
+ virtual int close (void);
+ virtual ssize_t log (ACE_Log_Record &log_record);
+
+private:
+ ACE_LOG_MSG_IPC_STREAM message_queue_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOG_MSG_H */
diff --git a/ACE/ace/Log_Msg_NT_Event_Log.cpp b/ACE/ace/Log_Msg_NT_Event_Log.cpp
new file mode 100644
index 00000000000..e22170c01dc
--- /dev/null
+++ b/ACE/ace/Log_Msg_NT_Event_Log.cpp
@@ -0,0 +1,162 @@
+// $Id$
+
+#include "ace/config-all.h"
+
+#if defined (ACE_HAS_LOG_MSG_NT_EVENT_LOG)
+
+#include "ace/Log_Msg_NT_Event_Log.h"
+#include "ace/Log_Msg.h"
+#include "ace/Log_Record.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(ace, Log_Msg_NT_Event_Log, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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)
+{
+ 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;
+ DWORD msg_file_length =
+ static_cast<DWORD> ((ACE_OS::strlen (msg_file) + 1) * sizeof (ACE_TCHAR));
+
+ // If a logger_key has been supplied then we use that as the event
+ // source name, otherwise we default to the program name.
+ const ACE_TCHAR *event_source_name = logger_key ? logger_key : ACE_Log_Msg::program_name ();
+
+ // 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_TEXT ("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"));
+ size_t reg_key_length = ACE_OS::strlen(reg_key);
+ ACE_OS::strncat (reg_key,
+ event_source_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_TEXT ("TypesSupported"),
+ 0,
+ REG_DWORD,
+ (LPBYTE) &flags,
+ sizeof (DWORD));
+ ACE_TEXT_RegSetValueEx (hkey,
+ ACE_TEXT ("EventMessageFile"),
+ 0,
+ REG_SZ,
+ (LPBYTE) msg_file,
+ msg_file_length);
+ RegCloseKey (hkey);
+
+ // Obtain a handle to the event source.
+ this->evlog_handle_ = ACE_TEXT_RegisterEventSource (0,
+ event_source_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 (this->evlog_handle_ == 0
+ || DeregisterEventSource (this->evlog_handle_))
+ {
+ this->evlog_handle_ = 0;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+ssize_t
+ACE_Log_Msg_NT_Event_Log::log (ACE_Log_Record &log_record)
+{
+ // Make a copy of the log text and replace any newlines with
+ // CR-LF. Newline characters on their own do not appear correctly in
+ // the event viewer. We allow for a doubling in the size of the msg
+ // data for the worst case of all newlines.
+ const ACE_TCHAR* src_msg_data = log_record.msg_data ();
+ ACE_TCHAR msg_data [ACE_Log_Record::MAXLOGMSGLEN * 2];
+
+ for (size_t i = 0, j = 0;
+ i < log_record.msg_data_len ();
+ ++i)
+ {
+ if (src_msg_data[i] == '\n')
+ {
+ msg_data[j++] = '\r';
+ msg_data[j++] = '\n';
+ }
+ else
+ msg_data[j++] = 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_LOG_MSG_NT_EVENT_LOG */
diff --git a/ACE/ace/Log_Msg_NT_Event_Log.h b/ACE/ace/Log_Msg_NT_Event_Log.h
new file mode 100644
index 00000000000..4bca6adaa20
--- /dev/null
+++ b/ACE/ace/Log_Msg_NT_Event_Log.h
@@ -0,0 +1,72 @@
+// -*- 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 ACE_HAS_LOG_MSG_NT_EVENT_LOG
+
+#include "ace/Log_Msg_Backend.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 ssize_t log (ACE_Log_Record &log_record);
+
+private:
+ HANDLE evlog_handle_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_LOG_MSG_NT_EVENT_LOG */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOG_MSG_NT_EVENT_LOG_H */
diff --git a/ACE/ace/Log_Msg_UNIX_Syslog.cpp b/ACE/ace/Log_Msg_UNIX_Syslog.cpp
new file mode 100644
index 00000000000..dba78bcd571
--- /dev/null
+++ b/ACE/ace/Log_Msg_UNIX_Syslog.cpp
@@ -0,0 +1,207 @@
+// $Id$
+
+#include "ace/config-all.h"
+
+#if !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"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/os_syslog.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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.
+#if defined (ACE_USES_WCHAR)
+ openlog (ACE_TEXT_ALWAYS_CHAR (logger_key),
+ LOG_CONS|LOG_PID,
+ ACE_DEFAULT_SYSLOG_FACILITY);
+#else
+ openlog (const_cast<char *> (logger_key),
+ LOG_CONS|LOG_PID,
+ ACE_DEFAULT_SYSLOG_FACILITY);
+#endif /* ACE_USES_WCHAR */
+
+ // 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;
+}
+
+ssize_t
+ACE_Log_Msg_UNIX_Syslog::log (ACE_Log_Record &log_record)
+{
+ int syslog_priority = this->convert_log_priority (log_record.type ());
+ u_long 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 ());
+ ACE_TCHAR *strtokp = 0;
+
+ for (ACE_TCHAR *line = ACE_OS::strtok_r (message,
+ ACE_TEXT ("\n"),
+ &strtokp);
+ line != 0;
+ line = ACE_OS::strtok_r (0,
+ ACE_TEXT ("\n"),
+ &strtokp))
+ {
+ // 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];
+ if (0 == ACE::timestamp (date_and_time, sizeof (date_and_time), 1))
+ ACE_OS::strcpy (date_and_time, ACE_TEXT ("<time error>"));
+ const ACE_TCHAR *prio_name =
+ ACE_Log_Record::priority_name(ACE_Log_Priority(log_record.type()));
+ syslog (syslog_priority,
+ "%s: %s: %s",
+ ACE_TEXT_ALWAYS_CHAR (date_and_time),
+ ACE_TEXT_ALWAYS_CHAR (prio_name),
+ ACE_TEXT_ALWAYS_CHAR (line));
+ }
+ else // No formatting required.
+ syslog (syslog_priority, "%s", ACE_TEXT_ALWAYS_CHAR (line));
+ }
+
+ return 0;
+}
+
+int
+ACE_Log_Msg_UNIX_Syslog::convert_log_priority (ACE_UINT32 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_LACKS_UNIX_SYSLOG */
diff --git a/ACE/ace/Log_Msg_UNIX_Syslog.h b/ACE/ace/Log_Msg_UNIX_Syslog.h
new file mode 100644
index 00000000000..01d5476360d
--- /dev/null
+++ b/ACE/ace/Log_Msg_UNIX_Syslog.h
@@ -0,0 +1,76 @@
+// -*- 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_LACKS_UNIX_SYSLOG)
+
+#include "ace/Log_Msg_Backend.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @c 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 ssize_t log (ACE_Log_Record &log_record);
+
+private:
+ /// Convert an ACE_Log_Priority value to the corresponding syslog priority.
+ int convert_log_priority (ACE_UINT32 lm_priority);
+
+ /// Convert an ACE_Log_Priority mask to the corresponding syslog mask value.
+ int convert_log_mask (int lm_mask);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_LACKS_UNIX_SYSLOG */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOG_MSG_UNIX_SYSLOG_H */
diff --git a/ACE/ace/Log_Priority.h b/ACE/ace/Log_Priority.h
new file mode 100644
index 00000000000..c1084bbeee5
--- /dev/null
+++ b/ACE/ace/Log_Priority.h
@@ -0,0 +1,85 @@
+// -*- 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"
+
+#include "ace/config-lite.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @enum ACE_Log_Priority
+ *
+ * @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
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOG_PRIORITY_H */
diff --git a/ACE/ace/Log_Record.cpp b/ACE/ace/Log_Record.cpp
new file mode 100644
index 00000000000..f790cf7d24c
--- /dev/null
+++ b/ACE/ace/Log_Record.cpp
@@ -0,0 +1,412 @@
+// $Id$
+
+#include "ace/Log_Record.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_time.h"
+#include "ace/CDR_Stream.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Truncate.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Log_Record.inl"
+#endif /* __ACE_INLINE__ */
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+// FUZZ: disable check_for_streams_include
+# include "ace/streams.h"
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+#include "ace/OS_Memory.h"
+
+ACE_RCSID(ace, Log_Record, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Log_Record)
+
+namespace
+{
+ // Symbolic names for the <ACE_Log_Priority> enumerators.
+ ACE_TCHAR const * ace_priority_names[] =
+ {
+ ACE_TEXT ("LM_SHUTDOWN"),
+ ACE_TEXT ("LM_TRACE"),
+ ACE_TEXT ("LM_DEBUG"),
+ ACE_TEXT ("LM_INFO"),
+ ACE_TEXT ("LM_NOTICE"),
+ ACE_TEXT ("LM_WARNING"),
+ ACE_TEXT ("LM_STARTUP"),
+ ACE_TEXT ("LM_ERROR"),
+ ACE_TEXT ("LM_CRITICAL"),
+ ACE_TEXT ("LM_ALERT"),
+ ACE_TEXT ("LM_EMERGENCY"),
+ ACE_TEXT ("LM_UNK(04000)"),
+ ACE_TEXT ("LM_UNK(010000)"),
+ ACE_TEXT ("LM_UNK(020000)"),
+ ACE_TEXT ("LM_UNK(040000)"),
+ ACE_TEXT ("LM_UNK(0100000)"),
+ ACE_TEXT ("LM_UNK(0200000)"),
+ ACE_TEXT ("LM_UNK(0400000)"),
+ ACE_TEXT ("LM_UNK(01000000)"),
+ ACE_TEXT ("LM_UNK(02000000)"),
+ ACE_TEXT ("LM_UNK(04000000)"),
+ ACE_TEXT ("LM_UNK(010000000)"),
+ ACE_TEXT ("LM_UNK(020000000)"),
+ ACE_TEXT ("LM_UNK(040000000)"),
+ ACE_TEXT ("LM_UNK(0100000000)"),
+ ACE_TEXT ("LM_UNK(0200000000)"),
+ ACE_TEXT ("LM_UNK(0400000000)"),
+ ACE_TEXT ("LM_UNK(01000000000)"),
+ ACE_TEXT ("LM_UNK(02000000000)"),
+ ACE_TEXT ("LM_UNK(04000000000)"),
+ ACE_TEXT ("LM_UNK(010000000000)"),
+ ACE_TEXT ("LM_UNK(020000000000)")
+ };
+}
+
+const ACE_TCHAR *
+ACE_Log_Record::priority_name (ACE_Log_Priority p)
+{
+ return ace_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_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
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Log_Record::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("length_ = %d\n"), this->length_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntype_ = %u\n"), this->type_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntime_stamp_ = (%:, %d)\n"),
+ this->secs_, this->usecs_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\npid_ = %u\n"), this->pid_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmsg_data_ (0x%@) = %s\n"),
+ this->msg_data_, this->msg_data_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmsg_data_size_ = %B\n"),
+ this->msg_data_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Log_Record::msg_data (const ACE_TCHAR *data)
+{
+ // ACE_TRACE ("ACE_Log_Record::msg_data");
+ size_t const newlen = ACE_OS::strlen (data) + 1; // Will need room for '\0'
+ if (newlen > this->msg_data_size_)
+ {
+ ACE_TCHAR *new_msg_data = 0;
+ ACE_NEW_RETURN (new_msg_data, ACE_TCHAR[newlen], -1);
+ delete [] this->msg_data_;
+ this->msg_data_ = new_msg_data;
+ this->msg_data_size_ = newlen;
+ }
+ ACE_OS::strcpy (this->msg_data_, data);
+ this->round_up ();
+ return 0;
+}
+
+ACE_Log_Record::ACE_Log_Record (ACE_Log_Priority lp,
+ time_t ts_sec,
+ long p)
+ : length_ (0),
+ type_ (ACE_UINT32 (lp)),
+ secs_ (ts_sec),
+ usecs_ (0),
+ pid_ (ACE_UINT32 (p)),
+ msg_data_ (0),
+ msg_data_size_ (0)
+{
+ // ACE_TRACE ("ACE_Log_Record::ACE_Log_Record");
+ ACE_NEW_NORETURN (this->msg_data_, ACE_TCHAR[MAXLOGMSGLEN]);
+ if (0 != this->msg_data_)
+ {
+ this->msg_data_size_ = MAXLOGMSGLEN;
+ this->msg_data_[0] = '\0';
+ }
+}
+
+ACE_Log_Record::ACE_Log_Record (ACE_Log_Priority lp,
+ const ACE_Time_Value &ts,
+ long p)
+ : length_ (0),
+ type_ (ACE_UINT32 (lp)),
+ secs_ (ts.sec ()),
+ usecs_ ((ACE_UINT32) ts.usec ()),
+ pid_ (ACE_UINT32 (p)),
+ msg_data_ (0),
+ msg_data_size_ (0)
+{
+ // ACE_TRACE ("ACE_Log_Record::ACE_Log_Record");
+ ACE_NEW_NORETURN (this->msg_data_, ACE_TCHAR[MAXLOGMSGLEN]);
+ if (0 != this->msg_data_)
+ {
+ this->msg_data_size_ = MAXLOGMSGLEN;
+ this->msg_data_[0] = '\0';
+ }
+}
+
+void
+ACE_Log_Record::round_up (void)
+{
+ // ACE_TRACE ("ACE_Log_Record::round_up");
+ // Determine the length of the payload.
+ size_t len = sizeof (*this) + (sizeof (ACE_TCHAR) * ((ACE_OS::strlen (this->msg_data_) + 1)));
+
+ // Round up to the alignment.
+ len = ((len + ACE_Log_Record::ALIGN_WORDB - 1)
+ & ~(ACE_Log_Record::ALIGN_WORDB - 1));
+ this->length_ = static_cast<ACE_UINT32> (len);
+}
+
+ACE_Log_Record::ACE_Log_Record (void)
+ : length_ (0),
+ type_ (0),
+ secs_ (0),
+ usecs_ (0),
+ pid_ (0),
+ msg_data_ (0),
+ msg_data_size_ (0)
+{
+ // ACE_TRACE ("ACE_Log_Record::ACE_Log_Record");
+ ACE_NEW_NORETURN (this->msg_data_, ACE_TCHAR[MAXLOGMSGLEN]);
+ if (0 != this->msg_data_)
+ {
+ this->msg_data_size_ = MAXLOGMSGLEN;
+ this->msg_data_[0] = '\0';
+ }
+}
+
+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.
+
+ // The sprintf format needs to be different for Windows and POSIX
+ // in the wide-char case.
+#if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+ const ACE_TCHAR *time_fmt = ACE_TEXT ("%s.%03ld %s");
+ const ACE_TCHAR *verbose_fmt = ACE_TEXT ("%s@%s@%u@%s@%s");
+ const ACE_TCHAR *verbose_lite_fmt = ACE_TEXT ("%s@%s@%s");
+#else
+ const ACE_TCHAR *time_fmt = ACE_TEXT ("%ls.%03ld %ls");
+ const ACE_TCHAR *verbose_fmt = ACE_TEXT ("%ls@%ls@%u@%ls@%ls");
+ const ACE_TCHAR *verbose_lite_fmt = ACE_TEXT ("%ls@%ls@%ls");
+#endif
+
+ if (ACE_BIT_ENABLED (verbose_flag,
+ ACE_Log_Msg::VERBOSE)
+ || ACE_BIT_ENABLED (verbose_flag,
+ ACE_Log_Msg::VERBOSE_LITE))
+ {
+ time_t const 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,
+ time_fmt,
+ ctp + 4,
+ ((long) this->usecs_) / 1000,
+ ctp + 20);
+ }
+
+ if (ACE_BIT_ENABLED (verbose_flag,
+ ACE_Log_Msg::VERBOSE))
+ {
+ const ACE_TCHAR *lhost_name = ((host_name == 0)
+ ? ACE_TEXT ("<local_host>")
+ : host_name);
+ ACE_OS::sprintf (verbose_msg,
+ verbose_fmt,
+ 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,
+ verbose_lite_fmt,
+ timestamp,
+ ACE_Log_Record::priority_name (ACE_Log_Priority (this->type_)),
+ this->msg_data_);
+ else
+ ACE_OS::strcpy (verbose_msg, this->msg_data_);
+ return 0;
+}
+
+int
+ACE_Log_Record::print (const ACE_TCHAR host_name[],
+ u_long verbose_flag,
+ FILE *fp)
+{
+ if (ACE_LOG_MSG->log_priority_enabled (ACE_Log_Priority (this->type_)))
+ {
+ ACE_TCHAR *verbose_msg = 0;
+ ACE_NEW_RETURN (verbose_msg, ACE_TCHAR[MAXVERBOSELOGMSGLEN], -1);
+
+ int result = this->format_msg (host_name, verbose_flag, verbose_msg);
+
+ if (result == 0)
+ {
+ if (fp != 0)
+ {
+ int const verbose_msg_len =
+ static_cast<int> (ACE_OS::strlen (verbose_msg));
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ int const fwrite_result = ACE_OS::fprintf (fp,
+ ACE_TEXT ("%ls"),
+ verbose_msg);
+#else
+ int const fwrite_result = ACE_OS::fprintf (fp,
+ ACE_TEXT ("%s"),
+ verbose_msg);
+#endif
+ // We should have written everything
+ if (fwrite_result != verbose_msg_len)
+ result = -1;
+ else
+ ACE_OS::fflush (fp);
+ }
+ }
+
+ delete [] verbose_msg;
+
+ return result;
+ }
+ else
+ return 0;
+}
+
+int
+operator<< (ACE_OutputCDR &cdr,
+ const ACE_Log_Record &log_record)
+{
+ // The written message length can't be more than 32 bits (ACE_CDR::ULong)
+ // so reduce it here if needed.
+ ACE_CDR::ULong u_msglen =
+ ACE_Utils::truncate_cast<ACE_CDR::ULong> (log_record.msg_data_len ());
+
+ // Insert each field from <log_record> into the output CDR stream.
+ cdr << ACE_CDR::Long (log_record.type ());
+ cdr << ACE_CDR::Long (log_record.pid ());
+ cdr << ACE_CDR::LongLong (log_record.time_stamp ().sec ());
+ cdr << ACE_CDR::Long (log_record.time_stamp ().usec ());
+ cdr << u_msglen;
+#if defined (ACE_USES_WCHAR)
+ cdr.write_wchar_array (log_record.msg_data (), u_msglen);
+#else
+ cdr.write_char_array (log_record.msg_data (), u_msglen);
+#endif /* ACE_USES_WCHAR */
+ return cdr.good_bit ();
+}
+
+int
+operator>> (ACE_InputCDR &cdr,
+ ACE_Log_Record &log_record)
+{
+ ACE_CDR::Long type;
+ ACE_CDR::Long pid;
+ ACE_CDR::LongLong sec;
+ ACE_CDR::Long usec;
+ ACE_CDR::ULong buffer_len;
+
+ // Extract each field from input CDR stream into <log_record>.
+ if ((cdr >> type) && (cdr >> pid) && (cdr >> sec) && (cdr >> usec)
+ && (cdr >> buffer_len)) {
+ ACE_TCHAR *log_msg;
+ ACE_NEW_RETURN (log_msg, ACE_TCHAR[buffer_len + 1], -1);
+ auto_ptr<ACE_TCHAR> log_msg_p (log_msg);
+ log_record.type (type);
+ log_record.pid (pid);
+ log_record.time_stamp (ACE_Time_Value (ACE_Utils::truncate_cast<time_t> (sec),
+ usec));
+#if defined (ACE_USES_WCHAR)
+ cdr.read_wchar_array (log_msg, buffer_len);
+#else
+ cdr.read_char_array (log_msg, buffer_len);
+#endif /* ACE_USES_WCHAR */
+ log_msg[buffer_len] = '\0';
+ if (-1 == log_record.msg_data (log_msg))
+ return -1;
+ }
+ return cdr.good_bit ();
+}
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+
+int
+ACE_Log_Record::print (const ACE_TCHAR host_name[],
+ u_long verbose_flag,
+ ACE_OSTREAM_TYPE &s)
+{
+ if (ACE_LOG_MSG->log_priority_enabled (ACE_Log_Priority (this->type_)))
+ {
+ ACE_TCHAR* verbose_msg = 0;
+ ACE_NEW_RETURN (verbose_msg, ACE_TCHAR[MAXVERBOSELOGMSGLEN], -1);
+
+ int const 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 ();
+ }
+
+ delete [] verbose_msg;
+
+ return result;
+ }
+ return 0;
+}
+
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Log_Record.h b/ACE/ace/Log_Record.h
new file mode 100644
index 00000000000..d03faeb8680
--- /dev/null
+++ b/ACE/ace/Log_Record.h
@@ -0,0 +1,223 @@
+// -*- 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/Log_Priority.h"
+
+#ifndef ACE_LOG_RECORD_H
+#define ACE_LOG_RECORD_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Default_Constants.h"
+#include "ace/Basic_Types.h"
+#include "ace/iosfwd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/// 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+1,
+
+ /// 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.
+ */
+ ACE_Log_Record (void);
+ ACE_Log_Record (ACE_Log_Priority lp,
+ time_t 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> iff the corresponding type is enabled.
+ 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> iff the corresponding type is enabled.
+ int print (const ACE_TCHAR host_name[],
+ u_long verbose_flag,
+ ACE_OSTREAM_TYPE &stream);
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+ int format_msg (const ACE_TCHAR host_name[],
+ u_long verbose_flag,
+ ACE_TCHAR *verbose_msg);
+
+ /**
+ * 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: @a 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.
+ /// @deprecated The encode() and decode() metods are deprecated; please use
+ /// the CDR insertion and extraction operators to properly encode and decode
+ /// ACE_Log_Record objects.
+ void encode (void);
+
+ /// Decode the <Log_Record> received from the network.
+ /// @deprecated The encode() and decode() metods are deprecated; please use
+ /// the CDR insertion and extraction operators to properly encode and decode
+ /// ACE_Log_Record objects.
+ void decode (void);
+
+ // = Set/get methods
+
+ /// Get the type of the <Log_Record>.
+ ACE_UINT32 type (void) const;
+
+ /// Set the type of the <Log_Record>.
+ void type (ACE_UINT32);
+
+ /**
+ * 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 total length of the <Log_Record>, which includes the
+ /// size of the various data member fields.
+ long length (void) const;
+
+ /// Set the total length of the <Log_Record>, which needs to account for
+ /// the size of the various data member fields.
+ 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 &ts);
+
+ /// 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 record. If @a data is longer than the
+ /// current msg_data_ buffer, a new msg_data_ buffer is allocated to
+ /// fit. If such a reallocation faisl, this method returns -1, else 0.
+ int 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.
+ time_t secs_;
+ ACE_UINT32 usecs_;
+
+ /// Id of process that generated the logging record.
+ ACE_UINT32 pid_;
+
+ /// Logging record data
+ ACE_TCHAR *msg_data_; // Heap-allocated text message area
+ size_t msg_data_size_; // Allocated size of msg_data_ in ACE_TCHARs
+
+ /// disallow copying...
+ ACE_Log_Record (const ACE_Log_Record& rhs);
+ ACE_Log_Record& operator= (const ACE_Log_Record& rhs);
+};
+
+// Forward decls.
+class ACE_InputCDR;
+class ACE_OutputCDR;
+
+// iostream operators for ACE_Log_Record.
+ACE_Export int operator>> (ACE_InputCDR &cdr, ACE_Log_Record &log_record);
+ACE_Export int operator<< (ACE_OutputCDR &cdr, const ACE_Log_Record &log_record);
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Log_Record.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LOG_RECORD_H */
diff --git a/ACE/ace/Log_Record.inl b/ACE/ace/Log_Record.inl
new file mode 100644
index 00000000000..aba217d93ef
--- /dev/null
+++ b/ACE/ace/Log_Record.inl
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+#include "ace/os_include/arpa/os_inet.h"
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Log_Record::~ACE_Log_Record (void)
+{
+ if (this->msg_data_)
+ delete [] this->msg_data_;
+}
+
+ACE_INLINE void
+ACE_Log_Record::encode (void)
+{
+ ACE_TRACE ("ACE_Log_Record::encode");
+#if !defined (ACE_LACKS_HTONL)
+ 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.
+ // secs_ is commented out because it can be 64 bits. This method is
+ // deprecated; use the CDR operations instead.
+ // this->secs_ = htonl (this->secs_);
+ this->usecs_ = htonl (this->usecs_);
+ this->pid_ = htonl (this->pid_);
+#endif /* ACE_LACKS_HTONL */
+}
+
+ACE_INLINE void
+ACE_Log_Record::decode (void)
+{
+ ACE_TRACE ("ACE_Log_Record::decode");
+#if !defined (ACE_LACKS_NTOHL)
+ ACE_Time_Value tv (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_);
+#endif /* ACE_LACKS_NTOHL */
+}
+
+ACE_INLINE ACE_UINT32
+ACE_Log_Record::type (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::type");
+ return this->type_;
+}
+
+ACE_INLINE void
+ACE_Log_Record::type (ACE_UINT32 t)
+{
+ ACE_TRACE ("ACE_Log_Record::type");
+ this->type_ = t;
+}
+
+ACE_INLINE long
+ACE_Log_Record::length (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::length");
+ return (long) this->length_;
+}
+
+ACE_INLINE void
+ACE_Log_Record::length (long l)
+{
+ ACE_TRACE ("ACE_Log_Record::length");
+ this->length_ = static_cast<ACE_UINT32> (l);
+}
+
+ACE_INLINE ACE_Time_Value
+ACE_Log_Record::time_stamp (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::time_stamp");
+ return ACE_Time_Value (this->secs_, (long) this->usecs_);
+}
+
+ACE_INLINE void
+ACE_Log_Record::time_stamp (const ACE_Time_Value &ts)
+{
+ ACE_TRACE ("ACE_Log_Record::time_stamp");
+ this->secs_ = ts.sec ();
+ this->usecs_ = (ACE_UINT32) ts.usec ();
+}
+
+ACE_INLINE long
+ACE_Log_Record::pid (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::pid");
+ return (long) this->pid_;
+}
+
+ACE_INLINE void
+ACE_Log_Record::pid (long p)
+{
+ ACE_TRACE ("ACE_Log_Record::pid");
+ this->pid_ = (ACE_UINT32) p;
+}
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Log_Record::msg_data (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::msg_data");
+ return this->msg_data_;
+}
+
+ACE_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Logging_Strategy.cpp b/ACE/ace/Logging_Strategy.cpp
new file mode 100644
index 00000000000..75458b3aa0d
--- /dev/null
+++ b/ACE/ace/Logging_Strategy.cpp
@@ -0,0 +1,566 @@
+// $Id$
+
+#include "ace/Logging_Strategy.h"
+#include "ace/Service_Config.h"
+#include "ace/ACE.h"
+#include "ace/Get_Opt.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Lib_Find.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID (ace,
+ Logging_Strategy,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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_;
+
+ ACE_TCHAR *strtokp;
+
+ // Parse string and alternate priority mask.
+
+ for (ACE_TCHAR *priority = ACE_OS::strtok_r (priority_string,
+ ACE_TEXT ("|"),
+ &strtokp);
+ priority != 0;
+ priority = ACE_OS::strtok_r (0,
+ ACE_TEXT ("|"),
+ &strtokp))
+ {
+ if (ACE_OS::strcmp (priority, ACE_TEXT ("SHUTDOWN")) == 0)
+ ACE_SET_BITS (priority_mask, LM_SHUTDOWN);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~SHUTDOWN")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_SHUTDOWN);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("TRACE")) == 0)
+ ACE_SET_BITS (priority_mask, LM_TRACE);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~TRACE")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_TRACE);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("DEBUG")) == 0)
+ ACE_SET_BITS (priority_mask, LM_DEBUG);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~DEBUG")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_DEBUG);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("INFO")) == 0)
+ ACE_SET_BITS (priority_mask, LM_INFO);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~INFO")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_INFO);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("NOTICE")) == 0)
+ ACE_SET_BITS (priority_mask, LM_NOTICE);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~NOTICE")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_NOTICE);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("WARNING")) == 0)
+ ACE_SET_BITS (priority_mask, LM_WARNING);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~WARNING")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_WARNING);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("STARTUP")) == 0)
+ ACE_SET_BITS (priority_mask, LM_STARTUP);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~STARTUP")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_STARTUP);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("ERROR")) == 0)
+ ACE_SET_BITS (priority_mask, LM_ERROR);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~ERROR")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_ERROR);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("CRITICAL")) == 0)
+ ACE_SET_BITS (priority_mask, LM_CRITICAL);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~CRITICAL")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_CRITICAL);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("ALERT")) == 0)
+ ACE_SET_BITS (priority_mask, LM_ALERT);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("~ALERT")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_ALERT);
+ else if (ACE_OS::strcmp (priority, ACE_TEXT ("EMERGENCY")) == 0)
+ ACE_SET_BITS (priority_mask, LM_EMERGENCY);
+ else if (ACE_OS::strcmp (priority, ACE_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)
+{
+ ACE_TCHAR *strtokp;
+
+ for (ACE_TCHAR *flag = ACE_OS::strtok_r (flag_string,
+ ACE_TEXT ("|"),
+ &strtokp);
+ flag != 0;
+ flag = ACE_OS::strtok_r (0, ACE_TEXT ("|"), &strtokp))
+ {
+ if (ACE_OS::strcmp (flag, ACE_TEXT ("STDERR")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::STDERR);
+ else if (ACE_OS::strcmp (flag, ACE_TEXT ("LOGGER")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::LOGGER);
+ else if (ACE_OS::strcmp (flag, ACE_TEXT ("OSTREAM")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::OSTREAM);
+ else if (ACE_OS::strcmp (flag, ACE_TEXT ("VERBOSE")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::VERBOSE);
+ else if (ACE_OS::strcmp (flag, ACE_TEXT ("VERBOSE_LITE")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::VERBOSE_LITE);
+ else if (ACE_OS::strcmp (flag, ACE_TEXT ("SILENT")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::SILENT);
+ else if (ACE_OS::strcmp (flag, ACE_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_ = false;
+ this->count_ = 0;
+ this->fixed_number_ = false;
+ this->order_files_ = false;
+ this->max_file_number_ = 1;
+ this->interval_ = ACE_DEFAULT_LOGFILE_POLL_INTERVAL;
+ this->max_size_ = 0;
+
+ ACE_Get_Opt get_opt (argc, argv,
+ ACE_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 from KB to bytes.
+ 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_ = true;
+ break;
+ case 'o':
+ // Log_files generation order
+ this->order_files_ = true;
+ 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_ = true;
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+ACE_Logging_Strategy::ACE_Logging_Strategy (void)
+ : thread_priority_mask_ (0),
+ process_priority_mask_ (0),
+ flags_ (0),
+ filename_ (0),
+ logger_key_ (0),
+ program_name_ (0),
+ wipeout_logfile_ (false),
+ fixed_number_ (false),
+ order_files_ (false),
+ count_ (0),
+ max_file_number_ (1), // 2 files by default (max file number + 1)
+ interval_ (ACE_DEFAULT_LOGFILE_POLL_INTERVAL),
+ max_size_ (0),
+ 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::get_temp_dir
+ (this->filename_,
+ MAXPATHLEN - 7) == -1) // 7 for "logfile"
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Temporary path too long, ")
+ ACE_TEXT ("defaulting to current directory\n")));
+ this->filename_[0] = 0;
+ }
+
+ // Add the filename to the end
+ ACE_OS::strcat (this->filename_,
+ ACE_TEXT ("logfile"));
+#endif /* ACE_DEFAULT_LOGFILE */
+}
+
+ACE_Logging_Strategy::~ACE_Logging_Strategy (void)
+{
+ // This is allocated in constructor, so it must be deallocated in
+ // the destructor!
+ delete [] this->filename_;
+}
+
+int
+ACE_Logging_Strategy::fini (void)
+{
+ delete [] this->filename_;
+ this->filename_ = 0; // Avoid double deletions.
+
+ delete [] this->logger_key_;
+ delete [] this->program_name_;
+
+ if (this->reactor ()
+ && this->interval_ > 0 && this->max_size_ > 0)
+ this->reactor ()->cancel_timer (this);
+
+ 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))
+ {
+ int delete_ostream = 0;
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ FILE *output_file = this->log_msg_->msg_ostream ();
+ if (wipeout_logfile_)
+ {
+ // close and re-open a stream if such exits
+ if (output_file &&
+ ACE_OS::fclose (output_file) == -1)
+ return -1;
+ output_file = ACE_OS::fopen (this->filename_, ACE_TEXT ("wt"));
+ }
+ // open a stream only if such doesn't exists
+ else if (output_file == 0)
+ output_file = ACE_OS::fopen (this->filename_,
+ ACE_TEXT ("at"));
+
+ if (output_file == 0)
+ return -1;
+#else
+ ostream *output_file = this->log_msg_->msg_ostream ();
+ // 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);
+ delete_ostream = 1;
+ }
+ else if (output_file == 0)
+ {
+ ACE_NEW_RETURN
+ (output_file,
+ ofstream (ACE_TEXT_ALWAYS_CHAR (this->filename_),
+ ios::app | ios::out),
+ -1);
+ delete_ostream = 1;
+ }
+
+ if (output_file->rdstate () != ios::goodbit)
+ {
+ if (delete_ostream)
+ 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, delete_ostream);
+
+ // 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::ftell (this->log_msg_->msg_ostream ()) > 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_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_,
+ ACE_TEXT ("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_TEXT ("%s.%d"),
+ this->filename_,
+ i);
+ ACE_OS::sprintf (to_backup,
+ ACE_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_TEXT ("%s.1"),
+ this->filename_);
+ }
+ else
+ {
+ if (fixed_number_ && count_>max_file_number_)
+ count_ = 1; // start over from 1
+
+ ACE_OS::sprintf (backup,
+ ACE_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_TEXT ("Backup file name too long; ")
+ ACE_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_, ACE_TEXT ("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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// 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/ace/Logging_Strategy.h b/ACE/ace/Logging_Strategy.h
new file mode 100644
index 00000000000..443e88915ec
--- /dev/null
+++ b/ACE/ace/Logging_Strategy.h
@@ -0,0 +1,195 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Logging_Strategy.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ * @author Orlando Ribeiro <oribeiro@inescporto.pt>
+ */
+//=============================================================================
+
+#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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Logging_Strategy
+ *
+ * @brief This class provides a way to dynamically configure the ACE logging
+ * mechanism at run time as well as enable the mechanisms for limiting
+ * log file size and log file backup/rotation capability.
+ *
+ * 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 @param sample_interval_in_secs and -m
+ * @param 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)).
+ *
+ * By default, the @c ACE_Logging_Strategy uses the singleton reactor,
+ * i.e., what's returned by @c ACE_Reactor::instance(). If you want
+ * to set the reactor used by @c ACE_Logging_Strategy to something
+ * other than the singleton reactor you'll need to get a pointer to
+ * the @c ACE_Logging_Strategy instance and do this
+ *
+ * ACE_Reactor my_reactor;
+ * ACE_Logging_Strategy *logging_strategy = ...... // Get instance.
+ *
+ * logging_strategy->reactor (&my_reactor);
+ *
+ * and then logging_strategy will use your reactor. If you're
+ * dynamically linking the @c ACE_Logging_Strategy then you can use
+ * the @c ACE_Dynamic_Service template to get a pointer to the
+ * @c ACE_Logging_Strategy.
+ */
+class ACE_Export ACE_Logging_Strategy : public ACE_Service_Object
+{
+public:
+ /// Constructor.
+ ACE_Logging_Strategy (void);
+
+ /// Destructor.
+ ~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.
+ * @arg '-f' Pass in the flags (such as OSTREAM, STDERR, LOGGER, VERBOSE,
+ * SILENT, VERBOSE_LITE) used to control logging.
+ * @arg '-i' The interval (in seconds) at which the logfile size is sampled
+ * (default is 0, i.e., do not sample by default).
+ * @arg '-k' Set the logging key.
+ * @arg '-m' Maximum logfile size in Kbytes.
+ * @arg '-n' Set the program name for the %n format specifier.
+ * @arg '-N' The maximum number of logfiles that we want created.
+ * @arg '-o' Specifies that we want the no standard logfiles ordering
+ * (fastest processing in <handle_timeout>). Default is not to
+ * order logfiles.
+ * @arg '-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).
+ * @arg '-s' Ensure that the OSTREAM flag is set and log to the @a filename.
+ * @arg '-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).
+ * @arg '-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);
+
+protected:
+ /// 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.
+ bool wipeout_logfile_;
+
+ /// If non-0 we have a maximum number of log files we can write.
+ /// Default value is 0, i.e., no maximum number.
+ bool 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.
+ bool order_files_;
+
+ /// This tells us in what file we last wrote. It will be increased
+ /// to enable multiple log files
+ int count_;
+
+ /// 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_END_VERSIONED_NAMESPACE_DECL
+
+ACE_FACTORY_DECLARE (ACE, ACE_Logging_Strategy)
+
+#endif /* ACE_LOGGING_STRATEGY_H */
diff --git a/ACE/ace/MEM_Acceptor.cpp b/ACE/ace/MEM_Acceptor.cpp
new file mode 100644
index 00000000000..fed5da3a328
--- /dev/null
+++ b/ACE/ace/MEM_Acceptor.cpp
@@ -0,0 +1,265 @@
+// $Id$
+
+#include "ace/MEM_Acceptor.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_unistd.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/MEM_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, MEM_Acceptor, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_Acceptor)
+
+void
+ACE_MEM_Acceptor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_MEM_Acceptor::dump");
+#endif /* ACE_HAS_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_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 in_blocking_mode = 1;
+ if (this->shared_accept_start (timeout,
+ restart,
+ in_blocking_mode) == -1)
+ return -1;
+ else
+ {
+ sockaddr *addr = 0;
+ struct sockaddr_in inet_addr;
+ int *len_ptr = 0;
+ int len = 0;
+
+ if (remote_sap != 0)
+ {
+ addr = reinterpret_cast<sockaddr *> (&inet_addr);
+ len = sizeof (inet_addr);
+ len_ptr = &len;
+ }
+
+ do
+ // On Win32 the third parameter to <accept> must be a NULL
+ // pointer if to ignore the client's address.
+ 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 (&inet_addr, len);
+ 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_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::get_temp_dir (buf, MAXPATHLEN - 24) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Temporary path too long, ")
+ ACE_TEXT ("defaulting to current directory\n")));
+ buf[0] = 0;
+ }
+
+ ACE_OS::sprintf (name,
+ ACE_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_MEM_IO::Signal_Strategy 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_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_TEXT ("ACE_MEM_Acceptor::%p error receiving strategy\n"), ACE_TEXT ("accept")),
+ -1);
+
+ // Ensure minimum buffer size
+ if (this->malloc_options_.minimum_bytes_ < ACE_MEM_STREAM_MIN_BUFFER)
+ this->malloc_options_.minimum_bytes_ = ACE_MEM_STREAM_MIN_BUFFER;
+
+ // Client will decide what signaling strategy to use.
+
+ // Now set up the shared memory malloc pool.
+ if (new_stream.init (buf,
+ static_cast<ACE_MEM_IO::Signal_Strategy> (client_signaling),
+ &this->malloc_options_) == -1)
+ return -1;
+
+ // @@ Need to handle timeout here.
+ ACE_UINT16 buf_len = static_cast<ACE_UINT16> ((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::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 */
+ if (new_handle == ACE_INVALID_HANDLE)
+ return -1;
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ACE/ace/MEM_Acceptor.h b/ACE/ace/MEM_Acceptor.h
new file mode 100644
index 00000000000..4a57b7528ff
--- /dev/null
+++ b/ACE/ace/MEM_Acceptor.h
@@ -0,0 +1,192 @@
+// -*- 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/ACE_export.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"
+
+#if !defined (ACE_HAS_WINCE)
+#include "ace/OS_QoS.h"
+#endif // ACE_HAS_WINCE
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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-domain sockets with mmap stream
+ * if so desired. (Currently, using UNIX-domain sockets, i.e.,
+ * ACE_LSOCK_*, 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).
+ * @a local_sap is the address that we're going to listen for
+ * connections on. If @a reuse_addr is 1 then we'll use the
+ * @c 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);
+
+ /**
+ * Change the initial MMAP buffer size (in bytes) of the MEM_Stream
+ * this MEM_Acceptor creates.
+ */
+ void init_buffer_size (ACE_OFF_T bytes);
+
+ /// Get the preferred signaling strategy.
+ ACE_MEM_IO::Signal_Strategy preferred_strategy (void) const;
+
+ /// Set the preferred signaling strategy.
+ 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.
+ /// @deprecated This method has been deprecated.
+ 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;
+
+#if !defined (ACE_HAS_WINCE)
+ 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;
+#endif // ACE_HAS_WINCE
+
+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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/MEM_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MEM_ACCEPTOR_H */
diff --git a/ACE/ace/MEM_Acceptor.inl b/ACE/ace/MEM_Acceptor.inl
new file mode 100644
index 00000000000..c06cdaaee4a
--- /dev/null
+++ b/ACE/ace/MEM_Acceptor.inl
@@ -0,0 +1,103 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+#if !defined (ACE_HAS_WINCE)
+ACE_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);
+}
+#endif // ACE_HAS_WINCE
+
+ACE_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;
+}
+
+ACE_INLINE const ACE_TCHAR *
+ACE_MEM_Acceptor::mmap_prefix (void) const
+{
+ return this->mmap_prefix_;
+}
+
+ACE_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);
+ }
+}
+
+ACE_INLINE ACE_MEM_IO::Signal_Strategy
+ACE_MEM_Acceptor::preferred_strategy (void) const
+{
+ return this->preferred_strategy_;
+}
+
+ACE_INLINE void
+ACE_MEM_Acceptor::preferred_strategy (ACE_MEM_IO::Signal_Strategy strategy)
+{
+ this->preferred_strategy_ = strategy;
+}
+
+ACE_INLINE void
+ACE_MEM_Acceptor::init_buffer_size (ACE_OFF_T bytes)
+{
+ this->malloc_options_.minimum_bytes_ = bytes;
+}
+
+ACE_INLINE ACE_MEM_SAP::MALLOC_OPTIONS &
+ACE_MEM_Acceptor::malloc_options (void)
+{
+ // @@ This function has been deprecated and will be removed in the
+ // future.
+
+ return this->malloc_options_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/MEM_Addr.cpp b/ACE/ace/MEM_Addr.cpp
new file mode 100644
index 00000000000..e86682d8b5c
--- /dev/null
+++ b/ACE/ace/MEM_Addr.cpp
@@ -0,0 +1,170 @@
+// $Id$
+
+// Defines the Internet domain address family address format.
+
+#include "ace/MEM_Addr.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/MEM_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/os_include/os_netdb.h"
+
+ACE_RCSID (ace,
+ MEM_Addr,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 = static_cast<u_short> (ACE_OS::strtoul (port_number,
+ 0,
+ 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);
+}
+
+ACE_MEM_Addr::~ACE_MEM_Addr (void)
+{
+}
+
+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_TEXT ("localhost"));
+ return 0;
+}
+
+int
+ACE_MEM_Addr::same_host (const ACE_INET_Addr &sap)
+{
+ ACE_TRACE ("ACE_MEM_Addr::same_host");
+
+ // ACE_INET_Addr::operator== takes port number into account, so get
+ // the addresses without a port number and compare.
+ ACE_INET_Addr me (this->external_);
+ ACE_INET_Addr you (sap);
+ me.set_port_number (0);
+ you.set_port_number (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 = static_cast<u_short> (ACE_OS::strtoul (s,
+ 0,
+ 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 ();
+}
+
+u_long
+ACE_MEM_Addr::hash (void) const
+{
+ return this->external_.hash ();
+}
+
+void
+ACE_MEM_Addr::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ACE/ace/MEM_Addr.h b/ACE/ace/MEM_Addr.h
new file mode 100644
index 00000000000..687c421443c
--- /dev/null
+++ b/ACE/ace/MEM_Addr.h
@@ -0,0 +1,155 @@
+// -*- 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_export.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"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_MEM_Addr from a @a port_number
+ ACE_MEM_Addr (u_short port_number);
+
+ /// Creates an ACE_MEM_Addr from a @a port_name.
+ 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 @a sap designates an endpoint on the same host.
+ int same_host (const ACE_INET_Addr& sap);
+
+ // These methods are useful after the object has been constructed.
+
+ /**
+ * Initializes an ACE_MEM_Addr from a @a port_number. If @a encode
+ * is enabled then @a 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_MEM_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_MEM_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_MEM_Addr from the @a 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.
+ bool operator == (const ACE_MEM_Addr &SAP) const;
+ bool operator == (const ACE_INET_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ bool operator != (const ACE_MEM_Addr &SAP) const;
+ bool 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/MEM_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MEM_ADDR_H */
diff --git a/ACE/ace/MEM_Addr.inl b/ACE/ace/MEM_Addr.inl
new file mode 100644
index 00000000000..ca2c0de2089
--- /dev/null
+++ b/ACE/ace/MEM_Addr.inl
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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 bool
+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 bool
+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 bool
+ACE_MEM_Addr::operator != (const ACE_MEM_Addr &sap) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::operator !=");
+ return !((*this) == sap);
+}
+
+ACE_INLINE bool
+ACE_MEM_Addr::operator != (const ACE_INET_Addr &sap) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::operator !=");
+ return !((*this) == sap);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/MEM_Connector.cpp b/ACE/ace/MEM_Connector.cpp
new file mode 100644
index 00000000000..c66641404bd
--- /dev/null
+++ b/ACE/ace/MEM_Connector.cpp
@@ -0,0 +1,149 @@
+// 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_INLINE__)
+#include "ace/MEM_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_Connector)
+
+void
+ACE_MEM_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_MEM_Connector::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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)
+ : 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);
+}
+
+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)
+{
+ ACE_TRACE ("ACE_MEM_Connector::connect");
+
+ if (!this->address_.same_host (remote_sap))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) MEM_Connector can't connect ")
+ ACE_TEXT ("to %s:%d which is not a local endpoint ")
+ ACE_TEXT ("(local address is %s:%d)\n"),
+ ACE_TEXT_CHAR_TO_TCHAR (remote_sap.get_host_name ()),
+ remote_sap.get_port_number (),
+ ACE_TEXT_CHAR_TO_TCHAR (this->address_.get_host_name ()),
+ this->address_.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) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_TEXT ("%p\n"),
+ ACE_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_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_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_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_TEXT ("ACE_MEM_Connector::connect error receiving shm filename.\n")),
+ -1);
+
+ if (new_stream.init (buf,
+ static_cast<ACE_MEM_IO::Signal_Strategy> (server_strategy),
+ &this->malloc_options_) == -1)
+ return -1;
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ACE/ace/MEM_Connector.h b/ACE/ace/MEM_Connector.h
new file mode 100644
index 00000000000..a8ebd995b1c
--- /dev/null
+++ b/ACE/ace/MEM_Connector.h
@@ -0,0 +1,179 @@
+/* -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/SOCK_Connector.h"
+#include "ace/MEM_Stream.h"
+#include "ace/MEM_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_MEM_Connector
+ *
+ * @brief Defines the format and interface for connecting to a peer
+ * on a @c ACE_MEM_Stream object.
+ */
+class ACE_Export ACE_MEM_Connector : public ACE_SOCK_Connector
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_MEM_Connector (void);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_MEM_Stream
+ * object if the connection succeeds.
+ *
+ * @param new_stream The @c ACE_MEM_Stream object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @note remote_sap must be an address on the local
+ * host.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ */
+ 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);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_MEM_Stream
+ * object if the connection succeeds.
+ *
+ * @param new_stream The @c ACE_MEM_Stream object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @note remote_sap must be an address on the local
+ * host.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ 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);
+
+ /// Get the preferred signaling strategy.
+ ACE_MEM_IO::Signal_Strategy preferred_strategy (void) const;
+
+ /// Set the preferred signaling strategy.
+ void preferred_strategy (ACE_MEM_IO::Signal_Strategy strategy);
+
+ /// Accessor to underlying malloc options.
+ /// @deprecated This method has been deprecated.
+ 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/MEM_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MEM_CONNECTOR_H */
diff --git a/ACE/ace/MEM_Connector.inl b/ACE/ace/MEM_Connector.inl
new file mode 100644
index 00000000000..024ab5d8b5b
--- /dev/null
+++ b/ACE/ace/MEM_Connector.inl
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// Establish a connection.
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_MEM_IO::Signal_Strategy
+ACE_MEM_Connector::preferred_strategy (void) const
+{
+ return this->preferred_strategy_;
+}
+
+ACE_INLINE void
+ACE_MEM_Connector::preferred_strategy (ACE_MEM_IO::Signal_Strategy strategy)
+{
+ this->preferred_strategy_ = strategy;
+}
+
+ACE_INLINE ACE_MEM_SAP::MALLOC_OPTIONS &
+ACE_MEM_Connector::malloc_options (void)
+{
+ // @@ This function has been deprecated and will be removed in the
+ // future.
+
+ return this->malloc_options_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/MEM_IO.cpp b/ACE/ace/MEM_IO.cpp
new file mode 100644
index 00000000000..9d6167c6ce7
--- /dev/null
+++ b/ACE/ace/MEM_IO.cpp
@@ -0,0 +1,541 @@
+// MEM_IO.cpp
+// $Id$
+
+#include "ace/MEM_IO.h"
+#include "ace/Handle_Set.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/MEM_IO.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, MEM_IO, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_IO)
+
+ACE_Reactive_MEM_IO::~ACE_Reactive_MEM_IO (void)
+{
+}
+
+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);
+}
+
+ssize_t
+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 || this->handle_ == ACE_INVALID_HANDLE)
+ return -1;
+
+ ACE_OFF_T new_offset = 0;
+ ssize_t retv = ACE::recv (this->handle_,
+ (char *) &new_offset,
+ sizeof (ACE_OFF_T),
+ flags,
+ timeout);
+
+ if (retv == 0)
+ {
+ // ACE_DEBUG ((LM_INFO, "MEM_Stream closed\n"));
+ buf = 0;
+ return 0;
+ }
+ else if (retv != sizeof (ACE_OFF_T))
+ {
+ // Nothing available or we are really screwed.
+ buf = 0;
+ return -1;
+ }
+
+ return this->get_buf_len (new_offset, buf);
+}
+
+ssize_t
+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 || this->handle_ == ACE_INVALID_HANDLE)
+ return -1;
+
+ ACE_OFF_T offset = reinterpret_cast<char *> (buf) -
+ 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_TEXT ("_sema_to_server"));
+ ACE_OS::strcpy (client_sema, basename);
+ ACE_OS::strcat (client_sema, ACE_TEXT ("_sema_to_client"));
+ ACE_OS::strcpy (server_lock, basename);
+ ACE_OS::strcat (server_lock, ACE_TEXT ("_lock_to_server"));
+ ACE_OS::strcpy (client_lock, basename);
+ ACE_OS::strcat (client_lock, ACE_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 = 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 = 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;
+}
+
+ssize_t
+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;
+ }
+}
+
+ssize_t
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_MEM_IO::dump");
+#endif /* ACE_HAS_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.
+
+ size_t len = message_block->total_length ();
+
+ if (len != 0)
+ {
+ ACE_MEM_SAP_Node *buf =
+ reinterpret_cast<ACE_MEM_SAP_Node *> (
+ this->deliver_strategy_->acquire_buffer (len));
+ size_t n = 0;
+ while (message_block != 0)
+ {
+ ACE_OS::memcpy (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;
+ }
+
+ int inlen;
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ FIONREAD,
+ &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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ACE/ace/MEM_IO.h b/ACE/ace/MEM_IO.h
new file mode 100644
index 00000000000..1c024d5c561
--- /dev/null
+++ b/ACE/ace/MEM_IO.h
@@ -0,0 +1,310 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/SOCK.h"
+#include "ace/MEM_SAP.h"
+#include "ace/Message_Block.h"
+#include "ace/Process_Semaphore.h"
+#include "ace/Process_Mutex.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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.
+ *
+ * @a options is used to pass in the Malloc_Options to initialize
+ * underlying ACE_MMAP.
+ */
+ 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, @a timeout only applies to ACE::recv.
+ */
+ virtual ssize_t recv_buf (ACE_MEM_SAP_Node *&buf,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Wait to to @a timeout amount of time to send @a buf. If <send>
+ * times out a -1 is returned with @c errno == ETIME. If it succeeds
+ * the number of bytes sent is returned. */
+ virtual ssize_t send_buf (ACE_MEM_SAP_Node *buf,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Convert the buffer offset <off> to absolute address to @a buf.
+ * Return the size of valid information containing in the @a buf,
+ * -1 if <shm_malloc_> is not initialized.
+ */
+ ssize_t get_buf_len (const ACE_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:
+ 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, @a timeout only applies to ACE::recv.
+ */
+ virtual ssize_t recv_buf (ACE_MEM_SAP_Node *&buf,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Wait to to @a timeout amount of time to send @a buf. If <send>
+ * times out a -1 is returned with @c errno == ETIME. If it succeeds
+ * the number of bytes sent is returned. */
+ virtual ssize_t 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 @a 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 @a n byte buffer from the shm_malloc_ thru connected socket.
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags) ;
+
+ /// Send an @a 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 @a n byte buffer from the shm_malloc_ thru connected socket.
+ ssize_t recv (void *buf,
+ size_t n) ;
+
+ /**
+ * Wait to to @a timeout amount of time to send up to @a n bytes into
+ * @a buf from <handle> (uses the <send> call). If <send> times out
+ * a -1 is returned with @c 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 @a timeout amount of time to send up to @a n bytes into
+ * @a buf from <handle> (uses the <send> call). If <send> times out
+ * a -1 is returned with @c 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 @a timeout amount of time to send the @a message_block.
+ * If <send> times out a -1 is returned with @c 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 @a timeout amount of time to receive up to @a n bytes
+ * into @a buf from <handle> (uses the <recv> call). If <recv> times
+ * out a -1 is returned with @c 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 @a timeout amount of time to receive up to @a n bytes
+ * into @a buf from <handle> (uses the <recv> call). If <recv> times
+ * out a -1 is returned with @c 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/MEM_IO.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_IO_H */
diff --git a/ACE/ace/MEM_IO.inl b/ACE/ace/MEM_IO.inl
new file mode 100644
index 00000000000..505c90c628c
--- /dev/null
+++ b/ACE/ace/MEM_IO.inl
@@ -0,0 +1,233 @@
+// -*- C++ -*-
+//
+// $Id$
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Reactive_MEM_IO::ACE_Reactive_MEM_IO ()
+{
+}
+
+#if defined (ACE_WIN32) || !defined (_ACE_USE_SV_SEM)
+ACE_INLINE
+ACE_MT_MEM_IO::Simple_Queue::Simple_Queue (void)
+ : mq_ (0),
+ malloc_ (0)
+{
+}
+
+ACE_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;
+}
+
+ACE_INLINE
+ACE_MT_MEM_IO::Simple_Queue::Simple_Queue (MQ_Struct *mq)
+ : mq_ (mq),
+ malloc_ (0)
+{
+}
+
+ACE_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 */
+
+ACE_INLINE ssize_t
+ACE_Reactive_MEM_IO::get_buf_len (const ACE_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 =
+ reinterpret_cast<ACE_MEM_SAP_Node *> (
+ 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.
+ACE_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");
+}
+
+ACE_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;
+ ssize_t 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;
+}
+
+ACE_INLINE
+ACE_MEM_IO::~ACE_MEM_IO (void)
+{
+ delete this->deliver_strategy_;
+}
+
+ACE_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);
+}
+
+ACE_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;
+}
+
+ACE_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.
+
+ACE_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.
+
+ACE_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.
+
+ACE_INLINE ssize_t
+ACE_MEM_IO::recv (void *buf, size_t n)
+{
+ ACE_TRACE ("ACE_MEM_IO::recv");
+
+ return this->recv (buf, n, 0);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/MEM_SAP.cpp b/ACE/ace/MEM_SAP.cpp
new file mode 100644
index 00000000000..8a98a3b3d0c
--- /dev/null
+++ b/ACE/ace/MEM_SAP.cpp
@@ -0,0 +1,97 @@
+// $Id$
+
+#include "ace/MEM_SAP.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/MEM_SAP.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, MEM_SAP, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_IPC_SAP)
+
+void
+ACE_MEM_SAP::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("ACE_MEM_SAP uninitialized.\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_MEM_SAP::ACE_MEM_SAP (void)
+ : handle_ (ACE_INVALID_HANDLE),
+ shm_malloc_ (0)
+{
+ // ACE_TRACE ("ACE_MEM_SAP::ACE_MEM_SAP");
+}
+
+ACE_MEM_SAP::~ACE_MEM_SAP (void)
+{
+ // ACE_TRACE ("ACE_MEM_SAP::~ACE_MEM_SAP");
+ delete this->shm_malloc_;
+}
+
+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);
+
+ if (this->shm_malloc_->bad () != 0)
+ {
+ this->shm_malloc_->remove (); // Cleanup OS resources
+ delete this->shm_malloc_;
+ this->shm_malloc_ = 0;
+ return -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 (1);
+
+ delete this->shm_malloc_;
+ this->shm_malloc_ = 0;
+
+ return retv;
+}
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/MEM_SAP.h b/ACE/ace/MEM_SAP.h
new file mode 100644
index 00000000000..a62b25ab2de
--- /dev/null
+++ b/ACE/ace/MEM_SAP.h
@@ -0,0 +1,169 @@
+// -*- 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/ACE_export.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/PI_Malloc.h"
+#include "ace/Malloc_T.h"
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Process_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_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, @a timeout only applies to ACE::recv.
+ */
+ virtual ssize_t recv_buf (ACE_MEM_SAP_Node *&buf,
+ int flags,
+ const ACE_Time_Value *timeout) = 0;
+
+ /**
+ * Wait to to @a timeout amount of time to send @a buf. If <send>
+ * times out a -1 is returned with @c errno == ETIME. If it succeeds
+ * the number of bytes sent is returned. */
+ virtual ssize_t send_buf (ACE_MEM_SAP_Node *buf,
+ int flags,
+ const ACE_Time_Value *timeout) = 0;
+
+ /// request a buffer of size @a 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 @a 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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/MEM_SAP.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SOCK_IO_H */
diff --git a/ACE/ace/MEM_SAP.inl b/ACE/ace/MEM_SAP.inl
new file mode 100644
index 00000000000..3c2a4eb9d9a
--- /dev/null
+++ b/ACE/ace/MEM_SAP.inl
@@ -0,0 +1,64 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/RW_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_MEM_SAP_Node::ACE_MEM_SAP_Node (size_t cap)
+ : capacity_ (cap),
+ size_ (0),
+ next_ (0)
+{
+}
+
+ACE_INLINE size_t
+ACE_MEM_SAP_Node::size (void) const
+{
+ return this->size_;
+}
+
+ACE_INLINE size_t
+ACE_MEM_SAP_Node::capacity (void) const
+{
+ return this->capacity_;
+}
+
+ACE_INLINE void *
+ACE_MEM_SAP_Node::data (void)
+{
+ return this + 1;
+}
+
+
+ACE_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,
+ static_cast<ACE_MEM_SAP_Node *>
+ (this->shm_malloc_->malloc (sizeof (ACE_MEM_SAP_Node) + size)),
+ ACE_MEM_SAP_Node (size),
+ 0);
+ return buf;
+}
+
+ACE_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/MEM_Stream.cpp b/ACE/ace/MEM_Stream.cpp
new file mode 100644
index 00000000000..0e8edb9ced7
--- /dev/null
+++ b/ACE/ace/MEM_Stream.cpp
@@ -0,0 +1,47 @@
+// $Id$
+
+#include "ace/MEM_Stream.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/MEM_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, MEM_Stream, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_Stream)
+
+void
+ACE_MEM_Stream::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_MEM_Stream::dump");
+#endif /* ACE_HAS_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 ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ACE/ace/MEM_Stream.h b/ACE/ace/MEM_Stream.h
new file mode 100644
index 00000000000..1a217adfb6e
--- /dev/null
+++ b/ACE/ace/MEM_Stream.h
@@ -0,0 +1,158 @@
+// -*- 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"
+
+#if !defined (ACE_MEM_STREAM_MIN_BUFFER)
+# define ACE_MEM_STREAM_MIN_BUFFER 4096
+#endif /* ACE_MEM_STREAM_MIN_BUFFER */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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. Notice that ACE_MEM_Stream can only send messages no bigger
+ * than the underlying MMAP file size minus sizeof (ACE_MEM_SAP_Node).
+ * The size of the MMAP file is default to ACE_MEM_STREAM_MIN_BUFFER.
+ * (Define above in this file, to 4096 bytes.)
+ * If you need to increase the size of allowable message
+ * ACE_MEM_Stream can handle, you can set it to either
+ * @c ACE_MEM_Acceptor::malloc_options(). minimal_bytes_
+ * @c ACE_MEM_Acceptor::init_buffer_size (size_t size);
+ * before establishing a connection.
+ */
+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, size_t n);
+ ssize_t recv_n (void *buf, size_t 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, size_t n, int flags);
+ ssize_t recv_n (void *buf, size_t n, int flags);
+
+#if 0
+ /**
+ * Try to send exactly @a len bytes into @a buf from <handle> (uses
+ * the <send> call). If <send> blocks for longer than @a timeout the
+ * number of bytes actually sent is returned with @c errno == ETIME.
+ * If a timeout does not occur, <send_n> return @a 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 @a len bytes into @a buf from <handle> (uses
+ * the <ACE::recv_n> call). The ACE_Time_Value indicates how long
+ * to blocking trying to receive. If @a timeout == 0, the caller
+ * will block until action is possible, else will wait until the
+ * relative time specified in *@a timeout elapses). If <recv> blocks
+ * for longer than @a timeout the number of bytes actually read is
+ * returned with @c errno == ETIME. If a timeout does not occur,
+ * <recv_n> return @a 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 @a 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 @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/MEM_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MEM_STREAM_H */
diff --git a/ACE/ace/MEM_Stream.inl b/ACE/ace/MEM_Stream.inl
new file mode 100644
index 00000000000..c29459ed35c
--- /dev/null
+++ b/ACE/ace/MEM_Stream.inl
@@ -0,0 +1,180 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/MEM_Stream.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_MEM_Stream::ACE_MEM_Stream (void)
+{
+ // ACE_TRACE ("ACE_MEM_Stream::ACE_MEM_Stream");
+}
+
+ACE_INLINE
+ACE_MEM_Stream::ACE_MEM_Stream (ACE_HANDLE h)
+{
+ // ACE_TRACE ("ACE_MEM_Stream::ACE_MEM_Stream");
+ this->set_handle (h);
+}
+
+ACE_INLINE
+ACE_MEM_Stream::~ACE_MEM_Stream (void)
+{
+ // ACE_TRACE ("ACE_MEM_Stream::~ACE_MEM_Stream");
+}
+
+ACE_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.
+
+ACE_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;
+}
+
+ACE_INLINE ssize_t
+ACE_MEM_Stream::send_n (const void *buf, size_t n)
+{
+ return this->send (buf, n);
+}
+
+
+ACE_INLINE ssize_t
+ACE_MEM_Stream::recv_n (void *buf, size_t n)
+{
+ return this->recv (buf, n);
+}
+
+ACE_INLINE ssize_t
+ACE_MEM_Stream::send_n (const void *buf, size_t n, int flags)
+{
+ return this->send (buf, n, flags);
+}
+
+ACE_INLINE ssize_t
+ACE_MEM_Stream::recv_n (void *buf, size_t n, int flags)
+{
+ return this->recv (buf, n, flags);
+}
+
+#if 0
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/MMAP_Memory_Pool.cpp b/ACE/ace/MMAP_Memory_Pool.cpp
new file mode 100644
index 00000000000..1051b33d9ec
--- /dev/null
+++ b/ACE/ace/MMAP_Memory_Pool.cpp
@@ -0,0 +1,578 @@
+// $Id$
+
+// MMAP_Memory_Pool.cpp
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/OS_NS_sys_mman.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/Log_Msg.h"
+#include "ace/Truncate.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 */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/MMAP_Memory_Pool.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace,
+ MMAP_Memory_Pool,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool)
+
+void
+ACE_MMAP_Memory_Pool::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_MMAP_Memory_Pool::release (int destroy)
+{
+ 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 */
+
+ if (destroy)
+ this->mmap_.remove ();
+ else
+ this->mmap_.close ();
+ return 0;
+}
+
+int
+ACE_MMAP_Memory_Pool::sync (size_t len, int flags)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
+
+ return this->mmap_.sync (len, flags);
+}
+
+int
+ACE_MMAP_Memory_Pool::sync (int flags)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
+
+ size_t const len = ACE_Utils::truncate_cast<size_t> (
+ 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.
+// Change protection of all pages in the mapped region.
+
+int
+ACE_MMAP_Memory_Pool::protect (size_t len, int prot)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
+
+ return this->mmap_.protect (len, prot);
+}
+
+int
+ACE_MMAP_Memory_Pool::protect (int prot)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
+
+ size_t const len = ACE_Utils::truncate_cast<size_t> (
+ 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),
+ use_fixed_addr_(0),
+ flags_ (MAP_SHARED),
+ write_each_page_ (0),
+ minimum_bytes_ (0),
+ sa_ (0),
+ file_mode_ (ACE_DEFAULT_FILE_PERMS)
+{
+ 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_ = false;
+#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_ = true;
+#endif /* (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32) */
+
+ // Only change the defaults if <options> != 0.
+ if (options)
+ {
+ if (options->flags_ != 0)
+ this->flags_ = options->flags_;
+ use_fixed_addr_ = options->use_fixed_addr_;
+
+ if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED)
+ {
+ this->base_addr_ = 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_;
+ this->file_mode_ = options->file_mode_;
+ }
+
+ 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::get_temp_dir (this->backing_store_name_,
+ MAXPATHLEN - 17) == -1)
+ // -17 for ace-malloc-XXXXXX
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Temporary path too long, ")
+ ACE_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_TEXT ("ace-malloc-XXXXXX"));
+
+ // If requested an unique filename, use mktemp to get a random file.
+ if (options && options->unique_)
+ ACE_OS::mktemp(this->backing_store_name_);
+#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)
+ if (this->signal_handler_.register_handler (SIGSEGV, this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n", this->backing_store_name_));
+#endif /* ACE_WIN32 */
+}
+
+ACE_MMAP_Memory_Pool::~ACE_MMAP_Memory_Pool (void)
+{
+}
+
+// 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,
+ size_t & map_size)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::commit_backing_store_name");
+
+#if defined (__Lynx__)
+ 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_Utils::truncate_cast<size_t> (
+ ACE_OS::lseek (this->mmap_.handle (),
+ static_cast<ACE_OFF_T> (seek_len - 1),
+ SEEK_END));
+
+ if (map_size == static_cast<size_t> (-1)
+ || ACE_OS::write (this->mmap_.handle (),
+ "",
+ 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ this->backing_store_name_),
+ -1);
+ }
+
+#if defined (ACE_OPENVMS)
+ ::fsync(this->mmap_.handle());
+#endif
+
+ // Increment by one to put us at the beginning of the next chunk...
+ ++map_size;
+#endif /* __Lynx__ */
+ return 0;
+}
+
+// Memory map the file up to <map_size> bytes.
+
+int
+ACE_MMAP_Memory_Pool::map_file (size_t map_size)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::map_file");
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ void* obase_addr = this->base_addr_;
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+ // Unmap the existing mapping.
+ this->mmap_.unmap ();
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::NEVER_FIXED)
+ this->base_addr_ = 0;
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+ // Remap the file; try to stay at the same location as a previous mapping
+ // but do not force it with MAP_FIXED. Doing so will give the OS permission
+ // to map locations currently holding other things (such as the heap, or
+ // the C library) into the map file, producing very unexpected results.
+ if (this->mmap_.map (map_size,
+ PROT_RDWR,
+ this->flags_,
+ this->base_addr_,
+ 0,
+ this->sa_) == -1
+ || this->base_addr_ != 0
+#ifdef ACE_HAS_WINCE
+ && this->mmap_.addr () == 0) // WinCE does not allow users to specify alloc addr.
+#else
+ && this->mmap_.addr () != this->base_addr_)
+#endif // ACE_HAS_WINCE
+ {
+#if 0
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) addr = %@, base_addr = %@, map_size = %B, %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 ();
+ if(obase_addr && this->base_addr_ != obase_addr)
+ ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (obase_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 =
+ // %B, rounded_bytes = %B\n", nbytes, rounded_bytes));
+
+ size_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 = %B,
+ // rounded_bytes = %B, map_size = %B\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 < static_cast <size_t> (this->minimum_bytes_))
+ nbytes = static_cast <size_t> (this->minimum_bytes_);
+
+ if (this->mmap_.open (this->backing_store_name_,
+ O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
+ this->file_mode_, 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_,
+ static_cast<size_t> (-1),
+ O_RDWR,
+ this->file_mode_,
+ PROT_RDWR,
+ this->flags_,
+ this->base_addr_,
+ 0,
+ this->sa_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("MMAP_Memory_Pool::init_acquire, EEXIST")),
+ 0);
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ // Update the mapped segment information
+ ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->mmap_.addr(),
+ this->mmap_.size());
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+ return this->mmap_.addr ();
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("MMAP_Memory_Pool::init_acquire")),
+ 0);
+}
+
+#if defined (ACE_WIN32)
+int
+ACE_MMAP_Memory_Pool::seh_selector (void *ep)
+{
+ DWORD const 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_TEXT ("Remapping with fault address at: %@\n"), addr));
+ size_t const current_map_size =
+ ACE_Utils::truncate_cast<size_t> (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,
+ size_t minimum_bytes,
+ u_int flags,
+ int guess_on_fault,
+ LPSECURITY_ATTRIBUTES sa,
+ mode_t file_mode,
+ bool unique)
+ : base_addr_ (base_addr),
+ use_fixed_addr_ (use_fixed_addr),
+ write_each_page_ (write_each_page),
+ minimum_bytes_ (minimum_bytes),
+ flags_ (flags),
+ guess_on_fault_ (guess_on_fault),
+ sa_ (sa),
+ file_mode_ (file_mode),
+ unique_ (unique)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options");
+ // for backwards compatability
+ if (base_addr_ == 0 && use_fixed_addr_ == ALWAYS_FIXED)
+ use_fixed_addr_ = FIRSTCALL_FIXED;
+}
+
+// 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;
+#if 0
+ else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) received %S\n"), signum));
+#endif
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) new mapping address = %@\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_TEXT ("(%P|%t) si_signo = %d, si_code = %d, addr = %@\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 %@ 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.
+ size_t const current_map_size =
+ ACE_Utils::truncate_cast<size_t> (ACE_OS::filesize (this->mmap_.handle ()));
+
+ if (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;
+}
+
+void *
+ACE_MMAP_Memory_Pool::base_addr (void) const
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::base_addr");
+ return this->base_addr_;
+}
+
+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_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");
+}
+
+ACE_Lite_MMAP_Memory_Pool::~ACE_Lite_MMAP_Memory_Pool (void)
+{
+}
+
+int
+ACE_Lite_MMAP_Memory_Pool::sync (size_t, int)
+{
+ ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
+ return 0;
+}
+
+int
+ACE_Lite_MMAP_Memory_Pool::sync (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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/MMAP_Memory_Pool.h b/ACE/ace/MMAP_Memory_Pool.h
new file mode 100644
index 00000000000..ede22814183
--- /dev/null
+++ b/ACE/ace/MMAP_Memory_Pool.h
@@ -0,0 +1,327 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file MMAP_Memory_Pool.h
+ *
+ * $Id$
+ *
+ * @author Dougls C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MMAP_MEMORY_POOL_H
+#define ACE_MMAP_MEMORY_POOL_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/ACE.h"
+#include "ace/Event_Handler.h"
+#include "ace/Sig_Handler.h"
+#include "ace/Mem_Map.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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:
+ enum
+ {
+ /**
+ * The base address from the first call to mmap will be used for subsequent
+ * calls to mmap.
+ */
+ FIRSTCALL_FIXED = 0,
+
+ /**
+ * The base address specified in base_addr will be used in all calls to
+ * mmap.
+ */
+ ALWAYS_FIXED = 1,
+
+ /**
+ * The base address will be selected by the OS for each call to mmap.
+ * Caution should be used with this mode since a call that requires the
+ * backing store to grow may change pointers that are cached by the
+ * application.
+ */
+ NEVER_FIXED = 2
+ };
+
+ // = Initialization method.
+ ACE_MMAP_Memory_Pool_Options (const void *base_addr = ACE_DEFAULT_BASE_ADDR,
+ int use_fixed_addr = ALWAYS_FIXED,
+ int write_each_page = 1,
+ size_t minimum_bytes = 0,
+ u_int flags = 0,
+ int guess_on_fault = 1,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ mode_t file_mode = ACE_DEFAULT_FILE_PERMS,
+ bool unique_ = false);
+
+ /// Base address of the memory-mapped backing store.
+ const void *base_addr_;
+
+ /**
+ * Determines whether we set @c base_addr_ or if mmap(2) selects it
+ * FIRSTCALL_FIXED The base address from the first call to mmap
+ * will be used for subsequent calls to mmap
+ * ALWAYS_FIXED The base address specified in base_addr will be
+ * used in all calls to mmap.
+ * NEVER_FIXED The base address will be selected by the OS for
+ * each call to mmap. Caution should be used with
+ * this mode since a call that requires the backing
+ * store to grow may change pointers that are
+ * cached by the application.
+ */
+ 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.
+ size_t minimum_bytes_;
+
+ /// Any special flags that need to be used for @c 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).
+ */
+ bool guess_on_fault_;
+
+ /// Pointer to a security attributes object. Only used on NT.
+ LPSECURITY_ATTRIBUTES sa_;
+
+ /// File mode for mmaped file, if it is created.
+ mode_t file_mode_;
+
+ /// Do we want an unique backing store name?
+ bool unique_;
+
+private:
+ // Prevent copying
+ ACE_MMAP_Memory_Pool_Options (const ACE_MMAP_Memory_Pool_Options &);
+ ACE_MMAP_Memory_Pool_Options &operator= (const ACE_MMAP_Memory_Pool_Options &);
+};
+
+/**
+ * @class ACE_MMAP_Memory_Pool
+ *
+ * @brief Make a memory pool that is based on @c 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);
+
+ /// Destructor.
+ 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 @a nbytes from the memory pool. @a 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 (int destroy = 1);
+
+ /// Sync the memory region to the backing store starting at
+ /// @c this->base_addr_.
+ virtual int sync (size_t len, int flags = MS_SYNC);
+
+ /// Sync the memory region to the backing store starting at
+ /// @c this->base_addr_. Will sync as much as the backing file
+ /// allows.
+ virtual int sync (int flags = MS_SYNC);
+
+ /// Sync the memory region to the backing store starting at @a addr.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to @a prot
+ * starting at <this->base_addr_> up to @a len bytes. If @a len == -1
+ * then change protection of all pages in the mapped region.
+ */
+ virtual int protect (size_t len, int prot = PROT_RDWR);
+
+ /**
+ * Change the protection of all the pages of the mapped region to @a prot
+ * starting at <this->base_addr_>.
+ */
+ virtual int protect (int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to @a prot
+ /// starting at @a addr up to @a 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 @a 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;
+
+ /// Get reference to underlying ACE_Mem_Map object.
+ ACE_Mem_Map const & mmap (void) const;
+
+ /// Get reference to underlying ACE_Mem_Map object.
+ ACE_Mem_Map & mmap (void);
+
+ /// 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 @a map_size of the backing store and commit the
+ /// memory.
+ virtual int commit_backing_store_name (size_t rounded_bytes,
+ size_t & map_size);
+
+ /// Memory map the file up to @a map_size bytes.
+ virtual int map_file (size_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_;
+
+ /// Must we use the @c base_addr_ or can we let mmap(2) select it?
+ int use_fixed_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.
+ size_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).
+ */
+ bool guess_on_fault_;
+
+ /// Security attributes object, only used on NT.
+ LPSECURITY_ATTRIBUTES sa_;
+
+ /// Protection mode for mmaped file.
+ mode_t file_mode_;
+};
+
+/**
+ * @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:
+ /// Initialize the pool.
+ ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name = 0,
+ const OPTIONS *options = 0);
+
+ /// Destructor.
+ virtual ~ACE_Lite_MMAP_Memory_Pool (void);
+
+ /// Overwrite the default sync behavior with no-op
+ virtual int sync (size_t len, int flags = MS_SYNC);
+
+ /// Overwrite the default sync behavior with no-op
+ virtual int sync (int flags = MS_SYNC);
+
+ /// Overwrite the default sync behavior with no-op
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/MMAP_Memory_Pool.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MMAP_MEMORY_POOL_H */
diff --git a/ACE/ace/MMAP_Memory_Pool.inl b/ACE/ace/MMAP_Memory_Pool.inl
new file mode 100644
index 00000000000..db3f5a7ba0f
--- /dev/null
+++ b/ACE/ace/MMAP_Memory_Pool.inl
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Mem_Map const &
+ACE_MMAP_Memory_Pool::mmap (void) const
+{
+ return mmap_;
+}
+
+ACE_INLINE
+ACE_Mem_Map &
+ACE_MMAP_Memory_Pool::mmap (void)
+{
+ return mmap_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Makefile.am b/ACE/ace/Makefile.am
new file mode 100644
index 00000000000..d5bc8bf0a99
--- /dev/null
+++ b/ACE/ace/Makefile.am
@@ -0,0 +1,1419 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## ./bin/mwc.pl -type automake -noreldefs ACE.mwc
+
+includedir = @includedir@/ace
+pkgconfigdir = @libdir@/pkgconfig
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+SUBDIRS = \
+ . \
+ QoS \
+ SSL
+
+CLEANFILES =
+lib_LTLIBRARIES =
+pkgconfig_DATA =
+nobase_include_HEADERS =
+
+## Makefile.ACE.am
+
+if !BUILD_ACE_FOR_TAO
+
+lib_LTLIBRARIES += libACE.la
+
+libACE_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_BUILD_DLL
+
+libACE_la_SOURCES = \
+ ACE.cpp \
+ ACE_crc32.cpp \
+ ACE_crc_ccitt.cpp \
+ ace_wchar.cpp \
+ ATM_Acceptor.cpp \
+ ATM_Addr.cpp \
+ ATM_Connector.cpp \
+ ATM_Params.cpp \
+ ATM_QoS.cpp \
+ ATM_Stream.cpp \
+ Activation_Queue.cpp \
+ Active_Map_Manager.cpp \
+ Addr.cpp \
+ Argv_Type_Converter.cpp \
+ Assert.cpp \
+ Asynch_IO.cpp \
+ Asynch_IO_Impl.cpp \
+ Asynch_Pseudo_Task.cpp \
+ Atomic_Op.cpp \
+ Atomic_Op_Sparc.c \
+ Auto_Event.cpp \
+ Barrier.cpp \
+ Base_Thread_Adapter.cpp \
+ Based_Pointer_Repository.cpp \
+ Basic_Stats.cpp \
+ Basic_Types.cpp \
+ CDR_Base.cpp \
+ CDR_Size.cpp \
+ CDR_Stream.cpp \
+ Capabilities.cpp \
+ Cleanup.cpp \
+ Codecs.cpp \
+ Codeset_IBM1047.cpp \
+ Codeset_Registry.cpp \
+ Codeset_Registry_db.cpp \
+ Condition_Recursive_Thread_Mutex.cpp \
+ Condition_Thread_Mutex.cpp \
+ Configuration.cpp \
+ Configuration_Import_Export.cpp \
+ Connection_Recycling_Strategy.cpp \
+ Containers.cpp \
+ Copy_Disabled.cpp \
+ Countdown_Time.cpp \
+ DEV.cpp \
+ DEV_Addr.cpp \
+ DEV_Connector.cpp \
+ DEV_IO.cpp \
+ DLL.cpp \
+ DLL_Manager.cpp \
+ Date_Time.cpp \
+ Dev_Poll_Reactor.cpp \
+ Dirent.cpp \
+ Dirent_Selector.cpp \
+ Dump.cpp \
+ Dynamic.cpp \
+ Dynamic_Message_Strategy.cpp \
+ Dynamic_Service_Base.cpp \
+ Dynamic_Service_Dependency.cpp \
+ Encoding_Converter.cpp \
+ Encoding_Converter_Factory.cpp \
+ Event.cpp \
+ Event_Handler.cpp \
+ FIFO.cpp \
+ FIFO_Recv.cpp \
+ FIFO_Recv_Msg.cpp \
+ FIFO_Send.cpp \
+ FIFO_Send_Msg.cpp \
+ FILE.cpp \
+ FILE_Addr.cpp \
+ FILE_Connector.cpp \
+ FILE_IO.cpp \
+ File_Lock.cpp \
+ Filecache.cpp \
+ Flag_Manip.cpp \
+ Framework_Component.cpp \
+ Functor.cpp \
+ Functor_String.cpp \
+ Get_Opt.cpp \
+ Handle_Ops.cpp \
+ Handle_Set.cpp \
+ Hashable.cpp \
+ High_Res_Timer.cpp \
+ ICMP_Socket.cpp \
+ INET_Addr.cpp \
+ IOStream.cpp \
+ IO_Cntl_Msg.cpp \
+ IO_SAP.cpp \
+ IPC_SAP.cpp \
+ Init_ACE.cpp \
+ LSOCK.cpp \
+ LSOCK_Acceptor.cpp \
+ LSOCK_CODgram.cpp \
+ LSOCK_Connector.cpp \
+ LSOCK_Dgram.cpp \
+ LSOCK_Stream.cpp \
+ Lib_Find.cpp \
+ Local_Memory_Pool.cpp \
+ Local_Name_Space.cpp \
+ Local_Tokens.cpp \
+ Lock.cpp \
+ Log_Msg.cpp \
+ Log_Msg_Backend.cpp \
+ Log_Msg_Callback.cpp \
+ Log_Msg_IPC.cpp \
+ Log_Msg_NT_Event_Log.cpp \
+ Log_Msg_UNIX_Syslog.cpp \
+ Log_Record.cpp \
+ Logging_Strategy.cpp \
+ MEM_Acceptor.cpp \
+ MEM_Addr.cpp \
+ MEM_Connector.cpp \
+ MEM_IO.cpp \
+ MEM_SAP.cpp \
+ MEM_Stream.cpp \
+ MMAP_Memory_Pool.cpp \
+ Malloc.cpp \
+ Malloc_Allocator.cpp \
+ Manual_Event.cpp \
+ Mem_Map.cpp \
+ Message_Block.cpp \
+ Message_Queue.cpp \
+ Message_Queue_NT.cpp \
+ Message_Queue_Vx.cpp \
+ Method_Request.cpp \
+ Msg_WFMO_Reactor.cpp \
+ Multihomed_INET_Addr.cpp \
+ Mutex.cpp \
+ NT_Service.cpp \
+ Name_Proxy.cpp \
+ Name_Request_Reply.cpp \
+ Name_Space.cpp \
+ Naming_Context.cpp \
+ Netlink_Addr.cpp \
+ Notification_Strategy.cpp \
+ Notification_Queue.cpp \
+ OS_Errno.cpp \
+ OS_Log_Msg_Attributes.cpp \
+ OS_NS_Thread.cpp \
+ OS_NS_arpa_inet.cpp \
+ OS_NS_ctype.cpp \
+ OS_NS_dirent.cpp \
+ OS_NS_dlfcn.cpp \
+ OS_NS_errno.cpp \
+ OS_NS_fcntl.cpp \
+ OS_NS_math.cpp \
+ OS_NS_netdb.cpp \
+ OS_NS_poll.cpp \
+ OS_NS_pwd.cpp \
+ OS_NS_regex.cpp \
+ OS_NS_signal.cpp \
+ OS_NS_stdio.cpp \
+ OS_NS_stdlib.cpp \
+ OS_NS_string.cpp \
+ OS_NS_strings.cpp \
+ OS_NS_stropts.cpp \
+ OS_NS_sys_mman.cpp \
+ OS_NS_sys_msg.cpp \
+ OS_NS_sys_resource.cpp \
+ OS_NS_sys_select.cpp \
+ OS_NS_sys_sendfile.cpp \
+ OS_NS_sys_shm.cpp \
+ OS_NS_sys_socket.cpp \
+ OS_NS_sys_stat.cpp \
+ OS_NS_sys_time.cpp \
+ OS_NS_sys_uio.cpp \
+ OS_NS_sys_utsname.cpp \
+ OS_NS_sys_wait.cpp \
+ OS_NS_time.cpp \
+ OS_NS_unistd.cpp \
+ OS_NS_wchar.cpp \
+ OS_QoS.cpp \
+ OS_TLI.cpp \
+ OS_Thread_Adapter.cpp \
+ OS_main.cpp \
+ Obchunk.cpp \
+ Object_Manager.cpp \
+ Object_Manager_Base.cpp \
+ PI_Malloc.cpp \
+ POSIX_Asynch_IO.cpp \
+ POSIX_CB_Proactor.cpp \
+ POSIX_Proactor.cpp \
+ Pagefile_Memory_Pool.cpp \
+ Parse_Node.cpp \
+ Ping_Socket.cpp \
+ Pipe.cpp \
+ Priority_Reactor.cpp \
+ Proactor.cpp \
+ Proactor_Impl.cpp \
+ Process.cpp \
+ Process_Manager.cpp \
+ Process_Mutex.cpp \
+ Process_Semaphore.cpp \
+ Profile_Timer.cpp \
+ RW_Mutex.cpp \
+ RW_Process_Mutex.cpp \
+ RW_Thread_Mutex.cpp \
+ Reactor.cpp \
+ Reactor_Impl.cpp \
+ Reactor_Notification_Strategy.cpp \
+ Reactor_Timer_Interface.cpp \
+ Read_Buffer.cpp \
+ Recursive_Thread_Mutex.cpp \
+ Recyclable.cpp \
+ Refcountable.cpp \
+ Registry.cpp \
+ Registry_Name_Space.cpp \
+ Remote_Name_Space.cpp \
+ Remote_Tokens.cpp \
+ Rtems_init.c \
+ SOCK.cpp \
+ SOCK_Acceptor.cpp \
+ SOCK_CODgram.cpp \
+ SOCK_Connector.cpp \
+ SOCK_Dgram.cpp \
+ SOCK_Dgram_Bcast.cpp \
+ SOCK_Dgram_Mcast.cpp \
+ SOCK_IO.cpp \
+ SOCK_Netlink.cpp \
+ SOCK_SEQPACK_Acceptor.cpp \
+ SOCK_SEQPACK_Association.cpp \
+ SOCK_SEQPACK_Connector.cpp \
+ SOCK_Stream.cpp \
+ SPIPE.cpp \
+ SPIPE_Acceptor.cpp \
+ SPIPE_Addr.cpp \
+ SPIPE_Connector.cpp \
+ SPIPE_Stream.cpp \
+ SString.cpp \
+ SUN_Proactor.cpp \
+ SV_Message.cpp \
+ SV_Message_Queue.cpp \
+ SV_Semaphore_Complex.cpp \
+ SV_Semaphore_Simple.cpp \
+ SV_Shared_Memory.cpp \
+ Sample_History.cpp \
+ Sbrk_Memory_Pool.cpp \
+ Sched_Params.cpp \
+ Select_Reactor_Base.cpp \
+ Semaphore.cpp \
+ Service_Config.cpp \
+ Service_Gestalt.cpp \
+ Service_Manager.cpp \
+ Service_Object.cpp \
+ Service_Repository.cpp \
+ Service_Types.cpp \
+ Shared_Memory.cpp \
+ Shared_Memory_MM.cpp \
+ Shared_Memory_Pool.cpp \
+ Shared_Memory_SV.cpp \
+ Shared_Object.cpp \
+ Sig_Adapter.cpp \
+ Sig_Handler.cpp \
+ Signal.cpp \
+ Sock_Connect.cpp \
+ Stats.cpp \
+ String_Base_Const.cpp \
+ Svc_Conf_Lexer.cpp \
+ Svc_Conf_y.cpp \
+ Synch_Options.cpp \
+ System_Time.cpp \
+ TLI.cpp \
+ TLI_Acceptor.cpp \
+ TLI_Connector.cpp \
+ TLI_Stream.cpp \
+ TP_Reactor.cpp \
+ TSS_Adapter.cpp \
+ TTY_IO.cpp \
+ Task.cpp \
+ Thread.cpp \
+ Thread_Adapter.cpp \
+ Thread_Control.cpp \
+ Thread_Exit.cpp \
+ Thread_Hook.cpp \
+ Thread_Manager.cpp \
+ Thread_Mutex.cpp \
+ Thread_Semaphore.cpp \
+ Throughput_Stats.cpp \
+ Time_Value.cpp \
+ Timeprobe.cpp \
+ Token.cpp \
+ Token_Collection.cpp \
+ Token_Invariants.cpp \
+ Token_Manager.cpp \
+ Token_Request_Reply.cpp \
+ Trace.cpp \
+ UNIX_Addr.cpp \
+ UPIPE_Acceptor.cpp \
+ UPIPE_Connector.cpp \
+ UPIPE_Stream.cpp \
+ UTF16_Encoding_Converter.cpp \
+ UTF32_Encoding_Converter.cpp \
+ UTF8_Encoding_Converter.cpp \
+ UUID.cpp \
+ WFMO_Reactor.cpp \
+ WIN32_Asynch_IO.cpp \
+ WIN32_Proactor.cpp \
+ XML_Svc_Conf.cpp \
+ XTI_ATM_Mcast.cpp \
+ gethrtime.cpp
+
+libACE_la_LDFLAGS = \
+ -release @ACE_VERSION_NAME@
+
+nobase_include_HEADERS += \
+ ACE.h \
+ ACE.inl \
+ ACE_export.h \
+ ARGV.cpp \
+ ARGV.h \
+ ARGV.inl \
+ ATM_Acceptor.h \
+ ATM_Acceptor.inl \
+ ATM_Addr.h \
+ ATM_Addr.inl \
+ ATM_Connector.h \
+ ATM_Connector.inl \
+ ATM_Params.h \
+ ATM_Params.inl \
+ ATM_QoS.h \
+ ATM_QoS.inl \
+ ATM_Stream.h \
+ ATM_Stream.inl \
+ Acceptor.cpp \
+ Acceptor.h \
+ Activation_Queue.h \
+ Activation_Queue.inl \
+ Active_Map_Manager.h \
+ Active_Map_Manager.inl \
+ Active_Map_Manager_T.cpp \
+ Active_Map_Manager_T.h \
+ Active_Map_Manager_T.inl \
+ Addr.h \
+ Addr.inl \
+ Arg_Shifter.cpp \
+ Arg_Shifter.h \
+ Argv_Type_Converter.h \
+ Argv_Type_Converter.inl \
+ Array.h \
+ Array_Base.cpp \
+ Array_Base.h \
+ Array_Base.inl \
+ Array_Map.cpp \
+ Array_Map.h \
+ Array_Map.inl \
+ Assert.h \
+ Asynch_Acceptor.cpp \
+ Asynch_Acceptor.h \
+ Asynch_Connector.cpp \
+ Asynch_Connector.h \
+ Asynch_IO.h \
+ Asynch_IO_Impl.h \
+ Asynch_IO_Impl.inl \
+ Asynch_Pseudo_Task.h \
+ Atomic_Op.h \
+ Atomic_Op.inl \
+ Atomic_Op_Sparc.h \
+ Atomic_Op_T.cpp \
+ Atomic_Op_T.h \
+ Atomic_Op_T.inl \
+ Auto_Event.h \
+ Auto_Event.inl \
+ Auto_Functor.cpp \
+ Auto_Functor.h \
+ Auto_Functor.inl \
+ Auto_IncDec_T.cpp \
+ Auto_IncDec_T.h \
+ Auto_IncDec_T.inl \
+ Auto_Ptr.cpp \
+ Auto_Ptr.h \
+ Auto_Ptr.inl \
+ Barrier.h \
+ Barrier.inl \
+ Base_Thread_Adapter.h \
+ Base_Thread_Adapter.inl \
+ Based_Pointer_Repository.h \
+ Based_Pointer_T.cpp \
+ Based_Pointer_T.h \
+ Based_Pointer_T.inl \
+ Basic_Stats.h \
+ Basic_Stats.inl \
+ Basic_Types.h \
+ Basic_Types.inl \
+ Bound_Ptr.h \
+ Bound_Ptr.inl \
+ CDR_Base.h \
+ CDR_Base.inl \
+ CDR_Size.h \
+ CDR_Size.inl \
+ CDR_Stream.h \
+ CDR_Stream.inl \
+ CORBA_macros.h \
+ Cache_Map_Manager_T.cpp \
+ Cache_Map_Manager_T.h \
+ Cache_Map_Manager_T.inl \
+ Cached_Connect_Strategy_T.cpp \
+ Cached_Connect_Strategy_T.h \
+ Caching_Strategies_T.cpp \
+ Caching_Strategies_T.h \
+ Caching_Strategies_T.inl \
+ Caching_Utility_T.cpp \
+ Caching_Utility_T.h \
+ Capabilities.h \
+ Capabilities.inl \
+ Cleanup.h \
+ Cleanup.inl \
+ Cleanup_Strategies_T.cpp \
+ Cleanup_Strategies_T.h \
+ Codecs.h \
+ Codeset_IBM1047.h \
+ Codeset_Registry.h \
+ Codeset_Registry.inl \
+ Condition_Recursive_Thread_Mutex.h \
+ Condition_T.cpp \
+ Condition_T.h \
+ Condition_T.inl \
+ Condition_Thread_Mutex.h \
+ Condition_Thread_Mutex.inl \
+ Configuration.h \
+ Configuration_Import_Export.h \
+ Connection_Recycling_Strategy.h \
+ Connector.cpp \
+ Connector.h \
+ Containers.h \
+ Containers.inl \
+ Containers_T.cpp \
+ Containers_T.h \
+ Containers_T.inl \
+ Copy_Disabled.h \
+ Countdown_Time.h \
+ DEV.h \
+ DEV.inl \
+ DEV_Addr.h \
+ DEV_Addr.inl \
+ DEV_Connector.h \
+ DEV_Connector.inl \
+ DEV_IO.h \
+ DEV_IO.inl \
+ DLL.h \
+ DLL_Manager.h \
+ Date_Time.h \
+ Date_Time.inl \
+ Default_Constants.h \
+ Dev_Poll_Reactor.h \
+ Dev_Poll_Reactor.inl \
+ Dirent.h \
+ Dirent.inl \
+ Dirent_Selector.h \
+ Dirent_Selector.inl \
+ Dump.h \
+ Dump_T.cpp \
+ Dump_T.h \
+ Dynamic.h \
+ Dynamic.inl \
+ Dynamic_Message_Strategy.h \
+ Dynamic_Message_Strategy.inl \
+ Dynamic_Service.cpp \
+ Dynamic_Service.h \
+ Dynamic_Service.inl \
+ Dynamic_Service_Base.h \
+ Dynamic_Service_Dependency.h \
+ Encoding_Converter.h \
+ Encoding_Converter_Factory.h \
+ Env_Value_T.cpp \
+ Env_Value_T.h \
+ Env_Value_T.inl \
+ Event.h \
+ Event.inl \
+ Event_Handler.h \
+ Event_Handler.inl \
+ Event_Handler_T.cpp \
+ Event_Handler_T.h \
+ Event_Handler_T.inl \
+ Exception_Macros.h \
+ FIFO.h \
+ FIFO.inl \
+ FIFO_Recv.h \
+ FIFO_Recv.inl \
+ FIFO_Recv_Msg.h \
+ FIFO_Recv_Msg.inl \
+ FIFO_Send.h \
+ FIFO_Send.inl \
+ FIFO_Send_Msg.h \
+ FIFO_Send_Msg.inl \
+ FILE.h \
+ FILE.inl \
+ FILE_Addr.h \
+ FILE_Addr.inl \
+ FILE_Connector.h \
+ FILE_Connector.inl \
+ FILE_IO.h \
+ FILE_IO.inl \
+ File_Lock.h \
+ File_Lock.inl \
+ Filecache.h \
+ Flag_Manip.h \
+ Flag_Manip.inl \
+ Framework_Component.h \
+ Framework_Component.inl \
+ Framework_Component_T.cpp \
+ Framework_Component_T.h \
+ Free_List.cpp \
+ Free_List.h \
+ Functor.h \
+ Functor.inl \
+ Functor_String.h \
+ Functor_String.inl \
+ Functor_T.cpp \
+ Functor_T.h \
+ Functor_T.inl \
+ Future.cpp \
+ Future.h \
+ Future_Set.cpp \
+ Future_Set.h \
+ Get_Opt.h \
+ Get_Opt.inl \
+ Global_Macros.h \
+ Guard_T.cpp \
+ Guard_T.h \
+ Guard_T.inl \
+ Handle_Gobbler.h \
+ Handle_Gobbler.inl \
+ Handle_Ops.h \
+ Handle_Set.h \
+ Handle_Set.inl \
+ Hash_Cache_Map_Manager_T.cpp \
+ Hash_Cache_Map_Manager_T.h \
+ Hash_Cache_Map_Manager_T.inl \
+ Hash_Map_Manager.h \
+ Hash_Map_Manager_T.cpp \
+ Hash_Map_Manager_T.h \
+ Hash_Map_Manager_T.inl \
+ Hash_Map_With_Allocator_T.cpp \
+ Hash_Map_With_Allocator_T.h \
+ Hash_Map_With_Allocator_T.inl \
+ Hash_Multi_Map_Manager_T.cpp \
+ Hash_Multi_Map_Manager_T.h \
+ Hash_Multi_Map_Manager_T.inl \
+ Hashable.h \
+ Hashable.inl \
+ High_Res_Timer.h \
+ High_Res_Timer.inl \
+ ICMP_Socket.h \
+ INET_Addr.h \
+ INET_Addr.inl \
+ IOStream.h \
+ IOStream_T.cpp \
+ IOStream_T.h \
+ IOStream_T.inl \
+ IO_Cntl_Msg.h \
+ IO_Cntl_Msg.inl \
+ IO_SAP.h \
+ IO_SAP.inl \
+ IPC_SAP.h \
+ IPC_SAP.inl \
+ If_Then_Else.h \
+ Init_ACE.h \
+ Intrusive_List.cpp \
+ Intrusive_List.h \
+ Intrusive_List.inl \
+ Intrusive_List_Node.cpp \
+ Intrusive_List_Node.h \
+ Intrusive_List_Node.inl \
+ LOCK_SOCK_Acceptor.cpp \
+ LOCK_SOCK_Acceptor.h \
+ LSOCK.h \
+ LSOCK.inl \
+ LSOCK_Acceptor.h \
+ LSOCK_CODgram.h \
+ LSOCK_CODgram.inl \
+ LSOCK_Connector.h \
+ LSOCK_Connector.inl \
+ LSOCK_Dgram.h \
+ LSOCK_Dgram.inl \
+ LSOCK_Stream.h \
+ LSOCK_Stream.inl \
+ Lib_Find.h \
+ Local_Memory_Pool.h \
+ Local_Name_Space.h \
+ Local_Name_Space_T.cpp \
+ Local_Name_Space_T.h \
+ Local_Tokens.h \
+ Local_Tokens.inl \
+ Lock.h \
+ Lock.inl \
+ Lock_Adapter_T.cpp \
+ Lock_Adapter_T.h \
+ Lock_Adapter_T.inl \
+ Log_Msg.h \
+ Log_Msg.inl \
+ Log_Msg_Backend.h \
+ Log_Msg_Callback.h \
+ Log_Msg_IPC.h \
+ Log_Msg_NT_Event_Log.h \
+ Log_Msg_UNIX_Syslog.h \
+ Log_Priority.h \
+ Log_Record.h \
+ Log_Record.inl \
+ Logging_Strategy.h \
+ MEM_Acceptor.h \
+ MEM_Acceptor.inl \
+ MEM_Addr.h \
+ MEM_Addr.inl \
+ MEM_Connector.h \
+ MEM_Connector.inl \
+ MEM_IO.h \
+ MEM_IO.inl \
+ MEM_SAP.h \
+ MEM_SAP.inl \
+ MEM_Stream.h \
+ MEM_Stream.inl \
+ MMAP_Memory_Pool.h \
+ MMAP_Memory_Pool.inl \
+ Malloc.h \
+ Malloc.inl \
+ Malloc_Allocator.h \
+ Malloc_Allocator.inl \
+ Malloc_Base.h \
+ Malloc_T.cpp \
+ Malloc_T.h \
+ Malloc_T.inl \
+ Managed_Object.cpp \
+ Managed_Object.h \
+ Managed_Object.inl \
+ Manual_Event.h \
+ Manual_Event.inl \
+ Map_Manager.cpp \
+ Map_Manager.h \
+ Map_Manager.inl \
+ Map_T.cpp \
+ Map_T.h \
+ Map_T.inl \
+ Mem_Map.h \
+ Mem_Map.inl \
+ Memory_Pool.h \
+ Message_Block.h \
+ Message_Block.inl \
+ Message_Block_T.cpp \
+ Message_Block_T.h \
+ Message_Block_T.inl \
+ Message_Queue.h \
+ Message_Queue.inl \
+ Message_Queue_Vx.h \
+ Message_Queue_Vx.inl \
+ Message_Queue_T.cpp \
+ Message_Queue_T.h \
+ Method_Object.h \
+ Method_Request.h \
+ Min_Max.h \
+ Module.cpp \
+ Module.h \
+ Module.inl \
+ Msg_WFMO_Reactor.h \
+ Msg_WFMO_Reactor.inl \
+ Multihomed_INET_Addr.h \
+ Multihomed_INET_Addr.inl \
+ Mutex.h \
+ Mutex.inl \
+ NT_Service.h \
+ NT_Service.inl \
+ Name_Proxy.h \
+ Name_Request_Reply.h \
+ Name_Space.h \
+ Naming_Context.h \
+ Netlink_Addr.h \
+ Netlink_Addr.inl \
+ Node.cpp \
+ Node.h \
+ Notification_Strategy.h \
+ Notification_Strategy.inl \
+ Notification_Queue.h \
+ Notification_Queue.inl \
+ Null_Barrier.h \
+ Null_Condition.h \
+ Null_Mutex.h \
+ Null_Semaphore.h \
+ Numeric_Limits.h \
+ OS.h \
+ OS.inl \
+ OS_Dirent.h \
+ OS_Errno.h \
+ OS_Errno.inl \
+ OS_Log_Msg_Attributes.h \
+ OS_Log_Msg_Attributes.inl \
+ OS_Memory.h \
+ OS_NS_Thread.h \
+ OS_NS_Thread.inl \
+ OS_NS_arpa_inet.h \
+ OS_NS_arpa_inet.inl \
+ OS_NS_ctype.h \
+ OS_NS_ctype.inl \
+ OS_NS_dirent.h \
+ OS_NS_dirent.inl \
+ OS_NS_dlfcn.h \
+ OS_NS_dlfcn.inl \
+ OS_NS_errno.h \
+ OS_NS_errno.inl \
+ OS_NS_fcntl.h \
+ OS_NS_fcntl.inl \
+ OS_NS_macros.h \
+ OS_NS_math.h \
+ OS_NS_math.inl \
+ OS_NS_netdb.h \
+ OS_NS_netdb.inl \
+ OS_NS_poll.h \
+ OS_NS_poll.inl \
+ OS_NS_pwd.h \
+ OS_NS_pwd.inl \
+ OS_NS_regex.h \
+ OS_NS_regex.inl \
+ OS_NS_signal.h \
+ OS_NS_signal.inl \
+ OS_NS_stdio.h \
+ OS_NS_stdio.inl \
+ OS_NS_stdlib.h \
+ OS_NS_stdlib.inl \
+ OS_NS_string.h \
+ OS_NS_string.inl \
+ OS_NS_strings.h \
+ OS_NS_strings.inl \
+ OS_NS_stropts.h \
+ OS_NS_stropts.inl \
+ OS_NS_sys_mman.h \
+ OS_NS_sys_mman.inl \
+ OS_NS_sys_msg.h \
+ OS_NS_sys_msg.inl \
+ OS_NS_sys_resource.h \
+ OS_NS_sys_resource.inl \
+ OS_NS_sys_select.h \
+ OS_NS_sys_select.inl \
+ OS_NS_sys_sendfile.h \
+ OS_NS_sys_sendfile.inl \
+ OS_NS_sys_shm.h \
+ OS_NS_sys_shm.inl \
+ OS_NS_sys_socket.h \
+ OS_NS_sys_socket.inl \
+ OS_NS_sys_stat.h \
+ OS_NS_sys_stat.inl \
+ OS_NS_sys_time.h \
+ OS_NS_sys_time.inl \
+ OS_NS_sys_uio.h \
+ OS_NS_sys_uio.inl \
+ OS_NS_sys_utsname.h \
+ OS_NS_sys_wait.h \
+ OS_NS_sys_wait.inl \
+ OS_NS_time.h \
+ OS_NS_time.inl \
+ OS_NS_unistd.h \
+ OS_NS_unistd.inl \
+ OS_NS_wchar.h \
+ OS_NS_wchar.inl \
+ OS_QoS.h \
+ OS_String.h \
+ OS_TLI.h \
+ OS_TLI.inl \
+ OS_Thread_Adapter.h \
+ OS_main.h \
+ Obchunk.h \
+ Obchunk.inl \
+ Object_Manager.h \
+ Object_Manager.inl \
+ Object_Manager_Base.h \
+ Obstack_T.cpp \
+ Obstack_T.h \
+ Obstack_T.inl \
+ PI_Malloc.h \
+ PI_Malloc.inl \
+ POSIX_Asynch_IO.h \
+ POSIX_CB_Proactor.h \
+ POSIX_Proactor.h \
+ POSIX_Proactor.inl \
+ Pagefile_Memory_Pool.h \
+ Pagefile_Memory_Pool.inl \
+ Pair.h \
+ Pair_T.cpp \
+ Pair_T.h \
+ Pair_T.inl \
+ Parse_Node.h \
+ Ping_Socket.h \
+ Ping_Socket.inl \
+ Pipe.h \
+ Pipe.inl \
+ Priority_Reactor.h \
+ Proactor.h \
+ Proactor.inl \
+ Proactor_Impl.h \
+ Process.h \
+ Process.inl \
+ Process_Manager.h \
+ Process_Manager.inl \
+ Process_Mutex.h \
+ Process_Mutex.inl \
+ Process_Semaphore.h \
+ Process_Semaphore.inl \
+ Profile_Timer.h \
+ Profile_Timer.inl \
+ RB_Tree.cpp \
+ RB_Tree.h \
+ RB_Tree.inl \
+ RW_Mutex.h \
+ RW_Mutex.inl \
+ RW_Process_Mutex.h \
+ RW_Process_Mutex.inl \
+ RW_Thread_Mutex.h \
+ RW_Thread_Mutex.inl \
+ Reactor.h \
+ Reactor.inl \
+ Reactor_Impl.h \
+ Reactor_Notification_Strategy.h \
+ Reactor_Notification_Strategy.inl \
+ Reactor_Timer_Interface.h \
+ Reactor_Token_T.cpp \
+ Reactor_Token_T.h \
+ Read_Buffer.h \
+ Read_Buffer.inl \
+ Recursive_Thread_Mutex.h \
+ Recursive_Thread_Mutex.inl \
+ Recyclable.h \
+ Recyclable.inl \
+ Refcountable.h \
+ Refcountable.inl \
+ Refcounted_Auto_Ptr.cpp \
+ Refcounted_Auto_Ptr.h \
+ Refcounted_Auto_Ptr.inl \
+ Registry.h \
+ Registry_Name_Space.h \
+ Remote_Name_Space.h \
+ Remote_Tokens.h \
+ Remote_Tokens.inl \
+ Reverse_Lock_T.cpp \
+ Reverse_Lock_T.h \
+ Reverse_Lock_T.inl \
+ SOCK.h \
+ SOCK.inl \
+ SOCK_Acceptor.h \
+ SOCK_Acceptor.inl \
+ SOCK_CODgram.h \
+ SOCK_CODgram.inl \
+ SOCK_Connector.h \
+ SOCK_Connector.inl \
+ SOCK_Dgram.h \
+ SOCK_Dgram.inl \
+ SOCK_Dgram_Bcast.h \
+ SOCK_Dgram_Bcast.inl \
+ SOCK_Dgram_Mcast.h \
+ SOCK_Dgram_Mcast.inl \
+ SOCK_IO.h \
+ SOCK_IO.inl \
+ SOCK_Netlink.h \
+ SOCK_Netlink.inl \
+ SOCK_SEQPACK_Acceptor.h \
+ SOCK_SEQPACK_Acceptor.inl \
+ SOCK_SEQPACK_Association.h \
+ SOCK_SEQPACK_Association.inl \
+ SOCK_SEQPACK_Connector.h \
+ SOCK_SEQPACK_Connector.inl \
+ SOCK_Stream.h \
+ SOCK_Stream.inl \
+ SPIPE.h \
+ SPIPE.inl \
+ SPIPE_Acceptor.h \
+ SPIPE_Addr.h \
+ SPIPE_Addr.inl \
+ SPIPE_Connector.h \
+ SPIPE_Connector.inl \
+ SPIPE_Stream.h \
+ SPIPE_Stream.inl \
+ SString.h \
+ SString.inl \
+ SStringfwd.h \
+ SUN_Proactor.h \
+ SV_Message.h \
+ SV_Message.inl \
+ SV_Message_Queue.h \
+ SV_Message_Queue.inl \
+ SV_Semaphore_Complex.h \
+ SV_Semaphore_Complex.inl \
+ SV_Semaphore_Simple.h \
+ SV_Semaphore_Simple.inl \
+ SV_Shared_Memory.h \
+ SV_Shared_Memory.inl \
+ Sample_History.h \
+ Sample_History.inl \
+ Sbrk_Memory_Pool.h \
+ Sched_Params.h \
+ Sched_Params.inl \
+ Select_Reactor.h \
+ Select_Reactor_Base.h \
+ Select_Reactor_Base.inl \
+ Select_Reactor_T.cpp \
+ Select_Reactor_T.h \
+ Select_Reactor_T.inl \
+ Semaphore.h \
+ Semaphore.inl \
+ Service_Config.h \
+ Service_Config.inl \
+ Service_Gestalt.h \
+ Service_Gestalt.inl \
+ Service_Manager.h \
+ Service_Object.h \
+ Service_Object.inl \
+ Service_Repository.h \
+ Service_Repository.inl \
+ Service_Types.h \
+ Service_Types.inl \
+ Shared_Memory.h \
+ Shared_Memory_MM.h \
+ Shared_Memory_MM.inl \
+ Shared_Memory_Pool.h \
+ Shared_Memory_SV.h \
+ Shared_Memory_SV.inl \
+ Shared_Object.h \
+ Shared_Object.inl \
+ Sig_Adapter.h \
+ Sig_Handler.h \
+ Sig_Handler.inl \
+ Signal.h \
+ Signal.inl \
+ Singleton.cpp \
+ Singleton.h \
+ Singleton.inl \
+ Sock_Connect.h \
+ Static_Object_Lock.h \
+ Stats.h \
+ Stats.inl \
+ Strategies.h \
+ Strategies_T.cpp \
+ Strategies_T.h \
+ Strategies_T.inl \
+ Stream.cpp \
+ Stream.h \
+ Stream.inl \
+ Stream_Modules.cpp \
+ Stream_Modules.h \
+ String_Base.cpp \
+ String_Base.h \
+ String_Base.inl \
+ String_Base_Const.h \
+ Svc_Conf.h \
+ Svc_Conf_Lexer.h \
+ Svc_Conf_Tokens.h \
+ Svc_Handler.cpp \
+ Svc_Handler.h \
+ Synch.h \
+ Synch_Options.h \
+ Synch_T.cpp \
+ Synch_T.h \
+ Synch_Traits.h \
+ System_Time.h \
+ TLI.h \
+ TLI.inl \
+ TLI_Acceptor.h \
+ TLI_Connector.h \
+ TLI_Connector.inl \
+ TLI_Stream.h \
+ TLI_Stream.inl \
+ TP_Reactor.h \
+ TP_Reactor.inl \
+ TSS_Adapter.h \
+ TSS_T.cpp \
+ TSS_T.h \
+ TSS_T.inl \
+ TTY_IO.h \
+ Task.h \
+ Task.inl \
+ Task_Ex_T.cpp \
+ Task_Ex_T.h \
+ Task_Ex_T.inl \
+ Task_T.cpp \
+ Task_T.h \
+ Task_T.inl \
+ Test_and_Set.cpp \
+ Test_and_Set.h \
+ Thread.h \
+ Thread.inl \
+ Thread_Adapter.h \
+ Thread_Adapter.inl \
+ Thread_Control.h \
+ Thread_Control.inl \
+ Thread_Exit.h \
+ Thread_Hook.h \
+ Thread_Manager.h \
+ Thread_Manager.inl \
+ Thread_Mutex.h \
+ Thread_Mutex.inl \
+ Thread_Semaphore.h \
+ Thread_Semaphore.inl \
+ Throughput_Stats.h \
+ Time_Value.h \
+ Time_Value.inl \
+ Timeprobe.h \
+ Timeprobe.inl \
+ Timeprobe_T.cpp \
+ Timeprobe_T.h \
+ Timer_Hash.h \
+ Timer_Hash_T.cpp \
+ Timer_Hash_T.h \
+ Timer_Heap.h \
+ Timer_Heap_T.cpp \
+ Timer_Heap_T.h \
+ Timer_List.h \
+ Timer_List_T.cpp \
+ Timer_List_T.h \
+ Timer_Queue.h \
+ Timer_Queue_Adapters.cpp \
+ Timer_Queue_Adapters.h \
+ Timer_Queue_Adapters.inl \
+ Timer_Queue_T.cpp \
+ Timer_Queue_T.h \
+ Timer_Queue_T.inl \
+ Timer_Queuefwd.h \
+ Timer_Wheel.h \
+ Timer_Wheel_T.cpp \
+ Timer_Wheel_T.h \
+ Token.h \
+ Token.inl \
+ Token_Collection.h \
+ Token_Collection.inl \
+ Token_Invariants.h \
+ Token_Manager.h \
+ Token_Manager.inl \
+ Token_Request_Reply.h \
+ Token_Request_Reply.inl \
+ Trace.h \
+ Truncate.h \
+ Typed_SV_Message.cpp \
+ Typed_SV_Message.h \
+ Typed_SV_Message.inl \
+ Typed_SV_Message_Queue.cpp \
+ Typed_SV_Message_Queue.h \
+ Typed_SV_Message_Queue.inl \
+ UNIX_Addr.h \
+ UNIX_Addr.inl \
+ UPIPE_Acceptor.h \
+ UPIPE_Acceptor.inl \
+ UPIPE_Addr.h \
+ UPIPE_Connector.h \
+ UPIPE_Connector.inl \
+ UPIPE_Stream.h \
+ UPIPE_Stream.inl \
+ UTF16_Encoding_Converter.h \
+ UTF16_Encoding_Converter.inl \
+ UTF32_Encoding_Converter.h \
+ UTF8_Encoding_Converter.h \
+ UUID.h \
+ UUID.inl \
+ Unbounded_Queue.cpp \
+ Unbounded_Queue.h \
+ Unbounded_Queue.inl \
+ Unbounded_Set.cpp \
+ Unbounded_Set.h \
+ Unbounded_Set.inl \
+ Value_Ptr.h \
+ Vector_T.cpp \
+ Vector_T.h \
+ Vector_T.inl \
+ Version.h \
+ Versioned_Namespace.h \
+ WFMO_Reactor.h \
+ WFMO_Reactor.inl \
+ WIN32_Asynch_IO.h \
+ WIN32_Proactor.h \
+ XML_Svc_Conf.h \
+ XTI_ATM_Mcast.h \
+ XTI_ATM_Mcast.inl \
+ ace_wchar.h \
+ ace_wchar.inl \
+ checked_iterator.h \
+ config-WinCE.h \
+ config-all.h \
+ config-borland-common.h \
+ config-lite.h \
+ config-macros.h \
+ config-minimal.h \
+ config-win32-borland.h \
+ config-win32-common.h \
+ config-win32-ghs.h \
+ config-win32-msvc-7.h \
+ config-win32-msvc-8.h \
+ config-win32-msvc.h \
+ config-win32.h \
+ config.h \
+ iosfwd.h \
+ os_include/arpa/os_inet.h \
+ os_include/net/os_if.h \
+ os_include/netinet/os_in.h \
+ os_include/netinet/os_tcp.h \
+ os_include/os_aio.h \
+ os_include/os_assert.h \
+ os_include/os_complex.h \
+ os_include/os_cpio.h \
+ os_include/os_ctype.h \
+ os_include/os_dirent.h \
+ os_include/os_dlfcn.h \
+ os_include/os_errno.h \
+ os_include/os_fcntl.h \
+ os_include/os_fenv.h \
+ os_include/os_float.h \
+ os_include/os_fmtmsg.h \
+ os_include/os_fnmatch.h \
+ os_include/os_ftw.h \
+ os_include/os_glob.h \
+ os_include/os_grp.h \
+ os_include/os_iconv.h \
+ os_include/os_inttypes.h \
+ os_include/os_iso646.h \
+ os_include/os_langinfo.h \
+ os_include/os_libgen.h \
+ os_include/os_limits.h \
+ os_include/os_local.h \
+ os_include/os_math.h \
+ os_include/os_monetary.h \
+ os_include/os_mqueue.h \
+ os_include/os_ndbm.h \
+ os_include/os_netdb.h \
+ os_include/os_nl_types.h \
+ os_include/os_poll.h \
+ os_include/os_pthread.h \
+ os_include/os_pwd.h \
+ os_include/os_regex.h \
+ os_include/os_sched.h \
+ os_include/os_search.h \
+ os_include/os_semaphore.h \
+ os_include/os_setjmp.h \
+ os_include/os_signal.h \
+ os_include/os_spawn.h \
+ os_include/os_stdarg.h \
+ os_include/os_stdbool.h \
+ os_include/os_stddef.h \
+ os_include/os_stdint.h \
+ os_include/os_stdio.h \
+ os_include/os_stdlib.h \
+ os_include/os_string.h \
+ os_include/os_strings.h \
+ os_include/os_stropts.h \
+ os_include/os_syslog.h \
+ os_include/os_tar.h \
+ os_include/os_termios.h \
+ os_include/os_tgmath.h \
+ os_include/os_time.h \
+ os_include/os_trace.h \
+ os_include/os_ucontext.h \
+ os_include/os_ulimit.h \
+ os_include/os_unistd.h \
+ os_include/os_utime.h \
+ os_include/os_utmpx.h \
+ os_include/os_wchar.h \
+ os_include/os_wctype.h \
+ os_include/os_wordexp.h \
+ os_include/sys/os_ipc.h \
+ os_include/sys/os_loadavg.h \
+ os_include/sys/os_mman.h \
+ os_include/sys/os_msg.h \
+ os_include/sys/os_pstat.h \
+ os_include/sys/os_resource.h \
+ os_include/sys/os_select.h \
+ os_include/sys/os_sem.h \
+ os_include/sys/os_shm.h \
+ os_include/sys/os_socket.h \
+ os_include/sys/os_stat.h \
+ os_include/sys/os_statvfs.h \
+ os_include/sys/os_sysctl.h \
+ os_include/sys/os_time.h \
+ os_include/sys/os_timeb.h \
+ os_include/sys/os_times.h \
+ os_include/sys/os_types.h \
+ os_include/sys/os_uio.h \
+ os_include/sys/os_un.h \
+ os_include/sys/os_utsname.h \
+ os_include/sys/os_wait.h \
+ post.h \
+ pre.h \
+ streams.h \
+ svc_export.h
+
+pkgconfig_DATA += \
+ ACE.pc
+
+CLEANFILES += \
+ ACE.pc
+
+ACE.pc: ${top_builddir}/config.status ${srcdir}/ACE.pc.in
+ ${top_builddir}/config.status --file $@:${srcdir}/ACE.pc.in
+
+endif !BUILD_ACE_FOR_TAO
+
+EXTRA_DIST = \
+ ACE.pc.in \
+ ace.rc
+
+
+## Makefile.ACE_FlReactor.am
+
+if BUILD_FL
+if BUILD_GL
+if BUILD_X11
+
+lib_LTLIBRARIES += libACE_FlReactor.la
+
+libACE_FlReactor_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ $(ACE_FLTK_CPPFLAGS) \
+ -DACE_FLREACTOR_BUILD_DLL
+
+libACE_FlReactor_la_SOURCES = \
+ FlReactor/FlReactor.cpp
+
+libACE_FlReactor_la_LDFLAGS = \
+ -release @ACE_VERSION_NAME@ $(ACE_FLTK_LDFLAGS)
+
+libACE_FlReactor_la_LIBADD = \
+ libACE.la \
+ $(ACE_FLTK_LIBS)
+
+nobase_include_HEADERS += \
+ FlReactor/ACE_FlReactor_export.h \
+ FlReactor/FlReactor.h
+
+pkgconfig_DATA += \
+ ACE_FlReactor.pc
+
+CLEANFILES += \
+ ACE_FlReactor.pc
+
+ACE_FlReactor.pc: ${top_builddir}/config.status ${srcdir}/FlReactor/ACE_FlReactor.pc.in
+ ${top_builddir}/config.status --file $@:${srcdir}/FlReactor/ACE_FlReactor.pc.in
+
+endif BUILD_X11
+endif BUILD_GL
+endif BUILD_FL
+
+EXTRA_DIST += \
+ FlReactor/ACE_FlReactor.pc.in
+
+
+## Makefile.ACE_QtReactor.am
+
+if BUILD_QT
+
+BUILT_SOURCES = \
+ QtReactor/QtReactor_moc.cpp
+
+CLEANFILES += \
+ QtReactor/QtReactor_moc.cpp
+
+QtReactor/QtReactor_moc.cpp: $(srcdir)/QtReactor/QtReactor.h
+ $(QTDIR)/bin/moc $(srcdir)/QtReactor/QtReactor.h -o QtReactor/QtReactor_moc.cpp
+
+lib_LTLIBRARIES += libACE_QtReactor.la
+
+libACE_QtReactor_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ $(ACE_QT_CPPFLAGS) \
+ -DACE_QTREACTOR_BUILD_DLL
+
+libACE_QtReactor_la_SOURCES = \
+ QtReactor/QtReactor.cpp \
+ QtReactor/QtReactor_moc.cpp
+
+libACE_QtReactor_la_LDFLAGS = \
+ -release @ACE_VERSION_NAME@ $(ACE_QT_LDFLAGS)
+
+libACE_QtReactor_la_LIBADD = \
+ libACE.la \
+ $(ACE_QT_LIBS)
+
+nobase_include_HEADERS += \
+ QtReactor/ACE_QtReactor_export.h \
+ QtReactor/QtReactor.h
+
+pkgconfig_DATA += \
+ ACE_QtReactor.pc
+
+CLEANFILES += \
+ ACE_QtReactor.pc
+
+ACE_QtReactor.pc: ${top_builddir}/config.status ${srcdir}/QtReactor/ACE_QtReactor.pc.in
+ ${top_builddir}/config.status --file $@:${srcdir}/QtReactor/ACE_QtReactor.pc.in
+
+endif BUILD_QT
+
+EXTRA_DIST += \
+ QtReactor/ACE_QtReactor.pc.in
+
+
+## Makefile.ACE_TkReactor.am
+
+if BUILD_TK
+
+lib_LTLIBRARIES += libACE_TkReactor.la
+
+libACE_TkReactor_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ $(ACE_TK_CPPFLAGS) \
+ $(ACE_TCL_CPPFLAGS) \
+ -DACE_TKREACTOR_BUILD_DLL
+
+libACE_TkReactor_la_SOURCES = \
+ TkReactor/TkReactor.cpp
+
+libACE_TkReactor_la_LDFLAGS = \
+ -release @ACE_VERSION_NAME@ $(ACE_TK_LDFLAGS) $(ACE_TCL_LDFLAGS)
+
+libACE_TkReactor_la_LIBADD = \
+ libACE.la \
+ $(ACE_TK_LIBS) \
+ $(ACE_TCL_LIBS)
+
+nobase_include_HEADERS += \
+ TkReactor/ACE_TkReactor_export.h \
+ TkReactor/TkReactor.h
+
+pkgconfig_DATA += \
+ ACE_TkReactor.pc
+
+CLEANFILES += \
+ ACE_TkReactor.pc
+
+ACE_TkReactor.pc: ${top_builddir}/config.status ${srcdir}/TkReactor/ACE_TkReactor.pc.in
+ ${top_builddir}/config.status --file $@:${srcdir}/TkReactor/ACE_TkReactor.pc.in
+
+endif BUILD_TK
+
+EXTRA_DIST += \
+ TkReactor/ACE_TkReactor.pc.in
+
+
+## Makefile.ACE_XtReactor.am
+
+if BUILD_X11
+if BUILD_XT
+
+lib_LTLIBRARIES += libACE_XtReactor.la
+
+libACE_XtReactor_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ $(ACE_X11_CPPFLAGS) \
+ $(ACE_XT_CPPFLAGS) \
+ -DACE_XTREACTOR_BUILD_DLL
+
+libACE_XtReactor_la_SOURCES = \
+ XtReactor/XtReactor.cpp
+
+libACE_XtReactor_la_LDFLAGS = \
+ -release @ACE_VERSION_NAME@ $(ACE_X11_LDFLAGS) $(ACE_XT_LDFLAGS)
+
+libACE_XtReactor_la_LIBADD = \
+ libACE.la \
+ $(ACE_XT_LIBS) \
+ $(ACE_X11_LIBS)
+
+nobase_include_HEADERS += \
+ XtReactor/ACE_XtReactor_export.h \
+ XtReactor/XtReactor.h
+
+pkgconfig_DATA += \
+ ACE_XtReactor.pc
+
+CLEANFILES += \
+ ACE_XtReactor.pc
+
+ACE_XtReactor.pc: ${top_builddir}/config.status ${srcdir}/XtReactor/ACE_XtReactor.pc.in
+ ${top_builddir}/config.status --file $@:${srcdir}/XtReactor/ACE_XtReactor.pc.in
+
+endif BUILD_XT
+endif BUILD_X11
+
+EXTRA_DIST += \
+ XtReactor/ACE_XtReactor.pc.in
+
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/ace/Malloc.cpp b/ACE/ace/Malloc.cpp
new file mode 100644
index 00000000000..9c6da58fb0a
--- /dev/null
+++ b/ACE/ace/Malloc.cpp
@@ -0,0 +1,187 @@
+// $Id$
+
+#include "ace/Malloc.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Malloc.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Object_Manager.h"
+#include "ace/Malloc_Base.h"
+#include "ace/OS_NS_string.h"
+
+
+ACE_RCSID (ace,
+ Malloc,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Control_Block::ACE_Malloc_Header::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnext_block = %@"), (ACE_Malloc_Header *) this->next_block_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nsize = %d\n"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Control_Block::print_alignment_info (void)
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Control_Block::print_alignment_info");
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Start ---> ACE_Control_Block::print_alignment_info:\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Sizeof ptr: %d\n")
+ ACE_TEXT ("Sizeof size_t: %d\n")
+ ACE_TEXT ("Sizeof long: %d\n")
+ ACE_TEXT ("Sizeof double: %d\n")
+ ACE_TEXT ("Sizeof ACE_MALLOC_ALIGN: %d\n")
+ ACE_TEXT ("Sizeof ACE_MALLOC_PADDING: %d\n")
+ ACE_TEXT ("Sizeof ACE_MALLOC_HEADER_SIZE: %d\n")
+ ACE_TEXT ("Sizeof ACE_MALLOC_PADDING_SIZE: %d\n")
+ ACE_TEXT ("Sizeof ACE_CONTROL_BLOCK_SIZE: %d\n")
+ ACE_TEXT ("Sizeof ACE_CONTROL_BLOCK_ALIGN_BYTES: %d\n")
+ ACE_TEXT ("Sizeof (MALLOC_HEADER): %d\n")
+ ACE_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_BYTES,
+ sizeof (ACE_Malloc_Header),
+ sizeof (ACE_Control_Block)
+ ));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("End <--- ACE_Control_Block::print_alignment_info:\n")));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Control_Block::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Control_Block::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Name Node:\n")));
+ for (ACE_Name_Node *nextn = this->name_head_;
+ nextn != 0;
+ nextn = nextn->next_)
+ nextn->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("freep_ = %@"), (ACE_Malloc_Header *) this->freep_));
+ this->base_.dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_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_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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;
+}
+
+const char *
+ACE_Control_Block::ACE_Name_Node::name (void) const
+{
+ return this->name_;
+}
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Control_Block::ACE_Name_Node::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("pointer = %@"), (const char *) this->pointer_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnext_ = %@"), (ACE_Name_Node *) this->next_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\nname_ = (%@, %s)"),
+ (const char *) this->name_,
+ (const char *) this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ACE_Malloc_Stats::ACE_Malloc_Stats (void)
+ : nchunks_ (0),
+ nblocks_ (0),
+ ninuse_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_Stats::ACE_Malloc_Stats");
+}
+
+void
+ACE_Malloc_Stats::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Malloc_Stats::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ int const nblocks = this->nblocks_.value ();
+ int const ninuse = this->ninuse_.value ();
+ int const nchunks = this->nchunks_.value ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("nblocks = %d"), nblocks));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("\nninuse = %d"), ninuse));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("\nnchunks = %d"), nchunks));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+#endif /*ACE_HAS_MALLOC_STATS*/
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Malloc.h b/ACE/ace/Malloc.h
new file mode 100644
index 00000000000..5dd76d47dd3
--- /dev/null
+++ b/ACE/ace/Malloc.h
@@ -0,0 +1,396 @@
+// -*- 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_export.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)
+# include "ace/Atomic_Op.h"
+# if defined (ACE_HAS_THREADS)
+# include "ace/Process_Mutex.h"
+# define ACE_PROCESS_MUTEX ACE_Process_Mutex
+# else /* ACE_HAS_THREADS */
+# include "ace/SV_Semaphore_Simple.h"
+# define ACE_PROCESS_MUTEX ACE_SV_Semaphore_Simple
+# endif /* ACE_HAS_THREADS */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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.)|
+ +-----------------------------------------+
+ |char paddings_[ACE_MALLOC_PADDING_SIZE]; |
+ | // Padding array. This purpose |
+ | // of this padding array is to adjust |
+ | // the sizeof (Malloc_Header) to be |
+ | // multiple of ACE_MALLOC_ALIGN. |
+ +-----------------------------------------+
+
+* 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. | |
+ +-----------------------------------------+ |
+ |char align_[CONTROL_BLOCK_ALIGN_BYTES]; | |
+ | // | |
+ +-----------------------------------------+ |
+ |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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# 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.
+
+# define ACE_MALLOC_PADDING 1
+#endif /* ACE_MALLOC_PADDING */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+union ACE_max_align_info
+{
+ int (*i)();
+ void* p;
+ long l;
+ double d;
+};
+
+#if !defined (ACE_MALLOC_ALIGN)
+// Align the malloc header size to a multiple of a double.
+# define ACE_MALLOC_ALIGN (sizeof (ACE_max_align_info))
+#endif /* ACE_MALLOC_ALIGN */
+
+#if !defined ACE_MALLOC_ROUNDUP
+# define ACE_MALLOC_ROUNDUP(X, Y) ((X) + ((Y) - 1) & ~((Y) - 1))
+#endif
+
+// ACE_MALLOC_HEADER_SIZE is the normalized malloc header size.
+#define ACE_MALLOC_HEADER_SIZE ACE_MALLOC_ROUNDUP(ACE_MALLOC_PADDING, 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)
+# define ACE_MALLOC_PADDING_SIZE ACE_MALLOC_ROUNDUP (ACE_MALLOC_HEADER_SIZE + sizeof (ACE_Malloc_Header*) + sizeof (size_t), ACE_MALLOC_ALIGN) - (sizeof (ACE_Malloc_Header*) + sizeof (size_t))
+# endif /* !ACE_MALLOC_PADDING_SIZE */
+ char padding_[(ACE_MALLOC_PADDING_SIZE) ? ACE_MALLOC_PADDING_SIZE : ACE_MALLOC_ALIGN];
+
+ /// 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 @c 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);
+
+ /// 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;
+
+ /// 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;
+ private:
+ /// Copy constructor.
+ ACE_Name_Node (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.
+ 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 */
+
+# if !defined (ACE_CONTROL_BLOCK_ALIGN_BYTES)
+# define ACE_CONTROL_BLOCK_ALIGN_BYTES \
+ ACE_MALLOC_ROUNDUP (ACE_CONTROL_BLOCK_SIZE, ACE_MALLOC_ALIGN) - ACE_CONTROL_BLOCK_SIZE
+# endif /* !ACE_CONTROL_BLOCK_ALIGN_BYTES */
+ char align_[(ACE_CONTROL_BLOCK_ALIGN_BYTES) ? ACE_CONTROL_BLOCK_ALIGN_BYTES : ACE_MALLOC_ALIGN];
+
+ /// 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Malloc.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MALLOC_H */
diff --git a/ACE/ace/Malloc.inl b/ACE/ace/Malloc.inl
new file mode 100644
index 00000000000..fdfbd1a612d
--- /dev/null
+++ b/ACE/ace/Malloc.inl
@@ -0,0 +1,26 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Malloc_Allocator.cpp b/ACE/ace/Malloc_Allocator.cpp
new file mode 100644
index 00000000000..b84d3fac3c8
--- /dev/null
+++ b/ACE/ace/Malloc_Allocator.cpp
@@ -0,0 +1,361 @@
+// $Id$
+
+#include "ace/Malloc_Allocator.h"
+#include "ace/Object_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Malloc_Allocator.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Guard_T.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Log_Msg.h" // for ACE_ASSERT
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace, Malloc_Allocator, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_New_Allocator::malloc (size_t nbytes)
+{
+ char *ptr = 0;
+
+ if (nbytes > 0)
+ ACE_NEW_RETURN (ptr, char[nbytes], 0);
+ return (void *) ptr;
+}
+
+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;
+}
+
+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);
+}
+
+void
+ACE_New_Allocator::free (void *ptr)
+{
+ delete [] (char *) ptr;
+}
+
+int
+ACE_New_Allocator::remove (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::bind (const char *, void *, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::trybind (const char *, void *&)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::find (const char *, void *&)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::find (const char *)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::unbind (const char *)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::unbind (const char *, void *&)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::sync (ssize_t, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::sync (void *, size_t, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::protect (ssize_t, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_New_Allocator::protect (void *, size_t, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+void
+ACE_New_Allocator::print_stats (void) const
+{
+}
+#endif /* ACE_HAS_MALLOC_STATS */
+
+void
+ACE_New_Allocator::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+#endif /* ACE_HAS_DUMP */
+}
+
+/******************************************************************************/
+
+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;
+ }
+}
+
+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;
+}
+
+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);
+}
+
+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_);
+}
+
+int
+ACE_Static_Allocator_Base::remove (void)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::bind (const char *, void *, int)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::trybind (const char *, void *&)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::find (const char *, void *&)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::find (const char *)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::unbind (const char *)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::unbind (const char *, void *&)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::sync (ssize_t, int)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::sync (void *, size_t, int)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::protect (ssize_t, int)
+{
+ return -1;
+}
+
+int
+ACE_Static_Allocator_Base::protect (void *, size_t, int)
+{
+ return -1;
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+void
+ACE_Static_Allocator_Base::print_stats (void) const
+{
+}
+#endif /* ACE_HAS_MALLOC_STATS */
+
+void
+ACE_Static_Allocator_Base::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Static_Allocator_Base::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\noffset_ = %d"), this->offset_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nsize_ = %d\n"), this->size_));
+ ACE_HEX_DUMP ((LM_DEBUG, this->buffer_, this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Malloc_Allocator.h b/ACE/ace/Malloc_Allocator.h
new file mode 100644
index 00000000000..1ac2f9d55ee
--- /dev/null
+++ b/ACE/ace/Malloc_Allocator.h
@@ -0,0 +1,146 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Malloc_Allocator.h
+ *
+ * $Id$
+ *
+ * @author Based on code that formerly existed in another ACE file.
+ */
+//==========================================================================
+
+#ifndef ACE_MALLOC_ALLOCATOR_H
+#define ACE_MALLOC_ALLOCATOR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Malloc_Base.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 */
+
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @c 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Malloc_Allocator.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* MALLOC_ALLOCATOR_H */
diff --git a/ACE/ace/Malloc_Allocator.inl b/ACE/ace/Malloc_Allocator.inl
new file mode 100644
index 00000000000..87a96099c1a
--- /dev/null
+++ b/ACE/ace/Malloc_Allocator.inl
@@ -0,0 +1,16 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Static_Allocator_Base::ACE_Static_Allocator_Base (char * buffer,
+ size_t size)
+ : buffer_ (buffer),
+ size_ (size),
+ offset_ (0)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Malloc_Base.h b/ACE/ace/Malloc_Base.h
new file mode 100644
index 00000000000..e9e15923737
--- /dev/null
+++ b/ACE/ace/Malloc_Base.h
@@ -0,0 +1,168 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+#include "ace/os_include/sys/os_mman.h"
+#include "ace/os_include/sys/os_types.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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:
+
+ /// Unsigned integer type used for specifying memory block lengths.
+ typedef size_t size_type;
+
+ // = 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 @a nbytes, but don't give them any initial value.
+ virtual void *malloc (size_type nbytes) = 0;
+
+ /// Allocate @a nbytes, giving them @a initial_value.
+ virtual void *calloc (size_type nbytes, char initial_value = '\0') = 0;
+
+ /// Allocate <n_elem> each of size @a elem_size, giving them
+ /// @a initial_value.
+ virtual void *calloc (size_type n_elem,
+ size_type 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 @a name with @a pointer. If @a duplicates == 0 then do
+ * not allow duplicate @a name/@a pointer associations, else if
+ * @a duplicates != 0 then allow duplicate @a name/@a pointer
+ * assocations. Returns 0 if successfully binds (1) a previously
+ * unbound @a name or (2) @a duplicates != 0, returns 1 if trying to
+ * bind a previously bound @a name and @a duplicates == 0, else
+ * returns -1 if a resource failure occurs.
+ */
+ virtual int bind (const char *name, void *pointer, int duplicates = 0) = 0;
+
+ /**
+ * Associate @a name with @a pointer. Does not allow duplicate
+ * @a name/@a pointer associations. Returns 0 if successfully binds
+ * (1) a previously unbound @a name, 1 if trying to bind a previously
+ * bound @a name, or returns -1 if a resource failure occurs. When
+ * this call returns @a pointer's value will always reference the
+ * void * that @a name is associated with. Thus, if the caller needs
+ * to use @a pointer (e.g., to free it) a copy must be maintained by
+ * the caller.
+ */
+ virtual int trybind (const char *name, void *&pointer) = 0;
+
+ /// Locate @a 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 @a len bytes of the memory region to the backing store
+ * starting at @c this->base_addr_. If @a len == -1 then sync the
+ * whole region.
+ */
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC) = 0;
+
+ /// Sync @a len bytes of the memory region to the backing store
+ /// starting at @a addr.
+ virtual int sync (void *addr, size_type len, int flags = MS_SYNC) = 0;
+
+ /**
+ * Change the protection of the pages of the mapped region to @a prot
+ * starting at <this->base_addr_> up to @a len bytes. If @a 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 @a prot
+ /// starting at @a addr up to @a len bytes.
+ virtual int protect (void *addr, size_type 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MALLOC_BASE_H */
diff --git a/ACE/ace/Malloc_T.cpp b/ACE/ace/Malloc_T.cpp
new file mode 100644
index 00000000000..7e5b222d6f7
--- /dev/null
+++ b/ACE/ace/Malloc_T.cpp
@@ -0,0 +1,1262 @@
+// $Id$
+
+#ifndef ACE_MALLOC_T_CPP
+#define ACE_MALLOC_T_CPP
+
+#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.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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)
+{
+ // To maintain alignment requirements, make sure that each element
+ // inserted into the free list is aligned properly for the platform.
+ // Since the memory is allocated as a char[], the compiler won't help.
+ // To make sure enough room is allocated, round up the size so that
+ // each element starts aligned.
+ //
+ // NOTE - this would probably be easier by defining pool_ as a pointer
+ // to T and allocating an array of them (the compiler would probably
+ // take care of the alignment for us), but then the ACE_NEW below would
+ // require a default constructor on T - a requirement that is not in
+ // previous versions of ACE
+ size_t chunk_size = sizeof (T);
+ chunk_size = ACE_MALLOC_ROUNDUP (chunk_size, ACE_MALLOC_ALIGN);
+ ACE_NEW (this->pool_,
+ char[n_chunks * chunk_size]);
+
+ for (size_t c = 0;
+ c < n_chunks;
+ c++)
+ {
+ void* placement = this->pool_ + c * chunk_size;
+ 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_;
+}
+
+template <class T, class ACE_LOCK> 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 0;
+
+ // 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> 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 0;
+
+ // 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 ();
+ if (ptr != 0)
+ ACE_OS::memset (ptr, initial_value, sizeof (T));
+ return ptr;
+}
+
+template <class T, class ACE_LOCK> void *
+ACE_Cached_Allocator<T, ACE_LOCK>::calloc (size_t,
+ size_t,
+ char)
+{
+ ACE_NOTSUP_RETURN (0);
+}
+
+template <class T, class ACE_LOCK> void
+ACE_Cached_Allocator<T, ACE_LOCK>::free (void * ptr)
+{
+ if (ptr != 0)
+ this->free_list_.add ((ACE_Cached_Mem_Pool_Node<T> *) ptr) ;
+}
+
+template <class ACE_LOCK>
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::ACE_Dynamic_Cached_Allocator
+ (size_t n_chunks, size_t chunk_size)
+ : pool_ (0),
+ free_list_ (ACE_PURE_FREE_LIST),
+ chunk_size_(chunk_size)
+{
+ chunk_size = ACE_MALLOC_ROUNDUP (chunk_size, ACE_MALLOC_ALIGN);
+ ACE_NEW (this->pool_, char[n_chunks * chunk_size_]);
+
+ for (size_t c = 0;
+ c < n_chunks;
+ c++)
+ {
+ void* placement = this->pool_ + c * chunk_size_;
+
+ this->free_list_.add (new (placement) ACE_Cached_Mem_Pool_Node<char>);
+ }
+ // Put into free list using placement contructor, no real memory
+ // allocation in the above <new>.
+}
+
+template <class ACE_LOCK>
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::~ACE_Dynamic_Cached_Allocator (void)
+{
+ delete [] this->pool_;
+ this->pool_ = 0;
+ chunk_size_ = 0;
+}
+
+template <class ACE_LOCK> void *
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::malloc (size_t nbytes)
+{
+ // Check if size requested fits within pre-determined size.
+ if (nbytes > chunk_size_)
+ return 0;
+
+ // 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 ACE_LOCK> void *
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::calloc (size_t nbytes,
+ char initial_value)
+{
+ // Check if size requested fits within pre-determined size.
+ if (nbytes > chunk_size_)
+ return 0;
+
+ // 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 ();
+ if (ptr != 0)
+ ACE_OS::memset (ptr, initial_value, chunk_size_);
+ return ptr;
+}
+
+template <class ACE_LOCK> void *
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::calloc (size_t, size_t, char)
+{
+ ACE_NOTSUP_RETURN (0);
+}
+
+template <class ACE_LOCK> void
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::free (void * ptr)
+{
+ if (ptr != 0)
+ this->free_list_.add ((ACE_Cached_Mem_Pool_Node<char> *) ptr);
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Malloc_T)
+
+template <class MALLOC> void *
+ACE_Allocator_Adapter<MALLOC>::malloc (size_t nbytes)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::malloc");
+ return this->allocator_.malloc (nbytes);
+}
+
+template <class MALLOC> 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> 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> MALLOC &
+ACE_Allocator_Adapter<MALLOC>::alloc (void)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::allocator");
+ return this->allocator_;
+}
+
+template <class MALLOC> void
+ACE_Allocator_Adapter<MALLOC>::free (void *ptr)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::free");
+ this->allocator_.free (ptr);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::remove (void)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::remove");
+ return this->allocator_.remove ();
+}
+
+template <class MALLOC> 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> 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> 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> int
+ACE_Allocator_Adapter<MALLOC>::find (const char *name)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::find");
+ return this->allocator_.find (name);
+}
+
+template <class MALLOC> 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> int
+ACE_Allocator_Adapter<MALLOC>::unbind (const char *name)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::unbind");
+ return this->allocator_.unbind (name);
+}
+
+template <class MALLOC> 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> 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 <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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::dump");
+ this->allocator_.dump ();
+#endif /* ACE_HAS_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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("cb_ptr_ = %@\n"), this->cb_ptr_));
+ 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));
+#endif /* ACE_HAS_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, *this->lock_);
+
+ if (this->cb_ptr_ == 0)
+ return;
+ this->cb_ptr_->malloc_stats_.dump ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_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_TEXT ("(%P|%t) ptr = %@, 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_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("init_acquire failed")),
+ -1);
+ else if (first_time)
+ {
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) first time in, control block = %@\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)
+ : cb_ptr_ (0),
+ memory_pool_ (pool_name),
+ bad_flag_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+ this->lock_ = ACE_Malloc_Lock_Adapter_T<ACE_LOCK> ()(pool_name);
+ if (this->lock_ == 0)
+ return;
+
+ this->delete_lock_ = true;
+
+ this->bad_flag_ = this->open ();
+
+ if (this->bad_flag_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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)
+ : cb_ptr_ (0),
+ memory_pool_ (pool_name, options),
+ bad_flag_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+ // Use pool_name for lock_name if lock_name not passed.
+ const ACE_TCHAR *name = lock_name ? lock_name : pool_name;
+ this->lock_ = ACE_Malloc_Lock_Adapter_T<ACE_LOCK> ()(name);
+ if (this->lock_ == 0)
+ return;
+
+ this->delete_lock_ = true;
+
+ this->bad_flag_ = this->open ();
+ if (this->bad_flag_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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_MEM_POOL_OPTIONS *options,
+ ACE_LOCK *lock)
+ : cb_ptr_ (0),
+ memory_pool_ (pool_name, options),
+ lock_ (lock),
+ delete_lock_ (false),
+ bad_flag_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+
+ if (lock == 0)
+ {
+ this->bad_flag_ = -1;
+ errno = EINVAL;
+ return;
+ }
+
+ this->bad_flag_ = this->open ();
+ if (this->bad_flag_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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)
+ : cb_ptr_ (0),
+ memory_pool_ (pool_name,
+ (const ACE_MEM_POOL_OPTIONS *) options),
+ bad_flag_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+
+ this->lock_ = ACE_Malloc_Lock_Adapter_T<ACE_LOCK> ()(lock_name);
+ if (this->lock_ == 0)
+ return;
+
+ this->delete_lock_ = true;
+ this->bad_flag_ = this->open ();
+ if (this->bad_flag_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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>");
+ if (this->delete_lock_)
+ {
+ delete this->lock_;
+ this->lock_ = 0;
+ }
+}
+
+// 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_TEXT ("(%P|%t) destroying ACE_Malloc_T\n")));
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ this->print_stats ();
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ // Remove the ACE_LOCK.
+ if (this->delete_lock_)
+ this->lock_->remove ();
+
+ // Give the memory pool a chance to release its resources.
+ int const 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 const 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 /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ // 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);
+ void *remap_addr = this->memory_pool_.base_addr ();
+ if (remap_addr != 0)
+ this->cb_ptr_ = (ACE_CB *) remap_addr;
+
+ 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_TEXT ("(%P|%t) %p\n"),
+ // ACE_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,
+ 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, *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 <class ACE_LOCK> ACE_LOCK *
+ACE_Malloc_Lock_Adapter_T<ACE_LOCK>::operator () (const ACE_TCHAR *name)
+{
+ ACE_LOCK *p = 0;
+ if (name == 0)
+ ACE_NEW_RETURN (p, ACE_LOCK (name), 0);
+ else
+ ACE_NEW_RETURN (p, ACE_LOCK (ACE::basename (name,
+ ACE_DIRECTORY_SEPARATOR_CHAR)),
+ 0);
+ return p;
+}
+
+/*****************************************************************************/
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("name_ = %s"), this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("name_ = %s"), this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_MALLOC_T_CPP */
diff --git a/ACE/ace/Malloc_T.h b/ACE/ace/Malloc_T.h
new file mode 100644
index 00000000000..eef3739f3f2
--- /dev/null
+++ b/ACE/ace/Malloc_T.h
@@ -0,0 +1,931 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Malloc_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+ * Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_MALLOC_T_H
+#define ACE_MALLOC_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Malloc.h" /* Need ACE_Control_Block */
+#include "ace/Malloc_Base.h" /* Need ACE_Allocator */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Malloc_Allocator.h"
+#include "ace/Free_List.h"
+#include "ace/Guard_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 ACE_Cached_Allocator
+ * class 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 A fixed-size allocator that caches items for quicker access.
+ *
+ * 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.
+ *
+ * This class can be configured flexibly with different types of
+ * ACE_LOCK strategies that support the @a ACE_Thread_Mutex,
+ * @a ACE_Thread_Semaphore, @a ACE_Process_Mutex, and @a
+ * ACE_Process_Semaphore constructor API.
+ *
+ * @sa ACE_Dynamic_Cached_Allocator
+ */
+template <class T, class ACE_LOCK>
+class ACE_Cached_Allocator : public ACE_New_Allocator
+{
+public:
+ /// Create a cached memory pool with @a 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 @a nbytes is
+ * only checked to make sure that it's less or equal to sizeof T, and is
+ * otherwise ignored since @c 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
+ * @a initial_value. Note that @a nbytes is only checked to make sure
+ * that it's less or equal to sizeof T, and is otherwise ignored since
+ * calloc() 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 *);
+
+ /// Return the number of chunks available in the cache.
+ size_t pool_depth (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_Dynamic_Cached_Allocator
+ *
+ * @brief A size-based allocator that caches blocks for quicker access.
+ *
+ * This class enables caching of dynamically allocated,
+ * fixed-size chunks. Notice that the <code>chunk_size</code>
+ * must be greater than or equal to <code> sizeof (void*) </code> for
+ * this to work properly.
+ *
+ * This class can be configured flexibly with different types of
+ * ACE_LOCK strategies that support the @a ACE_Thread_Mutex and @a
+ * ACE_Process_Mutex constructor API.
+ *
+ * @sa ACE_Cached_Allocator
+ */
+template <class ACE_LOCK>
+class ACE_Dynamic_Cached_Allocator : public ACE_New_Allocator
+{
+public:
+ /// Create a cached memory pool with @a n_chunks chunks
+ /// each with @a chunk_size size.
+ ACE_Dynamic_Cached_Allocator (size_t n_chunks, size_t chunk_size);
+
+ /// Clear things up.
+ ~ACE_Dynamic_Cached_Allocator (void);
+
+ /**
+ * Get a chunk of memory from free list cache. Note that @a nbytes is
+ * only checked to make sure that it's less or equal to @a chunk_size,
+ * and is otherwise ignored since malloc() always returns a pointer to an
+ * item of @a chunk_size size.
+ */
+ void *malloc (size_t nbytes = 0);
+
+ /**
+ * Get a chunk of memory from free list cache, giving them
+ * @a initial_value. Note that @a nbytes is only checked to make sure
+ * that it's less or equal to @a chunk_size, and is otherwise ignored
+ * since calloc() always returns a pointer to an item of @a chunk_size.
+ */
+ 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 *);
+
+ /// Return the number of chunks available in the cache.
+ size_t pool_depth (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. We use @c char as template
+ /// parameter, although sizeof(char) is usually less than
+ /// sizeof(void*). Really important is that @a chunk_size
+ /// must be greater or equal to sizeof(void*).
+ ACE_Locked_Free_List<ACE_Cached_Mem_Pool_Node<char>, ACE_LOCK> free_list_;
+
+ /// Remember the size of our chunks.
+ size_t chunk_size_;
+};
+
+/**
+ * @class ACE_Allocator_Adapter
+ *
+ * @brief This class is an adapter that allows the ACE_Allocator to
+ * use the ACE_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 typename MALLOC::MEMORY_POOL_OPTIONS *MEMORY_POOL_OPTIONS;
+#else
+ typedef const void *MEMORY_POOL_OPTIONS;
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+ // = Initialization.
+ /**
+ * Note that @a pool_name should be located in
+ * a directory with the appropriate visibility and protection so
+ * that all processes that need to access it can do so. */
+ ACE_Allocator_Adapter (const char *pool_name = 0);
+
+ /**
+ * Note that @a pool_name should be located in
+ * a directory with the appropriate visibility and protection so
+ * that all processes that need to access it can do so.
+ * This constructor must be inline to avoid bugs with some C++
+ * compilers. */
+ 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");
+ }
+
+#if defined (ACE_HAS_WCHAR)
+ /**
+ * Note that @a pool_name should be located in
+ * a directory with the appropriate visibility and protection so
+ * that all processes that need to access it can do so. */
+ ACE_Allocator_Adapter (const wchar_t *pool_name);
+
+ /**
+ * Note that @a pool_name should be located in
+ * a directory with the appropriate visibility and protection so
+ * that all processes that need to access it can do so.
+ * This constructor must be inline to avoid bugs with some C++
+ * compilers. */
+ 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");
+ }
+#endif /* ACE_HAS_WCHAR */
+
+ /// Destructor.
+ virtual ~ACE_Allocator_Adapter (void);
+
+ // = Memory Management
+
+ /// Allocate @a nbytes, but don't give them any initial value.
+ virtual void *malloc (size_t nbytes);
+
+ /// Allocate @a nbytes, giving them all an @a initial_value.
+ virtual void *calloc (size_t nbytes, char initial_value = '\0');
+
+ /// Allocate @a n_elem each of size @a elem_size, giving them
+ /// @a initial_value.
+ virtual void *calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value = '\0');
+
+ /// Free @a 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 @a name with @a pointer. If @a duplicates == 0 then do
+ * not allow duplicate @a name/pointer associations, else if
+ * @a duplicates != 0 then allow duplicate @a name/pointer
+ * assocations. Returns 0 if successfully binds (1) a previously
+ * unbound @a name or (2) @a duplicates != 0, returns 1 if trying to
+ * bind a previously bound @a name and @a duplicates == 0, else
+ * returns -1 if a resource failure occurs.
+ */
+ virtual int bind (const char *name, void *pointer, int duplicates = 0);
+
+ /**
+ * Associate @a name with @a pointer. Does not allow duplicate
+ * name/pointer associations. Returns 0 if successfully binds
+ * (1) a previously unbound @a name, 1 if trying to bind a previously
+ * bound @a name, or returns -1 if a resource failure occurs. When
+ * this call returns, @a pointer's value will always reference the
+ * void * that @a name is associated with. Thus, if the caller needs
+ * to use @a pointer (e.g., to free it) a copy must be maintained by
+ * the caller.
+ */
+ virtual int trybind (const char *name, void *&pointer);
+
+ /// Locate @a name and pass out parameter via pointer. If found,
+ /// return 0, returns -1 if @a 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 @a len bytes of the memory region to the backing store
+ * starting at @c this->base_addr_. If @a len == -1 then sync the
+ * whole region.
+ */
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync @a len bytes of the memory region to the backing store
+ /// starting at @c addr_.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to @a prot
+ * starting at @c this->base_addr_ up to @a len bytes. If @a 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 @a prot
+ /// starting at @a addr up to @a 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 @c 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 A class template that uses parameterized types to provide
+ * an extensible mechanism for encapsulating various dynamic
+ * memory management strategies.
+ *
+ * This class can be configured flexibly with different
+ * MEMORY_POOL strategies and different types of ACE_LOCK
+ * strategies that support the ACE_Thread_Mutex and ACE_Process_Mutex
+ * constructor API.
+ *
+ * Common MEMORY_POOL strategies to use with this class are:
+ * - ACE_Local_Memory_Pool
+ * - ACE_MMAP_Memory_Pool
+ * - ACE_Pagefile_Memory_Pool
+ * - ACE_Shared_Memory_Pool
+ * - ACE_Sbrk_Memory_Pool
+ *
+ * The MEMORY_POOL class must provide the following methods:
+ * - constructor (const ACE_TCHAR *pool_name)
+ * - constructor (const ACE_TCHAR *pool_name, const MEMORY_POOL_OPTIONS *options)
+ * - void dump (void) const (needed if ACE is built with ACE_HAS_DUMP defined)
+ * - void *init_acquire (size_t nbytes, size_t &rounded_bytes, int &first_time);
+ * - int release (void)
+ * - void *acquire (size_t nbytes, size_t &rounded_bytes)
+ * - void *base_addr (void)
+ * - seh_selector() (only needed on Windows)
+ *
+ * Note that the ACE_Allocator_Adapter class can be used to integrate allocator
+ * classes which do not meet the interface requirements of ACE_Malloc_T.
+ *
+ * @Note The bind() and find() methods use linear search, so
+ * it's not a good idea to use them for managing a large number of
+ * entities. If you need to manage a large number of entities, it's
+ * recommended that you bind() an ACE_Hash_Map_Manager that
+ * resides in shared memory, use find() to locate it, and then
+ * store/retrieve the entities in the hash map.
+ */
+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 typename ACE_CB::ACE_Name_Node NAME_NODE;
+ typedef typename ACE_CB::ACE_Malloc_Header MALLOC_HEADER;
+
+ // = Initialization and termination methods.
+ /**
+ * Initialize ACE_Malloc. This constructor passes @a 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).
+ *
+ * Note that @a pool_name should be located in
+ * a directory with the appropriate visibility and protection so
+ * that all processes that need to access it can do so.
+ */
+ ACE_Malloc_T (const ACE_TCHAR *pool_name = 0);
+
+ /**
+ * Initialize ACE_Malloc. This constructor passes @a pool_name to
+ * initialize the memory pool, and uses @a lock_name to automatically
+ * extract out the name used for the underlying lock name (if
+ * necessary). In addition, @a options is passed through to
+ * initialize the underlying memory pool.
+ *
+ * Note that @a pool_name should be located in
+ * a directory with the appropriate visibility and protection so
+ * that all processes that need to access it can do so.
+ */
+ ACE_Malloc_T (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const ACE_MEM_POOL_OPTIONS *options = 0);
+
+ /**
+ * Initialize an ACE_Malloc with an external ACE_LOCK.
+ * This constructor passes @a pool_name and @a options to initialize
+ * the memory pool. @a lock is used as the pool lock, and must be
+ * properly set up and ready for use before being passed to this method.
+ */
+ ACE_Malloc_T (const ACE_TCHAR *pool_name,
+ const ACE_MEM_POOL_OPTIONS *options,
+ ACE_LOCK *lock);
+
+#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 (int close = 0);
+
+ /// Releases resources allocated by this object.
+ int remove (void);
+
+ // = Memory management
+
+ /// Allocate @a nbytes, but don't give them any initial value.
+ void *malloc (size_t nbytes);
+
+ /// Allocate @a nbytes, giving them @a initial_value.
+ void *calloc (size_t nbytes, char initial_value = '\0');
+
+ /// Allocate @a n_elem each of size @a elem_size, giving them
+ /// @a initial_value.
+ void *calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value = '\0');
+
+ /// Deallocate memory pointed to by @a ptr, which must have been
+ /// allocated previously by malloc().
+ void free (void *ptr);
+
+ /// Returns a reference to the underlying memory pool.
+ MEMORY_POOL &memory_pool (void);
+
+ // = Map manager like functions
+
+ /**
+ * Associate @a name with @a pointer. If @a duplicates == 0 then do
+ * not allow duplicate name/pointer associations, else if
+ * @a duplicates != 0 then allow duplicate name/pointer
+ * assocations. Returns 0 if successfully binds (1) a previously
+ * unbound @a name or (2) @a duplicates != 0, returns 1 if trying to
+ * bind a previously bound @a name and @a duplicates == 0, else
+ * returns -1 if a resource failure occurs.
+ */
+ int bind (const char *name, void *pointer, int duplicates = 0);
+
+ /**
+ * Associate @a name with @a pointer. Does not allow duplicate
+ * name/pointer associations. Returns 0 if successfully binds
+ * (1) a previously unbound @a name, 1 if trying to bind a previously
+ * bound @a name, or returns -1 if a resource failure occurs. When
+ * this call returns @a pointer's value will always reference the
+ * void * that @a name is associated with. Thus, if the caller needs
+ * to use @a pointer (e.g., to free it) a copy must be maintained by
+ * the caller.
+ */
+ int trybind (const char *name, void *&pointer);
+
+ /// Locate @a name and pass out parameter via @a pointer. If found,
+ /// return 0, returns -1 if failure occurs.
+ int find (const char *name, void *&pointer);
+
+ /// Returns 0 if @a 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 @a name
+ * you'll need to call this method multiple times until it fails...
+ */
+ int unbind (const char *name);
+
+ /**
+ * Unbind (remove) one association of @a name to @a pointer. Returns
+ * the value of pointer in case the caller needs to deallocate
+ * memory. If you want to remove all occurrences of @a 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 @a len bytes of the memory region to the backing store
+ * starting at @c this->base_addr_. If @a len == -1 then sync the
+ * whole region.
+ */
+ int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync @a len bytes of the memory region to the backing store
+ /// starting at @c addr_.
+ int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to @a prot
+ * starting at @c this->base_addr_ up to @a len bytes. If @a 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 @a prot
+ /// starting at @a addr up to @a 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
+ * @a 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);
+
+ /**
+ * Bad flag. This operation should be called immediately after the
+ * construction of the Malloc object to query whether the object was
+ * constructed successfully. If not, the user should invoke @c
+ * remove and release the object (it is not usable.)
+ * @retval 0 if all is fine. non-zero if this malloc object is
+ * unuable.
+ */
+ int bad (void);
+
+private:
+ /// Initialize the Malloc pool.
+ int open (void);
+
+ /// Associate @a name with @a pointer. Assumes that locks are held by
+ /// callers.
+ int shared_bind (const char *name,
+ void *pointer);
+
+ /**
+ * Try to locate @a name. If found, return the associated
+ * ACE_Name_Node, else returns 0 if can't find the @a 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_;
+
+ /// True if destructor should delete the lock
+ bool delete_lock_;
+
+ /// Keep track of failure in constructor.
+ int bad_flag_;
+};
+
+/*****************************************************************************/
+
+/**
+ * @class ACE_Malloc_Lock_Adapter_T
+ *
+ * @brief Template functor adapter for lock strategies used with ACE_Malloc_T.
+ *
+ * This class acts as a factory for lock strategies that have various ctor
+ * signatures. If the lock strategy's ctor takes an ACE_TCHAR* as the first
+ * and only required parameter, it will just work. Otherwise use template
+ * specialization to create a version that matches the lock strategy's ctor
+ * signature. See ACE_Process_Semaphore and ACE_Thread_Semaphore for
+ * examples.
+ *
+ */
+/*****************************************************************************/
+
+/**
+ * @class ACE_Malloc_LIFO_Iterator_T
+ *
+ * @brief LIFO iterator for names stored in Malloc'd memory.
+ *
+ * This class can be configured flexibly with different types of
+ * ACE_LOCK strategies that support the @a ACE_Thread_Mutex and @a
+ * ACE_Process_Mutex constructor API.
+ *
+ * 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 typename ACE_CB::ACE_Name_Node NAME_NODE;
+ typedef typename ACE_CB::ACE_Malloc_Header MALLOC_HEADER;
+
+ // = Initialization method.
+ /// If @a name = 0 it will iterate through everything else only
+ /// through those entries whose @a name match.
+ ACE_Malloc_LIFO_Iterator_T (ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc,
+ const char *name = 0);
+
+ /// Destructor.
+ ~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.
+ *
+ * This class can be configured flexibly with different types of
+ * ACE_LOCK strategies that support the @a ACE_Thread_Mutex and @a
+ * ACE_Process_Mutex constructor API.
+ *
+ * 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 typename ACE_CB::ACE_Name_Node NAME_NODE;
+ typedef typename ACE_CB::ACE_Malloc_Header MALLOC_HEADER;
+
+ // = Initialization method.
+ /// If @a name = 0 it will iterate through everything else only
+ /// through those entries whose @a name match.
+ ACE_Malloc_FIFO_Iterator_T (ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc,
+ const char *name = 0);
+
+ /// Destructor.
+ ~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 @a 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). Note that @a pool_name should be located in
+ * a directory with the appropriate visibility and protection so
+ * that all processes that need to access it can do so.
+ */
+ ACE_Malloc (const ACE_TCHAR *pool_name = 0);
+
+ /**
+ * Initialize ACE_Malloc. This constructor passes @a pool_name to
+ * initialize the memory pool, and uses @a lock_name to automatically
+ * extract out the name used for the underlying lock name (if
+ * necessary). In addition, @a options is passed through to
+ * initialize the underlying memory pool. Note that @a pool_name
+ * should be located in a directory with the appropriate visibility
+ * and protection so that all processes that need to access it can
+ * do so.
+ */
+ 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 @a name = 0 it will iterate through everything else only
+ /// through those entries whose @a 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 @a name = 0 it will iterate through everything else only
+ /// through those entries whose @a name match.
+ ACE_Malloc_FIFO_Iterator (ACE_Malloc<ACE_MEM_POOL_2, ACE_LOCK> &malloc,
+ const char *name = 0);
+};
+
+template <class ACE_LOCK>
+class ACE_Malloc_Lock_Adapter_T
+{
+public:
+ ACE_LOCK * operator () (const ACE_TCHAR *myname);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Malloc_T.inl"
+#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/ace/Malloc_T.inl b/ACE/ace/Malloc_T.inl
new file mode 100644
index 00000000000..078c0308ff5
--- /dev/null
+++ b/ACE/ace/Malloc_T.inl
@@ -0,0 +1,184 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 static_cast<T *> (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 size_t
+ACE_Cached_Allocator<T, ACE_LOCK>::pool_depth (void)
+{
+ return this->free_list_.size ();
+}
+
+template <class ACE_LOCK> ACE_INLINE size_t
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::pool_depth (void)
+{
+ return this->free_list_.size ();
+}
+
+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, *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>::bad (void)
+{
+ return this->bad_flag_;
+}
+
+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 (int close)
+{
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+ if (this->cb_ptr_ != 0)
+ {
+ int const retv = --this->cb_ptr_->ref_counter_;
+
+#if 0
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) ACE_Malloc_T::release ->%d\n"),
+ this->cb_ptr_->ref_counter_ - 1));
+#endif /* 0 */
+ if (close)
+ this->memory_pool_.release (0);
+
+ if (retv == 0)
+ this->remove ();
+ return retv;
+ }
+ 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 /* 0 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Managed_Object.cpp b/ACE/ace/Managed_Object.cpp
new file mode 100644
index 00000000000..53381f88a7e
--- /dev/null
+++ b/ACE/ace/Managed_Object.cpp
@@ -0,0 +1,25 @@
+// $Id$
+
+#ifndef ACE_MANAGED_OBJECT_CPP
+#define ACE_MANAGED_OBJECT_CPP
+
+#include "ace/Managed_Object.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Managed_Object.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TYPE>
+ACE_Cleanup_Adapter<TYPE>::~ACE_Cleanup_Adapter (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_MANAGED_OBJECT_CPP */
diff --git a/ACE/ace/Managed_Object.h b/ACE/ace/Managed_Object.h
new file mode 100644
index 00000000000..1b35a82c840
--- /dev/null
+++ b/ACE/ace/Managed_Object.h
@@ -0,0 +1,168 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Managed_Object.h
+ *
+ * $Id$
+ *
+ * @author David L. Levine <levine@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MANAGED_OBJECT_H
+#define ACE_MANAGED_OBJECT_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/Object_Manager.h"
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Cleanup_Adapter
+ *
+ * @brief Adapter for ACE_Cleanup objects that allows them to be readily
+ * managed by the ACE_Object_Manager.
+ *
+ * This template class adapts an object of any type to be an
+ * ACE_Cleanup object. The object can then be destroyed
+ * type-safely by the ACE_Object_Manager. This class is
+ * typically used to replace a cast; but, it's a bit cleaner and
+ * allows insertion of, say, run-time type identification
+ * internally if desired.
+ */
+template <class TYPE>
+class ACE_Cleanup_Adapter : public ACE_Cleanup
+{
+public:
+ /// Default constructor.
+ ACE_Cleanup_Adapter (void);
+
+ /// Virtual destructor, needed by some compilers for vtable placement.
+ virtual ~ACE_Cleanup_Adapter (void);
+
+ /// Accessor for contained object.
+ TYPE &object (void);
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Cleanup_Adapter (const ACE_Cleanup_Adapter<TYPE> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Cleanup_Adapter<TYPE> &))
+
+ /// Contained object.
+ TYPE object_;
+};
+
+/**
+ * @class ACE_Managed_Object
+ *
+ * @brief Wrapper for interface to allocate an object managed by the
+ * ACE_Object_Manager.
+ *
+ * This template class wraps an interface that is used to
+ * allocate and access an object that is managed by the
+ * ACE_Object_Manager. Because static template member functions
+ * are not supported by some compilers, it is a separate
+ * (template) class.
+ * This interface is typically used to replace a static object
+ * with one that is dynamically allocated. It helps to avoid
+ * problems with order of static object
+ * construction/destruction. Managed objects won't be allocated
+ * until needed, but should be allocated when first needed. And
+ * they are destroyed in the reverse order of construction.
+ * <get_preallocated_object> accesses a "preallocated" object,
+ * i.e., one that is identified by a value in the
+ * ACE_Object_Manager:: Preallocated_Object enum. These objects
+ * are used internally by the ACE library.
+ * Hooks are provided for the application to preallocate objects
+ * via the same mechanism.
+ * ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS can be used
+ * to define enum values;
+ * ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS can be used
+ * to define the corresponding objects. The format of the ACE
+ * internal library definitions should be followed. And
+ * similarly, ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS
+ * and ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS can be
+ * used to preallocate arrays.
+ * By default, preallocation uses dynamic allocation. The
+ * preallocated objects and arrays are allocated off the heap in
+ * the ACE_Object_Manager constructor. To statically place the
+ * preallocated objects in program global data instead of on the
+ * heap, #define ACE_HAS_STATIC_PREALLOCATION prior to building
+ * the ACE library.
+ */
+template <class TYPE>
+class ACE_Managed_Object
+{
+public:
+ static TYPE *get_preallocated_object (ACE_Object_Manager::Preallocated_Object identifier)
+ {
+ // The preallocated objects are in a separate, "read-only" array so
+ // that this function doesn't need a lock. Also, because it is
+ // intended _only_ for use with hard-code values, it performs no
+ // range checking on "id".
+
+ // Cast the return type of the the object pointer based
+ // on the type of the function template parameter.
+ return &((ACE_Cleanup_Adapter<TYPE> *)
+ ACE_Object_Manager::preallocated_object[identifier])->object ();
+ }
+ // Get the preallocated object identified by "id". Returns a
+ // pointer to the object. Beware: no error indication is provided,
+ // because it can _only_ be used for accessing preallocated objects.
+ // @note The function definition is inlined here so that it compiles
+ // on AIX 4.1 w/xlC v. 3.01.
+
+ static TYPE *get_preallocated_array (ACE_Object_Manager::Preallocated_Array identifier)
+ {
+ // The preallocated array are in a separate, "read-only" array so
+ // that this function doesn't need a lock. Also, because it is
+ // intended _only_ for use with hard-code values, it performs no
+ // range checking on "id".
+
+ // Cast the return type of the the object pointer based
+ // on the type of the function template parameter.
+ return &((ACE_Cleanup_Adapter<TYPE> *)
+ ACE_Object_Manager::preallocated_array[identifier])->object ();
+ }
+ // Get the preallocated array identified by "id". Returns a
+ // pointer to the array. Beware: no error indication is provided,
+ // because it can _only_ be used for accessing preallocated arrays.
+ // @note The function definition is inlined here so that it compiles
+ // on AIX 4.1 w/xlC v. 3.01.
+
+protected:
+
+ // Disallow instantiation of this class.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Managed_Object (void))
+
+private:
+
+ ACE_UNIMPLEMENTED_FUNC (ACE_Managed_Object (const ACE_Managed_Object<TYPE> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Managed_Object<TYPE> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Managed_Object.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Managed_Object.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Managed_Object.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MANAGED_OBJECT_H */
diff --git a/ACE/ace/Managed_Object.inl b/ACE/ace/Managed_Object.inl
new file mode 100644
index 00000000000..0619691d8a6
--- /dev/null
+++ b/ACE/ace/Managed_Object.inl
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TYPE>
+ACE_INLINE
+ACE_Cleanup_Adapter<TYPE>::ACE_Cleanup_Adapter (void)
+ // Note: don't explicitly initialize "object_", because TYPE may not
+ // have a default constructor. Let the compiler figure it out . . .
+{
+}
+
+template <class TYPE>
+ACE_INLINE
+TYPE &
+ACE_Cleanup_Adapter<TYPE>::object (void)
+{
+ return this->object_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Manual_Event.cpp b/ACE/ace/Manual_Event.cpp
new file mode 100644
index 00000000000..57543a6d840
--- /dev/null
+++ b/ACE/ace/Manual_Event.cpp
@@ -0,0 +1,48 @@
+// $Id$
+
+#include "ace/Manual_Event.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Manual_Event.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID(ace, Manual_Event, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Manual_Event::ACE_Manual_Event (int initial_state,
+ int type,
+ const char *name,
+ void *arg)
+ : ACE_Event (1,
+ initial_state,
+ type,
+ ACE_TEXT_CHAR_TO_TCHAR (name),
+ arg)
+{
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_Manual_Event::ACE_Manual_Event (int initial_state,
+ int type,
+ const wchar_t *name,
+ void *arg)
+ : ACE_Event (1,
+ initial_state,
+ type,
+ ACE_TEXT_WCHAR_TO_TCHAR (name),
+ arg)
+{
+}
+#endif /* ACE_HAS_WCHAR */
+
+void
+ACE_Manual_Event::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_Event::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Manual_Event.h b/ACE/ace/Manual_Event.h
new file mode 100644
index 00000000000..80464fa1fc1
--- /dev/null
+++ b/ACE/ace/Manual_Event.h
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Manual_Event.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_MANUAL_EVENT_H
+#define ACE_MANUAL_EVENT_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Manual_Event
+ *
+ * @brief Manual Events.
+ *
+ * Specialization of Event mechanism which wakes up all waiting
+ * thread on <signal>. All platforms support process-scope locking
+ * support. However, only Win32 platforms support global naming and
+ * system-scope locking support.
+ */
+class ACE_Export ACE_Manual_Event : public ACE_Event
+{
+public:
+ /// constructor which will create manual event
+ ACE_Manual_Event (int initial_state = 0,
+ int type = USYNC_THREAD,
+ const char *name = 0,
+ void *arg = 0);
+
+#if defined (ACE_HAS_WCHAR)
+ /// constructor which will create manual event (wchar_t version)
+ ACE_Manual_Event (int initial_state,
+ int type,
+ const wchar_t *name,
+ void *arg = 0);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Default dtor.
+ ~ACE_Manual_Event (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Manual_Event.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MANUAL_EVENT_H */
diff --git a/ACE/ace/Manual_Event.inl b/ACE/ace/Manual_Event.inl
new file mode 100644
index 00000000000..42bf94f6404
--- /dev/null
+++ b/ACE/ace/Manual_Event.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Manual_Event::~ACE_Manual_Event (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Map.h b/ACE/ace/Map.h
new file mode 100644
index 00000000000..52e77aa37d5
--- /dev/null
+++ b/ACE/ace/Map.h
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Map.h
+ *
+ * $Id$
+ *
+ * Backward compatibility header.
+ *
+ * @author Irfan Pyarali
+ */
+//=============================================================================
+
+
+#ifndef ACE_MAP_H
+#define ACE_MAP_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Include the templates here.
+#include "ace/Map_T.h"
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MAP_H */
diff --git a/ACE/ace/Map_Manager.cpp b/ACE/ace/Map_Manager.cpp
new file mode 100644
index 00000000000..85957918df4
--- /dev/null
+++ b/ACE/ace/Map_Manager.cpp
@@ -0,0 +1,701 @@
+// $Id$
+
+#ifndef ACE_MAP_MANAGER_CPP
+#define ACE_MAP_MANAGER_CPP
+
+#include "ace/Map_Manager.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Malloc_Base.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Map_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Map_Entry)
+ACE_ALLOC_HOOK_DEFINE(ACE_Map_Manager)
+ACE_ALLOC_HOOK_DEFINE(ACE_Map_Const_Iterator_Base)
+ACE_ALLOC_HOOK_DEFINE(ACE_Map_Iterator_Base)
+ACE_ALLOC_HOOK_DEFINE(ACE_Map_Const_Iterator)
+ACE_ALLOC_HOOK_DEFINE(ACE_Map_Iterator)
+ACE_ALLOC_HOOK_DEFINE(ACE_Map_Reverse_Iterator)
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::open (size_t size,
+ ACE_Allocator *alloc)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ // Close old map (if any).
+ this->close_i ();
+
+ // Use the user specified allocator or the default singleton one.
+ if (alloc == 0)
+ alloc = ACE_Allocator::instance ();
+
+ this->allocator_ = alloc;
+
+ // This assertion is here to help track a situation that shouldn't
+ // happen.
+ ACE_ASSERT (size != 0);
+
+ // Active_Map_Manager depends on the <slot_index_> being of fixed
+ // size. It cannot be size_t because size_t is 64-bits on 64-bit
+ // platform and 32-bits on 32-bit platforms. Size of the <slot_index_>
+ // has to be consistent across platforms. ACE_UIN32 is chosen as
+ // ACE_UIN32_MAX is big enough. The assert is to ensure that the user
+ // doesn't open the ACE_Map_Manager with a bigger size than we can
+ // handle.
+ ACE_ASSERT (size <= ACE_UINT32_MAX);
+
+ // Resize from 0 to <size>. Note that this will also set up the
+ // circular free list.
+ return this->resize_i ((ACE_UINT32) size);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::close_i (void)
+{
+ // Free entries.
+ this->free_search_structure ();
+
+ // Reset sizes.
+ this->total_size_ = 0;
+ this->cur_size_ = 0;
+
+ // Reset circular free list.
+ this->free_list_.next (this->free_list_id ());
+ this->free_list_.prev (this->free_list_id ());
+
+ // Reset circular occupied list.
+ this->occupied_list_.next (this->occupied_list_id ());
+ this->occupied_list_.prev (this->occupied_list_id ());
+
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ // Try to find the key.
+ ACE_UINT32 slot = 0;
+ int result = this->find_and_return_index (ext_id,
+ slot);
+
+ if (result == 0)
+ // We found the key. Nothing to change.
+ return 1;
+ else
+ // We didn't find the key.
+ return this->shared_bind (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::next_free (ACE_UINT32 &free_slot)
+{
+ // Look in the free list for an empty slot.
+ free_slot = this->free_list_.next ();
+
+ // If we do find a free slot, return successfully.
+ if (free_slot != this->free_list_id ())
+ return 0;
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ // Move any free slots from occupied list to free list.
+ this->move_all_free_slots_from_occupied_list ();
+
+ // Try again in case we found any free slots in the occupied list.
+ free_slot = this->free_list_.next ();
+
+ // If we do find a free slot, return successfully.
+ if (free_slot != this->free_list_id ())
+ return 0;
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ // Resize the map.
+ int result = this->resize_i (this->new_size ());
+
+ // Check for errors.
+ if (result == 0)
+ // New free slot.
+ free_slot = this->free_list_.next ();
+
+ return result;
+}
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::move_all_free_slots_from_occupied_list (void)
+{
+ //
+ // In the case of lazy map managers, the movement of free slots from
+ // the occupied list to the free list is delayed until we run out of
+ // free slots in the free list.
+ //
+
+ // Go through the entire occupied list, moving free slots to the
+ // free list. Note that all free slots in the occupied list are
+ // moved in this loop.
+ for (ACE_UINT32 i = this->occupied_list_.next ();
+ i != this->occupied_list_id ();
+ )
+ {
+ //
+ // Note the trick used here: Information about the current slot
+ // is first noted; <i> then moves to the next occupied slot;
+ // only after this is the slot (potentially) moved from the
+ // occupied list to the free list. This order of things, i.e.,
+ // moving <i> before moving the free slot is necessary,
+ // otherwise we'll forget which our next occupied slot is.
+ //
+
+ // Note information about current slot.
+ ACE_Map_Entry<EXT_ID, INT_ID> &current_slot = this->search_structure_[i];
+ ACE_UINT32 position_of_current_slot = i;
+
+ // Move <i> to next occupied slot.
+ i = this->search_structure_[i].next ();
+
+ // If current slot is free
+ if (current_slot.free_)
+ {
+ // Reset free flag to zero before moving to free list.
+ current_slot.free_ = false;
+
+ // Move from occupied list to free list.
+ this->move_from_occupied_list_to_free_list (position_of_current_slot);
+ }
+ }
+}
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::shared_move (ACE_UINT32 slot,
+ ACE_Map_Entry<EXT_ID, INT_ID> &current_list,
+ ACE_UINT32 current_list_id,
+ ACE_Map_Entry<EXT_ID, INT_ID> &new_list,
+ ACE_UINT32 new_list_id)
+{
+ // Grab the entry.
+ ENTRY &entry = this->search_structure_[slot];
+
+ // Remove from current list.
+
+ // Fix the entry before us.
+ ACE_UINT32 current_list_prev = entry.prev ();
+
+ if (current_list_prev == current_list_id)
+ current_list.next (entry.next ());
+ else
+ this->search_structure_[current_list_prev].next (entry.next ());
+
+ // Fix the entry after us.
+ ACE_UINT32 current_list_next = entry.next ();
+
+ if (current_list_next == current_list_id)
+ current_list.prev (entry.prev ());
+ else
+ this->search_structure_[current_list_next].prev (entry.prev ());
+
+ // Add to new list.
+
+ // Fix us.
+ ACE_UINT32 new_list_next = new_list.next ();
+ entry.next (new_list_next);
+ entry.prev (new_list_id);
+
+ // Fix entry before us.
+ new_list.next (slot);
+
+ // Fix entry after us.
+ if (new_list_next == new_list_id)
+ new_list.prev (slot);
+ else
+ this->search_structure_[new_list_next].prev (slot);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::shared_bind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ // This function assumes that the find() has already been done, and
+ // therefore, simply adds to the map.
+
+ // Find an empty slot.
+ ACE_UINT32 slot = 0;
+ int result = this->next_free (slot);
+
+ if (result == 0)
+ {
+ // Copy key and value.
+ this->search_structure_[slot].int_id_ = int_id;
+ this->search_structure_[slot].ext_id_ = ext_id;
+
+ // Move from free list to occupied list
+ this->move_from_free_list_to_occupied_list (slot);
+
+ // Update the current size.
+ ++this->cur_size_;
+ }
+
+ return result;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id)
+{
+ // First try to find the key.
+ ACE_UINT32 slot = 0;
+ int result = this->find_and_return_index (ext_id,
+ slot);
+ if (result == 0)
+ {
+ // We found it, so make copies of the old entries and rebind
+ // current entries.
+ ENTRY &ss = this->search_structure_[slot];
+ old_ext_id = ss.ext_id_;
+ old_int_id = ss.int_id_;
+ ss.ext_id_ = ext_id;
+ ss.int_id_ = int_id;
+
+ // Sync changed entry.
+ this->allocator_->sync (&ss, sizeof ss);
+
+ return 1;
+ }
+ else
+ // We didn't find it, so let's add it.
+ return this->shared_bind (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id)
+{
+ // First try to find the key.
+ ACE_UINT32 slot = 0;
+ int result = this->find_and_return_index (ext_id,
+ slot);
+ if (result == 0)
+ {
+ // We found it, so make copies of the old entries and rebind
+ // current entries.
+ ENTRY &ss = this->search_structure_[slot];
+ old_int_id = ss.int_id_;
+ ss.ext_id_ = ext_id;
+ ss.int_id_ = int_id;
+
+ // Sync changed entry.
+ this->allocator_->sync (&ss, sizeof ss);
+
+ return 1;
+ }
+ else
+ // We didn't find it, so let's add it.
+ return this->shared_bind (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ // First try to find the key.
+ ACE_UINT32 slot = 0;
+ int result = this->find_and_return_index (ext_id,
+ slot);
+ if (result == 0)
+ {
+ // We found it, so rebind current entries.
+ ENTRY &ss = this->search_structure_[slot];
+ ss.ext_id_ = ext_id;
+ ss.int_id_ = int_id;
+
+ // Sync changed entry.
+ this->allocator_->sync (&ss, sizeof ss);
+
+ return 1;
+ }
+ else
+ // We didn't find it, so let's add it.
+ return this->shared_bind (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::trybind_i (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ // Try to find the key.
+ ACE_UINT32 slot = 0;
+ int result = this->find_and_return_index (ext_id,
+ slot);
+ if (result == 0)
+ {
+ // Key was found. Make a copy of value, but *don't* update
+ // anything in the map!
+ int_id = this->search_structure_[slot].int_id_;
+ return 1;
+ }
+ else
+ // We didn't find it, so let's bind it!
+ return this->bind_i (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::find_and_return_index (const EXT_ID &ext_id,
+ ACE_UINT32 &slot)
+{
+ // Go through the entire occupied list looking for the key.
+ for (ACE_UINT32 i = this->occupied_list_.next ();
+ i != this->occupied_list_id ();
+ i = this->search_structure_[i].next ())
+ {
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+ if (this->search_structure_[i].free_)
+ continue;
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ if (this->equal (this->search_structure_[i].ext_id_,
+ ext_id))
+ {
+ // If found, return slot.
+ slot = i;
+ return 0;
+ }
+ }
+
+ // Key was not found.
+ return -1;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_all (void)
+{
+ // Go through the entire occupied list.
+ for (ACE_UINT32 i = this->occupied_list_.next ();
+ i != this->occupied_list_id ();
+ )
+ {
+ //
+ // Note the trick used here: Information about the current slot
+ // is first noted; <i> then moves to the next occupied slot;
+ // only after this is the slot (potentially) moved from the
+ // occupied list to the free list. This order of things, i.e.,
+ // moving <i> before moving the free slot is necessary,
+ // otherwise we'll forget which our next occupied slot is.
+ //
+
+ // Note information about current slot.
+ ACE_Map_Entry<EXT_ID, INT_ID> &current_slot =
+ this->search_structure_[i];
+ ACE_UINT32 position_of_current_slot = i;
+
+ // Move <i> to next occupied slot.
+ i = current_slot.next ();
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+ if (current_slot.free_)
+ continue;
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ this->unbind_slot (position_of_current_slot);
+ }
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::find_i (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ // Try to find the key.
+ ACE_UINT32 slot = 0;
+ int result = this->find_and_return_index (ext_id,
+ slot);
+ if (result == 0)
+ // Key was found. Make a copy of value.
+ int_id = this->search_structure_[slot].int_id_;
+
+ return result;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_and_return_index (const EXT_ID &ext_id,
+ ACE_UINT32 &slot)
+{
+ // Try to find the key.
+ int result = this->find_and_return_index (ext_id,
+ slot);
+
+ if (result == 0)
+ this->unbind_slot (slot);
+
+ return result;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_slot (ACE_UINT32 slot)
+{
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ //
+ // In the case of lazy map managers, the movement of free slots
+ // from the occupied list to the free list is delayed until we
+ // run out of free slots in the free list.
+ //
+
+ this->search_structure_[slot].free_ = true;
+
+#else
+
+ // Move from occupied list to free list.
+ this->move_from_occupied_list_to_free_list (slot);
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ // Update the current size.
+ --this->cur_size_;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_i (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ // Unbind the entry.
+ ACE_UINT32 slot = 0;
+ int result = this->unbind_and_return_index (ext_id,
+ slot);
+ if (result == 0)
+ // If found, copy the value.
+ int_id = this->search_structure_[slot].int_id_;
+
+ return result;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::resize_i (ACE_UINT32 new_size)
+{
+ ACE_UINT32 i;
+ ENTRY *temp = 0;
+
+ // Allocate new memory.
+ ACE_ALLOCATOR_RETURN (temp,
+ (ENTRY *) this->allocator_->malloc (new_size * sizeof (ENTRY)),
+ -1);
+
+ // Copy over the occupied entires.
+ for (i = this->occupied_list_.next ();
+ i != this->occupied_list_id ();
+ i = this->search_structure_[i].next ())
+ // Call the copy constructor using operator placement new.
+ new (&(temp[i])) ENTRY (this->search_structure_[i]);
+
+ // Copy over the free entires.
+ for (i = this->free_list_.next ();
+ i != this->free_list_id ();
+ i = this->search_structure_[i].next ())
+ // Call the copy constructor using operator placement new.
+ new (&(temp[i])) ENTRY (this->search_structure_[i]);
+
+ // Construct the new elements.
+ for (i = this->total_size_; i < new_size; i++)
+ {
+ // Call the constructor for each element in the array using
+ // operator placement new. Note that this requires a default
+ // constructor for <EXT_ID> and <INT_ID>.
+ new (&(temp[i])) ENTRY;
+ temp[i].next (i + 1);
+ temp[i].prev (i - 1);
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ // Even though this slot is initially free, we need the <free_>
+ // flag to be zero so that we don't have to set it when the slot
+ // is moved to the occupied list. In addition, this flag has no
+ // meaning while this slot is in the free list.
+ temp[i].free_ = false;
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ }
+
+ // Add new entries to the free list.
+ this->free_list_.next (this->total_size_);
+ this->free_list_.prev (new_size - 1);
+ temp[new_size - 1].next (this->free_list_id ());
+ temp[this->total_size_].prev (this->free_list_id ());
+
+ // Remove/free old elements, update the new totoal size.
+ this->free_search_structure ();
+ this->total_size_ = new_size;
+
+ // Start using new elements.
+ this->search_structure_ = temp;
+
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_UINT32
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::new_size (void)
+{
+ // Calculate the new size.
+ ACE_UINT32 current_size = this->total_size_;
+
+ if (current_size < MAX_EXPONENTIAL)
+ // Exponentially increase if we haven't reached MAX_EXPONENTIAL.
+ current_size *= 2;
+ else
+ // Linear increase if we have reached MAX_EXPONENTIAL.
+ current_size += LINEAR_INCREASE;
+
+ // This should be the new size.
+ return current_size;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::free_search_structure (void)
+{
+ // Free up the structure.
+ if (this->search_structure_ != 0)
+ {
+ for (ACE_UINT32 i = 0; i < this->total_size_; i++)
+ // Explicitly call the destructor.
+ {
+ ENTRY *ss = &this->search_structure_[i];
+ // The "if" second argument results in a no-op instead of
+ // deallocation.
+ ACE_DES_FREE_TEMPLATE2 (ss, ACE_NOOP,
+ ACE_Map_Entry, EXT_ID, INT_ID);
+ }
+
+ // Actually free the memory.
+ this->allocator_->free (this->search_structure_);
+ this->search_structure_ = 0;
+ }
+}
+
+template <class EXT_ID, class INT_ID> void
+ACE_Map_Entry<EXT_ID, INT_ID>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %d"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("prev_ = %d"), this->prev_));
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("free_ = %d"), this->free_));
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("total_size_ = %d"), this->total_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_));
+ this->allocator_->dump ();
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::dump_i (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %d"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::dump_i (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %d"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Map_Entry<EXT_ID, INT_ID>&
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::operator* (void) const
+{
+ // @@ This function should be inlined. We moved it here to avoid a
+ // compiler bug in SunCC 4.2. Once we know the correct patch to fix
+ // the compiler problem, it should be moved back to .i file again.
+ ACE_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+ ACE_ASSERT (result != 0);
+ ACE_UNUSED_ARG (result);
+
+ return *retv;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+ACE_Map_Entry<EXT_ID, INT_ID>&
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::operator* (void) const
+{
+ // @@ This function should be inlined. We moved it here to avoid a
+ // compiler bug in SunCC 4.2. Once we know the correct patch to fix
+ // the compiler problem, it should be moved back to .i file again.
+ ACE_Map_Entry<EXT_ID, INT_ID> *retv = 0;
+
+ int result = this->next (retv);
+ ACE_ASSERT (result != 0);
+ ACE_UNUSED_ARG (result);
+
+ return *retv;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> void
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_MAP_MANAGER_CPP */
diff --git a/ACE/ace/Map_Manager.h b/ACE/ace/Map_Manager.h
new file mode 100644
index 00000000000..75c2b65f977
--- /dev/null
+++ b/ACE/ace/Map_Manager.h
@@ -0,0 +1,719 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Map_Manager.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MAP_MANAGER_H
+#define ACE_MAP_MANAGER_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/Global_Macros.h"
+#include "ace/Default_Constants.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration.
+class ACE_Allocator;
+
+/**
+ * @class ACE_Map_Entry
+ *
+ * @brief An entry in the Map.
+ */
+template <class EXT_ID, class INT_ID>
+class ACE_Map_Entry
+{
+public:
+ /// Initialize member variables.
+ ACE_Map_Entry (void);
+
+ /// We need this destructor to keep some compilers from complaining.
+ /// It's just a no-op, however.
+ ~ACE_Map_Entry (void);
+
+ /// Key used to look up an entry.
+ EXT_ID ext_id_;
+
+ /// The contents of the entry itself.
+ INT_ID int_id_;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // = These are really private, but unfortunately template friends
+ // are not portable.
+
+ /// Get next entry.
+ ACE_UINT32 next (void) const;
+
+ /// Set next entry.
+ void next (ACE_UINT32 n);
+
+ /// Get prev entry.
+ ACE_UINT32 prev (void) const;
+
+ /// Set prev entry.
+ void prev (ACE_UINT32 p);
+
+ /// Keeps track of the next entry.
+ ACE_UINT32 next_;
+
+ /// Keeps track of the previous entry.
+ ACE_UINT32 prev_;
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ /// Is this entry free?
+ bool free_;
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+};
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Iterator_Base;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Const_Iterator_Base;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Iterator;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Const_Iterator;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Reverse_Iterator;
+
+/**
+ * @class ACE_Map_Manager
+ *
+ * @brief Define a map abstraction that associates <EXT_ID>s with
+ * <INT_ID>s.
+ *
+ * The <EXT_ID> must support <operator==>. This constraint can
+ * be alleviated via template specialization, as shown in the
+ * $ACE_ROOT/tests/Conn_Test.cpp test.
+ * This class uses an ACE_Allocator to allocate memory. The
+ * user can make this a persistant class by providing an
+ * ACE_Allocator with a persistable memory pool.
+ * This implementation of a map uses an array, which is searched
+ * linearly. For more efficient searching you should use the
+ * <ACE_Hash_Map_Manager>.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Manager
+{
+public:
+ friend class ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>;
+ friend class ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>;
+ friend class ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>;
+ friend class ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>;
+ friend class ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>;
+
+ // = Traits.
+ typedef EXT_ID KEY;
+ typedef INT_ID VALUE;
+ typedef ACE_LOCK lock_type;
+ typedef ACE_Map_Entry<EXT_ID, INT_ID> ENTRY;
+ typedef ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> ITERATOR;
+ typedef ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> CONST_ITERATOR;
+ typedef ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> REVERSE_ITERATOR;
+
+ typedef ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> iterator;
+ typedef ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> const_iterator;
+ typedef ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> reverse_iterator;
+
+ // = Initialization and termination methods.
+ /// Initialize a ACE_Map_Manager with the ACE_DEFAULT_MAP_SIZE.
+ ACE_Map_Manager (ACE_Allocator *alloc = 0);
+
+ /// Initialize a ACE_Map_Manager with @a size entries.
+ ACE_Map_Manager (size_t size,
+ ACE_Allocator *alloc = 0);
+
+ /// Initialize a ACE_Map_Manager with size @a length.
+ int open (size_t length = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a ACE_Map_Manager and release dynamically allocated
+ /// resources.
+ int close (void);
+
+ /// Close down a ACE_Map_Manager and release dynamically allocated
+ /// resources.
+ ~ACE_Map_Manager (void);
+
+ /**
+ * Associate @a ext_id with @a int_id. If @a ext_id is already in the
+ * map then the ACE_Map_Entry is not changed.
+ * @retval 0 If a new entry is bound successfully.
+ * @retval 1 If an attempt is made to bind an existing entry.
+ * @retval -1 If failures occur.
+ */
+ int bind (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /**
+ * Reassociate @a ext_id with @a int_id. If @a ext_id is not in the
+ * map then behaves just like bind(). Otherwise, store the old
+ * values of @a ext_id and @a int_id into the "out" parameters and
+ * rebind the new parameters. This is very useful if you need to
+ * have an atomic way of updating <Map_Entries> and you also need
+ * full control over memory allocation.
+ * @retval 0 If a new entry is bound successfully.
+ * @retval 1 If an existing entry was rebound.
+ * @retval -1 If failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id);
+
+ /**
+ * Reassociate @a ext_id with @a int_id. If @a ext_id is not in the
+ * map then behaves just like <bind>. Otherwise, store the old
+ * values of @a int_id into the "out" parameter and rebind the new
+ * parameters.
+ * @retval 0 If a new entry is bound successfully.
+ * @retval 1 If an existing entry was rebound.
+ * @retval -1 If failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id);
+
+ /// Reassociate @a ext_id with @a int_id. Old values in the map are
+ /// ignored.
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /**
+ * Associate @a ext_id with @a int_id if and only if @a ext_id is not
+ * in the map. If @a ext_id is already in the map then the @a int_id
+ * parameter is overwritten with the existing value in the map
+ * @retval 0 If a new entry is bound successfully.
+ * @retval 1 If an attempt is made to bind an existing entry.
+ * @retval -1 If failures occur.
+ */
+ int trybind (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /**
+ * Locate @a ext_id and pass out parameter via @a int_id.
+ * @retval 0 If found.
+ * @retval -1 If not found.
+ */
+ int find (const EXT_ID &ext_id,
+ INT_ID &int_id) const;
+
+ /// Returns 0 if the @a ext_id is in the mapping, otherwise -1.
+ int find (const EXT_ID &ext_id) const;
+
+ /**
+ * Unbind (remove) the @a ext_id from the map. Don't return the
+ * @a int_id to the caller (this is useful for collections where the
+ * @a int_ids are *not* dynamically allocated...) Returns 0 if
+ * successful, else -1.
+ */
+ int unbind (const EXT_ID &ext_id);
+
+ /**
+ * Break any association of @a ext_id. Returns the value of @a int_id
+ * in case the caller needs to deallocate memory. Returns 0 if
+ * successful, else -1.
+ */
+ int unbind (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /**
+ * Unbind all entires.
+ */
+ void unbind_all (void);
+
+ /// Return the current size of the map.
+ size_t current_size (void) const;
+
+ /// Return the total size of the map.
+ size_t total_size (void) const;
+
+ /**
+ * Returns a reference to the underlying <ACE_LOCK>. This makes it
+ * possible to acquire the lock explicitly, which can be useful in
+ * some cases if you instantiate the ACE_Atomic_Op with an
+ * ACE_Recursive_Mutex or ACE_Process_Mutex, or if you need to
+ * guard the state of an iterator.
+ * @note The right name would be <lock>, but HP/C++ will choke on that!
+ */
+ ACE_LOCK &mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> begin (void);
+ ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> end (void);
+
+ /// Return reverse iterator.
+ ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> rbegin (void);
+ ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> rend (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ // = The following methods do the actual work.
+
+ // These methods assume that the locks are held by the private
+ // methods.
+
+ /// Performs the binding of @a ext_id to @a int_id. Must be called
+ /// with locks held.
+ int bind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Bind an entry (without finding first). Must be called with locks
+ /// held.
+ int shared_bind (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Performs a rebinding of <ext_it> to @a int_id. Also, recovers old
+ /// values. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id);
+
+ /// Performs a rebinding of <ext_it> to @a int_id. Also, recovers old
+ /// values. Must be called with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id);
+
+ /// Performs a rebinding of <ext_it> to @a int_id. Must be called
+ /// with locks held.
+ int rebind_i (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /// Performs a conditional bind of @a int_id using @a ext_id as the
+ /// key. Must be called with locks held.
+ int trybind_i (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /// Performs a find of @a int_id using @a ext_id as the key. Must be
+ /// called with locks held.
+ int find_i (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /// Performs a find using @a ext_id as the key. Must be called with
+ /// locks held.
+ int find_and_return_index (const EXT_ID &ext_id,
+ ACE_UINT32 &slot);
+
+ /// Performs an unbind of @a int_id using @a ext_id as the key. Must
+ /// be called with locks held.
+ int unbind_i (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /// Performs an unbind using @a ext_id as the key. Must be called
+ /// with locks held.
+ int unbind_i (const EXT_ID &ext_id);
+
+ /// Performs an unbind using @a ext_id as the key. Must be called
+ /// with locks held.
+ int unbind_and_return_index (const EXT_ID &ext_id,
+ ACE_UINT32 &slot);
+
+ /// Unbind @a slot.
+ void unbind_slot (ACE_UINT32 slot);
+
+ /// Resize the map. Must be called with locks held.
+ int resize_i (ACE_UINT32 size);
+
+ /// Close down a <Map_Manager>. Must be called with locks held.
+ int close_i (void);
+
+ /// Returns 1 if <id1> == <id2>, else 0. This is defined as a
+ /// separate method to facilitate template specialization.
+ int equal (const EXT_ID &id1, const EXT_ID &id2);
+
+ /// This function returns the new size of the Map Manager. This
+ /// function is called when we run out of room and need to resize.
+ ACE_UINT32 new_size (void);
+
+ /// Explicitly call the destructors and free up the
+ /// <search_structure_>.
+ void free_search_structure (void);
+
+ /// Id of the free list sentinel.
+ ACE_UINT32 free_list_id (void) const;
+
+ /// Id of the occupied list sentinel.
+ ACE_UINT32 occupied_list_id (void) const;
+
+ /// Finds the next free slot.
+ int next_free (ACE_UINT32 &slot);
+
+ /// Move from free list to occupied list.
+ void move_from_free_list_to_occupied_list (ACE_UINT32 slot);
+
+ /// Move from occupied list to free list.
+ void move_from_occupied_list_to_free_list (ACE_UINT32 slot);
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ /**
+ * In the case of lazy map managers, the movement of free slots from
+ * the occupied list to the free list is delayed until we run out of
+ * free slots in the free list. This function goes through the
+ * entire occupied list, moving free slots to the free list.
+ */
+ void move_all_free_slots_from_occupied_list (void);
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ /// Move helper.
+ void shared_move (ACE_UINT32 slot,
+ ACE_Map_Entry<EXT_ID, INT_ID> &current_list,
+ ACE_UINT32 current_list_id,
+ ACE_Map_Entry<EXT_ID, INT_ID> &new_list,
+ ACE_UINT32 new_list_id);
+
+ /// Pointer to a memory allocator.
+ ACE_Allocator *allocator_;
+
+ /// Synchronization variable for the MT_SAFE ACE_Map_Manager.
+ mutable ACE_LOCK lock_;
+
+ /// Implement the Map as a resizeable array of ACE_Map_Entry.
+ ACE_Map_Entry<EXT_ID, INT_ID> *search_structure_;
+
+ /// Total number of elements in this->search_structure_.
+ ACE_UINT32 total_size_;
+
+ /// Current size of the map.
+ ACE_UINT32 cur_size_;
+
+ /// Free list.
+ ACE_Map_Entry<EXT_ID, INT_ID> free_list_;
+
+ /// Occupied list.
+ ACE_Map_Entry<EXT_ID, INT_ID> occupied_list_;
+
+ enum
+ {
+ /// Grow map exponentially up to 64K
+ MAX_EXPONENTIAL = 64 * 1024,
+
+ /// Afterwards grow in chunks of 32K
+ LINEAR_INCREASE = 32 * 1024
+ };
+
+private:
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Map_Manager (const ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &))
+};
+
+/**
+ * @class ACE_Map_Iterator_Base
+ *
+ * @brief Iterator for the ACE_Map_Manager.
+ *
+ * This class factors out common code from its templatized
+ * subclasses.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Iterator_Base
+{
+public:
+ // = Initialization method.
+ /// Contructor. If head != 0, the iterator constructed is positioned
+ /// at the head of the map, it is positioned at the end otherwise.
+ ACE_Map_Iterator_Base (ACE_Map_Manager <EXT_ID, INT_ID, ACE_LOCK> &mm);
+
+ // = Iteration methods.
+
+ /// Pass back the next <entry> that hasn't been seen in the Set.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Map_Entry<EXT_ID, INT_ID> *&next_entry) const;
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Returns a reference to the interal element @c this is pointing to.
+ ACE_Map_Entry<EXT_ID, INT_ID>& operator* (void) const;
+
+ /// Returns reference the Map_Manager that is being iterated
+ /// over.
+ ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>& map (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> &) const;
+ bool operator!= (const ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Move forward by one element in the set. Returns 0 when there's
+ /// no more item in the set after the current items, else 1.
+ int forward_i (void);
+
+ /// Move backware by one element in the set. Returns 0 when there's
+ /// no more item in the set before the current item, else 1.
+ int reverse_i (void);
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ /// Map we are iterating over.
+ ACE_Map_Manager <EXT_ID, INT_ID, ACE_LOCK> *map_man_;
+
+ /// Keeps track of how far we've advanced...
+ ACE_UINT32 next_;
+};
+
+/**
+ * @class ACE_Map_Const_Iterator_Base
+ *
+ * @brief Const iterator for the ACE_Map_Manager.
+ *
+ * This class factors out common code from its templatized
+ * subclasses.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Const_Iterator_Base
+{
+public:
+ // = Initialization method.
+ /// Contructor. If head != 0, the iterator constructed is positioned
+ /// at the head of the map, it is positioned at the end otherwise.
+ ACE_Map_Const_Iterator_Base (const ACE_Map_Manager <EXT_ID, INT_ID, ACE_LOCK> &mm);
+
+ // = Iteration methods.
+
+ /// Pass back the next <entry> that hasn't been seen in the Set.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Map_Entry<EXT_ID, INT_ID> *&next_entry) const;
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Returns a reference to the interal element @c this is pointing to.
+ ACE_Map_Entry<EXT_ID, INT_ID>& operator* (void) const;
+
+ /// Returns reference the Map_Manager that is being iterated
+ /// over.
+ const ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>& map (void) const;
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> &) const;
+ bool operator!= (const ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Move forward by one element in the set. Returns 0 when there's
+ /// no more item in the set after the current items, else 1.
+ int forward_i (void);
+
+ /// Move backware by one element in the set. Returns 0 when there's
+ /// no more item in the set before the current item, else 1.
+ int reverse_i (void);
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ /// Map we are iterating over.
+ const ACE_Map_Manager <EXT_ID, INT_ID, ACE_LOCK> *map_man_;
+
+ /// Keeps track of how far we've advanced...
+ ACE_UINT32 next_;
+};
+
+/**
+ * @class ACE_Map_Iterator
+ *
+ * @brief Forward iterator for the ACE_Map_Manager.
+ *
+ * This class does not perform any internal locking of the
+ * ACE_Map_Manager it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * ACE_Guard or ACE_Read_Guard on the ACE_Map_Manager's
+ * internal lock, which is accessible via its <mutex> method.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Iterator : public ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>
+{
+public:
+ // = Initialization method.
+ ACE_Map_Iterator (ACE_Map_Manager <EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int pass_end = 0);
+
+ // = Iteration methods.
+
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance.
+ ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Map_Const_Iterator
+ *
+ * @brief Forward const iterator for the ACE_Map_Manager.
+ *
+ * This class does not perform any internal locking of the
+ * ACE_Map_Manager it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * ACE_Guard or ACE_Read_Guard on the ACE_Map_Manager's
+ * internal lock, which is accessible via its <mutex> method.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Const_Iterator : public ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>
+{
+public:
+ // = Initialization method.
+ ACE_Map_Const_Iterator (const ACE_Map_Manager <EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int pass_end = 0);
+
+ // = Iteration methods.
+
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix advance.
+ ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/**
+ * @class ACE_Map_Reverse_Iterator
+ *
+ * @brief Reverse Iterator for the ACE_Map_Manager.
+ *
+ * This class does not perform any internal locking of the
+ * ACE_Map_Manager it is iterating upon since locking is
+ * inherently inefficient and/or error-prone within an STL-style
+ * iterator. If you require locking, you can explicitly use an
+ * ACE_Guard or ACE_Read_Guard on the ACE_Map_Manager's
+ * internal lock, which is accessible via its <mutex> method.
+ */
+template <class EXT_ID, class INT_ID, class ACE_LOCK>
+class ACE_Map_Reverse_Iterator : public ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>
+{
+public:
+ // = Initialization method.
+ ACE_Map_Reverse_Iterator (ACE_Map_Manager <EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int pass_end = 0);
+
+ // = Iteration methods.
+
+ /// 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;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Prefix reverse.
+ ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> &operator++ (void);
+
+ /// Postfix reverse.
+ ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> operator++ (int);
+
+ /// Prefix advance.
+ ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> &operator-- (void);
+
+ /// Postfix advance.
+ ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Map_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Map_Manager.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Map_Manager.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MAP_MANAGER_H */
diff --git a/ACE/ace/Map_Manager.inl b/ACE/ace/Map_Manager.inl
new file mode 100644
index 00000000000..cbbc108bcf2
--- /dev/null
+++ b/ACE/ace/Map_Manager.inl
@@ -0,0 +1,729 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class EXT_ID, class INT_ID> ACE_INLINE
+ACE_Map_Entry<EXT_ID, INT_ID>::ACE_Map_Entry (void)
+ : next_ (0),
+ prev_ (0)
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+ , free_ (1)
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+{
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE
+ACE_Map_Entry<EXT_ID, INT_ID>::~ACE_Map_Entry (void)
+{
+ // No-op just to keep some compilers happy...
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE ACE_UINT32
+ACE_Map_Entry<EXT_ID, INT_ID>::next (void) const
+{
+ return this->next_;
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE void
+ACE_Map_Entry<EXT_ID, INT_ID>::next (ACE_UINT32 n)
+{
+ this->next_ = n;
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE ACE_UINT32
+ACE_Map_Entry<EXT_ID, INT_ID>::prev (void) const
+{
+ return this->prev_;
+}
+
+template <class EXT_ID, class INT_ID> ACE_INLINE void
+ACE_Map_Entry<EXT_ID, INT_ID>::prev (ACE_UINT32 p)
+{
+ this->prev_ = p;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::ACE_Map_Manager (size_t size,
+ ACE_Allocator *alloc)
+ : allocator_ (0),
+ search_structure_ (0),
+ total_size_ (0),
+ cur_size_ (0)
+{
+ if (this->open (size, alloc) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("ACE_Map_Manager\n")));
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::ACE_Map_Manager (ACE_Allocator *alloc)
+ : allocator_ (0),
+ search_structure_ (0),
+ total_size_ (0),
+ cur_size_ (0)
+{
+ if (this->open (ACE_DEFAULT_MAP_SIZE, alloc) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("ACE_Map_Manager\n")));
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::close (void)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->close_i ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::~ACE_Map_Manager (void)
+{
+ this->close ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->bind_i (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id,
+ int_id,
+ old_ext_id,
+ old_int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id,
+ int_id,
+ old_int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->rebind_i (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::trybind (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->trybind_i (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::find (const EXT_ID &ext_id) const
+{
+ ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> *nc_this =
+ (ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> *) this;
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, nc_this->lock_, -1);
+
+ ACE_UINT32 slot = 0;
+ return nc_this->find_and_return_index (ext_id, slot);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::find (const EXT_ID &ext_id,
+ INT_ID &int_id) const
+{
+ ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> *nc_this =
+ (ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> *) this;
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, nc_this->lock_, -1);
+
+ return nc_this->find_i (ext_id, int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_i (const EXT_ID &ext_id)
+{
+ // Unbind the entry.
+ ACE_UINT32 slot = 0;
+ return this->unbind_and_return_index (ext_id,
+ slot);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->unbind_i (ext_id,
+ int_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind (const EXT_ID &ext_id)
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+ return this->unbind_i (ext_id);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE size_t
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::current_size (void) const
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, static_cast<size_t> (-1));
+ return this->cur_size_;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE size_t
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::total_size (void) const
+{
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, static_cast<size_t> (-1));
+ return this->total_size_;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE ACE_LOCK &
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::mutex (void)
+{
+ return this->lock_;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE void
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::move_from_free_list_to_occupied_list (ACE_UINT32 slot)
+{
+ this->shared_move (slot,
+ this->free_list_,
+ this->free_list_id (),
+ this->occupied_list_,
+ this->occupied_list_id ());
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE void
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::move_from_occupied_list_to_free_list (ACE_UINT32 slot)
+{
+ this->shared_move (slot,
+ this->occupied_list_,
+ this->occupied_list_id (),
+ this->free_list_,
+ this->free_list_id ());
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::equal (const EXT_ID &id1,
+ const EXT_ID &id2)
+{
+ return id1 == id2;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE ACE_UINT32
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::free_list_id (void) const
+{
+ // If you change ~0, please change
+ // ACE_Active_Map_Manager_Key::ACE_Active_Map_Manager_Key()
+ // accordingly.
+ return (ACE_UINT32) ~0;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE ACE_UINT32
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::occupied_list_id (void) const
+{
+ return (ACE_UINT32) ~1;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::begin (void)
+{
+ return ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> (*this);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::end (void)
+{
+ return ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> (*this, 1);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rbegin (void)
+{
+ return ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> (*this);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rend (void)
+{
+ return ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> (*this, 1);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::ACE_Map_Iterator_Base (ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm)
+ : map_man_ (&mm),
+ next_ (map_man_->occupied_list_id ())
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::next (ACE_Map_Entry<EXT_ID, INT_ID> *&mm) const
+{
+ if (this->next_ != this->map_man_->occupied_list_id ())
+ {
+ mm = &this->map_man_->search_structure_[this->next_];
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::done (void) const
+{
+ return this->next_ == this->map_man_->occupied_list_id ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::forward_i (void)
+{
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ while (1)
+ {
+ // Go to the next item in the list.
+ this->next_ = this->map_man_->search_structure_[this->next_].next ();
+
+ // Stop if we reach the end.
+ if (this->done ())
+ break;
+
+ // Break if we find a non-free slot.
+ if (!this->map_man_->search_structure_[this->next_].free_)
+ {
+ break;
+ }
+ }
+
+#else
+
+ this->next_ = this->map_man_->search_structure_[this->next_].next ();
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ return this->next_ != this->map_man_->occupied_list_id ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::reverse_i (void)
+{
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ while (1)
+ {
+ // Go to the prev item in the list.
+ this->next_ = this->map_man_->search_structure_[this->next_].prev ();
+
+ // Stop if we reach the end.
+ if (this->done ())
+ break;
+
+ // Break if we find a non-free slot.
+ if (!this->map_man_->search_structure_[this->next_].free_)
+ {
+ break;
+ }
+ }
+
+#else
+
+ this->next_ = this->map_man_->search_structure_[this->next_].prev ();
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ return this->next_ != this->map_man_->occupied_list_id ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::map (void)
+{
+ return *this->map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE bool
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::operator== (const ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> &rhs) const
+{
+ return (this->map_man_ == rhs.map_man_ &&
+ this->next_ == rhs.next_);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE bool
+ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::operator!= (const ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::ACE_Map_Const_Iterator_Base (const ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm)
+ : map_man_ (&mm),
+ next_ (this->map_man_->occupied_list_id ())
+{
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::next (ACE_Map_Entry<EXT_ID, INT_ID> *&mm) const
+{
+ if (this->next_ != this->map_man_->occupied_list_id ())
+ {
+ mm = &this->map_man_->search_structure_[this->next_];
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::done (void) const
+{
+ return this->next_ == this->map_man_->occupied_list_id ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::forward_i (void)
+{
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ while (1)
+ {
+ // Go to the next item in the list.
+ this->next_ = this->map_man_->search_structure_[this->next_].next ();
+
+ // Stop if we reach the end.
+ if (this->done ())
+ break;
+
+ // Break if we find a non-free slot.
+ if (!this->map_man_->search_structure_[this->next_].free_)
+ {
+ break;
+ }
+ }
+
+#else
+
+ this->next_ = this->map_man_->search_structure_[this->next_].next ();
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ return this->next_ != this->map_man_->occupied_list_id ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::reverse_i (void)
+{
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ while (1)
+ {
+ // Go to the prev item in the list.
+ this->next_ = this->map_man_->search_structure_[this->next_].prev ();
+
+ // Stop if we reach the end.
+ if (this->done ())
+ break;
+
+ // Break if we find a non-free slot.
+ if (!this->map_man_->search_structure_[this->next_].free_)
+ {
+ break;
+ }
+ }
+
+#else
+
+ this->next_ = this->map_man_->search_structure_[this->next_].prev ();
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ return this->next_ != this->map_man_->occupied_list_id ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+const ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::map (void) const
+{
+ return *this->map_man_;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE bool
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::operator== (const ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> &rhs) const
+{
+ return (this->map_man_ == rhs.map_man_ &&
+ this->next_ == rhs.next_);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE bool
+ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::operator!= (const ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Map_Iterator (ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int pass_end)
+ : ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> (mm)
+{
+ if (!pass_end)
+ {
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ // Start here.
+ this->next_ = this->map_man_->occupied_list_.next ();
+
+ while (1)
+ {
+ // Stop if we reach the end.
+ if (this->done ())
+ break;
+
+ // Break if we find a non-free slot.
+ if (!this->map_man_->search_structure_[this->next_].free_)
+ {
+ break;
+ }
+
+ // Go to the next item in the list.
+ this->next_ = this->map_man_->search_structure_[this->next_].next ();
+ }
+
+#else
+
+ this->next_ = this->map_man_->occupied_list_.next ();
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ }
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::advance (void)
+{
+ return this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator++ (void)
+{
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator++ (int)
+{
+ ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator-- (void)
+{
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator-- (int)
+{
+ ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Map_Const_Iterator (const ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int pass_end)
+ : ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> (mm)
+{
+ if (!pass_end)
+ {
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ // Start here.
+ this->next_ = this->map_man_->occupied_list_.next ();
+
+ while (1)
+ {
+ // Stop if we reach the end.
+ if (this->done ())
+ break;
+
+ // Break if we find a non-free slot.
+ if (!this->map_man_->search_structure_[this->next_].free_)
+ {
+ break;
+ }
+
+ // Go to the next item in the list.
+ this->next_ = this->map_man_->search_structure_[this->next_].next ();
+ }
+
+#else
+
+ this->next_ = this->map_man_->occupied_list_.next ();
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+ }
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::advance (void)
+{
+ return this->forward_i ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator++ (void)
+{
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator++ (int)
+{
+ ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator-- (void)
+{
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator-- (int)
+{
+ ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::ACE_Map_Reverse_Iterator (ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &mm,
+ int pass_end)
+ : ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK> (mm)
+{
+ if (!pass_end)
+ {
+
+#if defined (ACE_HAS_LAZY_MAP_MANAGER)
+
+ // Start here.
+ this->next_ = this->map_man_->occupied_list_.prev ();
+
+ while (1)
+ {
+ // Stop if we reach the end.
+ if (this->done ())
+ break;
+
+ // Break if we find a non-free slot.
+ if (!this->map_man_->search_structure_[this->next_].free_)
+ {
+ break;
+ }
+
+ // Go to the prev item in the list.
+ this->next_ = this->map_man_->search_structure_[this->next_].prev ();
+ }
+
+#else
+
+ this->next_ = this->map_man_->occupied_list_.prev ();
+
+#endif /* ACE_HAS_LAZY_MAP_MANAGER */
+
+}
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE int
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::advance (void)
+{
+ return this->reverse_i ();
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator++ (void)
+{
+ this->reverse_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator++ (int)
+{
+ ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> &
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator-- (void)
+{
+ this->forward_i ();
+ return *this;
+}
+
+template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_INLINE
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>
+ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::operator-- (int)
+{
+ ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Map_T.cpp b/ACE/ace/Map_T.cpp
new file mode 100644
index 00000000000..2487481edc3
--- /dev/null
+++ b/ACE/ace/Map_T.cpp
@@ -0,0 +1,1343 @@
+// $Id$
+
+#ifndef ACE_MAP_T_CPP
+#define ACE_MAP_T_CPP
+
+#include "ace/Map_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Map_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class KEY, class VALUE>
+ACE_Map<KEY, VALUE>::~ACE_Map (void)
+{
+}
+
+template <class T>
+ACE_Iterator_Impl<T>::~ACE_Iterator_Impl (void)
+{
+}
+
+template <class T>
+ACE_Reverse_Iterator_Impl<T>::~ACE_Reverse_Iterator_Impl (void)
+{
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY>
+ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::~ACE_Map_Impl_Iterator_Adapter (void)
+{
+}
+
+
+template <class T, class IMPLEMENTATION, class ENTRY> ACE_Iterator_Impl<T> *
+ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::clone (void) const
+{
+ ACE_Iterator_Impl<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>) (*this),
+ 0);
+ return temp;
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> int
+ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::compare (const ACE_Iterator_Impl<T> &rhs) const
+{
+ const ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY> &rhs_local
+ = dynamic_cast<const ACE_Map_Impl_Iterator_Adapter< T, IMPLEMENTATION, ENTRY> &> (rhs);
+
+ return this->implementation_ == rhs_local.implementation_;
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> T
+ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::dereference () const
+{
+ ENTRY &entry = *this->implementation_;
+ return T (entry.ext_id_,
+ entry.int_id_);
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> void
+ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::plus_plus (void)
+{
+ ++this->implementation_;
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> void
+ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::minus_minus (void)
+{
+ --this->implementation_;
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY>
+ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::~ACE_Map_Impl_Reverse_Iterator_Adapter (void)
+{
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> ACE_Reverse_Iterator_Impl<T> *
+ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::clone (void) const
+{
+ ACE_Reverse_Iterator_Impl<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>) (*this),
+ 0);
+ return temp;
+}
+
+
+template <class T, class IMPLEMENTATION, class ENTRY> int
+ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const
+{
+ const ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY> &rhs_local
+ = dynamic_cast<const ACE_Map_Impl_Reverse_Iterator_Adapter< T, IMPLEMENTATION, ENTRY> &> (rhs);
+
+ return this->implementation_ == rhs_local.implementation_;
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> T
+ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::dereference () const
+{
+ ENTRY &entry = *this->implementation_;
+ return T (entry.ext_id_,
+ entry.int_id_);
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> void
+ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::plus_plus (void)
+{
+ ++this->implementation_;
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> void
+ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::minus_minus (void)
+{
+ --this->implementation_;
+}
+
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY>
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::~ACE_Map_Impl (void)
+{
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::open (size_t length,
+ ACE_Allocator *alloc)
+{
+ return this->implementation_.open (length,
+ alloc);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::close (void)
+{
+ return this->implementation_.close ();
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::bind (const KEY &key,
+ const VALUE &value)
+{
+ return this->implementation_.bind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::bind_modify_key (const VALUE &value,
+ KEY &key)
+{
+ return this->implementation_.bind_modify_key (value,
+ key);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::create_key (KEY &key)
+{
+ return this->implementation_.create_key (key);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::bind_create_key (const VALUE &value,
+ KEY &key)
+{
+ return this->implementation_.bind_create_key (value,
+ key);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::bind_create_key (const VALUE &value)
+{
+ return this->implementation_.bind_create_key (value);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::recover_key (const KEY &modified_key,
+ KEY &original_key)
+{
+ return this->implementation_.recover_key (modified_key,
+ original_key);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::rebind (const KEY &key,
+ const VALUE &value)
+{
+ return this->implementation_.rebind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value)
+{
+ return this->implementation_.rebind (key,
+ value,
+ old_value);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value)
+{
+ return this->implementation_.rebind (key,
+ value,
+ old_key,
+ old_value);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::trybind (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.trybind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::find (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.find (key,
+ value);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::find (const KEY &key)
+{
+ return this->implementation_.find (key);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::unbind (const KEY &key)
+{
+ return this->implementation_.unbind (key);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> int
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::unbind (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.unbind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> size_t
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::current_size (void) const
+{
+ return this->implementation_.current_size ();
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> size_t
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::total_size (void) const
+{
+ return this->implementation_.total_size ();
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> void
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->implementation_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::begin_impl (void)
+{
+ ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ iterator_impl (this->implementation_.begin ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::end_impl (void)
+{
+ ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ iterator_impl (this->implementation_.end ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::rbegin_impl (void)
+{
+ ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ reverse_iterator_impl (this->implementation_.rbegin ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::rend_impl (void)
+{
+ ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ reverse_iterator_impl (this->implementation_.rend ()),
+ 0);
+ return temp;
+}
+
+template <class T, class VALUE>
+ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>::~ACE_Active_Map_Manager_Iterator_Adapter (void)
+{
+}
+
+template <class T, class VALUE> ACE_Iterator_Impl<T> *
+ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>::clone (void) const
+{
+ ACE_Iterator_Impl<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>) (*this),
+ 0);
+ return temp;
+}
+
+
+template <class T, class VALUE> int
+ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>::compare (const ACE_Iterator_Impl<T> &rhs) const
+{
+ const ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE> &rhs_local
+ = dynamic_cast<const ACE_Active_Map_Manager_Iterator_Adapter< T, VALUE> &> (rhs);
+
+ return this->implementation_ == rhs_local.implementation_;
+}
+
+template <class T, class VALUE> T
+ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>::dereference () const
+{
+ // The following syntax is necessary to work around certain broken compilers.
+ // In particular, please do not prefix implementation_ with this->
+ return T ((*implementation_).int_id_.first (),
+ (*implementation_).int_id_.second ());
+}
+
+template <class T, class VALUE> void
+ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>::plus_plus (void)
+{
+ ++this->implementation_;
+}
+
+template <class T, class VALUE> void
+ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>::minus_minus (void)
+{
+ --this->implementation_;
+}
+
+template <class T, class VALUE>
+ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>::~ACE_Active_Map_Manager_Reverse_Iterator_Adapter (void)
+{
+}
+
+template <class T, class VALUE> ACE_Reverse_Iterator_Impl<T> *
+ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>::clone (void) const
+{
+ ACE_Reverse_Iterator_Impl<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>) (*this),
+ 0);
+ return temp;
+}
+
+
+template <class T, class VALUE> int
+ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>::compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const
+{
+ const ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE> &rhs_local
+ = dynamic_cast<const ACE_Active_Map_Manager_Reverse_Iterator_Adapter< T, VALUE> &> (rhs);
+
+ return this->implementation_ == rhs_local.implementation_;
+}
+
+template <class T, class VALUE> T
+ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>::dereference () const
+{
+ // The following syntax is necessary to work around certain broken compilers.
+ // In particular, please do not prefix implementation_ with this->
+ return T ((*implementation_).int_id_.first (),
+ (*implementation_).int_id_.second ());
+}
+
+template <class T, class VALUE> void
+ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>::plus_plus (void)
+{
+ ++this->implementation_;
+}
+
+template <class T, class VALUE> void
+ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>::minus_minus (void)
+{
+ --this->implementation_;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER>
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::~ACE_Active_Map_Manager_Adapter (void)
+{
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::open (size_t length,
+ ACE_Allocator *alloc)
+{
+ return this->implementation_.open (length,
+ alloc);
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::close (void)
+{
+ return this->implementation_.close ();
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::bind (const KEY &,
+ const VALUE &)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::bind_modify_key (const VALUE &value,
+ KEY &key)
+{
+ // Reserve a slot and create an active key.
+ expanded_value *internal_value = 0;
+ ACE_Active_Map_Manager_Key active_key;
+ int result = this->implementation_.bind (active_key,
+ internal_value);
+ if (result == 0)
+ {
+ // Encode the active key and the existing user key into key part
+ // of <expanded_value>.
+ result = this->key_adapter_.encode (key,
+ active_key,
+ internal_value->first ());
+ if (result == 0)
+ {
+ // Copy user value into <expanded_value>.
+ internal_value->second (value);
+ // Copy new, modified key back to the user key.
+ key = internal_value->first ();
+ }
+ else
+ {
+ // In case of errors, unbind from map.
+ this->implementation_.unbind (active_key);
+ }
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::create_key (KEY &)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::bind_create_key (const VALUE &value,
+ KEY &key)
+{
+ // Reserve a slot and create an active key.
+ expanded_value *internal_value = 0;
+ ACE_Active_Map_Manager_Key active_key;
+ int result = this->implementation_.bind (active_key,
+ internal_value);
+ if (result == 0)
+ {
+ // Encode the active key into key part of <expanded_value>.
+ result = this->key_adapter_.encode (internal_value->first (),
+ active_key,
+ internal_value->first ());
+ if (result == 0)
+ {
+ // Copy user value into <expanded_value>.
+ internal_value->second (value);
+ // Copy new, modified key to the user key.
+ key = internal_value->first ();
+ }
+ else
+ {
+ // In case of errors, unbind from map.
+ this->implementation_.unbind (active_key);
+ }
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::bind_create_key (const VALUE &value)
+{
+ // Reserve a slot and create an active key.
+ expanded_value *internal_value = 0;
+ ACE_Active_Map_Manager_Key active_key;
+ int result = this->implementation_.bind (active_key,
+ internal_value);
+ if (result == 0)
+ {
+ // Encode the active key into key part of <expanded_value>.
+ result = this->key_adapter_.encode (internal_value->first (),
+ active_key,
+ internal_value->first ());
+ if (result == 0)
+ {
+ // Copy user value into <expanded_value>.
+ internal_value->second (value);
+ }
+ else
+ {
+ // In case of errors, unbind from map.
+ this->implementation_.unbind (active_key);
+ }
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::recover_key (const KEY &modified_key,
+ KEY &original_key)
+{
+ // Ask the <key_adapter_> to help out with recovering the original
+ // user key, since it was the one that encode it in the first place.
+ return this->key_adapter_.decode (modified_key,
+ original_key);
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::find (const KEY &key,
+ expanded_value *&internal_value)
+{
+ // Ask the <key_adapter_> to recover the active key.
+ ACE_Active_Map_Manager_Key active_key;
+ int result = this->key_adapter_.decode (key,
+ active_key);
+ if (result == 0)
+ {
+ // Find recovered active key in map.
+ result = this->implementation_.find (active_key,
+ internal_value);
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::find (const KEY &key,
+ VALUE &value)
+{
+ expanded_value *internal_value = 0;
+ int result = this->find (key,
+ internal_value);
+
+ if (result == 0)
+ {
+ // Copy value.
+ value = internal_value->second ();
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::find (const KEY &key)
+{
+ expanded_value *internal_value = 0;
+ return this->find (key,
+ internal_value);
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::rebind (const KEY &key,
+ const VALUE &value)
+{
+ expanded_value *internal_value = 0;
+ int result = this->find (key,
+ internal_value);
+
+ if (result == 0)
+ {
+ // Reset value.
+ internal_value->second (value);
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value)
+{
+ expanded_value *internal_value = 0;
+ int result = this->find (key,
+ internal_value);
+
+ if (result == 0)
+ {
+ // Copy old value.
+ old_value = internal_value->second ();
+
+ // Reset to new value.
+ internal_value->second (value);
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value)
+{
+ expanded_value *internal_value = 0;
+ int result = this->find (key,
+ internal_value);
+
+ if (result == 0)
+ {
+ // Copy old key and value.
+ old_key = internal_value->first ();
+ old_value = internal_value->second ();
+
+ // Reset to new value.
+ internal_value->second (value);
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::trybind (const KEY &,
+ VALUE &)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::unbind (const KEY &key,
+ expanded_value *&internal_value)
+{
+ // Ask the <key_adapter_> to recover the active key.
+ ACE_Active_Map_Manager_Key active_key;
+ int result = this->key_adapter_.decode (key,
+ active_key);
+ if (result == 0)
+ {
+ // Unbind recovered active key from map.
+ result = this->implementation_.unbind (active_key,
+ internal_value);
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::unbind (const KEY &key)
+{
+ expanded_value *internal_value = 0;
+ return this->unbind (key,
+ internal_value);
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> int
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::unbind (const KEY &key,
+ VALUE &value)
+{
+ expanded_value *internal_value = 0;
+ int result = this->unbind (key,
+ internal_value);
+
+ if (result == 0)
+ {
+ // Copy value.
+ value = internal_value->second ();
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> size_t
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::current_size (void) const
+{
+ return this->implementation_.current_size ();
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> size_t
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::total_size (void) const
+{
+ return this->implementation_.total_size ();
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> void
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->implementation_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::begin_impl (void)
+{
+ ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ iterator_impl (this->implementation_.begin ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::end_impl (void)
+{
+ ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ iterator_impl (this->implementation_.end ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::rbegin_impl (void)
+{
+ ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ reverse_iterator_impl (this->implementation_.rbegin ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::rend_impl (void)
+{
+ ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ reverse_iterator_impl (this->implementation_.rend ()),
+ 0);
+ return temp;
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS>
+ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::~ACE_Hash_Map_Manager_Ex_Iterator_Adapter (void)
+{
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> ACE_Iterator_Impl<T> *
+ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::clone (void) const
+{
+ ACE_Iterator_Impl<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>) (*this),
+ 0);
+ return temp;
+}
+
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> int
+ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::compare (const ACE_Iterator_Impl<T> &rhs) const
+{
+ const ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS> &rhs_local
+ = dynamic_cast<const ACE_Hash_Map_Manager_Ex_Iterator_Adapter< T, KEY, VALUE, HASH_KEY, COMPARE_KEYS> &> (rhs);
+
+ return this->implementation_ == rhs_local.implementation_;
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> T
+ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::dereference () const
+{
+ // The following syntax is necessary to work around certain broken compilers.
+ // In particular, please do not prefix implementation_ with this->
+ return T ((*implementation_).ext_id_,
+ (*implementation_).int_id_);
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> void
+ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::plus_plus (void)
+{
+ ++this->implementation_;
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> void
+ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::minus_minus (void)
+{
+ --this->implementation_;
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS>
+ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::~ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter (void)
+{
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> ACE_Reverse_Iterator_Impl<T> *
+ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::clone (void) const
+{
+ ACE_Reverse_Iterator_Impl<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>) (*this),
+ 0);
+ return temp;
+}
+
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> int
+ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const
+{
+ const ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS> &rhs_local
+ = dynamic_cast<const ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter< T, KEY, VALUE, HASH_KEY, COMPARE_KEYS> &> (rhs);
+
+ return this->implementation_ == rhs_local.implementation_;
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> T
+ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::dereference () const
+{
+ // The following syntax is necessary to work around certain broken compilers.
+ // In particular, please do not prefix implementation_ with this->
+ return T ((*implementation_).ext_id_,
+ (*implementation_).int_id_);
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> void
+ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::plus_plus (void)
+{
+ ++this->implementation_;
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> void
+ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::minus_minus (void)
+{
+ --this->implementation_;
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR>
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::~ACE_Hash_Map_Manager_Ex_Adapter (void)
+{
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::open (size_t length,
+ ACE_Allocator *alloc)
+{
+ return this->implementation_.open (length,
+ alloc);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::close (void)
+{
+ return this->implementation_.close ();
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::bind (const KEY &key,
+ const VALUE &value)
+{
+ return this->implementation_.bind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::bind_modify_key (const VALUE &value,
+ KEY &key)
+{
+ return this->implementation_.bind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::create_key (KEY &key)
+{
+ // Invoke the user specified key generation functor.
+ return this->key_generator_ (key);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::bind_create_key (const VALUE &value,
+ KEY &key)
+{
+ // Invoke the user specified key generation functor.
+ int result = this->key_generator_ (key);
+
+ if (result == 0)
+ {
+ // Try to add.
+ result = this->implementation_.bind (key,
+ value);
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::bind_create_key (const VALUE &value)
+{
+ KEY key;
+ return this->bind_create_key (value,
+ key);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::recover_key (const KEY &modified_key,
+ KEY &original_key)
+{
+ original_key = modified_key;
+ return 0;
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::rebind (const KEY &key,
+ const VALUE &value)
+{
+ return this->implementation_.rebind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value)
+{
+ return this->implementation_.rebind (key,
+ value,
+ old_value);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value)
+{
+ return this->implementation_.rebind (key,
+ value,
+ old_key,
+ old_value);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::trybind (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.trybind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::find (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.find (key,
+ value);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::find (const KEY &key)
+{
+ return this->implementation_.find (key);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::unbind (const KEY &key)
+{
+ return this->implementation_.unbind (key);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> int
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::unbind (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.unbind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> size_t
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::current_size (void) const
+{
+ return this->implementation_.current_size ();
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> size_t
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::total_size (void) const
+{
+ return this->implementation_.total_size ();
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> void
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->implementation_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::begin_impl (void)
+{
+ ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ iterator_impl (this->implementation_.begin ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::end_impl (void)
+{
+ ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ iterator_impl (this->implementation_.end ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::rbegin_impl (void)
+{
+ ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ reverse_iterator_impl (this->implementation_.rbegin ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::rend_impl (void)
+{
+ ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ reverse_iterator_impl (this->implementation_.rend ()),
+ 0);
+ return temp;
+}
+
+template <class T, class KEY, class VALUE>
+ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>::~ACE_Map_Manager_Iterator_Adapter (void)
+{
+}
+
+template <class T, class KEY, class VALUE> ACE_Iterator_Impl<T> *
+ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>::clone (void) const
+{
+ ACE_Iterator_Impl<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>) (*this),
+ 0);
+ return temp;
+}
+
+
+template <class T, class KEY, class VALUE> int
+ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>::compare (const ACE_Iterator_Impl<T> &rhs) const
+{
+ const ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE> &rhs_local
+ = dynamic_cast<const ACE_Map_Manager_Iterator_Adapter< T, KEY, VALUE> &> (rhs);
+
+ return this->implementation_ == rhs_local.implementation_;
+}
+
+template <class T, class KEY, class VALUE> T
+ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>::dereference () const
+{
+ // The following syntax is necessary to work around certain broken compilers.
+ // In particular, please do not prefix implementation_ with this->
+ return T ((*implementation_).ext_id_,
+ (*implementation_).int_id_);
+}
+
+template <class T, class KEY, class VALUE> void
+ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>::plus_plus (void)
+{
+ ++this->implementation_;
+}
+
+template <class T, class KEY, class VALUE> void
+ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>::minus_minus (void)
+{
+ --this->implementation_;
+}
+
+template <class T, class KEY, class VALUE>
+ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>::~ACE_Map_Manager_Reverse_Iterator_Adapter (void)
+{
+}
+
+template <class T, class KEY, class VALUE> ACE_Reverse_Iterator_Impl<T> *
+ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>::clone (void) const
+{
+ ACE_Reverse_Iterator_Impl<T> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>) (*this),
+ 0);
+ return temp;
+}
+
+
+template <class T, class KEY, class VALUE> int
+ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>::compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const
+{
+ const ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE> &rhs_local
+ = dynamic_cast<const ACE_Map_Manager_Reverse_Iterator_Adapter< T, KEY, VALUE> &> (rhs);
+
+ return this->implementation_ == rhs_local.implementation_;
+}
+
+template <class T, class KEY, class VALUE> T
+ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>::dereference () const
+{
+ // The following syntax is necessary to work around certain broken compilers.
+ // In particular, please do not prefix implementation_ with this->
+ return T ((*implementation_).ext_id_,
+ (*implementation_).int_id_);
+}
+
+template <class T, class KEY, class VALUE> void
+ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>::plus_plus (void)
+{
+ ++this->implementation_;
+}
+
+template <class T, class KEY, class VALUE> void
+ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>::minus_minus (void)
+{
+ --this->implementation_;
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR>
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::~ACE_Map_Manager_Adapter (void)
+{
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::open (size_t length,
+ ACE_Allocator *alloc)
+{
+ return this->implementation_.open (length,
+ alloc);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::close (void)
+{
+ return this->implementation_.close ();
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::bind (const KEY &key,
+ const VALUE &value)
+{
+ return this->implementation_.bind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::bind_modify_key (const VALUE &value,
+ KEY &key)
+{
+ return this->implementation_.bind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::create_key (KEY &key)
+{
+ // Invoke the user specified key generation functor.
+ return this->key_generator_ (key);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::bind_create_key (const VALUE &value,
+ KEY &key)
+{
+ // Invoke the user specified key generation functor.
+ int result = this->key_generator_ (key);
+
+ if (result == 0)
+ {
+ // Try to add.
+ result = this->implementation_.bind (key,
+ value);
+ }
+
+ return result;
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::bind_create_key (const VALUE &value)
+{
+ KEY key;
+ return this->bind_create_key (value,
+ key);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::recover_key (const KEY &modified_key,
+ KEY &original_key)
+{
+ original_key = modified_key;
+ return 0;
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::rebind (const KEY &key,
+ const VALUE &value)
+{
+ return this->implementation_.rebind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value)
+{
+ return this->implementation_.rebind (key,
+ value,
+ old_value);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value)
+{
+ return this->implementation_.rebind (key,
+ value,
+ old_key,
+ old_value);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::trybind (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.trybind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::find (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.find (key,
+ value);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::find (const KEY &key)
+{
+ return this->implementation_.find (key);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::unbind (const KEY &key)
+{
+ return this->implementation_.unbind (key);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> int
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::unbind (const KEY &key,
+ VALUE &value)
+{
+ return this->implementation_.unbind (key,
+ value);
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> size_t
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::current_size (void) const
+{
+ return this->implementation_.current_size ();
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> size_t
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::total_size (void) const
+{
+ return this->implementation_.total_size ();
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> void
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ this->implementation_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::begin_impl (void)
+{
+ ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ iterator_impl (this->implementation_.begin ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::end_impl (void)
+{
+ ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ iterator_impl (this->implementation_.end ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::rbegin_impl (void)
+{
+ ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ reverse_iterator_impl (this->implementation_.rbegin ()),
+ 0);
+ return temp;
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::rend_impl (void)
+{
+ ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *temp = 0;
+ ACE_NEW_RETURN (temp,
+ reverse_iterator_impl (this->implementation_.rend ()),
+ 0);
+ return temp;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_MAP_T_CPP */
diff --git a/ACE/ace/Map_T.h b/ACE/ace/Map_T.h
new file mode 100644
index 00000000000..142d07803ce
--- /dev/null
+++ b/ACE/ace/Map_T.h
@@ -0,0 +1,1611 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Map_T.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MAP_T_H
+#define ACE_MAP_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Pair_T.h"
+#include "ace/Map_Manager.h"
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Active_Map_Manager.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Noop_Key_Generator
+ *
+ * @brief Defines a noop key generator.
+ */
+template <class T>
+class ACE_Noop_Key_Generator
+{
+public:
+
+ /// Functor method: generates a new key.
+ int operator () (T &);
+};
+
+/**
+ * @class ACE_Incremental_Key_Generator
+ *
+ * @brief Defines a simple incremental key generator.
+ *
+ * Generates a new key of type T by incrementing current
+ * value. Requirements on T are:
+ * - Constructor that accepts 0 in the constructor.
+ * - Prefix increment.
+ * - Assignment.
+ * Note that a primitive types such as u_long, int, etc., are
+ * suitable for this class.
+ */
+template <class T>
+class ACE_Incremental_Key_Generator
+{
+public:
+
+ /// Constructor.
+ ACE_Incremental_Key_Generator (void);
+
+ /// Functor method: generates a new key.
+ int operator () (T &t);
+
+ /// Returns the current value.
+ const T& current_value (void) const;
+
+protected:
+
+ /// Current value.
+ T t_;
+};
+
+/**
+ * @class ACE_Iterator_Impl
+ *
+ * @brief Defines a abstract iterator.
+ *
+ * Implementation to be provided by subclasses.
+ */
+template <class T>
+class ACE_Iterator_Impl
+{
+public:
+
+ /// Destructor.
+ virtual ~ACE_Iterator_Impl (void);
+
+ /// Clone.
+ virtual ACE_Iterator_Impl<T> *clone (void) const = 0;
+
+ /// Comparison.
+ virtual int compare (const ACE_Iterator_Impl<T> &rhs) const = 0;
+
+ /// Dereference.
+ virtual T dereference (void) const = 0;
+
+ /// Advance.
+ virtual void plus_plus (void) = 0;
+
+ /// Reverse.
+ virtual void minus_minus (void) = 0;
+};
+
+/**
+ * @class ACE_Reverse_Iterator_Impl
+ *
+ * @brief Defines a abstract reverse iterator.
+ *
+ * Implementation to be provided by subclasses.
+ */
+template <class T>
+class ACE_Reverse_Iterator_Impl
+{
+public:
+
+ /// Destructor.
+ virtual ~ACE_Reverse_Iterator_Impl (void);
+
+ /// Clone.
+ virtual ACE_Reverse_Iterator_Impl<T> *clone (void) const = 0;
+
+ /// Comparison.
+ virtual int compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const = 0;
+
+ /// Dereference.
+ virtual T dereference (void) const = 0;
+
+ /// Advance.
+ virtual void plus_plus (void) = 0;
+
+ /// Reverse.
+ virtual void minus_minus (void) = 0;
+};
+
+/**
+ * @class ACE_Iterator
+ *
+ * @brief Defines the iterator interface.
+ *
+ * Implementation to be provided by forwarding.
+ */
+template <class T>
+class ACE_Iterator
+{
+public:
+
+ // = Traits.
+ typedef T value_type;
+ typedef ACE_Iterator_Impl<T> implementation;
+
+ /// Constructor.
+ ACE_Iterator (ACE_Iterator_Impl<T> *impl);
+
+ /// Copy constructor.
+ ACE_Iterator (const ACE_Iterator<T> &rhs);
+
+ /// Destructor.
+ ~ACE_Iterator (void);
+
+ /// Assignment operator.
+ ACE_Iterator<T> &operator= (const ACE_Iterator<T> &rhs);
+
+ /// Comparison operators.
+ bool operator== (const ACE_Iterator<T> &rhs) const;
+ bool operator!= (const ACE_Iterator<T> &rhs) const;
+
+ /// Dereference operator.
+ T operator *() const;
+
+ /// Prefix advance.
+ ACE_Iterator<T> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Iterator<T> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Iterator<T> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Iterator<T> operator-- (int);
+
+ /// Accessor to implementation object.
+ ACE_Iterator_Impl<T> &impl (void);
+
+protected:
+
+ /// Implementation pointer.
+ ACE_Iterator_Impl<T> *implementation_;
+};
+
+/**
+ * @class ACE_Reverse_Iterator
+ *
+ * @brief Defines the reverse iterator interface.
+ *
+ * Implementation to be provided by forwarding.
+ */
+template <class T>
+class ACE_Reverse_Iterator
+{
+public:
+
+ // = Traits.
+ typedef T value_type;
+ typedef ACE_Reverse_Iterator_Impl<T> implementation;
+
+ /// Constructor.
+ ACE_Reverse_Iterator (ACE_Reverse_Iterator_Impl<T> *impl);
+
+ /// Copy constructor.
+ ACE_Reverse_Iterator (const ACE_Reverse_Iterator<T> &rhs);
+
+ /// Destructor.
+ ~ACE_Reverse_Iterator (void);
+
+ /// Assignment operator.
+ ACE_Reverse_Iterator<T> &operator= (const ACE_Reverse_Iterator<T> &rhs);
+
+ /**
+ * @name Comparison Operators
+ *
+ * The usual equality operators.
+ */
+ //@{
+ bool operator== (const ACE_Reverse_Iterator<T> &rhs) const;
+ bool operator!= (const ACE_Reverse_Iterator<T> &rhs) const;
+ //@}
+
+ /// Dereference operator.
+ T operator *() const;
+
+ /// Prefix advance.
+ ACE_Reverse_Iterator<T> &operator++ (void);
+
+ /// Postfix advance.
+ ACE_Reverse_Iterator<T> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_Reverse_Iterator<T> &operator-- (void);
+
+ /// Postfix reverse.
+ ACE_Reverse_Iterator<T> operator-- (int);
+
+ /// Accessor to implementation object.
+ ACE_Reverse_Iterator_Impl<T> &impl (void);
+
+protected:
+
+ /// Implementation pointer.
+ ACE_Reverse_Iterator_Impl<T> *implementation_;
+};
+
+/**
+ * @class ACE_Map
+ *
+ * @brief Defines a map interface.
+ *
+ * Implementation to be provided by subclasses.
+ */
+template <class KEY, class VALUE>
+class ACE_Map
+{
+public:
+
+ // = Traits.
+ typedef KEY
+ key_type;
+ typedef VALUE
+ mapped_type;
+ typedef ACE_Reference_Pair<const KEY, VALUE>
+ value_type;
+ typedef ACE_Iterator<value_type>
+ iterator;
+ typedef ACE_Reverse_Iterator<value_type>
+ reverse_iterator;
+ typedef ACE_Iterator_Impl<value_type>
+ iterator_implementation;
+ typedef ACE_Reverse_Iterator_Impl<value_type>
+ reverse_iterator_implementation;
+
+ /// Close down and release dynamically allocated resources.
+ virtual ~ACE_Map (void);
+
+ /// Initialize a map with size @a length.
+ virtual int open (size_t length = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0) = 0;
+
+ /// Close down a <Map> and release dynamically allocated resources.
+ virtual int close (void) = 0;
+
+ /**
+ * Add @a key / @a value pair to the map. If @a key is already in the
+ * map then no changes are made and 1 is returned. Returns 0 on a
+ * successful addition. This function fails for maps that do not
+ * allow user specified keys. @a key is an "in" parameter.
+ */
+ virtual int bind (const KEY &key,
+ const VALUE &value) = 0;
+
+ /**
+ * Add @a key / @a value pair to the map. @a key is an "inout" parameter
+ * and maybe modified/extended by the map to add additional
+ * information. To recover original key, call the <recover_key>
+ * method.
+ */
+ virtual int bind_modify_key (const VALUE &value,
+ KEY &key) = 0;
+
+ /**
+ * Produce a key and return it through @a key which is an "out"
+ * parameter. For maps that do not naturally produce keys, the map
+ * adapters will use the @c KEY_GENERATOR class to produce a key.
+ * However, the users are responsible for not jeopardizing this key
+ * production scheme by using user specified keys with keys produced
+ * by the key generator.
+ */
+ virtual int create_key (KEY &key) = 0;
+
+ /**
+ * Add @a value to the map, and the corresponding key produced by the
+ * Map is returned through @a key which is an "out" parameter. For
+ * maps that do not naturally produce keys, the map adapters will
+ * use the @c KEY_GENERATOR class to produce a key. However, the
+ * users are responsible for not jeopardizing this key production
+ * scheme by using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value,
+ KEY &key) = 0;
+
+ /**
+ * Add @a value to the map. The user does not care about the
+ * corresponding key produced by the Map. For maps that do not
+ * naturally produce keys, the map adapters will use the
+ * @c KEY_GENERATOR class to produce a key. However, the users are
+ * responsible for not jeopardizing this key production scheme by
+ * using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value) = 0;
+
+ /// Recovers the original key potentially modified by the map during
+ /// <bind_modify_key>.
+ virtual int recover_key (const KEY &modified_key,
+ KEY &original_key) = 0;
+
+ /**
+ * Reassociate @a key with @a value. The function fails if @a key is
+ * not in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value) = 0;
+
+ /**
+ * Reassociate @a key with @a value, storing the old value into the
+ * "out" parameter @a old_value. The function fails if @a key is not
+ * in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value) = 0;
+
+ /**
+ * Reassociate @a key with @a value, storing the old key and value
+ * into the "out" parameters @a old_key and @a old_value. The
+ * function fails if @a key is not in the map for maps that do not
+ * allow user specified keys. However, for maps that allow user
+ * specified keys, if the key is not in the map, a new @a key / @a value
+ * association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value) = 0;
+
+ /**
+ * Associate @a key with @a value if and only if @a key is not in the
+ * map. If @a key is already in the map, then the @a value parameter
+ * is overwritten with the existing value in the map. Returns 0 if a
+ * new @a key / @a value association is created. Returns 1 if an
+ * attempt is made to bind an existing entry. This function fails
+ * for maps that do not allow user specified keys.
+ */
+ virtual int trybind (const KEY &key,
+ VALUE &value) = 0;
+
+ /// Locate @a value associated with @a key.
+ virtual int find (const KEY &key,
+ VALUE &value) = 0;
+
+ /// Is @a key in the map?
+ virtual int find (const KEY &key) = 0;
+
+ /// Remove @a key from the map.
+ virtual int unbind (const KEY &key) = 0;
+
+ /// Remove @a key from the map, and return the @a value associated with
+ /// @a key.
+ virtual int unbind (const KEY &key,
+ VALUE &value) = 0;
+
+ /// Return the current size of the map.
+ virtual size_t current_size (void) const = 0;
+
+ /// Return the total size of the map.
+ virtual size_t total_size (void) const = 0;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const = 0;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ iterator begin (void);
+ iterator end (void);
+
+ /// Return reverse iterator.
+ reverse_iterator rbegin (void);
+ reverse_iterator rend (void);
+
+protected:
+
+ // = Protected no-op constructor.
+ ACE_Map (void);
+
+ /// Return forward iterator.
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *begin_impl (void) = 0;
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *end_impl (void) = 0;
+
+ /// Return reverse iterator.
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rbegin_impl (void) = 0;
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rend_impl (void) = 0;
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Map<KEY, VALUE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Map (const ACE_Map<KEY, VALUE> &))
+};
+
+/**
+ * @class ACE_Map_Impl_Iterator_Adapter
+ *
+ * @brief Defines a iterator implementation for the Map_Impl class.
+ *
+ * Implementation to be provided by <IMPLEMENTATION>.
+ */
+template <class T, class IMPLEMENTATION, class ENTRY>
+class ACE_Map_Impl_Iterator_Adapter : public ACE_Iterator_Impl<T>
+{
+public:
+
+ // = Traits.
+ typedef IMPLEMENTATION
+ implementation;
+
+ /// Constructor.
+ ACE_Map_Impl_Iterator_Adapter (const IMPLEMENTATION &impl);
+
+ /// Destructor.
+ virtual ~ACE_Map_Impl_Iterator_Adapter (void);
+
+ /// Clone.
+ virtual ACE_Iterator_Impl<T> *clone (void) const;
+
+ /// Comparison.
+ virtual int compare (const ACE_Iterator_Impl<T> &rhs) const;
+
+ /// Dereference.
+ virtual T dereference (void) const;
+
+ /// Advance.
+ virtual void plus_plus (void);
+
+ /// Reverse.
+ virtual void minus_minus (void);
+
+ /// Accessor to implementation object.
+ IMPLEMENTATION &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ IMPLEMENTATION implementation_;
+};
+
+/**
+ * @class ACE_Map_Impl_Reverse_Iterator_Adapter
+ *
+ * @brief Defines a reverse iterator implementation for the Map_Impl class.
+ *
+ * Implementation to be provided by IMPLEMENTATION.
+ */
+template <class T, class IMPLEMENTATION, class ENTRY>
+class ACE_Map_Impl_Reverse_Iterator_Adapter : public ACE_Reverse_Iterator_Impl<T>
+{
+public:
+
+ // = Traits.
+ typedef IMPLEMENTATION
+ implementation;
+
+ /// Constructor.
+ ACE_Map_Impl_Reverse_Iterator_Adapter (const IMPLEMENTATION &impl);
+
+ /// Destructor.
+ virtual ~ACE_Map_Impl_Reverse_Iterator_Adapter (void);
+
+ /// Clone.
+ virtual ACE_Reverse_Iterator_Impl<T> *clone (void) const;
+
+ /// Comparison.
+ virtual int compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const;
+
+ /// Dereference.
+ virtual T dereference (void) const;
+
+ /// Advance.
+ virtual void plus_plus (void);
+
+ /// Reverse.
+ virtual void minus_minus (void);
+
+ /// Accessor to implementation object.
+ IMPLEMENTATION &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ IMPLEMENTATION implementation_;
+};
+
+/**
+ * @class ACE_Map_Impl
+ *
+ * @brief Defines a map implementation.
+ *
+ * Implementation to be provided by <IMPLEMENTATION>.
+ */
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY>
+class ACE_Map_Impl : public ACE_Map<KEY, VALUE>
+{
+public:
+
+ // = Traits.
+ typedef ACE_Map_Impl_Iterator_Adapter<typename ACE_Map<KEY, VALUE>::value_type, ITERATOR, ENTRY>
+ iterator_impl;
+ typedef ACE_Map_Impl_Reverse_Iterator_Adapter<typename ACE_Map<KEY, VALUE>::value_type, REVERSE_ITERATOR, ENTRY>
+ reverse_iterator_impl;
+
+ typedef IMPLEMENTATION
+ implementation;
+
+ // = Initialization and termination methods.
+ /// Initialize with the ACE_DEFAULT_MAP_SIZE.
+ ACE_Map_Impl (ACE_Allocator *alloc = 0);
+
+ /// Initialize with @a size entries. The @a size parameter is ignored
+ /// by maps for which an initialize size does not make sense.
+ ACE_Map_Impl (size_t size,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down and release dynamically allocated resources.
+ virtual ~ACE_Map_Impl (void);
+
+ /// Initialize a <Map> with size @a length.
+ virtual int open (size_t length = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a <Map> and release dynamically allocated resources.
+ virtual int close (void);
+
+ /**
+ * Add @a key / @a value pair to the map. If @a key is already in the
+ * map then no changes are made and 1 is returned. Returns 0 on a
+ * successful addition. This function fails for maps that do not
+ * allow user specified keys. @a key is an "in" parameter.
+ */
+ virtual int bind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Add @a key / @a value pair to the map. @a key is an "inout" parameter
+ * and maybe modified/extended by the map to add additional
+ * information. To recover original key, call the <recover_key>
+ * method.
+ */
+ virtual int bind_modify_key (const VALUE &value,
+ KEY &key);
+
+ /**
+ * Produce a key and return it through @a key which is an "out"
+ * parameter. For maps that do not naturally produce keys, the map
+ * adapters will use the @c KEY_GENERATOR class to produce a key.
+ * However, the users are responsible for not jeopardizing this key
+ * production scheme by using user specified keys with keys produced
+ * by the key generator.
+ */
+ virtual int create_key (KEY &key);
+
+ /**
+ * Add @a value to the map, and the corresponding key produced by the
+ * Map is returned through @a key which is an "out" parameter. For
+ * maps that do not naturally produce keys, the map adapters will
+ * use the @c KEY_GENERATOR class to produce a key. However, the
+ * users are responsible for not jeopardizing this key production
+ * scheme by using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value,
+ KEY &key);
+
+ /**
+ * Add @a value to the map. The user does not care about the
+ * corresponding key produced by the Map. For maps that do not
+ * naturally produce keys, the map adapters will use the
+ * @c KEY_GENERATOR class to produce a key. However, the users are
+ * responsible for not jeopardizing this key production scheme by
+ * using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value);
+
+ /// Recovers the original key potentially modified by the map during
+ /// <bind_modify_key>.
+ virtual int recover_key (const KEY &modified_key,
+ KEY &original_key);
+
+ /**
+ * Reassociate @a key with @a value. The function fails if @a key is
+ * not in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old value into the
+ * "out" parameter @a old_value. The function fails if @a key is not
+ * in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old key and value
+ * into the "out" parameters @a old_key and @a old_value. The
+ * function fails if @a key is not in the map for maps that do not
+ * allow user specified keys. However, for maps that allow user
+ * specified keys, if the key is not in the map, a new @a key / @a value
+ * association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value);
+
+ /**
+ * Associate @a key with @a value if and only if @a key is not in the
+ * map. If @a key is already in the map, then the @a value parameter
+ * is overwritten with the existing value in the map. Returns 0 if a
+ * new @a key / @a value association is created. Returns 1 if an
+ * attempt is made to bind an existing entry. This function fails
+ * for maps that do not allow user specified keys.
+ */
+ virtual int trybind (const KEY &key,
+ VALUE &value);
+
+ /// Locate @a value associated with @a key.
+ virtual int find (const KEY &key,
+ VALUE &value);
+
+ /// Is @a key in the map?
+ virtual int find (const KEY &key);
+
+ /// Remove @a key from the map.
+ virtual int unbind (const KEY &key);
+
+ /// Remove @a key from the map, and return the @a value associated with
+ /// @a key.
+ virtual int unbind (const KEY &key,
+ VALUE &value);
+
+ /// Return the current size of the map.
+ virtual size_t current_size (void) const;
+
+ /// Return the total size of the map.
+ virtual size_t total_size (void) const;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Accessor to implementation object.
+ IMPLEMENTATION &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ IMPLEMENTATION implementation_;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *begin_impl (void);
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *end_impl (void);
+
+ /// Return reverse iterator.
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rbegin_impl (void);
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rend_impl (void);
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Map_Impl (const ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY> &))
+};
+
+/**
+ * @class ACE_Active_Map_Manager_Iterator_Adapter
+ *
+ * @brief Defines a iterator implementation for the Active_Map_Manager_Adapter.
+ *
+ * Implementation to be provided by ACE_Active_Map_Manager::iterator.
+ */
+template <class T, class VALUE>
+class ACE_Active_Map_Manager_Iterator_Adapter : public ACE_Iterator_Impl<T>
+{
+public:
+
+ // = Traits.
+ typedef typename ACE_Active_Map_Manager<VALUE>::iterator
+ implementation;
+
+ /// Constructor.
+ ACE_Active_Map_Manager_Iterator_Adapter (const ACE_Map_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> &impl);
+
+ /// Destructor.
+ virtual ~ACE_Active_Map_Manager_Iterator_Adapter (void);
+
+ /// Clone.
+ virtual ACE_Iterator_Impl<T> *clone (void) const;
+
+ /// Comparison.
+ virtual int compare (const ACE_Iterator_Impl<T> &rhs) const;
+
+ /// Dereference.
+ virtual T dereference (void) const;
+
+ /// Advance.
+ virtual void plus_plus (void);
+
+ /// Reverse.
+ virtual void minus_minus (void);
+
+ /// Accessor to implementation object.
+ ACE_Map_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ ACE_Map_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> implementation_;
+};
+
+/**
+ * @class ACE_Active_Map_Manager_Reverse_Iterator_Adapter
+ *
+ * @brief Defines a reverse iterator implementation for the Active_Map_Manager_Adapter.
+ *
+ * Implementation to be provided by ACE_Active_Map_Manager::reverse_iterator.
+ */
+template <class T, class VALUE>
+class ACE_Active_Map_Manager_Reverse_Iterator_Adapter : public ACE_Reverse_Iterator_Impl<T>
+{
+public:
+
+ // = Traits.
+ typedef typename ACE_Active_Map_Manager<VALUE>::reverse_iterator
+ implementation;
+
+ /// Constructor.
+ ACE_Active_Map_Manager_Reverse_Iterator_Adapter (const ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> &impl);
+
+ /// Destructor.
+ virtual ~ACE_Active_Map_Manager_Reverse_Iterator_Adapter (void);
+
+ /// Clone.
+ virtual ACE_Reverse_Iterator_Impl<T> *clone (void) const;
+
+ /// Comparison.
+ virtual int compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const;
+
+ /// Dereference.
+ virtual T dereference (void) const;
+
+ /// Advance.
+ virtual void plus_plus (void);
+
+ /// Reverse.
+ virtual void minus_minus (void);
+
+ /// Accessor to implementation object.
+ ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> implementation_;
+};
+
+/**
+ * @class ACE_Active_Map_Manager_Adapter
+ *
+ * @brief Defines a map implementation.
+ *
+ * Implementation to be provided by <ACE_Active_Map_Manager>.
+ */
+template <class KEY, class VALUE, class KEY_ADAPTER>
+class ACE_Active_Map_Manager_Adapter : public ACE_Map<KEY, VALUE>
+{
+public:
+
+ // = Traits.
+ typedef ACE_Pair<KEY, VALUE>
+ expanded_value;
+ typedef ACE_Active_Map_Manager_Iterator_Adapter<ACE_Reference_Pair<const KEY, VALUE>, expanded_value>
+ iterator_impl;
+ typedef ACE_Active_Map_Manager_Reverse_Iterator_Adapter<ACE_Reference_Pair<const KEY, VALUE>, expanded_value>
+ reverse_iterator_impl;
+ typedef ACE_Active_Map_Manager<expanded_value>
+ implementation;
+
+ // = Initialization and termination methods.
+ /// Initialize with the ACE_DEFAULT_MAP_SIZE.
+ ACE_Active_Map_Manager_Adapter (ACE_Allocator *alloc = 0);
+
+ /// Initialize with @a size entries. The @a size parameter is ignored
+ /// by maps for which an initialize size does not make sense.
+ ACE_Active_Map_Manager_Adapter (size_t size,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down and release dynamically allocated resources.
+ virtual ~ACE_Active_Map_Manager_Adapter (void);
+
+ /// Initialize a <Map> with size @a length.
+ virtual int open (size_t length = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a <Map> and release dynamically allocated resources.
+ virtual int close (void);
+
+ /**
+ * Add @a key / @a value pair to the map. If @a key is already in the
+ * map then no changes are made and 1 is returned. Returns 0 on a
+ * successful addition. This function fails for maps that do not
+ * allow user specified keys. @a key is an "in" parameter.
+ */
+ virtual int bind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Add @a key / @a value pair to the map. @a key is an "inout" parameter
+ * and maybe modified/extended by the map to add additional
+ * information. To recover original key, call the <recover_key>
+ * method.
+ */
+ virtual int bind_modify_key (const VALUE &value,
+ KEY &key);
+
+ /**
+ * Produce a key and return it through @a key which is an "out"
+ * parameter. For maps that do not naturally produce keys, the map
+ * adapters will use the @c KEY_GENERATOR class to produce a key.
+ * However, the users are responsible for not jeopardizing this key
+ * production scheme by using user specified keys with keys produced
+ * by the key generator.
+ */
+ virtual int create_key (KEY &key);
+
+ /**
+ * Add @a value to the map, and the corresponding key produced by the
+ * Map is returned through @a key which is an "out" parameter. For
+ * maps that do not naturally produce keys, the map adapters will
+ * use the @c KEY_GENERATOR class to produce a key. However, the
+ * users are responsible for not jeopardizing this key production
+ * scheme by using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value,
+ KEY &key);
+
+ /**
+ * Add @a value to the map. The user does not care about the
+ * corresponding key produced by the Map. For maps that do not
+ * naturally produce keys, the map adapters will use the
+ * @c KEY_GENERATOR class to produce a key. However, the users are
+ * responsible for not jeopardizing this key production scheme by
+ * using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value);
+
+ /// Recovers the original key potentially modified by the map during
+ /// <bind_modify_key>.
+ virtual int recover_key (const KEY &modified_key,
+ KEY &original_key);
+
+ /**
+ * Reassociate @a key with @a value. The function fails if @a key is
+ * not in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old value into the
+ * "out" parameter @a old_value. The function fails if @a key is not
+ * in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old key and value
+ * into the "out" parameters @a old_key and @a old_value. The
+ * function fails if @a key is not in the map for maps that do not
+ * allow user specified keys. However, for maps that allow user
+ * specified keys, if the key is not in the map, a new @a key / @a value
+ * association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value);
+
+ /**
+ * Associate @a key with @a value if and only if @a key is not in the
+ * map. If @a key is already in the map, then the @a value parameter
+ * is overwritten with the existing value in the map. Returns 0 if a
+ * new @a key / @a value association is created. Returns 1 if an
+ * attempt is made to bind an existing entry. This function fails
+ * for maps that do not allow user specified keys.
+ */
+ virtual int trybind (const KEY &key,
+ VALUE &value);
+
+ /// Locate @a value associated with @a key.
+ virtual int find (const KEY &key,
+ VALUE &value);
+
+ /// Is @a key in the map?
+ virtual int find (const KEY &key);
+
+ /// Remove @a key from the map.
+ virtual int unbind (const KEY &key);
+
+ /// Remove @a key from the map, and return the @a value associated with
+ /// @a key.
+ virtual int unbind (const KEY &key,
+ VALUE &value);
+
+ /// Return the current size of the map.
+ virtual size_t current_size (void) const;
+
+ /// Return the total size of the map.
+ virtual size_t total_size (void) const;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Accessor to implementation object.
+ ACE_Active_Map_Manager<ACE_Pair<KEY, VALUE> > &impl (void);
+
+ /// Accessor to key adapter.
+ KEY_ADAPTER &key_adapter (void);
+
+protected:
+
+ /// Find helper.
+ virtual int find (const KEY &key,
+ expanded_value *&internal_value);
+
+ /// Unbind helper.
+ virtual int unbind (const KEY &key,
+ expanded_value *&internal_value);
+
+ /// All implementation details are forwarded to this class.
+ ACE_Active_Map_Manager<ACE_Pair<KEY, VALUE> > implementation_;
+
+ /// Adapts between the user key and the Active_Map_Manager_Key.
+ KEY_ADAPTER key_adapter_;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *begin_impl (void);
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *end_impl (void);
+
+ /// Return reverse iterator.
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rbegin_impl (void);
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rend_impl (void);
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Active_Map_Manager_Adapter (const ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER> &))
+};
+
+/**
+ * @class ACE_Hash_Map_Manager_Ex_Iterator_Adapter
+ *
+ * @brief Defines a iterator implementation for the Hash_Map_Manager_Adapter.
+ *
+ * Implementation to be provided by ACE_Hash_Map_Manager_Ex::iterator.
+ */
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS>
+class ACE_Hash_Map_Manager_Ex_Iterator_Adapter : public ACE_Iterator_Impl<T>
+{
+public:
+
+ // = Traits.
+ typedef typename ACE_Hash_Map_Manager_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex>::iterator
+ implementation;
+
+ /// Constructor.
+ ACE_Hash_Map_Manager_Ex_Iterator_Adapter (const ACE_Hash_Map_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &impl);
+
+ /// Destructor.
+ virtual ~ACE_Hash_Map_Manager_Ex_Iterator_Adapter (void);
+
+ /// Clone.
+ virtual ACE_Iterator_Impl<T> *clone (void) const;
+
+ /// Comparison.
+ virtual int compare (const ACE_Iterator_Impl<T> &rhs) const;
+
+ /// Dereference.
+ virtual T dereference (void) const;
+
+ /// Advance.
+ virtual void plus_plus (void);
+
+ /// Reverse.
+ virtual void minus_minus (void);
+
+ /// Accessor to implementation object.
+ ACE_Hash_Map_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ ACE_Hash_Map_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> implementation_;
+};
+
+/**
+ * @class ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter
+ *
+ * @brief Defines a reverse iterator implementation for the Hash_Map_Manager_Adapter.
+ *
+ * Implementation to be provided by ACE_Hash_Map_Manager_Ex::reverse_iterator.
+ */
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS>
+class ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter : public ACE_Reverse_Iterator_Impl<T>
+{
+public:
+
+ // = Traits.
+ typedef typename ACE_Hash_Map_Manager_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex>::reverse_iterator
+ implementation;
+
+ /// Constructor.
+ ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter (const ACE_Hash_Map_Reverse_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &impl);
+
+ /// Destructor.
+ virtual ~ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter (void);
+
+ /// Clone.
+ virtual ACE_Reverse_Iterator_Impl<T> *clone (void) const;
+
+ /// Comparison.
+ virtual int compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const;
+
+ /// Dereference.
+ virtual T dereference (void) const;
+
+ /// Advance.
+ virtual void plus_plus (void);
+
+ /// Reverse.
+ virtual void minus_minus (void);
+
+ /// Accessor to implementation object.
+ ACE_Hash_Map_Reverse_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ ACE_Hash_Map_Reverse_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> implementation_;
+};
+
+/**
+ * @class ACE_Hash_Map_Manager_Ex_Adapter
+ *
+ * @brief Defines a map implementation.
+ *
+ * Implementation to be provided by ACE_Hash_Map_Manager_Ex.
+ */
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR>
+class ACE_Hash_Map_Manager_Ex_Adapter : public ACE_Map<KEY, VALUE>
+{
+public:
+
+ // = Traits.
+ typedef ACE_Hash_Map_Manager_Ex_Iterator_Adapter<ACE_Reference_Pair<const KEY, VALUE>, KEY, VALUE, HASH_KEY, COMPARE_KEYS>
+ iterator_impl;
+ typedef ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<ACE_Reference_Pair<const KEY, VALUE>, KEY, VALUE, HASH_KEY, COMPARE_KEYS>
+ reverse_iterator_impl;
+ typedef ACE_Hash_Map_Manager_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex>
+ implementation;
+
+ // = Initialization and termination methods.
+ /// Initialize with the ACE_DEFAULT_MAP_SIZE.
+ ACE_Hash_Map_Manager_Ex_Adapter (ACE_Allocator *alloc = 0);
+
+ /// Initialize with @a size entries. The @a size parameter is ignored
+ /// by maps for which an initialize size does not make sense.
+ ACE_Hash_Map_Manager_Ex_Adapter (size_t size,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down and release dynamically allocated resources.
+ virtual ~ACE_Hash_Map_Manager_Ex_Adapter (void);
+
+ /// Initialize a <Map> with size @a length.
+ virtual int open (size_t length = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a <Map> and release dynamically allocated resources.
+ virtual int close (void);
+
+ /**
+ * Add @a key / @a value pair to the map. If @a key is already in the
+ * map then no changes are made and 1 is returned. Returns 0 on a
+ * successful addition. This function fails for maps that do not
+ * allow user specified keys. @a key is an "in" parameter.
+ */
+ virtual int bind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Add @a key / @a value pair to the map. @a key is an "inout" parameter
+ * and maybe modified/extended by the map to add additional
+ * information. To recover original key, call the <recover_key>
+ * method.
+ */
+ virtual int bind_modify_key (const VALUE &value,
+ KEY &key);
+
+ /**
+ * Produce a key and return it through @a key which is an "out"
+ * parameter. For maps that do not naturally produce keys, the map
+ * adapters will use the @c KEY_GENERATOR class to produce a key.
+ * However, the users are responsible for not jeopardizing this key
+ * production scheme by using user specified keys with keys produced
+ * by the key generator.
+ */
+ virtual int create_key (KEY &key);
+
+ /**
+ * Add @a value to the map, and the corresponding key produced by the
+ * Map is returned through @a key which is an "out" parameter. For
+ * maps that do not naturally produce keys, the map adapters will
+ * use the @c KEY_GENERATOR class to produce a key. However, the
+ * users are responsible for not jeopardizing this key production
+ * scheme by using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value,
+ KEY &key);
+
+ /**
+ * Add @a value to the map. The user does not care about the
+ * corresponding key produced by the Map. For maps that do not
+ * naturally produce keys, the map adapters will use the
+ * @c KEY_GENERATOR class to produce a key. However, the users are
+ * responsible for not jeopardizing this key production scheme by
+ * using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value);
+
+ /// Recovers the original key potentially modified by the map during
+ /// <bind_modify_key>.
+ virtual int recover_key (const KEY &modified_key,
+ KEY &original_key);
+
+ /**
+ * Reassociate @a key with @a value. The function fails if @a key is
+ * not in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old value into the
+ * "out" parameter @a old_value. The function fails if @a key is not
+ * in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old key and value
+ * into the "out" parameters @a old_key and @a old_value. The
+ * function fails if @a key is not in the map for maps that do not
+ * allow user specified keys. However, for maps that allow user
+ * specified keys, if the key is not in the map, a new @a key / @a value
+ * association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value);
+
+ /**
+ * Associate @a key with @a value if and only if @a key is not in the
+ * map. If @a key is already in the map, then the @a value parameter
+ * is overwritten with the existing value in the map. Returns 0 if a
+ * new @a key / @a value association is created. Returns 1 if an
+ * attempt is made to bind an existing entry. This function fails
+ * for maps that do not allow user specified keys.
+ */
+ virtual int trybind (const KEY &key,
+ VALUE &value);
+
+ /// Locate @a value associated with @a key.
+ virtual int find (const KEY &key,
+ VALUE &value);
+
+ /// Is @a key in the map?
+ virtual int find (const KEY &key);
+
+ /// Remove @a key from the map.
+ virtual int unbind (const KEY &key);
+
+ /// Remove @a key from the map, and return the @a value associated with
+ /// @a key.
+ virtual int unbind (const KEY &key,
+ VALUE &value);
+
+ /// Return the current size of the map.
+ virtual size_t current_size (void) const;
+
+ /// Return the total size of the map.
+ virtual size_t total_size (void) const;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Accessor to implementation object.
+ ACE_Hash_Map_Manager_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &impl (void);
+
+ /// Accessor to key generator.
+ KEY_GENERATOR &key_generator (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ ACE_Hash_Map_Manager_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> implementation_;
+
+ /// Functor class used for generating key.
+ KEY_GENERATOR key_generator_;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *begin_impl (void);
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *end_impl (void);
+
+ /// Return reverse iterator.
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rbegin_impl (void);
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rend_impl (void);
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Hash_Map_Manager_Ex_Adapter (const ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR> &))
+};
+
+/**
+ * @class ACE_Map_Manager_Iterator_Adapter
+ *
+ * @brief Defines a iterator implementation for the Map_Manager_Adapter.
+ *
+ * Implementation to be provided by ACE_Map_Manager::iterator.
+ */
+template <class T, class KEY, class VALUE>
+class ACE_Map_Manager_Iterator_Adapter : public ACE_Iterator_Impl<T>
+{
+public:
+
+ // = Traits.
+ typedef typename ACE_Map_Manager<KEY, VALUE, ACE_Null_Mutex>::iterator
+ implementation;
+
+ /// Constructor.
+ ACE_Map_Manager_Iterator_Adapter (const ACE_Map_Iterator<KEY, VALUE, ACE_Null_Mutex> &impl);
+
+ /// Destructor.
+ virtual ~ACE_Map_Manager_Iterator_Adapter (void);
+
+ /// Clone.
+ virtual ACE_Iterator_Impl<T> *clone (void) const;
+
+ /// Comparison.
+ virtual int compare (const ACE_Iterator_Impl<T> &rhs) const;
+
+ /// Dereference.
+ virtual T dereference (void) const;
+
+ /// Advance.
+ virtual void plus_plus (void);
+
+ /// Reverse.
+ virtual void minus_minus (void);
+
+ /// Accessor to implementation object.
+ ACE_Map_Iterator<KEY, VALUE, ACE_Null_Mutex> &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ ACE_Map_Iterator<KEY, VALUE, ACE_Null_Mutex> implementation_;
+};
+
+/**
+ * @class ACE_Map_Manager_Reverse_Iterator_Adapter
+ *
+ * @brief Defines a reverse iterator implementation for the Map Manager.
+ *
+ * Implementation to be provided by ACE_Map_Manager::reverse_iterator.
+ */
+template <class T, class KEY, class VALUE>
+class ACE_Map_Manager_Reverse_Iterator_Adapter : public ACE_Reverse_Iterator_Impl<T>
+{
+public:
+
+ // = Traits.
+ typedef typename ACE_Map_Manager<KEY, VALUE, ACE_Null_Mutex>::reverse_iterator
+ implementation;
+
+ /// Constructor.
+ ACE_Map_Manager_Reverse_Iterator_Adapter (const ACE_Map_Reverse_Iterator<KEY, VALUE, ACE_Null_Mutex> &impl);
+
+ /// Destructor.
+ virtual ~ACE_Map_Manager_Reverse_Iterator_Adapter (void);
+
+ /// Clone.
+ virtual ACE_Reverse_Iterator_Impl<T> *clone (void) const;
+
+ /// Comparison.
+ virtual int compare (const ACE_Reverse_Iterator_Impl<T> &rhs) const;
+
+ /// Dereference.
+ virtual T dereference (void) const;
+
+ /// Advance.
+ virtual void plus_plus (void);
+
+ /// Reverse.
+ virtual void minus_minus (void);
+
+ /// Accessor to implementation object.
+ ACE_Map_Reverse_Iterator<KEY, VALUE, ACE_Null_Mutex> &impl (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ ACE_Map_Reverse_Iterator<KEY, VALUE, ACE_Null_Mutex> implementation_;
+};
+
+/**
+ * @class ACE_Map_Manager_Adapter
+ *
+ * @brief Defines a map implementation.
+ *
+ * Implementation to be provided by ACE_Map_Manager.
+ */
+template <class KEY, class VALUE, class KEY_GENERATOR>
+class ACE_Map_Manager_Adapter : public ACE_Map<KEY, VALUE>
+{
+public:
+
+ // = Traits.
+ typedef ACE_Map_Manager_Iterator_Adapter<ACE_Reference_Pair<const KEY, VALUE>, KEY, VALUE>
+ iterator_impl;
+ typedef ACE_Map_Manager_Reverse_Iterator_Adapter<ACE_Reference_Pair<const KEY, VALUE>, KEY, VALUE>
+ reverse_iterator_impl;
+ typedef ACE_Map_Manager<KEY, VALUE, ACE_Null_Mutex>
+ implementation;
+
+ // = Initialization and termination methods.
+ /// Initialize with the ACE_DEFAULT_MAP_SIZE.
+ ACE_Map_Manager_Adapter (ACE_Allocator *alloc = 0);
+
+ /// Initialize with @a size entries. The @a size parameter is ignored
+ /// by maps for which an initialize size does not make sense.
+ ACE_Map_Manager_Adapter (size_t size,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down and release dynamically allocated resources.
+ virtual ~ACE_Map_Manager_Adapter (void);
+
+ /// Initialize a <Map> with size @a length.
+ virtual int open (size_t length = ACE_DEFAULT_MAP_SIZE,
+ ACE_Allocator *alloc = 0);
+
+ /// Close down a <Map> and release dynamically allocated resources.
+ virtual int close (void);
+
+ /**
+ * Add @a key / @a value pair to the map. If @a key is already in the
+ * map then no changes are made and 1 is returned. Returns 0 on a
+ * successful addition. This function fails for maps that do not
+ * allow user specified keys. @a key is an "in" parameter.
+ */
+ virtual int bind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Add @a key / @a value pair to the map. @a key is an "inout" parameter
+ * and maybe modified/extended by the map to add additional
+ * information. To recover original key, call the <recover_key>
+ * method.
+ */
+ virtual int bind_modify_key (const VALUE &value,
+ KEY &key);
+
+ /**
+ * Produce a key and return it through @a key which is an "out"
+ * parameter. For maps that do not naturally produce keys, the map
+ * adapters will use the @c KEY_GENERATOR class to produce a key.
+ * However, the users are responsible for not jeopardizing this key
+ * production scheme by using user specified keys with keys produced
+ * by the key generator.
+ */
+ virtual int create_key (KEY &key);
+
+ /**
+ * Add @a value to the map, and the corresponding key produced by the
+ * Map is returned through @a key which is an "out" parameter. For
+ * maps that do not naturally produce keys, the map adapters will
+ * use the @c KEY_GENERATOR class to produce a key. However, the
+ * users are responsible for not jeopardizing this key production
+ * scheme by using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value,
+ KEY &key);
+
+ /**
+ * Add @a value to the map. The user does not care about the
+ * corresponding key produced by the Map. For maps that do not
+ * naturally produce keys, the map adapters will use the
+ * @c KEY_GENERATOR class to produce a key. However, the users are
+ * responsible for not jeopardizing this key production scheme by
+ * using user specified keys with keys produced by the key
+ * generator.
+ */
+ virtual int bind_create_key (const VALUE &value);
+
+ /// Recovers the original key potentially modified by the map during
+ /// <bind_modify_key>.
+ virtual int recover_key (const KEY &modified_key,
+ KEY &original_key);
+
+ /**
+ * Reassociate @a key with @a value. The function fails if @a key is
+ * not in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old value into the
+ * "out" parameter @a old_value. The function fails if @a key is not
+ * in the map for maps that do not allow user specified keys.
+ * However, for maps that allow user specified keys, if the key is
+ * not in the map, a new @a key / @a value association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ VALUE &old_value);
+
+ /**
+ * Reassociate @a key with @a value, storing the old key and value
+ * into the "out" parameters @a old_key and @a old_value. The
+ * function fails if @a key is not in the map for maps that do not
+ * allow user specified keys. However, for maps that allow user
+ * specified keys, if the key is not in the map, a new @a key / @a value
+ * association is created.
+ */
+ virtual int rebind (const KEY &key,
+ const VALUE &value,
+ KEY &old_key,
+ VALUE &old_value);
+
+ /**
+ * Associate @a key with @a value if and only if @a key is not in the
+ * map. If @a key is already in the map, then the @a value parameter
+ * is overwritten with the existing value in the map. Returns 0 if a
+ * new @a key / @a value association is created. Returns 1 if an
+ * attempt is made to bind an existing entry. This function fails
+ * for maps that do not allow user specified keys.
+ */
+ virtual int trybind (const KEY &key,
+ VALUE &value);
+
+ /// Locate @a value associated with @a key.
+ virtual int find (const KEY &key,
+ VALUE &value);
+
+ /// Is @a key in the map?
+ virtual int find (const KEY &key);
+
+ /// Remove @a key from the map.
+ virtual int unbind (const KEY &key);
+
+ /// Remove @a key from the map, and return the @a value associated with
+ /// @a key.
+ virtual int unbind (const KEY &key,
+ VALUE &value);
+
+ /// Return the current size of the map.
+ virtual size_t current_size (void) const;
+
+ /// Return the total size of the map.
+ virtual size_t total_size (void) const;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Accessor to implementation object.
+ ACE_Map_Manager<KEY, VALUE, ACE_Null_Mutex> &impl (void);
+
+ /// Accessor to key generator.
+ KEY_GENERATOR &key_generator (void);
+
+protected:
+
+ /// All implementation details are forwarded to this class.
+ ACE_Map_Manager<KEY, VALUE, ACE_Null_Mutex> implementation_;
+
+ /// Functor class used for generating key.
+ KEY_GENERATOR key_generator_;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator.
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *begin_impl (void);
+ virtual ACE_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *end_impl (void);
+
+ /// Return reverse iterator.
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rbegin_impl (void);
+ virtual ACE_Reverse_Iterator_Impl<ACE_Reference_Pair<const KEY, VALUE> > *rend_impl (void);
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Map_Manager_Adapter (const ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Map_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Map_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Map_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MAP_T_H */
diff --git a/ACE/ace/Map_T.inl b/ACE/ace/Map_T.inl
new file mode 100644
index 00000000000..8dea4a198b3
--- /dev/null
+++ b/ACE/ace/Map_T.inl
@@ -0,0 +1,415 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> ACE_INLINE int
+ACE_Noop_Key_Generator<T>::operator() (T &)
+{
+ return -1;
+}
+
+template <class T> ACE_INLINE
+ACE_Incremental_Key_Generator<T>::ACE_Incremental_Key_Generator (void)
+ : t_ (0)
+{
+}
+
+template <class T> ACE_INLINE int
+ACE_Incremental_Key_Generator<T>::operator() (T &t)
+{
+ t = ++this->t_;
+ return 0;
+}
+
+template <class T> ACE_INLINE const T &
+ACE_Incremental_Key_Generator<T>::current_value (void) const
+{
+ return this->t_;
+}
+
+template <class T> ACE_INLINE
+ACE_Iterator<T>::ACE_Iterator (ACE_Iterator_Impl<T> *impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T> ACE_INLINE
+ACE_Iterator<T>::ACE_Iterator (const ACE_Iterator<T> &rhs)
+ : implementation_ (rhs.implementation_->clone ())
+{
+}
+
+template <class T> ACE_INLINE
+ACE_Iterator<T>::~ACE_Iterator (void)
+{
+ delete this->implementation_;
+}
+
+template <class T> ACE_INLINE ACE_Iterator<T> &
+ACE_Iterator<T>::operator= (const ACE_Iterator<T> &rhs)
+{
+ delete this->implementation_;
+ this->implementation_ = rhs.implementation_->clone ();
+ return *this;
+}
+
+template <class T> ACE_INLINE bool
+ACE_Iterator<T>::operator== (const ACE_Iterator<T> &rhs) const
+{
+ return this->implementation_->compare (*rhs.implementation_);
+}
+
+template <class T> ACE_INLINE bool
+ACE_Iterator<T>::operator!= (const ACE_Iterator<T> &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+template <class T> ACE_INLINE T
+ACE_Iterator<T>::operator* (void) const
+{
+ return this->implementation_->dereference ();
+}
+
+template <class T> ACE_INLINE ACE_Iterator<T> &
+ACE_Iterator<T>::operator++ (void)
+{
+ this->implementation_->plus_plus ();
+ return *this;
+}
+
+template <class T> ACE_INLINE ACE_Iterator<T>
+ACE_Iterator<T>::operator++ (int)
+{
+ ACE_Iterator<T> tmp = *this;
+ this->implementation_->plus_plus ();
+ return tmp;
+}
+
+template <class T> ACE_INLINE ACE_Iterator<T> &
+ACE_Iterator<T>::operator-- (void)
+{
+ this->implementation_->minus_minus ();
+ return *this;
+}
+
+template <class T> ACE_INLINE ACE_Iterator<T>
+ACE_Iterator<T>::operator-- (int)
+{
+ ACE_Iterator<T> tmp = *this;
+ this->implementation_->minus_minus ();
+ return tmp;
+}
+
+template <class T> ACE_INLINE ACE_Iterator_Impl<T> &
+ACE_Iterator<T>::impl (void)
+{
+ return *this->implementation_;
+}
+
+template <class T> ACE_INLINE
+ACE_Reverse_Iterator<T>::ACE_Reverse_Iterator (ACE_Reverse_Iterator_Impl<T> *impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T> ACE_INLINE
+ACE_Reverse_Iterator<T>::ACE_Reverse_Iterator (const ACE_Reverse_Iterator<T> &rhs)
+ : implementation_ (rhs.implementation_->clone ())
+{
+}
+
+template <class T> ACE_INLINE
+ACE_Reverse_Iterator<T>::~ACE_Reverse_Iterator (void)
+{
+ delete this->implementation_;
+}
+
+template <class T> ACE_INLINE ACE_Reverse_Iterator<T> &
+ACE_Reverse_Iterator<T>::operator= (const ACE_Reverse_Iterator<T> &rhs)
+{
+ delete this->implementation_;
+ this->implementation_ = rhs.implementation_->clone ();
+ return *this;
+}
+
+template <class T> ACE_INLINE bool
+ACE_Reverse_Iterator<T>::operator== (const ACE_Reverse_Iterator<T> &rhs) const
+{
+ return this->implementation_->compare (*rhs.implementation_);
+}
+
+template <class T> ACE_INLINE bool
+ACE_Reverse_Iterator<T>::operator!= (const ACE_Reverse_Iterator<T> &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+template <class T> ACE_INLINE T
+ACE_Reverse_Iterator<T>::operator* (void) const
+{
+ return this->implementation_->dereference ();
+}
+
+template <class T> ACE_INLINE ACE_Reverse_Iterator<T> &
+ACE_Reverse_Iterator<T>::operator++ (void)
+{
+ this->implementation_->plus_plus ();
+ return *this;
+}
+
+template <class T> ACE_INLINE ACE_Reverse_Iterator<T>
+ACE_Reverse_Iterator<T>::operator++ (int)
+{
+ ACE_Reverse_Iterator<T> tmp = *this;
+ this->implementation_->plus_plus ();
+ return tmp;
+}
+
+template <class T> ACE_INLINE ACE_Reverse_Iterator<T> &
+ACE_Reverse_Iterator<T>::operator-- (void)
+{
+ this->implementation_->minus_minus ();
+ return *this;
+}
+
+template <class T> ACE_INLINE ACE_Reverse_Iterator<T>
+ACE_Reverse_Iterator<T>::operator-- (int)
+{
+ ACE_Reverse_Iterator<T> tmp = *this;
+ this->implementation_->minus_minus ();
+ return tmp;
+}
+
+template <class T> ACE_INLINE ACE_Reverse_Iterator_Impl<T> &
+ACE_Reverse_Iterator<T>::impl (void)
+{
+ return *this->implementation_;
+}
+
+template <class KEY, class VALUE> ACE_INLINE
+ACE_Map<KEY, VALUE>::ACE_Map (void)
+{
+}
+
+template <class KEY, class VALUE> ACE_INLINE ACE_Iterator<ACE_Reference_Pair<const KEY, VALUE> >
+ACE_Map<KEY, VALUE>::begin (void)
+{
+ return iterator (this->begin_impl ());
+}
+
+template <class KEY, class VALUE> ACE_INLINE ACE_Iterator<ACE_Reference_Pair<const KEY, VALUE> >
+ACE_Map<KEY, VALUE>::end (void)
+{
+ return iterator (this->end_impl ());
+}
+
+template <class KEY, class VALUE> ACE_INLINE ACE_Reverse_Iterator<ACE_Reference_Pair<const KEY, VALUE> >
+ACE_Map<KEY, VALUE>::rbegin (void)
+{
+ return reverse_iterator (this->rbegin_impl ());
+}
+
+template <class KEY, class VALUE> ACE_INLINE ACE_Reverse_Iterator<ACE_Reference_Pair<const KEY, VALUE> >
+ACE_Map<KEY, VALUE>::rend (void)
+{
+ return reverse_iterator (this->rend_impl ());
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> ACE_INLINE
+ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::ACE_Map_Impl_Iterator_Adapter (const IMPLEMENTATION &impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> ACE_INLINE IMPLEMENTATION &
+ACE_Map_Impl_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> ACE_INLINE
+ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::ACE_Map_Impl_Reverse_Iterator_Adapter (const IMPLEMENTATION &impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T, class IMPLEMENTATION, class ENTRY> ACE_INLINE IMPLEMENTATION &
+ACE_Map_Impl_Reverse_Iterator_Adapter<T, IMPLEMENTATION, ENTRY>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> ACE_INLINE
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::ACE_Map_Impl (ACE_Allocator *alloc)
+ : implementation_ (alloc)
+{
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> ACE_INLINE
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::ACE_Map_Impl (size_t size,
+ ACE_Allocator *alloc)
+ : implementation_ (size,
+ alloc)
+{
+}
+
+template <class KEY, class VALUE, class IMPLEMENTATION, class ITERATOR, class REVERSE_ITERATOR, class ENTRY> ACE_INLINE IMPLEMENTATION &
+ACE_Map_Impl<KEY, VALUE, IMPLEMENTATION, ITERATOR, REVERSE_ITERATOR, ENTRY>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class T, class VALUE> ACE_INLINE
+ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>::ACE_Active_Map_Manager_Iterator_Adapter (const ACE_Map_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> &impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T, class VALUE> ACE_INLINE ACE_Map_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> &
+ACE_Active_Map_Manager_Iterator_Adapter<T, VALUE>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class T, class VALUE> ACE_INLINE
+ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>::ACE_Active_Map_Manager_Reverse_Iterator_Adapter (const ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> &impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T, class VALUE> ACE_INLINE ACE_Map_Reverse_Iterator<ACE_Active_Map_Manager_Key, VALUE, ACE_Null_Mutex> &
+ACE_Active_Map_Manager_Reverse_Iterator_Adapter<T, VALUE>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> ACE_INLINE
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::ACE_Active_Map_Manager_Adapter (ACE_Allocator *alloc)
+ : implementation_ (alloc)
+{
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> ACE_INLINE
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::ACE_Active_Map_Manager_Adapter (size_t size,
+ ACE_Allocator *alloc)
+ : implementation_ (size,
+ alloc)
+{
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> ACE_INLINE ACE_Active_Map_Manager<ACE_Pair<KEY, VALUE> > &
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class KEY, class VALUE, class KEY_ADAPTER> ACE_INLINE KEY_ADAPTER &
+ACE_Active_Map_Manager_Adapter<KEY, VALUE, KEY_ADAPTER>::key_adapter (void)
+{
+ return this->key_adapter_;
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> ACE_INLINE
+ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::ACE_Hash_Map_Manager_Ex_Iterator_Adapter (const ACE_Hash_Map_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> ACE_INLINE ACE_Hash_Map_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &
+ACE_Hash_Map_Manager_Ex_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> ACE_INLINE
+ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter (const ACE_Hash_Map_Reverse_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T, class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS> ACE_INLINE ACE_Hash_Map_Reverse_Iterator_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &
+ACE_Hash_Map_Manager_Ex_Reverse_Iterator_Adapter<T, KEY, VALUE, HASH_KEY, COMPARE_KEYS>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> ACE_INLINE
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::ACE_Hash_Map_Manager_Ex_Adapter (ACE_Allocator *alloc)
+ : implementation_ (alloc)
+{
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> ACE_INLINE
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::ACE_Hash_Map_Manager_Ex_Adapter (size_t size,
+ ACE_Allocator *alloc)
+ : implementation_ (size,
+ alloc)
+{
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> ACE_INLINE ACE_Hash_Map_Manager_Ex<KEY, VALUE, HASH_KEY, COMPARE_KEYS, ACE_Null_Mutex> &
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class KEY, class VALUE, class HASH_KEY, class COMPARE_KEYS, class KEY_GENERATOR> ACE_INLINE KEY_GENERATOR &
+ACE_Hash_Map_Manager_Ex_Adapter<KEY, VALUE, HASH_KEY, COMPARE_KEYS, KEY_GENERATOR>::key_generator (void)
+{
+ return this->key_generator_;
+}
+
+template <class T, class KEY, class VALUE> ACE_INLINE
+ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>::ACE_Map_Manager_Iterator_Adapter (const ACE_Map_Iterator<KEY, VALUE, ACE_Null_Mutex> &impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T, class KEY, class VALUE> ACE_INLINE ACE_Map_Iterator<KEY, VALUE, ACE_Null_Mutex> &
+ACE_Map_Manager_Iterator_Adapter<T, KEY, VALUE>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class T, class KEY, class VALUE> ACE_INLINE
+ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>::ACE_Map_Manager_Reverse_Iterator_Adapter (const ACE_Map_Reverse_Iterator<KEY, VALUE, ACE_Null_Mutex> &impl)
+ : implementation_ (impl)
+{
+}
+
+template <class T, class KEY, class VALUE> ACE_INLINE ACE_Map_Reverse_Iterator<KEY, VALUE, ACE_Null_Mutex> &
+ACE_Map_Manager_Reverse_Iterator_Adapter<T, KEY, VALUE>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> ACE_INLINE
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::ACE_Map_Manager_Adapter (ACE_Allocator *alloc)
+ : implementation_ (alloc)
+{
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> ACE_INLINE
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::ACE_Map_Manager_Adapter (size_t size,
+ ACE_Allocator *alloc)
+ : implementation_ (size,
+ alloc)
+{
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> ACE_INLINE ACE_Map_Manager<KEY, VALUE, ACE_Null_Mutex> &
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::impl (void)
+{
+ return this->implementation_;
+}
+
+template <class KEY, class VALUE, class KEY_GENERATOR> ACE_INLINE KEY_GENERATOR &
+ACE_Map_Manager_Adapter<KEY, VALUE, KEY_GENERATOR>::key_generator (void)
+{
+ return this->key_generator_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Mem_Map.cpp b/ACE/ace/Mem_Map.cpp
new file mode 100644
index 00000000000..02c38699d10
--- /dev/null
+++ b/ACE/ace/Mem_Map.cpp
@@ -0,0 +1,310 @@
+// $Id$
+
+// Defines the member functions for the memory mapping facility.
+
+#include "ace/Mem_Map.h"
+#if !defined (__ACE_INLINE__)
+#include "ace/Mem_Map.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+#include "ace/Truncate.h"
+
+ACE_RCSID(ace, Mem_Map, "Mem_Map.cpp,v 4.39 2003/11/01 11:15:13 dhinton Exp")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Mem_Map)
+
+
+void
+ACE_Mem_Map::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Mem_Map::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base_addr_ = %x"), this->base_addr_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nfilename_ = %s"), this->filename_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nlength_ = %d"), this->length_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhandle_ = %d"), this->handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nfile_mapping_ = %d"), this->file_mapping_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nclose_handle_ = %d"), this->close_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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,
+ size_t length_request,
+ int prot,
+ int share,
+ void *addr,
+ ACE_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 const unmap_result = this->unmap ();
+ if (unmap_result != 0)
+ return unmap_result;
+#endif /* ACE_LACKS_AUTO_MMAP_REPLACEMENT */
+
+ this->base_addr_ = addr;
+ this->handle_ = handle;
+
+ // Get the current filesize
+ ACE_OFF_T const current_file_length = ACE_OS::filesize (this->handle_);
+
+ // Flag to indicate if we need to extend the back store
+ bool extend_backing_store = false;
+
+ // File length requested by user
+ ACE_OFF_T requested_file_length = 0;
+
+ // Check <length_request>
+ if (length_request == static_cast<size_t> (-1))
+ {
+ // Set length to file_request or size_t max.
+ this->length_ = ACE_Utils::truncate_cast<size_t> (current_file_length - offset);
+ }
+ else
+ {
+ // Make sure that we have not been asked to do the impossible.
+ if (static_cast<ACE_UINT64> (length_request)
+ + static_cast<ACE_UINT64> (offset)
+ > static_cast<ACE_UINT64> (ACE_Numeric_Limits<ACE_OFF_T>::max ()))
+ return -1;
+
+ // File length implicitly requested by user
+ requested_file_length = static_cast<ACE_OFF_T> (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 = true;
+ }
+
+ // Set length to length_request
+ this->length_ = length_request;
+ }
+
+ // Check if we need to extend the backing store.
+ if (extend_backing_store)
+ {
+ // Remember than write increases the size by one.
+ ACE_OFF_T null_byte_position = 0;
+ if (requested_file_length > 0)
+ {
+ // This will make the file size <requested_file_length>
+ null_byte_position = requested_file_length - 1;
+ }
+
+ if (ACE_OS::pwrite (this->handle_,
+ "",
+ 1,
+ null_byte_position) == -1)
+ return -1;
+ }
+
+ 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,
+ mode_t perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::open");
+
+#if defined (INTEGRITY) || defined (__QNXNTO__) || defined (ACE_VXWORKS)
+ this->handle_ = ACE_OS::shm_open (file_name, flags, perms, sa);
+#elif defined (ACE_OPENVMS)
+ ACE_OSCALL (::open (file_name, flags, perms, "shr=get,put,upd"), ACE_HANDLE, -1, this->handle_);
+#else
+ this->handle_ = ACE_OS::open (file_name, flags, perms, sa);
+#endif /* INTEGRITY */
+
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ return -1;
+ else
+ {
+ ACE_OS::strsncpy (this->filename_,
+ file_name,
+ MAXPATHLEN);
+
+ this->close_handle_ = true;
+ return 0;
+ }
+}
+
+int
+ACE_Mem_Map::map (const ACE_TCHAR *file_name,
+ size_t len,
+ int flags,
+ mode_t mode,
+ int prot,
+ int share,
+ void *addr,
+ ACE_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_ (false)
+{
+ 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,
+ size_t len,
+ int flags,
+ mode_t mode,
+ int prot,
+ int share,
+ void *addr,
+ ACE_OFF_T offset,
+ LPSECURITY_ATTRIBUTES sa)
+ : base_addr_ (MAP_FAILED),
+ length_ (0),
+ handle_ (ACE_INVALID_HANDLE),
+ file_mapping_ (ACE_INVALID_HANDLE),
+ close_handle_ (false)
+{
+ 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_TEXT ("%p\n"),
+ ACE_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,
+ size_t len,
+ int prot,
+ int share,
+ void *addr,
+ ACE_OFF_T offset,
+ LPSECURITY_ATTRIBUTES sa)
+ : base_addr_ (MAP_FAILED),
+ length_ (0),
+ handle_ (ACE_INVALID_HANDLE),
+ file_mapping_ (ACE_INVALID_HANDLE),
+ close_handle_ (false)
+{
+ 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_TEXT ("%p\n"),
+ ACE_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 (INTEGRITY) || defined (__QNXNTO__) || defined (ACE_VXWORKS)
+ return ACE_OS::shm_unlink (this->filename_);
+#else
+ return ACE_OS::unlink (this->filename_);
+#endif /* __QNXNTO__ */
+
+ else
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Mem_Map.h b/ACE/ace/Mem_Map.h
new file mode 100644
index 00000000000..2329722c9cd
--- /dev/null
+++ b/ACE/ace/Mem_Map.h
@@ -0,0 +1,235 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Mem_Map.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_MEM_MAP_H
+#define ACE_MEM_MAP_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+#include "ace/os_include/sys/os_mman.h"
+#include "ace/os_include/os_limits.h"
+#include "ace/os_include/os_fcntl.h"
+#include "ace/Default_Constants.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a handle. This function
+ /// will lookup the length of the file if it is not given.
+ ACE_Mem_Map (ACE_HANDLE handle,
+ size_t length = static_cast<size_t> (-1),
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ ACE_OFF_T offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Map a file specified by @a file_name.
+ ACE_Mem_Map (const ACE_TCHAR *filename,
+ size_t length = static_cast<size_t> (-1),
+ int flags = O_RDWR | O_CREAT,
+ mode_t mode = ACE_DEFAULT_FILE_PERMS,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ ACE_OFF_T offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Map a file from an open file descriptor @a handle. This function
+ /// will lookup the length of the file if it is not given.
+ int map (ACE_HANDLE handle,
+ size_t length = static_cast<size_t> (-1),
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ ACE_OFF_T offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Remap the file associated with <handle_>.
+ int map (size_t length = static_cast<size_t> (-1),
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ ACE_OFF_T offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Map a file specified by @a filename.
+ int map (const ACE_TCHAR *filename,
+ size_t length = static_cast<size_t> (-1),
+ int flags = O_RDWR | O_CREAT,
+ mode_t mode = ACE_DEFAULT_FILE_PERMS,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ ACE_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,
+ mode_t perms = 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 (ssize_t len = -1);
+
+ /// Unmap the region starting at <addr_>.
+ int unmap (void *addr, ssize_t len);
+
+ /**
+ * Sync @a len bytes of the memory region to the backing store
+ * starting at <base_addr_>. If @a len == -1 then sync the whole
+ * region.
+ */
+ int sync (size_t len, int flags = MS_SYNC);
+
+ /**
+ * Sync the whole memory region to the backing store
+ * starting at <base_addr_>.
+ */
+ int sync (int flags = MS_SYNC);
+
+ /// Sync @a 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 @a prot
+ * starting at <base_addr_> up to @a len bytes.
+ */
+ int protect (size_t len, int prot = PROT_RDWR);
+
+ /**
+ * Change the protection of all the pages of the mapped region to @a prot
+ * starting at <base_addr_>.
+ */
+ int protect (int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to @a prot
+ /// starting at @a addr up to @a 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:
+
+ /// This method does the dirty work of actually calling ::mmap to map
+ /// the file into memory.
+ int map_it (ACE_HANDLE handle,
+ size_t len = static_cast<size_t> (-1),
+ int prot = PROT_RDWR,
+ int share = MAP_SHARED,
+ void *addr = 0,
+ ACE_OFF_T offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ // = Disallow copying and assignment.
+ ACE_Mem_Map (const ACE_Mem_Map &);
+ void operator = (const ACE_Mem_Map &);
+
+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_;
+
+ /// Keeps track of whether we need to close the handle. This is set
+ /// if we opened the file.
+ bool close_handle_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Mem_Map.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MEM_MAP_H */
diff --git a/ACE/ace/Mem_Map.inl b/ACE/ace/Mem_Map.inl
new file mode 100644
index 00000000000..78a99646a88
--- /dev/null
+++ b/ACE/ace/Mem_Map.inl
@@ -0,0 +1,238 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_mman.h"
+#include "ace/OS_NS_sys_stat.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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,
+ size_t length,
+ int prot,
+ int share,
+ void *addr,
+ ACE_OFF_T offset,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::map");
+ return this->map_it (handle, length, prot, share, addr, offset, sa);
+}
+
+// Remap the file associated with <this->handle_>.
+
+ACE_INLINE int
+ACE_Mem_Map::map (size_t length,
+ int prot,
+ int share,
+ void *addr,
+ ACE_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 (), length, 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)
+ {
+ 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 (ssize_t len)
+{
+ ACE_TRACE ("ACE_Mem_Map::unmap");
+
+ this->close_filemapping_handle ();
+
+ if (this->base_addr_ != MAP_FAILED)
+ {
+ int const result = ACE_OS::munmap (this->base_addr_,
+ len < 0 ? this->length_ : len);
+ this->base_addr_ = MAP_FAILED;
+ return result;
+ }
+ else
+ return 0;
+}
+
+// Unmap the region starting at <addr_>.
+
+ACE_INLINE int
+ACE_Mem_Map::unmap (void *addr, ssize_t len)
+{
+ ACE_TRACE ("ACE_Mem_Map::unmap");
+
+ this->close_filemapping_handle ();
+
+ return ACE_OS::munmap (addr,
+ len < 0 ? this->length_ : len);
+}
+
+// Sync <len> bytes of the memory region to the backing store starting
+// at <this->base_addr_>.
+
+ACE_INLINE int
+ACE_Mem_Map::sync (size_t len, int flags)
+{
+ ACE_TRACE ("ACE_Mem_Map::sync");
+ return ACE_OS::msync (this->base_addr_,
+ len,
+ flags);
+}
+
+// Sync the whole mapped region.
+ACE_INLINE int
+ACE_Mem_Map::sync (int flags)
+{
+ ACE_TRACE ("ACE_Mem_Map::sync");
+ return ACE_OS::msync (this->base_addr_,
+ this->length_,
+ 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.
+
+ACE_INLINE int
+ACE_Mem_Map::protect (size_t len, int prot)
+{
+ ACE_TRACE ("ACE_Mem_Map::protect");
+ return ACE_OS::mprotect (this->base_addr_, len, prot);
+}
+
+
+// Change the protection of all the pages of the mapped region to <prot>
+// starting at <this->base_addr_>.
+
+ACE_INLINE int
+ACE_Mem_Map::protect (int prot)
+{
+ ACE_TRACE ("ACE_Mem_Map::protect");
+ return ACE_OS::mprotect (this->base_addr_, this->length_, 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");
+ const size_t advise_len =
+ len < 0 ? this->length_ : static_cast<size_t> (len);
+
+ return ACE_OS::madvise ((caddr_t) this->base_addr_,
+ advise_len,
+ behavior);
+}
+
+ACE_INLINE int
+ACE_Mem_Map::close_handle (void)
+{
+ int result = 0;
+
+ if (this->close_handle_)
+ {
+ this->close_handle_ = false;
+ result = ACE_OS::close (this->handle_);
+ this->handle_ = ACE_INVALID_HANDLE;
+ }
+
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Memory_Pool.h b/ACE/ace/Memory_Pool.h
new file mode 100644
index 00000000000..628a6e09c24
--- /dev/null
+++ b/ACE/ace/Memory_Pool.h
@@ -0,0 +1,31 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Memory_Pool.h
+ *
+ * $Id$
+ *
+ * @author Dougls C. Schmidt <schmidt@cs.wustl.edu>
+ * @author 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/Local_Memory_Pool.h"
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Sbrk_Memory_Pool.h"
+#include "ace/Shared_Memory_Pool.h"
+#include "ace/Pagefile_Memory_Pool.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MEMORY_POOL_H */
diff --git a/ACE/ace/Message_Block.cpp b/ACE/ace/Message_Block.cpp
new file mode 100644
index 00000000000..8a73512f3c2
--- /dev/null
+++ b/ACE/ace/Message_Block.cpp
@@ -0,0 +1,1273 @@
+#include "ace/Message_Block.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Message_Block.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Malloc_Base.h"
+#include "ace/OS_NS_string.h"
+
+//#define ACE_ENABLE_TIMEPROBES
+#include "ace/Timeprobe.h"
+
+ACE_RCSID (ace,
+ Message_Block,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Message_Block)
+
+#if defined (ACE_ENABLE_TIMEPROBES)
+
+static const char *ACE_MB_Timeprobe_Description[] =
+{
+ "Message_Block::init_i - enter",
+ "Message_Block::init_i - leave",
+ "Message_Block::init_i - db alloc",
+ "Message_Block::init_i - db ctor",
+ "Data_Block::ctor[1] - enter",
+ "Data_Block::ctor[1] - leave",
+ "Data_Block::ctor[2] - enter",
+ "Data_Block::ctor[2] - leave",
+ "Data_Block::clone - enter",
+ "Data_Block::clone - leave"
+};
+
+enum
+{
+ ACE_MESSAGE_BLOCK_INIT_I_ENTER = 3000,
+ ACE_MESSAGE_BLOCK_INIT_I_LEAVE,
+ ACE_MESSAGE_BLOCK_INIT_I_DB_ALLOC,
+ ACE_MESSAGE_BLOCK_INIT_I_DB_CTOR,
+ ACE_DATA_BLOCK_CTOR1_ENTER,
+ ACE_DATA_BLOCK_CTOR1_LEAVE,
+ ACE_DATA_BLOCK_CTOR2_ENTER,
+ ACE_DATA_BLOCK_CTOR2_LEAVE,
+ ACE_DATA_BLOCK_CLONE_ENTER,
+ ACE_DATA_BLOCK_CLONE_LEAVE
+};
+
+
+// Setup Timeprobes
+ACE_TIMEPROBE_EVENT_DESCRIPTIONS (ACE_MB_Timeprobe_Description,
+ ACE_MESSAGE_BLOCK_INIT_I_ENTER);
+
+#endif /* ACE_ENABLE_TIMEPROBES */
+
+void
+ACE_Message_Block::data_block (ACE_Data_Block *db)
+{
+ ACE_TRACE ("ACE_Message_Block::data_block");
+ if (ACE_BIT_DISABLED (this->flags_,
+ ACE_Message_Block::DONT_DELETE)
+ && this->data_block_ != 0)
+ this->data_block_->release ();
+
+ this->data_block_ = db;
+
+ // Set the read and write pointers in the <Message_Block> to point
+ // to the buffer in the <ACE_Data_Block>.
+ this->rd_ptr (this->data_block ()->base ());
+ this->wr_ptr (this->data_block ()->base ());
+}
+
+int
+ACE_Message_Block::copy (const char *buf, size_t n)
+{
+ ACE_TRACE ("ACE_Message_Block::copy");
+
+ /*size_t len = static_cast<size_t> (this->end () - this->wr_ptr ());*/
+ // Note that for this to work correct, end () *must* be >= mark ().
+ size_t len = this->space ();
+
+ if (len < n)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+ else
+ {
+ (void) ACE_OS::memcpy (this->wr_ptr (),
+ buf,
+ n);
+ this->wr_ptr (n);
+ return 0;
+ }
+}
+
+int
+ACE_Message_Block::copy (const char *buf)
+{
+ ACE_TRACE ("ACE_Message_Block::copy");
+
+ /* size_t len = static_cast<size_t> (this->end () - this->wr_ptr ()); */
+ // Note that for this to work correct, end() *must* be >= wr_ptr().
+ size_t len = this->space ();
+
+ size_t buflen = ACE_OS::strlen (buf) + 1;
+
+ if (len < buflen)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+ else
+ {
+ (void) ACE_OS::memcpy (this->wr_ptr (),
+ buf,
+ buflen);
+ this->wr_ptr (buflen);
+ return 0;
+ }
+}
+
+int
+ACE_Message_Block::crunch (void)
+{
+ if (this->rd_ptr_ != 0)
+ {
+ if (this->rd_ptr_ > this->wr_ptr_)
+ return -1;
+
+ size_t const len = this->length ();
+ (void) ACE_OS::memmove (this->base (),
+ this->rd_ptr (),
+ len);
+ this->rd_ptr (this->base ());
+ this->wr_ptr (this->base () + len);
+ }
+ return 0;
+}
+
+void
+ACE_Data_Block::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Data_Block::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("-----( Data Block )-----\n")
+ ACE_TEXT ("type_ = %d\n")
+ ACE_TEXT ("cur_size_ = %u\n")
+ ACE_TEXT ("max_size_ = %u\n")
+ ACE_TEXT ("flags_ = %u\n")
+ ACE_TEXT ("base_ = %u\n")
+ ACE_TEXT ("locking_strategy_ = %u\n")
+ ACE_TEXT ("reference_count_ = %u\n")
+ ACE_TEXT ("---------------------------\n"),
+ this->type_,
+ this->cur_size_,
+ this->max_size_,
+ this->flags_,
+ this->base_,
+ this->locking_strategy_,
+ this->reference_count_));
+ this->allocator_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Message_Block::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Message_Block::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("-----( Message Block )-----\n")
+ ACE_TEXT ("priority_ = %d\n")
+ ACE_TEXT ("next_ = %u\n")
+ ACE_TEXT ("prev_ = %u\n")
+ ACE_TEXT ("cont_ = %u\n")
+ ACE_TEXT ("rd_ptr_ = %u\n")
+ ACE_TEXT ("wr_ptr_ = %u\n")
+ ACE_TEXT ("---------------------------\n"),
+ this->priority_,
+ this->next_,
+ this->prev_,
+ this->cont_,
+ this->rd_ptr_,
+ this->wr_ptr_));
+ this->data_block ()->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Data_Block::reference_count (void) const
+{
+ if (this->locking_strategy_)
+ {
+ // We need to acquire the lock before retrieving the count
+ ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->locking_strategy_, 0);
+
+ return this->reference_count_i ();
+ }
+
+ return this->reference_count_i ();
+}
+
+int
+ACE_Data_Block::size (size_t length)
+{
+ ACE_TRACE ("ACE_Data_Block::size");
+
+ if (length <= this->max_size_)
+ this->cur_size_ = length;
+ else
+ {
+ // We need to resize!
+ char *buf = 0;
+ ACE_ALLOCATOR_RETURN (buf,
+ (char *) this->allocator_strategy_->malloc (length),
+ -1);
+
+ ACE_OS::memcpy (buf,
+ this->base_,
+ this->cur_size_);
+ if (ACE_BIT_DISABLED (this->flags_,
+ ACE_Message_Block::DONT_DELETE))
+ this->allocator_strategy_->free ((void *) this->base_);
+ else
+ // We now assume ownership.
+ ACE_CLR_BITS (this->flags_,
+ ACE_Message_Block::DONT_DELETE);
+ this->max_size_ = length;
+ this->cur_size_ = length;
+ this->base_ = buf;
+ }
+ return 0;
+}
+
+int
+ACE_Message_Block::size (size_t length)
+{
+ ACE_TRACE ("ACE_Message_Block::size");
+
+ // Resize the underlying <ACE_Data_Block>.
+ if (this->data_block ()->size (length) == -1)
+ return -1;
+
+ return 0;
+}
+
+void
+ACE_Message_Block::total_size_and_length (size_t &mb_size,
+ size_t &mb_length) const
+{
+ ACE_TRACE ("ACE_Message_Block::total_size_and_length");
+
+ for (const ACE_Message_Block *i = this;
+ i != 0;
+ i = i->cont ())
+ {
+ mb_size += i->size ();
+ mb_length += i->length ();
+ }
+}
+
+size_t
+ACE_Message_Block::total_size (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::total_size");
+
+ size_t size = 0;
+ for (const ACE_Message_Block *i = this;
+ i != 0;
+ i = i->cont ())
+ size += i->size ();
+
+ return size;
+}
+
+size_t
+ACE_Message_Block::total_length (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::total_length");
+
+ size_t length = 0;
+ for (const ACE_Message_Block *i = this;
+ i != 0;
+ i = i->cont ())
+ length += i->length ();
+
+ return length;
+}
+
+size_t
+ACE_Message_Block::total_capacity (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::total_capacity");
+
+ size_t size = 0;
+
+ for (const ACE_Message_Block *i = this;
+ i != 0;
+ i = i->cont ())
+ size += i->capacity ();
+
+ return size;
+}
+
+ACE_Data_Block::ACE_Data_Block (void)
+ : type_ (ACE_Message_Block::MB_DATA),
+ cur_size_ (0),
+ max_size_ (0),
+ flags_ (ACE_Message_Block::DONT_DELETE),
+ base_ (0),
+ allocator_strategy_ (0),
+ locking_strategy_ (0),
+ reference_count_ (1),
+ data_block_allocator_ (0)
+{
+ ACE_TRACE ("ACE_Data_Block::ACE_Data_Block");
+ ACE_FUNCTION_TIMEPROBE (ACE_DATA_BLOCK_CTOR1_ENTER);
+
+ ACE_ALLOCATOR (this->allocator_strategy_,
+ ACE_Allocator::instance ());
+
+ ACE_ALLOCATOR (this->data_block_allocator_,
+ ACE_Allocator::instance ());
+}
+
+ACE_Data_Block::ACE_Data_Block (size_t size,
+ ACE_Message_Block::ACE_Message_Type msg_type,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Lock *locking_strategy,
+ ACE_Message_Block::Message_Flags flags,
+ ACE_Allocator *data_block_allocator)
+ : type_ (msg_type),
+ cur_size_ (0), // Reset later if memory alloc'd ok
+ max_size_ (0),
+ flags_ (flags),
+ base_ (const_cast <char *> (msg_data)),
+ allocator_strategy_ (allocator_strategy),
+ locking_strategy_ (locking_strategy),
+ reference_count_ (1),
+ data_block_allocator_ (data_block_allocator)
+{
+ ACE_TRACE ("ACE_Data_Block::ACE_Data_Block");
+ ACE_FUNCTION_TIMEPROBE (ACE_DATA_BLOCK_CTOR2_ENTER);
+
+ // If the user didn't pass one in, let's use the
+ // <ACE_Allocator::instance>.
+ if (this->allocator_strategy_ == 0)
+ ACE_ALLOCATOR (this->allocator_strategy_,
+ ACE_Allocator::instance ());
+
+ if (this->data_block_allocator_ == 0)
+ ACE_ALLOCATOR (this->data_block_allocator_,
+ ACE_Allocator::instance ());
+
+ if (msg_data == 0)
+ {
+ ACE_ALLOCATOR (this->base_,
+ (char *) this->allocator_strategy_->malloc (size));
+#if defined (ACE_INITIALIZE_MEMORY_BEFORE_USE)
+ (void) ACE_OS::memset (this->base_,
+ '\0',
+ size);
+#endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
+ }
+
+ // ACE_ALLOCATOR returns on alloc failure but we cant throw, so setting
+ // the size to 0 (i.e. "bad bit") ...
+ if (this->base_ == 0)
+ {
+ size = 0;
+ }
+
+ // The memory is legit, whether passed in or allocated, so set
+ // the size.
+ this->cur_size_ = this->max_size_ = size;
+}
+
+ACE_Message_Block::ACE_Message_Block (const char *data,
+ size_t size,
+ unsigned long priority)
+ : flags_ (0),
+ data_block_ (0)
+{
+ ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
+
+ if (this->init_i (size, // size
+ MB_DATA, // type
+ 0, // cont
+ data, // data
+ 0, // allocator
+ 0, // locking strategy
+ ACE_Message_Block::DONT_DELETE, // flags
+ priority, // priority
+ ACE_Time_Value::zero, // execution time
+ ACE_Time_Value::max_time, // absolute time of deadline
+ 0, // data block
+ 0, // data_block allocator
+ 0) == -1) // message_block allocator
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Message_Block")));
+}
+
+ACE_Message_Block::ACE_Message_Block (ACE_Allocator *message_block_allocator)
+ : flags_ (0),
+ data_block_ (0)
+{
+ ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
+
+ if (this->init_i (0, // size
+ MB_DATA, // type
+ 0, // cont
+ 0, // data
+ 0, // allocator
+ 0, // locking strategy
+ ACE_Message_Block::DONT_DELETE, // flags
+ 0, // priority
+ ACE_Time_Value::zero, // execution time
+ ACE_Time_Value::max_time, // absolute time of deadline
+ 0, // data block
+ 0, // data_block allocator
+ message_block_allocator) == -1) // message_block allocator
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Message_Block")));
+}
+
+ACE_Message_Block::ACE_Message_Block (size_t size,
+ ACE_Message_Type msg_type,
+ ACE_Message_Block *msg_cont,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Lock *locking_strategy,
+ unsigned long priority,
+ const ACE_Time_Value &execution_time,
+ const ACE_Time_Value &deadline_time,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator)
+ :flags_ (0),
+ data_block_ (0)
+{
+ ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
+
+ if (this->init_i (size,
+ msg_type,
+ msg_cont,
+ msg_data,
+ allocator_strategy,
+ locking_strategy,
+ msg_data ? ACE_Message_Block::DONT_DELETE : 0,
+ priority,
+ execution_time,
+ deadline_time,
+ 0, // data block
+ data_block_allocator,
+ message_block_allocator) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Message_Block")));
+}
+
+int
+ACE_Message_Block::init (size_t size,
+ ACE_Message_Type msg_type,
+ ACE_Message_Block *msg_cont,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Lock *locking_strategy,
+ unsigned long priority,
+ const ACE_Time_Value &execution_time,
+ const ACE_Time_Value &deadline_time,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator)
+{
+ ACE_TRACE ("ACE_Message_Block::init");
+
+ return this->init_i (size,
+ msg_type,
+ msg_cont,
+ msg_data,
+ allocator_strategy,
+ locking_strategy,
+ msg_data ? ACE_Message_Block::DONT_DELETE : 0,
+ priority,
+ execution_time,
+ deadline_time,
+ 0, // data block
+ data_block_allocator,
+ message_block_allocator);
+}
+
+int
+ACE_Message_Block::init (const char *data,
+ size_t size)
+{
+ ACE_TRACE ("ACE_Message_Block::init");
+ // Should we also initialize all the other fields, as well?
+
+ return this->init_i (size, // size
+ MB_DATA, // type
+ 0, // cont
+ data, // data
+ 0, // allocator
+ 0, // locking strategy
+ ACE_Message_Block::DONT_DELETE, // flags
+ 0, // priority
+ ACE_Time_Value::zero, // execution time
+ ACE_Time_Value::max_time, // absolute time of deadline
+ 0, // data block
+ 0, // data_block allocator
+ 0); // message_block allocator
+}
+
+ACE_Message_Block::ACE_Message_Block (size_t size,
+ ACE_Message_Type msg_type,
+ ACE_Message_Block *msg_cont,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Lock *locking_strategy,
+ Message_Flags flags,
+ unsigned long priority,
+ const ACE_Time_Value &execution_time,
+ const ACE_Time_Value &deadline_time,
+ ACE_Data_Block *db,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator)
+ : flags_ (0),
+ data_block_ (0)
+{
+ ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
+
+ if (this->init_i (size,
+ msg_type,
+ msg_cont,
+ msg_data,
+ allocator_strategy,
+ locking_strategy,
+ flags,
+ priority,
+ execution_time,
+ deadline_time,
+ db,
+ data_block_allocator,
+ message_block_allocator) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Message_Block")));
+}
+
+ACE_Message_Block::ACE_Message_Block (ACE_Data_Block *data_block,
+ ACE_Message_Block::Message_Flags flags,
+ ACE_Allocator *message_block_allocator)
+ : flags_ (flags),
+ data_block_ (0)
+{
+ ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
+
+ if (this->init_i (0, // size
+ MB_NORMAL, // type
+ 0, // cont
+ 0, // data
+ 0, // allocator
+ 0, // locking strategy
+ 0, // flags
+ 0, // priority
+ ACE_Time_Value::zero, // execution time
+ ACE_Time_Value::max_time, // absolute time of deadline
+ data_block, // data block
+ data_block->data_block_allocator (),
+ message_block_allocator) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Message_Block")));
+}
+
+ACE_Message_Block::ACE_Message_Block (const ACE_Message_Block &mb,
+ size_t align)
+ :flags_ (0),
+ data_block_ (0)
+{
+ ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
+
+ if (ACE_BIT_DISABLED (mb.flags_,
+ ACE_Message_Block::DONT_DELETE))
+ {
+ if (this->init_i (0, // size
+ MB_NORMAL, // type
+ 0, // cont
+ 0, // data
+ 0, // allocator
+ 0, // locking strategy
+ 0, // flags
+ 0, // priority
+ ACE_Time_Value::zero, // execution time
+ ACE_Time_Value::max_time, // absolute time of deadline
+ mb.data_block ()->duplicate (), // data block
+ mb.data_block ()->data_block_allocator (),
+ mb.message_block_allocator_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Message_Block")));
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ // Align ourselves
+ char *start = ACE_ptr_align_binary (this->base (),
+ align);
+#else
+ char *start = this->base ();
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ // Set our rd & wr pointers
+ this->rd_ptr (start);
+ this->wr_ptr (start);
+
+ }
+ else
+ {
+ if (this->init_i (0, // size
+ MB_NORMAL, // type
+ 0, // cont
+ 0, // data
+ 0, // allocator
+ 0, // locking strategy
+ 0, // flags
+ 0, // priority
+ ACE_Time_Value::zero, // execution time
+ ACE_Time_Value::max_time, // absolute time of deadline
+ mb.data_block ()->clone_nocopy (),// data block
+ mb.data_block ()->data_block_allocator (),
+ mb.message_block_allocator_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Message_Block")));
+
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ // Align ourselves
+ char *start = ACE_ptr_align_binary (this->base (),
+ align);
+#else
+ char *start = this->base ();
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ // Set our rd & wr pointers
+ this->rd_ptr (start);
+ this->wr_ptr (start);
+
+#if !defined (ACE_LACKS_CDR_ALIGNMENT)
+ // Get the alignment offset of the incoming ACE_Message_Block
+ start = ACE_ptr_align_binary (mb.base (),
+ align);
+#else
+ start = mb.base ();
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+
+ // Actual offset for the incoming message block assuming that it
+ // is also aligned to the same "align" byte
+ size_t const wr_offset = mb.wr_ptr_ - (start - mb.base ());
+
+ // Copy wr_offset amount of data in to <this->data_block>
+ (void) ACE_OS::memcpy (this->wr_ptr (),
+ start,
+ wr_offset);
+
+ // Dont move the write pointer, just leave it to the application
+ // to do what it wants
+
+ }
+#if defined (ACE_LACKS_CDR_ALIGNMENT)
+ ACE_UNUSED_ARG (align);
+#endif /* ACE_LACKS_CDR_ALIGNMENT */
+}
+
+int
+ACE_Message_Block::init_i (size_t size,
+ ACE_Message_Type msg_type,
+ ACE_Message_Block *msg_cont,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Lock *locking_strategy,
+ Message_Flags flags,
+ unsigned long priority,
+ const ACE_Time_Value &execution_time,
+ const ACE_Time_Value &deadline_time,
+ ACE_Data_Block *db,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator)
+{
+ ACE_TRACE ("ACE_Message_Block::init_i");
+ ACE_FUNCTION_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_ENTER);
+
+ this->rd_ptr_ = 0;
+ this->wr_ptr_ = 0;
+ this->priority_ = priority;
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+ this->execution_time_ = execution_time;
+ this->deadline_time_ = deadline_time;
+#else
+ ACE_UNUSED_ARG (execution_time);
+ ACE_UNUSED_ARG (deadline_time);
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+ this->cont_ = msg_cont;
+ this->next_ = 0;
+ this->prev_ = 0;
+
+ this->message_block_allocator_ = message_block_allocator;
+
+ if (this->data_block_ != 0)
+ {
+ this->data_block_->release ();
+ this->data_block_ = 0;
+ }
+
+ if (db == 0)
+ {
+ if (data_block_allocator == 0)
+ ACE_ALLOCATOR_RETURN (data_block_allocator,
+ ACE_Allocator::instance (),
+ -1);
+
+ ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_ALLOC);
+
+ // Allocate the <ACE_Data_Block> portion, which is reference
+ // counted.
+ ACE_NEW_MALLOC_RETURN (db,
+ static_cast<ACE_Data_Block *> (
+ data_block_allocator->malloc (sizeof (ACE_Data_Block))),
+ ACE_Data_Block (size,
+ msg_type,
+ msg_data,
+ allocator_strategy,
+ locking_strategy,
+ flags,
+ data_block_allocator),
+ -1);
+ ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_CTOR);
+
+ // Message block initialization may fail, while the construction
+ // succeds. Since ACE may throw no exceptions, we have to do a
+ // separate check and clean up, like this:
+ if (db != 0 && db->size () < size)
+ {
+ db->ACE_Data_Block::~ACE_Data_Block(); // placement destructor ...
+ data_block_allocator->free (db); // free ...
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ // Reset the data_block_ pointer.
+ this->data_block (db);
+
+ return 0;
+}
+
+ACE_Data_Block::~ACE_Data_Block (void)
+{
+ // Sanity check...
+ ACE_ASSERT (this->reference_count_ <= 1);
+
+ // Just to be safe...
+ this->reference_count_ = 0;
+
+ if (ACE_BIT_DISABLED (this->flags_,
+ ACE_Message_Block::DONT_DELETE))
+ {
+ this->allocator_strategy_->free ((void *) this->base_);
+ this->base_ = 0;
+ }
+}
+
+ACE_Data_Block *
+ACE_Data_Block::release_i (void)
+{
+ ACE_TRACE ("ACE_Data_Block::release_i");
+
+ ACE_ASSERT (this->reference_count_ > 0);
+
+ ACE_Data_Block *result = 0;
+
+ // decrement reference count
+ --this->reference_count_;
+
+ if (this->reference_count_ == 0)
+ // this will cause deletion of this
+ result = 0;
+ else
+ result = this;
+
+ return result;
+}
+
+ACE_Data_Block *
+ACE_Data_Block::release_no_delete (ACE_Lock *lock)
+{
+ ACE_TRACE ("ACE_Data_Block::release_no_delete");
+
+ ACE_Data_Block *result = 0;
+ ACE_Lock *lock_to_be_used = 0;
+
+ // Check if we were passed in a lock
+ if (lock != 0)
+ {
+ // Make sure that the lock passed in and our lock are the same
+ if (lock == this->locking_strategy_)
+ // In this case no locking is required.
+ lock_to_be_used = 0;
+
+ // The lock passed in does not match our lock
+ else
+ // Lock to be used is our lock
+ lock_to_be_used = this->locking_strategy_;
+ }
+ // This is the case when no lock was passed in
+ else
+ // Lock to be used is our lock
+ lock_to_be_used = this->locking_strategy_;
+
+ // If there's a locking strategy then we need to acquire the lock
+ // before decrementing the count.
+ if (lock_to_be_used != 0)
+ {
+ ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock_to_be_used, 0);
+
+ result = this->release_i ();
+ }
+ else
+ result = this->release_i ();
+
+ return result;
+}
+
+ACE_Data_Block *
+ACE_Data_Block::release (ACE_Lock *lock)
+{
+ ACE_TRACE ("ACE_Data_Block::release");
+
+ ACE_Allocator *allocator = this->data_block_allocator_;
+
+ ACE_Data_Block *result = this->release_no_delete (lock);
+
+ // We must delete this outside the scope of the locking_strategy_
+ // since otherwise we'd be trying to "release" through a deleted
+ // pointer!
+ if (result == 0)
+ ACE_DES_FREE (this,
+ allocator->free,
+ ACE_Data_Block);
+ return result;
+}
+
+ACE_Message_Block *
+ACE_Message_Block::release (void)
+{
+ ACE_TRACE ("ACE_Message_Block::release");
+
+ // We want to hold the data block in a temporary variable because we
+ // invoked "delete this;" at some point, so using this->data_block_
+ // could be a bad idea.
+ ACE_Data_Block *tmp = this->data_block ();
+
+ // This flag is set to 1 when we have to destroy the data_block
+ int destroy_dblock = 0;
+
+ ACE_Lock *lock = 0;
+
+ // Do we have a valid data block
+ if (this->data_block ())
+ {
+ // Grab the lock that belongs to my data block
+ lock = this->data_block ()->locking_strategy ();
+
+ // if we have a lock
+ if (lock != 0)
+ {
+ // One guard for all
+ ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock, 0);
+
+ // Call non-guarded release with <lock>
+ destroy_dblock = this->release_i (lock);
+ }
+ // This is the case when we have a valid data block but no lock
+ else
+ // Call non-guarded release with no lock
+ destroy_dblock = this->release_i (0);
+ }
+ else
+ // This is the case when we don't even have a valid data block
+ destroy_dblock = this->release_i (0);
+
+ if (destroy_dblock != 0)
+ {
+ ACE_Allocator *allocator = tmp->data_block_allocator ();
+ ACE_DES_FREE (tmp,
+ allocator->free,
+ ACE_Data_Block);
+ }
+
+ return 0;
+}
+
+int
+ACE_Message_Block::release_i (ACE_Lock *lock)
+{
+ ACE_TRACE ("ACE_Message_Block::release_i");
+
+ // Free up all the continuation messages.
+ if (this->cont_)
+ {
+ ACE_Message_Block *mb = this->cont_;
+ ACE_Message_Block *tmp = 0;
+
+ do
+ {
+ tmp = mb;
+ mb = mb->cont_;
+ tmp->cont_ = 0;
+
+ ACE_Data_Block *db = tmp->data_block ();
+ if (tmp->release_i (lock) != 0)
+ {
+ ACE_Allocator *allocator = db->data_block_allocator ();
+ ACE_DES_FREE (db,
+ allocator->free,
+ ACE_Data_Block);
+ }
+ }
+ while (mb);
+
+ this->cont_ = 0;
+ }
+
+ int result = 0;
+
+ if (ACE_BIT_DISABLED (this->flags_,
+ ACE_Message_Block::DONT_DELETE) &&
+ this->data_block ())
+ {
+ if (this->data_block ()->release_no_delete (lock) == 0)
+ result = 1;
+ this->data_block_ = 0;
+ }
+
+ // We will now commit suicide: this object *must* have come from the
+ // allocator given.
+ if (this->message_block_allocator_ == 0)
+ delete this;
+ else
+ {
+ ACE_Allocator *allocator = this->message_block_allocator_;
+ ACE_DES_FREE (this,
+ allocator->free,
+ ACE_Message_Block);
+ }
+
+ return result;
+}
+
+/* static */ ACE_Message_Block *
+ACE_Message_Block::release (ACE_Message_Block *mb)
+{
+ ACE_TRACE ("ACE_Message_Block::release");
+
+ if (mb != 0)
+ return mb->release ();
+ else
+ return 0;
+}
+
+ACE_Message_Block::~ACE_Message_Block (void)
+{
+ ACE_TRACE ("ACE_Message_Block::~ACE_Message_Block");
+
+ if (ACE_BIT_DISABLED (this->flags_,
+ ACE_Message_Block::DONT_DELETE)&&
+ this->data_block ())
+ this->data_block ()->release ();
+
+ this->prev_ = 0;
+ this->next_ = 0;
+}
+
+ACE_Data_Block *
+ACE_Data_Block::duplicate (void)
+{
+ ACE_TRACE ("ACE_Data_Block::duplicate");
+
+ // Create a new <ACE_Message_Block>, but share the <base_> pointer
+ // data (i.e., don't copy that).
+ if (this->locking_strategy_)
+ {
+ // We need to acquire the lock before incrementing the count.
+ ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->locking_strategy_, 0);
+ ++this->reference_count_;
+ }
+ else
+ ++this->reference_count_;
+
+ return this;
+}
+
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+#define ACE_EXECUTION_TIME this->execution_time_
+#define ACE_DEADLINE_TIME this->deadline_time_
+#else
+#define ACE_EXECUTION_TIME ACE_Time_Value::zero
+#define ACE_DEADLINE_TIME ACE_Time_Value::max_time
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+
+ACE_Message_Block *
+ACE_Message_Block::duplicate (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::duplicate");
+
+ ACE_Message_Block *nb = 0;
+
+ // Create a new <ACE_Message_Block> that contains unique copies of
+ // the message block fields, but a reference counted duplicate of
+ // the <ACE_Data_Block>.
+
+ // If there is no allocator, use the standard new and delete calls.
+ if (this->message_block_allocator_ == 0)
+ ACE_NEW_RETURN (nb,
+ ACE_Message_Block (0, // size
+ ACE_Message_Type (0), // type
+ 0, // cont
+ 0, // data
+ 0, // allocator
+ 0, // locking strategy
+ 0, // flags
+ this->priority_, // priority
+ ACE_EXECUTION_TIME,
+ ACE_DEADLINE_TIME,
+ // Get a pointer to a
+ // "duplicated" <ACE_Data_Block>
+ // (will simply increment the
+ // reference count).
+ this->data_block ()->duplicate (),
+ this->data_block ()->data_block_allocator (),
+ this->message_block_allocator_),
+ 0);
+ else // Otherwise, use the message_block_allocator passed in.
+ ACE_NEW_MALLOC_RETURN (nb,
+ static_cast<ACE_Message_Block*> (
+ message_block_allocator_->malloc (sizeof (ACE_Message_Block))),
+ ACE_Message_Block (0, // size
+ ACE_Message_Type (0), // type
+ 0, // cont
+ 0, // data
+ 0, // allocator
+ 0, // locking strategy
+ 0, // flags
+ this->priority_, // priority
+ ACE_EXECUTION_TIME,
+ ACE_DEADLINE_TIME,
+ // Get a pointer to a
+ // "duplicated" <ACE_Data_Block>
+ // (will simply increment the
+ // reference count).
+ this->data_block ()->duplicate (),
+ this->data_block ()->data_block_allocator (),
+ this->message_block_allocator_),
+ 0);
+
+ // Set the read and write pointers in the new <Message_Block> to the
+ // same relative offset as in the existing <Message_Block>. Note
+ // that we are assuming that the data_block()->base() pointer
+ // doesn't change when it's duplicated.
+ nb->rd_ptr (this->rd_ptr_);
+ nb->wr_ptr (this->wr_ptr_);
+
+ // Increment the reference counts of all the continuation messages.
+ if (this->cont_)
+ {
+ nb->cont_ = this->cont_->duplicate ();
+
+ // If things go wrong, release all of our resources and return
+ // 0.
+ if (nb->cont_ == 0)
+ {
+ nb->release ();
+ nb = 0;
+ }
+ }
+
+ return nb;
+}
+
+ACE_Message_Block *
+ACE_Message_Block::duplicate (const ACE_Message_Block *mb)
+{
+ ACE_TRACE ("ACE_Message_Block::duplicate");
+ if (mb == 0)
+ return 0;
+ else
+ return mb->duplicate ();
+}
+
+ACE_Data_Block *
+ACE_Data_Block::clone (ACE_Message_Block::Message_Flags mask) const
+{
+ ACE_TRACE ("ACE_Data_Block::clone");
+
+ ACE_Data_Block *nb = this->clone_nocopy (mask);
+
+ // Copy all of the payload memory into the new object. The new block
+ // was allocated with max_size_ (and, thus, it's cur_size_ is the same
+ // as max_size_). Maintain the same "has been written" boundary in the
+ // new block by only copying cur_size_ bytes.
+ if (nb != 0)
+ {
+ ACE_OS::memcpy (nb->base_,
+ this->base_,
+ this->cur_size_);
+ }
+
+ return nb;
+}
+
+ACE_Data_Block *
+ACE_Data_Block::clone_nocopy (ACE_Message_Block::Message_Flags mask,
+ size_t max_size) const
+{
+ ACE_FUNCTION_TIMEPROBE(ACE_DATA_BLOCK_CLONE_ENTER);
+
+ ACE_TRACE ("ACE_Data_Block::clone_nocopy");
+
+ // You always want to clear this one to prevent memory leaks but you
+ // might add some others later.
+ const ACE_Message_Block::Message_Flags always_clear =
+ ACE_Message_Block::DONT_DELETE;
+
+ const size_t newsize =
+ max_size == 0 ? this->max_size_ : max_size;
+
+ ACE_Data_Block *nb = 0;
+
+ ACE_NEW_MALLOC_RETURN (nb,
+ static_cast<ACE_Data_Block*> (
+ this->data_block_allocator_->malloc (sizeof (ACE_Data_Block))),
+ ACE_Data_Block (newsize, // size
+ this->type_, // type
+ 0, // data
+ this->allocator_strategy_, // allocator
+ this->locking_strategy_, // locking strategy
+ this->flags_, // flags
+ this->data_block_allocator_),
+ 0);
+
+ // Message block initialization may fail while the construction
+ // succeds. Since as a matter of policy, ACE may throw no
+ // exceptions, we have to do a separate check like this.
+ if (nb != 0 && nb->size () < newsize)
+ {
+ nb->ACE_Data_Block::~ACE_Data_Block(); // placement destructor ...
+ this->data_block_allocator_->free (nb); // free ...
+ errno = ENOMEM;
+ return 0;
+ }
+
+
+ // Set new flags minus the mask...
+ nb->clr_flags (mask | always_clear);
+ return nb;
+}
+
+ACE_Message_Block *
+ACE_Message_Block::clone (Message_Flags mask) const
+{
+ ACE_TRACE ("ACE_Message_Block::clone");
+
+ // Get a pointer to a "cloned" <ACE_Data_Block> (will copy the
+ // values rather than increment the reference count).
+ ACE_Data_Block *db = this->data_block ()->clone (mask);
+
+ if (db == 0)
+ return 0;
+
+ ACE_Message_Block *nb = 0;
+
+ if(message_block_allocator_ == 0)
+ {
+ ACE_NEW_RETURN (nb,
+ ACE_Message_Block (0, // size
+ ACE_Message_Type (0), // type
+ 0, // cont
+ 0, // data
+ 0, // allocator
+ 0, // locking strategy
+ 0, // flags
+ this->priority_, // priority
+ ACE_EXECUTION_TIME, // execution time
+ ACE_DEADLINE_TIME, // absolute time to deadline
+ // Get a pointer to a
+ // "duplicated" <ACE_Data_Block>
+ // (will simply increment the
+ // reference count).
+ db,
+ db->data_block_allocator (),
+ this->message_block_allocator_),
+ 0);
+ }
+ else
+ {
+ // This is the ACE_NEW_MALLOC macro with the return check removed.
+ // We need to do it this way because if it fails we need to release
+ // the cloned data block that was created above. If we used
+ // ACE_NEW_MALLOC_RETURN, there would be a memory leak because the
+ // above db pointer would be left dangling.
+ nb = static_cast<ACE_Message_Block*> (message_block_allocator_->malloc (sizeof (ACE_Message_Block)));
+ if(nb != 0)
+ new (nb) ACE_Message_Block (0, // size
+ ACE_Message_Type (0), // type
+ 0, // cont
+ 0, // data
+ 0, // allocator
+ 0, // locking strategy
+ 0, // flags
+ this->priority_, // priority
+ ACE_EXECUTION_TIME, // execution time
+ ACE_DEADLINE_TIME, // absolute time to deadline
+ db,
+ db->data_block_allocator (),
+ this->message_block_allocator_);
+ }
+
+ if (nb == 0)
+ {
+ db->release ();
+ return 0;
+ }
+
+ // Set the read and write pointers in the new <Message_Block> to the
+ // same relative offset as in the existing <Message_Block>.
+ nb->rd_ptr (this->rd_ptr_);
+ nb->wr_ptr (this->wr_ptr_);
+
+ // Clone all the continuation messages if necessary.
+ if (this->cont () != 0
+ && (nb->cont_ = this->cont ()->clone (mask)) == 0)
+ {
+ nb->release ();
+ return 0;
+ }
+ return nb;
+}
+
+// This is private.
+ACE_Message_Block &
+ACE_Message_Block::operator= (const ACE_Message_Block &)
+{
+ ACE_TRACE ("ACE_Message_Block::operator=");
+ return *this;
+}
+
+void
+ACE_Data_Block::base (char *msg_data,
+ size_t msg_length,
+ ACE_Message_Block::Message_Flags msg_flags)
+{
+ if (ACE_BIT_DISABLED (this->flags_,
+ ACE_Message_Block::DONT_DELETE))
+ this->allocator_strategy_->free (this->base_);
+
+ this->max_size_ = msg_length;
+ this->cur_size_ = msg_length;
+ this->base_ = msg_data;
+ this->flags_ = msg_flags;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Message_Block.h b/ACE/ace/Message_Block.h
new file mode 100644
index 00000000000..e8906c94048
--- /dev/null
+++ b/ACE/ace/Message_Block.h
@@ -0,0 +1,871 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Message_Block.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_MESSAGE_BLOCK_H
+#define ACE_MESSAGE_BLOCK_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Default_Constants.h"
+#include "ace/Global_Macros.h"
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration.
+class ACE_Allocator;
+class ACE_Data_Block;
+class ACE_Lock;
+
+
+/**
+ * @class ACE_Message_Block
+ *
+ * @brief Stores messages for use throughout ACE (particularly
+ * in an ACE_Message_Queue).
+ *
+ * An ACE_Message_Block is modeled after the message data
+ * structures used in System V STREAMS. Its purpose is to
+ * enable efficient manipulation of arbitrarily large messages
+ * without incurring much memory copying overhead. Here are the
+ * main characteristics of an ACE_Message_Block:
+ * - Contains a pointer to a reference-counted
+ * ACE_Data_Block, which in turn points to the actual data
+ * buffer. This allows very flexible and efficient sharing of
+ * data by multiple ACE_Message_Block objects.
+ * - One or more ACE_Message_Blocks can be linked to form a
+ * ``fragment chain.''
+ * - ACE_Message_Blocks can be linked together in a doubly linked fashion
+ * to form a queue of messages (this is how ACE_Message_Queue works).
+ *
+ * @see C++NPv1, section 4.2; APG, section 12.3.2.
+ */
+class ACE_Export ACE_Message_Block
+{
+public:
+ friend class ACE_Data_Block;
+
+ enum
+ {
+ // = Data and proto
+ /// Undifferentiated data message
+ MB_DATA = 0x01,
+ /// Undifferentiated protocol control
+ MB_PROTO = 0x02,
+
+ // = Control messages
+ /// Line break (regular and priority)
+ MB_BREAK = 0x03,
+ /// Pass file pointer
+ MB_PASSFP = 0x04,
+ /// Post an event to an event queue
+ MB_EVENT = 0x05,
+ /// Generate process signal
+ MB_SIG = 0x06,
+ /// ioctl; set/get params
+ MB_IOCTL = 0x07,
+ /// Set various stream head options
+ MB_SETOPTS = 0x08,
+
+ // = Control messages
+ /// Acknowledge ioctl (high priority; go to head of queue)
+ MB_IOCACK = 0x81,
+ /// Negative ioctl acknowledge
+ MB_IOCNAK = 0x82,
+ /// Priority proto message
+ MB_PCPROTO = 0x83,
+ /// Generate process signal
+ MB_PCSIG = 0x84,
+ /// Generate read notification
+ MB_READ = 0x85,
+ /// Flush your queues
+ MB_FLUSH = 0x86,
+ /// Stop transmission immediately
+ MB_STOP = 0x87,
+ /// Restart transmission after stop
+ MB_START = 0x88,
+ /// Line disconnect
+ MB_HANGUP = 0x89,
+ /// Fatal error used to set u.u_error
+ MB_ERROR = 0x8a,
+ /// Post an event to an event queue
+ MB_PCEVENT = 0x8b,
+
+ // = Message class masks
+ /// Normal priority message mask
+ MB_NORMAL = 0x00,
+ /// High priority control message mask
+ MB_PRIORITY = 0x80,
+ /// User-defined message mask
+ MB_USER = 0x200
+ };
+
+ typedef int ACE_Message_Type;
+ typedef unsigned long Message_Flags;
+
+ enum
+ {
+ /// Don't delete the data on exit since we don't own it.
+ DONT_DELETE = 01,
+ /// user defined flags start here
+ USER_FLAGS = 0x1000
+ };
+
+ // = Initialization and termination.
+ /// Create an empty message.
+ ACE_Message_Block (ACE_Allocator *message_block_allocator = 0);
+
+ /**
+ * Create an ACE_Message_Block that owns the specified ACE_Data_Block
+ * without copying it. If the @a flags is set to @c DONT_DELETE we
+ * don't delete the ACE_Data_Block. It is left to the client's
+ * responsibility to take care of the memory allocated for the
+ * data_block
+ */
+ ACE_Message_Block (ACE_Data_Block *,
+ Message_Flags flags = 0,
+ ACE_Allocator *message_block_allocator = 0);
+
+ /**
+ * Create an ACE_Message_Block that refers to @a data without
+ * copying it. The @a data memory will not be freed when this block is
+ * destroyed; memory management of @a data is left to the caller.
+ * Note that the @c size of the new ACE_Message_Block will be @a size, but
+ * the @c length will be 0 until the write pointer is changed.
+ */
+ ACE_Message_Block (const char *data,
+ size_t size = 0,
+ unsigned long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY);
+
+ /**
+ * Create an initialized message of type @a type containing @a size
+ * bytes. The @a cont argument initializes the continuation field in
+ * the ACE_Message_Block. If @a data == 0 then this block allocates and
+ * owns the block's memory, using @a allocator to get the data if it's
+ * non-0. If @a data != 0 then this block refers to that memory until
+ * this this block ceases to exist; this object will not free @a data on
+ * destruction. If @a locking_strategy is non-0 then this is used
+ * to protect regions of code that access shared state (e.g.,
+ * reference counting) from race conditions. Note that the @c size
+ * of the ACE_Message_Block will be @a size, but the @c length will be 0
+ * until the write pointer is set. The @a data_block_allocator is used to
+ * allocate the data blocks while the @a allocator_strategy is used
+ * to allocate the buffers contained by those. The
+ * @a message_block_allocator is used to allocate new ACE_Message_Block
+ * objects when the duplicate() method is called. If a
+ * @a message_block_allocator is given, this ACE_Message_Block and
+ * future ACE_Message_Block objects created by duplicate() will be
+ * freed using this allocator when they are released.
+ * @note If you use this allocator, the ACE_Message_Block you created
+ * should have been created using this allocator because it will be
+ * released to the same allocator.
+ */
+ ACE_Message_Block (size_t size,
+ ACE_Message_Type type = MB_DATA,
+ ACE_Message_Block *cont = 0,
+ const char *data = 0,
+ ACE_Allocator *allocator_strategy = 0,
+ ACE_Lock *locking_strategy = 0,
+ unsigned long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY,
+ const ACE_Time_Value &execution_time = ACE_Time_Value::zero,
+ const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time,
+ ACE_Allocator *data_block_allocator = 0,
+ ACE_Allocator *message_block_allocator = 0);
+
+ /**
+ * A copy constructor. This constructor is a bit different. If the
+ * incoming Message Block has a data block from the stack this
+ * constructor does a deep copy ie. allocates a new data block on
+ * the heap and does a copy of the data from the incoming message
+ * block. As a final note, the alignment information is used to
+ * align the data block if it is created afresh. If the incoming
+ * @a mb has a data block has a data block allocated from the heap,
+ * then this constructor just duplicates (ie. a shallow copy) the
+ * data block of the incoming @a mb.
+ */
+ ACE_Message_Block (const ACE_Message_Block &mb,
+ size_t align);
+
+ /**
+ * Create a Message Block that assumes it has ownership of @a data,
+ * but in reality it doesnt (i.e., cannot delete it since it didn't
+ * malloc it!). Note that the @c size of the Message_Block will
+ * be @a size, but the @a length will be 0 until <wr_ptr> is set.
+ */
+ int init (const char *data,
+ size_t size = 0);
+
+ /**
+ * Create an initialized message of type @a type containing @a size
+ * bytes. The @a cont argument initializes the continuation field in
+ * the <Message_Block>. If @a data == 0 then we create and own the
+ * @a data, using @a allocator_strategy to get the data if it's non-0. If
+ * @a data != 0 we assume that we have ownership of the @a data till
+ * this object ceases to exist (and don't delete it during
+ * destruction). If @a locking_strategy is non-0 then this is used
+ * to protect regions of code that access shared state (e.g.,
+ * reference counting) from race conditions. Note that the @a size
+ * of the <Message_Block> will be @a size, but the @a length will be 0
+ * until <wr_ptr> is set. The @a data_block_allocator is use to
+ * allocate the data blocks while the @a allocator_strategy is used
+ * to allocate the buffers contained by those.
+ */
+ int init (size_t size,
+ ACE_Message_Type type = MB_DATA,
+ ACE_Message_Block *cont = 0,
+ const char *data = 0,
+ ACE_Allocator *allocator_strategy = 0,
+ ACE_Lock *locking_strategy = 0,
+ unsigned long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY,
+ const ACE_Time_Value &execution_time = ACE_Time_Value::zero,
+ const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time,
+ ACE_Allocator *data_block_allocator = 0,
+ ACE_Allocator *message_block_allocator = 0);
+
+ /**
+ * Delete all the resources held in the message.
+ *
+ * Note that <release()> is designed to release the continuation
+ * chain; the destructor is not. See <release()> for details.
+ */
+ virtual ~ACE_Message_Block (void);
+
+ // = Message Type accessors and mutators.
+
+ /// Get type of the message.
+ ACE_Message_Type msg_type (void) const;
+
+ /// Set type of the message.
+ void msg_type (ACE_Message_Type type);
+
+ /// Find out what type of message this is.
+ int is_data_msg (void) const;
+
+ /// Find out what class of message this is (there are two classes,
+ /// @c normal messages and @c high-priority messages).
+ ACE_Message_Type msg_class (void) const;
+
+ // = Message flag accessors and mutators.
+ /// Bitwise-or the @a more_flags into the existing message flags and
+ /// return the new value.
+ Message_Flags set_flags (Message_Flags more_flags);
+
+ /// Clear the message flag bits specified in @a less_flags and return
+ /// the new value.
+ Message_Flags clr_flags (Message_Flags less_flags);
+
+ /// Get the current message flags.
+ Message_Flags flags (void) const;
+
+ // = Data Block flag accessors and mutators.
+ /// Bitwise-or the @a more_flags into the existing message flags and
+ /// return the new value.
+ /* @todo: I think the following set of methods could not be used at
+ * all. May be they are useless. Let us have it so that we dont
+ * mess up memory management of the Message_Block. Somebody correct
+ * me if I am totally totally wrong..
+ */
+ Message_Flags set_self_flags (ACE_Message_Block::Message_Flags more_flags);
+
+ /// Clear the message flag bits specified in @a less_flags and return
+ /// the new value.
+ Message_Flags clr_self_flags (ACE_Message_Block::Message_Flags less_flags);
+
+ /// Get the current message flags.
+ Message_Flags self_flags (void) const;
+
+ /// Get priority of the message.
+ unsigned long msg_priority (void) const;
+
+ /// Set priority of the message.
+ void msg_priority (unsigned long priority);
+
+ /// Get execution time associated with the message.
+ const ACE_Time_Value &msg_execution_time (void) const;
+
+ /// Set execution time associated with the message.
+ void msg_execution_time (const ACE_Time_Value &et);
+
+ /// Get absolute time of deadline associated with the message.
+ const ACE_Time_Value &msg_deadline_time (void) const;
+
+ /// Set absolute time of deadline associated with the message.
+ void msg_deadline_time (const ACE_Time_Value &dt);
+
+ // = Deep copy and shallow copy methods.
+
+ /// Return an exact "deep copy" of the message, i.e., create fresh
+ /// new copies of all the Data_Blocks and continuations.
+ virtual ACE_Message_Block *clone (Message_Flags mask = 0) const;
+
+ /// Return a "shallow" copy that increments our reference count by 1.
+ virtual ACE_Message_Block *duplicate (void) const;
+
+ /**
+ * Return a "shallow" copy that increments our reference count by 1.
+ * This is similar to CORBA's <_duplicate> method, which is useful
+ * if you want to eliminate lots of checks for NULL @a mb pointers
+ * before calling <_duplicate> on them.
+ */
+ static ACE_Message_Block *duplicate (const ACE_Message_Block *mb);
+
+ /**
+ * Decrease the shared ACE_Data_Block's reference count by 1. If the
+ * ACE_Data_Block's reference count goes to 0, it is deleted.
+ * In all cases, this ACE_Message_Block is deleted - it must have come
+ * from the heap, or there will be trouble.
+ *
+ * release() is designed to release the continuation chain; the
+ * destructor is not. If we make the destructor release the
+ * continuation chain by calling release() or delete on the message
+ * blocks in the continuation chain, the following code will not
+ * work since the message block in the continuation chain is not off
+ * the heap:
+ *
+ * ACE_Message_Block mb1 (1024);
+ * ACE_Message_Block mb2 (1024);
+ *
+ * mb1.cont (&mb2);
+ *
+ * And hence, call release() on a dynamically allocated message
+ * block. This will release all the message blocks in the
+ * continuation chain. If you call delete or let the message block
+ * fall off the stack, cleanup of the message blocks in the
+ * continuation chain becomes the responsibility of the user.
+ *
+ * @retval 0, always, and the object this method was invoked on is no
+ * longer valid.
+ */
+ virtual ACE_Message_Block *release (void);
+
+ /**
+ * This behaves like the non-static method <release>, except that it
+ * checks if @a mb is 0. This is similar to <CORBA::release>, which
+ * is useful if you want to eliminate lots of checks for NULL
+ * pointers before calling <release> on them. Returns @a mb.
+ */
+ static ACE_Message_Block *release (ACE_Message_Block *mb);
+
+ // = Operations on Message data
+
+ /**
+ * Copies data into this ACE_Message_Block. Data is copied into the
+ * block starting at the current write pointer.
+ *
+ * @param buf Pointer to the buffer to copy from.
+ * @param n The number of bytes to copy.
+ *
+ * @retval 0 on success; the write pointer is advanced by @arg n.
+ * @retval -1 if the amount of free space following the write pointer
+ * in the block is less than @arg n. Free space can be checked
+ * by calling space().
+ */
+ int copy (const char *buf, size_t n);
+
+ /**
+ * Copies a 0-terminated character string into this ACE_Message_Block.
+ * The string is copied into the block starting at the current write
+ * pointer. The 0-terminator is included in the copied data.
+ *
+ * @param buf Pointer to the character string to copy from.
+ *
+ * @retval 0 on success; the write pointer is advanced by the string's
+ * length, including the 0 terminator.
+ * @retval -1 if the amount of free space following the write pointer
+ * in the block is less than required to hold the entire string.
+ * Free space can be checked by calling space().
+ */
+ int copy (const char *buf);
+
+ /// Normalizes data in the top-level <Message_Block> to align with the base,
+ /// i.e., it "shifts" the data pointed to by <rd_ptr> down to the <base> and
+ /// then readjusts <rd_ptr> to point to <base> and <wr_ptr> to point
+ /// to <base> + the length of the moved data. Returns -1 and does
+ /// nothing if the <rd_ptr> is > <wr_ptr>, else 0 on success.
+ int crunch (void);
+
+ /// Resets the Message Block data to contain nothing, i.e., sets the
+ /// read and write pointers to align with the base.
+ void reset (void);
+
+ /// Access all the allocators in the message block.
+ /// @@todo: Not sure whether we would need finer control while
+ /// trying to access allocators ie. a method for every allocator.
+ /**
+ * This method returns the allocators only from the first message
+ * block in the chain.
+ *
+ * @param allocator_strategy Strategy used to allocate the
+ * underlying buffer
+ *
+ * @param data_block_allocator Strategy used to allocate the
+ * underlying data block
+ *
+ * @param message_block_allocator Strategy used to allocate the
+ * message block
+ */
+ void access_allocators (ACE_Allocator *&allocator_strategy,
+ ACE_Allocator *&data_block_allocator,
+ ACE_Allocator *&message_block_allocator);
+
+ /// Reset all the allocators in the message block.
+ /// @todo Not sure whether we would need finer control while
+ /// trying to reset allocators ie. a method for every allocator.
+ /**
+ * This method resets the allocators in all the message blocks in
+ * the chain.
+ */
+ void reset_allocators (ACE_Allocator *allocator_strategy = 0,
+ ACE_Allocator *data_block_allocator = 0,
+ ACE_Allocator *message_block_allocator = 0);
+
+ /// Get message data.
+ char *base (void) const;
+
+ /// Set message data (doesn't reallocate).
+ void base (char *data,
+ size_t size,
+ Message_Flags = DONT_DELETE);
+
+ /// Return a pointer to 1 past the end of the allocated data in a message.
+ char *end (void) const;
+
+ /**
+ * Return a pointer to 1 past the end of the allotted data in a message.
+ * Allotted data may be less than allocated data if a value smaller than
+ * capacity() to is passed to size().
+ */
+ char *mark (void) const;
+
+ /// Get the read pointer.
+ char *rd_ptr (void) const;
+
+ /// Set the read pointer to @a ptr.
+ void rd_ptr (char *ptr);
+
+ /// Set the read pointer ahead @a n bytes.
+ void rd_ptr (size_t n);
+
+ /// Get the write pointer.
+ char *wr_ptr (void) const;
+
+ /// Set the write pointer to @a ptr.
+ void wr_ptr (char *ptr);
+
+ /// Set the write pointer ahead @a n bytes. This is used to compute
+ /// the <length> of a message.
+ void wr_ptr (size_t n);
+
+ /** @name Message length and size operations
+ *
+ * Message length is (wr_ptr - rd_ptr).
+ *
+ * Message size is capacity of the message, including data outside
+ * the [rd_ptr,wr_ptr] range.
+ */
+ //@{
+ /// Get the length of the message
+ size_t length (void) const;
+
+ /// Set the length of the message
+ void length (size_t n);
+
+ /// Get the length of the <Message_Block>s, including chained
+ /// <Message_Block>s.
+ size_t total_length (void) const;
+
+ /// Get the total number of bytes in all <Message_Block>s, including
+ /// chained <Message_Block>s.
+ size_t total_size (void) const;
+
+ /// Get the total number of bytes and total length in all
+ /// <Message_Block>s, including chained <Message_Block>s.
+ void total_size_and_length (size_t &mb_size,
+ size_t &mb_length) const;
+
+ /// Get the number of bytes in the top-level <Message_Block> (i.e.,
+ /// does not consider the bytes in chained <Message_Block>s).
+ size_t size (void) const;
+
+ /**
+ * Set the number of bytes in the top-level <Message_Block>,
+ * reallocating space if necessary. However, the <rd_ptr_> and
+ * <wr_ptr_> remain at the original offsets into the buffer, even if
+ * it is reallocated. Returns 0 if successful, else -1.
+ */
+ int size (size_t length);
+
+ /// Get the number of allocated bytes in all <Message_Block>, including
+ /// chained <Message_Block>s.
+ size_t total_capacity (void) const;
+
+ /// Get the number of allocated bytes in the top-level <Message_Block>.
+ size_t capacity (void) const;
+
+ /// Get the number of bytes available after the <wr_ptr_> in the
+ /// top-level <Message_Block>.
+ size_t space (void) const;
+ //@}
+
+ // = ACE_Data_Block methods.
+
+ /**
+ * Get a pointer to the data block. Note that the ACE_Message_Block
+ * still references the block; this call does not change the reference
+ * count.
+ */
+ ACE_Data_Block *data_block (void) const;
+
+ /**
+ * Set a new data block pointer. The original ACE_Data_Block is released
+ * as a result of this call. If you need to keep the original block, call
+ * <replace_data_block> instead. Upon return, this ACE_Message_Block
+ * holds a pointer to the new ACE_Data_Block, taking over the reference
+ * you held on it prior to the call.
+ */
+ void data_block (ACE_Data_Block *);
+
+ /// Set a new data block pointer. A pointer to the original ACE_Data_Block
+ /// is returned, and not released (as it is with <data_block>).
+ ACE_Data_Block *replace_data_block (ACE_Data_Block*);
+
+ // = The continuation field chains together composite messages.
+ /// Get the continuation field.
+ ACE_Message_Block *cont (void) const;
+
+ /// Set the continuation field.
+ void cont (ACE_Message_Block *);
+
+ // = Pointer to the <Message_Block> directly ahead in the ACE_Message_Queue.
+ /// Get link to next message.
+ ACE_Message_Block *next (void) const;
+
+ /// Set link to next message.
+ void next (ACE_Message_Block *);
+
+ // = Pointer to the <Message_Block> directly behind in the ACE_Message_Queue.
+ /// Get link to prev message.
+ ACE_Message_Block *prev (void) const;
+
+ /// Set link to prev message.
+ void prev (ACE_Message_Block *);
+
+ // = The locking strategy prevents race conditions.
+ /// Get the locking strategy.
+ ACE_Lock *locking_strategy (void);
+
+ /// Set a new locking strategy and return the hold one.
+ ACE_Lock *locking_strategy (ACE_Lock *);
+
+ /// Get the current reference count.
+ int reference_count (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Internal initialization methods.
+ /// Perform the actual initialization.
+ ACE_Message_Block (size_t size,
+ ACE_Message_Type type,
+ ACE_Message_Block *cont,
+ const char *data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Lock *locking_strategy,
+ Message_Flags flags,
+ unsigned long priority,
+ const ACE_Time_Value &execution_time,
+ const ACE_Time_Value &deadline_time,
+ ACE_Data_Block *db,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator);
+
+ /// Internal release implementation
+ /// Returns 1 if the data block has to be destroyed.
+ int release_i (ACE_Lock *lock);
+
+ /// Perform the actual initialization.
+ int init_i (size_t size,
+ ACE_Message_Type type,
+ ACE_Message_Block *cont,
+ const char *data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Lock *locking_strategy,
+ Message_Flags flags,
+ unsigned long priority,
+ const ACE_Time_Value &execution_time,
+ const ACE_Time_Value &deadline_time,
+ ACE_Data_Block *db,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator);
+
+ /// Pointer to beginning of next read.
+ size_t rd_ptr_;
+
+ /// Pointer to beginning of next write.
+ size_t wr_ptr_;
+
+ /// Priority of message.
+ unsigned long priority_;
+
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+ /// Execution time associated with the message.
+ ACE_Time_Value execution_time_;
+
+ /// Absolute deadline time for message.
+ ACE_Time_Value deadline_time_;
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+
+ // = Links to other ACE_Message_Block *s.
+ /// Pointer to next message block in the chain.
+ ACE_Message_Block *cont_;
+
+ /// Pointer to next message in the list.
+ ACE_Message_Block *next_;
+
+ /// Pointer to previous message in the list.
+ ACE_Message_Block *prev_;
+
+ /// Misc flags (e.g., DONT_DELETE and USER_FLAGS).
+ ACE_Message_Block::Message_Flags flags_;
+
+ /// Pointer to the reference counted data structure that contains the
+ /// actual memory buffer.
+ ACE_Data_Block *data_block_;
+
+ /// The allocator used to destroy ourselves when release is called
+ /// and create new message blocks on duplicate.
+ ACE_Allocator *message_block_allocator_;
+
+private:
+ // = Disallow these operations for now (use <clone> instead).
+ ACE_Message_Block &operator= (const ACE_Message_Block &);
+ ACE_Message_Block (const ACE_Message_Block &);
+};
+
+/**
+ * @class ACE_Data_Block
+ *
+ * @brief Stores the data payload that is accessed via one or more
+ * ACE_Message_Block's.
+ *
+ * This data structure is reference counted to maximize
+ * sharing. It also contains the <locking_strategy_> (which
+ * protects the reference count from race conditions in
+ * concurrent programs) and the <allocation_strategy_> (which
+ * determines what memory pool is used to allocate the memory).
+ */
+class ACE_Export ACE_Data_Block
+{
+public:
+ // = Initialization and termination methods.
+ /// Default "do-nothing" constructor.
+ ACE_Data_Block (void);
+
+ /// Initialize.
+ ACE_Data_Block (size_t size,
+ ACE_Message_Block::ACE_Message_Type msg_type,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Lock *locking_strategy,
+ ACE_Message_Block::Message_Flags flags,
+ ACE_Allocator *data_block_allocator);
+
+ /// Delete all the resources held in the message.
+ virtual ~ACE_Data_Block (void);
+
+ /// Get type of the message.
+ ACE_Message_Block::ACE_Message_Type msg_type (void) const;
+
+ /// Set type of the message.
+ void msg_type (ACE_Message_Block::ACE_Message_Type type);
+
+ /// Get message data pointer
+ char *base (void) const;
+
+ /// Set message data pointer (doesn't reallocate).
+ void base (char *data,
+ size_t size,
+ ACE_Message_Block::Message_Flags mflags = ACE_Message_Block::DONT_DELETE);
+
+ /// Return a pointer to 1 past the end of the allocated data in a message.
+ char *end (void) const;
+
+ /**
+ * Return a pointer to 1 past the end of the allotted data in a message.
+ * The allotted data may be less than allocated data if <size()> is passed
+ * an argument less than <capacity()>.
+ */
+ char *mark (void) const;
+
+ // = Message size is the total amount of space alloted.
+
+ /// Get the total amount of allotted space in the message. The amount of
+ /// allotted space may be less than allocated space.
+ size_t size (void) const;
+
+ /// Set the total amount of space in the message. Returns 0 if
+ /// successful, else -1.
+ int size (size_t length);
+
+ /// Get the total amount of allocated space.
+ size_t capacity (void) const;
+
+ /**
+ * Return an exact "deep copy" of the message, i.e., create fresh
+ * new copies of all the Data_Blocks and continuations.
+ * Notice that Data_Blocks can act as "Prototypes", i.e. derived
+ * classes can override this method and create instances of
+ * themselves.
+ */
+ virtual ACE_Data_Block *clone (ACE_Message_Block::Message_Flags mask = 0) const;
+
+ /**
+ * As clone above, but it does not copy the contents of the buffer,
+ * i.e., create a new Data_Block of the same dynamic type, with the
+ * same allocator, locking_strategy, and with the same amount of
+ * storage available (if @a max_size is zero) but the buffer is unitialized.
+ * If @a max_size is specified other than zero, it will be used when
+ * creating the new data block.
+ */
+ virtual ACE_Data_Block *clone_nocopy (ACE_Message_Block::Message_Flags mask = 0,
+ size_t max_size = 0) const;
+
+ /// Return a "shallow" copy that increments our reference count by 1.
+ ACE_Data_Block *duplicate (void);
+
+ /**
+ * Decrease the shared reference count by 1. If the reference count
+ * is > 0 then return this; else if reference count == 0 then delete
+ * @c this and @a mb and return 0. Behavior is undefined if reference
+ * count < 0.
+ */
+ ACE_Data_Block *release (ACE_Lock *lock = 0);
+
+ // = Message flag accessors and mutators.
+ /// Bitwise-or the <more_flags> into the existing message flags and
+ /// return the new value.
+ ACE_Message_Block::Message_Flags set_flags (ACE_Message_Block::Message_Flags more_flags);
+
+ /// Clear the message flag bits specified in <less_flags> and return
+ /// the new value.
+ ACE_Message_Block::Message_Flags clr_flags (ACE_Message_Block::Message_Flags less_flags);
+
+ /// Get the current message flags.
+ ACE_Message_Block::Message_Flags flags (void) const;
+
+ /// Obtain the allocator strategy.
+ ACE_Allocator *allocator_strategy (void) const;
+
+ // = The locking strategy prevents race conditions.
+ /// Get the locking strategy.
+ ACE_Lock *locking_strategy (void);
+
+ /// Set a new locking strategy and return the hold one.
+ ACE_Lock *locking_strategy (ACE_Lock *);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Get the current reference count.
+ int reference_count (void) const;
+
+ /// Get the allocator used to create this object
+ ACE_Allocator *data_block_allocator (void) const;
+
+protected:
+ /// Internal release implementation
+ virtual ACE_Data_Block *release_i (void);
+
+ /// Internal get the current reference count.
+ int reference_count_i (void) const;
+
+ /**
+ * Decrease the reference count, but don't delete the object.
+ * Returns 0 if the object should be removed.
+ * If <lock> is equal to the locking strategy then we assume that
+ * the lock is beign held by the current thread; this is used to
+ * release all the data blocks in a chain while holding a single
+ * lock.
+ */
+ friend class ACE_Message_Block;
+ ACE_Data_Block *release_no_delete (ACE_Lock *lock);
+
+ /// Type of message.
+ ACE_Message_Block::ACE_Message_Type type_;
+
+ /// Current size of message block.
+ size_t cur_size_;
+
+ /// Total size of buffer.
+ size_t max_size_;
+
+ /// Misc flags (e.g., DONT_DELETE and USER_FLAGS).
+ ACE_Message_Block::Message_Flags flags_;
+
+ /// Pointer To beginning of message payload.
+ char *base_;
+
+ // = Strategies.
+ /**
+ * Pointer to the allocator defined for this ACE_Data_Block. Note
+ * that this pointer is shared by all owners of this
+ * ACE_Data_Block.
+ */
+ ACE_Allocator *allocator_strategy_;
+
+ /**
+ * Pointer to the locking strategy defined for this
+ * ACE_Data_Block. This is used to protect regions of code that
+ * access shared ACE_Data_Block state. Note that this lock is
+ * shared by all owners of the ACE_Data_Block's data.
+ */
+ ACE_Lock *locking_strategy_;
+
+ /**
+ * Reference count for this ACE_Data_Block, which is used to avoid
+ * deep copies (i.e., <clone>). Note that this pointer value is
+ * shared by all owners of the <Data_Block>'s data, i.e., all the
+ * ACE_Message_Blocks.
+ */
+ int reference_count_;
+
+ /// The allocator use to destroy ourselves.
+ ACE_Allocator *data_block_allocator_;
+
+private:
+ // = Disallow these operations.
+ ACE_Data_Block &operator= (const ACE_Data_Block &);
+ ACE_Data_Block (const ACE_Data_Block &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Message_Block.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Message_Block_T.h"
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MESSAGE_BLOCK_H */
diff --git a/ACE/ace/Message_Block.inl b/ACE/ace/Message_Block.inl
new file mode 100644
index 00000000000..71537e9fc16
--- /dev/null
+++ b/ACE/ace/Message_Block.inl
@@ -0,0 +1,508 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_Data_Block *
+ACE_Message_Block::data_block (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::data_block");
+ return this->data_block_;
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Message_Block::set_self_flags (ACE_Message_Block::Message_Flags more_flags)
+{
+ ACE_TRACE ("ACE_Message_Block::set_self_flags");
+ // Later we might mask more_glags so that user can't change internal
+ // ones: more_flags &= ~(USER_FLAGS -1).
+ return ACE_SET_BITS (this->flags_, more_flags);
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Message_Block::clr_self_flags (ACE_Message_Block::Message_Flags less_flags)
+{
+ ACE_TRACE ("ACE_Message_Block::clr_self_flags");
+ // Later we might mask more_flags so that user can't change internal
+ // ones: less_flags &= ~(USER_FLAGS -1).
+ return ACE_CLR_BITS (this->flags_, less_flags);
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Message_Block::self_flags (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::self_flags");
+ return this->flags_;
+}
+
+ACE_INLINE int
+ACE_Data_Block::reference_count_i (void) const
+{
+ return reference_count_;
+}
+
+ACE_INLINE int
+ACE_Message_Block::reference_count (void) const
+{
+ return data_block () ? data_block ()->reference_count () : 0;
+}
+
+ACE_INLINE char *
+ACE_Data_Block::base (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::base");
+ return this->base_;
+}
+
+ACE_INLINE size_t
+ACE_Data_Block::size (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::size");
+ return this->cur_size_;
+}
+
+ACE_INLINE size_t
+ACE_Data_Block::capacity (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::capacity");
+ return this->max_size_;
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Data_Block::set_flags (ACE_Message_Block::Message_Flags more_flags)
+{
+ ACE_TRACE ("ACE_Data_Block::set_flags");
+ // Later we might mask more_glags so that user can't change internal
+ // ones: more_flags &= ~(USER_FLAGS -1).
+ return ACE_SET_BITS (this->flags_, more_flags);
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Data_Block::clr_flags (ACE_Message_Block::Message_Flags less_flags)
+{
+ ACE_TRACE ("ACE_Data_Block::clr_flags");
+ // Later we might mask more_flags so that user can't change internal
+ // ones: less_flags &= ~(USER_FLAGS -1).
+ return ACE_CLR_BITS (this->flags_, less_flags);
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Data_Block::flags (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::flags");
+ return this->flags_;
+}
+
+ACE_INLINE ACE_Allocator*
+ACE_Data_Block::data_block_allocator (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::data_block_allocator");
+ return this->data_block_allocator_;
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Message_Block::set_flags (ACE_Message_Block::Message_Flags more_flags)
+{
+ ACE_TRACE ("ACE_Message_Block::set_flags");
+ return this->data_block ()->set_flags (more_flags);
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Message_Block::clr_flags (ACE_Message_Block::Message_Flags less_flags)
+{
+ ACE_TRACE ("ACE_Message_Block::clr_flags");
+ return this->data_block ()->clr_flags (less_flags);
+}
+
+ACE_INLINE ACE_Message_Block::Message_Flags
+ACE_Message_Block::flags (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::flags");
+ return this->data_block ()->flags ();
+}
+
+// Return the length of the "active" portion of the message.
+
+ACE_INLINE size_t
+ACE_Message_Block::length (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::length");
+ return this->wr_ptr_ - this->rd_ptr_;
+}
+
+// Sets the length of the "active" portion of the message. This is
+// defined as the offset from RD_PTR to WR_PTR.
+
+ACE_INLINE void
+ACE_Message_Block::length (size_t len)
+{
+ ACE_TRACE ("ACE_Message_Block::length");
+ this->wr_ptr_ = this->rd_ptr_ + len;
+}
+
+// Return the length of the potential size of the message.
+
+ACE_INLINE size_t
+ACE_Message_Block::size (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::size");
+ return this->data_block ()->size ();
+}
+
+ACE_INLINE size_t
+ACE_Message_Block::capacity (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::capacity");
+ return this->data_block ()->capacity ();
+}
+
+ACE_INLINE ACE_Message_Block::ACE_Message_Type
+ACE_Data_Block::msg_type (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::msg_type");
+ return this->type_;
+}
+
+ACE_INLINE void
+ACE_Data_Block::msg_type (ACE_Message_Block::ACE_Message_Type t)
+{
+ ACE_TRACE ("ACE_Data_Block::msg_type");
+ this->type_ = t;
+}
+
+ACE_INLINE ACE_Message_Block::ACE_Message_Type
+ACE_Message_Block::msg_type (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::msg_type");
+ return this->data_block ()->msg_type ();
+}
+
+ACE_INLINE void
+ACE_Message_Block::msg_type (ACE_Message_Block::ACE_Message_Type t)
+{
+ ACE_TRACE ("ACE_Message_Block::msg_type");
+ this->data_block ()->msg_type (t);
+}
+
+ACE_INLINE ACE_Message_Block::ACE_Message_Type
+ACE_Message_Block::msg_class (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::msg_class");
+
+ if (this->msg_type () < ACE_Message_Block::MB_PRIORITY)
+ return ACE_Message_Block::MB_NORMAL;
+ else if (this->msg_type () < ACE_Message_Block::MB_USER)
+ return ACE_Message_Block::MB_PRIORITY;
+ else
+ return ACE_Message_Block::MB_USER;
+}
+
+ACE_INLINE int
+ACE_Message_Block::is_data_msg (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::is_data_msg");
+ ACE_Message_Type mt = this->msg_type ();
+ return
+ mt == ACE_Message_Block::MB_DATA
+ || mt == ACE_Message_Block::MB_PROTO
+ || mt == ACE_Message_Block::MB_PCPROTO;
+}
+
+ACE_INLINE unsigned long
+ACE_Message_Block::msg_priority (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::msg_priority");
+ return this->priority_;
+}
+
+ACE_INLINE void
+ACE_Message_Block::msg_priority (unsigned long pri)
+{
+ ACE_TRACE ("ACE_Message_Block::msg_priority");
+ this->priority_ = pri;
+}
+
+ACE_INLINE const ACE_Time_Value &
+ACE_Message_Block::msg_execution_time (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::msg_execution_time (void)");
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+ return this->execution_time_;
+#else
+ return ACE_Time_Value::zero;
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+}
+
+ACE_INLINE void
+ACE_Message_Block::msg_execution_time (const ACE_Time_Value &et)
+{
+ ACE_TRACE ("ACE_Message_Block::msg_execution_time (const ACE_Time_Value & et)");
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+ this->execution_time_ = et;
+#else
+ ACE_UNUSED_ARG (et);
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+}
+
+ACE_INLINE const ACE_Time_Value &
+ACE_Message_Block::msg_deadline_time (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::msg_deadline_time (void)");
+
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+ return this->deadline_time_;
+#else
+ return ACE_Time_Value::max_time; // absolute time of deadline
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+}
+
+ACE_INLINE void
+ACE_Message_Block::msg_deadline_time (const ACE_Time_Value &dt)
+{
+ ACE_TRACE ("ACE_Message_Block::msg_deadline_time (const ACE_Time_Value & et)");
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+ this->deadline_time_ = dt;
+#else
+ ACE_UNUSED_ARG (dt);
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+}
+
+ACE_INLINE void
+ACE_Message_Block::access_allocators (ACE_Allocator *& allocator_strategy,
+ ACE_Allocator *& data_block_allocator,
+ ACE_Allocator *& message_block_allocator)
+{
+ allocator_strategy =
+ this->data_block_->allocator_strategy_;
+ data_block_allocator =
+ this->data_block_->data_block_allocator_;
+ message_block_allocator =
+ this->message_block_allocator_;
+}
+
+ACE_INLINE char *
+ACE_Message_Block::base (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::base");
+ return this->data_block ()->base ();
+}
+
+ACE_INLINE void
+ACE_Message_Block::base (char *msg_data,
+ size_t msg_length,
+ Message_Flags msg_flags)
+{
+ ACE_TRACE ("ACE_Message_Block::base");
+ this->rd_ptr_ = 0;
+ this->wr_ptr_ = 0;
+ this->data_block ()->base (msg_data, msg_length, msg_flags);
+}
+
+ACE_INLINE char *
+ACE_Message_Block::rd_ptr (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::rd_ptr");
+ return this->base () + this->rd_ptr_;
+}
+
+ACE_INLINE void
+ACE_Message_Block::wr_ptr (char *new_ptr)
+{
+ ACE_TRACE ("ACE_Message_Block::wr_ptr");
+ this->wr_ptr_ = new_ptr - this->base ();
+}
+
+// Return a pointer to 1 past the end of the data buffer.
+
+ACE_INLINE char *
+ACE_Data_Block::mark (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::mark");
+ return this->base_ + this->cur_size_;
+}
+
+ACE_INLINE char *
+ACE_Message_Block::mark (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::mark");
+ return this->data_block ()->mark ();
+}
+
+ACE_INLINE char *
+ACE_Data_Block::end (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::end");
+ return this->base_ + this->max_size_;
+}
+
+ACE_INLINE char *
+ACE_Message_Block::end (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::end");
+ return this->data_block ()->end ();
+}
+
+
+ACE_INLINE void
+ACE_Message_Block::rd_ptr (char *new_ptr)
+{
+ ACE_TRACE ("ACE_Message_Block::rd_ptr");
+ this->rd_ptr_ = new_ptr - this->base ();
+}
+
+ACE_INLINE void
+ACE_Message_Block::rd_ptr (size_t n)
+{
+ ACE_TRACE ("ACE_Message_Block::rd_ptr");
+ this->rd_ptr_ += n;
+}
+
+ACE_INLINE char *
+ACE_Message_Block::wr_ptr (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::wr_ptr");
+ return this->base () + this->wr_ptr_;
+}
+
+ACE_INLINE void
+ACE_Message_Block::wr_ptr (size_t n)
+{
+ ACE_TRACE ("ACE_Message_Block::wr_ptr");
+ this->wr_ptr_ += n;
+}
+
+ACE_INLINE void
+ACE_Message_Block::reset (void)
+{
+ ACE_TRACE ("ACE_Message_Block::reset");
+ this->rd_ptr_ = 0;
+ this->wr_ptr_ = 0;
+}
+
+ACE_INLINE size_t
+ACE_Message_Block::space (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::space");
+ return this->mark () - this->wr_ptr ();
+}
+
+ACE_INLINE ACE_Data_Block *
+ACE_Message_Block::replace_data_block (ACE_Data_Block *db)
+{
+ ACE_TRACE ("ACE_Message_Block::replace_data_block");
+ ACE_Data_Block *old = this->data_block_;
+ this->data_block_ = db;
+
+ if (db != 0)
+ {
+ // Set the read and write pointers in the <Message_Block> to point
+ // to the buffer in the <ACE_Data_Block>.
+ this->rd_ptr (this->data_block ()->base ());
+ this->wr_ptr (this->data_block ()->base ());
+ }
+
+ return old;
+}
+
+ACE_INLINE void
+ACE_Message_Block::cont (ACE_Message_Block *cont_msg)
+{
+ ACE_TRACE ("ACE_Message_Block::cont");
+ this->cont_ = cont_msg;
+}
+
+ACE_INLINE ACE_Message_Block *
+ACE_Message_Block::cont (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::cont");
+ return this->cont_;
+}
+
+ACE_INLINE void
+ACE_Message_Block::reset_allocators (ACE_Allocator *allocator_strategy,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator)
+{
+ this->data_block_->allocator_strategy_ =
+ allocator_strategy;
+ this->data_block_->data_block_allocator_ =
+ data_block_allocator;
+ this->message_block_allocator_ =
+ message_block_allocator;
+
+ if (this->cont () != 0)
+ this->cont ()->reset_allocators (allocator_strategy,
+ data_block_allocator,
+ message_block_allocator);
+}
+
+ACE_INLINE void
+ACE_Message_Block::next (ACE_Message_Block *next_msg)
+{
+ ACE_TRACE ("ACE_Message_Block::next");
+ this->next_ = next_msg;
+}
+
+ACE_INLINE ACE_Message_Block *
+ACE_Message_Block::next (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::next");
+ return this->next_;
+}
+
+ACE_INLINE void
+ACE_Message_Block::prev (ACE_Message_Block *next_msg)
+{
+ ACE_TRACE ("ACE_Message_Block::prev");
+ this->prev_ = next_msg;
+}
+
+ACE_INLINE ACE_Message_Block *
+ACE_Message_Block::prev (void) const
+{
+ ACE_TRACE ("ACE_Message_Block::prev");
+ return this->prev_;
+}
+
+ACE_INLINE ACE_Allocator *
+ACE_Data_Block::allocator_strategy (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::allocator_strategy");
+ return this->allocator_strategy_;
+}
+
+ACE_INLINE ACE_Lock *
+ACE_Data_Block::locking_strategy (void)
+{
+ ACE_TRACE ("ACE_Data_Block::locking_strategy");
+ return this->locking_strategy_;
+}
+
+ACE_INLINE ACE_Lock *
+ACE_Data_Block::locking_strategy (ACE_Lock *nls)
+{
+ ACE_TRACE ("ACE_Data_Block::locking_strategy");
+ ACE_Lock *ols = this->locking_strategy_;
+
+ this->locking_strategy_ = nls;
+ return ols;
+}
+
+ACE_INLINE ACE_Lock *
+ACE_Message_Block::locking_strategy (void)
+{
+ ACE_TRACE ("ACE_Message_Block::locking_strategy");
+ return this->data_block ()->locking_strategy ();
+}
+
+ACE_INLINE ACE_Lock *
+ACE_Message_Block::locking_strategy (ACE_Lock *nls)
+{
+ ACE_TRACE ("ACE_Message_Block::locking_strategy");
+ ACE_Lock *ols = this->data_block ()->locking_strategy ();
+ this->data_block ()->locking_strategy (nls);
+ return ols;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Message_Block_T.cpp b/ACE/ace/Message_Block_T.cpp
new file mode 100644
index 00000000000..c02fb7c0401
--- /dev/null
+++ b/ACE/ace/Message_Block_T.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+#ifndef ACE_MESSAGE_BLOCK_T_CPP
+#define ACE_MESSAGE_BLOCK_T_CPP
+
+#include "ace/Malloc_Base.h" /* Need ACE_Allocator */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Message_Block_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/os_include/os_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class L>
+ACE_Locked_Data_Block<L>::~ACE_Locked_Data_Block (void)
+{
+}
+
+template<class ACE_LOCK> ACE_Data_Block *
+ACE_Locked_Data_Block<ACE_LOCK>::clone_nocopy (ACE_Message_Block::Message_Flags mask,
+ size_t max_size) const
+{
+ ACE_TRACE ("ACE_Locked_Data_Block::clone_nocopy");
+
+ // You always want to clear this one to prevent memory leaks but you
+ // might add some others later.
+ const ACE_Message_Block::Message_Flags always_clear =
+ ACE_Message_Block::DONT_DELETE;
+
+ ACE_Locked_Data_Block<ACE_LOCK> *nb = 0;
+
+ ACE_NEW_MALLOC_RETURN (nb,
+ static_cast<ACE_Locked_Data_Block<ACE_LOCK>*> (
+ this->data_block_allocator ()->malloc (sizeof (ACE_Locked_Data_Block<ACE_LOCK>))),
+ ACE_Locked_Data_Block<ACE_LOCK> (
+ max_size == 0 ?
+ this->size () : max_size,
+ this->msg_type (),
+ 0,
+ this->allocator_strategy (),
+ this->flags (),
+ this->data_block_allocator ()),
+ 0);
+
+ // Set new flags minus the mask...
+ nb->clr_flags (mask | always_clear);
+ return nb;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_MESSAGE_BLOCK_T_CPP */
diff --git a/ACE/ace/Message_Block_T.h b/ACE/ace/Message_Block_T.h
new file mode 100644
index 00000000000..e65c92872a8
--- /dev/null
+++ b/ACE/ace/Message_Block_T.h
@@ -0,0 +1,88 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Message_Block_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Carlos O'Ryan <coryan@atdesk.com>
+ */
+//=============================================================================
+
+#ifndef ACE_MESSAGE_BLOCK_T_H
+#define ACE_MESSAGE_BLOCK_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Message_Block.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Locked_Data_Block
+ *
+ * @brief A Data_Block with a concrete locking strategy.
+ *
+ * Data_Blocks can be parametric on the kind of lock they use; in
+ * many cases the lifetime of the lock is tied to the lifetime of
+ * the Data_Block itself. But since Data_Blocks are reference
+ * counted it is hard for users to control the lock lifetime.
+ * This class is parametric over the kind of lock used.
+ */
+template <class ACE_LOCK>
+class ACE_Locked_Data_Block : public ACE_Data_Block
+{
+public:
+ // = Initialization and termination methods.
+ /// Default "do-nothing" constructor.
+ ACE_Locked_Data_Block (void);
+
+ /// Initialize.
+ ACE_Locked_Data_Block (size_t size,
+ ACE_Message_Block::ACE_Message_Type msg_type,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Message_Block::Message_Flags flags,
+ ACE_Allocator *data_block_allocator);
+
+ /// Delete all the resources held in the message.
+ virtual ~ACE_Locked_Data_Block (void);
+
+ /**
+ * Return an exact "deep copy" of the message, the dynamic type is
+ * ACE_Locked_Data_Block<>
+ * See the documentation in Message_Block.h for details.
+ */
+ virtual ACE_Data_Block *clone_nocopy (ACE_Message_Block::Message_Flags mask = 0,
+ size_t max_size = 0) const;
+
+private:
+ /// The lock
+ ACE_LOCK lock_;
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Locked_Data_Block<ACE_LOCK> &operator= (const ACE_Locked_Data_Block<ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Locked_Data_Block (const ACE_Locked_Data_Block<ACE_LOCK> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Message_Block_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Message_Block_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Message_Block_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MESSAGE_BLOCK_T_H */
diff --git a/ACE/ace/Message_Block_T.inl b/ACE/ace/Message_Block_T.inl
new file mode 100644
index 00000000000..6829bd6c360
--- /dev/null
+++ b/ACE/ace/Message_Block_T.inl
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class ACE_LOCK> ACE_INLINE
+ACE_Locked_Data_Block<ACE_LOCK>::ACE_Locked_Data_Block (void)
+{
+ this->locking_strategy_ = &this->lock_;
+}
+
+template<class ACE_LOCK> ACE_INLINE
+ACE_Locked_Data_Block<ACE_LOCK>::
+ACE_Locked_Data_Block (size_t size,
+ ACE_Message_Block::ACE_Message_Type msg_type,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Message_Block::Message_Flags flags,
+ ACE_Allocator *data_block_allocator)
+ : ACE_Data_Block (size,
+ msg_type,
+ msg_data,
+ allocator_strategy,
+ &lock_,
+ flags,
+ data_block_allocator)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Message_Queue.cpp b/ACE/ace/Message_Queue.cpp
new file mode 100644
index 00000000000..0ce105db50b
--- /dev/null
+++ b/ACE/ace/Message_Queue.cpp
@@ -0,0 +1,28 @@
+// $Id$
+
+#include "ace/Message_Queue.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Message_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Message_Queue,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Message_Queue_Base::~ACE_Message_Queue_Base (void)
+{
+}
+
+int
+ACE_Message_Queue_Base::state (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Base::state");
+
+ return this->state_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Message_Queue.h b/ACE/ace/Message_Queue.h
new file mode 100644
index 00000000000..b5f847700fd
--- /dev/null
+++ b/ACE/ace/Message_Queue.h
@@ -0,0 +1,237 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Message_Queue.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MESSAGE_QUEUE_H
+#define ACE_MESSAGE_QUEUE_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Message_Block.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/IO_Cntl_Msg.h"
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+# include "ace/Synch_Traits.h" /* Needed in ACE_Message_Queue_NT */
+# include "ace/Thread_Mutex.h" /* Needed in ACE_Message_Queue_NT */
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls.
+class ACE_Notification_Strategy;
+template <ACE_SYNCH_DECL> class ACE_Message_Queue_Iterator;
+template <ACE_SYNCH_DECL> class ACE_Message_Queue_Reverse_Iterator;
+
+/**
+ * @class ACE_Message_Queue_Base
+ *
+ * @brief Base class for ACE_Message_Queue, which is the central
+ * queueing facility for messages in the ACE framework.
+ *
+ * For all the ACE_Time_Value pointer parameters the caller will
+ * block until action is possible if @a timeout == 0. Otherwise, it
+ * will wait until the absolute time specified in *@a timeout
+ * elapses.
+ *
+ * A queue is always in one of three states:
+ * . ACTIVATED
+ * . DEACTIVATED
+ * . PULSED
+ */
+class ACE_Export ACE_Message_Queue_Base
+{
+public:
+ enum
+ {
+ // Default high and low watermarks.
+
+ /// Default high watermark (16 K).
+ DEFAULT_HWM = 16 * 1024,
+ /// Default low watermark (same as high water mark).
+ DEFAULT_LWM = 16 * 1024,
+
+ // Queue states. Before PULSED state was added, the activate()
+ // and deactivate() methods returned WAS_INACTIVE or WAS_ACTIVE
+ // to indicate the previous condition. Now those methods
+ // return the state the queue was previously in. WAS_ACTIVE
+ // and WAS_INACTIVE are defined to match previous semantics for
+ // applications that don't use the PULSED state.
+
+ /// @deprecated Use ACTIVATED instead.
+ WAS_ACTIVE = 1,
+ /// Message queue is active and processing normally
+ ACTIVATED = 1,
+
+ /// @deprecated Use DEACTIVATED instead.
+ WAS_INACTIVE = 2,
+ /// Queue is deactivated; no enqueue or dequeue operations allowed.
+ DEACTIVATED = 2,
+
+ /// Message queue was pulsed; enqueue and dequeue may proceed normally.
+ PULSED = 3
+
+ };
+
+ ACE_Message_Queue_Base (void);
+
+ /// Close down the message queue and release all resources.
+ virtual int close (void) = 0;
+
+ /// Close down the message queue and release all resources.
+ virtual ~ACE_Message_Queue_Base (void);
+
+ // = Enqueue and dequeue methods.
+
+ /**
+ * Retrieve the first ACE_Message_Block without removing it. Note
+ * that @a timeout uses <{absolute}> time rather than <{relative}>
+ * time. If the @a timeout elapses without receiving a message -1 is
+ * returned and @c errno is set to @c EWOULDBLOCK. If the queue is
+ * deactivated -1 is returned and @c errno is set to <ESHUTDOWN>.
+ * Otherwise, returns -1 on failure, else the number of items still
+ * on the queue.
+ */
+ virtual int peek_dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0) = 0;
+
+ /**
+ * Enqueue a <ACE_Message_Block *> into the tail of the queue.
+ * Returns number of items in queue if the call succeeds or -1
+ * otherwise. These calls return -1 when queue is closed,
+ * deactivated (in which case @c errno == <ESHUTDOWN>), when a signal
+ * occurs (in which case @c errno == <EINTR>, or if the time
+ * specified in timeout elapses (in which case @c errno ==
+ * @c EWOULDBLOCK).
+ */
+ virtual int enqueue_tail (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0) = 0;
+ virtual int enqueue (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0) = 0;
+
+ /**
+ * Dequeue and return the <ACE_Message_Block *> at the head of the
+ * queue. Returns number of items in queue if the call succeeds or
+ * -1 otherwise. These calls return -1 when queue is closed,
+ * deactivated (in which case @c errno == <ESHUTDOWN>), when a signal
+ * occurs (in which case @c errno == <EINTR>, or if the time
+ * specified in timeout elapses (in which case @c errno ==
+ * @c EWOULDBLOCK).
+ */
+ virtual int dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0) = 0;
+ virtual int dequeue (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0) = 0;
+
+ // = Check if queue is full/empty.
+ /// True if queue is full, else false.
+ virtual bool is_full (void) = 0;
+
+ /// True if queue is empty, else false.
+ virtual bool is_empty (void) = 0;
+
+ // = Queue statistic methods.
+
+ /// Number of total bytes on the queue, i.e., sum of the message
+ /// block sizes.
+ virtual size_t message_bytes (void) = 0;
+
+ /// Number of total length on the queue, i.e., sum of the message
+ /// block lengths.
+ virtual size_t message_length (void) = 0;
+
+ /// Number of total messages on the queue.
+ virtual size_t message_count (void) = 0;
+
+ /// New value of the number of total bytes on the queue, i.e.,
+ /// sum of the message block sizes.
+ virtual void message_bytes (size_t new_size) = 0;
+
+ /// New value of the number of total length on the queue, i.e.,
+ /// sum of the message block lengths.
+ virtual void message_length (size_t new_length) = 0;
+
+ // = Activation control methods.
+
+ /**
+ * Deactivate the queue and wake up all threads waiting on the queue
+ * so they can continue. No messages are removed from the queue,
+ * however. Any other operations called until the queue is
+ * activated again will immediately return -1 with @c errno
+ * ESHUTDOWN.
+ *
+ * @retval The queue's state before this call.
+ */
+ virtual int deactivate (void) = 0;
+
+ /**
+ * Reactivate the queue so that threads can enqueue and dequeue
+ * messages again.
+ *
+ * @retval The queue's state before this call.
+ */
+ virtual int activate (void) = 0;
+
+ /**
+ * Pulse the queue to wake up any waiting threads. Changes the
+ * queue state to PULSED; future enqueue/dequeue operations proceed
+ * as in ACTIVATED state.
+ *
+ * @retval The queue's state before this call.
+ */
+ virtual int pulse (void) = 0;
+
+ /// Returns the current state of the queue.
+ virtual int state (void);
+
+ /// Returns 1 if the state of the queue is DEACTIVATED,
+ /// and 0 if the queue's state is ACTIVATED or PULSED.
+ virtual int deactivated (void) = 0;
+
+ /// Get the notification strategy for the <Message_Queue>
+ virtual ACE_Notification_Strategy *notification_strategy (void) = 0;
+
+ /// Set the notification strategy for the <Message_Queue>
+ virtual void notification_strategy (ACE_Notification_Strategy *s) = 0;
+
+ // = Notification hook.
+
+ /// Dump the state of an object.
+ virtual void dump (void) const = 0;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ // = Disallow copying and assignment.
+ ACE_Message_Queue_Base (const ACE_Message_Queue_Base &);
+ void operator= (const ACE_Message_Queue_Base &);
+
+protected:
+ /// Indicates the state of the queue, which can be
+ /// <ACTIVATED>, <DEACTIVATED>, or <PULSED>.
+ int state_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Include the templates here.
+#include "ace/Message_Queue_T.h"
+
+#if defined (__ACE_INLINE__)
+#include "ace/Message_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MESSAGE_QUEUE_H */
diff --git a/ACE/ace/Message_Queue.inl b/ACE/ace/Message_Queue.inl
new file mode 100644
index 00000000000..aaadea9d3e6
--- /dev/null
+++ b/ACE/ace/Message_Queue.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Message_Queue_Base::ACE_Message_Queue_Base (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Message_Queue_NT.cpp b/ACE/ace/Message_Queue_NT.cpp
new file mode 100644
index 00000000000..3c4fbe99c64
--- /dev/null
+++ b/ACE/ace/Message_Queue_NT.cpp
@@ -0,0 +1,237 @@
+// $Id$
+
+#include "ace/Message_Queue_NT.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Message_Queue_NT.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Message_Queue_NT,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+
+ACE_Message_Queue_NT::ACE_Message_Queue_NT (DWORD max_threads)
+ : max_cthrs_ (max_threads),
+ cur_thrs_ (0),
+ cur_bytes_ (0),
+ cur_length_ (0),
+ cur_count_ (0),
+ completion_port_ (ACE_INVALID_HANDLE)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::ACE_Message_Queue_NT");
+ this->open (max_threads);
+}
+
+int
+ACE_Message_Queue_NT::open (DWORD max_threads)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::open");
+ this->max_cthrs_ = max_threads;
+ this->completion_port_ = ::CreateIoCompletionPort (ACE_INVALID_HANDLE,
+ 0,
+ ACE_Message_Queue_Base::ACTIVATED,
+ max_threads);
+ return (this->completion_port_ == 0 ? -1 : 0);
+}
+
+int
+ACE_Message_Queue_NT::close (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::close");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);
+ this->deactivate ();
+ return (::CloseHandle (this->completion_port_) ? 0 : -1 );
+}
+
+ACE_Message_Queue_NT::~ACE_Message_Queue_NT (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::~ACE_Message_Queue_NT");
+ this->close ();
+}
+
+int
+ACE_Message_Queue_NT::enqueue (ACE_Message_Block *new_item,
+ ACE_Time_Value *)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::enqueue");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);
+ if (this->state_ != ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ size_t const msize = new_item->total_size ();
+ size_t const mlength = new_item->total_length ();
+ // Note - we send ACTIVATED in the 3rd arg to tell the completion
+ // routine it's _NOT_ being woken up because of deactivate().
+ ULONG_PTR state_to_post;
+ state_to_post = ACE_Message_Queue_Base::ACTIVATED;
+ if (::PostQueuedCompletionStatus (this->completion_port_,
+ static_cast<DWORD> (msize),
+ state_to_post,
+ reinterpret_cast<LPOVERLAPPED> (new_item)))
+ {
+ // Update the states once I succeed.
+ this->cur_bytes_ += msize;
+ this->cur_length_ += mlength;
+ return ACE_Utils::truncate_cast<int> (++this->cur_count_);
+ }
+ }
+ else
+ errno = ESHUTDOWN;
+
+ // Fail to enqueue the message.
+ return -1;
+}
+
+int
+ACE_Message_Queue_NT::dequeue (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::dequeue_head");
+
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);
+
+ // Make sure the MQ is not deactivated before proceeding.
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN; // Operation on deactivated MQ not allowed.
+ return -1;
+ }
+ else
+ ++this->cur_thrs_; // Increase the waiting thread count.
+ }
+
+ ULONG_PTR queue_state;
+ DWORD msize;
+ // Get a message from the completion port.
+ int retv = ::GetQueuedCompletionStatus (this->completion_port_,
+ &msize,
+ &queue_state,
+ reinterpret_cast<LPOVERLAPPED *> (&first_item),
+ (timeout == 0 ? INFINITE : timeout->msec ()));
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);
+ --this->cur_thrs_; // Decrease waiting thread count.
+ if (retv)
+ {
+ if (queue_state == ACE_Message_Queue_Base::ACTIVATED)
+ { // Really get a valid MB from the queue.
+ --this->cur_count_;
+ this->cur_bytes_ -= msize;
+ this->cur_length_ -= first_item->total_length ();
+ return ACE_Utils::truncate_cast<int> (this->cur_count_);
+ }
+ else // Woken up by deactivate () or pulse ().
+ errno = ESHUTDOWN;
+ }
+ }
+ return -1;
+}
+
+int
+ACE_Message_Queue_NT::deactivate (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::deactivate");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);
+
+ int const previous_state = this->state_;
+ if (previous_state != ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ this->state_ = ACE_Message_Queue_Base::DEACTIVATED;
+
+ // Get the number of shutdown messages necessary to wake up all
+ // waiting threads.
+ DWORD cntr =
+ this->cur_thrs_ - static_cast<DWORD> (this->cur_count_);
+ while (cntr-- > 0)
+ ::PostQueuedCompletionStatus (this->completion_port_,
+ 0,
+ this->state_,
+ 0);
+ }
+ return previous_state;
+}
+
+int
+ACE_Message_Queue_NT::activate (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::activate");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);
+ int const previous_status = this->state_;
+ this->state_ = ACE_Message_Queue_Base::ACTIVATED;
+ return previous_status;
+}
+
+int
+ACE_Message_Queue_NT::pulse (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::pulse");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);
+
+ int const previous_state = this->state_;
+ if (previous_state != ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ this->state_ = ACE_Message_Queue_Base::PULSED;
+
+ // Get the number of shutdown messages necessary to wake up all
+ // waiting threads.
+
+ DWORD cntr =
+ this->cur_thrs_ - static_cast<DWORD> (this->cur_count_);
+ while (cntr-- > 0)
+ ::PostQueuedCompletionStatus (this->completion_port_,
+ 0,
+ this->state_,
+ 0);
+ }
+ return previous_state;
+}
+
+void
+ACE_Message_Queue_NT::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Message_Queue_NT::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ switch (this->state_)
+ {
+ case ACE_Message_Queue_Base::ACTIVATED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = ACTIVATED\n")));
+ break;
+ case ACE_Message_Queue_Base::DEACTIVATED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = DEACTIVATED\n")));
+ break;
+ case ACE_Message_Queue_Base::PULSED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = PULSED\n")));
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("max_cthrs_ = %d\n")
+ ACE_TEXT ("cur_thrs_ = %d\n")
+ ACE_TEXT ("cur_bytes = %d\n")
+ ACE_TEXT ("cur_length = %d\n")
+ ACE_TEXT ("cur_count = %d\n")
+ ACE_TEXT ("completion_port_ = %x\n"),
+ this->max_cthrs_,
+ this->cur_thrs_,
+ this->cur_bytes_,
+ this->cur_length_,
+ this->cur_count_,
+ this->completion_port_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Message_Queue_NT.h b/ACE/ace/Message_Queue_NT.h
new file mode 100644
index 00000000000..94f14b0d673
--- /dev/null
+++ b/ACE/ace/Message_Queue_NT.h
@@ -0,0 +1,231 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Message_Queue_NT.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MESSAGE_QUEUE_NT_H
+#define ACE_MESSAGE_QUEUE_NT_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Message_Queue.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+# include "ace/Synch_Traits.h" /* Needed in ACE_Message_Queue_NT */
+# include "ace/Thread_Mutex.h" /* Needed in ACE_Message_Queue_NT */
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+/**
+ * @class ACE_Message_Queue_NT
+ *
+ * @brief Message Queue implementation using IO completion port on NT.
+ *
+ * Implementation of a strip-downed ACE_Message_Queue using NT's
+ * IO completion port mechanism.
+ * @note *Many* ACE_Message_Queue features are not supported with
+ * this implementation, including:
+ * * <open> method have different signatures.
+ * * <dequeue_head> *requires* that the ACE_Message_Block
+ * pointer argument point to an ACE_Message_Block that was
+ * allocated by the caller.
+ * * <peek_dequeue_head>.
+ * * <ACE_Message_Queue_Iterators>.
+ * * No flow control.
+ */
+class ACE_Export ACE_Message_Queue_NT : public ACE_Message_Queue_Base
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Message_Queue_NT (DWORD max_threads = ACE_Message_Queue_Base::DEFAULT_HWM);
+
+ /**
+ * Initialize the Message Queue by creating a new NT I/O completion
+ * port. The first arguemnt specifies the number of threads
+ * released by the MQ that are allowed to run concurrently. Return
+ * 0 when succeeds, -1 otherwise.
+ */
+ virtual int open (DWORD max_threads = ACE_Message_Queue_Base::DEFAULT_HWM);
+
+ /// Close down the underlying I/O completion port. You need to
+ /// re-open the MQ after this function is executed.
+ virtual int close (void);
+
+ /// Close down the message queue and release all resources.
+ virtual ~ACE_Message_Queue_NT (void);
+
+ // = Enqueue and dequeue methods.
+
+ /**
+ * Enqueue an <ACE_Message_Block *> at the end of the queue.
+ * Returns -1 on failure, else the number of items still on the
+ * queue.
+ */
+ virtual int enqueue_tail (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+ virtual int enqueue (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue and return the <ACE_Message_Block *> at the head of the
+ * queue. Returns -1 on failure, else the number of items still on
+ * the queue.
+ */
+ virtual int dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+ virtual int dequeue (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ // = Check if queue is full/empty.
+ /**
+ * Always return false.
+ */
+
+ virtual bool is_full (void);
+ /**
+ * True if queue is empty, else false. Notice the return value is
+ * only transient.
+ */
+ virtual bool is_empty (void);
+
+ // = Queue statistic methods (transient.)
+ /**
+ * Number of total bytes on the queue, i.e., sum of the message
+ * block sizes.
+ */
+ virtual size_t message_bytes (void);
+
+ /**
+ * Number of total length on the queue, i.e., sum of the message
+ * block lengths.
+ */
+ virtual size_t message_length (void);
+
+ /**
+ * Number of total messages on the queue.
+ */
+ virtual size_t message_count (void);
+
+ // = Manual changes to these stats (used when queued message blocks
+ // change size or lengths).
+ /**
+ * New value of the number of total bytes on the queue, i.e., sum of
+ * the message block sizes.
+ */
+ virtual void message_bytes (size_t new_size);
+
+ /**
+ * New value of the number of total length on the queue, i.e., sum
+ * of the message block lengths.
+ */
+ virtual void message_length (size_t new_length);
+
+ /// Get the max concurrent thread number.
+ virtual DWORD max_threads (void);
+
+ // = Activation control methods.
+
+ /**
+ * Deactivate the queue and wake up all threads waiting on the queue
+ * so they can continue. No messages are removed from the queue,
+ * however. Any other operations called until the queue is
+ * activated again will immediately return -1 with @c errno
+ * ESHUTDOWN.
+ *
+ * @retval The queue's state before this call.
+ */
+ virtual int deactivate (void);
+
+ /**
+ * Reactivate the queue so that threads can enqueue and dequeue
+ * messages again. Returns the state of the queue before the call.
+ */
+ virtual int activate (void);
+
+ /**
+ * Pulse the queue to wake up any waiting threads. Changes the
+ * queue state to PULSED; future enqueue/dequeue operations proceed
+ * as in ACTIVATED state.
+ *
+ * @retval The queue's state before this call.
+ */
+ virtual int pulse (void);
+
+ /// Returns true if the state of the queue is <DEACTIVATED>,
+ /// but false if the queue's is <ACTIVATED> or <PULSED>.
+ virtual int deactivated (void);
+
+ // = Not currently implemented...
+ int peek_dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+ ACE_Notification_Strategy *notification_strategy (void);
+ void notification_strategy (ACE_Notification_Strategy *s);
+
+ // = Notification hook.
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Get the handle to the underlying completion port.
+ virtual ACE_HANDLE completion_port (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ // Disallow copying and assignment.
+ ACE_Message_Queue_NT (const ACE_Message_Queue_NT &);
+ void operator= (const ACE_Message_Queue_NT &);
+
+private:
+ // = Internal states.
+
+ /// Maximum threads that can be released (and run) concurrently.
+ DWORD max_cthrs_;
+
+ /// Current number of threads waiting to dequeue messages.
+ DWORD cur_thrs_;
+
+ /// Current number of bytes in queue.
+ size_t cur_bytes_;
+
+ /// Current length of messages in queue.
+ size_t cur_length_;
+
+ /// Current number of messages in the queue.
+ size_t cur_count_;
+
+ /**
+ * Synchronizer. This should really be an ACE_Recursive_Thread_Mutex
+ * but since this class is only supported on NT, it's okay to use
+ * ACE_Thread_Mutex here.
+ */
+ ACE_SYNCH_MUTEX lock_;
+
+ /// Underlying NT IoCompletionPort.
+ ACE_HANDLE completion_port_;
+
+};
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Message_Queue_NT.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MESSAGE_QUEUE_NT_H */
diff --git a/ACE/ace/Message_Queue_NT.inl b/ACE/ace/Message_Queue_NT.inl
new file mode 100644
index 00000000000..6db82111d5b
--- /dev/null
+++ b/ACE/ace/Message_Queue_NT.inl
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+# include "ace/Guard_T.h"
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+
+ACE_INLINE int
+ACE_Message_Queue_NT::enqueue_tail (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::enqueue_tail");
+ return this->enqueue (new_item, timeout);
+}
+
+ACE_INLINE int
+ACE_Message_Queue_NT::dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::dequeue_head");
+ return this->dequeue (first_item, timeout);
+}
+
+ACE_INLINE bool
+ACE_Message_Queue_NT::is_full (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::is_full");
+ return false; // Always not full.
+}
+
+ACE_INLINE bool
+ACE_Message_Queue_NT::is_empty (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::is_empty");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, false);
+
+ return this->cur_bytes_ > 0 || this->cur_count_ > 0 ? false : true;
+}
+
+ACE_INLINE size_t
+ACE_Message_Queue_NT::message_bytes (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::message_bytes");
+ // Accessing to size_t must be atomic.
+ return this->cur_bytes_;
+}
+
+ACE_INLINE size_t
+ACE_Message_Queue_NT::message_length (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::message_length");
+ // Accessing to size_t must be atomic.
+ return this->cur_length_;
+}
+
+ACE_INLINE size_t
+ACE_Message_Queue_NT::message_count (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::message_count");
+ // Accessing to size_t must be atomic.
+ return this->cur_count_;
+}
+
+ACE_INLINE void
+ACE_Message_Queue_NT::message_bytes (size_t new_value)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::message_bytes");
+ ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->lock_);
+
+ this->cur_bytes_ = new_value;
+}
+
+ACE_INLINE void
+ACE_Message_Queue_NT::message_length (size_t new_value)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::message_length");
+ ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->lock_);
+
+ this->cur_length_ = new_value;
+}
+
+ACE_INLINE DWORD
+ACE_Message_Queue_NT::max_threads (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::max_threads");
+ return this->max_cthrs_;
+}
+
+ACE_INLINE int
+ACE_Message_Queue_NT::deactivated (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::deactivated");
+ // Accessing to int must be atomic.
+ return this->state_ == ACE_Message_Queue_Base::DEACTIVATED;
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_Message_Queue_NT::completion_port (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_NT::completion_port");
+ return this->completion_port_;
+}
+
+ACE_INLINE int
+ACE_Message_Queue_NT::peek_dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_UNUSED_ARG(first_item);
+ ACE_UNUSED_ARG(timeout);
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE ACE_Notification_Strategy *
+ACE_Message_Queue_NT::notification_strategy (void)
+{
+ ACE_NOTSUP_RETURN (0);
+}
+
+ACE_INLINE void
+ACE_Message_Queue_NT::notification_strategy (ACE_Notification_Strategy *)
+{
+}
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Message_Queue_T.cpp b/ACE/ace/Message_Queue_T.cpp
new file mode 100644
index 00000000000..82f29e8656b
--- /dev/null
+++ b/ACE/ace/Message_Queue_T.cpp
@@ -0,0 +1,2814 @@
+// $Id$
+
+#ifndef ACE_MESSAGE_QUEUE_T_CPP
+#define ACE_MESSAGE_QUEUE_T_CPP
+
+// #include Message_Queue.h instead of Message_Queue_T.h to avoid
+// circular include problems.
+#include "ace/Message_Queue.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_time.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Notification_Strategy.h"
+#include "ace/Truncate.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Message_Queue)
+ACE_ALLOC_HOOK_DEFINE(ACE_Dynamic_Message_Queue)
+ACE_ALLOC_HOOK_DEFINE(ACE_Message_Queue_Ex)
+ACE_ALLOC_HOOK_DEFINE(ACE_Message_Queue_Ex_N)
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> void
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dump");
+
+ this->queue_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> void
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_bytes (size_t new_value)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_bytes");
+
+ this->queue_.message_bytes (new_value);
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> void
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_length (size_t new_value)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_length");
+
+ this->queue_.message_length (new_value);
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL>
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::ACE_Message_Queue_Ex (size_t hwm,
+ size_t lwm,
+ ACE_Notification_Strategy *ns)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::ACE_Message_Queue_Ex");
+
+ if (this->queue_.open (hwm, lwm, ns) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Message_Queue_Ex")));
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL>
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::~ACE_Message_Queue_Ex (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::~ACE_Message_Queue_Ex");
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::open (size_t hwm,
+ size_t lwm,
+ ACE_Notification_Strategy *ns)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::open");
+
+ return this->queue_.open (hwm, lwm, ns);
+}
+
+// Clean up the queue if we have not already done so!
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::close (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::close");
+
+ return this->queue_.close ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::flush (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::flush");
+
+ return this->queue_.flush ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::flush_i (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::flush_i");
+
+ return this->queue_.flush_i ();
+}
+
+// Take a look at the first item without removing it.
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::peek_dequeue_head (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::peek_dequeue_head");
+
+ ACE_Message_Block *mb = 0;
+
+ int const cur_count = this->queue_.peek_dequeue_head (mb, timeout);
+
+ if (cur_count != -1)
+ first_item = reinterpret_cast<ACE_MESSAGE_TYPE *> (mb->base ());
+
+ return cur_count;
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_head (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_head");
+
+ ACE_Message_Block *mb = 0;
+
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block ((char *) new_item,
+ sizeof (*new_item),
+ ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::DEFAULT_PRIORITY),
+ -1);
+
+ int const result = this->queue_.enqueue_head (mb, timeout);
+ if (result == -1)
+ // Zap the message.
+ mb->release ();
+ return result;
+}
+
+// Enqueue an <ACE_MESSAGE_TYPE *> into the <Message_Queue> in
+// accordance with its <msg_priority> (0 is lowest priority). Returns
+// -1 on failure, else the number of items still on the queue.
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue");
+
+ return this->enqueue_prio (new_item, timeout);
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_prio (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout,
+ unsigned long priority)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_prio");
+
+ ACE_Message_Block *mb = 0;
+
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block ((char *) new_item,
+ sizeof (*new_item),
+ priority),
+ -1);
+
+ int const result = this->queue_.enqueue_prio (mb, timeout);
+ if (result == -1)
+ // Zap the message.
+ mb->release ();
+
+ return result;
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_deadline (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_deadline");
+
+ ACE_Message_Block *mb = 0;
+
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block ((char *) new_item,
+ sizeof (*new_item),
+ ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::DEFAULT_PRIORITY ),
+ -1);
+
+ int const result = this->queue_.enqueue_deadline (mb, timeout);
+ if (result == -1)
+ // Zap the message.
+ mb->release ();
+
+ return result;
+}
+
+// Block indefinitely waiting for an item to arrive,
+// does not ignore alerts (e.g., signals).
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_tail (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_tail");
+
+ ACE_Message_Block *mb = 0;
+
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block ((char *) new_item,
+ sizeof (*new_item),
+ ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::DEFAULT_PRIORITY),
+ -1);
+
+ int const result = this->queue_.enqueue_tail (mb, timeout);
+ if (result == -1)
+ // Zap the message.
+ mb->release ();
+ return result;
+}
+
+// Remove an item from the front of the queue. If timeout == 0 block
+// indefinitely (or until an alert occurs). Otherwise, block for upto
+// the amount of time specified by timeout.
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue_head (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue_head");
+
+ ACE_Message_Block *mb = 0;
+
+ int const cur_count = this->queue_.dequeue_head (mb, timeout);
+
+ // Dequeue the message.
+ if (cur_count != -1)
+ {
+ first_item = reinterpret_cast<ACE_MESSAGE_TYPE *> (mb->base ());
+ // Delete the message block.
+ mb->release ();
+ }
+
+ return cur_count;
+}
+
+// Remove the item with the lowest priority from the queue. If timeout == 0
+// block indefinitely (or until an alert occurs). Otherwise, block for upto
+// the amount of time specified by timeout.
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue_prio (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue_prio");
+
+ ACE_Message_Block *mb = 0;
+
+ int const cur_count = this->queue_.dequeue_prio (mb, timeout);
+
+ // Dequeue the message.
+ if (cur_count != -1)
+ {
+ dequeued = reinterpret_cast<ACE_MESSAGE_TYPE *> (mb->base ());
+ // Delete the message block.
+ mb->release ();
+ }
+
+ return cur_count;
+}
+
+// Remove an item from the end of the queue. If timeout == 0 block
+// indefinitely (or until an alert occurs). Otherwise, block for upto
+// the amount of time specified by timeout.
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue_tail (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue_tail");
+
+ ACE_Message_Block *mb = 0;
+
+ int const cur_count = this->queue_.dequeue_tail (mb, timeout);
+
+ // Dequeue the message.
+ if (cur_count != -1)
+ {
+ dequeued = reinterpret_cast<ACE_MESSAGE_TYPE *> (mb->base ());
+ // Delete the message block.
+ mb->release ();
+ }
+
+ return cur_count;
+}
+
+// Remove an item with the lowest deadline time. If timeout == 0 block
+// indefinitely (or until an alert occurs). Otherwise, block for upto
+// the amount of time specified by timeout.
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue_deadline (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue_deadline");
+
+ ACE_Message_Block *mb = 0;
+
+ int const cur_count = this->queue_.dequeue_deadline (mb, timeout);
+
+ // Dequeue the message.
+ if (cur_count != -1)
+ {
+ dequeued = reinterpret_cast<ACE_MESSAGE_TYPE *> (mb->base ());
+ // Delete the message block.
+ mb->release ();
+ }
+
+ return cur_count;
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::notify (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::notify");
+
+ return this->queue_.notify ();
+}
+
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL>
+ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::ACE_Message_Queue_Ex_N
+ (size_t high_water_mark,
+ size_t low_water_mark,
+ ACE_Notification_Strategy *ns):
+ ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE> (high_water_mark,
+ low_water_mark,
+ ns)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::ACE_Message_Queue_Ex_N");
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL>
+ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::~ACE_Message_Queue_Ex_N (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::~ACE_Message_Queue_Ex_N");
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_head
+ (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_head");
+
+ // Create a chained ACE_Message_Blocks wrappers around the 'chained'
+ // ACE_MESSAGE_TYPES.
+ ACE_Message_Block *mb = this->wrap_with_mbs_i (new_item);
+ if (0 == mb)
+ {
+ return -1;
+ }
+
+ int result = this->queue_.enqueue_head (mb, timeout);
+ if (-1 == result)
+ {
+ // Zap the messages.
+ mb->release ();
+ }
+ return result;
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_tail
+ (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::enqueue_tail");
+
+ // Create a chained ACE_Message_Blocks wrappers around the 'chained'
+ // ACE_MESSAGE_TYPES.
+ ACE_Message_Block *mb = this->wrap_with_mbs_i (new_item);
+ if (0 == mb)
+ {
+ return -1;
+ }
+
+ int result = this->queue_.enqueue_tail (mb, timeout);
+ if (-1 == result)
+ {
+ // Zap the message.
+ mb->release ();
+ }
+ return result;
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> ACE_Message_Block *
+ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::wrap_with_mbs_i
+ (ACE_MESSAGE_TYPE *new_item)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex_N<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::wrap_with_mbs_i");
+
+ // We need to keep a reference to the head of the chain
+ ACE_Message_Block *mb_head = 0;
+
+ ACE_NEW_RETURN (mb_head,
+ ACE_Message_Block ((char *) new_item,
+ sizeof (*new_item),
+ ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::DEFAULT_PRIORITY),
+ 0);
+
+ // mb_tail will point to the last ACE_Message_Block
+ ACE_Message_Block *mb_tail = mb_head;
+
+ // Run through rest of the messages and wrap them
+ for (ACE_MESSAGE_TYPE *pobj = new_item->next (); pobj; pobj = pobj->next ())
+ {
+ ACE_Message_Block *mb_temp = 0;
+ ACE_NEW_NORETURN (mb_temp,
+ ACE_Message_Block ((char *) pobj,
+ sizeof (*pobj),
+ ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::DEFAULT_PRIORITY));
+ if (mb_temp == 0)
+ {
+ mb_head->release ();
+ mb_head = 0;
+ break;
+ }
+
+ mb_tail->next (mb_temp);
+ mb_tail = mb_temp;
+ }
+
+ return mb_head;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Message_Queue_Reverse_Iterator)
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::dequeue");
+
+ return this->dequeue_head (first_item, timeout);
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> ACE_Notification_Strategy *
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::notification_strategy (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::notification_strategy");
+
+ return this->queue_.notification_strategy ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> void
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::notification_strategy (ACE_Notification_Strategy *s)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::notification_strategy");
+
+ this->queue_.notification_strategy (s);
+}
+
+// Check if queue is empty (holds locks).
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> bool
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::is_empty (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::is_empty");
+
+ return this->queue_.is_empty ();
+}
+
+// Check if queue is full (holds locks).
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> bool
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::is_full (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::is_full");
+
+ return this->queue_.is_full ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> size_t
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::high_water_mark (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::high_water_mark");
+
+ return this->queue_.high_water_mark ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> void
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::high_water_mark (size_t hwm)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::high_water_mark");
+
+ this->queue_.high_water_mark (hwm);
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> size_t
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::low_water_mark (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::low_water_mark");
+
+ return this->queue_.low_water_mark ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> void
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::low_water_mark (size_t lwm)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::low_water_mark");
+
+ this->queue_.low_water_mark (lwm);
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> size_t
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_bytes (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_bytes");
+
+ return this->queue_.message_bytes ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> size_t
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_length (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_length");
+
+ return this->queue_.message_length ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> size_t
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_count (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::message_count");
+
+ return this->queue_.message_count ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::deactivate (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::deactivate");
+
+ return this->queue_.deactivate ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::activate (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::activate");
+
+ return this->queue_.activate ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::pulse (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::pulse");
+
+ return this->queue_.pulse ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::deactivated (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::deactivated");
+
+ return this->queue_.deactivated ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> int
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::state (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::state");
+
+ return this->queue_.state ();
+}
+
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL> ACE_SYNCH_MUTEX_T &
+ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>::lock (void)
+{
+ return this->queue_.lock ();
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Message_Queue_Iterator<ACE_SYNCH_USE>::ACE_Message_Queue_Iterator (ACE_Message_Queue <ACE_SYNCH_USE> &q)
+ : queue_ (q),
+ curr_ (q.head_)
+{
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue_Iterator<ACE_SYNCH_USE>::next (ACE_Message_Block *&entry)
+{
+ ACE_READ_GUARD_RETURN (ACE_SYNCH_MUTEX_T, m, this->queue_.lock_, -1)
+
+ if (this->curr_ != 0)
+ {
+ entry = this->curr_;
+ return 1;
+ }
+
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue_Iterator<ACE_SYNCH_USE>::done (void) const
+{
+ ACE_READ_GUARD_RETURN (ACE_SYNCH_MUTEX_T, m, this->queue_.lock_, -1)
+
+ return this->curr_ == 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue_Iterator<ACE_SYNCH_USE>::advance (void)
+{
+ ACE_READ_GUARD_RETURN (ACE_SYNCH_MUTEX_T, m, this->queue_.lock_, -1)
+
+ if (this->curr_)
+ this->curr_ = this->curr_->next ();
+ return this->curr_ != 0;
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Message_Queue_Iterator<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Message_Queue_Iterator)
+
+template <ACE_SYNCH_DECL>
+ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>::ACE_Message_Queue_Reverse_Iterator (ACE_Message_Queue <ACE_SYNCH_USE> &q)
+ : queue_ (q),
+ curr_ (queue_.tail_)
+{
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>::next (ACE_Message_Block *&entry)
+{
+ ACE_READ_GUARD_RETURN (ACE_SYNCH_MUTEX_T, m, this->queue_.lock_, -1)
+
+ if (this->curr_ != 0)
+ {
+ entry = this->curr_;
+ return 1;
+ }
+
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>::done (void) const
+{
+ ACE_READ_GUARD_RETURN (ACE_SYNCH_MUTEX_T, m, this->queue_.lock_, -1)
+
+ return this->curr_ == 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>::advance (void)
+{
+ ACE_READ_GUARD_RETURN (ACE_SYNCH_MUTEX_T, m, this->queue_.lock_, -1)
+
+ if (this->curr_)
+ this->curr_ = this->curr_->prev ();
+ return this->curr_ != 0;
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue");
+ return this->dequeue_head (first_item, timeout);
+}
+
+template <ACE_SYNCH_DECL> ACE_Notification_Strategy *
+ACE_Message_Queue<ACE_SYNCH_USE>::notification_strategy (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::notification_strategy");
+
+ return this->notification_strategy_;
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Message_Queue<ACE_SYNCH_USE>::notification_strategy (ACE_Notification_Strategy *s)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::notification_strategy");
+
+ this->notification_strategy_ = s;
+}
+
+// Check if queue is empty (does not hold locks).
+
+template <ACE_SYNCH_DECL> bool
+ACE_Message_Queue<ACE_SYNCH_USE>::is_empty_i (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::is_empty_i");
+ return this->tail_ == 0;
+}
+
+// Check if queue is full (does not hold locks).
+
+template <ACE_SYNCH_DECL> bool
+ACE_Message_Queue<ACE_SYNCH_USE>::is_full_i (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::is_full_i");
+ return this->cur_bytes_ >= this->high_water_mark_;
+}
+
+// Check if queue is empty (holds locks).
+
+template <ACE_SYNCH_DECL> bool
+ACE_Message_Queue<ACE_SYNCH_USE>::is_empty (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::is_empty");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, false);
+
+ return this->is_empty_i ();
+}
+
+// Check if queue is full (holds locks).
+
+template <ACE_SYNCH_DECL> bool
+ACE_Message_Queue<ACE_SYNCH_USE>::is_full (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::is_full");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, false);
+
+ return this->is_full_i ();
+}
+
+template <ACE_SYNCH_DECL> size_t
+ACE_Message_Queue<ACE_SYNCH_USE>::high_water_mark (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::high_water_mark");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, 0);
+
+ return this->high_water_mark_;
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Message_Queue<ACE_SYNCH_USE>::high_water_mark (size_t hwm)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::high_water_mark");
+ ACE_GUARD (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_);
+
+ this->high_water_mark_ = hwm;
+}
+
+template <ACE_SYNCH_DECL> size_t
+ACE_Message_Queue<ACE_SYNCH_USE>::low_water_mark (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::low_water_mark");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, 0);
+
+ return this->low_water_mark_;
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Message_Queue<ACE_SYNCH_USE>::low_water_mark (size_t lwm)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::low_water_mark");
+ ACE_GUARD (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_);
+
+ this->low_water_mark_ = lwm;
+}
+
+template <ACE_SYNCH_DECL> size_t
+ACE_Message_Queue<ACE_SYNCH_USE>::message_bytes (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::message_bytes");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, 0);
+
+ return this->cur_bytes_;
+}
+
+template <ACE_SYNCH_DECL> size_t
+ACE_Message_Queue<ACE_SYNCH_USE>::message_length (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::message_length");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, 0);
+
+ return this->cur_length_;
+}
+
+template <ACE_SYNCH_DECL> size_t
+ACE_Message_Queue<ACE_SYNCH_USE>::message_count (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::message_count");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, 0);
+
+ return this->cur_count_;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::deactivate ()
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::deactivate");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ return this->deactivate_i (0); // Not a pulse
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::activate (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::activate");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ return this->activate_i ();
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::pulse ()
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::pulse");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ return this->deactivate_i (1); // Just a pulse
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::deactivated (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::deactivated");
+
+ return this->state_ == ACE_Message_Queue_Base::DEACTIVATED;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::state (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::state");
+
+ return this->state_;
+}
+
+template <ACE_SYNCH_DECL> ACE_SYNCH_MUTEX_T &
+ACE_Message_Queue<ACE_SYNCH_USE>::lock (void)
+{
+ return this->lock_;
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Message_Queue<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ switch (this->state_)
+ {
+ case ACE_Message_Queue_Base::ACTIVATED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = ACTIVATED\n")));
+ break;
+ case ACE_Message_Queue_Base::DEACTIVATED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = DEACTIVATED\n")));
+ break;
+ case ACE_Message_Queue_Base::PULSED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = PULSED\n")));
+ break;
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("low_water_mark = %d\n")
+ ACE_TEXT ("high_water_mark = %d\n")
+ ACE_TEXT ("cur_bytes = %d\n")
+ ACE_TEXT ("cur_length = %d\n")
+ ACE_TEXT ("cur_count = %d\n")
+ ACE_TEXT ("head_ = %u\n")
+ ACE_TEXT ("tail_ = %u\n"),
+ this->low_water_mark_,
+ this->high_water_mark_,
+ this->cur_bytes_,
+ this->cur_length_,
+ this->cur_count_,
+ this->head_,
+ this->tail_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("not_full_cond: \n")));
+ not_full_cond_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("not_empty_cond: \n")));
+ not_empty_cond_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Message_Queue<ACE_SYNCH_USE>::message_bytes (size_t new_value)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::message_bytes");
+ ACE_GUARD (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_);
+
+ this->cur_bytes_ = new_value;
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Message_Queue<ACE_SYNCH_USE>::message_length (size_t new_value)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::message_length");
+ ACE_GUARD (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_);
+
+ this->cur_length_ = new_value;
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Message_Queue<ACE_SYNCH_USE>::ACE_Message_Queue (size_t hwm,
+ size_t lwm,
+ ACE_Notification_Strategy *ns)
+ : not_empty_cond_ (lock_),
+ not_full_cond_ (lock_)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::ACE_Message_Queue");
+
+ if (this->open (hwm, lwm, ns) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("open")));
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Message_Queue<ACE_SYNCH_USE>::~ACE_Message_Queue (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::~ACE_Message_Queue");
+ if (this->head_ != 0 && this->close () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("close")));
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::flush_i (void)
+{
+ int number_flushed = 0;
+
+ // Remove all the <ACE_Message_Block>s in the <ACE_Message_Queue>
+ // and <release> their memory.
+ for (this->tail_ = 0; this->head_ != 0; )
+ {
+ ++number_flushed;
+
+ size_t mb_bytes = 0;
+ size_t mb_length = 0;
+ this->head_->total_size_and_length (mb_bytes,
+ mb_length);
+ // Subtract off all of the bytes associated with this message.
+ this->cur_bytes_ -= mb_bytes;
+ this->cur_length_ -= mb_length;
+ --this->cur_count_;
+
+ ACE_Message_Block *temp = this->head_;
+ this->head_ = this->head_->next ();
+
+ // Make sure to use <release> rather than <delete> since this is
+ // reference counted.
+ temp->release ();
+ }
+
+ return number_flushed;
+}
+
+// Don't bother locking since if someone calls this function more than
+// once for the same queue, we're in bigger trouble than just
+// concurrency control!
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::open (size_t hwm,
+ size_t lwm,
+ ACE_Notification_Strategy *ns)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::open");
+ this->high_water_mark_ = hwm;
+ this->low_water_mark_ = lwm;
+ this->state_ = ACE_Message_Queue_Base::ACTIVATED;
+ this->cur_bytes_ = 0;
+ this->cur_length_ = 0;
+ this->cur_count_ = 0;
+ this->tail_ = 0;
+ this->head_ = 0;
+ this->notification_strategy_ = ns;
+ return 0;
+}
+
+// Implementation of the public deactivate() method
+// (assumes locks are held).
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::deactivate_i (int pulse)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::deactivate_i");
+ int const previous_state = this->state_;
+
+ if (previous_state != ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ // Wakeup all waiters.
+ this->not_empty_cond_.broadcast ();
+ this->not_full_cond_.broadcast ();
+
+ if (pulse)
+ this->state_ = ACE_Message_Queue_Base::PULSED;
+ else
+ this->state_ = ACE_Message_Queue_Base::DEACTIVATED;
+ }
+ return previous_state;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::activate_i (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::activate_i");
+ int const previous_state = this->state_;
+ this->state_ = ACE_Message_Queue_Base::ACTIVATED;
+ return previous_state;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::flush (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::flush");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ // Free up the remaining messages on the queue.
+ return this->flush_i ();
+}
+
+// Clean up the queue if we have not already done so!
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::close (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::close");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ int const result = this->deactivate_i ();
+
+ // Free up the remaining messages on the queue.
+ this->flush_i ();
+
+ return result;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::signal_enqueue_waiters (void)
+{
+ if (this->not_full_cond_.signal () != 0)
+ return -1;
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::signal_dequeue_waiters (void)
+{
+ // Tell any blocked threads that the queue has a new item!
+ if (this->not_empty_cond_.signal () != 0)
+ return -1;
+ return 0;
+}
+
+// Actually put the node at the end (no locking so must be called with
+// locks held).
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_tail_i (ACE_Message_Block *new_item)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_tail_i");
+
+ if (new_item == 0)
+ return -1;
+
+ // Update the queued size and length, taking into account any chained
+ // blocks (total_size_and_length() counts all continuation blocks).
+ // Keep count of how many blocks we're adding and, if there is a chain of
+ // blocks, find the end in seq_tail and be sure they're properly
+ // back-connected along the way.
+ ACE_Message_Block *seq_tail = new_item;
+ ++this->cur_count_;
+ new_item->total_size_and_length (this->cur_bytes_,
+ this->cur_length_);
+ while (seq_tail->next () != 0)
+ {
+ seq_tail->next ()->prev (seq_tail);
+ seq_tail = seq_tail->next ();
+ ++this->cur_count_;
+ seq_tail->total_size_and_length (this->cur_bytes_,
+ this->cur_length_);
+ }
+
+ // List was empty, so build a new one.
+ if (this->tail_ == 0)
+ {
+ this->head_ = new_item;
+ this->tail_ = seq_tail;
+ // seq_tail->next (0); This is a condition of the while() loop above.
+ new_item->prev (0);
+ }
+ // Link at the end.
+ else
+ {
+ // seq_tail->next (0); This is a condition of the while() loop above.
+ this->tail_->next (new_item);
+ new_item->prev (this->tail_);
+ this->tail_ = seq_tail;
+ }
+
+ if (this->signal_dequeue_waiters () == -1)
+ return -1;
+ else
+ return ACE_Utils::truncate_cast<int> (this->cur_count_);
+}
+
+// Actually put the node(s) at the head (no locking)
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_head_i (ACE_Message_Block *new_item)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_head_i");
+
+ if (new_item == 0)
+ return -1;
+
+ // Update the queued size and length, taking into account any chained
+ // blocks (total_size_and_length() counts all continuation blocks).
+ // Keep count of how many blocks we're adding and, if there is a chain of
+ // blocks, find the end in seq_tail and be sure they're properly
+ // back-connected along the way.
+ ACE_Message_Block *seq_tail = new_item;
+ ++this->cur_count_;
+ new_item->total_size_and_length (this->cur_bytes_,
+ this->cur_length_);
+ while (seq_tail->next () != 0)
+ {
+ seq_tail->next ()->prev (seq_tail);
+ seq_tail = seq_tail->next ();
+ ++this->cur_count_;
+ seq_tail->total_size_and_length (this->cur_bytes_,
+ this->cur_length_);
+ }
+
+ new_item->prev (0);
+ seq_tail->next (this->head_);
+
+ if (this->head_ != 0)
+ this->head_->prev (seq_tail);
+ else
+ this->tail_ = seq_tail;
+
+ this->head_ = new_item;
+
+ if (this->signal_dequeue_waiters () == -1)
+ return -1;
+ else
+ return ACE_Utils::truncate_cast<int> (this->cur_count_);
+}
+
+// Actually put the node at its proper position relative to its
+// priority.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_i (ACE_Message_Block *new_item)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_i");
+
+ if (new_item == 0)
+ return -1;
+
+ // Since this method uses enqueue_head_i() and enqueue_tail_i() for
+ // special situations, and this method doesn't support enqueueing
+ // chains of blocks off the 'next' pointer, make sure the new_item's
+ // next pointer is 0.
+ new_item->next (0);
+
+ if (this->head_ == 0)
+ // Check for simple case of an empty queue, where all we need to
+ // do is insert <new_item> into the head.
+ return this->enqueue_head_i (new_item);
+ else
+ {
+ ACE_Message_Block *temp = 0;
+
+ // Figure out where the new item goes relative to its priority.
+ // We start looking from the lowest priority (at the tail) to
+ // the highest priority (at the head).
+
+ for (temp = this->tail_;
+ temp != 0;
+ temp = temp->prev ())
+ if (temp->msg_priority () >= new_item->msg_priority ())
+ // Break out when we've located an item that has
+ // greater or equal priority.
+ break;
+
+ if (temp == 0)
+ // Check for simple case of inserting at the head of the queue,
+ // where all we need to do is insert <new_item> before the
+ // current head.
+ return this->enqueue_head_i (new_item);
+ else if (temp->next () == 0)
+ // Check for simple case of inserting at the tail of the
+ // queue, where all we need to do is insert <new_item> after
+ // the current tail.
+ return this->enqueue_tail_i (new_item);
+ else
+ {
+ // Insert the new message behind the message of greater or
+ // equal priority. This ensures that FIFO order is
+ // maintained when messages of the same priority are
+ // inserted consecutively.
+ new_item->prev (temp);
+ new_item->next (temp->next ());
+ temp->next ()->prev (new_item);
+ temp->next (new_item);
+ }
+ }
+
+ // Make sure to count all the bytes in a composite message!!!
+ new_item->total_size_and_length (this->cur_bytes_,
+ this->cur_length_);
+ ++this->cur_count_;
+
+ if (this->signal_dequeue_waiters () == -1)
+ return -1;
+ else
+ return ACE_Utils::truncate_cast<int> (this->cur_count_);
+}
+
+// Actually put the node at its proper position relative to its
+// deadline time.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_deadline_i (ACE_Message_Block *new_item)
+{
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_deadline_i");
+
+ if (new_item == 0)
+ return -1;
+
+ // Since this method uses enqueue_head_i() and enqueue_tail_i() for
+ // special situations, and this method doesn't support enqueueing
+ // chains of blocks off the 'next' pointer, make sure the new_item's
+ // next pointer is 0.
+ new_item->next (0);
+
+ if (this->head_ == 0)
+ // Check for simple case of an empty queue, where all we need to
+ // do is insert <new_item> into the head.
+ return this->enqueue_head_i (new_item);
+ else
+ {
+ ACE_Message_Block *temp = 0;
+
+ // Figure out where the new item goes relative to its priority.
+ // We start looking from the smallest deadline to the highest
+ // deadline.
+
+ for (temp = this->head_;
+ temp != 0;
+ temp = temp->next ())
+ if (new_item->msg_deadline_time () < temp->msg_deadline_time ())
+ // Break out when we've located an item that has
+ // greater or equal priority.
+ break;
+
+ if (temp == 0 || temp->next () == 0)
+ // Check for simple case of inserting at the tail of the queue,
+ // where all we need to do is insert <new_item> after the
+ // current tail.
+ return this->enqueue_tail_i (new_item);
+ else
+ {
+ // Insert the new message behind the message of
+ // lesser or equal deadline time. This ensures that FIFO order is
+ // maintained when messages of the same priority are
+ // inserted consecutively.
+ new_item->prev (temp);
+ new_item->next (temp->next ());
+ temp->next ()->prev (new_item);
+ temp->next (new_item);
+ }
+ }
+
+ // Make sure to count all the bytes in a composite message!!!
+ new_item->total_size_and_length (this->cur_bytes_,
+ this->cur_length_);
+ ++this->cur_count_;
+
+ if (this->signal_dequeue_waiters () == -1)
+ return -1;
+ else
+ return this->cur_count_;
+#else
+ return this->enqueue_tail_i (new_item);
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+}
+
+// Actually get the first ACE_Message_Block (no locking, so must be
+// called with locks held). This method assumes that the queue has at
+// least one item in it when it is called.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_head_i (ACE_Message_Block *&first_item)
+{
+ if (this->head_ ==0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Attempting to dequeue from empty queue")),
+ -1);
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_head_i");
+ first_item = this->head_;
+ this->head_ = this->head_->next ();
+
+ if (this->head_ == 0)
+ this->tail_ = 0;
+ else
+ // The prev pointer of first message block must point to 0...
+ this->head_->prev (0);
+
+ size_t mb_bytes = 0;
+ size_t mb_length = 0;
+ first_item->total_size_and_length (mb_bytes,
+ mb_length);
+ // Subtract off all of the bytes associated with this message.
+ this->cur_bytes_ -= mb_bytes;
+ this->cur_length_ -= mb_length;
+ --this->cur_count_;
+
+ if (this->cur_count_ == 0 && this->head_ == this->tail_)
+ this->head_ = this->tail_ = 0;
+
+ // Make sure that the prev and next fields are 0!
+ first_item->prev (0);
+ first_item->next (0);
+
+ // Only signal enqueueing threads if we've fallen below the low
+ // water mark.
+ if (this->cur_bytes_ <= this->low_water_mark_
+ && this->signal_enqueue_waiters () == -1)
+ return -1;
+ else
+ return ACE_Utils::truncate_cast<int> (this->cur_count_);
+}
+
+// Get the earliest (i.e., FIFO) ACE_Message_Block with the lowest
+// priority (no locking, so must be called with locks held). This
+// method assumes that the queue has at least one item in it when it
+// is called.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_prio_i (ACE_Message_Block *&dequeued)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_prio_i");
+
+ if (this->head_ == 0)
+ return -1;
+
+ // Find the earliest (i.e., FIFO) message enqueued with the lowest
+ // priority.
+ ACE_Message_Block *chosen = 0;
+ u_long priority = ULONG_MAX;
+
+ for (ACE_Message_Block *temp = this->tail_;
+ temp != 0;
+ temp = temp->prev ())
+ {
+ // Find the first version of the earliest message (i.e.,
+ // preserve FIFO order for messages at the same priority).
+ if (temp->msg_priority () <= priority)
+ {
+ priority = temp->msg_priority ();
+ chosen = temp;
+ }
+ }
+
+ // If every message block is the same priority, pass back the first
+ // one.
+ if (chosen == 0)
+ chosen = this->head_;
+
+ // Patch up the queue. If we don't have a previous then we are at
+ // the head of the queue.
+ if (chosen->prev () == 0)
+ this->head_ = chosen->next ();
+ else
+ chosen->prev ()->next (chosen->next ());
+
+ if (chosen->next () == 0)
+ this->tail_ = chosen->prev ();
+ else
+ chosen->next ()->prev (chosen->prev ());
+
+ // Pass back the chosen block
+ dequeued = chosen;
+
+ size_t mb_bytes = 0;
+ size_t mb_length = 0;
+ dequeued->total_size_and_length (mb_bytes,
+ mb_length);
+ // Subtract off all of the bytes associated with this message.
+ this->cur_bytes_ -= mb_bytes;
+ this->cur_length_ -= mb_length;
+ --this->cur_count_;
+
+ if (this->cur_count_ == 0 && this->head_ == this->tail_)
+ this->head_ = this->tail_ = 0;
+
+ // Make sure that the prev and next fields are 0!
+ dequeued->prev (0);
+ dequeued->next (0);
+
+ // Only signal enqueueing threads if we've fallen below the low
+ // water mark.
+ if (this->cur_bytes_ <= this->low_water_mark_
+ && this->signal_enqueue_waiters () == -1)
+ return -1;
+ else
+ return ACE_Utils::truncate_cast<int> (this->cur_count_);
+}
+
+// Actually get the last ACE_Message_Block (no locking, so must be
+// called with locks held). This method assumes that the queue has at
+// least one item in it when it is called.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_tail_i (ACE_Message_Block *&dequeued)
+{
+ if (this->head_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Attempting to dequeue from empty queue")),
+ -1);
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_tail_i");
+ dequeued = this->tail_;
+ if (this->tail_->prev () == 0)
+ {
+ this->head_ = 0;
+ this->tail_ = 0;
+ }
+ else
+ {
+ this->tail_->prev ()->next (0);
+ this->tail_ = this->tail_->prev ();
+ }
+
+ size_t mb_bytes = 0;
+ size_t mb_length = 0;
+ dequeued->total_size_and_length (mb_bytes,
+ mb_length);
+ // Subtract off all of the bytes associated with this message.
+ this->cur_bytes_ -= mb_bytes;
+ this->cur_length_ -= mb_length;
+ --this->cur_count_;
+
+ if (this->cur_count_ == 0 && this->head_ == this->tail_)
+ this->head_ = this->tail_ = 0;
+
+ // Make sure that the prev and next fields are 0!
+ dequeued->prev (0);
+ dequeued->next (0);
+
+ // Only signal enqueueing threads if we've fallen below the low
+ // water mark.
+ if (this->cur_bytes_ <= this->low_water_mark_
+ && this->signal_enqueue_waiters () == -1)
+ return -1;
+ else
+ return ACE_Utils::truncate_cast<int> (this->cur_count_);
+}
+
+// Actually get the ACE_Message_Block with the lowest deadline time
+// (no locking, so must be called with locks held). This method assumes
+// that the queue has at least one item in it when it is called.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_deadline_i (ACE_Message_Block *&dequeued)
+{
+#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
+ if (this->head_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Attempting to dequeue from empty queue")),
+ -1);
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_deadline_i");
+
+ // Find the last message enqueued with the lowest deadline time
+ ACE_Message_Block* chosen = 0;
+ ACE_Time_Value deadline = ACE_Time_Value::max_time;
+ for (ACE_Message_Block *temp = this->head_; temp != 0; temp = temp->next ())
+ if (temp->msg_deadline_time () < deadline)
+ {
+ deadline = temp->msg_deadline_time ();
+ chosen = temp;
+ }
+
+ // If every message block is the same deadline time,
+ // pass back the first one
+ if (chosen == 0)
+ chosen = this->head_;
+
+ // Patch up the queue. If we don't have a previous
+ // then we are at the head of the queue.
+ if (chosen->prev () == 0)
+ this->head_ = chosen->next ();
+ else
+ chosen->prev ()->next (chosen->next ());
+
+ if (chosen->next () == 0)
+ this->tail_ = chosen->prev ();
+ else
+ chosen->next ()->prev (chosen->prev ());
+
+ // Pass back the chosen block
+ dequeued = chosen;
+
+ size_t mb_bytes = 0;
+ size_t mb_length = 0;
+ dequeued->total_size_and_length (mb_bytes,
+ mb_length);
+ // Subtract off all of the bytes associated with this message.
+ this->cur_bytes_ -= mb_bytes;
+ this->cur_length_ -= mb_length;
+ --this->cur_count_;
+
+ if (this->cur_count_ == 0 && this->head_ == this->tail_)
+ this->head_ = this->tail_ = 0;
+
+ // Make sure that the prev and next fields are 0!
+ dequeued->prev (0);
+ dequeued->next (0);
+
+ // Only signal enqueueing threads if we've fallen below the low
+ // water mark.
+ if (this->cur_bytes_ <= this->low_water_mark_
+ && this->signal_enqueue_waiters () == -1)
+ return -1;
+ else
+ return this->cur_count_;
+#else
+ return this->dequeue_head_i (dequeued);
+#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
+}
+
+// Take a look at the first item without removing it.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::peek_dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::peek_dequeue_head");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ // Wait for at least one item to become available.
+
+ if (this->wait_not_empty_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ first_item = this->head_;
+ return ACE_Utils::truncate_cast<int> (this->cur_count_);
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::wait_not_full_cond (ACE_Guard<ACE_SYNCH_MUTEX_T> &,
+ ACE_Time_Value *timeout)
+{
+ int result = 0;
+
+ // Wait while the queue is full.
+
+ while (this->is_full_i ())
+ {
+ if (this->not_full_cond_.wait (timeout) == -1)
+ {
+ if (errno == ETIME)
+ errno = EWOULDBLOCK;
+ result = -1;
+ break;
+ }
+ if (this->state_ != ACE_Message_Queue_Base::ACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ result = -1;
+ break;
+ }
+ }
+ return result;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::wait_not_empty_cond
+ (ACE_Guard<ACE_SYNCH_MUTEX_T> &, ACE_Time_Value *timeout)
+{
+ int result = 0;
+
+ // Wait while the queue is empty.
+
+ while (this->is_empty_i ())
+ {
+ if (this->not_empty_cond_.wait (timeout) == -1)
+ {
+ if (errno == ETIME)
+ errno = EWOULDBLOCK;
+ result = -1;
+ break;
+ }
+ if (this->state_ != ACE_Message_Queue_Base::ACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ result = -1;
+ break;
+ }
+ }
+ return result;
+}
+
+// Block indefinitely waiting for an item to arrive, does not ignore
+// alerts (e.g., signals).
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_head (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_head");
+ int queue_count = 0;
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ if (this->wait_not_full_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ queue_count = this->enqueue_head_i (new_item);
+
+ if (queue_count == -1)
+ return -1;
+
+ this->notify ();
+ }
+ return queue_count;
+}
+
+// Enqueue an <ACE_Message_Block *> into the <Message_Queue> in
+// accordance with its <msg_priority> (0 is lowest priority). Returns
+// -1 on failure, else the number of items still on the queue.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_prio (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_prio");
+ int queue_count = 0;
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ if (this->wait_not_full_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ queue_count = this->enqueue_i (new_item);
+
+ if (queue_count == -1)
+ return -1;
+
+ this->notify ();
+ }
+ return queue_count;
+}
+
+// Enqueue an <ACE_Message_Block *> into the <Message_Queue> in
+// accordance with its <msg_deadline_time>. Returns
+// -1 on failure, else the number of items still on the queue.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_deadline (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_deadline");
+ int queue_count = 0;
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ if (this->wait_not_full_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ queue_count = this->enqueue_deadline_i (new_item);
+
+ if (queue_count == -1)
+ return -1;
+
+ this->notify ();
+ }
+ return queue_count;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue");
+ return this->enqueue_prio (new_item, timeout);
+}
+
+// Block indefinitely waiting for an item to arrive,
+// does not ignore alerts (e.g., signals).
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_tail (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::enqueue_tail");
+ int queue_count = 0;
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ if (this->wait_not_full_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ queue_count = this->enqueue_tail_i (new_item);
+
+ if (queue_count == -1)
+ return -1;
+
+ this->notify ();
+ }
+ return queue_count;
+}
+
+// Remove an item from the front of the queue. If timeout == 0 block
+// indefinitely (or until an alert occurs). Otherwise, block for upto
+// the amount of time specified by timeout.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_head");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ if (this->wait_not_empty_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ return this->dequeue_head_i (first_item);
+}
+
+// Remove item with the lowest priority from the queue. If timeout == 0 block
+// indefinitely (or until an alert occurs). Otherwise, block for upto
+// the amount of time specified by timeout.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_prio (ACE_Message_Block *&dequeued,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_prio");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ if (this->wait_not_empty_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ return this->dequeue_prio_i (dequeued);
+}
+
+// Remove an item from the end of the queue. If timeout == 0 block
+// indefinitely (or until an alert occurs). Otherwise, block for upto
+// the amount of time specified by timeout.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_tail (ACE_Message_Block *&dequeued,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_tail");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ if (this->wait_not_empty_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ return this->dequeue_tail_i (dequeued);
+}
+
+// Remove an item with the lowest deadline time. If timeout == 0 block
+// indefinitely (or until an alert occurs). Otherwise, block for upto
+// the amount of time specified by timeout.
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_deadline (ACE_Message_Block *&dequeued,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::dequeue_deadline");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ if (this->wait_not_empty_cond (ace_mon, timeout) == -1)
+ return -1;
+
+ return this->dequeue_deadline_i (dequeued);
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Message_Queue<ACE_SYNCH_USE>::notify (void)
+{
+ ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_USE>::notify");
+
+ // By default, don't do anything.
+ if (this->notification_strategy_ == 0)
+ return 0;
+ else
+ return this->notification_strategy_->notify ();
+}
+
+
+// = Initialization and termination methods.
+template <ACE_SYNCH_DECL>
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::ACE_Dynamic_Message_Queue (ACE_Dynamic_Message_Strategy & message_strategy,
+ size_t hwm,
+ size_t lwm,
+ ACE_Notification_Strategy *ns)
+ : ACE_Message_Queue<ACE_SYNCH_USE> (hwm, lwm, ns),
+ pending_head_ (0),
+ pending_tail_ (0),
+ late_head_ (0),
+ late_tail_ (0),
+ beyond_late_head_ (0),
+ beyond_late_tail_ (0),
+ message_strategy_ (message_strategy)
+{
+ // Note, the ACE_Dynamic_Message_Queue assumes full responsibility
+ // for the passed ACE_Dynamic_Message_Strategy object, and deletes
+ // it in its own dtor
+}
+
+// dtor: free message strategy and let base class dtor do the rest.
+
+template <ACE_SYNCH_DECL>
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::~ACE_Dynamic_Message_Queue (void)
+{
+ delete &this->message_strategy_;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::remove_messages (ACE_Message_Block *&list_head,
+ ACE_Message_Block *&list_tail,
+ u_int status_flags)
+{
+ // start with an empty list
+ list_head = 0;
+ list_tail = 0;
+
+ // Get the current time
+ ACE_Time_Value current_time = ACE_OS::gettimeofday ();
+
+ // Refresh priority status boundaries in the queue.
+ int result = this->refresh_queue (current_time);
+ if (result < 0)
+ return result;
+
+ if (ACE_BIT_ENABLED (status_flags,
+ (u_int) ACE_Dynamic_Message_Strategy::PENDING)
+ && this->pending_head_
+ && this->pending_tail_)
+ {
+ // patch up pointers for the new tail of the queue
+ if (this->pending_head_->prev ())
+ {
+ this->tail_ = this->pending_head_->prev ();
+ this->pending_head_->prev ()->next (0);
+ }
+ else
+ {
+ // the list has become empty
+ this->head_ = 0;
+ this->tail_ = 0;
+ }
+
+ // point to the head and tail of the list
+ list_head = this->pending_head_;
+ list_tail = this->pending_tail_;
+
+ // cut the pending messages out of the queue entirely
+ this->pending_head_->prev (0);
+ this->pending_head_ = 0;
+ this->pending_tail_ = 0;
+ }
+
+ if (ACE_BIT_ENABLED (status_flags,
+ (u_int) ACE_Dynamic_Message_Strategy::LATE)
+ && this->late_head_
+ && this->late_tail_)
+ {
+ // Patch up pointers for the (possibly) new head and tail of the
+ // queue.
+ if (this->late_tail_->next ())
+ this->late_tail_->next ()->prev (this->late_head_->prev ());
+ else
+ this->tail_ = this->late_head_->prev ();
+
+ if (this->late_head_->prev ())
+ this->late_head_->prev ()->next (this->late_tail_->next ());
+ else
+ this->head_ = this->late_tail_->next ();
+
+ // put late messages behind pending messages (if any) being returned
+ this->late_head_->prev (list_tail);
+ if (list_tail)
+ list_tail->next (this->late_head_);
+ else
+ list_head = this->late_head_;
+
+ list_tail = this->late_tail_;
+
+ this->late_tail_->next (0);
+ this->late_head_ = 0;
+ this->late_tail_ = 0;
+ }
+
+ if (ACE_BIT_ENABLED (status_flags,
+ (u_int) ACE_Dynamic_Message_Strategy::BEYOND_LATE)
+ && this->beyond_late_head_
+ && this->beyond_late_tail_)
+ {
+ // Patch up pointers for the new tail of the queue
+ if (this->beyond_late_tail_->next ())
+ {
+ this->head_ = this->beyond_late_tail_->next ();
+ this->beyond_late_tail_->next ()->prev (0);
+ }
+ else
+ {
+ // the list has become empty
+ this->head_ = 0;
+ this->tail_ = 0;
+ }
+
+ // Put beyond late messages at the end of the list being
+ // returned.
+ if (list_tail)
+ {
+ this->beyond_late_head_->prev (list_tail);
+ list_tail->next (this->beyond_late_head_);
+ }
+ else
+ list_head = this->beyond_late_head_;
+
+ list_tail = this->beyond_late_tail_;
+
+ this->beyond_late_tail_->next (0);
+ this->beyond_late_head_ = 0;
+ this->beyond_late_tail_ = 0;
+ }
+
+ // Decrement message and size counts for removed messages.
+ ACE_Message_Block *temp1;
+
+ for (temp1 = list_head;
+ temp1 != 0;
+ temp1 = temp1->next ())
+ {
+ --this->cur_count_;
+
+ size_t mb_bytes = 0;
+ size_t mb_length = 0;
+ temp1->total_size_and_length (mb_bytes,
+ mb_length);
+ // Subtract off all of the bytes associated with this message.
+ this->cur_bytes_ -= mb_bytes;
+ this->cur_length_ -= mb_length;
+ }
+
+ return result;
+}
+
+// Detach all messages with status given in the passed flags from the
+// queue and return them by setting passed head and tail pointers to
+// the linked list they comprise. This method is intended primarily
+// as a means of periodically harvesting messages that have missed
+// their deadlines, but is available in its most general form. All
+// messages are returned in priority order, from head to tail, as of
+// the time this method was called.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::dequeue_head");
+
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->state_ == ACE_Message_Queue_Base::DEACTIVATED)
+ {
+ errno = ESHUTDOWN;
+ return -1;
+ }
+
+ int result;
+
+ // get the current time
+ ACE_Time_Value current_time = ACE_OS::gettimeofday ();
+
+ // refresh priority status boundaries in the queue
+ result = this->refresh_queue (current_time);
+ if (result < 0)
+ return result;
+
+ // *now* it's appropriate to wait for an enqueued item
+ result = this->wait_not_empty_cond (ace_mon, timeout);
+ if (result == -1)
+ return result;
+
+ // call the internal dequeue method, which selects an item from the
+ // highest priority status portion of the queue that has messages
+ // enqueued.
+ result = this->dequeue_head_i (first_item);
+
+ return result;
+}
+
+// Dequeue and return the <ACE_Message_Block *> at the (logical) head
+// of the queue.
+
+template <ACE_SYNCH_DECL> void
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Message_Queue<ACE_SYNCH_USE> (base class): \n")));
+ this->ACE_Message_Queue<ACE_SYNCH_USE>::dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("pending_head_ = %u\n")
+ ACE_TEXT ("pending_tail_ = %u\n")
+ ACE_TEXT ("late_head_ = %u\n")
+ ACE_TEXT ("late_tail_ = %u\n")
+ ACE_TEXT ("beyond_late_head_ = %u\n")
+ ACE_TEXT ("beyond_late_tail_ = %u\n"),
+ this->pending_head_,
+ this->pending_tail_,
+ this->late_head_,
+ this->late_tail_,
+ this->beyond_late_head_,
+ this->beyond_late_tail_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("message_strategy_ : \n")));
+ message_strategy_.dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+ // dump the state of the queue
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::enqueue_i (ACE_Message_Block *new_item)
+{
+ ACE_TRACE ("ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::enqueue_i");
+
+ if (new_item == 0)
+ return -1;
+
+ int result = 0;
+
+ // Get the current time.
+ ACE_Time_Value current_time = ACE_OS::gettimeofday ();
+
+ // Refresh priority status boundaries in the queue.
+
+ result = this->refresh_queue (current_time);
+ if (result < 0)
+ return result;
+
+ // Where we enqueue depends on the message's priority status.
+ switch (message_strategy_.priority_status (*new_item,
+ current_time))
+ {
+ case ACE_Dynamic_Message_Strategy::PENDING:
+ if (this->pending_tail_ == 0)
+ {
+ // Check for simple case of an empty pending queue, where
+ // all we need to do is insert <new_item> into the tail of
+ // the queue.
+ pending_head_ = new_item;
+ pending_tail_ = pending_head_;
+ return this->enqueue_tail_i (new_item);
+ }
+ else
+ {
+ // Enqueue the new message in priority order in the pending
+ // sublist
+ result = sublist_enqueue_i (new_item,
+ current_time,
+ this->pending_head_,
+ this->pending_tail_,
+ ACE_Dynamic_Message_Strategy::PENDING);
+ }
+ break;
+
+ case ACE_Dynamic_Message_Strategy::LATE:
+ if (this->late_tail_ == 0)
+ {
+ late_head_ = new_item;
+ late_tail_ = late_head_;
+
+ if (this->pending_head_ == 0)
+ // Check for simple case of an empty pending queue,
+ // where all we need to do is insert <new_item> into the
+ // tail of the queue.
+ return this->enqueue_tail_i (new_item);
+ else if (this->beyond_late_tail_ == 0)
+ // Check for simple case of an empty beyond late queue, where all
+ // we need to do is insert <new_item> into the head of the queue.
+ return this->enqueue_head_i (new_item);
+ else
+ {
+ // Otherwise, we can just splice the new message in
+ // between the pending and beyond late portions of the
+ // queue.
+ this->beyond_late_tail_->next (new_item);
+ new_item->prev (this->beyond_late_tail_);
+ this->pending_head_->prev (new_item);
+ new_item->next (this->pending_head_);
+ }
+ }
+ else
+ {
+ // Enqueue the new message in priority order in the late
+ // sublist
+ result = sublist_enqueue_i (new_item,
+ current_time,
+ this->late_head_,
+ this->late_tail_,
+ ACE_Dynamic_Message_Strategy::LATE);
+ }
+ break;
+
+ case ACE_Dynamic_Message_Strategy::BEYOND_LATE:
+ if (this->beyond_late_tail_ == 0)
+ {
+ // Check for simple case of an empty beyond late queue,
+ // where all we need to do is insert <new_item> into the
+ // head of the queue.
+ beyond_late_head_ = new_item;
+ beyond_late_tail_ = beyond_late_head_;
+ return this->enqueue_head_i (new_item);
+ }
+ else
+ {
+ // all beyond late messages have the same (zero) priority,
+ // so just put the new one at the end of the beyond late
+ // messages
+ if (this->beyond_late_tail_->next ())
+ this->beyond_late_tail_->next ()->prev (new_item);
+ else
+ this->tail_ = new_item;
+
+ new_item->next (this->beyond_late_tail_->next ());
+ this->beyond_late_tail_->next (new_item);
+ new_item->prev (this->beyond_late_tail_);
+ this->beyond_late_tail_ = new_item;
+ }
+
+ break;
+
+ // should never get here, but just in case...
+ default:
+ result = -1;
+ break;
+ }
+
+ if (result < 0)
+ return result;
+
+ size_t mb_bytes = 0;
+ size_t mb_length = 0;
+ new_item->total_size_and_length (mb_bytes,
+ mb_length);
+ this->cur_bytes_ += mb_bytes;
+ this->cur_length_ += mb_length;
+ ++this->cur_count_;
+
+ if (this->signal_dequeue_waiters () == -1)
+ return -1;
+ else
+ return this->cur_count_;
+}
+
+// Enqueue an <ACE_Message_Block *> in accordance with its priority.
+// priority may be *dynamic* or *static* or a combination or *both* It
+// calls the priority evaluation function passed into the Dynamic
+// Message Queue constructor to update the priorities of all enqueued
+// messages.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::sublist_enqueue_i (ACE_Message_Block *new_item,
+ const ACE_Time_Value &current_time,
+ ACE_Message_Block *&sublist_head,
+ ACE_Message_Block *&sublist_tail,
+ ACE_Dynamic_Message_Strategy::Priority_Status status)
+{
+ int result = 0;
+ ACE_Message_Block *current_item = 0;
+
+ // Find message after which to enqueue new item, based on message
+ // priority and priority status.
+ for (current_item = sublist_tail;
+ current_item;
+ current_item = current_item->prev ())
+ {
+ if (message_strategy_.priority_status (*current_item, current_time) == status)
+ {
+ if (current_item->msg_priority () >= new_item->msg_priority ())
+ break;
+ }
+ else
+ {
+ sublist_head = new_item;
+ break;
+ }
+ }
+
+ if (current_item == 0)
+ {
+ // If the new message has highest priority of any, put it at the
+ // head of the list (and sublist).
+ new_item->prev (0);
+ new_item->next (this->head_);
+ if (this->head_ != 0)
+ this->head_->prev (new_item);
+ else
+ {
+ this->tail_ = new_item;
+ sublist_tail = new_item;
+ }
+ this->head_ = new_item;
+ sublist_head = new_item;
+ }
+ else
+ {
+ // insert the new item into the list
+ new_item->next (current_item->next ());
+ new_item->prev (current_item);
+
+ if (current_item->next ())
+ current_item->next ()->prev (new_item);
+ else
+ this->tail_ = new_item;
+
+ current_item->next (new_item);
+
+ // If the new item has lowest priority of any in the sublist,
+ // move the tail pointer of the sublist back to the new item
+ if (current_item == sublist_tail)
+ sublist_tail = new_item;
+ }
+
+ return result;
+}
+
+// Enqueue a message in priority order within a given priority status
+// sublist.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::dequeue_head_i (ACE_Message_Block *&first_item)
+{
+ ACE_TRACE ("ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::dequeue_head_i");
+
+ int result = 0;
+ int last_in_subqueue = 0;
+
+ // first, try to dequeue from the head of the pending list
+ if (this->pending_head_)
+ {
+ first_item = this->pending_head_;
+
+ if (0 == this->pending_head_->prev ())
+ this->head_ = this->pending_head_->next ();
+ else
+ this->pending_head_->prev ()->next (this->pending_head_->next ());
+
+ if (0 == this->pending_head_->next ())
+ {
+ this->tail_ = this->pending_head_->prev ();
+ this->pending_head_ = 0;
+ this->pending_tail_ = 0;
+ }
+ else
+ {
+ this->pending_head_->next ()->prev (this->pending_head_->prev ());
+ this->pending_head_ = this->pending_head_->next ();
+ }
+
+ first_item->prev (0);
+ first_item->next (0);
+ }
+
+ // Second, try to dequeue from the head of the late list
+ else if (this->late_head_)
+ {
+ last_in_subqueue = this->late_head_ == this->late_tail_ ? 1 : 0;
+
+ first_item = this->late_head_;
+
+ if (0 == this->late_head_->prev ())
+ this->head_ = this->late_head_->next ();
+ else
+ this->late_head_->prev ()->next (this->late_head_->next ());
+
+ if (0 == this->late_head_->next ())
+ this->tail_ = this->late_head_->prev ();
+ else
+ {
+ this->late_head_->next ()->prev (this->late_head_->prev ());
+ this->late_head_ = this->late_head_->next ();
+ }
+
+ if (last_in_subqueue)
+ {
+ this->late_head_ = 0;
+ this->late_tail_ = 0;
+ }
+
+ first_item->prev (0);
+ first_item->next (0);
+ }
+ // finally, try to dequeue from the head of the beyond late list
+ else if (this->beyond_late_head_)
+ {
+ last_in_subqueue =
+ (this->beyond_late_head_ == this->beyond_late_tail_) ? 1 : 0;
+
+ first_item = this->beyond_late_head_;
+ this->head_ = this->beyond_late_head_->next ();
+
+ if (0 == this->beyond_late_head_->next ())
+ this->tail_ = this->beyond_late_head_->prev ();
+ else
+ {
+ this->beyond_late_head_->next ()->prev (this->beyond_late_head_->prev ());
+ this->beyond_late_head_ = this->beyond_late_head_->next ();
+ }
+
+ if (last_in_subqueue)
+ {
+ this->beyond_late_head_ = 0;
+ this->beyond_late_tail_ = 0;
+ }
+
+ first_item->prev (0);
+ first_item->next (0);
+ }
+ else
+ {
+ // nothing to dequeue: set the pointer to zero and return an error code
+ first_item = 0;
+ result = -1;
+ }
+
+ if (result < 0)
+ return result;
+
+ size_t mb_bytes = 0;
+ size_t mb_length = 0;
+ first_item->total_size_and_length (mb_bytes,
+ mb_length);
+ // Subtract off all of the bytes associated with this message.
+ this->cur_bytes_ -= mb_bytes;
+ this->cur_length_ -= mb_length;
+ --this->cur_count_;
+
+ // Only signal enqueueing threads if we've fallen below the low
+ // water mark.
+ if (this->cur_bytes_ <= this->low_water_mark_
+ && this->signal_enqueue_waiters () == -1)
+ return -1;
+ else
+ return this->cur_count_;
+}
+
+// Dequeue and return the <ACE_Message_Block *> at the head of the
+// logical queue. Attempts first to dequeue from the pending portion
+// of the queue, or if that is empty from the late portion, or if that
+// is empty from the beyond late portion, or if that is empty just
+// sets the passed pointer to zero and returns -1.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::refresh_queue (const ACE_Time_Value &current_time)
+{
+ int result;
+
+ result = refresh_pending_queue (current_time);
+
+ if (result != -1)
+ result = refresh_late_queue (current_time);
+
+ return result;
+}
+
+// Refresh the queue using the strategy specific priority status
+// function.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::refresh_pending_queue (const ACE_Time_Value &current_time)
+{
+ ACE_Dynamic_Message_Strategy::Priority_Status current_status;
+
+ // refresh priority status boundaries in the queue
+ if (this->pending_head_)
+ {
+ current_status = message_strategy_.priority_status (*this->pending_head_,
+ current_time);
+ switch (current_status)
+ {
+ case ACE_Dynamic_Message_Strategy::BEYOND_LATE:
+ // Make sure the head of the beyond late queue is set (there
+ // may not have been any beyond late messages previously)
+ this->beyond_late_head_ = this->head_;
+
+ // Zero out the late queue pointers, and set them only if
+ // there turn out to be late messages in the pending sublist
+ this->late_head_ = 0;
+ this->late_tail_ = 0;
+
+ // Advance through the beyond late messages in the pending queue
+ do
+ {
+ this->pending_head_ = this->pending_head_->next ();
+
+ if (this->pending_head_)
+ current_status = message_strategy_.priority_status (*this->pending_head_,
+ current_time);
+ else
+ break; // do while
+
+ }
+ while (current_status == ACE_Dynamic_Message_Strategy::BEYOND_LATE);
+
+ if (this->pending_head_)
+ {
+ // point tail of beyond late sublist to previous item
+ this->beyond_late_tail_ = this->pending_head_->prev ();
+
+ if (current_status == ACE_Dynamic_Message_Strategy::PENDING)
+ // there are no late messages left in the queue
+ break; // switch
+ else if (current_status != ACE_Dynamic_Message_Strategy::LATE)
+ {
+ // if we got here, something is *seriously* wrong with the queue
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Unexpected message priority status [%d] (expected LATE)"),
+ (int) current_status),
+ -1);
+ }
+ /* FALLTHRU */
+ }
+ else
+ {
+ // There are no pending or late messages left in the
+ // queue.
+ this->beyond_late_tail_ = this->tail_;
+ this->pending_head_ = 0;
+ this->pending_tail_ = 0;
+ break; // switch
+ }
+
+ case ACE_Dynamic_Message_Strategy::LATE:
+ // Make sure the head of the late queue is set (there may
+ // not have been any late messages previously, or they may
+ // have all become beyond late).
+ if (this->late_head_ == 0)
+ this->late_head_ = this->pending_head_;
+
+ // advance through the beyond late messages in the pending queue
+ do
+ {
+ this->pending_head_ = this->pending_head_->next ();
+
+ if (this->pending_head_)
+ current_status = message_strategy_.priority_status (*this->pending_head_,
+ current_time);
+ else
+ break; // do while
+
+ }
+ while (current_status == ACE_Dynamic_Message_Strategy::LATE);
+
+ if (this->pending_head_)
+ {
+ if (current_status != ACE_Dynamic_Message_Strategy::PENDING)
+ // if we got here, something is *seriously* wrong with the queue
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("Unexpected message priority status [%d] (expected PENDING)"),
+ (int) current_status),
+ -1);
+
+ // Point tail of late sublist to previous item
+ this->late_tail_ = this->pending_head_->prev ();
+ }
+ else
+ {
+ // there are no pending messages left in the queue
+ this->late_tail_ = this->tail_;
+ this->pending_head_ = 0;
+ this->pending_tail_ = 0;
+ }
+
+ break; // switch
+ case ACE_Dynamic_Message_Strategy::PENDING:
+ // do nothing - the pending queue is unchanged
+ break; // switch
+ default:
+ // if we got here, something is *seriously* wrong with the queue
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("Unknown message priority status [%d]"),
+ (int) current_status),
+ -1);
+ }
+ }
+ return 0;
+}
+
+// Refresh the pending queue using the strategy specific priority
+// status function.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::refresh_late_queue (const ACE_Time_Value &current_time)
+{
+ ACE_Dynamic_Message_Strategy::Priority_Status current_status;
+
+ if (this->late_head_)
+ {
+ current_status = message_strategy_.priority_status (*this->late_head_,
+ current_time);
+ switch (current_status)
+ {
+ case ACE_Dynamic_Message_Strategy::BEYOND_LATE:
+
+ // make sure the head of the beyond late queue is set
+ // (there may not have been any beyond late messages previously)
+ this->beyond_late_head_ = this->head_;
+
+ // advance through the beyond late messages in the late queue
+ do
+ {
+ this->late_head_ = this->late_head_->next ();
+
+ if (this->late_head_)
+ current_status = message_strategy_.priority_status (*this->late_head_,
+ current_time);
+ else
+ break; // do while
+
+ }
+ while (current_status == ACE_Dynamic_Message_Strategy::BEYOND_LATE);
+
+ if (this->late_head_)
+ {
+ // point tail of beyond late sublist to previous item
+ this->beyond_late_tail_ = this->late_head_->prev ();
+
+ if (current_status == ACE_Dynamic_Message_Strategy::PENDING)
+ {
+ // there are no late messages left in the queue
+ this->late_head_ = 0;
+ this->late_tail_ = 0;
+ }
+ else if (current_status != ACE_Dynamic_Message_Strategy::LATE)
+ // if we got here, something is *seriously* wrong with the queue
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Unexpected message priority status [%d] (expected LATE)"),
+ (int) current_status),
+ -1);
+ }
+ else
+ {
+ // there are no late messages left in the queue
+ this->beyond_late_tail_ = this->tail_;
+ this->late_head_ = 0;
+ this->late_tail_ = 0;
+ }
+
+ break; // switch
+
+ case ACE_Dynamic_Message_Strategy::LATE:
+ // do nothing - the late queue is unchanged
+ break; // switch
+
+ case ACE_Dynamic_Message_Strategy::PENDING:
+ // if we got here, something is *seriously* wrong with the queue
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Unexpected message priority status ")
+ ACE_TEXT ("[%d] (expected LATE or BEYOND_LATE)"),
+ (int) current_status),
+ -1);
+ default:
+ // if we got here, something is *seriously* wrong with the queue
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Unknown message priority status [%d]"),
+ (int) current_status),
+ -1);
+ }
+ }
+
+ return 0;
+}
+
+// Refresh the late queue using the strategy specific priority status
+// function.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::peek_dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout)
+{
+ return ACE_Message_Queue<ACE_SYNCH_USE>::peek_dequeue_head (first_item,
+ timeout);
+}
+
+// Private method to hide public base class method: just calls base
+// class method.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::enqueue_tail (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::enqueue_tail");
+ return this->enqueue_prio (new_item, timeout);
+}
+
+// Just call priority enqueue method: tail enqueue semantics for
+// dynamic message queues are unstable: the message may or may not be
+// where it was placed after the queue is refreshed prior to the next
+// enqueue or dequeue operation.
+
+template <ACE_SYNCH_DECL> int
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::enqueue_head (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Dynamic_Message_Queue<ACE_SYNCH_USE>::enqueue_head");
+ return this->enqueue_prio (new_item, timeout);
+}
+
+// Just call priority enqueue method: head enqueue semantics for
+// dynamic message queues are unstable: the message may or may not be
+// where it was placed after the queue is refreshed prior to the next
+// enqueue or dequeue operation.
+
+template <ACE_SYNCH_DECL>
+ACE_Message_Queue<ACE_SYNCH_USE> *
+ACE_Message_Queue_Factory<ACE_SYNCH_USE>::create_static_message_queue (size_t hwm,
+ size_t lwm,
+ ACE_Notification_Strategy *ns)
+{
+ ACE_Message_Queue<ACE_SYNCH_USE> *tmp = 0;
+
+ ACE_NEW_RETURN (tmp,
+ ACE_Message_Queue<ACE_SYNCH_USE> (hwm, lwm, ns),
+ 0);
+ return tmp;
+}
+
+// Factory method for a statically prioritized ACE_Message_Queue.
+
+template <ACE_SYNCH_DECL>
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> *
+ACE_Message_Queue_Factory<ACE_SYNCH_USE>::create_deadline_message_queue (size_t hwm,
+ size_t lwm,
+ ACE_Notification_Strategy *ns,
+ u_long static_bit_field_mask,
+ u_long static_bit_field_shift,
+ u_long dynamic_priority_max,
+ u_long dynamic_priority_offset)
+{
+ ACE_Deadline_Message_Strategy *adms = 0;
+
+ ACE_NEW_RETURN (adms,
+ ACE_Deadline_Message_Strategy (static_bit_field_mask,
+ static_bit_field_shift,
+ dynamic_priority_max,
+ dynamic_priority_offset),
+ 0);
+
+ ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> *tmp = 0;
+ ACE_NEW_RETURN (tmp,
+ ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> (*adms, hwm, lwm, ns),
+ 0);
+ return tmp;
+}
+
+// Factory method for a dynamically prioritized (by time to deadline)
+// ACE_Dynamic_Message_Queue.
+
+template <ACE_SYNCH_DECL>
+ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> *
+ACE_Message_Queue_Factory<ACE_SYNCH_USE>::create_laxity_message_queue (size_t hwm,
+ size_t lwm,
+ ACE_Notification_Strategy *ns,
+ u_long static_bit_field_mask,
+ u_long static_bit_field_shift,
+ u_long dynamic_priority_max,
+ u_long dynamic_priority_offset)
+{
+ ACE_Laxity_Message_Strategy *alms = 0;
+
+ ACE_NEW_RETURN (alms,
+ ACE_Laxity_Message_Strategy (static_bit_field_mask,
+ static_bit_field_shift,
+ dynamic_priority_max,
+ dynamic_priority_offset),
+ 0);
+
+ ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> *tmp = 0;
+ ACE_NEW_RETURN (tmp,
+ ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> (*alms, hwm, lwm, ns),
+ 0);
+ return tmp;
+}
+
+// Factory method for a dynamically prioritized (by laxity)
+// <ACE_Dynamic_Message_Queue>.
+
+#if defined (ACE_VXWORKS)
+
+template <ACE_SYNCH_DECL>
+ACE_Message_Queue_Vx *
+ACE_Message_Queue_Factory<ACE_SYNCH_USE>::create_Vx_message_queue (size_t max_messages,
+ size_t max_message_length,
+ ACE_Notification_Strategy *ns)
+{
+ ACE_Message_Queue_Vx *tmp = 0;
+
+ ACE_NEW_RETURN (tmp,
+ ACE_Message_Queue_Vx (max_messages, max_message_length, ns),
+ 0);
+ return tmp;
+}
+ // factory method for a wrapped VxWorks message queue
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+
+template <ACE_SYNCH_DECL>
+ACE_Message_Queue_NT *
+ACE_Message_Queue_Factory<ACE_SYNCH_USE>::create_NT_message_queue (size_t max_threads)
+{
+ ACE_Message_Queue_NT *tmp = 0;
+
+ ACE_NEW_RETURN (tmp,
+ ACE_Message_Queue_NT (max_threads);
+ 0);
+ return tmp;
+}
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+#endif /* defined (ACE_VXWORKS) */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_MESSAGE_QUEUE_T_CPP */
diff --git a/ACE/ace/Message_Queue_T.h b/ACE/ace/Message_Queue_T.h
new file mode 100644
index 00000000000..62869da889e
--- /dev/null
+++ b/ACE/ace/Message_Queue_T.h
@@ -0,0 +1,1476 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Message_Queue_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MESSAGE_QUEUE_T_H
+#define ACE_MESSAGE_QUEUE_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Message_Queue.h"
+#include "ace/Dynamic_Message_Strategy.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Guard_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_VXWORKS)
+class ACE_Message_Queue_Vx;
+#endif /* defined (ACE_VXWORKS) */
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+class ACE_Message_Queue_NT;
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO*/
+
+/**
+ * @class ACE_Message_Queue
+ *
+ * @brief A message queueing facility with parameterized synchronization
+ * capability. ACE_Message_Queue is modeled after the queueing facilities
+ * in System V STREAMs.
+ *
+ * ACE_Message_Queue is the primary queueing facility for
+ * messages in the ACE framework. It's one template argument parameterizes
+ * the queue's synchronization. The argument specifies a synchronization
+ * strategy. The two main strategies available for ACE_SYNCH_DECL are:
+ * -# ACE_MT_SYNCH: all operations are thread-safe
+ * -# ACE_NULL_SYNCH: no synchronization and no locking overhead
+ *
+ * All data passing through ACE_Message_Queue is in the form of
+ * ACE_Message_Block objects. @sa ACE_Message_Block.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Message_Queue : public ACE_Message_Queue_Base
+{
+public:
+ friend class ACE_Message_Queue_Iterator<ACE_SYNCH_USE>;
+ friend class ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>;
+
+ // = Traits
+ typedef ACE_Message_Queue_Iterator<ACE_SYNCH_USE>
+ ITERATOR;
+ typedef ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>
+ REVERSE_ITERATOR;
+
+ /**
+ * @name Initialization methods
+ */
+ //@{
+ /**
+ * Initialize an ACE_Message_Queue.
+ *
+ * @param hwm High water mark. Determines how many bytes can be stored in a
+ * queue before it's considered full. Supplier threads must block
+ * until the queue is no longer full.
+ * @param lwm Low water mark. Determines how many bytes must be in the queue
+ * before supplier threads are allowed to enqueue additional
+ * data. By default, the @a hwm equals @a lwm, which means
+ * that suppliers will be able to enqueue new messages as soon as
+ * a consumer removes any message from the queue. Making the low
+ * water mark smaller than the high water mark forces consumers to
+ * drain more messages from the queue before suppliers can enqueue
+ * new messages, which can minimize the "silly window syndrome."
+ * @param ns Notification strategy. Pointer to an object conforming to the
+ * ACE_Notification_Strategy interface. If set, the object's
+ * notify(void) method will be called each time data is added to
+ * this ACE_Message_Queue. @see ACE_Reactor_Notification_Strategy.
+ */
+ ACE_Message_Queue (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy *ns = 0);
+ virtual int open (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy *ns = 0);
+ //@}
+
+ /// Releases all resources from the message queue and marks it deactivated.
+ /// @sa flush().
+ ///
+ /// @retval The number of messages released from the queue; -1 on error.
+ virtual int close (void);
+
+ /// Releases all resources from the message queue and marks it deactivated.
+ virtual ~ACE_Message_Queue (void);
+
+ /**
+ * Releases all resources from the message queue but does not mark it
+ * deactivated. This method holds the queue lock during this operation.
+ * @sa close().
+ *
+ * @return The number of messages flushed; -1 on error.
+ */
+ virtual int flush (void);
+
+ /**
+ * Release all resources from the message queue but do not mark it
+ * as deactivated.
+ *
+ * @pre The caller must be holding the queue lock before calling this
+ * method.
+ *
+ * @return The number of messages flushed.
+ */
+ virtual int flush_i (void);
+
+ /** @name Enqueue and dequeue methods
+ *
+ * The enqueue and dequeue methods accept a timeout value passed as
+ * an ACE_Time_Value *. In all cases, if the timeout pointer is 0,
+ * the caller will block until action is possible. If the timeout pointer
+ * is non-zero, the call will wait (if needed, subject to water mark
+ * settings) until the absolute time specified in the referenced
+ * ACE_Time_Value object is reached. If the time is reached before the
+ * desired action is possible, the method will return -1 with errno set
+ * to @c EWOULDBLOCK. Regardless of the timeout setting, however,
+ * these methods will also fail and return -1 when the queue is closed,
+ * deactivated, pulsed, or when a signal occurs.
+ *
+ * See C++NPv2 Section 6.2 and APG Section 12.3 for a fuller treatment of
+ * ACE_Message_Queue, enqueueing, dequeueing, and how these operations are
+ * affected by queue state transitions.
+ */
+ //@{
+ /**
+ * Retrieve a pointer to the first ACE_Message_Block in the queue
+ * without removing it.
+ *
+ * @note Because the block whose pointer is returned is still on the queue,
+ * another thread may dequeue the referenced block at any time,
+ * including before the calling thread examines the peeked-at block.
+ * Be very careful with this method in multithreaded queueing
+ * situations.
+ *
+ * @param first_item Reference to an ACE_Message_Block * that will
+ * point to the first block on the queue. The block
+ * remains on the queue until this or another thread
+ * dequeues it.
+ * @param timeout The absolute time the caller will wait until
+ * for a block to be queued.
+ *
+ * @retval >0 The number of ACE_Message_Blocks on the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int peek_dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an ACE_Message_Block into the queue in accordance with
+ * the ACE_Message_Block's priority (0 is lowest priority). FIFO
+ * order is maintained when messages of the same priority are
+ * inserted consecutively.
+ *
+ * @param new_item Pointer to an ACE_Message_Block that will be
+ * added to the queue. The block's @c msg_priority()
+ * method will be called to obtain the queueing priority.
+ * @param timeout The absolute time the caller will wait until
+ * for the block to be queued.
+ *
+ * @retval >0 The number of ACE_Message_Blocks on the queue after adding
+ * the specified block.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_prio (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an ACE_Message_Block into the queue in accordance with the
+ * block's deadline time. FIFO order is maintained when messages of
+ * the same deadline time are inserted consecutively.
+ *
+ * @param new_item Pointer to an ACE_Message_Block that will be
+ * added to the queue. The block's @c msg_deadline_time()
+ * method will be called to obtain the relative queueing
+ * position.
+ * @param timeout The absolute time the caller will wait until
+ * for the block to be queued.
+ *
+ * @retval >0 The number of ACE_Message_Blocks on the queue after adding
+ * the specified block.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_deadline (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * @deprecated This is an alias for enqueue_prio(). It's only here for
+ * backwards compatibility and will go away in a subsequent release.
+ * Please use enqueue_prio() instead.
+ */
+ virtual int enqueue (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue one or more ACE_Message_Block objects at the tail of the queue.
+ * If the @a new_item @c next() pointer is non-zero, it is assumed to be the
+ * start of a series of ACE_Message_Block objects connected via their
+ * @c next() pointers. The series of blocks will be added to the queue in
+ * the same order they are passed in as.
+ *
+ * @param new_item Pointer to an ACE_Message_Block that will be
+ * added to the queue. If the block's @c next() pointer
+ * is non-zero, all blocks chained from the @c next()
+ * pointer are enqueued as well.
+ * @param timeout The absolute time the caller will wait until
+ * for the block to be queued.
+ *
+ * @retval >0 The number of ACE_Message_Blocks on the queue after adding
+ * the specified block(s).
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_tail (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue one or more ACE_Message_Block objects at the head of the queue.
+ * If the @a new_item @c next() pointer is non-zero, it is assumed to be the
+ * start of a series of ACE_Message_Block objects connected via their
+ * @c next() pointers. The series of blocks will be added to the queue in
+ * the same order they are passed in as.
+ *
+ * @param new_item Pointer to an ACE_Message_Block that will be
+ * added to the queue. If the block's @c next() pointer
+ * is non-zero, all blocks chained from the @c next()
+ * pointer are enqueued as well.
+ * @param timeout The absolute time the caller will wait until
+ * for the block to be queued.
+ *
+ * @retval >0 The number of ACE_Message_Blocks on the queue after adding
+ * the specified block(s).
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_head (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /// This method is an alias for the dequeue_head() method.
+ virtual int dequeue (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue the ACE_Message_Block at the head of the queue and return
+ * a pointer to the dequeued block.
+ *
+ * @param first_item Reference to an ACE_Message_Block * that will
+ * be set to the address of the dequeued block.
+ * @param timeout The absolute time the caller will wait until
+ * for a block to be dequeued.
+ *
+ * @retval >=0 The number of ACE_Message_Blocks remaining in the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue the ACE_Message_Block that has the lowest priority (preserves
+ * FIFO order for messages with the same priority) and return a pointer
+ * to the dequeued block.
+ *
+ * @param first_item Reference to an ACE_Message_Block * that will
+ * be set to the address of the dequeued block.
+ * @param timeout The absolute time the caller will wait until
+ * for a block to be dequeued.
+ *
+ * @retval >=0 The number of ACE_Message_Blocks remaining in the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int dequeue_prio (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue the ACE_Message_Block at the tail of the queue and return
+ * a pointer to the dequeued block.
+ *
+ * @param dequeued Reference to an ACE_Message_Block * that will
+ * be set to the address of the dequeued block.
+ * @param timeout The absolute time the caller will wait until
+ * for a block to be dequeued.
+ *
+ * @retval >=0 The number of ACE_Message_Blocks remaining in the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int dequeue_tail (ACE_Message_Block *&dequeued,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue the ACE_Message_Block with the earliest deadline time and return
+ * a pointer to the dequeued block.
+ *
+ * @param dequeued Reference to an ACE_Message_Block * that will
+ * be set to the address of the dequeued block.
+ * @param timeout The absolute time the caller will wait until
+ * for a block to be dequeued.
+ *
+ * @retval >=0 The number of ACE_Message_Blocks remaining in the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int dequeue_deadline (ACE_Message_Block *&dequeued,
+ ACE_Time_Value *timeout = 0);
+ //@}
+
+ /** @name Queue statistics methods
+ */
+ //@{
+
+ /// True if queue is full, else false.
+ virtual bool is_full (void);
+ /// True if queue is empty, else false.
+ virtual bool is_empty (void);
+
+ /**
+ * Number of total bytes on the queue, i.e., sum of the message
+ * block sizes.
+ */
+ virtual size_t message_bytes (void);
+
+ /**
+ * Number of total length on the queue, i.e., sum of the message
+ * block lengths.
+ */
+ virtual size_t message_length (void);
+
+ /**
+ * Number of total messages on the queue.
+ */
+ virtual size_t message_count (void);
+
+ // = Manual changes to these stats (used when queued message blocks
+ // change size or lengths).
+ /**
+ * New value of the number of total bytes on the queue, i.e., sum of
+ * the message block sizes.
+ */
+ virtual void message_bytes (size_t new_size);
+ /**
+ * New value of the number of total length on the queue, i.e., sum
+ * of the message block lengths.
+ */
+ virtual void message_length (size_t new_length);
+
+ //@}
+
+
+ /** @name Water mark (flow control) methods
+ */
+ //@{
+
+ /**
+ * Get high watermark.
+ */
+ virtual size_t high_water_mark (void);
+ /**
+ * Set the high watermark, which determines how many bytes can be
+ * stored in a queue before it's considered "full."
+ */
+ virtual void high_water_mark (size_t hwm);
+
+ /**
+ * Get low watermark.
+ */
+ virtual size_t low_water_mark (void);
+ /**
+ * Set the low watermark, which determines how many bytes must be in
+ * the queue before supplier threads are allowed to enqueue
+ * additional ACE_Message_Blocks.
+ */
+ virtual void low_water_mark (size_t lwm);
+ //@}
+
+ /** @name Activation and queue state methods
+ * See C++NPv2 Section 6.2 and APG Section 12.3 for a fuller treatment of
+ * queue states and transitions and how the transitions affect message
+ * enqueueing and dequeueing operations.
+ */
+ //@{
+
+ /**
+ * Deactivate the queue and wakeup all threads waiting on the queue
+ * so they can continue. No messages are removed from the queue,
+ * however. Any other operations called until the queue is
+ * activated again will immediately return -1 with @c errno ==
+ * ESHUTDOWN. Returns WAS_INACTIVE if queue was inactive before the
+ * call and WAS_ACTIVE if queue was active before the call.
+ */
+ virtual int deactivate (void);
+
+ /**
+ * Reactivate the queue so that threads can enqueue and dequeue
+ * messages again. Returns the state of the queue before the call.
+ */
+ virtual int activate (void);
+
+ /**
+ * Pulse the queue to wake up any waiting threads. Changes the
+ * queue state to PULSED; future enqueue/dequeue operations proceed
+ * as in ACTIVATED state.
+ *
+ * @return The queue's state before this call.
+ */
+ virtual int pulse (void);
+
+ /// Returns the current state of the queue, which can be one of
+ /// ACTIVATED, DEACTIVATED, or PULSED.
+ virtual int state (void);
+
+ /// Returns true if the state of the queue is <DEACTIVATED>,
+ /// but false if the queue's is <ACTIVATED> or <PULSED>.
+ virtual int deactivated (void);
+ //@}
+
+ /** @name Notification strategy methods
+ */
+ //@{
+
+ /**
+ * This hook is automatically invoked by <enqueue_head>,
+ * <enqueue_tail>, and <enqueue_prio> when a new item is inserted
+ * into the queue. Subclasses can override this method to perform
+ * specific notification strategies (e.g., signaling events for a
+ * <WFMO_Reactor>, notifying a <Reactor>, etc.). In a
+ * multi-threaded application with concurrent consumers, there is no
+ * guarantee that the queue will be still be non-empty by the time
+ * the notification occurs.
+ */
+ virtual int notify (void);
+
+ /// Get the notification strategy for the <Message_Queue>
+ virtual ACE_Notification_Strategy *notification_strategy (void);
+
+ /// Set the notification strategy for the <Message_Queue>
+ virtual void notification_strategy (ACE_Notification_Strategy *s);
+ //@}
+
+ /// Returns a reference to the lock used by the ACE_Message_Queue.
+ virtual ACE_SYNCH_MUTEX_T &lock (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Routines that actually do the enqueueing and dequeueing.
+
+ // These routines assume that locks are held by the corresponding
+ // public methods. Since they are virtual, you can change the
+ // queueing mechanism by subclassing from ACE_Message_Queue.
+
+ /// Enqueue an <ACE_Message_Block *> in accordance with its priority.
+ virtual int enqueue_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> in accordance with its deadline time.
+ virtual int enqueue_deadline_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> at the end of the queue.
+ virtual int enqueue_tail_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> at the head of the queue.
+ virtual int enqueue_head_i (ACE_Message_Block *new_item);
+
+ /// Dequeue and return the <ACE_Message_Block *> at the head of the
+ /// queue.
+ virtual int dequeue_head_i (ACE_Message_Block *&first_item);
+
+ /// Dequeue and return the <ACE_Message_Block *> with the lowest
+ /// priority.
+ virtual int dequeue_prio_i (ACE_Message_Block *&dequeued);
+
+ /// Dequeue and return the <ACE_Message_Block *> at the tail of the
+ /// queue.
+ virtual int dequeue_tail_i (ACE_Message_Block *&first_item);
+
+ /// Dequeue and return the <ACE_Message_Block *> with the lowest
+ /// deadline time.
+ virtual int dequeue_deadline_i (ACE_Message_Block *&first_item);
+
+ // = Check the boundary conditions (assumes locks are held).
+
+ /// True if queue is full, else false.
+ virtual bool is_full_i (void);
+
+ /// True if queue is empty, else false.
+ virtual bool is_empty_i (void);
+
+ // = Implementation of the public <activate> and <deactivate> methods.
+
+ // These methods assume locks are held.
+
+ /**
+ * Notifies all waiting threads that the queue has been deactivated
+ * so they can wakeup and continue other processing.
+ * No messages are removed from the queue.
+ *
+ * @param pulse If 0, the queue's state is changed to DEACTIVATED
+ * and any other operations called until the queue is
+ * reactivated will immediately return -1 with
+ * errno == ESHUTDOWN.
+ * If not zero, only the waiting threads are notified and
+ * the queue's state changes to PULSED.
+ *
+ * @return The state of the queue before the call.
+ */
+ virtual int deactivate_i (int pulse = 0);
+
+ /// Activate the queue.
+ virtual int activate_i (void);
+
+ // = Helper methods to factor out common #ifdef code.
+
+ /// Wait for the queue to become non-full.
+ virtual int wait_not_full_cond (ACE_Guard<ACE_SYNCH_MUTEX_T> &mon,
+ ACE_Time_Value *timeout);
+
+ /// Wait for the queue to become non-empty.
+ virtual int wait_not_empty_cond (ACE_Guard<ACE_SYNCH_MUTEX_T> &mon,
+ ACE_Time_Value *timeout);
+
+ /// Inform any threads waiting to enqueue that they can procede.
+ virtual int signal_enqueue_waiters (void);
+
+ /// Inform any threads waiting to dequeue that they can procede.
+ virtual int signal_dequeue_waiters (void);
+
+ /// Pointer to head of ACE_Message_Block list.
+ ACE_Message_Block *head_;
+
+ /// Pointer to tail of ACE_Message_Block list.
+ ACE_Message_Block *tail_;
+
+ /// Lowest number before unblocking occurs.
+ size_t low_water_mark_;
+
+ /// Greatest number of bytes before blocking.
+ size_t high_water_mark_;
+
+ /// Current number of bytes in the queue.
+ size_t cur_bytes_;
+
+ /// Current length of messages in the queue.
+ size_t cur_length_;
+
+ /// Current number of messages in the queue.
+ size_t cur_count_;
+
+ /// The notification strategy used when a new message is enqueued.
+ ACE_Notification_Strategy *notification_strategy_;
+
+ // = Synchronization primitives for controlling concurrent access.
+ /// Protect queue from concurrent access.
+ ACE_SYNCH_MUTEX_T lock_;
+
+ /// Used to make threads sleep until the queue is no longer empty.
+ ACE_SYNCH_CONDITION_T not_empty_cond_;
+
+ /// Used to make threads sleep until the queue is no longer full.
+ ACE_SYNCH_CONDITION_T not_full_cond_;
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Message_Queue<ACE_SYNCH_USE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Message_Queue (const ACE_Message_Queue<ACE_SYNCH_USE> &))
+};
+
+// This typedef is used to get around a compiler bug in g++/vxworks.
+typedef ACE_Message_Queue<ACE_SYNCH> ACE_DEFAULT_MESSAGE_QUEUE_TYPE;
+
+
+/**
+ * @class ACE_Message_Queue_Iterator
+ *
+ * @brief Iterator for the ACE_Message_Queue.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Message_Queue_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Message_Queue_Iterator (ACE_Message_Queue <ACE_SYNCH_USE> &queue);
+
+ // = Iteration methods.
+ /// Pass back the @a entry that hasn't been seen in the queue.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Message_Block *&entry);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Move forward by one element in the queue. 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:
+ /// Message_Queue we are iterating over.
+ ACE_Message_Queue <ACE_SYNCH_USE> &queue_;
+
+ /// Keeps track of how far we've advanced...
+ ACE_Message_Block *curr_;
+};
+
+/**
+ * @class ACE_Message_Queue_Reverse_Iterator
+ *
+ * @brief Reverse Iterator for the ACE_Message_Queue.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Message_Queue_Reverse_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Message_Queue_Reverse_Iterator (ACE_Message_Queue <ACE_SYNCH_USE> &queue);
+
+ // = Iteration methods.
+ /// Pass back the @a entry that hasn't been seen in the queue.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Message_Block *&entry);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Move forward by one element in the queue. 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:
+ /// Message_Queue we are iterating over.
+ ACE_Message_Queue <ACE_SYNCH_USE> &queue_;
+
+ /// Keeps track of how far we've advanced...
+ ACE_Message_Block *curr_;
+};
+
+/**
+ * @class ACE_Dynamic_Message_Queue
+ *
+ * @brief A derived class which adapts the ACE_Message_Queue
+ * class in order to maintain dynamic priorities for enqueued
+ * <ACE_Message_Blocks> and manage the queue order according
+ * to these dynamic priorities.
+ *
+ * The messages in the queue are managed so as to preserve
+ * a logical ordering with minimal overhead per enqueue and
+ * dequeue operation. For this reason, the actual order of
+ * messages in the linked list of the queue may differ from
+ * their priority order. As time passes, a message may change
+ * from pending status to late status, and eventually to beyond
+ * late status. To minimize reordering overhead under this
+ * design force, three separate boundaries are maintained
+ * within the linked list of messages. Messages are dequeued
+ * preferentially from the head of the pending portion, then
+ * the head of the late portion, and finally from the head
+ * of the beyond late portion. In this way, only the boundaries
+ * need to be maintained (which can be done efficiently, as
+ * aging messages maintain the same linked list order as they
+ * progress from one status to the next), with no reordering
+ * of the messages themselves, while providing correct priority
+ * ordered dequeueing semantics.
+ * Head and tail enqueue methods inherited from ACE_Message_Queue
+ * are made private to prevent out-of-order messages from confusing
+ * management of the various portions of the queue. Messages in
+ * the pending portion of the queue whose priority becomes late
+ * (according to the specific dynamic strategy) advance into
+ * the late portion of the queue. Messages in the late portion
+ * of the queue whose priority becomes later than can be represented
+ * advance to the beyond_late portion of the queue. These behaviors
+ * support a limited schedule overrun, with pending messages prioritized
+ * ahead of late messages, and late messages ahead of beyond late
+ * messages. These behaviors can be modified in derived classes by
+ * providing alternative definitions for the appropriate virtual methods.
+ * When filled with messages, the queue's linked list should look like:
+ * H T
+ * | |
+ * B - B - B - B - L - L - L - P - P - P - P - P
+ * | | | | | |
+ * BH BT LH LT PH PT
+ * Where the symbols are as follows:
+ * H = Head of the entire list
+ * T = Tail of the entire list
+ * B = Beyond late message
+ * BH = Beyond late messages Head
+ * BT = Beyond late messages Tail
+ * L = Late message
+ * LH = Late messages Head
+ * LT = Late messages Tail
+ * P = Pending message
+ * PH = Pending messages Head
+ * PT = Pending messages Tail
+ * Caveat: the virtual methods enqueue_tail, enqueue_head,
+ * and peek_dequeue_head have semantics for the static
+ * message queues that cannot be guaranteed for dynamic
+ * message queues. The peek_dequeue_head method just
+ * calls the base class method, while the two enqueue
+ * methods call the priority enqueue method. The
+ * order of messages in the dynamic queue is a function
+ * of message deadlines and how long they are in the
+ * queues. You can manipulate these in some cases to
+ * ensure the correct semantics, but that is not a
+ * very stable or portable approach (discouraged).
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Dynamic_Message_Queue : public ACE_Message_Queue<ACE_SYNCH_USE>
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Dynamic_Message_Queue (ACE_Dynamic_Message_Strategy & message_strategy,
+ size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy * = 0);
+
+ /// Close down the message queue and release all resources.
+ virtual ~ACE_Dynamic_Message_Queue (void);
+
+ /**
+ * Detach all messages with status given in the passed flags from
+ * the queue and return them by setting passed head and tail pointers
+ * to the linked list they comprise. This method is intended primarily
+ * as a means of periodically harvesting messages that have missed
+ * their deadlines, but is available in its most general form. All
+ * messages are returned in priority order, from head to tail, as of
+ * the time this method was called.
+ */
+ virtual int remove_messages (ACE_Message_Block *&list_head,
+ ACE_Message_Block *&list_tail,
+ u_int status_flags);
+
+ /**
+ * Dequeue and return the <ACE_Message_Block *> at the head of the
+ * queue. Returns -1 on failure, else the number of items still on
+ * the queue.
+ */
+ virtual int dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /// Dump the state of the queue.
+ virtual void dump (void) const;
+
+ /**
+ * Just call priority enqueue method: tail enqueue semantics for dynamic
+ * message queues are unstable: the message may or may not be where
+ * it was placed after the queue is refreshed prior to the next
+ * enqueue or dequeue operation.
+ */
+ virtual int enqueue_tail (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Just call priority enqueue method: head enqueue semantics for dynamic
+ * message queues are unstable: the message may or may not be where
+ * it was placed after the queue is refreshed prior to the next
+ * enqueue or dequeue operation.
+ */
+ virtual int enqueue_head (ACE_Message_Block *new_item,
+ ACE_Time_Value *timeout = 0);
+
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ /**
+ * Enqueue an <ACE_Message_Block *> in accordance with its priority.
+ * priority may be *dynamic* or *static* or a combination or *both*
+ * It calls the priority evaluation function passed into the Dynamic
+ * Message Queue constructor to update the priorities of all
+ * enqueued messages.
+ */
+ virtual int enqueue_i (ACE_Message_Block *new_item);
+
+ /// Enqueue a message in priority order within a given priority status sublist
+ virtual int sublist_enqueue_i (ACE_Message_Block *new_item,
+ const ACE_Time_Value &current_time,
+ ACE_Message_Block *&sublist_head,
+ ACE_Message_Block *&sublist_tail,
+ ACE_Dynamic_Message_Strategy::Priority_Status status);
+
+ /**
+ * Dequeue and return the <ACE_Message_Block *> at the head of the
+ * logical queue. Attempts first to dequeue from the pending
+ * portion of the queue, or if that is empty from the late portion,
+ * or if that is empty from the beyond late portion, or if that is
+ * empty just sets the passed pointer to zero and returns -1.
+ */
+ virtual int dequeue_head_i (ACE_Message_Block *&first_item);
+
+ /// Refresh the queue using the strategy
+ /// specific priority status function.
+ virtual int refresh_queue (const ACE_Time_Value & current_time);
+
+ /// Refresh the pending queue using the strategy
+ /// specific priority status function.
+ virtual int refresh_pending_queue (const ACE_Time_Value & current_time);
+
+ /// Refresh the late queue using the strategy
+ /// specific priority status function.
+ virtual int refresh_late_queue (const ACE_Time_Value & current_time);
+
+ /// Pointer to head of the pending messages
+ ACE_Message_Block *pending_head_;
+
+ /// Pointer to tail of the pending messages
+ ACE_Message_Block *pending_tail_;
+
+ /// Pointer to head of the late messages
+ ACE_Message_Block *late_head_;
+
+ /// Pointer to tail of the late messages
+ ACE_Message_Block *late_tail_;
+
+ /// Pointer to head of the beyond late messages
+ ACE_Message_Block *beyond_late_head_;
+
+ /// Pointer to tail of the beyond late messages
+ ACE_Message_Block *beyond_late_tail_;
+
+ /// Pointer to a dynamic priority evaluation function.
+ ACE_Dynamic_Message_Strategy &message_strategy_;
+
+private:
+ // = Disallow public access to these operations.
+
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dynamic_Message_Queue (const ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> &))
+
+ // provide definitions for these (just call base class method),
+ // but make them private so they're not accessible outside the class
+
+ /// Private method to hide public base class method: just calls base class method
+ virtual int peek_dequeue_head (ACE_Message_Block *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+};
+
+/**
+ * @class ACE_Message_Queue_Factory
+ *
+ * @brief ACE_Message_Queue_Factory is a static factory class template which
+ * provides a separate factory method for each of the major kinds of
+ * priority based message dispatching: static, earliest deadline first
+ * (EDF), and minimum laxity first (MLF).
+ *
+ * The ACE_Dynamic_Message_Queue class assumes responsibility for
+ * releasing the resources of the strategy with which it was
+ * constructed: the user of a message queue constructed by
+ * any of these factory methods is only responsible for
+ * ensuring destruction of the message queue itself.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Message_Queue_Factory
+{
+public:
+ /// Factory method for a statically prioritized ACE_Message_Queue
+ static ACE_Message_Queue<ACE_SYNCH_USE> *
+ create_static_message_queue (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy * = 0);
+
+ /// Factory method for a dynamically prioritized (by time to deadline) ACE_Dynamic_Message_Queue
+ static ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> *
+ create_deadline_message_queue (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy * = 0,
+ u_long static_bit_field_mask = 0x3FFUL, // 2^(10) - 1
+ u_long static_bit_field_shift = 10, // 10 low order bits
+ u_long dynamic_priority_max = 0x3FFFFFUL, // 2^(22)-1
+ u_long dynamic_priority_offset = 0x200000UL); // 2^(22-1)
+
+ /// Factory method for a dynamically prioritized (by laxity) ACE_Dynamic_Message_Queue
+ static ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> *
+ create_laxity_message_queue (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy * = 0,
+ u_long static_bit_field_mask = 0x3FFUL, // 2^(10) - 1
+ u_long static_bit_field_shift = 10, // 10 low order bits
+ u_long dynamic_priority_max = 0x3FFFFFUL, // 2^(22)-1
+ u_long dynamic_priority_offset = 0x200000UL); // 2^(22-1)
+
+
+#if defined (ACE_VXWORKS)
+
+ /// Factory method for a wrapped VxWorks message queue
+ static ACE_Message_Queue_Vx *
+ create_Vx_message_queue (size_t max_messages, size_t max_message_length,
+ ACE_Notification_Strategy *ns = 0);
+
+#endif /* defined (ACE_VXWORKS) */
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+
+ /// Factory method for a NT message queue.
+ static ACE_Message_Queue_NT *
+ create_NT_message_queue (size_t max_threads);
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+};
+
+/**
+ * @class ACE_Message_Queue_Ex
+ *
+ * @brief A threaded message queueing facility, modeled after the
+ * queueing facilities in System V STREAMs.
+ *
+ * ACE_Message_Queue_Ex is a strongly-typed version of the
+ * ACE_Message_Queue class. Rather than queueing in terms of ACE_Message_Block
+ * objects, ACE_Message_Queue_Ex has a template argument to specify the
+ * type of objects that are queued.
+ *
+ * The second template argument parameterizes the queue's synchronization.
+ * The argument specifies a synchronization strategy. The two main
+ * strategies available for ACE_SYNCH_DECL are:
+ * -# ACE_MT_SYNCH: all operations are thread-safe
+ * -# ACE_NULL_SYNCH: no synchronization and no locking overhead
+ */
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL>
+class ACE_Message_Queue_Ex
+{
+public:
+
+ enum
+ {
+ /// Default priority value. This is the lowest priority.
+ DEFAULT_PRIORITY = 0
+ };
+
+#if 0
+ // @@ Iterators are not implemented yet...
+
+ friend class ACE_Message_Queue_Iterator<ACE_SYNCH_USE>;
+ friend class ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>;
+
+ // = Traits
+ typedef ACE_Message_Queue_Iterator<ACE_SYNCH_USE>
+ ITERATOR;
+ typedef ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>
+ REVERSE_ITERATOR;
+#endif /* 0 */
+
+ /**
+ * @name Initialization methods
+ */
+ //@{
+ /**
+ * Initialize an ACE_Message_Queue_Ex.
+ *
+ * @param high_water_mark High water mark. Determines how many bytes can be
+ * stored in a queue before it's considered full. Supplier threads
+ * must block until the queue is no longer full.
+ * @param low_water_mark Low water mark. Determines how many bytes must be in
+ * the queue before supplier threads are allowed to enqueue additional
+ * data. By default, the @a hwm equals @a lwm, which means
+ * that suppliers will be able to enqueue new messages as soon as
+ * a consumer removes any message from the queue. Making the low
+ * water mark smaller than the high water mark forces consumers to
+ * drain more messages from the queue before suppliers can enqueue
+ * new messages, which can minimize the "silly window syndrome."
+ * @param ns Notification strategy. Pointer to an object conforming to the
+ * ACE_Notification_Strategy interface. If set, the object's
+ * notify(void) method will be called each time data is added to
+ * this ACE_Message_Queue. @see ACE_Reactor_Notification_Strategy.
+ */
+ ACE_Message_Queue_Ex (size_t high_water_mark = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t low_water_mark = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy * ns = 0);
+ virtual int open (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy * = 0);
+ //@}
+
+ /// Releases all resources from the message queue and marks it deactivated.
+ /// @sa flush().
+ ///
+ /// @retval The number of messages released from the queue; -1 on error.
+ virtual int close (void);
+
+ /// Releases all resources from the message queue and marks it deactivated.
+ virtual ~ACE_Message_Queue_Ex (void);
+
+ /**
+ * Releases all resources from the message queue but does not mark it
+ * deactivated. This method holds the queue lock during this operation.
+ * @sa close().
+ *
+ * @return The number of messages flushed; -1 on error.
+ */
+ virtual int flush (void);
+
+ /**
+ * Release all resources from the message queue but do not mark it
+ * as deactivated.
+ *
+ * @pre The caller must be holding the queue lock before calling this
+ * method.
+ *
+ * @return The number of messages flushed.
+ */
+ virtual int flush_i (void);
+
+ /** @name Enqueue and dequeue methods
+ *
+ * The enqueue and dequeue methods accept a timeout value passed as
+ * an ACE_Time_Value *. In all cases, if the timeout pointer is 0,
+ * the caller will block until action is possible. If the timeout pointer
+ * is non-zero, the call will wait (if needed, subject to water mark
+ * settings) until the absolute time specified in the referenced
+ * ACE_Time_Value object is reached. If the time is reached before the
+ * desired action is possible, the method will return -1 with errno set
+ * to @c EWOULDBLOCK. Regardless of the timeout setting, however,
+ * these methods will also fail and return -1 when the queue is closed,
+ * deactivated, pulsed, or when a signal occurs.
+ *
+ * The time parameters are handled the same as in ACE_Message_Queue, so
+ * you can see C++NPv2 Section 6.2 and APG Section 12.3 for a fuller
+ * treatment of ACE_Message_Queue, enqueueing, dequeueing, and how these
+ * operations are affected by queue state transitions.
+ */
+ //@{
+ /**
+ * Retrieve a pointer to the first item in the queue without removing it.
+ *
+ * @note Because the item whose pointer is returned is still on the queue,
+ * another thread may dequeue that item at any time,
+ * including before the calling thread examines the peeked-at item.
+ * Be very careful with this method in multithreaded queueing
+ * situations.
+ *
+ * @param first_item Reference to an ACE_MESSAGE_TYPE * that will
+ * point to the first item on the queue. The item
+ * remains on the queue until this or another thread
+ * dequeues it.
+ * @param timeout The absolute time the caller will wait until
+ * for an item to be queued.
+ *
+ * @retval >0 The number of items on the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int peek_dequeue_head (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an ACE_MESSAGE TYPE into the queue in accordance with
+ * the specified priority (0 is lowest priority). FIFO
+ * order is maintained when items of the same priority are
+ * inserted consecutively.
+ *
+ * @param new_item Pointer to an item that will be added to the queue.
+ * @param timeout The absolute time the caller will wait until
+ * for the block to be queued.
+ * @param priority The priority to use when enqueueing the item.
+ *
+ * @retval >0 The number of items on the queue after adding
+ * the specified item.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_prio (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0,
+ unsigned long priority = DEFAULT_PRIORITY);
+
+ /**
+ * This method acts just like enqueue_tail(). There's no deadline
+ * time associated with items.
+ */
+ virtual int enqueue_deadline (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * @deprecated This is an alias for enqueue_prio(). It's only here for
+ * backwards compatibility and will go away in a subsequent release.
+ * Please use enqueue_prio() instead.
+ */
+ virtual int enqueue (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an item at the tail of the queue.
+ *
+ * @param new_item Pointer to an item that will be added to the queue.
+ * @param timeout The absolute time the caller will wait until
+ * for the item to be queued.
+ *
+ * @retval >0 The number of items on the queue after adding
+ * the specified item.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_tail (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an item at the head of the queue.
+ *
+ * @param new_item Pointer to an item that will be added to the queue.
+ * @param timeout The absolute time the caller will wait until
+ * for the item to be queued.
+ *
+ * @retval >0 The number of items on the queue after adding
+ * the specified item.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_head (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /// This method is an alias for the following <dequeue_head> method.
+ virtual int dequeue (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue the item at the head of the queue and return a pointer to it.
+ *
+ * @param first_item Reference to an ACE_MESSAGE_TYPE * that will
+ * be set to the address of the dequeued item.
+ * @param timeout The absolute time the caller will wait until
+ * for an item to be dequeued.
+ *
+ * @retval >=0 The number of items remaining in the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int dequeue_head (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue the item that has the lowest priority (preserves
+ * FIFO order for items with the same priority) and return a pointer
+ * to it.
+ *
+ * @param dequeued Reference to an ACE_MESSAGE_TYPE * that will
+ * be set to the address of the dequeued item.
+ * @param timeout The absolute time the caller will wait until
+ * for an item to be dequeued.
+ *
+ * @retval >=0 The number of items remaining in the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int dequeue_prio (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue the item at the tail of the queue and return a pointer to it.
+ *
+ * @param dequeued Reference to an ACE_MESSAGE_TYPE * that will
+ * be set to the address of the dequeued item.
+ * @param timeout The absolute time the caller will wait until
+ * for an item to be dequeued.
+ *
+ * @retval >=0 The number of items remaining in the queue.
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int dequeue_tail (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Because there's deadline associated with enqueue_deadline(), this
+ * method will behave just as dequeue_head().
+ */
+ virtual int dequeue_deadline (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout = 0);
+ //@}
+
+ /** @name Queue statistics methods
+ */
+ //@{
+
+ /// True if queue is full, else false.
+ virtual bool is_full (void);
+
+ /// True if queue is empty, else false.
+ virtual bool is_empty (void);
+
+ /**
+ * Number of total bytes on the queue, i.e., sum of the message
+ * block sizes.
+ */
+ virtual size_t message_bytes (void);
+ /**
+ * Number of total length on the queue, i.e., sum of the message
+ * block lengths.
+ */
+ virtual size_t message_length (void);
+ /**
+ * Number of total messages on the queue.
+ */
+ virtual size_t message_count (void);
+
+ // = Manual changes to these stats (used when queued message blocks
+ // change size or lengths).
+ /**
+ * New value of the number of total bytes on the queue, i.e., sum of
+ * the message block sizes.
+ */
+ virtual void message_bytes (size_t new_size);
+ /**
+ * New value of the number of total length on the queue, i.e., sum
+ * of the message block lengths.
+ */
+ virtual void message_length (size_t new_length);
+
+ //@}
+
+ /** @name Water mark (flow control) methods
+ */
+ //@{
+
+ /**
+ * Get high watermark.
+ */
+ virtual size_t high_water_mark (void);
+ /**
+ * Set the high watermark, which determines how many bytes can be
+ * stored in a queue before it's considered "full."
+ */
+ virtual void high_water_mark (size_t hwm);
+
+ /**
+ * Get low watermark.
+ */
+ virtual size_t low_water_mark (void);
+ /**
+ * Set the low watermark, which determines how many bytes must be in
+ * the queue before supplier threads are allowed to enqueue
+ * additional <ACE_MESSAGE_TYPE>s.
+ */
+ virtual void low_water_mark (size_t lwm);
+ //@}
+
+ /** @name Activation and queue state methods
+ * See C++NPv2 Section 6.2 and APG Section 12.3 for a fuller treatment of
+ * queue states and transitions and how the transitions affect message
+ * enqueueing and dequeueing operations.
+ */
+ //@{
+
+ /**
+ * Deactivate the queue and wakeup all threads waiting on the queue
+ * so they can continue. No messages are removed from the queue,
+ * however. Any other operations called until the queue is
+ * activated again will immediately return -1 with @c errno ==
+ * ESHUTDOWN. Returns WAS_INACTIVE if queue was inactive before the
+ * call and WAS_ACTIVE if queue was active before the call.
+ */
+ virtual int deactivate (void);
+
+ /**
+ * Reactivate the queue so that threads can enqueue and dequeue
+ * messages again. Returns the state of the queue before the call.
+ */
+ virtual int activate (void);
+
+ /**
+ * Pulse the queue to wake up any waiting threads. Changes the
+ * queue state to PULSED; future enqueue/dequeue operations proceed
+ * as in ACTIVATED state.
+ *
+ * @retval The queue's state before this call.
+ */
+ virtual int pulse (void);
+
+ /// Returns the current state of the queue, which can be one of
+ /// ACTIVATED, DEACTIVATED, or PULSED.
+ virtual int state (void);
+
+ /// Returns true if the state of the queue is DEACTIVATED,
+ /// but false if the queue's state is ACTIVATED or PULSED.
+ virtual int deactivated (void);
+ //@}
+
+ /** @name Notification strategy methods
+ */
+ //@{
+
+ /**
+ * This hook is automatically invoked by <enqueue_head>,
+ * <enqueue_tail>, and <enqueue_prio> when a new item is inserted
+ * into the queue. Subclasses can override this method to perform
+ * specific notification strategies (e.g., signaling events for a
+ * <WFMO_Reactor>, notifying a <Reactor>, etc.). In a
+ * multi-threaded application with concurrent consumers, there is no
+ * guarantee that the queue will be still be non-empty by the time
+ * the notification occurs.
+ */
+ virtual int notify (void);
+
+ /// Get the notification strategy for the <Message_Queue>
+ virtual ACE_Notification_Strategy *notification_strategy (void);
+
+ /// Set the notification strategy for the <Message_Queue>
+ virtual void notification_strategy (ACE_Notification_Strategy *s);
+ //@}
+
+ /// Returns a reference to the lock used by the ACE_Message_Queue_Ex.
+ virtual ACE_SYNCH_MUTEX_T &lock (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Implement this via an ACE_Message_Queue.
+ ACE_Message_Queue<ACE_SYNCH_USE> queue_;
+};
+
+/**
+ * @class ACE_Message_Queue_Ex_N
+ *
+ * @brief A threaded message queueing facility, modeled after the
+ * queueing facilities in System V STREAMs which can enqueue
+ * multiple messages in one call.
+ *
+ * As ACE_Message_Queue_Ex, ACE_Message_Queue_Ex_N is a strongly-typed
+ * version of the ACE_Message_Queue. If @c ACE_SYNCH_DECL is @c ACE_MT_SYNCH
+ * then all operations are thread-safe. Otherwise, if it's @c ACE_NULL_SYNCH
+ * then there's no locking overhead.
+ *
+ * The @c ACE_MESSAGE_TYPE messages that are sent to this
+ * queue can be chained. Messages are expected to have a
+ * @c next method that returns the next message in the chain;
+ * ACE_Message_Queue_Ex_N uses this method to run through
+ * all the incoming messages and enqueue them in one call.
+ */
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL>
+class ACE_Message_Queue_Ex_N : public ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>
+{
+public:
+ // = Initialization and termination methods.
+
+ /**
+ * Initialize an ACE_Message_Queue_Ex_N. The @a high_water_mark
+ * determines how many bytes can be stored in a queue before it's
+ * considered "full." Supplier threads must block until the queue
+ * is no longer full. The @a low_water_mark determines how many
+ * bytes must be in the queue before supplier threads are allowed to
+ * enqueue additional messages. By default, the @a high_water_mark
+ * equals the @a low_water_mark, which means that suppliers will be
+ * able to enqueue new messages as soon as a consumer removes any message
+ * from the queue. Making the @a low_water_mark smaller than the
+ * @a high_water_mark forces consumers to drain more messages from the
+ * queue before suppliers can enqueue new messages, which can minimize
+ * the "silly window syndrome."
+ */
+ ACE_Message_Queue_Ex_N (size_t high_water_mark = ACE_Message_Queue_Base::DEFAULT_HWM,
+ size_t low_water_mark = ACE_Message_Queue_Base::DEFAULT_LWM,
+ ACE_Notification_Strategy * ns = 0);
+
+ /// Close down the message queue and release all resources.
+ virtual ~ACE_Message_Queue_Ex_N (void);
+
+ /**
+ * Enqueue one or more @c ACE_MESSAGE_TYPE objects at the head of the queue.
+ * If the @a new_item @c next() pointer is non-zero, it is assumed to be the
+ * start of a series of @c ACE_MESSAGE_TYPE objects connected via their
+ * @c next() pointers. The series of blocks will be added to the queue in
+ * the same order they are passed in as.
+ *
+ * @param new_item Pointer to an @c ACE_MESSAGE_TYPE that will be
+ * added to the queue. If the block's @c next() pointer
+ * is non-zero, all blocks chained from the @c next()
+ * pointer are enqueued as well.
+ * @param tv The absolute time the caller will wait until
+ * for the block to be queued.
+ *
+ * @retval >0 The number of @c ACE_MESSAGE_TYPE objects on the queue after
+ * adding the specified block(s).
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_head (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *tv = 0);
+
+ /**
+ * Enqueue one or more @c ACE_MESSAGE_TYPE objects at the tail of the queue.
+ * If the @a new_item @c next() pointer is non-zero, it is assumed to be the
+ * start of a series of @c ACE_MESSAGE_TYPE objects connected via their
+ * @c next() pointers. The series of blocks will be added to the queue in
+ * the same order they are passed in as.
+ *
+ * @param new_item Pointer to an @c ACE_MESSAGE_TYPE that will be
+ * added to the queue. If the block's @c next() pointer
+ * is non-zero, all blocks chained from the @c next()
+ * pointer are enqueued as well.
+ * @param tv The absolute time the caller will wait until
+ * for the block to be queued.
+ *
+ * @retval >0 The number of @c ACE_MESSAGE_TYPE objects on the queue after
+ * adding the specified block(s).
+ * @retval -1 On failure. errno holds the reason. Common errno values are:
+ * - EWOULDBLOCK: the timeout elapsed
+ * - ESHUTDOWN: the queue was deactivated or pulsed
+ */
+ virtual int enqueue_tail (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *tv = 0);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /**
+ * An helper method that wraps the incoming chain messages
+ * with ACE_Message_Blocks.
+ */
+ ACE_Message_Block *wrap_with_mbs_i (ACE_MESSAGE_TYPE *new_item);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Message_Queue_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Message_Queue_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MESSAGE_QUEUE_T_H */
diff --git a/ACE/ace/Message_Queue_Vx.cpp b/ACE/ace/Message_Queue_Vx.cpp
new file mode 100644
index 00000000000..dca82a2641d
--- /dev/null
+++ b/ACE/ace/Message_Queue_Vx.cpp
@@ -0,0 +1,368 @@
+// $Id$
+
+#include "ace/Message_Queue_Vx.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Message_Queue_Vx.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Message_Queue_Vx,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_VXWORKS)
+
+////////////////////////////////
+// class ACE_Message_Queue_Vx //
+////////////////////////////////
+
+void
+ACE_Message_Queue_Vx::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Message_Queue_Vx::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ switch (this->state_)
+ {
+ case ACE_Message_Queue_Base::ACTIVATED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = ACTIVATED\n")));
+ break;
+ case ACE_Message_Queue_Base::DEACTIVATED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = DEACTIVATED\n")));
+ break;
+ case ACE_Message_Queue_Base::PULSED:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("state = PULSED\n")));
+ break;
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("low_water_mark = %d\n")
+ ACE_TEXT ("high_water_mark = %d\n")
+ ACE_TEXT ("cur_bytes = %d\n")
+ ACE_TEXT ("cur_length = %d\n")
+ ACE_TEXT ("cur_count = %d\n")
+ ACE_TEXT ("head_ = %u\n")
+ ACE_TEXT ("MSG_Q_ID = %u\n"),
+ this->low_water_mark_,
+ this->high_water_mark_,
+ this->cur_bytes_,
+ this->cur_length_,
+ this->cur_count_,
+ this->head_,
+ this->tail_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Message_Queue_Vx::ACE_Message_Queue_Vx (size_t max_messages,
+ size_t max_message_length,
+ ACE_Notification_Strategy *ns)
+ : ACE_Message_Queue<ACE_NULL_SYNCH> (0, 0, ns),
+ max_messages_ (static_cast<int> (max_messages)),
+ max_message_length_ (static_cast<int> (max_message_length))
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::ACE_Message_Queue_Vx");
+
+ if (this->open (max_messages_, max_message_length_, ns) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("open")));
+}
+
+ACE_Message_Queue_Vx::~ACE_Message_Queue_Vx (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::~ACE_Message_Queue_Vx");
+
+ if (this->tail_ != 0 && this->close () == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("close")));
+}
+
+// Don't bother locking since if someone calls this function more than
+// once for the same queue, we're in bigger trouble than just
+// concurrency control!
+
+int
+ACE_Message_Queue_Vx::open (size_t max_messages,
+ size_t max_message_length,
+ ACE_Notification_Strategy *ns)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::open");
+ this->high_water_mark_ = 0;
+ this->low_water_mark_ = 0;
+ this->cur_bytes_ = 0;
+ this->cur_length_ = 0;
+ this->cur_count_ = 0;
+ this->head_ = 0;
+ this->notification_strategy_ = ns;
+ this->max_messages_ = static_cast<int> (max_messages);
+ this->max_message_length_ = static_cast<int> (max_message_length);
+
+ if (tail_)
+ {
+ // Had already created a msgQ, so delete it.
+ close ();
+ activate_i ();
+ }
+
+ return (this->tail_ =
+ reinterpret_cast<ACE_Message_Block *> (
+ ::msgQCreate (max_messages_,
+ max_message_length_,
+ MSG_Q_FIFO))) == 0 ? -1 : 0;
+}
+
+// Clean up the queue if we have not already done so!
+
+int
+ACE_Message_Queue_Vx::close (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::close");
+ // Don't lock, because we don't have a lock. It shouldn't be
+ // necessary, anyways.
+
+ this->deactivate_i ();
+
+ // Don't bother to free up the remaining message on the list,
+ // because we don't have any way to iterate over what's in the
+ // queue.
+
+ return ::msgQDelete (msgq ());
+}
+
+bool
+ACE_Message_Queue_Vx::is_empty_i (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::is_empty_i");
+ return ::msgQNumMsgs (msgq ()) == 0;
+}
+
+bool
+ACE_Message_Queue_Vx::is_full_i (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::is_full_i");
+ return ::msgQNumMsgs (msgq ()) >= max_messages_;
+}
+
+size_t
+ACE_Message_Queue_Vx::high_water_mark (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::high_water_mark");
+ ACE_NOTSUP_RETURN ((size_t) -1);
+}
+
+void
+ACE_Message_Queue_Vx::high_water_mark (size_t)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::high_water_mark");
+ ACE_NOTSUP;
+}
+
+size_t
+ACE_Message_Queue_Vx::low_water_mark (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::low_water_mark");
+ // Don't need to guard, because this is fixed.
+
+ ACE_NOTSUP_RETURN ((size_t) -1);
+}
+
+void
+ACE_Message_Queue_Vx::low_water_mark (size_t)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::low_water_mark");
+ ACE_NOTSUP;
+}
+
+size_t
+ACE_Message_Queue_Vx::message_bytes (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::message_bytes");
+ ACE_NOTSUP_RETURN ((size_t) -1);
+}
+
+size_t
+ACE_Message_Queue_Vx::message_length (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::message_length");
+ ACE_NOTSUP_RETURN ((size_t) -1);
+}
+
+size_t
+ACE_Message_Queue_Vx::message_count (void)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::message_count");
+ // Don't need to guard, because this is a system call.
+
+ return ::msgQNumMsgs (msgq ());
+}
+
+void
+ACE_Message_Queue_Vx::message_bytes (size_t)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::message_bytes");
+ ACE_NOTSUP;
+}
+
+void
+ACE_Message_Queue_Vx::message_length (size_t)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::message_length");
+ ACE_NOTSUP;
+}
+
+int
+ACE_Message_Queue_Vx::signal_enqueue_waiters (void)
+{
+ // No-op.
+ return 0;
+}
+
+int
+ACE_Message_Queue_Vx::signal_dequeue_waiters (void)
+{
+ // No-op.
+ return 0;
+}
+
+int
+ACE_Message_Queue_Vx::enqueue_tail_i (ACE_Message_Block *new_item)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::enqueue_tail_i");
+
+ if (new_item == 0)
+ return -1;
+
+ // Don't try to send a composite message!!!! Only the first
+ // block will be sent.
+
+ ++this->cur_count_;
+
+ // Always use this method to actually send a message on the queue.
+ if (::msgQSend (msgq (),
+ new_item->rd_ptr (),
+ new_item->size (),
+ WAIT_FOREVER,
+ MSG_PRI_NORMAL) == OK)
+ return ::msgQNumMsgs (msgq ());
+ else
+ return -1;
+}
+
+int
+ACE_Message_Queue_Vx::enqueue_head_i (ACE_Message_Block *new_item)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::enqueue_head_i");
+
+ // Just delegate to enqueue_tail_i.
+ return enqueue_tail_i (new_item);
+}
+
+int
+ACE_Message_Queue_Vx::enqueue_i (ACE_Message_Block *new_item)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::enqueue_i");
+
+ if (new_item == 0)
+ return -1;
+
+ if (this->head_ == 0)
+ // Should always take this branch.
+ return this->enqueue_head_i (new_item);
+ else
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_Message_Queue_Vx::enqueue_deadline_i (ACE_Message_Block *new_item)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::enqueue_deadline_i");
+
+ // Just delegate to enqueue_tail_i.
+ return enqueue_tail_i (new_item);
+}
+
+// Actually get the first ACE_Message_Block (no locking, so must be
+// called with locks held). This method assumes that the queue has at
+// least one item in it when it is called.
+
+int
+ACE_Message_Queue_Vx::dequeue_head_i (ACE_Message_Block *&first_item)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::dequeue_head_i");
+
+ // We don't allocate a new Message_Block: the caller must provide
+ // it, and must ensure that it is big enough (without chaining).
+
+ if (first_item == 0 || first_item->wr_ptr () == 0)
+ return -1;
+
+ if (::msgQReceive (msgq (),
+ first_item->wr_ptr (),
+ first_item->size (),
+ WAIT_FOREVER) == ERROR)
+ return -1;
+ else
+ return ::msgQNumMsgs (msgq ());
+}
+
+int
+ACE_Message_Queue_Vx::dequeue_prio_i (ACE_Message_Block *& /*dequeued*/)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::dequeue_prio_i");
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_Message_Queue_Vx::dequeue_tail_i (ACE_Message_Block *& /*dequeued*/)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::dequeue_tail_i");
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_Message_Queue_Vx::dequeue_deadline_i (ACE_Message_Block *& /*dequeued*/)
+{
+ ACE_TRACE ("ACE_Message_Queue_Vx::dequeue_deadline_i");
+ ACE_NOTSUP_RETURN (-1);
+}
+
+// Take a look at the first item without removing it.
+
+int
+ACE_Message_Queue_Vx::wait_not_full_cond (ACE_Guard<ACE_Null_Mutex> &mon,
+ ACE_Time_Value *tv)
+{
+ // Always return here, and let the VxWorks message queue handle blocking.
+ ACE_UNUSED_ARG (mon);
+ ACE_UNUSED_ARG (tv);
+
+ return 0;
+}
+
+int
+ACE_Message_Queue_Vx::wait_not_empty_cond (ACE_Guard<ACE_Null_Mutex> &mon,
+ ACE_Time_Value *tv)
+{
+ // Always return here, and let the VxWorks message queue handle blocking.
+ ACE_UNUSED_ARG (mon);
+ ACE_UNUSED_ARG (tv);
+
+ return 0;
+}
+
+#if ! defined (ACE_NEEDS_FUNC_DEFINITIONS)
+int
+ACE_Message_Queue_Vx::peek_dequeue_head (ACE_Message_Block *&,
+ ACE_Time_Value *)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+#endif /* ! ACE_NEEDS_FUNC_DEFINITIONS */
+
+#endif /* ACE_VXWORKS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Message_Queue_Vx.h b/ACE/ace/Message_Queue_Vx.h
new file mode 100644
index 00000000000..421ebce99ea
--- /dev/null
+++ b/ACE/ace/Message_Queue_Vx.h
@@ -0,0 +1,227 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Message_Queue_Vx.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MESSAGE_QUEUE_VX_H
+#define ACE_MESSAGE_QUEUE_VX_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Message_Block.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_VXWORKS)
+
+// Include the templates here.
+#include "ace/Message_Queue_T.h"
+
+# include /**/ <msgQLib.h>
+# include "ace/Null_Mutex.h"
+# include "ace/Null_Condition.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Message_Queue_Vx
+ *
+ * @brief Wrapper for VxWorks message queues.
+ *
+ * Specialization of ACE_Message_Queue to simply wrap VxWorks
+ * MsgQ. It does not use any synchronization, because it relies
+ * on the native MsgQ implementation to take care of that. The
+ * only system calls that it uses are VxWorks msgQLib calls, so
+ * it is suitable for use in interrupt service routines.
+ * @note *Many* ACE_Message_Queue features are not supported with
+ * this specialization, including:
+ * * The two size arguments to the constructor and <open> are
+ * interpreted differently. The first is interpreted as the
+ * maximum number of bytes in a message. The second is
+ * interpreted as the maximum number of messages that can be
+ * queued.
+ * * <dequeue_head> *requires* that the ACE_Message_Block
+ * pointer argument point to an ACE_Message_Block that was
+ * allocated by the caller. It must be big enough to support
+ * the received message, without using continuation. The
+ * pointer argument is not modified.
+ * * Message priority. MSG_Q_FIFO is hard-coded.
+ * * enqueue method timeouts.
+ * * <peek_dequeue_head>.
+ * * <ACE_Message_Queue_Iterators>.
+ * * The ability to change low and high water marks after creation.
+ * * <Message_Block> chains. The continuation field of ACE_Message_Block
+ * * is ignored; only the first block of a fragment chain is
+ * * recognized.
+ */
+class ACE_Message_Queue_Vx : public ACE_Message_Queue<ACE_NULL_SYNCH>
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Message_Queue_Vx (size_t max_messages,
+ size_t max_message_length,
+ ACE_Notification_Strategy * = 0);
+
+ // Create a message queue with all the defaults.
+ /// Create a message queue with all the defaults.
+ virtual int open (size_t max_messages,
+ size_t max_message_length,
+ ACE_Notification_Strategy * = 0);
+
+ /// Close down the message queue and release all resources.
+ virtual int close (void);
+
+ /// Close down the message queue and release all resources.
+ virtual ~ACE_Message_Queue_Vx (void);
+
+ // = Queue statistic methods.
+ /**
+ * Number of total bytes on the queue, i.e., sum of the message
+ * block sizes.
+ */
+ virtual size_t message_bytes (void);
+
+ /**
+ * Number of total length on the queue, i.e., sum of the message
+ * block lengths.
+ */
+ virtual size_t message_length (void);
+
+ /**
+ * Number of total messages on the queue.
+ */
+ virtual size_t message_count (void);
+
+ // = Manual changes to these stats (used when queued message blocks
+ // change size or lengths).
+ /**
+ * New value of the number of total bytes on the queue, i.e., sum of
+ * the message block sizes.
+ */
+ virtual void message_bytes (size_t new_size);
+ /**
+ * New value of the number of total length on the queue, i.e., sum
+ * of the message block lengths.
+ */
+ virtual void message_length (size_t new_length);
+
+ // = Flow control routines
+
+ /// Get high watermark.
+ virtual size_t high_water_mark (void);
+
+ /// Set high watermark.
+ virtual void high_water_mark (size_t hwm);
+
+ /// Get low watermark.
+ virtual size_t low_water_mark (void);
+
+ /// Set low watermark.
+ virtual void low_water_mark (size_t lwm);
+
+ // = Activation control methods.
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Enqueue an <ACE_Message_Block *> in accordance with its priority.
+ virtual int enqueue_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> in accordance with its deadline time.
+ virtual int enqueue_deadline_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> at the end of the queue.
+ virtual int enqueue_tail_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> at the head of the queue.
+ virtual int enqueue_head_i (ACE_Message_Block *new_item);
+
+ /// Dequeue and return the <ACE_Message_Block *> at the head of the
+ /// queue.
+ virtual int dequeue_head_i (ACE_Message_Block *&first_item);
+
+ /// Dequeue and return the <ACE_Message_Block *> with the lowest
+ /// priority.
+ virtual int dequeue_prio_i (ACE_Message_Block *&dequeued);
+
+ /// Dequeue and return the <ACE_Message_Block *> at the tail of the
+ /// queue.
+ virtual int dequeue_tail_i (ACE_Message_Block *&dequeued);
+
+ /// Dequeue and return the <ACE_Message_Block *> that has the lowest
+ /// deadline time.
+ virtual int dequeue_deadline_i (ACE_Message_Block *&dequeued);
+
+ // = Check the boundary conditions (assumes locks are held).
+ /// True if queue is full, else false.
+ virtual bool is_full_i (void);
+
+ /// True if queue is empty, else false.
+ virtual bool is_empty_i (void);
+
+ // = Implementation of public <activate>/<deactivate> methods above.
+
+ // These methods assume locks are held.
+
+ // = Helper methods to factor out common #ifdef code.
+ /// Wait for the queue to become non-full.
+ virtual int wait_not_full_cond (ACE_Guard<ACE_Null_Mutex> &mon,
+ ACE_Time_Value *tv);
+
+ /// Wait for the queue to become non-empty.
+ virtual int wait_not_empty_cond (ACE_Guard<ACE_Null_Mutex> &mon,
+ ACE_Time_Value *tv);
+
+ /// Inform any threads waiting to enqueue that they can procede.
+ virtual int signal_enqueue_waiters (void);
+
+ /// Inform any threads waiting to dequeue that they can procede.
+ virtual int signal_dequeue_waiters (void);
+
+ /// Access the underlying msgQ.
+ MSG_Q_ID msgq (void);
+
+private:
+
+ // Disallow copying and assignment.
+ ACE_Message_Queue_Vx (const ACE_Message_Queue_Vx &);
+ void operator= (const ACE_Message_Queue_Vx &);
+
+ ACE_UNIMPLEMENTED_FUNC (virtual int peek_dequeue_head
+ (ACE_Message_Block *&first_item,
+ ACE_Time_Value *tv = 0))
+
+private:
+ /// Maximum number of messages that can be queued.
+ int max_messages_;
+
+ /// Maximum message size, in bytes.
+ int max_message_length_;
+
+ /// Native message queue options.
+ int options_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_VXWORKS */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Message_Queue_Vx.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MESSAGE_QUEUE_VX_H */
diff --git a/ACE/ace/Message_Queue_Vx.inl b/ACE/ace/Message_Queue_Vx.inl
new file mode 100644
index 00000000000..0231c8f06c6
--- /dev/null
+++ b/ACE/ace/Message_Queue_Vx.inl
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_VXWORKS)
+// Specialization to use native VxWorks Message Queues.
+
+ACE_INLINE MSG_Q_ID
+ACE_Message_Queue_Vx::msgq (void)
+{
+ // Hijack the tail_ field to store the MSG_Q_ID.
+ return reinterpret_cast<MSG_Q_ID> (tail_);
+}
+
+#endif /* ACE_VXWORKS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Method_Object.h b/ACE/ace/Method_Object.h
new file mode 100644
index 00000000000..ffabf82d454
--- /dev/null
+++ b/ACE/ace/Method_Object.h
@@ -0,0 +1,38 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Method_Object.h
+ *
+ * $Id$
+ *
+ * This file just #includes "ace/Method_Request.h" and is just here
+ * for backwards compatibility with earlier versions of ACE.
+ * Please don't use it directly since it may go away at some point.
+ *
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_METHOD_OBJECT_H
+#define ACE_METHOD_OBJECT_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Method_Request.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Maintain backwards compatibility so that Steve Huston doesn't go
+// postal... ;-)
+typedef ACE_Method_Request ACE_Method_Object;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_METHOD_OBJECT_H */
diff --git a/ACE/ace/Method_Request.cpp b/ACE/ace/Method_Request.cpp
new file mode 100644
index 00000000000..283a087905f
--- /dev/null
+++ b/ACE/ace/Method_Request.cpp
@@ -0,0 +1,30 @@
+#include "ace/Method_Request.h"
+
+ACE_RCSID (ace,
+ Method_Request,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Method_Request::ACE_Method_Request (unsigned long prio)
+ : priority_ (prio)
+{
+}
+
+ACE_Method_Request::~ACE_Method_Request (void)
+{
+}
+
+unsigned long
+ACE_Method_Request::priority (void) const
+{
+ return this->priority_;
+}
+
+void
+ACE_Method_Request::priority (unsigned long prio)
+{
+ this->priority_ = prio;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Method_Request.h b/ACE/ace/Method_Request.h
new file mode 100644
index 00000000000..887a7f58073
--- /dev/null
+++ b/ACE/ace/Method_Request.h
@@ -0,0 +1,100 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Method_Request.h
+ *
+ * $Id$
+ *
+ * @author Andres Kruse <Andres.Kruse@cern.ch>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_METHOD_REQUEST_H
+#define ACE_METHOD_REQUEST_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Method_Request
+ *
+ * @brief Reifies a method into a request. Subclasses must provide
+ * the necessary state and behavior.
+ *
+ * An ACE_Method_Request is inserted in an ACE_Activation_Queue,
+ * where it is subsequently removed by a scheduler object (often
+ * derived from ACE_Task), which invokes the @c call() method.
+ *
+ * This class is discussed in depth in the Active Object chapter
+ * of POSA2.
+ *
+ * @sa ACE_Activation_Queue
+ */
+class ACE_Export ACE_Method_Request
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Method_Request (unsigned long priority = 0);
+
+ /// Destructor.
+ virtual ~ACE_Method_Request (void);
+
+ // = Accessors.
+ /// Get priority.
+ unsigned long priority (void) const;
+
+ /// Set priority.
+ /**
+ * Priority values are user-defined. The default (set in the constructor)
+ * is 0. The priority value is used in the ACE_Activation_Queue::enqueue()
+ * method to order the method requests in the queue by priority.
+ * 0 is the lowest priority.
+ *
+ * @param prio unsigned long, the new priority value for this object.
+ *
+ * @sa ACE_Activation_Queue::enqueue
+ */
+ void priority (unsigned long prio);
+
+ // = Invocation method (must be overridden by subclasses).
+ /// Invoked by the scheduler to execute the request.
+ /**
+ * This method must be implemented by the subclass to perform the
+ * desired actions.
+ *
+ * @return int; not interpreted by ACE. The scheduler class must
+ * decide the meaning of this return value and act on it
+ * if needed.
+ */
+ virtual int call (void) = 0;
+
+private:
+
+ /// Disallow copying and assignment.
+ ACE_Method_Request (const ACE_Method_Request &);
+ void operator= (const ACE_Method_Request &);
+
+protected:
+ /// The priority of the request.
+ unsigned long priority_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#include /**/ "ace/post.h"
+#endif /* ACE_METHOD_REQUEST_H */
diff --git a/ACE/ace/Metrics_Cache.h b/ACE/ace/Metrics_Cache.h
new file mode 100644
index 00000000000..2ec8c69344b
--- /dev/null
+++ b/ACE/ace/Metrics_Cache.h
@@ -0,0 +1,140 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Metrics_Cache.h
+ *
+ * $Id$
+ *
+ * @author Chris Gill
+ */
+//=============================================================================
+
+
+#ifndef ACE_METRICS_CACHE_H
+#define ACE_METRICS_CACHE_H
+
+#include "ace/Timeprobe.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_METRICS_COLLECTION)
+
+#if defined (ACE_ENABLE_TIMEPROBES) && defined (ACE_COMPILE_TIMEPROBES)
+
+/**
+ * Call the appropriate 'report_ + NAME + _start' function. The start function makes a time probe measurement.
+ *
+ * ACE: The cache is a double-sided space of ACE_Timeprobe objects. For example if there is 10 probes there
+ * will be a two lists of 10 probes all initialized. When a record is made, the appropriate probe is found,
+ * add the measurement is made.
+ *
+ * TAO: The cache is still double sided but this time the X argument is a handle_t. The appropriate monitor
+ * map is located in the Metrics_Cache, find the data, and if there is nothing wrong with the data
+ * make a time measurement. The data is actually a ACE_Metrics_Timeprobe (Why not TAO_Metrics_Timeprobe?)
+ *
+ * USAGE_LEVEL: ACE+TAO
+ *
+ * @param METRICS_PTR - Pointer to a initialized metrics cache
+ * @param NAME - Name of defining function (e.g. ACE: enqueue/dequeue)
+ * @param X - Argument (ACE: u_int, TAO: RtecScheduler::handle_t)
+ */
+# define START_DISPATCH_METRIC(METRICS_PTR,NAME,X) \
+do { if((METRICS_PTR->metrics_enabled())) { \
+METRICS_PTR->report_##NAME##_start(X); \
+} } while (0)
+
+/**
+ * Call the appropriate 'report_ + NAME + _stop' function. The stop function makes a time probe measurement.
+ *
+ * ACE & TAO: Same as START_DISPATCH_METRIC
+ *
+ * USAGE_LEVEL: ACE+TAO
+ *
+ * @param METRICS_PTR - Pointer to a initialized metrics cache
+ * @param NAME - Name of defining function (e.g. ACE: enqueue/dequeue)
+ * @param X - Argument (ACE: u_int, TAO: RtecScheduler::handle_t)
+ */
+# define STOP_DISPATCH_METRIC(METRICS_PTR,NAME,X) \
+do { if((METRICS_PTR->metrics_enabled())) { \
+METRICS_PTR->report_##NAME##_stop(X); \
+} } while (0)
+
+/**
+ * Call the appropriate 'report_ + NAME + _suspend' function. The suspend function makes a time probe measurement.
+ * This marks when the object under observation has been suspended.
+ *
+ * USAGE_LEVEL: ACE+TAO
+ *
+ * @param METRICS_PTR - Pointer to a initialized metrics cache
+ * @param NAME - Name of defining function (e.g. ACE: enqueue/dequeue)
+ * @param X - Argument (ACE: u_int, TAO: RtecScheduler::handle_t)
+ */
+# define PAUSE_DISPATCH_METRIC(METRICS_PTR,NAME,X) \
+do { if((METRICS_PTR->metrics_enabled())) { \
+METRICS_PTR->report_##NAME##_suspend(X); \
+} } while (0)
+
+/**
+ * Call the appropriate 'report_ + NAME + _resume' function. The suspend function makes a time probe measurement.
+ * This marks when the object under observation that was suspended is not resuming normal execution.
+ *
+ * USAGE_LEVEL: ACE+TAO
+ *
+ * @param METRICS_PTR - Pointer to a initialized metrics cache
+ * @param NAME - Name of defining function (e.g. ACE: enqueue/dequeue)
+ * @param X - Argument (ACE: u_int, TAO: RtecScheduler::handle_t)
+ */
+# define RESUME_DISPATCH_METRIC(METRICS_PTR,NAME,X) \
+do { if((METRICS_PTR->metrics_enabled())) { \
+METRICS_PTR->report_##NAME##_resume(X); \
+} } while (0)
+
+
+/**
+ * Mystery macros. I could not find where there were functions like 'report_base_metrics_start ()'. All the
+ * start and stop functions had an argument to find the probe in the cache
+ */
+# define START_METRIC(METRICS_PTR,NAME) \
+do { if((METRICS_PTR->metrics_enabled())) { \
+METRICS_PTR->report_##NAME##_start(); \
+} } while (0)
+
+# define STOP_METRIC(METRICS_PTR,NAME) \
+do { if((METRICS_PTR->metrics_enabled())) { \
+METRICS_PTR->report_##NAME##_stop(); \
+} } while (0)
+
+#include "ace/Metrics_Cache_T.h"
+#include "ace/Singleton.h"
+
+#if defined (_MSC_VER)
+// Disable warning of using Microsoft Extension.
+#pragma warning(disable:4231)
+#endif /* _MSC_VER */
+
+#if defined (_MSC_VER)
+// Default back the warning of using Microsoft Extension.
+#pragma warning(default:4231)
+#endif /* _MSC_VER */
+
+#else
+#error ACE_Compile_Timeprobes must be defined in order to collect metrics
+#endif /* ACE_ENABLE_TIMEPROBES & ACE_COMPILE_TIMEPROBES */
+
+#else
+
+# define REGISTER_METRICS_PROBE_RETURN(METRICS_PTR,METRICS_REGION,PROBE_NAME,PROBE_TYPE,METRICS_HANDLE)
+# define REGISTER_METRICS_REPORTING_PROBE_RETURN(METRICS_PTR,METRICS_REGION,PROBE_NAME,PROBE_TYPE,METRICS_LOGGER_REF,METRICS_HANDLE)
+# define START_DISPATCH_METRIC(METRICS_PTR,NAME,X)
+# define STOP_DISPATCH_METRIC(METRICS_PTR,NAME,X)
+# define PAUSE_DISPATCH_METRIC(METRICS_PTR,NAME,X)
+# define RESUME_DISPATCH_METRIC(METRICS_PTR,NAME,X)
+# define START_METRIC(METRICS_PTR,NAME)
+# define STOP_METRIC(METRICS_PTR,NAME)
+
+#endif /* ACE_ENABLE_TIMEPROBES && ACE_COMPILE_TIMEPROBES */
+
+#endif /* ACE_METRICS_CACHE_H */
diff --git a/ACE/ace/Metrics_Cache_T.cpp b/ACE/ace/Metrics_Cache_T.cpp
new file mode 100644
index 00000000000..285df4a9753
--- /dev/null
+++ b/ACE/ace/Metrics_Cache_T.cpp
@@ -0,0 +1,237 @@
+// $Id$
+
+#ifndef ACE_METRICS_CACHE_CPP
+#define ACE_METRICS_CACHE_CPP
+
+//#define ACE_BUILD_DLL
+
+#include "ace/Metrics_Cache_T.h"
+
+#if defined (ACE_COMPILE_TIMEPROBES)
+
+#include "ace/Metrics_Cache.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Metrics_Cache_T.inl"
+#endif /* __ACE_INLINE__ */
+
+// Const strings for timeprobe event type descriptions.
+
+static const char * event_description_strings [] =
+{
+ "start",
+ "stop",
+ "suspend",
+ "resume"
+};
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/////////////////////////////////
+// class ACE_Metrics_Timeprobe //
+/////////////////////////////////
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::ACE_Metrics_Timeprobe (u_int id,
+ const char *name,
+ u_long size)
+ :
+ ACE_Timeprobe<ACE_LOCK> (size),
+ id_ (id),
+ name_ (0)
+{
+ if (name == 0)
+ {
+ name = "";
+ }
+
+ char * name_tmp = 0;
+ ACE_NEW_MALLOC_ARRAY (name_tmp,
+ (char *) this->allocator ()->malloc (ACE_OS::strlen(name)+1),
+ char,
+ ACE_OS::strlen(name)+1);
+ ACE_OS::memcpy (name_tmp, name, ACE_OS::strlen (name)+1);
+ name_ = name_tmp;
+
+ this->event_descriptions (event_description_strings,
+ sizeof(event_description_strings)/sizeof(const char *));
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::
+ACE_Metrics_Timeprobe (ALLOCATOR *alloc,
+ u_int id,
+ const char *name,
+ u_long size)
+ : ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR> (size),
+ id_ (id),
+ name_ (0)
+{
+ if (name == 0)
+ {
+ name = "";
+ }
+
+ char * name_tmp = 0;
+ ACE_NEW_MALLOC_ARRAY (name_tmp,
+ (char *) alloc->malloc(ACE_OS::strlen(name)+1),
+ char,
+ ACE_OS::strlen(name)+1);
+ ACE_OS::memcpy (name_tmp, name, ACE_OS::strlen (name)+1);
+ name_ = name_tmp;
+
+ this->event_descriptions (event_description_strings,
+ sizeof(event_description_strings)/sizeof(const char *));
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::~ACE_Metrics_Timeprobe ()
+{
+ if (name_)
+ {
+ this->allocator ()->free ((void*) name_);
+ }
+}
+
+
+// Returns true if a timeprobe matches the passed id.
+
+template <class ACE_LOCK, class ALLOCATOR>
+int
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::is_event (const ACE_Metrics_Timeprobe<ACE_LOCK,
+ ALLOCATOR>::
+ ACE_METRICS_TIMEPROBE_DATA_TYPE &t,
+ ACE_Metrics_Timeprobe<ACE_LOCK,
+ ALLOCATOR>::
+ event_id id)
+{
+ return (t.event_.event_number_ == (u_long) id) ? 1 : 0;
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+const char *
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::probe_name (void)
+{
+ return name_;
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+void
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::probe_name (char * name)
+{
+ char * name_tmp = 0;
+ ACE_NEW_MALLOC_ARRAY (name_tmp,
+ (char *) this->allocator ()->malloc (ACE_OS::strlen(name)+1),
+ char,
+ ACE_OS::strlen(name)+1);
+ ACE_OS::memcpy (name_tmp, name, ACE_OS::strlen (name)+1);
+
+ if (name_)
+ {
+ this->allocator ()->free (name_);
+ }
+
+ name_ = name_tmp;
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+u_int
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::probe_id (void)
+{
+ return id_;
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+void
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::probe_id (u_int id)
+{
+ id_ = id;
+}
+
+
+// Flush the ACE metrics timeprobe into shared memory.
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::
+flush_ACE_Metrics_Timeprobe ()
+{
+}
+
+
+/////////////////////////////
+// Class ACE_Metrics_Cache //
+/////////////////////////////
+
+
+// Constructor.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::
+ACE_Metrics_Cache (u_long table_size,
+ u_long number_of_probes,
+ ALLOCATOR *alloc)
+ : probe_set_size_ (0),
+ enqueue_names_ (0),
+ dequeue_names_ (0),
+ consumer_index_ (0),
+ supplier_index_ (1),
+ table_size_ (table_size),
+ interval_start_ (ACE_Time_Value::zero),
+ interval_end_ (ACE_Time_Value::zero),
+ interval_initialized_ (0),
+ metrics_enabled_(1),
+ allocator_ (alloc)
+{
+ ACE_UNUSED_ARG(number_of_probes);
+ // Initialize probe and count arrays.
+
+ // Ensure that the high res timer global scale factor
+ // is set before any of its static methods are used
+ ACE_High_Res_Timer::global_scale_factor ();
+
+ enqueue_count_ [0] = 0;
+ enqueue_count_ [1] = 0;
+ dequeue_count_ [0] = 0;
+ dequeue_count_ [1] = 0;
+ enqueue_probes_ [0] = 0;
+ enqueue_probes_ [1] = 0;
+ dequeue_probes_ [0] = 0;
+ dequeue_probes_ [1] = 0;
+}
+
+// Destructor.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::~ACE_Metrics_Cache ()
+{
+}
+
+
+// Obtain an allocator pointer correctly thunked for the current
+// address space. If there is no allocator stored in the instance,
+// the singleton allocator in the current process is used.
+
+template <class ACE_LOCK, class ALLOCATOR> ALLOCATOR *
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::allocator (void)
+{
+ ALLOCATOR * alloc = allocator_;
+ return alloc
+ ? alloc
+ : ACE_Singleton<ALLOCATOR, ACE_LOCK>::instance ();
+}
+
+
+// Flush the ACE metrics cache into shared memory.
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::
+flush_ACE_Metrics_Cache ()
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* defined (ACE_COMPILE_TIMEPROBES) */
+
+#endif /* ACE_METRICS_CACHE_CPP */
diff --git a/ACE/ace/Metrics_Cache_T.h b/ACE/ace/Metrics_Cache_T.h
new file mode 100644
index 00000000000..5f0abdf31fa
--- /dev/null
+++ b/ACE/ace/Metrics_Cache_T.h
@@ -0,0 +1,243 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Metrics_Cache_T.h
+ *
+ * $Id$
+ *
+ * @author Chris Gill <cdgill@cse.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_METRICS_CACHE_T_H
+#define ACE_METRICS_CACHE_T_H
+
+#include /**/ "ace/config-all.h"
+
+// helpful macro definitions
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_COMPILE_TIMEPROBES)
+
+#include "ace/Timeprobe.h"
+#include "ace/Timeprobe_T.h"
+
+// Defaults for initializing timeprobes and timeprobe arays.
+#define METRICS_MIN_TIMEPROBE_TABLE_SIZE 256 * 4
+#define METRICS_MAX_TIMEPROBE_TABLE_SIZE 256 * 256
+#define METRICS_DEFAULT_TIMEPROBE_TABLE_SIZE METRICS_MIN_TIMEPROBE_TABLE_SIZE
+#define METRICS_DEFAULT_TIMEPROBE_COUNT 6
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Metrics_Timeprobe
+ *
+ * @brief This class implements a timeprobe for use in a Metrics framework.
+ *
+ * This class provides a probe for specific thread and method call
+ * metrics timing points.
+ */
+template <class ACE_LOCK, class ALLOCATOR>
+class ACE_Metrics_Timeprobe :
+ public ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>
+ {
+public:
+
+ typedef ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>
+ ACE_METRICS_TIMEPROBE_TYPE;
+
+ typedef ACE_timeprobe_t ACE_METRICS_TIMEPROBE_DATA_TYPE;
+ typedef ACE_METRICS_TIMEPROBE_TYPE* ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE;
+ typedef char* ACE_METRICS_NAME_BASED_PTR_TYPE;
+
+ // Enumerated timeprobe event types.
+ enum event_id
+ {
+ WORK_START = 0,
+ WORK_STOP = 1,
+ WORK_SUSPEND = 2,
+ WORK_RESUME = 3
+ };
+
+ // Default constructor: plugs in the above event descriptions.
+ ACE_Metrics_Timeprobe (u_int id = 0,
+ const char *name = 0,
+ u_long size = METRICS_DEFAULT_TIMEPROBE_TABLE_SIZE);
+
+ // Constructor with allocator: plugs in the above event descriptions.
+ ACE_Metrics_Timeprobe (ALLOCATOR *allocatorPtr,
+ u_int id = 0,
+ const char *name = 0,
+ u_long size = METRICS_DEFAULT_TIMEPROBE_TABLE_SIZE);
+
+ // Destructor.
+ virtual ~ACE_Metrics_Timeprobe ();
+
+ // Returns true if a timeprobe event matches the passed id.
+ int is_event (const ACE_METRICS_TIMEPROBE_DATA_TYPE &t,
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::event_id id);
+
+ // Accessor and mutator for probe name.
+ const char * probe_name (void);
+ void probe_name (char * name);
+
+ // Accessor for probe id.
+ u_int probe_id (void);
+
+ // Mutator for probe id.
+ void probe_id (u_int id);
+
+ // Flush the ACE metrics timeprobe into shared memory.
+ void flush_ACE_Metrics_Timeprobe ();
+
+protected:
+
+ // Identifier for the timeprobe.
+ u_int id_;
+
+ // Name of the timeprobe.
+ char* name_;
+
+private:
+
+ // Declare but do not define.
+ ACE_Metrics_Timeprobe (const ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> &);
+ void operator =(const ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> &);
+};
+
+/**
+ * @class ACE_Metrics_Cache
+ *
+ * @brief This class implements a cache for metrics timeprobe data.
+ *
+ * This class allows probes to be recorded into a single cache that
+ * monitors and other higher level metrics classes can query.
+ */
+template <class ACE_LOCK, class ALLOCATOR>
+class ACE_Metrics_Cache
+{
+public:
+
+ typedef ACE_Metrics_Cache <ACE_LOCK, ALLOCATOR> ACE_METRICS_CACHE_TYPE;
+
+ // Default constructor.
+ ACE_Metrics_Cache (u_long table_size
+ = METRICS_DEFAULT_TIMEPROBE_TABLE_SIZE,
+ u_long number_of_probes
+ = METRICS_DEFAULT_TIMEPROBE_COUNT,
+ ALLOCATOR * allocatorPtr = (ALLOCATOR*)ALLOCATOR::instance());
+
+ // Destructor.
+ ~ACE_Metrics_Cache ();
+
+ // = Dispatching metrics.
+
+ // Report start, stop, suspend, and resume times of a dispatch
+ // enqueue: stores data metrics on the supplier side.
+ void report_enqueue_start (u_long i);
+ void report_enqueue_stop (u_long i);
+ void report_enqueue_suspend (u_long i);
+ void report_enqueue_resume (u_long i);
+
+ // Report start, stop, suspend, and resume times of a dispatch
+ // dequeue: stores data metrics on the supplier side..
+ void report_dequeue_start (u_long i);
+ void report_dequeue_stop (u_long i);
+ void report_dequeue_suspend (u_long i);
+ void report_dequeue_resume (u_long i);
+
+ // Reset the metrics data on the consumer side.
+ void reset_base_statistics ();
+
+ // Flips the supplier and consumer sides.
+ void flip_supplier_and_consumer ();
+
+ // Flush the ACE metrics cache into shared memory.
+ void flush_ACE_Metrics_Cache ();
+
+ // Set the enable state for metrics collection.
+ void metrics_enabled(int enabled);
+
+ // Return the enable state for metrics collection.
+ int metrics_enabled(void) const;
+
+protected:
+
+ // Obtain an allocator pointer correctly thunked for the current
+ // address space. If there is no allocator stored in the instance,
+ // the singleton allocator in the current process is used.
+ ALLOCATOR * allocator (void);
+
+ // = Implementation members.
+
+ // Number of probes in each supplier/consumer set.
+ u_long probe_set_size_;
+
+ // Probe data counts for each supplier/consumer set.
+ u_long * enqueue_count_ [2];
+ u_long * dequeue_count_ [2];
+
+ // Probes for each supplier/consumer set.
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> ** enqueue_probes_ [2];
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> ** dequeue_probes_ [2];
+
+ // Names for the probes.
+ char ** enqueue_names_;
+ char ** dequeue_names_;
+
+ // Index from which probe events are being consumed.
+ // for WSOA, it's the data being sent to the logger
+ int consumer_index_;
+
+ // Index to which probe events are being supplied.
+ // for WSOA, it's the data being recorded from the probes
+ int supplier_index_;
+
+ // Size of the timestamp table in each probe.
+ u_long table_size_;
+
+ // Interval start and stop timestamps.
+ ACE_Time_Value interval_start_;
+
+ // Interval start and stop timestamps.
+ ACE_Time_Value interval_end_;
+
+ // Flag to indicate whether or not start time of interval has been
+ // initialized since the last reset.
+ int interval_initialized_;
+
+ // Indicator of whether metrics is enabled.
+ int metrics_enabled_;
+
+private:
+
+ // Allocation strategy object.
+ ALLOCATOR* allocator_;
+
+ // Declare but do not define.
+ ACE_Metrics_Cache (const ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR> &);
+ void operator = (const ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR> &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Metrics_Cache_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Metrics_Cache_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Metrics_Cache_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* defined (ACE_COMPILE_TIMEPROBES) */
+
+#endif /* ACE_METRICS_CACHE_T_H */
diff --git a/ACE/ace/Metrics_Cache_T.inl b/ACE/ace/Metrics_Cache_T.inl
new file mode 100644
index 00000000000..e0f542ab366
--- /dev/null
+++ b/ACE/ace/Metrics_Cache_T.inl
@@ -0,0 +1,240 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifndef ACE_METRICS_CACHE_T_INL
+#define ACE_METRICS_CACHE_T_INL
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/////////////////////////////
+// Class ACE_Metrics_Cache //
+/////////////////////////////
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::report_enqueue_start (u_long i)
+{
+ if (i < this->probe_set_size_)
+ {
+ u_long & count =
+ this->enqueue_count_ [this->supplier_index_] [i];
+ ++count;
+
+ if (! this->interval_initialized_)
+ {
+ this->interval_initialized_ = 1;
+ ACE_hrtime_t hrtime_now = ACE_OS::gethrtime ();
+ ACE_High_Res_Timer::hrtime_to_tv (this->interval_start_,
+ hrtime_now);
+ this->interval_end_.set (this->interval_start_.sec(),
+ this->interval_start_.usec());
+ }
+
+ // Take the metrics timeprobe last, to avoid measuring the above
+ // metrics processing.
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->enqueue_probes_ [this->supplier_index_][i];
+ probe->
+ timeprobe (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_START);
+ }
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::report_enqueue_stop (u_long i)
+{
+ if (i < this->probe_set_size_)
+ {
+ // Take the metrics timeprobe first, to avoid measuring the below
+ // metrics processing.
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->enqueue_probes_ [this->supplier_index_][i];
+ probe->
+ timeprobe (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_STOP);
+
+ ACE_hrtime_t hrtime_now = ACE_OS::gethrtime ();
+ ACE_High_Res_Timer::hrtime_to_tv (this->interval_end_,
+ hrtime_now);
+
+ u_long & count = enqueue_count_ [this->supplier_index_][i];
+ ++count;
+ }
+
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::report_enqueue_suspend (u_long i)
+{
+ if (i < this->probe_set_size_)
+ {
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->enqueue_probes_ [this->supplier_index_][i];
+ probe->
+ timeprobe (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_SUSPEND);
+ u_long & count =
+ this->enqueue_count_ [this->supplier_index_] [i];
+ ++count;
+ }
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::report_enqueue_resume (u_long i)
+{
+ if (i < this->probe_set_size_)
+ {
+ u_long & count =
+ this->enqueue_count_ [this->supplier_index_] [i];
+ ++count;
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->enqueue_probes_ [this->supplier_index_][i];
+ probe->
+ timeprobe (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_RESUME);
+ }
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::report_dequeue_start (u_long i)
+{
+ if (i < this->probe_set_size_)
+ {
+ u_long & count =
+ this->dequeue_count_ [this->supplier_index_] [i];
+ ++count;
+
+ if (! this->interval_initialized_)
+ {
+ this->interval_initialized_ = 1;
+ ACE_hrtime_t hrtime_now = ACE_OS::gethrtime ();
+ ACE_High_Res_Timer::hrtime_to_tv (this->interval_start_,
+ hrtime_now);
+ this->interval_end_.set (this->interval_start_.sec(),
+ this->interval_start_.usec());
+ }
+
+ // Take the metrics timeprobe last, to avoid measuring the above
+ // metrics processing.
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->dequeue_probes_ [this->supplier_index_][i];
+ probe->
+ timeprobe (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_START);
+ }
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::report_dequeue_stop (u_long i)
+{
+ if (i < this->probe_set_size_)
+ {
+ // Take the metrics timeprobe first, to avoid measuring the
+ // metrics processing below.
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->dequeue_probes_ [this->supplier_index_][i];
+
+ probe->timeprobe (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_STOP);
+
+ ACE_hrtime_t hrtime_now = ACE_OS::gethrtime ();
+ ACE_High_Res_Timer::hrtime_to_tv (this->interval_end_,
+ hrtime_now);
+
+ u_long & count = dequeue_count_ [this->supplier_index_] [i];
+ ++count;
+ }
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::report_dequeue_suspend (u_long i)
+{
+ if (i < this->probe_set_size_)
+ {
+ u_long & count =
+ this->dequeue_count_ [this->supplier_index_] [i];
+ ++count;
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->dequeue_probes_ [this->supplier_index_][i];
+ probe->
+ timeprobe (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_SUSPEND);
+ }
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::report_dequeue_resume (u_long i)
+{
+ if (i < this->probe_set_size_)
+ {
+ u_long & count =
+ this->dequeue_count_ [this->supplier_index_] [i];
+ ++count;
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->dequeue_probes_ [this->supplier_index_][i];
+ probe->
+ timeprobe (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_RESUME);
+ }
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::reset_base_statistics ()
+{
+ this->interval_initialized_ = 0;
+ this->interval_start_.set (0, 0);
+ this->interval_end_.set (0, 0);
+
+ for (u_int i = 0; i < this->probe_set_size_; ++i)
+ {
+ this->enqueue_count_ [this->consumer_index_] [i] = 0;
+ this->dequeue_count_ [this->consumer_index_] [i] = 0;
+
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> * probe =
+ this->enqueue_probes_ [this->consumer_index_][i];
+ probe->reset ();
+ probe =
+ this->dequeue_probes_ [this->consumer_index_][i];
+ probe->reset ();
+ }
+}
+
+
+// Flips the supplier and consumer positions.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::flip_supplier_and_consumer ()
+{
+ int temp = consumer_index_;
+ consumer_index_ = supplier_index_;
+ supplier_index_ = temp;
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::metrics_enabled(int enabled)
+{
+ metrics_enabled_ = enabled;
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE int
+ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>::metrics_enabled(void) const
+{
+ return metrics_enabled_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_METRICS_CACHE_T_INL */
diff --git a/ACE/ace/Min_Max.h b/ACE/ace/Min_Max.h
new file mode 100644
index 00000000000..74fe058590f
--- /dev/null
+++ b/ACE/ace/Min_Max.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Min_Max.h
+ *
+ * $Id$
+ *
+ * Define an appropriate set of min()/max() functions using templates.
+ *
+ *
+ * @author Derek Dominish <Derek.Dominish@Australia.Boeing.com>
+ */
+//=============================================================================
+
+#ifndef ACE_MIN_MAX_H
+#define ACE_MIN_MAX_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T>
+inline const T &
+ace_min (const T &t1, const T &t2)
+{
+ return t2 > t1 ? t1 : t2;
+}
+
+template <class T>
+inline const T &
+ace_max (const T &t1, const T &t2)
+{
+ return t1 > t2 ? t1 : t2;
+}
+
+template <class T>
+inline const T &
+ace_min (const T &t1, const T &t2, const T &t3)
+{
+ return ace_min (ace_min (t1, t2), t3);
+}
+
+template <class T>
+inline const T &
+ace_max (const T &t1, const T &t2, const T &t3)
+{
+ return ace_max (ace_max (t1, t2), t3);
+}
+
+template <class T>
+inline const T &
+ace_range (const T &min, const T &max, const T &val)
+{
+ return ace_min (ace_max (min, val), max);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# define ACE_MIN(a,b) ace_min((a),(b))
+# define ACE_MAX(a,b) ace_max((a),(b))
+# define ACE_RANGE(a,b,c) ace_range((a),(b),(c))
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MIN_MAX_H */
diff --git a/ACE/ace/Module.cpp b/ACE/ace/Module.cpp
new file mode 100644
index 00000000000..78723cf674b
--- /dev/null
+++ b/ACE/ace/Module.cpp
@@ -0,0 +1,273 @@
+// $Id$
+
+#ifndef ACE_MODULE_CPP
+#define ACE_MODULE_CPP
+
+#include "ace/Module.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Stream_Modules.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Module.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Module)
+
+template <ACE_SYNCH_DECL> void
+ACE_Module<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Module<ACE_SYNCH_USE>::writer (ACE_Task<ACE_SYNCH_USE> *q,
+ int flags /* = M_DELETE_WRITER */)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::writer");
+
+ // Close and maybe delete old writer
+ this->close_i (1, flags);
+
+ this->q_pair_[1] = q;
+
+ if (q != 0)
+ {
+ ACE_CLR_BITS (q->flags_, ACE_Task_Flags::ACE_READER);
+ // Set the q's module pointer to point to us.
+ q->mod_ = this;
+ }
+
+ // Don't allow the caller to change the reader status.
+ ACE_SET_BITS (flags_, (flags & M_DELETE_WRITER));
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Module<ACE_SYNCH_USE>::reader (ACE_Task<ACE_SYNCH_USE> *q,
+ int flags /* = M_DELETE_READER */)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::reader");
+
+ // Close and maybe delete old writer
+ this->close_i (0, flags);
+
+ this->q_pair_[0] = q;
+
+ if (q != 0)
+ {
+ ACE_SET_BITS (q->flags_, ACE_Task_Flags::ACE_READER);
+ // Set the q's module pointer to point to us.
+ q->mod_ = this;
+ }
+
+ // don't allow the caller to change the reader status
+ ACE_SET_BITS (flags_, (flags & M_DELETE_READER));
+}
+
+// Link this ACE_Module on top of ACE_Module M.
+
+template <ACE_SYNCH_DECL> void
+ACE_Module<ACE_SYNCH_USE>::link (ACE_Module<ACE_SYNCH_USE> *m)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::link");
+ this->next (m);
+ this->writer ()->next (m->writer ());
+ m->reader ()->next (this->reader ());
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Module<ACE_SYNCH_USE>::open (const ACE_TCHAR *mod_name,
+ ACE_Task<ACE_SYNCH_USE> *writer_q,
+ ACE_Task<ACE_SYNCH_USE> *reader_q,
+ void *arg,
+ int flags /* = M_DELETE */)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::open");
+ this->name (mod_name);
+ this->arg_ = arg;
+
+ // We may already have readers and/or writers.
+ if (this->reader ())
+ this->close_i (0, M_DELETE_READER);
+
+ if (this->writer ())
+ this->close_i (1, M_DELETE_WRITER);
+
+ if (writer_q == 0)
+ {
+ ACE_NEW_RETURN (writer_q,
+ ACE_Thru_Task<ACE_SYNCH_USE>,
+ -1);
+ ACE_SET_BITS (flags, M_DELETE_WRITER);
+ }
+
+ if (reader_q == 0)
+ {
+ ACE_NEW_RETURN (reader_q,
+ ACE_Thru_Task<ACE_SYNCH_USE>,
+ -1);
+ ACE_SET_BITS (flags, M_DELETE_READER);
+ }
+
+ this->reader (reader_q);
+ this->writer (writer_q);
+
+ // Save the flags
+ this->flags_ = flags;
+
+ // Make sure that the memory is allocated before proceding.
+ if (writer_q == 0 || reader_q == 0)
+ {
+ // These calls will delete writer_q and/or reader_q, if
+ // necessary.
+ this->close_i (0, M_DELETE_READER);
+ this->close_i (1, M_DELETE_WRITER);
+
+ errno = ENOMEM;
+ return -1;
+ }
+
+ // Setup back pointers (this must come last, after we've made sure
+ // there's memory allocated here.
+ reader_q->mod_ = this;
+ writer_q->mod_ = this;
+
+ return 0;
+}
+
+// Set and get pointer to sibling ACE_Task in ACE_Module.
+
+template <ACE_SYNCH_DECL> ACE_Task<ACE_SYNCH_USE> *
+ACE_Module<ACE_SYNCH_USE>::sibling (ACE_Task<ACE_SYNCH_USE> *orig)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::sibling");
+ if (this->q_pair_[0] == orig)
+ return this->q_pair_[1];
+ else if (this->q_pair_[1] == orig)
+ return this->q_pair_[0];
+ else
+ return 0;
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Module<ACE_SYNCH_USE>::ACE_Module (void)
+ : flags_ (M_FLAGS_NOT_SET)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::ACE_Module");
+ this->name (ACE_TEXT ("<unknown>"));
+ // Do nothing...
+ this->q_pair_[0] = 0;
+ this->q_pair_[1] = 0;
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Module<ACE_SYNCH_USE>::~ACE_Module (void)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::~ACE_Module");
+
+ // Only close down if we haven't already done so.
+ if (this->reader () || this->writer ())
+ this->close ();
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Module<ACE_SYNCH_USE>::ACE_Module (const ACE_TCHAR *mod_name,
+ ACE_Task<ACE_SYNCH_USE> *writer_q,
+ ACE_Task<ACE_SYNCH_USE> *reader_q,
+ void *args,
+ int flags /* = M_DELETE */)
+ : flags_ (M_FLAGS_NOT_SET)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::ACE_Module");
+
+ this->q_pair_[0] = 0;
+ this->q_pair_[1] = 0;
+
+ if (this->open (mod_name, writer_q, reader_q, args, flags) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Module")));
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Module<ACE_SYNCH_USE>::close (int flags /* = M_DELETE_NONE */)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::close");
+
+ int result = 0;
+
+ // Only pay attention to the flags parameter if we haven't already
+ // set the task delete policies.
+ if (this->flags_ == M_FLAGS_NOT_SET)
+ ACE_SET_BITS (flags_, flags);
+
+ if (this->close_i (0, flags_) == -1)
+ result = -1;
+
+ if (this->close_i (1, flags_) == -1)
+ result = -1;
+
+ return result;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Module<ACE_SYNCH_USE>::close_i (int which,
+ int flags)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::close_i");
+
+ if (this->q_pair_[which] == 0)
+ return 0;
+
+ // Copy task pointer to prevent problems when ACE_Task::close
+ // changes the task pointer
+ ACE_Task<ACE_SYNCH_USE> *task = this->q_pair_[which];
+
+ // Change so that close doesn't get called again from the task base.
+
+ // Now close the task.
+ int result = 0;
+
+ if (task->module_closed () == -1)
+ result = -1;
+
+ task->flush ();
+ task->next (0);
+
+ // Should we also delete it ?
+ if (flags != M_DELETE_NONE
+ && ACE_BIT_ENABLED (flags_, which + 1))
+ {
+ // Only delete the Tasks if there aren't any more threads
+ // running in them.
+ task->wait ();
+
+ // If this assert happens it is likely because the task was
+ // activated with the THR_DETACHED flag, which means that we
+ // can't join() with the thread. Not using THR_DETACHED should
+ // solve this problem.
+ ACE_ASSERT (task->thr_count () == 0);
+
+ delete task;
+ }
+
+ // Set the tasks pointer to 0 so that we don't try to close()
+ // this object again if the destructor gets called.
+ this->q_pair_[which] = 0;
+
+ // Finally remove the delete bit.
+ ACE_CLR_BITS (flags_, which + 1);
+
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_MODULE_CPP */
diff --git a/ACE/ace/Module.h b/ACE/ace/Module.h
new file mode 100644
index 00000000000..a13d88d5f92
--- /dev/null
+++ b/ACE/ace/Module.h
@@ -0,0 +1,215 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Module.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_MODULE_H
+#define ACE_MODULE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Task_T.h"
+#include "ace/os_include/os_dirent.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Module_Base
+ *
+ * @brief Workaround HP/C++ compiler bug with enums in templates.
+ *
+ * Certain C++ compilers, e.g., the HP/UX 10.x and 9.x compilers,
+ * seem to fail if enums are defined inside a template, hence we
+ * have to move them into a base class.
+ */
+class ACE_Export ACE_Module_Base
+{
+public:
+ enum
+ {
+ /// Indicates that the flags have not been set
+ M_FLAGS_NOT_SET = 0,
+
+ /// Indicates that <close> should delete the writer Task.
+ M_DELETE_READER = 1,
+
+ /// Indicates that <close> should delete the reader Task.
+ M_DELETE_WRITER = 2,
+
+ /// Indicates that <close> deletes the Tasks.
+ /**
+ * Don't change this value without updating the same enum in class
+ * ACE_Stream...
+ * The <M_DELETE_READER> and <M_DELETE_WRITER> flags may be or'ed
+ * together.
+ */
+ M_DELETE = 3,
+
+ /// Indicates that <close> should not delete any Tasks.
+ M_DELETE_NONE = 4
+ };
+};
+
+/**
+ * @class ACE_Module
+ *
+ * @brief An abstraction for managing a bi-directional flow of messages.
+ *
+ * This is based on the Module concept in System V Streams,
+ * which contains a pair of Tasks, one for handling upstream
+ * processing, one for handling downstream processing. In
+ * general, you shouldn't subclass from this class, but instead
+ * subclass from the ACE_Task.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Module : public ACE_Module_Base
+{
+public:
+ // = Initialization and termination methods.
+ /// Create an empty Module.
+ ACE_Module (void);
+
+ /// Shutdown the Module.
+ virtual ~ACE_Module (void);
+
+ /// Create an initialized module with @a module_name as its identity
+ /// and @a reader and @a writer as its tasks.
+ ACE_Module (const ACE_TCHAR *module_name,
+ ACE_Task<ACE_SYNCH_USE> *writer = 0,
+ ACE_Task<ACE_SYNCH_USE> *reader = 0,
+ void *args = 0,
+ int flags = M_DELETE);
+
+ /**
+ * Initialize the module with <module_name> as its identity
+ * and <reader> and <writer> as its tasks. Previously register
+ * reader or writers or closed down and deleted according to the
+ * value of flags_. Should not be called from within
+ * <ACE_Task::module_closed>.
+ */
+ int open (const ACE_TCHAR *module_name,
+ ACE_Task<ACE_SYNCH_USE> *writer = 0,
+ ACE_Task<ACE_SYNCH_USE> *reader = 0,
+ void *a = 0,
+ int flags = M_DELETE);
+
+ /**
+ * Close down the module and its tasks. The flags argument can be
+ * used to override the default behaviour, which depends on previous
+ * @a flags values in calls to c'tor, <open>, <reader>, and <writer>.
+ * A previous value M_DELETE[_XXX] can not be overridden. Should
+ * not be called from within <ACE_Task::module_closed>.
+ */
+ int close (int flags = M_DELETE_NONE);
+
+ // = ACE_Task manipulation routines
+ /// Get the writer task.
+ ACE_Task<ACE_SYNCH_USE> *writer (void);
+
+ /**
+ * Set the writer task. @a flags can be used to indicate that the
+ * module should delete the writer during a call to close or to the
+ * destructor. If a previous writer exists, it is closed. It may
+ * also be deleted, depending on the old flags_ value. Should not
+ * be called from within <ACE_Task::module_closed>.
+ */
+ void writer (ACE_Task<ACE_SYNCH_USE> *q, int flags = M_DELETE_WRITER);
+
+ /// Get the reader task.
+ ACE_Task<ACE_SYNCH_USE> *reader (void);
+
+ /**
+ * Set the reader task. @a flags can be used to indicate that the
+ * module should delete the reader during a call to close or to the
+ * destructor. If a previous reader exists, it is closed. It may
+ * also be deleted, depending on the old flags_ value. Should not
+ * be called from within <ACE_Task::module_closed>.
+ */
+ void reader (ACE_Task<ACE_SYNCH_USE> *q, int flags = M_DELETE_READER);
+
+ /// Set and get pointer to sibling ACE_Task in an ACE_Module
+ ACE_Task<ACE_SYNCH_USE> *sibling (ACE_Task<ACE_SYNCH_USE> *orig);
+
+ // = Identify the module
+ /// Get the module name.
+ const ACE_TCHAR *name (void) const;
+
+ /// Set the module name.
+ void name (const ACE_TCHAR *);
+
+ // = Argument to the Tasks.
+ /// Get the argument passed to the tasks.
+ void *arg (void) const;
+
+ /// Set the argument passed to the tasks.
+ void arg (void *);
+
+ /// Link to other modules in the ustream stack
+ void link (ACE_Module<ACE_SYNCH_USE> *m);
+
+ /// Get the next pointer to the module above in the stream.
+ ACE_Module<ACE_SYNCH_USE> *next (void);
+
+ /// Set the next pointer to the module above in the stream.
+ void next (ACE_Module<ACE_SYNCH_USE> *m);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Implements the close operation for either the reader or the
+ /// writer task (depending on <which>).
+ int close_i (int which, int flags);
+
+ /// Pair of Tasks that form the "read-side" and "write-side" of the
+ /// ACE_Module partitioning.
+ ACE_Task<ACE_SYNCH_USE> *q_pair_[2];
+
+ /// Name of the ACE_Module.
+ ACE_TCHAR name_[MAXPATHLEN + 1];
+
+ /// Next ACE_Module in the stack.
+ ACE_Module<ACE_SYNCH_USE> *next_;
+
+ /// Argument passed through to the reader and writer task when they
+ /// are opened.
+ void *arg_;
+
+ /// Holds flags which are used to determine if the reader and writer
+ /// task have to be deleted on exit
+ int flags_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Module.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Module.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Module.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MODULE_H */
diff --git a/ACE/ace/Module.inl b/ACE/ace/Module.inl
new file mode 100644
index 00000000000..483d436aa69
--- /dev/null
+++ b/ACE/ace/Module.inl
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <ACE_SYNCH_DECL> ACE_INLINE void *
+ACE_Module<ACE_SYNCH_USE>::arg (void) const
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::arg");
+ return this->arg_;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE void
+ACE_Module<ACE_SYNCH_USE>::arg (void *a)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::arg");
+ this->arg_ = a;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE const ACE_TCHAR *
+ACE_Module<ACE_SYNCH_USE>::name (void) const
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::name");
+ return this->name_;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE void
+ACE_Module<ACE_SYNCH_USE>::name (const ACE_TCHAR *n)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::name");
+ ACE_OS::strsncpy (this->name_, n, MAXPATHLEN);
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE ACE_Task<ACE_SYNCH_USE> *
+ACE_Module<ACE_SYNCH_USE>::writer (void)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::writer");
+ return this->q_pair_[1];
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE ACE_Task<ACE_SYNCH_USE> *
+ACE_Module<ACE_SYNCH_USE>::reader (void)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::reader");
+ return this->q_pair_[0];
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE ACE_Module<ACE_SYNCH_USE> *
+ACE_Module<ACE_SYNCH_USE>::next (void)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::next");
+ return this->next_;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE void
+ACE_Module<ACE_SYNCH_USE>::next (ACE_Module<ACE_SYNCH_USE> *m)
+{
+ ACE_TRACE ("ACE_Module<ACE_SYNCH_USE>::next");
+ this->next_ = m;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Msg_WFMO_Reactor.cpp b/ACE/ace/Msg_WFMO_Reactor.cpp
new file mode 100644
index 00000000000..bbc95b948fa
--- /dev/null
+++ b/ACE/ace/Msg_WFMO_Reactor.cpp
@@ -0,0 +1,85 @@
+// $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.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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)
+{
+}
+
+DWORD
+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.
+ return ::MsgWaitForMultipleObjectsEx (this->handler_rep_.max_handlep1 (),
+ this->handler_rep_.handles (),
+ timeout,
+ QS_ALLINPUT,
+ alertable);
+}
+
+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, 0, 0, 0, PM_REMOVE))
+ {
+ ::TranslateMessage (&msg);
+ if (msg.message == WM_QUIT)
+ {
+ // Should inform the main thread
+ ::PostQuitMessage (LOWORD (msg.wParam));
+ return -1;
+ }
+
+ ::DispatchMessage (&msg);
+ ++number_of_messages;
+ }
+
+ return number_of_messages;
+}
+
+DWORD
+ACE_Msg_WFMO_Reactor::poll_remaining_handles (DWORD slot)
+{
+ return ::MsgWaitForMultipleObjects (this->handler_rep_.max_handlep1 () - slot,
+ this->handler_rep_.handles () + slot,
+ FALSE,
+ 0,
+ QS_ALLINPUT);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && !ACE_LACKS_MSG_WFMO */
diff --git a/ACE/ace/Msg_WFMO_Reactor.h b/ACE/ace/Msg_WFMO_Reactor.h
new file mode 100644
index 00000000000..cc6746d8a26
--- /dev/null
+++ b/ACE/ace/Msg_WFMO_Reactor.h
@@ -0,0 +1,120 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_MSG_WFMO)
+
+#include "ace/WFMO_Reactor.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a size. Two slots will be
+ * added to the @a 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 @a max_wait_time before
+ * returning. It will return earlier if timer events, I/O events,
+ * window events, or signal events occur. Note that @a max_wait_time
+ * can be 0, in which case this method blocks indefinitely until
+ * events occur.
+ *
+ * @a 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,
+ * @a 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_Handlers that were
+ * dispatched, 0 if the @a 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
+ * @a 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 DWORD wait_for_multiple_events (int timeout,
+ int alertable);
+
+ /// Check for activity on remaining handles.
+ virtual DWORD poll_remaining_handles (DWORD index);
+
+ /// Dispatches window messages.
+ virtual int dispatch_window_messages (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Msg_WFMO_Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_WIN32 && !ACE_LACKS_MSG_WFMO */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MSG_WFMO_REACTOR_H */
diff --git a/ACE/ace/Msg_WFMO_Reactor.inl b/ACE/ace/Msg_WFMO_Reactor.inl
new file mode 100644
index 00000000000..be021dc58a5
--- /dev/null
+++ b/ACE/ace/Msg_WFMO_Reactor.inl
@@ -0,0 +1,35 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_MSG_WFMO)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && !ACE_LACKS_MSG_WFMO */
diff --git a/ACE/ace/Multihomed_INET_Addr.cpp b/ACE/ace/Multihomed_INET_Addr.cpp
new file mode 100644
index 00000000000..131adbe070e
--- /dev/null
+++ b/ACE/ace/Multihomed_INET_Addr.cpp
@@ -0,0 +1,300 @@
+// $Id$
+
+// Extends ACE_INET_Addr with support for multi-homed addresses.
+
+#include "ace/Multihomed_INET_Addr.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Multihomed_INET_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Multihomed_INET_Addr,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Multihomed_INET_Addr)
+
+// Default constructor
+
+ACE_Multihomed_INET_Addr::ACE_Multihomed_INET_Addr (void)
+ : secondaries_ (0)
+{
+ ACE_TRACE ("ACE_Multihomed_INET_Addr::ACE_Multihomed_INET_Addr");
+}
+
+ACE_Multihomed_INET_Addr::ACE_Multihomed_INET_Addr (const char address[])
+ : ACE_INET_Addr (address),
+ secondaries_ (0)
+{
+}
+
+ACE_Multihomed_INET_Addr::ACE_Multihomed_INET_Addr(u_short port_number,
+ const char host_name[],
+ int encode,
+ int address_family,
+ const char *(secondary_host_names[]),
+ size_t size){
+
+ // Initialize the primary INET addr
+ ACE_INET_Addr::set(port_number, host_name, encode, address_family);
+
+ // check for secondary INET addrs
+ if (secondary_host_names && size){
+ // we have a non-zero pointer and size
+ this->secondaries_.size(size); // size the array
+
+ size_t next_empty_slot = 0;
+ for (size_t i = 0; i < size; ++i) {
+ int ret = this->secondaries_[next_empty_slot].set(port_number,
+ secondary_host_names[i],
+ encode,
+ address_family);
+ if (ret) {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Invalid INET addr (%s:%u) will be ignored\n"),
+ ACE_TEXT_CHAR_TO_TCHAR (secondary_host_names[i]), port_number));
+ this->secondaries_.size(this->secondaries_.size() - 1);
+ }
+ else
+ ++next_empty_slot;
+ }
+ }
+
+ return;
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_Multihomed_INET_Addr::ACE_Multihomed_INET_Addr(u_short port_number,
+ const wchar_t host_name[],
+ int encode,
+ int address_family,
+ const wchar_t *(secondary_host_names[]),
+ size_t size){
+
+ // Initialize the primary INET addr
+ ACE_INET_Addr::set(port_number, host_name, encode, address_family);
+
+ // check for secondary INET addrs
+ if (secondary_host_names && size){
+ // we have a non-zero pointer and size
+ this->secondaries_.size(size); // size the array
+
+ size_t next_empty_slot = 0;
+ for (size_t i = 0; i < size; ++i) {
+ int ret = this->secondaries_[next_empty_slot].set(port_number,
+ secondary_host_names[i],
+ encode,
+ address_family);
+ if (ret) {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Invalid INET addr (%s:%u) will be ignored\n"),
+ ACE_TEXT_WCHAR_TO_TCHAR (secondary_host_names[i]), port_number));
+ this->secondaries_.size(this->secondaries_.size() - 1);
+ }
+ else
+ ++next_empty_slot;
+ }
+ }
+
+ return;
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_Multihomed_INET_Addr::ACE_Multihomed_INET_Addr(u_short port_number,
+ ACE_UINT32 primary_ip_addr,
+ int encode,
+ const ACE_UINT32 *secondary_ip_addrs,
+ size_t size){
+
+ // Initialize the primary INET addr
+ ACE_INET_Addr::set(port_number, primary_ip_addr, encode);
+
+ // check for secondary INET addrs
+ if (secondary_ip_addrs && size){
+ // we have a non-zero pointer and size
+ this->secondaries_.size(size); // size the array
+
+ size_t next_empty_slot = 0;
+ for (size_t i = 0; i < size; ++i) {
+ int const ret = this->secondaries_[next_empty_slot].set(port_number,
+ secondary_ip_addrs[i],
+ encode);
+
+ if (ret) {
+ ACE_DEBUG ((LM_DEBUG,
+ "Invalid INET addr (%u:%u) will be ignored\n",
+ secondary_ip_addrs[i], port_number));
+ this->secondaries_.size(this->secondaries_.size() - 1);
+ }
+ else
+ ++next_empty_slot;
+ }
+ }
+
+ return;
+}
+
+// Set implementations (NEED BETTER COMMENT HERE)
+int
+ACE_Multihomed_INET_Addr::set (u_short port_number,
+ const char host_name[],
+ int encode,
+ int address_family,
+ const char *(secondary_host_names[]),
+ size_t size)
+{
+ this->secondaries_.size(size);
+
+ for (size_t i = 0; i < size; ++i) {
+
+ int const ret = this->secondaries_[i].set(port_number,
+ secondary_host_names[i],
+ encode,
+ address_family);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ return ACE_INET_Addr::set(port_number, host_name, encode, address_family);
+}
+
+#if defined (ACE_HAS_WCHAR)
+//
+// WCHAR version of ::set
+//
+int
+ACE_Multihomed_INET_Addr::set (u_short port_number,
+ const wchar_t host_name[],
+ int encode,
+ int address_family,
+ const wchar_t *(secondary_host_names[]),
+ size_t size)
+{
+ this->secondaries_.size(size);
+
+ for (size_t i = 0; i < size; ++i) {
+
+ int ret = this->secondaries_[i].set(port_number,
+ secondary_host_names[i],
+ encode,
+ address_family);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ return ACE_INET_Addr::set(port_number, host_name, encode, address_family);
+}
+#endif /* ACE_HAS_WCHAR */
+
+int
+ACE_Multihomed_INET_Addr::set (u_short port_number,
+ ACE_UINT32 primary_ip_addr,
+ int encode,
+ const ACE_UINT32 *secondary_ip_addrs,
+ size_t size)
+{
+ this->secondaries_.size(size);
+
+ for (size_t i = 0; i < size; ++i) {
+
+ int ret = this->secondaries_[i].set(port_number,
+ secondary_ip_addrs[i],
+ encode);
+
+ if (ret) {
+ return ret;
+ }
+ }
+
+ return ACE_INET_Addr::set(port_number, primary_ip_addr, encode);
+}
+
+void
+ACE_Multihomed_INET_Addr::set_port_number (u_short port_number, int encode)
+{
+ size_t i = 0;
+ while (i < secondaries_.size())
+ secondaries_[i++].set_port_number(port_number, encode);
+
+ this->ACE_INET_Addr::set_port_number(port_number, encode);
+}
+
+int
+ACE_Multihomed_INET_Addr::get_secondary_addresses(ACE_INET_Addr *secondary_addrs,
+ size_t size) const
+{
+ size_t top =
+ size < this->secondaries_.size() ?
+ size : this->secondaries_.size();
+
+ for (size_t i = 0; i < top; ++i)
+ {
+
+ int ret =
+ secondary_addrs[i].set (this->secondaries_[i]);
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+void
+ACE_Multihomed_INET_Addr::get_addresses(sockaddr_in *addrs,
+ size_t size) const
+{
+ // Copy primary address to the first slot of the user-supplied array
+ if (size > 0) {
+ addrs[0] = *reinterpret_cast<sockaddr_in*> (this->get_addr ());
+ }
+
+ // Copy secondary addresses to remaining slots of the user-supplied
+ // array. Secondary address [i] is copied to slot [i+1]
+
+ size_t top = size - 1 < this->secondaries_.size() ?
+ size - 1 : this->secondaries_.size();
+
+ for (size_t i = 0; i < top; ++i) {
+ addrs[i+1] =
+ *reinterpret_cast<sockaddr_in*> (this->secondaries_[i].get_addr());
+ }
+}
+
+#if defined (ACE_HAS_IPV6)
+void
+ACE_Multihomed_INET_Addr::get_addresses(sockaddr_in6 *addrs,
+ size_t size) const
+{
+ // Copy primary address to the first slot of the user-supplied array
+ if (size > 0)
+ {
+ addrs[0] = *reinterpret_cast<sockaddr_in6*> (this->get_addr ());
+ }
+
+ // Copy secondary addresses to remaining slots of the user-supplied
+ // array. Secondary address [i] is copied to slot [i+1]
+ size_t top =
+ size - 1 < this->secondaries_.size() ?
+ size - 1 : this->secondaries_.size();
+
+ for (size_t i = 0; i < top; ++i)
+ {
+ addrs[i+1] =
+ *reinterpret_cast<sockaddr_in6*> (this->secondaries_[i].get_addr());
+ }
+}
+#endif /* ACE_HAS_IPV6 */
+
+
+ACE_Multihomed_INET_Addr::~ACE_Multihomed_INET_Addr (void)
+{
+
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Multihomed_INET_Addr.h b/ACE/ace/Multihomed_INET_Addr.h
new file mode 100644
index 00000000000..34b99d2c49e
--- /dev/null
+++ b/ACE/ace/Multihomed_INET_Addr.h
@@ -0,0 +1,198 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Multihomed_INET_Addr.h
+ *
+ * $Id$
+ *
+ * @author Edward R. Mulholland <emulholl@atl.lmco.com>
+ */
+//=============================================================================
+
+#ifndef ACE_MULTIHOMED_INET_ADDR_H
+#define ACE_MULTIHOMED_INET_ADDR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+#include "ace/Containers_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Multihomed_INET_Addr
+ *
+ * @brief Extends ACE_INET_Addr with support for multi-homed
+ * addresses.
+ */
+class ACE_Export ACE_Multihomed_INET_Addr : public ACE_INET_Addr
+{
+public:
+ // = Initialization methods.
+
+ /// Default constructor.
+ ACE_Multihomed_INET_Addr (void);
+
+ /**
+ * Initializes an ACE_Multihomed_INET_Addr from the @a 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 @a address it
+ * is assumed to be a port number, with the IP address being
+ * INADDR_ANY.
+ */
+ explicit ACE_Multihomed_INET_Addr (const char address[]);
+
+ /**
+ * Constructs an ACE_Multihomed_INET_Addr from a @a port_number, a
+ * @a primary_host_name, and an array of <secondary_host_names>.
+ * @a size is taken to be the length of the array. If @a encode is
+ * non-zero, then @a port_number is converted into network byte
+ * order; otherwise it is assumed to be in network byte order
+ * already and is passed straight through. @a 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.
+ */
+ ACE_Multihomed_INET_Addr(u_short port_number,
+ const char primary_host_name[],
+ int encode = 1,
+ int address_family = AF_UNSPEC,
+ const char *(secondary_host_names[]) = 0,
+ size_t size = 0);
+
+ /**
+ * Constructs an ACE_Multihomed_INET_Addr from a @a port_number,
+ * a @a primary_ip_addr, and an array of @a secondary_ip_addrs. @a
+ * size is taken to be the length of the array. If @a encode is
+ * non-zero, then the port number and the IP addresses are converted
+ * into network byte order; otherwise they are assumed to be in
+ * network byte order already and are passed straight through.
+ */
+ ACE_Multihomed_INET_Addr(u_short port_number,
+ ACE_UINT32 primary_ip_addr = INADDR_ANY,
+ int encode = 1,
+ const ACE_UINT32 *secondary_ip_addrs = 0,
+ size_t size = 0);
+
+#if defined (ACE_HAS_WCHAR)
+ /**
+ * WCHAR versions of the methods that take char's as arguments.
+ */
+ ACE_Multihomed_INET_Addr(u_short port_number,
+ const wchar_t primary_host_name[],
+ int encode = 1,
+ int address_family = AF_UNSPEC,
+ const wchar_t *(secondary_host_names[]) = 0,
+ size_t size = 0);
+ int set (u_short port_number,
+ const wchar_t primary_host_name[],
+ int encode = 1,
+ int address_family = AF_UNSPEC,
+ const wchar_t *(secondary_host_names[]) = 0,
+ size_t size = 0);
+
+#endif /* ACE_HAS_WCHAR */
+
+ /// Use compiler-generated copy constructor.
+
+ /// Use compiler-generated assignment operator.
+
+ /// Default dtor.
+ ~ACE_Multihomed_INET_Addr (void);
+
+ // = Direct initialization methods.
+
+ // These methods are useful after the object has been constructed.
+
+ /**
+ * Initializes an ACE_Multihomed_INET_Addr from a @a port_number, a
+ * @a primary_host_name, and an array of <secondary_host_names>.
+ * @a size is taken to be the length of the array. If @a encode is
+ * non-zero, then @a port_number is converted into network byte
+ * order; otherwise it is assumed to be in network byte order
+ * already and is passed straight through. @a 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 primary_host_name[],
+ int encode = 1,
+ int address_family = AF_UNSPEC,
+ const char *(secondary_host_names[]) = 0,
+ size_t size = 0);
+
+ /**
+ * Initializes an ACE_Multihomed_INET_Addr from a @a port_number,
+ * a @a primary_ip_addr, and an array of @a secondary_ip_addrs. @a
+ * size is taken to be the length of the array. If @a encode is
+ * non-zero, then the port number and the IP addresses 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 primary_ip_addr = INADDR_ANY,
+ int encode = 1,
+ const ACE_UINT32 *secondary_ip_addrs = 0,
+ size_t size = 0);
+
+ /**
+ * Sets the port number without affecting the host name. The port
+ * numbers of the primary address, and of any and all secondary
+ * addresses, are affected. If @a encode is enabled, then
+ * @a port_number is converted into network byte order, otherwise it
+ * is assumed to be in network byte order already and is passed
+ * straight through.
+ */
+ void set_port_number (u_short port_number,
+ int encode = 1);
+
+ // = Accessor methods.
+
+ /**
+ * Returns the number of secondary addresses.
+ */
+ size_t get_num_secondary_addresses () const;
+
+ /**
+ * Initialize user-supplied array @a secondary_addrs with the current
+ * secondary addresses. @a size is taken as the size of this array.
+ */
+ int get_secondary_addresses(ACE_INET_Addr *secondary_addrs,
+ size_t size) const;
+
+ /**
+ * Initialize user-supplied array @a addrs with the the current
+ * primary and secondary addresses. @a size is taken as the size of
+ * this array.
+ */
+ void get_addresses(sockaddr_in *addrs,
+ size_t size) const;
+
+#if defined (ACE_HAS_IPV6)
+
+ /// IPV6 version of the above.
+ void get_addresses(sockaddr_in6 *addrs,
+ size_t size) const;
+#endif /* ACE_HAS_IPV6 */
+
+private:
+ ACE_Array<ACE_INET_Addr> secondaries_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Multihomed_INET_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MULTIHOMED_INET_ADDR_H */
diff --git a/ACE/ace/Multihomed_INET_Addr.inl b/ACE/ace/Multihomed_INET_Addr.inl
new file mode 100644
index 00000000000..50f67c01191
--- /dev/null
+++ b/ACE/ace/Multihomed_INET_Addr.inl
@@ -0,0 +1,15 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Accessor implementations
+ACE_INLINE
+size_t
+ACE_Multihomed_INET_Addr::get_num_secondary_addresses() const
+{
+ return this->secondaries_.size();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Mutex.cpp b/ACE/ace/Mutex.cpp
new file mode 100644
index 00000000000..406c1b3ed1c
--- /dev/null
+++ b/ACE/ace/Mutex.cpp
@@ -0,0 +1,125 @@
+// $Id$
+
+#include "ace/Mutex.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/sys/os_mman.h"
+
+
+ACE_RCSID (ace,
+ Mutex,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Mutex)
+
+void
+ACE_Mutex::dump (void) const
+{
+// ACE_TRACE ("ACE_Mutex::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("lockname_ = %s\n"), this->lockname_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("process_lock_ = %x\n"), this->process_lock_));
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_Mutex::ACE_Mutex (int type, const ACE_TCHAR *name,
+ ACE_mutexattr_t *arg, mode_t mode)
+ :
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ process_lock_ (0),
+ lockname_ (0),
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ removed_ (false)
+{
+ // ACE_TRACE ("ACE_Mutex::ACE_Mutex");
+
+ // These platforms need process-wide mutex to be in shared memory.
+#if defined(ACE_HAS_PTHREADS) || defined (ACE_HAS_STHREADS)
+ if (type == USYNC_PROCESS)
+ {
+ // Let's see if the shared memory entity already exists.
+ ACE_HANDLE fd = ACE_OS::shm_open (name, O_RDWR | O_CREAT | O_EXCL, mode);
+ if (fd == ACE_INVALID_HANDLE)
+ {
+ if (errno == EEXIST)
+ fd = ACE_OS::shm_open (name, O_RDWR | O_CREAT, mode);
+ else
+ return;
+ }
+ else
+ {
+ // We own this shared memory object! Let's set its size.
+ if (ACE_OS::ftruncate (fd,
+ sizeof (ACE_mutex_t)) == -1)
+ {
+ ACE_OS::close (fd);
+ return;
+ }
+ this->lockname_ = ACE_OS::strdup (name);
+ if (this->lockname_ == 0)
+ {
+ ACE_OS::close (fd);
+ return;
+ }
+ }
+
+ this->process_lock_ =
+ (ACE_mutex_t *) ACE_OS::mmap (0,
+ sizeof (ACE_mutex_t),
+ PROT_RDWR,
+ MAP_SHARED,
+ fd,
+ 0);
+ ACE_OS::close (fd);
+ if (this->process_lock_ == MAP_FAILED)
+ return;
+
+ if (this->lockname_
+ && ACE_OS::mutex_init (this->process_lock_,
+ type,
+ name,
+ arg) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Mutex::ACE_Mutex")));
+ return;
+ }
+ }
+ else
+ {
+ // local mutex init if USYNC_PROCESS flag is not enabled.
+#else
+ ACE_UNUSED_ARG (mode);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+
+ if (ACE_OS::mutex_init (&this->lock_,
+ type,
+ name,
+ arg) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Mutex::ACE_Mutex")));
+#if defined(ACE_HAS_PTHREADS) || defined (ACE_HAS_STHREADS)
+ }
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+}
+
+ACE_Mutex::~ACE_Mutex (void)
+{
+// ACE_TRACE ("ACE_Mutex::~ACE_Mutex");
+ this->remove ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Mutex.h b/ACE/ace/Mutex.h
new file mode 100644
index 00000000000..e876a09d3f8
--- /dev/null
+++ b/ACE/ace/Mutex.h
@@ -0,0 +1,192 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Mutex.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_MUTEX_H
+#define ACE_MUTEX_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_Thread.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/os_include/os_fcntl.h"
+
+# if !defined (ACE_DEFAULT_MUTEX_A)
+# define ACE_DEFAULT_MUTEX_A "ACE_MUTEX"
+# endif /* ACE_DEFAULT_MUTEX_A */
+
+# if defined (ACE_HAS_WCHAR)
+# define ACE_DEFAULT_MUTEX_W ACE_TEXT_WIDE(ACE_DEFAULT_MUTEX_A)
+# endif /* ACE_HAS_WCHAR */
+
+# define ACE_DEFAULT_MUTEX ACE_TEXT (ACE_DEFAULT_MUTEX_A)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Mutex
+ *
+ * @brief @c ACE_Mutex wrapper (valid in same process or across
+ * processes (depending on @a TYPE flag)). In general,
+ * however, we recommend using @a ACE_Process_Mutex or @a
+ * ACE_Thread_Mutex rather than @a ACE_Mutex.
+ */
+class ACE_Export ACE_Mutex
+{
+public:
+ /// Initialize the mutex.
+ ACE_Mutex (int type = USYNC_THREAD,
+ const ACE_TCHAR *name = 0,
+ ACE_mutexattr_t *arg = 0,
+ mode_t mode = ACE_DEFAULT_FILE_PERMS);
+
+ /// Implicitly destroy the mutex.
+ ~ACE_Mutex (void);
+
+ /// Explicitly destroy the mutex.
+ /**
+ * @note Only one thread should call this method since it doesn't
+ * protect against race conditions.
+ */
+ int remove (void);
+
+ /// Acquire lock ownership (wait on queue if necessary).
+ int acquire (void);
+
+ /// Block the thread until the mutex is acquired or @a tv times out,
+ /// in which case -1 is returned and @c errno == @c ETIME.
+ /**
+ * @note @a tv is assumed to be in "absolute" rather than
+ * " relative" time. The value of @a tv is updated upon return
+ * to show the actual(absolute) acquisition time.
+ */
+ int acquire (ACE_Time_Value &tv);
+
+ /// Block the thread until the mutex is acquired or @a *tv times
+ /// out, in which case -1 is returned and @c errno == @c ETIME.
+ /**
+ * If @a tv == 0 then call @c acquire() directly. Otherwise, block
+ * the thread until the mutex is acquired or @a tv times out, in
+ * which case -1 is returned and @c errno == @c ETIME.
+ *
+ * @note @a *tv is assumed to be in "absolute" rather than
+ * "relative" time. The value of @a *tv is updated upon
+ * return to show the actual (absolute) acquisition time.
+ */
+ int acquire (ACE_Time_Value *tv);
+
+ /// Conditionally acquire lock (i.e., don't wait on queue).
+ /**
+ * @return -1 on failure. If we "failed" because someone
+ * else already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire (void);
+
+ /// Release lock and unblock a thread at head of queue.
+ int release (void);
+
+ /// Acquire mutex ownership.
+ /**
+ * This calls @c acquire and is only here to make the @c ACE_Mutex
+ * interface consistent with the other synchronization APIs.
+ */
+ int acquire_read (void);
+
+ /// Acquire mutex ownership.
+ /**
+ * This calls @c acquire and is only here to make the @c ACE_Mutex
+ * interface consistent with the other synchronization APIs.
+ */
+ int acquire_write (void);
+
+ /// Conditionally acquire mutex (i.e., won't block).
+ /**
+ * This calls @c tryacquire and is only here to make the @c ACE_Mutex
+ * interface consistent with the other synchronization APIs.
+ *
+ * @return -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_read (void);
+
+ /// Conditionally acquire mutex (i.e., won't block).
+ /**
+ * This calls @c tryacquire and is only here to make the @c ACE_Mutex
+ * interface consistent with the other synchronization APIs.
+ *
+ * @return -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_write (void);
+
+ /**
+ * This is only here for consistency with the other synchronization
+ * APIs and usability with Lock adapters. Assumes the caller already has
+ * acquired the mutex and returns 0 in all cases.
+ */
+ int tryacquire_write_upgrade (void);
+
+ /// Return the underlying mutex.
+ const ACE_mutex_t &lock (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // = This should be protected but some C++ compilers complain...
+public:
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ /// This lock resides in shared memory.
+ ACE_mutex_t *process_lock_;
+
+ /**
+ * Remember the name of the mutex if we created it so we can unlink
+ * it when we go away (only the actor that initialized the memory
+ * can destroy it).
+ */
+ const ACE_TCHAR *lockname_;
+#endif /* ACE_HAS_PTHREADS */
+
+ /// Mutex type supported by the OS.
+ ACE_mutex_t lock_;
+
+ /// Keeps track of whether @c remove has been called yet to avoid
+ /// multiple @c remove calls, e.g., explicitly and implicitly in the
+ /// destructor. This flag isn't protected by a lock, so make sure
+ /// that you don't have multiple threads simultaneously calling
+ /// @c remove on the same object, which is a bad idea anyway.
+ bool removed_;
+
+private:
+ // Prevent assignment and initialization.
+ void operator= (const ACE_Mutex &);
+ ACE_Mutex (const ACE_Mutex &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_MUTEX_H */
diff --git a/ACE/ace/Mutex.inl b/ACE/ace/Mutex.inl
new file mode 100644
index 00000000000..eb09217501d
--- /dev/null
+++ b/ACE/ace/Mutex.inl
@@ -0,0 +1,175 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#include "ace/OS_NS_sys_mman.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Mutex::acquire_read (void)
+{
+// ACE_TRACE ("ACE_Mutex::acquire_read");
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_lock (this->process_lock_);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return ACE_OS::mutex_lock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Mutex::acquire_write (void)
+{
+// ACE_TRACE ("ACE_Mutex::acquire_write");
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_lock (this->process_lock_);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return ACE_OS::mutex_lock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Mutex::tryacquire_read (void)
+{
+// ACE_TRACE ("ACE_Mutex::tryacquire_read");
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_trylock (this->process_lock_);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return ACE_OS::mutex_trylock (&this->lock_);
+}
+
+ACE_INLINE const ACE_mutex_t &
+ACE_Mutex::lock (void) const
+{
+// ACE_TRACE ("ACE_Mutex::lock");
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return *this->process_lock_;
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return this->lock_;
+}
+
+ACE_INLINE int
+ACE_Mutex::tryacquire_write (void)
+{
+// ACE_TRACE ("ACE_Mutex::tryacquire_write");
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_trylock (this->process_lock_);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return ACE_OS::mutex_trylock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Mutex::tryacquire_write_upgrade (void)
+{
+// ACE_TRACE ("ACE_Mutex::tryacquire_write_upgrade");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Mutex::acquire (void)
+{
+// ACE_TRACE ("ACE_Mutex::acquire");
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_lock (this->process_lock_);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return ACE_OS::mutex_lock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Mutex::acquire (ACE_Time_Value &tv)
+{
+ // ACE_TRACE ("ACE_Mutex::acquire");
+ #if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_lock (this->process_lock_, tv);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS*/
+ return ACE_OS::mutex_lock (&this->lock_, tv);
+}
+
+ACE_INLINE int
+ACE_Mutex::acquire (ACE_Time_Value *tv)
+{
+ #if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_lock (this->process_lock_, tv);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS*/
+ return ACE_OS::mutex_lock (&this->lock_, tv);
+}
+
+ACE_INLINE int
+ACE_Mutex::tryacquire (void)
+{
+// ACE_TRACE ("ACE_Mutex::tryacquire");
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_trylock (this->process_lock_);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return ACE_OS::mutex_trylock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Mutex::release (void)
+{
+// ACE_TRACE ("ACE_Mutex::release");
+#if defined (ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
+ if (this->process_lock_)
+ return ACE_OS::mutex_unlock (this->process_lock_);
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return ACE_OS::mutex_unlock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Mutex::remove (void)
+{
+// ACE_TRACE ("ACE_Mutex::remove");
+ int result = 0;
+#if defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_STHREADS)
+ // In the case of a interprocess mutex, the owner is the first
+ // process that created the shared memory object. In this case, the
+ // lockname_ pointer will be non-zero (points to allocated memory
+ // for the name). Owner or not, the memory needs to be unmapped
+ // from the process. If we are the owner, the file used for
+ // shm_open needs to be deleted as well.
+ if (this->process_lock_)
+ {
+ if (this->removed_ == false)
+ {
+ this->removed_ = true;
+ // Only destroy the lock if we're the ones who initialized
+ // it.
+ if (!this->lockname_)
+ ACE_OS::munmap ((void *) this->process_lock_,
+ sizeof (ACE_mutex_t));
+ else
+ {
+ result = ACE_OS::mutex_destroy (this->process_lock_);
+ ACE_OS::munmap ((void *) this->process_lock_,
+ sizeof (ACE_mutex_t));
+ ACE_OS::shm_unlink (this->lockname_);
+ ACE_OS::free (
+ static_cast<void *> (
+ const_cast<ACE_TCHAR *> (this->lockname_)));
+ }
+ }
+ }
+ else
+ {
+#else /* !ACE_HAS_PTHREADS && !ACE_HAS_STHREADS */
+ if (this->removed_ == false)
+ {
+ this->removed_ = true;
+ result = ACE_OS::mutex_destroy (&this->lock_);
+ }
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+#if defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_STHREADS)
+ }
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_STHREADS */
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/NT_Service.cpp b/ACE/ace/NT_Service.cpp
new file mode 100644
index 00000000000..3e04fe5a64e
--- /dev/null
+++ b/ACE/ace/NT_Service.cpp
@@ -0,0 +1,618 @@
+// $Id$
+
+#include "ace/config-all.h"
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES)
+
+#include "ace/NT_Service.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/NT_Service.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/Service_Object.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_NT_Service)
+
+// ACE_NT_Service destructor.
+
+ACE_NT_Service::~ACE_NT_Service (void)
+{
+ if (this->svc_sc_handle_ != 0)
+ {
+ CloseServiceHandle (this->svc_sc_handle_);
+ this->svc_sc_handle_ = 0;
+ }
+ delete [] this->desc_;
+ delete [] this->name_;
+ delete [] this->host_;
+}
+
+// This default implementation of ACE_NT_Service::open sets the
+// service's status to START_PENDING with the estimated time until
+// STARTED set to the value given when this object was constructed.
+// Then the svc function is called, which implements the guts of the
+// service. Note that this function is running in a thread created by
+// the OS, not by ACE_Thread_Manager. The thread manager does not
+// know anything about this thread. The service can, however, use
+// ACE_Thread_Manager to start more threads if desired. When the svc
+// function returns, the service status is set to STOPPED, and exit
+// codes set based on errno/GetLastError if the svc function returns
+// -1.
+//
+// The svc function is expected to set the service status to SERVICE_RUNNING
+// after it initializes.
+//
+// The handle_control function will be called for each time there is a
+// request for the service. It is up to that function and svc to
+// cooperate to both respond appropriately to the request (by at least
+// updating the service's status) and to fulfill the request.
+
+int
+ACE_NT_Service::open (void *args)
+{
+ ACE_UNUSED_ARG (args);
+ this->report_status (SERVICE_START_PENDING, 0);
+
+ int svc_return = this->svc ();
+ if (svc_return == 0)
+ {
+ this->svc_status_.dwWin32ExitCode = NO_ERROR;
+ this->svc_status_.dwServiceSpecificExitCode = 0;
+ }
+ else
+ {
+ if (errno == 0)
+ {
+ this->svc_status_.dwWin32ExitCode = GetLastError ();
+ }
+ else
+ {
+ this->svc_status_.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
+ this->svc_status_.dwServiceSpecificExitCode = errno;
+ }
+ }
+
+ return svc_return;
+
+}
+
+int
+ACE_NT_Service::fini (void)
+{
+ return this->report_status (SERVICE_STOPPED, 0);
+}
+
+
+void
+ACE_NT_Service::handle_control (DWORD control_code)
+{
+ switch (control_code)
+ {
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ this->stop_requested (control_code);
+ break;
+
+ case SERVICE_CONTROL_PAUSE:
+ this->pause_requested (control_code);
+ break;
+
+ case SERVICE_CONTROL_CONTINUE:
+ this->continue_requested (control_code);
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ this->interrogate_requested (control_code);
+ break;
+ }
+}
+
+void
+ACE_NT_Service::stop_requested (DWORD)
+{
+ this->report_status (SERVICE_STOP_PENDING);
+ /* how to cancel? */
+}
+
+void
+ACE_NT_Service::pause_requested (DWORD)
+{
+ this->report_status (SERVICE_PAUSE_PENDING);
+ this->suspend ();
+ this->report_status (SERVICE_PAUSED);
+}
+
+void
+ACE_NT_Service::continue_requested (DWORD)
+{
+ this->report_status (SERVICE_CONTINUE_PENDING);
+ this->resume ();
+ this->report_status (SERVICE_RUNNING);
+}
+
+void
+ACE_NT_Service::interrogate_requested (DWORD)
+{
+ this->report_status (0);
+}
+
+void
+ACE_NT_Service::name (const ACE_TCHAR *name, const ACE_TCHAR *desc)
+{
+ delete [] this->desc_;
+ delete [] this->name_;
+
+ if (desc == 0)
+ desc = name;
+
+ this->name_ = ACE::strnew (name);
+ this->desc_ = ACE::strnew (desc);
+}
+
+void
+ACE_NT_Service::host (const ACE_TCHAR *host)
+{
+ delete [] this->host_;
+
+ if (this->svc_sc_handle_ != 0)
+ {
+ CloseServiceHandle (this->svc_sc_handle_);
+ this->svc_sc_handle_ = 0;
+ }
+
+ if (host == 0)
+ {
+ this->host_ = 0;
+ }
+ else
+ {
+ this->host_ = ACE::strnew (host);
+ }
+}
+
+int
+ACE_NT_Service::insert (DWORD start_type,
+ DWORD error_control,
+ const ACE_TCHAR *exe_path,
+ const ACE_TCHAR *group_name,
+ LPDWORD tag_id,
+ const ACE_TCHAR *dependencies,
+ const ACE_TCHAR *account_name,
+ const ACE_TCHAR *password,
+ DWORD desired_access)
+{
+ ACE_TCHAR this_exe[MAXPATHLEN + 2];
+
+ // Insure ACE_OS::last_error finds GetLastError unless we set errno.
+ errno = 0;
+
+ if (exe_path == 0)
+ {
+ if (ACE_TEXT_GetModuleFileName (0, this_exe + 1, MAXPATHLEN) == 0)
+ return -1;
+ // Make sure that this_exe is quoted
+ this_exe[0] = ACE_TEXT ('\"');
+ ACE_OS::strcat (this_exe, ACE_TEXT ("\""));
+ exe_path = this_exe;
+ }
+
+ SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (),
+ 0,
+ SC_MANAGER_ALL_ACCESS);
+ if (sc_mgr == 0)
+ return -1;
+
+ SC_HANDLE sh = ACE_TEXT_CreateService (sc_mgr,
+ this->name (),
+ this->desc (),
+ desired_access,
+ this->svc_status_.dwServiceType,
+ start_type,
+ error_control,
+ exe_path,
+ group_name,
+ tag_id,
+ dependencies,
+ account_name,
+ password);
+ // If there was an error, stash GetLastError before CloseServiceHandle
+ // smashes it. ACE_OS::last_error will find the saved error value.
+ if (sh == 0)
+ ACE_OS::set_errno_to_last_error ();
+
+ CloseServiceHandle (sc_mgr);
+
+ if (sh == 0)
+ return -1;
+
+ if (this->svc_sc_handle_ != 0)
+ CloseServiceHandle (this->svc_sc_handle_);
+ this->svc_sc_handle_ = sh;
+
+ return 0;
+
+}
+
+int
+ACE_NT_Service::remove (void)
+{
+ if (this->svc_sc_handle () == 0)
+ return -1;
+
+ if (DeleteService (this->svc_sc_handle()) == 0
+ && GetLastError () != ERROR_SERVICE_MARKED_FOR_DELETE)
+ return -1;
+
+ return 0;
+}
+
+// Sets the startup type for the service. Returns -1 on error, 0 on
+// success.
+int
+ACE_NT_Service::startup (DWORD startup)
+{
+ SC_HANDLE svc = this->svc_sc_handle ();
+ if (svc == 0)
+ return -1;
+
+ BOOL ok =
+ ChangeServiceConfig (svc,
+ (DWORD) SERVICE_NO_CHANGE,// No change to service type
+ startup, // New startup type
+ (DWORD) SERVICE_NO_CHANGE,// No change to error ctrl
+ 0, // No change to pathname
+ 0, // No change to load group
+ 0, // No change to tag
+ 0, // No change to dependencies
+ 0, 0, // No change to acct/passwd
+ 0); // No change to name
+
+ return ok ? 0 : -1;
+}
+
+// Returns the current startup type.
+
+DWORD
+ACE_NT_Service::startup (void)
+{
+ // The query buffer will hold strings as well as the defined struct.
+ // The string pointers in the struct point to other areas in the
+ // passed memory area, so it has to be large enough to hold the
+ // struct plus all the strings.
+ char cfgbuff[1024];
+ LPQUERY_SERVICE_CONFIG cfg;
+ DWORD cfgsize, needed_size;
+
+ SC_HANDLE svc = this->svc_sc_handle ();
+ if (svc == 0)
+ {
+ // To distinguish this error from the QueryServiceConfig failure
+ // below, return the DWORD equivalent of -2, rather than -1.
+ return MAXDWORD - 1;
+ }
+ cfgsize = sizeof cfgbuff;
+ cfg = (LPQUERY_SERVICE_CONFIG) cfgbuff;
+ BOOL ok = QueryServiceConfig (svc, cfg, cfgsize, &needed_size);
+ if (ok)
+ return cfg->dwStartType;
+ // Zero is a valid return value for QueryServiceConfig, so if
+ // QueryServiceConfig fails, return the DWORD equivalent of -1.
+ return MAXDWORD;
+
+}
+
+
+void
+ACE_NT_Service::capture_log_msg_attributes (void)
+{
+ ACE_Log_Msg::init_hook (this->log_msg_attributes_);
+}
+
+void
+ACE_NT_Service::inherit_log_msg_attributes (void)
+{
+ // There's no thread descriptor involved with a NT-started
+ // thread, so the first arg is 0.
+ ACE_Log_Msg::inherit_hook (0, this->log_msg_attributes_);
+}
+
+
+int
+ACE_NT_Service::start_svc (ACE_Time_Value *wait_time,
+ DWORD *svc_state,
+ DWORD argc, const ACE_TCHAR **argv)
+{
+ SC_HANDLE svc = this->svc_sc_handle ();
+ if (svc == 0)
+ return -1;
+
+ if (!ACE_TEXT_StartService (svc, argc, argv))
+ return -1;
+
+ this->wait_for_service_state (SERVICE_RUNNING, wait_time);
+ if (svc_state != 0)
+ *svc_state = this->svc_status_.dwCurrentState;
+
+ return 0;
+}
+
+int
+ACE_NT_Service::stop_svc (ACE_Time_Value *wait_time,
+ DWORD *svc_state)
+{
+ SC_HANDLE svc = this->svc_sc_handle ();
+ if (svc == 0)
+ return -1;
+
+ if (!ControlService (svc,
+ SERVICE_CONTROL_STOP,
+ &this->svc_status_))
+ return -1;
+
+ this->wait_for_service_state (SERVICE_STOPPED,
+ wait_time);
+ if (svc_state != 0)
+ *svc_state = this->svc_status_.dwCurrentState;
+
+ return 0;
+}
+
+int
+ACE_NT_Service::pause_svc (ACE_Time_Value *wait_time,
+ DWORD *svc_state)
+{
+ SC_HANDLE svc = this->svc_sc_handle ();
+ if (svc == 0)
+ return -1;
+
+ if (!ControlService (svc,
+ SERVICE_CONTROL_PAUSE,
+ &this->svc_status_))
+ return -1;
+
+ this->wait_for_service_state (SERVICE_PAUSED,
+ wait_time);
+ if (svc_state != 0)
+ *svc_state = this->svc_status_.dwCurrentState;
+
+ return 0;
+}
+
+int
+ACE_NT_Service::continue_svc (ACE_Time_Value *wait_time,
+ DWORD *svc_state)
+{
+ SC_HANDLE svc = this->svc_sc_handle ();
+ if (svc == 0)
+ return -1;
+
+ if (!ControlService (svc,
+ SERVICE_CONTROL_CONTINUE,
+ &this->svc_status_))
+ return -1;
+
+ this->wait_for_service_state (SERVICE_RUNNING,
+ wait_time);
+ if (svc_state != 0)
+ *svc_state = this->svc_status_.dwCurrentState;
+
+ return 0;
+}
+
+DWORD
+ACE_NT_Service::state (ACE_Time_Value *wait_hint)
+{
+ DWORD curr_state;
+
+ if (this->state (&curr_state,
+ wait_hint) == -1)
+ return 0;
+ return curr_state;
+}
+
+int
+ACE_NT_Service::state (DWORD *pstate,
+ ACE_Time_Value *wait_hint)
+{
+ SC_HANDLE svc = this->svc_sc_handle ();
+
+ if (svc == 0)
+ return -1;
+
+ // Need to create a temporary copy of this variable since the
+ // QueryServiceStatus call will modify the setting depending on the
+ // current state of the Service. If the service is currently
+ // STOPPED, the value will be cleared.
+ DWORD controls_accepted = this->svc_status_.dwControlsAccepted;
+
+ if (QueryServiceStatus (svc,
+ &this->svc_status_) == 0)
+ return -1;
+
+ if (wait_hint != 0)
+ wait_hint->msec (this->svc_status_.dwWaitHint);
+
+ *pstate = this->svc_status_.dwCurrentState;
+ this->svc_status_.dwControlsAccepted = controls_accepted;
+ return 0;
+}
+
+// test_access
+//
+// Open a new handle, ignoring any handle open in svc_sc_handle_.
+// This function's results are returned without leaving the handle
+// open.
+
+int
+ACE_NT_Service::test_access (DWORD desired_access)
+{
+ int status = -1; // Guilty until proven innocent
+
+ SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (),
+ 0,
+ GENERIC_READ);
+ if (sc_mgr != 0)
+ {
+ SC_HANDLE handle = ACE_TEXT_OpenService (sc_mgr,
+ this->name (),
+ desired_access);
+ CloseServiceHandle (sc_mgr);
+ if (handle != 0)
+ {
+ status = 0;
+ CloseServiceHandle (handle);
+ }
+ }
+
+ return status;
+}
+
+// report_status
+//
+// Reports the current status. If new_status is not 0, it sets the
+// status to the new value before reporting. NOTE - this assumes that
+// no actual service status values have the value 0. This is true in
+// WinNT 4. If the status is a 'pending' type, the supplied time hint
+// is used unless it's 0, in which case the existing hint is used.
+// The dwWaitHint is not updated by this function. The checkpoint is
+// incremented by one after a pending report.
+
+int
+ACE_NT_Service::report_status (DWORD new_status,
+ DWORD time_hint)
+{
+ int bump_checkpoint = 0;
+ int retval = 0;
+ DWORD save_controls = 0;
+
+ if (new_status != 0)
+ this->svc_status_.dwCurrentState = new_status;
+ switch (this->svc_status_.dwCurrentState)
+ {
+ case SERVICE_START_PENDING:
+ save_controls = this->svc_status_.dwControlsAccepted;
+ this->svc_status_.dwControlsAccepted = 0;
+ /* Fall through */
+ case SERVICE_STOP_PENDING:
+ case SERVICE_CONTINUE_PENDING:
+ case SERVICE_PAUSE_PENDING:
+ this->svc_status_.dwWaitHint = time_hint ? time_hint : this->start_time_;
+ bump_checkpoint = 1;
+ break;
+
+ default:
+ this->svc_status_.dwCheckPoint = 0;
+ }
+
+ retval = SetServiceStatus (this->svc_handle_,
+ &this->svc_status_) ? 0 : -1;
+
+ if (save_controls != 0)
+ this->svc_status_.dwControlsAccepted = save_controls;
+
+ if (bump_checkpoint)
+ ++this->svc_status_.dwCheckPoint;
+
+ return retval;
+}
+
+SC_HANDLE
+ACE_NT_Service::svc_sc_handle (void)
+{
+ if (this->svc_sc_handle_ == 0)
+ {
+ SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (),
+ 0,
+ SC_MANAGER_ALL_ACCESS);
+ if (sc_mgr != 0)
+ {
+ this->svc_sc_handle_ = ACE_TEXT_OpenService (sc_mgr,
+ this->name (),
+ SERVICE_ALL_ACCESS);
+ if (this->svc_sc_handle_ == 0)
+ ACE_OS::set_errno_to_last_error ();
+ CloseServiceHandle (sc_mgr);
+ }
+ else
+ ACE_OS::set_errno_to_last_error ();
+ }
+
+ return this->svc_sc_handle_;
+}
+
+void
+ACE_NT_Service::wait_for_service_state (DWORD desired_state,
+ ACE_Time_Value *wait_time)
+{
+ DWORD last_state = 0;
+ DWORD last_check_point = 0;
+ int first_time = 1;
+ int service_ok;
+
+ ACE_Time_Value time_out = ACE_OS::gettimeofday ();
+ if (wait_time != 0)
+ time_out += *wait_time;
+
+ // Poll until the service reaches the desired state.
+ for (;;)
+ {
+ service_ok = 0 != QueryServiceStatus (this->svc_sc_handle_,
+ &this->svc_status_);
+
+ // If we cannot query the service, we are done.
+ if (!service_ok)
+ break;
+
+ // If the service has the desired state, we are done.
+ if (desired_state == this->svc_status_.dwCurrentState)
+ break;
+
+ // If we time-out, we are done
+ if (wait_time != 0 && ACE_OS::gettimeofday () > time_out )
+ {
+ errno = ETIME;
+ break;
+ }
+
+ if (first_time)
+ {
+ // remember the service state, the first time we wait
+ last_state = this->svc_status_.dwCurrentState;
+ last_check_point = this->svc_status_.dwCheckPoint;
+ first_time = 0;
+ }
+ else
+ {
+ // update the state change.
+ if (last_state != this->svc_status_.dwCurrentState)
+ {
+ last_state = this->svc_status_.dwCurrentState;
+ last_check_point = this->svc_status_.dwCheckPoint;
+ }
+ else
+ {
+ // The check-point should have increased
+ if (this->svc_status_.dwCheckPoint > last_check_point)
+ last_check_point = this->svc_status_.dwCheckPoint;
+ else
+ {
+ // Service control failure, we are done.
+ service_ok = 0;
+ break;
+ }
+ }
+ }
+
+ ::Sleep (this->svc_status_.dwWaitHint);
+ }
+
+ return;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && !ACE_LACKS_WIN32_SERVICES */
diff --git a/ACE/ace/NT_Service.h b/ACE/ace/NT_Service.h
new file mode 100644
index 00000000000..7023a0df0b2
--- /dev/null
+++ b/ACE/ace/NT_Service.h
@@ -0,0 +1,439 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file NT_Service.h
+ *
+ * $Id$
+ *
+ * @author Steve Huston <shuston@riverace.com>
+ */
+//==========================================================================
+
+#ifndef ACE_NT_SERVICE_H
+#define ACE_NT_SERVICE_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_WIN32_SERVICES)
+
+#include "ace/ACE.h"
+#include "ace/OS_Log_Msg_Attributes.h"
+#include "ace/Service_Object.h"
+#include "ace/Task.h"
+#include "ace/OS_NS_errno.h" // needed for those using our macros
+
+// ACE_NT_SERVICE_START_TIMEOUT is an estimate of the number of
+// milliseconds your service will take to start. Default is 5
+// seconds; you can pass a different value (or set one) when you
+// create the ACE_NT_Service object for your service.
+#if !defined ACE_NT_SERVICE_START_TIMEOUT
+#define ACE_NT_SERVICE_START_TIMEOUT 5000
+#endif /* ACE_NT_SERVICE_TIMEOUT */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_NT_Service
+ *
+ * @brief Provide the base class which defines the interface for controlling
+ * an NT service.
+ *
+ * NT Services can be implemented using the framework defined by
+ * the ACE_NT_Service class, and the macros defined in this file.
+ * Some quick refresher notes on NT Services:
+ *
+ * - The main program defines an array of entries describing the
+ * services offered. The ACE_NT_SERVICE_ENTRY macro can help with
+ * this.
+ * - For each service, a separate ServiceMain and Handler function
+ * need to be defined. These are taken care of by the
+ * ACE_NT_SERVICE_DEFINE macro.
+ * - When the main program/thread calls
+ * StartServiceCtrlDispatcher, NT creates a thread for each
+ * service, and runs the ServiceMain function for the service in
+ * that new thread. When that thread exits, the service is gone.
+ *
+ * To use this facility, you could derive a class from
+ * ACE_Service_Object (if you want to start via ACE's service
+ * configurator), or use any other class to run when the image
+ * starts (assuming that NT runs the image). You must set up an
+ * NT SERVICE_TABLE_ENTRY array to define your service(s). You
+ * can use the ACE_NT_SERVICE_... macros defined below for this.
+ *
+ * A SERVICE_TABLE might look like this:
+ * ACE_NT_SERVICE_REFERENCE(Svc1); // If service is in another file
+ * SERVICE_TABLE_ENTRY myServices[] = {
+ * ACE_NT_SERVICE_ENTRY ("MyNeatService", Svc1),
+ * { 0, 0 } };
+ *
+ * In the file where your service(s) are implemented, use the
+ * ACE_NT_SERVICE_DEFINE macro to set up the following:
+ * 1. A pointer to the service's implementation object (must be derived
+ * from ACE_NT_Service).
+ * 2. The service's Handler function (forwards all requests to the
+ * ACE_NT_Service-derived object's handle_control function).
+ * 3. The service's ServiceMain function. Creates a new instance
+ * of the ACE_NT_Service-derived class SVCCLASS, unless one has
+ * been created already.
+ *
+ * If you are using all the default constructor values, you can
+ * let the generated ServiceMain function create the object, else
+ * you need to create it by hand before calling
+ * StartServiceCtrlDispatcher. Set the pointer so ServiceMain
+ * won't create another one. Another reason you may want to do
+ * the object creation yourself is if you want to also implement
+ * suspend and resume functions (the ones inherited from
+ * ACE_Service_Object) to do something intelligent to the services
+ * which are running, like call their handle_control functions to
+ * request suspend and resume actions, similar to what NT would do
+ * if a Services control panel applet would do if the user clicks
+ * on Suspend.
+ */
+class ACE_Export ACE_NT_Service : public ACE_Task<ACE_MT_SYNCH>
+{
+
+public:
+ // = Initialization and termination methods.
+ /// Constructor primarily for use when running the service.
+ ACE_NT_Service (DWORD start_timeout = ACE_NT_SERVICE_START_TIMEOUT,
+ DWORD service_type = SERVICE_WIN32_OWN_PROCESS,
+ DWORD controls_mask = SERVICE_ACCEPT_STOP);
+
+ /// Constructor primarily for use when inserting/removing/controlling
+ /// the service.
+ ACE_NT_Service (const ACE_TCHAR *name,
+ const ACE_TCHAR *desc = 0,
+ DWORD start_timeout = ACE_NT_SERVICE_START_TIMEOUT,
+ DWORD service_type = SERVICE_WIN32_OWN_PROCESS,
+ DWORD controls_mask = SERVICE_ACCEPT_STOP);
+
+ virtual ~ACE_NT_Service (void);
+
+ // = Functions to operate the service
+
+ /**
+ * Hook called to open the service. By default, sets the service
+ * status to SERVICE_START_PENDING, calls the @c svc() method,
+ * interprets and sets the service status, and returns.
+ */
+ virtual int open (void *args = 0);
+
+ /**
+ * Hook called when terminating the service. Inherited from
+ * ACE_Shared_Object. Default implementation sets the service status
+ * to SERVICE_STOPPED.
+ */
+ virtual int fini (void);
+
+ /**
+ * The actual service implementation. This function need not be overridden
+ * by applications that are just using SCM capabilities, but must be
+ * by subclasses when actually running the service. It is expected that
+ * this function will set the status to RUNNING.
+ */
+ virtual int svc (void);
+
+ /**
+ * This function is called in response to a request from the Service
+ * Dispatcher. It must interact with the <svc> function to effect the
+ * requested control operation. The default implementation handles
+ * all requests as follows:
+ * SERVICE_CONTROL_STOP: set stop pending, set cancel flag
+ * SERVICE_CONTROL_PAUSE: set pause pending, <suspend>, set paused
+ * SERVICE_CONTROL_CONTINUE: set continue pending, <resume>, set running
+ * SERVICE_CONTROL_INTERROGATE: reports current status
+ * SERVICE_CONTROL_SHUTDOWN: same as SERVICE_CONTROL_STOP.
+ */
+ virtual void handle_control (DWORD control_code);
+
+ /// Set the svc_handle_ member. This is only a public function because
+ /// the macro-generated service function calls it.
+ void svc_handle (const SERVICE_STATUS_HANDLE new_svc_handle);
+
+
+ // = Methods which can be used to do SCP-like functions. The first group
+ // are used to register/insert and remove the service's definition in the
+ // SCM registry.
+
+ /// Sets the name and description for the service.
+ /// If desc is 0, it takes the same value as name.
+ void name (const ACE_TCHAR *name, const ACE_TCHAR *desc = 0);
+
+ /// Get the service name.
+ const ACE_TCHAR *name (void) const;
+
+ /// Get the service description.
+ const ACE_TCHAR *desc (void) const;
+
+ /// Sets the host machine
+ void host (const ACE_TCHAR *host);
+
+ /// Get the host machine.
+ const ACE_TCHAR *host (void) const;
+
+ /**
+ * Insert (create) the service in the NT Service Control Manager,
+ * with the given creation values. exe_path defaults to the path name
+ * of the program that calls the function. All other 0-defaulted arguments
+ * pass 0 into the service creation, taking NT_specified defaults.
+ * Returns -1 on error, 0 on success.
+ */
+ int insert (DWORD start_type = SERVICE_DEMAND_START,
+ DWORD error_control = SERVICE_ERROR_IGNORE,
+ const ACE_TCHAR *exe_path = 0,
+ const ACE_TCHAR *group_name = 0,
+ LPDWORD tag_id = 0,
+ const ACE_TCHAR *dependencies = 0,
+ const ACE_TCHAR *account_name = 0,
+ const ACE_TCHAR *password = 0,
+ DWORD desired_access = SERVICE_ALL_ACCESS);
+
+ /**
+ * Remove the service from the NT Service Control Manager. Returns -1 on
+ * error, 0 on success. This just affects the SCM and registry - the
+ * can and will keep running fine if it is already running.
+ */
+ int remove (void);
+
+ /// Sets the startup type for the service. Returns -1 on error, 0 on success.
+ int startup (DWORD startup);
+
+ /// Returns the current startup type.
+ DWORD startup (void);
+
+ // = Methods to control ACE_Log_Msg behavior in the service.
+
+ /**
+ * Set the ACE_Log_Msg attributes that the service thread will use to
+ * initialize its ACE_Log_Msg instance. This is how the initiating
+ * thread's logging ostream, etc. get into the service thread. The
+ * logging attributes in effect when this function is called are what
+ * the service thread will have at its disposal when it starts; therefore,
+ * the main thread should set up logging options for the process, and
+ * call this function just before calling the StartServiceCtrlDispatcher
+ * function.
+ */
+ void capture_log_msg_attributes (void);
+
+ /**
+ * Set the ACE_Log_Msg attributes in the current thread to those saved
+ * in the most recent call to @c capture_log_msg_attributes(). This function
+ * should be called from the service's service thread. Ideally, it is the
+ * first method called to be sure that any logging done is incorporated
+ * correctly into the process's established logging setup.
+ */
+ void inherit_log_msg_attributes (void);
+
+ // = Methods which control the service's execution.
+
+ // These methods to start/pause/resume/stop/check the service all
+ // have the following common behavior with respect to @a wait_time
+ // and return value. @a wait_time is a pointer to an ACE_Time_Value
+ // object. If not supplied (a zero pointer) the function will wait
+ // indefinitely for the action to be finalized (service reach
+ // running state, completely shut down, etc.) or get "stuck" before
+ // returning. If the time is supplied, it specifies how long to
+ // wait for the service to reach a steady state, and on return, it
+ // is updated to the service's last reported wait hint. So, if you
+ // want to control the waiting yourself (for example, you want to
+ // react to UI events during the wait) specify a @a wait_time of (0,
+ // 0) and use the updated time to know when to check the service's
+ // state again. NOTE!!!! The wait_time things don't work yet. The
+ // calls always check status once, and do not wait for it to change.
+ //
+ // The return value from start_svc, stop_svc, pause_svc,
+ // continue_svc is 0 if the request to NT to effect the change was
+ // made successfully. The service may refuse to change, or not do
+ // what you wanted; so if you need to know, supply a <svc_state>
+ // pointer to receive the service's reported last state on return
+ // and check it to see if it's what you want. The functions only
+ // return -1 when the actual request to the service is refused -
+ // this would include privilege restrictions and if the service is
+ // not configured to receive the request (this is most likely to
+ // happen in the case of pause and continue).
+
+ /**
+ * Start the service (must have been inserted before). wait_time is
+ * the time to wait for the service to reach a steady state before
+ * returning. If it is 0, the function waits as long as it takes
+ * for the service to reach the 'running' state, or gets stuck in
+ * some other state, or exits. If @a wait_time is supplied, it is
+ * updated on return to hold the service's last reported wait hint.
+ * svc_state can be used to receive the state which the service
+ * settled in. If the value is 0, the service never ran. argc/argv
+ * are passed to the service's ServiceMain function when it starts.
+ * Returns 0 for success, -1 for error.
+ */
+ int start_svc (ACE_Time_Value *wait_time = 0,
+ DWORD *svc_state = 0,
+ DWORD argc = 0, const ACE_TCHAR **argv = 0);
+
+ /**
+ * Requests the service to stop. Will wait up to @a wait_time for
+ * the service to actually stop. If not specified, the function
+ * waits until the service either stops or gets stuck in some other
+ * state before it stops. If <svc_state> is specified, it receives
+ * the last reported state of the service. Returns 0 if the request
+ * was made successfully, -1 if not.
+ */
+ int stop_svc (ACE_Time_Value *wait_time = 0, DWORD *svc_state = 0);
+
+ /// Pause the service.
+ int pause_svc (ACE_Time_Value *wait_time = 0, DWORD *svc_state = 0);
+
+ /// Continue the service.
+ int continue_svc (ACE_Time_Value *wait_time = 0, DWORD *svc_state = 0);
+
+ /**
+ * Get the current state for the service. If <wait_hint> is not 0,
+ * it receives the service's reported wait hint. Note that this
+ * function returns 0 on failure (not -1 as is usual in ACE). A
+ * zero return would (probably) only be returned if there is either
+ * no service with the given name in the SCM database, or the caller
+ * does not have sufficient rights to access the service state. The
+ * set of valid service state values are all greater than 0.
+ */
+ DWORD state (ACE_Time_Value *wait_hint = 0);
+
+ /// A version of <state> that returns -1 for failure, 0 for success.
+ /// The DWORD pointed to by pstate receives the state value.
+ int state (DWORD *pstate, ACE_Time_Value *wait_hint = 0);
+
+ /**
+ * Test access to the object's service in the SCM. The service must
+ * already have been inserted in the SCM database. This function
+ * has no affect on the service itself. Returns 0 if the specified
+ * access is allowed, -1 otherwise (either the access is denied, or
+ * there is a problem with the service's definition - check
+ * ACE_OS::last_error to get the specific error indication.
+ */
+ int test_access (DWORD desired_access = SERVICE_ALL_ACCESS);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ int report_status (DWORD new_status, DWORD time_hint = 0);
+
+ /**
+ * Return the svc_sc_handle_ member. If the member is null, it
+ * retrieves the handle from the Service Control Manager and caches
+ * it.
+ */
+ SC_HANDLE svc_sc_handle (void);
+
+ /**
+ * Waits for the service to reach <desired_state> or get
+ * (apparently) stuck before it reaches that state. Will wait at
+ * most @a wait_time to get to the desired state. If @a wait_time is
+ * 0, then the function keeps waiting until the desired state is
+ * reached or the service doesn't update its state any further. The
+ * svc_status_ class member is updated upon return.
+ */
+ void wait_for_service_state (DWORD desired_state,
+ ACE_Time_Value *wait_time);
+
+ /// Called by <handle_control> when a stop/shutdown was requested.
+ virtual void stop_requested (DWORD control_code);
+
+ /// Called by <handle_control> when a pause was requested.
+ virtual void pause_requested (DWORD control_code);
+
+ /// Called by <handle_control> when a continue was requested.
+ virtual void continue_requested (DWORD control_code);
+
+ /// Called by <handle_control> when a interrogate was requested.
+ virtual void interrogate_requested (DWORD control_code);
+
+protected:
+ /// Estimate of init time needed
+ DWORD start_time_;
+ /// Service handle - doesn't need close.
+ SERVICE_STATUS_HANDLE svc_handle_;
+ SERVICE_STATUS svc_status_;
+
+ /// Service's SCM handle
+ SC_HANDLE svc_sc_handle_;
+ ACE_TCHAR *name_;
+ ACE_TCHAR *desc_;
+ ACE_TCHAR *host_;
+
+ /// ACE_Log_Msg attributes to inherit from the starting thread.
+ ACE_OS_Log_Msg_Attributes log_msg_attributes_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// These macros help to get things set up correctly at compile time
+// and to take most of the grudge work out of creating the proper
+// functions and doing the registrations.
+//
+// ACE_NT_SERVICE_DEFINE - defines the 'ServiceMain' function which NT will
+// call in its own thread when the service control
+// dispatcher starts.
+
+#define ACE_NT_SERVICE_DEFINE(SVCNAME, SVCCLASS, SVCDESC) \
+ ACE_NT_Service * _ace_nt_svc_obj_##SVCNAME = 0; \
+ VOID WINAPI ace_nt_svc_handler_##SVCNAME (DWORD fdwControl) { \
+ _ace_nt_svc_obj_##SVCNAME->handle_control(fdwControl); \
+ } \
+ VOID WINAPI ace_nt_svc_main_##SVCNAME (DWORD dwArgc, \
+ ACE_TCHAR **lpszArgv) { \
+ bool delete_svc_obj = false; \
+ if (_ace_nt_svc_obj_##SVCNAME == 0) { \
+ ACE_NEW (_ace_nt_svc_obj_##SVCNAME, SVCCLASS); \
+ if (_ace_nt_svc_obj_##SVCNAME == 0) \
+ return; \
+ delete_svc_obj = true; \
+ } \
+ else \
+ _ace_nt_svc_obj_##SVCNAME->inherit_log_msg_attributes (); \
+ _ace_nt_svc_obj_##SVCNAME->init(dwArgc, lpszArgv); \
+ _ace_nt_svc_obj_##SVCNAME->svc_handle( \
+ ACE_TEXT_RegisterServiceCtrlHandler(SVCDESC, \
+ &ace_nt_svc_handler_##SVCNAME)); \
+ _ace_nt_svc_obj_##SVCNAME->open(); \
+ _ace_nt_svc_obj_##SVCNAME->wait(); \
+ _ace_nt_svc_obj_##SVCNAME->fini(); \
+ if (delete_svc_obj) { \
+ delete _ace_nt_svc_obj_##SVCNAME; \
+ _ace_nt_svc_obj_##SVCNAME = 0; \
+ } \
+ return; \
+ }
+
+#define ACE_NT_SERVICE_REFERENCE(SVCNAME) \
+extern ACE_NT_Service * _ace_nt_svc_obj_##SVCNAME; \
+extern VOID WINAPI ace_nt_svc_main_##SVCNAME (DWORD dwArgc, \
+ ACE_TCHAR **lpszArgv);
+
+#define ACE_NT_SERVICE_ENTRY(SVCDESC, SVCNAME) \
+ { SVCDESC, &ace_nt_svc_main_##SVCNAME }
+
+#define ACE_NT_SERVICE_RUN(SVCNAME, SVCINSTANCE, RET) \
+ ACE_TEXT_SERVICE_TABLE_ENTRY _ace_nt_svc_table[2] = \
+ { \
+ ACE_NT_SERVICE_ENTRY(ACE_TEXT (#SVCNAME), SVCNAME), \
+ { 0, 0 } \
+ }; \
+ _ace_nt_svc_obj_##SVCNAME = SVCINSTANCE; \
+ _ace_nt_svc_obj_##SVCNAME->capture_log_msg_attributes (); \
+ ACE_OS::last_error (0); \
+ int RET = ACE_TEXT_StartServiceCtrlDispatcher(_ace_nt_svc_table);
+
+#if defined (__ACE_INLINE__)
+#include "ace/NT_Service.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_WIN32 && !ACE_LACKS_WIN32_SERVICES */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SERVICE_OBJECT_H */
diff --git a/ACE/ace/NT_Service.inl b/ACE/ace/NT_Service.inl
new file mode 100644
index 00000000000..bd9b7ea5b63
--- /dev/null
+++ b/ACE/ace/NT_Service.inl
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_NT_Service::ACE_NT_Service (DWORD start_timeout,
+ DWORD service_type,
+ DWORD controls_mask) :
+ start_time_(start_timeout),
+ svc_handle_(0),
+ svc_sc_handle_(0),
+ name_(0),
+ desc_(0),
+ host_(0)
+{
+ svc_status_.dwServiceType = service_type;
+ svc_status_.dwCurrentState = 0;
+ svc_status_.dwControlsAccepted = controls_mask;
+ svc_status_.dwWin32ExitCode = NO_ERROR;
+ svc_status_.dwServiceSpecificExitCode = 0;
+ svc_status_.dwCheckPoint = 0;
+ svc_status_.dwWaitHint = 0;
+}
+
+
+ACE_INLINE
+ACE_NT_Service::ACE_NT_Service (const ACE_TCHAR *name,
+ const ACE_TCHAR *desc,
+ DWORD start_timeout,
+ DWORD service_type,
+ DWORD controls_mask) :
+ start_time_(start_timeout),
+ svc_handle_(0),
+ svc_sc_handle_(0),
+ name_(ACE::strnew(name)),
+ desc_(ACE::strnew(desc)),
+ host_(0)
+{
+ svc_status_.dwServiceType = service_type;
+ svc_status_.dwCurrentState = 0;
+ svc_status_.dwControlsAccepted = controls_mask;
+ svc_status_.dwWin32ExitCode = NO_ERROR;
+ svc_status_.dwServiceSpecificExitCode = 0;
+ svc_status_.dwCheckPoint = 0;
+}
+
+
+ACE_INLINE int
+ACE_NT_Service::svc (void)
+{
+ return -1;
+}
+
+
+ACE_INLINE
+const ACE_TCHAR *
+ACE_NT_Service::name (void) const
+{
+ return name_;
+}
+
+ACE_INLINE
+const ACE_TCHAR *
+ACE_NT_Service::desc (void) const
+{
+ return desc_;
+}
+
+ACE_INLINE
+const ACE_TCHAR *
+ACE_NT_Service::host (void) const
+{
+ return host_;
+}
+
+ACE_INLINE void
+ACE_NT_Service::svc_handle(const SERVICE_STATUS_HANDLE new_svc_handle)
+{
+ this->svc_handle_ = new_svc_handle;
+ return;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Name_Proxy.cpp b/ACE/ace/Name_Proxy.cpp
new file mode 100644
index 00000000000..026856e75bd
--- /dev/null
+++ b/ACE/ace/Name_Proxy.cpp
@@ -0,0 +1,209 @@
+// $Id$
+
+#include "ace/Name_Proxy.h"
+#include "ace/Log_Msg.h"
+#include "ace/os_include/arpa/os_inet.h"
+
+ACE_RCSID(ace, Name_Proxy, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Name_Proxy::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("reactor_ = %x"), this->reactor_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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 = 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)
+ : reactor_ (0)
+{
+ 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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("encode failed")),
+ -1);
+
+ // Transmit request via a blocking send.
+
+ if (this->peer_.send_n (buffer, length) != length)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("recv failed")),
+ -1);
+ else if (reply.decode () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_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_TEXT ("****************** recv_reply returned -1\n")));
+ default:
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p got %d bytes, expected %d bytes\n"),
+ ACE_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 = ACE_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_TEXT ("%p expected %d, got %d\n"),
+ ACE_TEXT ("invalid length"),
+ length,
+ n));
+ return -1;
+ }
+
+ // Decode the request into host byte order.
+ if (reply.decode () == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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 ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Name_Proxy.h b/ACE/ace/Name_Proxy.h
new file mode 100644
index 00000000000..16411b17334
--- /dev/null
+++ b/ACE/ace/Name_Proxy.h
@@ -0,0 +1,101 @@
+// -*- 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 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"
+#include "ace/Event_Handler.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_;
+
+private:
+ // Prevent copying
+ ACE_Name_Proxy (const ACE_Name_Proxy &);
+ ACE_Name_Proxy &operator= (const ACE_Name_Proxy &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_NAME_PROXY_H */
diff --git a/ACE/ace/Name_Request_Reply.cpp b/ACE/ace/Name_Request_Reply.cpp
new file mode 100644
index 00000000000..e602cd58b80
--- /dev/null
+++ b/ACE/ace/Name_Request_Reply.cpp
@@ -0,0 +1,577 @@
+#include "ace/Name_Request_Reply.h"
+#include "ace/Basic_Types.h"
+#include "ace/CDR_Base.h"
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+#include "ace/Truncate.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/arpa/os_inet.h"
+
+ACE_RCSID (ace,
+ Name_Request_Reply,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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_WCHAR_T name[], // Name
+ const ACE_UINT32 name_length, // size in bytes
+ const ACE_WCHAR_T 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_WCHAR_T) ];
+ this->type_ = (char *)(&this->value_[value_length / sizeof (ACE_WCHAR_T)]); //
+
+ (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 (static_cast<ACE_UINT32> (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");
+ time_t sec = ACE_Utils::truncate_cast<time_t> (this->transfer_.sec_timeout_);
+ return ACE_Time_Value (sec, 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_WCHAR_T *
+ACE_Name_Request::name (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::name");
+ return this->name_;
+}
+
+void
+ACE_Name_Request::name (const ACE_WCHAR_T *t)
+{
+ ACE_TRACE ("ACE_Name_Request::name");
+ (void) ACE_OS::memcpy (this->name_,
+ t,
+ this->name_len ());
+}
+
+// = Set/get the value
+
+const ACE_WCHAR_T *
+ACE_Name_Request::value (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::value");
+ return this->value_;
+}
+
+void
+ACE_Name_Request::value (const ACE_WCHAR_T *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.
+
+ ACE_UINT32 len = this->length ();
+
+ size_t nv_data_len =
+ (this->transfer_.name_len_ + this->transfer_.value_len_)
+ / sizeof (ACE_WCHAR_T);
+
+ for (size_t i = 0; i < nv_data_len; i++)
+ this->transfer_.data_[i] =
+ ACE_HTONS (this->transfer_.data_[i]);
+
+ buf = (void *) &this->transfer_;
+ this->transfer_.block_forever_ = ACE_HTONL (this->transfer_.block_forever_);
+ this->transfer_.usec_timeout_ = ACE_HTONL (this->transfer_.usec_timeout_);
+#if defined (ACE_LITTLE_ENDIAN)
+ ACE_UINT64 secs = this->transfer_.sec_timeout_;
+ ACE_CDR::swap_8 ((const char *)&secs, (char *)&this->transfer_.sec_timeout_);
+#endif
+ this->transfer_.length_ = ACE_HTONL (this->transfer_.length_);
+ this->transfer_.msg_type_ = ACE_HTONL (this->transfer_.msg_type_);
+ this->transfer_.name_len_ = ACE_HTONL (this->transfer_.name_len_);
+ this->transfer_.value_len_ = ACE_HTONL (this->transfer_.value_len_);
+ this->transfer_.type_len_ = ACE_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_ = ACE_NTOHL (this->transfer_.block_forever_);
+ this->transfer_.usec_timeout_ = ACE_NTOHL (this->transfer_.usec_timeout_);
+#if defined (ACE_LITTLE_ENDIAN)
+ ACE_UINT64 secs = this->transfer_.sec_timeout_;
+ ACE_CDR::swap_8 ((const char *)&secs, (char *)&this->transfer_.sec_timeout_);
+#endif
+ this->transfer_.length_ = ACE_NTOHL (this->transfer_.length_);
+ this->transfer_.msg_type_ = ACE_NTOHL (this->transfer_.msg_type_);
+ this->transfer_.name_len_ = ACE_NTOHL (this->transfer_.name_len_);
+ this->transfer_.value_len_ = ACE_NTOHL (this->transfer_.value_len_);
+ this->transfer_.type_len_ = ACE_NTOHL (this->transfer_.type_len_);
+
+ size_t nv_data_len =
+ (this->transfer_.name_len_ + this->transfer_.value_len_)
+ / sizeof (ACE_WCHAR_T);
+
+ for (size_t i = 0; i < nv_data_len; i++)
+ this->transfer_.data_[i] =
+ ACE_NTOHS (this->transfer_.data_[i]);
+
+ this->name_ = this->transfer_.data_;
+ this->value_ = &this->name_[this->transfer_.name_len_ / sizeof (ACE_WCHAR_T)];
+ this->type_ = (char *)(&this->value_[this->transfer_.value_len_ / sizeof (ACE_WCHAR_T)]);
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Name_Request::dump");
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("*******\nlength = %d\n"),
+ this->length ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("message-type = ")));
+
+ switch (this->msg_type ())
+ {
+ case ACE_Name_Request::BIND:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("BIND\n")));
+ break;
+ case ACE_Name_Request::REBIND:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("REBIND\n")));
+ break;
+ case ACE_Name_Request::RESOLVE:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("RESOLVE\n")));
+ break;
+ case ACE_Name_Request::UNBIND:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("UNBIND\n")));
+ break;
+ case ACE_Name_Request::LIST_NAMES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("LIST_NAMES\n")));
+ break;
+ case ACE_Name_Request::LIST_VALUES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("LIST_VALUES\n")));
+ break;
+ case ACE_Name_Request::LIST_TYPES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("LIST_TYPES\n")));
+ break;
+ case ACE_Name_Request::LIST_NAME_ENTRIES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("LIST_NAME_ENTRIES\n")));
+ break;
+ case ACE_Name_Request::LIST_VALUE_ENTRIES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("LIST_VALUE_ENTRIES\n")));
+ break;
+ case ACE_Name_Request::LIST_TYPE_ENTRIES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("LIST_TYPE_ENTRIES\n")));
+ break;
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("<unknown type> = %d\n"),
+ this->msg_type ()));
+ break;
+ }
+
+ if (this->block_forever ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("blocking forever\n")));
+ else
+ {
+#if !defined (ACE_NLOGGING)
+ ACE_Time_Value tv = this->timeout ();
+#endif /* ! ACE_NLOGGING */
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("waiting for %d secs and %d usecs\n"),
+ tv.sec (),
+ tv.usec ()));
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("*******\nname_len = %d\n"),
+ this->name_len ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("*******\nvalue_len = %d\n"),
+ this->value_len ()));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("+++++++\n")));
+#endif /* ACE_HAS_DUMP */
+}
+
+// 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_ = ACE_HTONL (this->transfer_.length_);
+ this->transfer_.type_ = ACE_HTONL (this->transfer_.type_);
+ this->transfer_.errno_ = ACE_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_ = ACE_NTOHL (this->transfer_.length_);
+ this->transfer_.type_ = ACE_NTOHL (this->transfer_.type_);
+ this->transfer_.errno_ = ACE_NTOHL (this->transfer_.errno_);
+ return 0;
+}
+
+// Print out current values of the ACE_Name_Reply object.
+
+void
+ACE_Name_Reply::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Name_Reply::dump");
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("*******\nlength = %d\nerrnum = %d"),
+ this->length (),
+ this->errnum ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("type = ")));
+ switch (this->msg_type ())
+ {
+ case 0:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("SUCCESS\n")));
+ break;
+ case -1:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("FAILURE\n")));
+ break;
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("<unknown type> = %d\n"),
+ this->msg_type ()));
+ break;
+ }
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Name_Request_Reply.h b/ACE/ace/Name_Request_Reply.h
new file mode 100644
index 00000000000..3a927e9f9e3
--- /dev/null
+++ b/ACE/ace/Name_Request_Reply.h
@@ -0,0 +1,265 @@
+// -*- 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 Prashant Jain
+ */
+//=============================================================================
+
+
+#ifndef ACE_NAME_REQUEST_REPLY_H
+#define ACE_NAME_REQUEST_REPLY_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Basic_Types.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @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_WCHAR_T name[], //
+ const ACE_UINT32 name_length,
+ const ACE_WCHAR_T 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_WCHAR_T *name (void) const;
+ void name (const ACE_WCHAR_T *);
+
+ // = Set/get the value
+ const ACE_WCHAR_T *value (void) const;
+ void value (const ACE_WCHAR_T *);
+
+ // = 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
+ {
+ /// Length of entire request.
+ ACE_UINT32 length_;
+
+ /// Type of the request (i.e., <BIND>, <REBIND>, <RESOLVE>, and <UNBIND>).
+ ACE_UINT32 msg_type_;
+
+ /// Indicates if we should block forever. If 0, then <secTimeout_>
+ /// and <usecTimeout_> indicates how long we should wait.
+ ACE_UINT32 block_forever_;
+
+ /// Max seconds willing to wait for name if not blocking forever.
+ ACE_UINT64 sec_timeout_;
+
+ /// Max micro seconds to wait for name if not blocking forever.
+ ACE_UINT32 usec_timeout_;
+
+ /// Len of name in bytes
+ ACE_UINT32 name_len_;
+
+ /// Len of value in bytes
+ ACE_UINT32 value_len_;
+
+ /// Len of type in bytes
+ ACE_UINT32 type_len_;
+
+ /// The data portion contains the <name_>
+ /// followed by the <value_>
+ /// followed by the <type_>.
+ ACE_WCHAR_T data_[MAX_NAME_LENGTH + MAXPATHLEN + MAXPATHLEN + 2];
+ };
+
+ /// Transfer buffer.
+ Transfer transfer_;
+
+ /// Pointer to the beginning of the name in this->data_.
+ ACE_WCHAR_T *name_;
+
+ /// Pointer to the beginning of the value in this->data_;
+ ACE_WCHAR_T *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
+ {
+ /// Length of entire reply.
+ ACE_UINT32 length_;
+
+ /// Type of the reply, i.e., success (0) or failure (-1).
+ ACE_INT32 type_;
+
+ /// Indicates why error occurred if <this->type_> == failure (-1).
+ /// Typical reasons include: @c ETIME (if the client timed out after
+ /// waiting for the name).
+ ACE_UINT32 errno_;
+ };
+
+ /// Transfer buffer.
+ Transfer transfer_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_NAME_REQUEST_REPLY_H */
diff --git a/ACE/ace/Name_Space.cpp b/ACE/ace/Name_Space.cpp
new file mode 100644
index 00000000000..2f15a9e71d3
--- /dev/null
+++ b/ACE/ace/Name_Space.cpp
@@ -0,0 +1,73 @@
+// Name_Space.cpp
+// $Id$
+
+#include "ace/Name_Space.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID(ace, Name_Space, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Name_Binding::ACE_Name_Binding (void)
+ : name_ (),
+ value_ (),
+ 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 =");
+
+ if (this != &s)
+ {
+ ACE_OS::free ((void *) this->type_);
+ this->name_ = s.name_;
+ this->value_ = s.value_;
+ this->type_ = ACE_OS::strdup (s.type_);
+ }
+}
+
+bool
+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");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Name_Space.h b/ACE/ace/Name_Space.h
new file mode 100644
index 00000000000..fff070d1e96
--- /dev/null
+++ b/ACE/ace/Name_Space.h
@@ -0,0 +1,165 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Name_Space.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain <pjain@cse.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_NAME_SPACE_H
+#define ACE_NAME_SPACE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SString.h"
+#include "ace/Unbounded_Set.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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.
+ bool 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_NAME_SPACE_H */
diff --git a/ACE/ace/Naming_Context.cpp b/ACE/ace/Naming_Context.cpp
new file mode 100644
index 00000000000..71602de6b44
--- /dev/null
+++ b/ACE/ace/Naming_Context.cpp
@@ -0,0 +1,647 @@
+// $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/MMAP_Memory_Pool.h"
+#include "ace/RW_Process_Mutex.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#if defined (ACE_HAS_TRACE)
+# include "ace/OS_NS_strings.h"
+# include "ace/Trace.h"
+#endif /* ACE_HAS_TRACE */
+
+ACE_RCSID(ace, Naming_Context, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Naming_Context.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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 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_TCHAR buf[BUFSIZ];
+
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("%s\t#%s\n"),
+ ACE_TEXT ("ACE_Naming_Context"),
+ ACE_TEXT ("Proxy for making calls to a Name Server"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return static_cast<int> (ACE_OS::strlen (buf));
+}
+
+int
+ACE_Naming_Context::local (void)
+{
+ ACE_TRACE ("ACE_Naming_Context::local");
+ return ACE_OS::strcmp (this->netnameserver_host_,
+ ACE_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 (ACE_USES_WCHAR))
+// This only works on Win32 platforms when ACE_USES_WCHAR 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 && ACE_USES_WCHAR */
+ 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_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),
+ netnameserver_host_ (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_TEXT ("%p\n"),
+ ACE_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 ()
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Naming_Context::dump");
+ this->name_space_->dump();
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Naming_Context::init (int argc, ACE_TCHAR *argv[])
+{
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_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_TEXT ("ACE_Naming_Context::fini\n")));
+ this->close_down ();
+ return 0;
+}
+
+ACE_Name_Options::ACE_Name_Options (void)
+ : debugging_ (0),
+ verbosity_ (0),
+ use_registry_ (false),
+ 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_ = static_cast <ACE_TCHAR *> (ACE_OS::malloc (pathsize));
+
+ if (ACE::get_temp_dir (this->namespace_dir_, MAXPATHLEN) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Temporary path too long, ")
+ ACE_TEXT ("defaulting to current directory\n")));
+ ACE_OS::strcpy (this->namespace_dir_, ACE_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");
+ 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;
+}
+
+void
+ACE_Name_Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Name_Options::parse_args");
+
+ const ACE_TCHAR* program_name = 0;
+
+ // Argc can be 0 on some platforms like VxWorks.
+ if (argc > 0)
+ program_name = argv[0];
+
+ ACE_LOG_MSG->open (program_name);
+ this->process_name (program_name);
+
+ // 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_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_TEXT ("PROC_LOCAL")) == 0)
+ this->context (ACE_Naming_Context::PROC_LOCAL);
+ else if (ACE_OS::strcmp (get_opt.opt_arg (), ACE_TEXT ("NODE_LOCAL")) == 0)
+ this->context (ACE_Naming_Context::NODE_LOCAL);
+ else if (ACE_OS::strcmp (get_opt.opt_arg (), ACE_TEXT ("NET_LOCAL")) == 0)
+ this->context (ACE_Naming_Context::NET_LOCAL);
+ }
+ break;
+ case 'd':
+ this->debugging_ = 1;
+ break;
+ case 'r':
+ this->use_registry_ = true;
+ 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
+ (static_cast<char *> (ACE_OS::atop (get_opt.opt_arg ())));
+ break;
+ case 'T':
+#if defined (ACE_HAS_TRACE)
+ if (ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT ("ON")) == 0)
+ ACE_Trace::start_tracing ();
+ else if (ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT ("OFF")) == 0)
+ ACE_Trace::stop_tracing ();
+#endif /* ACE_HAS_TRACE */
+ 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;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// 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_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)
diff --git a/ACE/ace/Naming_Context.h b/ACE/ace/Naming_Context.h
new file mode 100644
index 00000000000..6cd91e3e212
--- /dev/null
+++ b/ACE/ace/Naming_Context.h
@@ -0,0 +1,387 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Naming_Context.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Prashant Jain <pjain@uci.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_NAMING_CONTEXT_H
+#define ACE_NAMING_CONTEXT_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Object.h"
+#include "ace/Name_Space.h"
+#include "ace/os_include/os_netdb.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl
+class ACE_Name_Options;
+class ACE_Static_Svc_Descriptor;
+
+/**
+ * @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 @a 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 @a 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 @a value_out> and @a 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 @a value_out and
+ * @a 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 @a value_out and @a 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 the port number
+ void nameserver_port (int port);
+
+ /// Get the port number
+ int nameserver_port (void);
+
+ /// Get the context
+ ACE_Naming_Context::Context_Scope_Type context (void);
+
+ /// Set the context
+ void context (ACE_Naming_Context::Context_Scope_Type);
+
+ /// Set the host name
+ void nameserver_host (const ACE_TCHAR *host);
+
+ /// Get the host name
+ const ACE_TCHAR *nameserver_host (void);
+
+ /// Set name space directory
+ void namespace_dir (const ACE_TCHAR *dir);
+
+ /// Get name space directory
+ const ACE_TCHAR *namespace_dir (void);
+
+ /// Set process name
+ void process_name (const ACE_TCHAR *dir);
+
+ /// Get process name
+ const ACE_TCHAR *process_name (void);
+
+ /// Set database name
+ void database (const ACE_TCHAR *);
+
+ /// Get database name
+ const ACE_TCHAR *database (void);
+
+ /// Set base address of the underlying allocator
+ void base_address (char *address);
+
+ /// Get base address of the underlying allocator
+ char *base_address (void);
+
+ /// Get use of registry in naming
+ bool use_registry (void) const;
+
+ /// Set use of registry in naming
+ void use_registry (bool x);
+
+ /// 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
+ bool 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_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Naming_Context.inl"
+#endif /* __ACE_INLINE__ */
+
+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/ace/Naming_Context.inl b/ACE/ace/Naming_Context.inl
new file mode 100644
index 00000000000..4c90343c1ee
--- /dev/null
+++ b/ACE/ace/Naming_Context.inl
@@ -0,0 +1,44 @@
+// $Id$
+
+ACE_INLINE bool
+ACE_Name_Options::use_registry (void) const
+{
+ ACE_TRACE ("ACE_Name_Options::use_registry");
+ return this->use_registry_;
+}
+
+ACE_INLINE void
+ACE_Name_Options::use_registry (bool x)
+{
+ ACE_TRACE ("ACE_Name_Options::use_registry");
+ this->use_registry_ = x;
+}
+
+ACE_INLINE int
+ACE_Name_Options::verbose (void)
+{
+ ACE_TRACE ("ACE_Name_Options::verbose");
+ return this->verbosity_;
+}
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Name_Options::process_name (void)
+{
+ ACE_TRACE ("ACE_Name_Options::process_name");
+ return this->process_name_;
+}
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Name_Options::namespace_dir (void)
+{
+ ACE_TRACE ("ACE_Name_Options::namespace_dir");
+ return this->namespace_dir_;
+}
+
+ACE_INLINE int
+ACE_Name_Options::debug (void)
+{
+ ACE_TRACE ("ACE_Name_Options::debug");
+ return this->debugging_;
+}
+
diff --git a/ACE/ace/Netlink_Addr.cpp b/ACE/ace/Netlink_Addr.cpp
new file mode 100644
index 00000000000..2a7ef2a8bde
--- /dev/null
+++ b/ACE/ace/Netlink_Addr.cpp
@@ -0,0 +1,68 @@
+// $Id$
+
+//=============================================================================
+/**
+ * @file Netlink_Addr.cpp
+ *
+ * $Id$
+ *
+ * @author Robert Iakobashvilli <coroberti@gmail.com>
+ * @author Raz Ben Yehuda <raziebe@gmail.com>
+ */
+//=============================================================================
+
+#include "ace/Netlink_Addr.h"
+
+#ifdef ACE_HAS_NETLINK
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Netlink_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Netlink_Addr)
+
+int ACE_Netlink_Addr::set (const ACE_Netlink_Addr &sa)
+{
+ ACE_OS::memset ((void *) &this->nl_,0,sizeof this->nl_);
+ this->nl_.nl_family = AF_NETLINK;
+ this->base_set (sa.get_type (), sa.get_size ());
+ return 0;
+}
+
+// Copy constructor.
+
+ACE_Netlink_Addr::ACE_Netlink_Addr (const ACE_Netlink_Addr &sa)
+: ACE_Addr (AF_NETLINK, sa.get_size ())
+{
+ this->set (sa);
+}
+
+int ACE_Netlink_Addr::set (const sockaddr_nl *un, int len)
+{
+ (void) ACE_OS::memcpy ((void *) &this->nl_,un,len);
+ return 0;
+}
+
+ACE_Netlink_Addr::ACE_Netlink_Addr (const sockaddr_nl *un, int len)
+{
+ this->set (un, len);
+}
+
+int
+ACE_Netlink_Addr::get_pid (void) const
+{
+ return this->nl_.nl_pid;
+}
+
+int
+ACE_Netlink_Addr::get_gid (void) const
+{
+ return this->nl_.nl_groups;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif
+
diff --git a/ACE/ace/Netlink_Addr.h b/ACE/ace/Netlink_Addr.h
new file mode 100644
index 00000000000..a012c7e9cac
--- /dev/null
+++ b/ACE/ace/Netlink_Addr.h
@@ -0,0 +1,120 @@
+// $Id$
+
+//=============================================================================
+/**
+ * @file Netlink_Addr.h
+ *
+ * $Id$
+ *
+ * @author Robert Iakobashvilli <coroberti@gmail.com>
+ * @author Raz Ben Yehuda <raziebe@gmail.com>
+ */
+//=============================================================================
+
+#ifndef ACE_NETLINK_ADDR_H
+#define ACE_NETLINK_ADDR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+ #pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#ifdef ACE_HAS_NETLINK
+
+#include "ace/OS_NS_string.h"
+#include "ace/Global_Macros.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Addr.h"
+#include "ace/os_include/sys/os_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Netlink_Addr
+ *
+ * @brief Defines a C++ wrapper facade for the netlink sockets
+ */
+class ACE_Export ACE_Netlink_Addr : public ACE_Addr {
+public:
+ // = Initialization methods.
+
+ /// Default constructor.
+ ACE_Netlink_Addr (void);
+
+ /// Copy constructor.
+ ACE_Netlink_Addr (const ACE_Netlink_Addr &);
+
+ /// Creates an ACE_INET_Addr from a sockaddr_in structure.
+ ACE_Netlink_Addr (const sockaddr_nl *, int len);
+
+ /// Dtor
+ ~ACE_Netlink_Addr (void);
+
+ /**
+ * @param naddr sets the nl_ member @see nl_
+ */
+ int set (const ACE_Netlink_Addr &naddr);
+ /**
+ * sets the pid and groups fields of member nl_ @see nl_
+ */
+ void set (int pid, int gid);
+ /**
+ * set nl_ to nl_ @see nl_
+ */
+ int set (const sockaddr_nl *, int len);
+ /**
+ * @return pid
+ */
+ int get_pid (void) const;
+ /**
+ * @return the group id @see nl_
+ */
+ int get_gid (void) const;
+ /**
+ * @return addr pointer @see nl_
+ */
+ virtual void *get_addr (void) const;
+ /**
+ * @return nl_ member @see nl_ size
+ */
+ int get_addr_size (void) const;
+ /**
+ * Set a pointer to the address
+ */
+ virtual void set_addr (void *, int len= sizeof(sockaddr_nl) );
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /**
+ * @return family type AF_NETLINK
+ *
+ * */
+ int determine_type (void) const;
+ /**
+ * set nl_ @see nl_ to zero and sets address family to default value
+ */
+ void reset (void);
+
+ sockaddr_nl nl_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Netlink_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_NETLINK */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_NETLINK_ADDR_H */
+
+
+
diff --git a/ACE/ace/Netlink_Addr.inl b/ACE/ace/Netlink_Addr.inl
new file mode 100644
index 00000000000..5b47a0c053f
--- /dev/null
+++ b/ACE/ace/Netlink_Addr.inl
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+// $Id$
+
+#ifdef ACE_HAS_NETLINK
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_Netlink_Addr::~ACE_Netlink_Addr (void){}
+
+ACE_INLINE ACE_Netlink_Addr::ACE_Netlink_Addr (void):
+ACE_Addr (this->determine_type(), sizeof (sockaddr_nl))
+{
+ this->nl_.nl_family = AF_NETLINK;
+}
+
+ACE_INLINE void ACE_Netlink_Addr::set(int pid, int gid)
+{
+ this->nl_.nl_pid = pid;
+ this->nl_.nl_groups = gid;
+}
+
+ACE_INLINE void ACE_Netlink_Addr::reset (void)
+{
+ ACE_OS::memset (&this->nl_, 0, sizeof (this->nl_));
+ this->nl_.nl_family = AF_NETLINK;
+}
+
+ACE_INLINE int ACE_Netlink_Addr::determine_type (void) const
+{
+ return AF_NETLINK;
+}
+
+ACE_INLINE void *ACE_Netlink_Addr::get_addr (void) const
+{
+ return (void*)&(this->nl_);
+}
+
+ACE_INLINE int ACE_Netlink_Addr::get_addr_size (void) const
+{
+ return sizeof(this->nl_);
+}
+
+
+ACE_INLINE void ACE_Netlink_Addr::set_addr (void *addr, int len){
+ ACE_OS::memcpy (&this->nl_,addr,len);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_NETLINK */
+
diff --git a/ACE/ace/Node.cpp b/ACE/ace/Node.cpp
new file mode 100644
index 00000000000..3520a8a0c6b
--- /dev/null
+++ b/ACE/ace/Node.cpp
@@ -0,0 +1,46 @@
+// $Id$
+
+#ifndef ACE_NODE_CPP
+#define ACE_NODE_CPP
+
+#include "ace/Node.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Node)
+
+template <class T>
+ACE_Node<T>::~ACE_Node (void)
+{
+}
+
+template <class T>
+ACE_Node<T>::ACE_Node (const T &i, ACE_Node<T> *n)
+ : next_ (n),
+ item_ (i)
+{
+ // ACE_TRACE ("ACE_Node<T>::ACE_Node");
+}
+
+template <class T>
+ACE_Node<T>::ACE_Node (ACE_Node<T> *n, int)
+ : next_ (n)
+{
+ // ACE_TRACE ("ACE_Node<T>::ACE_Node");
+}
+
+template <class T>
+ACE_Node<T>::ACE_Node (const ACE_Node<T> &s)
+ : next_ (s.next_),
+ item_ (s.item_)
+{
+ // ACE_TRACE ("ACE_Node<T>::ACE_Node");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_NODE_CPP */
diff --git a/ACE/ace/Node.h b/ACE/ace/Node.h
new file mode 100644
index 00000000000..023086dbb91
--- /dev/null
+++ b/ACE/ace/Node.h
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Node.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_NODE_H
+#define ACE_NODE_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+template <class T> class ACE_Unbounded_Set;
+template <class T> class ACE_Unbounded_Set_Iterator;
+template <class T> class ACE_Unbounded_Set_Const_Iterator;
+template <class T> class ACE_Unbounded_Queue;
+template <class T> class ACE_Unbounded_Queue_Iterator;
+template <class T> class ACE_Unbounded_Queue_Const_Iterator;
+template <class T> class ACE_Unbounded_Stack;
+template <class T> class ACE_Unbounded_Stack_Iterator;
+
+/**
+ * @class ACE_Node
+ *
+ * @brief Implementation element in a Queue, Set, and Stack.
+ */
+template<class T>
+class ACE_Node
+{
+public:
+ friend class ACE_Unbounded_Queue<T>;
+ friend class ACE_Unbounded_Queue_Iterator<T>;
+ friend class ACE_Unbounded_Queue_Const_Iterator<T>;
+ friend class ACE_Unbounded_Set<T>;
+ friend class ACE_Unbounded_Set_Iterator<T>;
+ friend class ACE_Unbounded_Set_Const_Iterator<T>;
+ friend class ACE_Unbounded_Stack<T>;
+ friend class ACE_Unbounded_Stack_Iterator<T>;
+
+ /// This isn't necessary, but it keeps some compilers happy.
+ ~ACE_Node (void);
+
+private:
+ // = Initialization methods
+ ACE_Node (const T &i, ACE_Node<T> *n);
+ ACE_Node (ACE_Node<T> *n = 0, int = 0);
+ ACE_Node (const ACE_Node<T> &n);
+private:
+ /// Not possible
+ void operator= (const ACE_Node<T> &);
+
+private:
+ /// Pointer to next element in the list of ACE_Nodes.
+ ACE_Node<T> *next_;
+
+ /// Current value of the item in this node.
+ T item_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Node.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Node.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_NODE_H */
diff --git a/ACE/ace/Notification_Queue.cpp b/ACE/ace/Notification_Queue.cpp
new file mode 100644
index 00000000000..ee0b6a31100
--- /dev/null
+++ b/ACE/ace/Notification_Queue.cpp
@@ -0,0 +1,222 @@
+// $Id$
+
+#include "ace/Notification_Queue.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Notification_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_Notification_Queue::
+ACE_Notification_Queue()
+ : ACE_Copy_Disabled()
+ , alloc_queue_()
+ , notify_queue_()
+ , free_queue_()
+{
+}
+
+ACE_Notification_Queue::
+~ACE_Notification_Queue()
+{
+ reset();
+}
+
+int
+ACE_Notification_Queue::
+open()
+{
+ ACE_TRACE ("ACE_Notification_Queue::open");
+
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
+
+ if (!this->free_queue_.is_empty ())
+ return 0;
+
+ return allocate_more_buffers();
+}
+
+void
+ACE_Notification_Queue::
+reset()
+{
+ ACE_TRACE ("ACE_Notification_Queue::reset");
+
+ // Release all the event handlers still in the queue ...
+ for (ACE_Notification_Queue_Node * node = notify_queue_.head();
+ node != 0;
+ node = node->next())
+ {
+ if (node->get().eh_ == 0)
+ {
+ continue;
+ }
+ (void) node->get().eh_->remove_reference();
+ }
+
+ // ... free up the dynamically allocated resources ...
+ ACE_Notification_Queue_Node **b = 0;
+ for (ACE_Unbounded_Queue_Iterator<ACE_Notification_Queue_Node *> alloc_iter (this->alloc_queue_);
+ alloc_iter.next (b) != 0;
+ alloc_iter.advance ())
+ {
+ delete [] *b;
+ *b = 0;
+ }
+
+ // ... cleanup the list of allocated blocks ...
+ this->alloc_queue_.reset ();
+
+ // ... swap with empty lists to reset the contents ...
+ Buffer_List().swap(notify_queue_);
+ Buffer_List().swap(free_queue_);
+}
+
+int ACE_Notification_Queue::
+allocate_more_buffers()
+{
+ ACE_TRACE ("ACE_Notification_Queue::allocate_more_buffers");
+
+ ACE_Notification_Queue_Node *temp = 0;
+
+ ACE_NEW_RETURN (temp,
+ ACE_Notification_Queue_Node[ACE_REACTOR_NOTIFICATION_ARRAY_SIZE],
+ -1);
+
+ if (this->alloc_queue_.enqueue_head (temp) == -1)
+ {
+ delete [] temp;
+ return -1;
+ }
+
+ for (size_t i = 0; i < ACE_REACTOR_NOTIFICATION_ARRAY_SIZE; ++i)
+ {
+ free_queue_.push_front(temp + i);
+ }
+
+ return 0;
+}
+
+int
+ACE_Notification_Queue::
+purge_pending_notifications(ACE_Event_Handler * eh,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Notification_Queue::purge_pending_notifications");
+
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
+
+ if (this->notify_queue_.is_empty ())
+ return 0;
+
+ int number_purged = 0;
+ ACE_Notification_Queue_Node * node = notify_queue_.head();
+ while(node != 0)
+ {
+ if (!node->matches_for_purging(eh))
+ {
+ // Easy case, skip to the next node
+ node = node->next();
+ continue;
+ }
+
+ if (!node->mask_disables_all_notifications(mask))
+ {
+ // ... another easy case, skip this node too, but clear the
+ // mask first ...
+ node->clear_mask(mask);
+ node = node->next();
+ continue;
+ }
+
+ // ... this is the more complicated case, we want to remove the
+ // node from the notify_queue_ list. First save the next node
+ // on the list:
+ ACE_Notification_Queue_Node * next = node->next();
+
+ // ... then remove it ...
+ notify_queue_.unsafe_remove(node);
+ ++number_purged;
+
+ // ... release resources ...
+ ACE_Event_Handler *event_handler = node->get().eh_;
+ event_handler->remove_reference ();
+
+ // ... now this is a free node ...
+ free_queue_.push_front(node);
+
+ // ... go to the next node, if there is one ...
+ node = next;
+ }
+
+ return number_purged;
+}
+
+int ACE_Notification_Queue::
+push_new_notification(
+ ACE_Notification_Buffer const & buffer)
+{
+ ACE_TRACE ("ACE_Notification_Queue::push_new_notification");
+
+ bool notification_required = false;
+
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
+
+ // No pending notifications.
+ if (this->notify_queue_.is_empty ())
+ notification_required = true;
+
+ if (free_queue_.is_empty())
+ {
+ if (allocate_more_buffers() == -1)
+ {
+ return -1;
+ }
+ }
+
+ ACE_Notification_Queue_Node * node =
+ free_queue_.pop_front();
+
+ ACE_ASSERT (node != 0);
+ node->set(buffer);
+
+ notify_queue_.push_back(node);
+
+ if (!notification_required)
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+ACE_Notification_Queue::pop_next_notification(
+ ACE_Notification_Buffer & current,
+ bool & more_messages_queued,
+ ACE_Notification_Buffer & next)
+{
+ ACE_TRACE ("ACE_Notification_Queue::pop_next_notification");
+
+ more_messages_queued = false;
+
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
+
+ if (notify_queue_.is_empty ())
+ {
+ return 0;
+ }
+
+ ACE_Notification_Queue_Node * node =
+ notify_queue_.pop_front();
+
+ current = node->get();
+ free_queue_.push_front(node);
+
+ if(!this->notify_queue_.is_empty())
+ {
+ more_messages_queued = true;
+ next = notify_queue_.head()->get();
+ }
+
+ return 1;
+}
diff --git a/ACE/ace/Notification_Queue.h b/ACE/ace/Notification_Queue.h
new file mode 100644
index 00000000000..d4cf815aada
--- /dev/null
+++ b/ACE/ace/Notification_Queue.h
@@ -0,0 +1,156 @@
+#ifndef ACE_NOTIFICATION_QUEUE_H
+#define ACE_NOTIFICATION_QUEUE_H
+
+#include /**/ "ace/pre.h"
+
+/**
+ * @file Notification_Queue.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@atdesk.com>
+ */
+#include "ace/Copy_Disabled.h"
+#include "ace/Event_Handler.h"
+#include "ace/Intrusive_List.h"
+#include "ace/Intrusive_List_Node.h"
+#include "ace/Unbounded_Queue.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Notification_Queue_Node
+ *
+ * @brief Helper class
+ */
+class ACE_Export ACE_Notification_Queue_Node
+ : public ACE_Intrusive_List_Node<ACE_Notification_Queue_Node>
+{
+public:
+ /**
+ * @brief Constructor
+ */
+ ACE_Notification_Queue_Node();
+
+ /**
+ * @brief Modifier change the contained buffer
+ */
+ void set(ACE_Notification_Buffer const & rhs);
+
+ /**
+ * @brief Accessor, fetch the contained buffer
+ */
+ ACE_Notification_Buffer const & get() const;
+
+ /**
+ * @brief Checks if the event handler matches the purge condition
+ */
+ bool matches_for_purging(ACE_Event_Handler * eh) const;
+
+ /**
+ * @brief Return true if clearing the mask would leave no
+ * notifications to deliver.
+ */
+ bool mask_disables_all_notifications(ACE_Reactor_Mask mask);
+
+ /**
+ * @brief Clear the notifications specified by @c mask
+ */
+ void clear_mask(ACE_Reactor_Mask mask);
+
+private:
+ ACE_Notification_Buffer contents_;
+};
+
+/**
+ * @class ACE_Notification_Queue
+ *
+ * @brief Implements a user-space queue to send Reactor notifications.
+ *
+ * The ACE_Reactor uses a pipe to send wake up the thread running the
+ * event loop from other threads. This pipe can be limited in size
+ * under some operating systems. For some applications, this limit
+ * presents a problem. A user-space notification queue is used to
+ * overcome those limitations. The queue tries to use as few
+ * resources on the pipe as possible, while keeping all the data in
+ * user space.
+ *
+ * This code was refactored from Select_Reactor_Base.
+ */
+class ACE_Export ACE_Notification_Queue : private ACE_Copy_Disabled
+{
+public:
+ ACE_Notification_Queue();
+ ~ACE_Notification_Queue();
+
+ /**
+ * @brief Pre-allocate resources in the queue
+ */
+ int open();
+
+ /**
+ * @brief Release all resources in the queue
+ */
+ void reset();
+
+ /**
+ * @brief Remove all elements in the queue matching @c eh and @c mask
+ *
+ * I suggest reading the documentation in ACE_Reactor to find a more
+ * detailed description. This is just a helper function.
+ */
+ int purge_pending_notifications(ACE_Event_Handler * eh,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * @brief Add a new notification to the queue
+ *
+ * @return -1 on failure, 1 if a new message should be sent through
+ * the pipe and 0 otherwise.
+ */
+ int push_new_notification(ACE_Notification_Buffer const & buffer);
+
+ /**
+ * @brief Extract the next notification from the queue
+ *
+ * @return -1 on failure, 1 if a message was popped, 0 otherwise
+ */
+ int pop_next_notification(
+ ACE_Notification_Buffer & current,
+ bool & more_messages_queued,
+ ACE_Notification_Buffer & next);
+
+private:
+ /**
+ * @brief Allocate more memory for the queue
+ */
+ int allocate_more_buffers();
+
+private:
+ /// Keeps track of allocated arrays of type
+ /// ACE_Notification_Buffer. The idea is to amortize allocation
+ /// costs by allocating multiple ACE_Notification_Buffer objects at
+ /// a time.
+ ACE_Unbounded_Queue <ACE_Notification_Queue_Node*> alloc_queue_;
+
+ typedef ACE_Intrusive_List<ACE_Notification_Queue_Node> Buffer_List;
+
+ /// Keeps track of all pending notifications.
+ Buffer_List notify_queue_;
+
+ /// Keeps track of all free buffers.
+ Buffer_List free_queue_;
+
+ /// Synchronization for handling of queues.
+ ACE_SYNCH_MUTEX notify_queue_lock_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Notification_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_NOTIFICATION_QUEUE_H */
diff --git a/ACE/ace/Notification_Queue.inl b/ACE/ace/Notification_Queue.inl
new file mode 100644
index 00000000000..b7ef09a820f
--- /dev/null
+++ b/ACE/ace/Notification_Queue.inl
@@ -0,0 +1,47 @@
+// $Id$
+
+ACE_INLINE ACE_Notification_Queue_Node::
+ACE_Notification_Queue_Node()
+ : ACE_Intrusive_List_Node<ACE_Notification_Queue_Node>()
+ , contents_(0, 0)
+{
+}
+
+ACE_INLINE void
+ACE_Notification_Queue_Node::
+set(ACE_Notification_Buffer const & rhs)
+{
+ contents_ = rhs;
+}
+
+ACE_INLINE ACE_Notification_Buffer const &
+ACE_Notification_Queue_Node::
+get() const
+{
+ return contents_;
+}
+
+ACE_INLINE bool
+ACE_Notification_Queue_Node::
+matches_for_purging(ACE_Event_Handler * eh) const
+{
+ return (0 != get().eh_) && (0 == eh || eh == get().eh_);
+}
+
+ACE_INLINE bool
+ACE_Notification_Queue_Node::
+mask_disables_all_notifications(ACE_Reactor_Mask mask)
+{
+ // the existing notification mask is left with nothing when applying
+ // the mask
+ return ACE_BIT_DISABLED (get().mask_, ~mask);
+}
+
+ACE_INLINE void
+ACE_Notification_Queue_Node::
+clear_mask(ACE_Reactor_Mask mask)
+{
+ ACE_CLR_BITS(contents_.mask_, mask);
+}
+
+
diff --git a/ACE/ace/Notification_Strategy.cpp b/ACE/ace/Notification_Strategy.cpp
new file mode 100644
index 00000000000..f12bf3a569e
--- /dev/null
+++ b/ACE/ace/Notification_Strategy.cpp
@@ -0,0 +1,22 @@
+#include "ace/Notification_Strategy.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Notification_Strategy.inl"
+#endif /* __ACE_INLINE __ */
+
+ACE_RCSID(ace, Strategies, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Notification_Strategy::ACE_Notification_Strategy (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+ : eh_ (eh),
+ mask_ (mask)
+{
+}
+
+ACE_Notification_Strategy::~ACE_Notification_Strategy (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Notification_Strategy.h b/ACE/ace/Notification_Strategy.h
new file mode 100644
index 00000000000..5fe5d836c05
--- /dev/null
+++ b/ACE/ace/Notification_Strategy.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Notification_Strategy.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+#ifndef ACE_NOTIFICATION_STRATEGY_H
+#define ACE_NOTIFICATION_STRATEGY_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Event_Handler.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls.
+class ACE_Reactor;
+
+/**
+ * @class ACE_Notification_Strategy
+ *
+ * @brief Abstract class used for notifying an interested party
+ *
+ * A vehicle for extending the behavior of ACE_Message_Queue wrt
+ * notification *without subclassing*. Thus, it's an example of
+ * the Bridge/Strategy patterns.
+ */
+class ACE_Export ACE_Notification_Strategy
+{
+public:
+ /// Constructor.
+ ACE_Notification_Strategy (ACE_Event_Handler *eh, ACE_Reactor_Mask mask);
+
+ /// Destructor.
+ virtual ~ACE_Notification_Strategy (void);
+
+ virtual int notify (void) = 0;
+ virtual int notify (ACE_Event_Handler *, ACE_Reactor_Mask mask) = 0;
+
+ /// Get the event handler.
+ ACE_Event_Handler *event_handler (void);
+
+ /// Set the event handler.
+ void event_handler (ACE_Event_Handler *eh);
+
+ /// Get the reactor mask.
+ ACE_Reactor_Mask mask (void) const;
+
+ /// Set the reactor mask.
+ void mask (ACE_Reactor_Mask m);
+
+protected:
+ /// The event handler.
+ ACE_Event_Handler *eh_;
+
+ /// The reactor mask.
+ ACE_Reactor_Mask mask_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Notification_Strategy.inl"
+#endif /* __ACE_INLINE __ */
+
+#include /**/ "ace/post.h"
+#endif /*ACE_NOTIFICATION_STRATEGY_H */
diff --git a/ACE/ace/Notification_Strategy.inl b/ACE/ace/Notification_Strategy.inl
new file mode 100644
index 00000000000..47479030ab6
--- /dev/null
+++ b/ACE/ace/Notification_Strategy.inl
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+//
+//$Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_Event_Handler *
+ACE_Notification_Strategy::event_handler (void)
+{
+ return eh_;
+}
+
+ACE_INLINE void
+ACE_Notification_Strategy::event_handler (ACE_Event_Handler *eh)
+{
+ this->eh_ = eh;
+}
+
+ACE_INLINE ACE_Reactor_Mask
+ACE_Notification_Strategy::mask (void) const
+{
+ return mask_;
+}
+
+ACE_INLINE void
+ACE_Notification_Strategy::mask (ACE_Reactor_Mask m)
+{
+ this->mask_ = m;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Null_Barrier.h b/ACE/ace/Null_Barrier.h
new file mode 100644
index 00000000000..9b3bc16912a
--- /dev/null
+++ b/ACE/ace/Null_Barrier.h
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Null_Barrier.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_NULL_BARRIER_H
+#define ACE_NULL_BARRIER_H
+#include /**/ "ace/pre.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// All methods in this class are inline, so there is no
+// need to import or export on Windows. -- CAE 12/18/2003
+
+/**
+ * @class ACE_Null_Barrier
+ *
+ * @brief Implements "NULL barrier synchronization".
+ */
+class ACE_Null_Barrier
+{
+public:
+ /// Initialize the barrier to synchronize <count> threads.
+ ACE_Null_Barrier (unsigned int,
+ const char * = 0,
+ void * = 0) {};
+
+ /// Default dtor.
+ ~ACE_Null_Barrier (void) {};
+
+ /// Block the caller until all <count> threads have called <wait> and
+ /// then allow all the caller threads to continue in parallel.
+ int wait (void) { return 0; };
+
+ /// Dump the state of an object.
+ void dump (void) const {};
+
+ /// Declare the dynamic allocation hooks.
+ //ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Null_Barrier &);
+ ACE_Null_Barrier (const ACE_Null_Barrier &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_NULL_BARRIER_H */
diff --git a/ACE/ace/Null_Condition.h b/ACE/ace/Null_Condition.h
new file mode 100644
index 00000000000..e67f2a0bb41
--- /dev/null
+++ b/ACE/ace/Null_Condition.h
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Null_Condition.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_NULL_CONDITION_H
+#define ACE_NULL_CONDITION_H
+#include /**/ "ace/pre.h"
+
+// All methods in this class are inline, so there is no
+// need to import or export on Windows. -- CAE 12/18/2003
+#include "ace/Null_Mutex.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Null_Condition
+ *
+ * @brief Implement a do nothing ACE_Condition variable wrapper,
+ * i.e., all methods are no ops. This class is necessary since
+ * some C++ compilers are *very* lame...
+ */
+class ACE_Null_Condition
+{
+public:
+ ACE_Null_Condition (const ACE_Null_Mutex &m,
+ const ACE_TCHAR * = 0,
+ void * = 0)
+ : mutex_ ((ACE_Null_Mutex &) m) {}
+
+ ~ACE_Null_Condition (void) {}
+
+ /// Returns 0.
+ int remove (void) {return 0;}
+
+ /// Returns -1 with @c errno == @c ETIME.
+ int wait (const ACE_Time_Value * = 0) {errno = ETIME; return -1;}
+
+ /// Returns -1 with @c errno == @c ETIME.
+ int wait (ACE_Null_Mutex &,
+ const ACE_Time_Value * = 0) {errno = ETIME; return -1;}
+
+ /// Returns 0.
+ int signal (void) {return 0;}
+
+ /// Returns 0.
+ int broadcast (void) {return 0;}
+ ACE_Null_Mutex &mutex (void) {return this->mutex_;};
+
+ /// Dump the state of an object.
+ void dump (void) const {}
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+protected:
+ ACE_Null_Mutex &mutex_; // Reference to mutex lock.
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Null_Condition &);
+ ACE_Null_Condition (const ACE_Null_Condition &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_NULL_CONDITION_H */
diff --git a/ACE/ace/Null_Mutex.h b/ACE/ace/Null_Mutex.h
new file mode 100644
index 00000000000..8d68c709d5a
--- /dev/null
+++ b/ACE/ace/Null_Mutex.h
@@ -0,0 +1,232 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Null_Mutex.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_NULL_MUTEX_H
+#define ACE_NULL_MUTEX_H
+#include /**/ "ace/pre.h"
+
+// All methods in this class are inline, so there is no
+// need to import or export on Windows. -- CAE 12/18/2003
+// Update... leaving off the ACE_Export causes compile warnings in some
+// cases with Microsoft Visual Studio .NET 2005, so I added the ACE_Export
+// to these class declarations. Steve Huston, 12/8/2006.
+
+#include "ace/os_include/os_errno.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+#include "ace/OS_Memory.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Null_Mutex
+ *
+ * @brief Implement a do nothing ACE_Mutex, i.e., all the methods are
+ * no ops.
+ */
+class ACE_Export ACE_Null_Mutex
+{
+public:
+ ACE_Null_Mutex (const ACE_TCHAR * = 0)
+ : lock_ (0) {}
+ ~ACE_Null_Mutex (void) {}
+ /// Return 0.
+ int remove (void) {return 0;}
+
+ /// Return 0.
+ int acquire (void) {return 0;}
+
+ /// Return -1 with @c errno == @c ETIME.
+ int acquire (ACE_Time_Value &) {errno = ETIME; return -1;}
+
+ /// Return -1 with @c errno == @c ETIME.
+ int acquire (ACE_Time_Value *) {errno = ETIME; return -1;}
+
+ /// Return 0.
+ int tryacquire (void) {return 0;}
+
+ /// Return 0.
+ int release (void) {return 0;}
+
+ /// Return 0.
+ int acquire_write (void) {return 0;}
+
+ /// Return 0.
+ int tryacquire_write (void) {return 0;}
+
+ /// Return 0.
+ int tryacquire_write_upgrade (void) {return 0;}
+
+ /// Return 0.
+ int acquire_read (void) {return 0;}
+
+ /// Return 0.
+ int tryacquire_read (void) {return 0;}
+
+ /// Dump the state of an object.
+ void dump (void) const {}
+
+ /// Declare the dynamic allocation hooks.
+ //ACE_ALLOC_HOOK_DECLARE;
+
+ int lock_; // A dummy lock.
+};
+
+#if defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
+/**
+ * @class ACE_Null_Mutex_Guard
+ *
+ * @brief This data structure is meant to be used within a method or
+ * function... It performs automatic aquisition and release of
+ * an ACE_Null_Mutex.
+ *
+ * This class is obsolete and should be replaced by
+ * ACE_Guard<ACE_Null_Mutex>.
+ */
+class ACE_Export ACE_Null_Mutex_Guard
+{
+public:
+ ACE_Null_Mutex_Guard (ACE_Null_Mutex &) {}
+ ~ACE_Null_Mutex_Guard (void) {}
+ int remove (void) {return 0;}
+ int locked (void) {return 1;}
+ int acquire (void) {return 0;}
+ int tryacquire (void) {return 0;}
+ int release (void) {return 0:}
+ void dump (void) const {}
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Null_Mutex_Guard &);
+ ACE_Null_Mutex_Guard (const ACE_Null_Mutex_Guard &);
+};
+#endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
+
+template <class ACE_LOCK>
+class ACE_Guard;
+
+/**
+ * @class ACE_Guard<ACE_Null_Mutex>
+ *
+ * @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.
+ */
+template<>
+class ACE_Export ACE_Guard<ACE_Null_Mutex>
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Guard (ACE_Null_Mutex &) {}
+ ACE_Guard (ACE_Null_Mutex &, int) {}
+ ACE_Guard (ACE_Null_Mutex &, int, int) {}
+#if defined (ACE_WIN32)
+ ~ACE_Guard (void) {}
+#endif /* ACE_WIN32 */
+
+ int acquire (void) { return 0; }
+ int tryacquire (void) { return 0; }
+ int release (void) { return 0; }
+ void disown (void) {}
+ int locked (void) { return 1; }
+ int remove (void) { return 0; }
+ void dump (void) const {}
+
+private:
+
+ // Disallow copying and assignment.
+ ACE_Guard (const ACE_Guard<ACE_Null_Mutex> &);
+ void operator= (const ACE_Guard<ACE_Null_Mutex> &);
+
+};
+
+template <class ACE_LOCK>
+class ACE_Write_Guard;
+
+/**
+ * @class ACE_Write_Guard<ACE_Null_Mutex>
+ *
+ */
+template<>
+class ACE_Export ACE_Write_Guard<ACE_Null_Mutex>
+ : public ACE_Guard<ACE_Null_Mutex>
+{
+public:
+ ACE_Write_Guard (ACE_Null_Mutex &m)
+ : ACE_Guard<ACE_Null_Mutex> (m) {}
+ ACE_Write_Guard (ACE_Null_Mutex &m, int blocked)
+ : ACE_Guard<ACE_Null_Mutex> (m, blocked) {}
+
+ int acquire_write (void) { return 0; }
+ int acquire (void) { return 0; }
+ int tryacquire_write (void) { return 0; }
+ int tryacquire (void) { return 0; }
+ void dump (void) const {}
+};
+
+template <class ACE_LOCK>
+class ACE_Read_Guard;
+
+/**
+ * @class ACE_Read_Guard<ACE_Null_Mutex>
+ *
+ */
+template<>
+class ACE_Export ACE_Read_Guard<ACE_Null_Mutex>
+ : public ACE_Guard<ACE_Null_Mutex>
+{
+public:
+ ACE_Read_Guard (ACE_Null_Mutex &m)
+ : ACE_Guard<ACE_Null_Mutex> (m) {}
+ ACE_Read_Guard (ACE_Null_Mutex &m, int blocked)
+ : ACE_Guard<ACE_Null_Mutex> (m, blocked) {}
+
+ int acquire_read (void) { return 0; }
+ int acquire (void) { return 0; }
+ int tryacquire_read (void) { return 0; }
+ int tryacquire (void) { return 0; }
+ void dump (void) const {}
+};
+
+template <class T> class ACE_Malloc_Lock_Adapter_T;
+
+/**
+ * @class ACE_Malloc_Lock_Adapter_T<ACE_Null_Mutex>
+ *
+ */
+template<>
+class ACE_Export ACE_Malloc_Lock_Adapter_T<ACE_Null_Mutex>
+{
+public:
+ ACE_Null_Mutex * operator () (const ACE_TCHAR *name)
+ {
+ ACE_Null_Mutex *p;
+ ACE_NEW_RETURN (p, ACE_Null_Mutex (name), 0);
+ return p;
+ }
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_NULL_MUTEX_H */
diff --git a/ACE/ace/Null_Semaphore.h b/ACE/ace/Null_Semaphore.h
new file mode 100644
index 00000000000..23650db7518
--- /dev/null
+++ b/ACE/ace/Null_Semaphore.h
@@ -0,0 +1,105 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Null_Semaphore.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_NULL_SEMAPHORE_H
+#define ACE_NULL_SEMAPHORE_H
+#include /**/ "ace/pre.h"
+
+// All methods in this class are inline, so there is no
+// need to import or export on Windows. -- CAE 12/18/2003
+#include "ace/os_include/os_errno.h"
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Null_Semaphore
+ *
+ * @brief Implement a do nothing ACE_Semaphore, i.e., all the methods are
+ * no ops.
+ *
+ * Although the methods are no-ops, the return values are different for
+ * the blocking as opposed to timed acquires. The blocking version of
+ * acquire() is often used to serialize access to a critical section,
+ * whereas the timed version is often used to wait for another thread
+ * to update some condition or change some shared state. When using an
+ * ACE_Null_Semaphore, however, there's no other thread involved to
+ * change a state or condition (otherwise, a null semaphore would be
+ * inappropriate). Returning an error value signifies that the
+ * state or condition has not been (and can't be) changed, which is
+ * consistent with the behavior of the threaded case where a timeout
+ * occurs before the state or condition is changed.
+ */
+class ACE_Null_Semaphore
+{
+public:
+ ACE_Null_Semaphore (unsigned int = 1,
+ int = 0,
+ const ACE_TCHAR * = 0,
+ void * = 0,
+ int = 0x7fffffff) {}
+ ~ACE_Null_Semaphore (void) {}
+ /// Return 0.
+ int remove (void) {return 0;}
+
+ /// Return 0.
+ int acquire (void) {return 0;}
+
+ /// Return -1 with @c errno == @c ETIME.
+ int acquire (ACE_Time_Value &) {errno = ETIME; return -1;}
+
+ /// Return -1 with @c errno == @c ETIME.
+ int acquire (ACE_Time_Value *) {errno = ETIME; return -1;}
+
+ /// Return 0.
+ int tryacquire (void) {return 0;}
+
+ /// Return 0.
+ int release (void) {return 0;}
+
+ /// Return 0.
+ int release (size_t) {return 0;}
+
+ /// Return 0.
+ int acquire_write (void) {return 0;}
+
+ /// Return 0.
+ int tryacquire_write (void) {return 0;}
+
+ /// Return 0.
+ int tryacquire_write_upgrade (void) {return 0;}
+
+ /// Return 0.
+ int acquire_read (void) {return 0;}
+
+ /// Return 0.
+ int tryacquire_read (void) {return 0;}
+
+ /// Dump the state of an object.
+ void dump (void) const {}
+
+ /// Declare the dynamic allocation hooks.
+ //ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_NULL_SEMAPHORE_H */
diff --git a/ACE/ace/Numeric_Limits.h b/ACE/ace/Numeric_Limits.h
new file mode 100644
index 00000000000..d50abb19f98
--- /dev/null
+++ b/ACE/ace/Numeric_Limits.h
@@ -0,0 +1,270 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Numeric_Limits.h
+ *
+ * $Id$
+ *
+ * Traits containing basic integer limits. Useful for template-based
+ * code on platforms that lack @c std::numeric_limits<>.
+ *
+ * @note These traits are not meant to be a replacement for
+ * @c std::numeric_limits<>. Rather they are a crutch until all
+ * ACE-supported platforms also support
+ * @c std::numeric_limits<>.
+ *
+ * @internal Only meant for internal use by ACE.
+ * @deprecated This header will be removed once all platforms
+ * supported by ACE support @c std::numeric_limits<>.
+ *
+ * @author Ossama Othman <ossama_othman at symantec dot com>
+ */
+//=============================================================================
+
+#ifndef ACE_NUMERIC_LIMITS_H
+#define ACE_NUMERIC_LIMITS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#ifdef ACE_LACKS_NUMERIC_LIMITS
+# include "ace/Basic_Types.h"
+#else
+
+# ifdef __MINGW32__
+// Windows defines min/max macros that interfere with the
+// numeric_limits::min/max() traits. Undefine those macros before
+// including <limits>.
+//
+// Ideally, we could prevent those macros from being defined by
+// defining the Windows-specific NOMINMAX symbol before any Windows
+// headers are included, preferrably on the command line. However,
+// that would probably break some applications.
+//
+// @@ Why isn't this a problem with MSVC++ and Borland builds?
+# undef min
+# undef max
+# endif /* __MINGW32__ */
+
+# if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+// For ACE_U_LongLong.
+# include "ace/Basic_Types.h"
+# endif /* ACE_LACKS_LONGLONG_T || ACE_LACKS_UNSIGNEDLONGLONG_T */
+
+# include <limits>
+#endif /* ACE_LACKS_NUMERIC_LIMITS */
+
+// Address global namespace pollution potentially incurred by some
+// platforms.
+#undef min
+#undef max
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#ifdef ACE_LACKS_NUMERIC_LIMITS
+
+template <typename T> struct ACE_Numeric_Limits;
+
+
+// ------------------------------------------
+// Special cases.
+template<>
+struct ACE_Export ACE_Numeric_Limits<char>
+{
+ static char min (void) { return CHAR_MIN; }
+ static char max (void) { return CHAR_MAX; }
+};
+
+// ------------------------------------------
+// Signed integers.
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<signed char>
+{
+ static signed char min (void) { return SCHAR_MIN; }
+ static signed char max (void) { return SCHAR_MAX; }
+};
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<signed short>
+{
+ static signed short min (void) { return SHRT_MIN; }
+ static signed short max (void) { return SHRT_MAX; }
+};
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<signed int>
+{
+ static signed int min (void) { return INT_MIN; }
+ static signed int max (void) { return INT_MAX; }
+};
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<signed long>
+{
+ static signed long min (void) { return LONG_MIN; }
+ static signed long max (void) { return LONG_MAX; }
+};
+
+// #ifndef ACE_LACKS_LONGLONG_T
+// template<>
+// struct ACE_Export ACE_Numeric_Limits<signed long long>
+// {
+// #if defined (LLONG_MIN)
+// # define ACE_LLONG_MIN LLONG_MIN
+// #elif defined (LONG_LONG_MIN)
+// # define ACE_LLONG_MIN LONG_LONG_MIN
+// #elif defined (LONGLONG_MIN)
+// # define ACE_LLONG_MIN LONGLONG_MIN
+// #else
+// # error Unable to determine minimum signed long long value.
+// #endif /* LLONG_MIN */
+
+// #if defined (LLONG_MAX)
+// # define ACE_LLONG_MAX LLONG_MAX
+// #elif defined (LONG_LONG_MAX)
+// # define ACE_LLONG_MAX LONG_LONG_MAX
+// #elif defined (LONGLONG_MAX)
+// # define ACE_LLONG_MAX LONGLONG_MAX
+// #else
+// # error Unable to determine maximum signed long long value.
+// #endif /* LLONG_MAX */
+
+// static signed long long min (void) { return ACE_LLONG_MIN; }
+// static signed long long max (void) { return ACE_LLONG_MAX; }
+// };
+// #endif /* !ACE_LACKS_LONGLONG_T */
+
+// ------------------------------------------
+// Unsigned integers
+template<>
+struct ACE_Export ACE_Numeric_Limits<unsigned char>
+{
+ static unsigned char min (void) { return 0; }
+ static unsigned char max (void) { return UCHAR_MAX; }
+};
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<unsigned short>
+{
+ static unsigned short min (void) { return 0; }
+ static unsigned short max (void) { return USHRT_MAX; }
+};
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<unsigned int>
+{
+ static unsigned int min (void) { return 0; }
+ static unsigned int max (void) { return UINT_MAX; }
+};
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<unsigned long>
+{
+ static unsigned long min (void) { return 0; }
+ static unsigned long max (void) { return ULONG_MAX; }
+};
+
+// #ifndef ACE_LACKS_LONGLONG_T
+// template<>
+// struct ACE_Export ACE_Numeric_Limits<unsigned long long>
+// {
+// static unsigned long long min (void) { return 0; }
+// static unsigned long long max (void)
+// {
+// # if defined (ULLONG_MAX)
+// return ULLONG_MAX;
+// # elif defined (ULONGLONG_MAX)
+// return ULONGLONG_MAX;
+// # else
+// # error Unable to determine maximum unsigned long long value.
+// # endif /* ULLONG_MAX */
+// }
+// };
+// #endif /* !ACE_LACKS_LONGLONG_T */
+
+// ------------------------------------------
+// Floating point types
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<float>
+{
+ static float min (void) { return FLT_MIN; }
+ static float max (void) { return FLT_MAX; }
+};
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<double>
+{
+ static double min (void) { return DBL_MIN; }
+ static double max (void) { return DBL_MAX; }
+};
+
+template<>
+struct ACE_Export ACE_Numeric_Limits<long double>
+{
+ static long double min (void) { return LDBL_MIN; }
+ static long double max (void) { return LDBL_MAX; }
+};
+
+#else
+
+// std::numeric_limits<> has all of the necessary specializations.
+// Just wrap it.
+
+template <typename T>
+struct ACE_Numeric_Limits
+{
+ static T min (void) { return std::numeric_limits<T>::min (); }
+ static T max (void) { return std::numeric_limits<T>::max (); }
+};
+
+# if (defined (ACE_WIN64) && defined (_MSC_VER) && _MSC_VER <= 1310) \
+ || defined (ACE_LACKS_NUMERIC_LIMITS_64_BIT_TYPES)
+// The Microsoft Platform SDK does not provide std::numeric_limits<>
+// specializations for 64 bit integers so we need to explicitly provide
+// ACE_Numeric_Limits<> specializations to compensate for this
+// deficiency.
+//
+// Unfortunately there is no way to tell if the platform SDK is being
+// used so we specialize for the ACE_WIN64 + MSVC++ 7.1 case, which is
+// the configuration that exhibits this problem. It also happens to
+// be a fairly isolated configuration since 64-bit support in MSVC++
+// 7.1 was not very good to begin with.
+template<>
+struct ACE_Numeric_Limits<LONGLONG>
+{
+ static LONGLONG min (void) { return _I64_MIN; }
+ static LONGLONG max (void) { return _I64_MAX; }
+};
+
+template<>
+struct ACE_Numeric_Limits<ULONGLONG>
+{
+ static ULONGLONG min (void) { return 0; }
+ static ULONGLONG max (void) { return _UI64_MAX; }
+};
+# endif /* ACE_WIN64 && _MSC_VER <= 1310 */
+
+#endif /* ACE_LACKS_NUMERIC_LIMITS */
+
+#if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+template<>
+struct ACE_Numeric_Limits<ACE_U_LongLong>
+{
+ static ACE_U_LongLong min (void) { return ACE_U_LongLong (); /* 0 */ }
+ static ACE_U_LongLong max (void) { return ACE_UINT64_MAX; }
+};
+#endif /* ACE_LACKS_LONGLONG_T || defined ACE_LACKS_UNSIGNEDLONGLONG_T */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_NUMERIC_LIMITS_H */
diff --git a/ACE/ace/OS.cpp b/ACE/ace/OS.cpp
new file mode 100644
index 00000000000..a1ea80d7307
--- /dev/null
+++ b/ACE/ace/OS.cpp
@@ -0,0 +1,53 @@
+// $Id$
+
+// FUZZ: disable check_for_OS_h_include
+#include "ace/OS.h"
+
+#if !defined (ACE_HAS_WINCE)
+# include "ace/OS_QoS.h"
+#endif // ACE_HAS_WINCE
+
+// Perhaps we should *always* include ace/OS.i in order to make sure
+// we can always link against the OS symbols?
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+ACE_RCSID(ace, OS, "$Id$")
+
+// include new cpps
+#include "ace/Cleanup.cpp"
+#include "ace/Object_Manager_Base.cpp"
+#include "ace/OS_main.cpp"
+#include "ace/OS_NS_arpa_inet.cpp"
+#include "ace/OS_NS_ctype.cpp"
+#include "ace/OS_NS_dirent.cpp"
+#include "ace/OS_NS_dlfcn.cpp"
+#include "ace/OS_NS_errno.cpp"
+#include "ace/OS_NS_fcntl.cpp"
+#include "ace/OS_NS_math.cpp"
+#include "ace/OS_NS_netdb.cpp"
+#include "ace/OS_NS_poll.cpp"
+#include "ace/OS_NS_pwd.cpp"
+#include "ace/OS_NS_regex.cpp"
+#include "ace/OS_NS_signal.cpp"
+#include "ace/OS_NS_stdio.cpp"
+#include "ace/OS_NS_stdlib.cpp"
+#include "ace/OS_NS_string.cpp"
+#include "ace/OS_NS_strings.cpp"
+#include "ace/OS_NS_stropts.cpp"
+#include "ace/OS_NS_sys_mman.cpp"
+#include "ace/OS_NS_sys_msg.cpp"
+#include "ace/OS_NS_sys_resource.cpp"
+#include "ace/OS_NS_sys_select.cpp"
+#include "ace/OS_NS_sys_shm.cpp"
+#include "ace/OS_NS_sys_socket.cpp"
+#include "ace/OS_NS_sys_stat.cpp"
+#include "ace/OS_NS_sys_time.cpp"
+#include "ace/OS_NS_sys_uio.cpp"
+#include "ace/OS_NS_sys_utsname.cpp"
+#include "ace/OS_NS_sys_wait.cpp"
+#include "ace/OS_NS_Thread.cpp"
+#include "ace/OS_NS_time.cpp"
+#include "ace/OS_NS_unistd.cpp"
+#include "ace/OS_NS_wchar.cpp"
diff --git a/ACE/ace/OS.h b/ACE/ace/OS.h
new file mode 100644
index 00000000000..dda4c475b41
--- /dev/null
+++ b/ACE/ace/OS.h
@@ -0,0 +1,329 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ */
+//=============================================================================
+
+#ifndef ACE_OS_H
+#define ACE_OS_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 (DO_NOT_INCLUDE_OS_H)
+#include "ace/Cleanup.h"
+#include "ace/Object_Manager_Base.h"
+#include "ace/OS_main.h"
+#include "ace/OS_NS_arpa_inet.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_dirent.h"
+#include "ace/OS_NS_dlfcn.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_math.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/OS_NS_poll.h"
+#include "ace/OS_NS_pwd.h"
+#include "ace/OS_NS_regex.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_strings.h"
+#include "ace/OS_NS_stropts.h"
+#include "ace/OS_NS_sys_mman.h"
+#include "ace/OS_NS_sys_msg.h"
+#include "ace/OS_NS_sys_resource.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_NS_sys_shm.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_sys_uio.h"
+#include "ace/OS_NS_sys_utsname.h"
+#include "ace/OS_NS_sys_wait.h"
+#include "ace/OS_NS_Thread.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_wchar.h"
+
+// Include the split up ACE_OS classes
+#include "ace/OS_Dirent.h"
+#include "ace/OS_String.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_TLI.h"
+#include "ace/OS_Errno.h"
+
+#include "ace/os_include/os_dlfcn.h"
+#include "ace/os_include/sys/os_mman.h"
+#include "ace/os_include/os_netdb.h"
+#include "ace/os_include/sys/os_socket.h"
+#include "ace/os_include/net/os_if.h"
+#include "ace/os_include/sys/os_sem.h"
+
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Timeout_Manager;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Here are all ACE-specific default constants, needed throughout ACE
+// and its applications. The values can be over written by user
+// specific values in config.h files.
+#include "ace/Default_Constants.h"
+
+// Here are all ACE-specific global declarations needed throughout
+// ACE.
+#include "ace/Global_Macros.h"
+
+// include the ACE min()/max() functions.
+# include "ace/Min_Max.h"
+
+///////////////////////////////////////////
+// //
+// NOTE: Please do not add any #includes //
+// before this point. On VxWorks, //
+// vxWorks.h must be #included //
+// first! //
+// //
+///////////////////////////////////////////
+
+#include "ace/os_include/netinet/os_tcp.h"
+#include "ace/os_include/sys/os_stat.h"
+#include "ace/os_include/os_stropts.h"
+#include "ace/os_include/os_unistd.h"
+#include "ace/os_include/sys/os_wait.h"
+
+
+// This needs to go here *first* to avoid problems with AIX.
+# if defined (ACE_HAS_PTHREADS)
+# include "ace/os_include/os_pthread.h"
+# endif /* ACE_HAS_PTHREADS */
+
+# if defined (ACE_HAS_PROC_FS)
+# include /**/ <sys/procfs.h>
+# endif /* ACE_HAS_PROC_FS */
+
+# if defined (ACE_HAS_POSIX_SEM)
+# include "ace/os_include/os_semaphore.h"
+# endif /* ACE_HAS_POSIX_SEM */
+
+#include "ace/os_include/sys/os_types.h"
+#include "ace/os_include/os_stddef.h"
+#if !defined (ACE_LACKS_UNISTD_H)
+# include "ace/os_include/os_unistd.h"
+#endif /* ACE_LACKS_UNISTD_H */
+
+// Standard C Library includes
+# if !defined (ACE_HAS_WINCE)
+# include "ace/os_include/os_assert.h"
+# include "ace/os_include/os_stdio.h"
+
+# if !defined (ACE_LACKS_NEW_H)
+# if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+# include /**/ <new>
+# else
+# include /**/ <new.h>
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+# endif /* ! ACE_LACKS_NEW_H */
+
+# if !defined (ACE_VXWORKS)
+# define ACE_DONT_INCLUDE_ACE_SIGNAL_H
+# include "ace/os_include/os_signal.h"
+# undef ACE_DONT_INCLUDE_ACE_SIGNAL_H
+# endif /* ! VXWORKS */
+
+# include "ace/os_include/os_fcntl.h"
+# endif /* ACE_HAS_WINCE */
+
+# include "ace/os_include/os_limits.h"
+# include "ace/os_include/os_ctype.h"
+# include "ace/os_include/os_string.h"
+# include "ace/os_include/os_stdlib.h"
+# include "ace/os_include/os_float.h"
+
+# if defined (ACE_NEEDS_SCHED_H)
+# include "ace/os_include/os_sched.h"
+# endif /* ACE_NEEDS_SCHED_H */
+
+# include "ace/iosfwd.h"
+
+# if !defined (ACE_HAS_WINCE)
+# include "ace/os_include/os_fcntl.h"
+# endif /* ACE_HAS_WINCE */
+
+# if defined ACE_HAS_BYTESEX_H
+# include /**/ <bytesex.h>
+# endif /* ACE_HAS_BYTESEX_H */
+# include "ace/Basic_Types.h"
+
+# if defined (ACE_HAS_UTIME)
+# include "ace/os_include/os_utime.h"
+# endif /* ACE_HAS_UTIME */
+
+# if defined (ACE_WIN32)
+
+# if !defined (ACE_HAS_WINCE)
+# include "ace/os_include/sys/os_timeb.h"
+# endif /* ACE_HAS_WINCE */
+
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+# include "ace/os_include/netinet/os_in.h" // <ws2tcpip.h>
+# endif /* ACE_HAS_WINSOCK2 */
+
+# if !defined (ACE_HAS_WINCE)
+# include "ace/os_include/os_time.h"
+# include "ace/os_include/sys/os_stat.h" // <direct.h>
+# include "ace/os_include/os_unistd.h" // <process.h>
+# endif /* ACE_HAS_WINCE */
+
+# include "ace/os_include/os_fcntl.h"
+
+# else /* !defined (ACE_WIN32) */
+
+# if defined (CYGWIN32)
+# include "ace/os_include/sys/os_uio.h"
+# include "ace/os_include/os_fcntl.h" // <sys/file.h>
+# include "ace/os_include/sys/os_time.h"
+# include "ace/os_include/sys/os_resource.h"
+# include "ace/os_include/sys/os_wait.h"
+# include "ace/os_include/os_pwd.h"
+# elif defined (__QNX__)
+# include "ace/os_include/sys/os_uio.h"
+# include "ace/os_include/sys/os_ipc.h"
+# include "ace/os_include/sys/os_time.h"
+# include "ace/os_include/sys/os_wait.h"
+# include "ace/os_include/sys/os_resource.h"
+# include "ace/os_include/os_pwd.h"
+ // sets O_NDELAY
+# include /**/ <unix.h>
+# include "ace/os_include/os_limits.h" // <sys/param.h> /* for NBBY */
+# elif defined(ACE_HAS_RTEMS)
+# include "ace/os_include/os_fcntl.h" // <sys/file.h>
+# include "ace/os_include/sys/os_resource.h"
+# include "ace/os_include/sys/os_time.h"
+# include "ace/os_include/sys/os_utsname.h"
+# include "ace/os_include/sys/os_wait.h"
+# include "ace/os_include/os_pwd.h"
+
+# elif ! defined (ACE_VXWORKS) && ! defined (INTEGRITY)
+# include "ace/os_include/sys/os_uio.h"
+# include "ace/os_include/sys/os_ipc.h"
+# if !defined(ACE_LACKS_SYSV_SHMEM)
+// No reason to #include this if the platform lacks support for SHMEM
+# include "ace/os_include/sys/os_shm.h"
+# endif /* ACE_LACKS_SYSV_SHMEM */
+# include "ace/os_include/os_fcntl.h" // <sys/file.h>
+# include "ace/os_include/sys/os_time.h"
+# include "ace/os_include/sys/os_resource.h"
+# include "ace/os_include/sys/os_wait.h"
+# include "ace/os_include/os_pwd.h"
+# endif /* ! VXWORKS */
+# include "ace/os_include/os_stropts.h" // <sys/ioctl.h>
+
+// IRIX5 defines bzero() in this odd file...
+# if defined (ACE_HAS_BSTRING)
+# include /**/ <bstring.h>
+# endif /* ACE_HAS_BSTRING */
+
+// AIX defines bzero() in this odd file...
+# if defined (ACE_HAS_STRINGS)
+# include "ace/os_include/os_strings.h"
+# endif /* ACE_HAS_STRINGS */
+
+# if defined (ACE_HAS_TERMIOS)
+# include "ace/os_include/os_termios.h"
+# endif /* ACE_HAS_TERMIOS */
+
+# if defined (ACE_HAS_AIO_CALLS)
+# include "ace/os_include/os_aio.h"
+# endif /* ACE_HAS_AIO_CALLS */
+
+# include "ace/os_include/os_limits.h" // <sys/param.h>
+
+# if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+# include "ace/os_include/sys/os_un.h"
+# endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+
+# if defined (ACE_HAS_POLL)
+# include "ace/os_include/os_poll.h"
+# endif /* ACE_HAS_POLL */
+
+# if defined (ACE_HAS_SELECT_H)
+# include "ace/os_include/sys/os_select.h"
+# endif /* ACE_HAS_SELECT_H */
+
+# include "ace/os_include/sys/os_msg.h"
+
+# if defined (ACE_HAS_PRIOCNTL)
+# include /**/ <sys/priocntl.h>
+# endif /* ACE_HAS_PRIOCNTL */
+
+# endif /* !defined (ACE_WIN32) */
+
+# if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SYSLOG)
+# include "ace/os_include/os_syslog.h"
+# endif /* !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SYSLOG) */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @namespace ACE_OS
+ *
+ * @brief This namespace defines an OS independent programming API that
+ * shields developers from nonportable aspects of writing
+ * efficient system programs on Win32, POSIX and other versions
+ * of UNIX, and various real-time operating systems.
+ *
+ * This namespace encapsulates the differences between various OS
+ * platforms. When porting ACE to a new platform, this class is
+ * the place to focus on. Once this file is ported to a new
+ * platform, pretty much everything else comes for "free." See
+ * <www.cs.wustl.edu/~schmidt/ACE_wrappers/etc/ACE-porting.html>
+ * for instructions on porting ACE. Please see the README file
+ * in this directory for complete information on the meaning of
+ * the various macros.
+ */
+namespace ACE_OS
+{
+ // = A set of wrappers for miscellaneous operations.
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if defined (ACE_LEGACY_MODE)
+# include "ace/Log_Msg.h"
+# include "ace/Thread_Hook.h"
+# include "ace/Thread_Adapter.h"
+# include "ace/Thread_Exit.h"
+# include "ace/Thread_Control.h"
+#endif /* ACE_LEGACY_MODE */
+
+#endif /* 0 */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_H */
diff --git a/ACE/ace/OS.inl b/ACE/ace/OS.inl
new file mode 100644
index 00000000000..e4b063a57f3
--- /dev/null
+++ b/ACE/ace/OS.inl
@@ -0,0 +1,93 @@
+// -*- C++ -*-
+// $Id$
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# undef ACE_INLINE
+# define ACE_INLINE
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if defined (ACE_HAS_XLI)
+# include /**/ <xliuser.h>
+#endif /* ACE_HAS_XLI */
+
+#if !defined (ACE_HAS_CPLUSPLUS_HEADERS)
+# include /**/ <libc.h>
+# include /**/ <osfcn.h>
+#endif /* ACE_HAS_CPLUSPLUS_HEADERS */
+
+#if defined (ACE_HAS_SYSENT_H)
+# include /**/ <sysent.h>
+#endif /* ACE_HAS_SYSENT_H */
+
+#if defined (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB) && \
+ (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB != 0)
+using std::bsearch;
+using std::qsort;
+# if defined (ACE_WIN32)
+using std::_tzset;
+# else
+using std::tzset;
+# endif
+using std::ctime;
+using std::localtime;
+using std::gmtime;
+using std::asctime;
+using std::strftime;
+#endif /* ACE_USES_STD_NAMESPACE_FOR_STDC_LIB */
+
+#if !defined (ACE_LACKS_MALLOC_H)
+# include /**/ <malloc.h>
+#endif /* ACE_LACKS_MALLOC_H */
+
+#if !defined (ACE_WIN32)
+
+// Matthew Stevens 7-10-95 Fix GNU GCC 2.7 for memchr() problem.
+# if defined (ACE_HAS_GNU_CSTRING_H)
+// Define this file to keep /usr/include/memory.h from being included.
+# include /**/ <cstring>
+# else
+# if defined (ACE_LACKS_MEMORY_H)
+# include "ace/os_include/os_string.h"
+# else
+# include /**/ <memory.h>
+# endif /* ACE_LACKS_MEMORY_H */
+# endif /* ACE_HAS_GNU_CSTRING_H */
+
+// The following are #defines and #includes that must be visible for
+// ACE to compile it's OS wrapper class implementation correctly. We
+// put them inside of here to reduce compiler overhead if we're not
+// inlining...
+
+# if defined (ACE_HAS_REGEX)
+# include /**/ <regexpr.h>
+# endif /* ACE_HAS_REGEX */
+
+# if defined (ACE_HAS_SYSINFO)
+# include /**/ <sys/systeminfo.h>
+# endif /* ACE_HAS_SYS_INFO */
+
+# if defined (ACE_HAS_SYS_SYSCALL_H)
+# include /**/ <sys/syscall.h>
+# endif /* ACE_HAS_SYS_SYSCALL_H */
+
+# if defined (UNIXWARE) /* See strcasecmp, below */
+# include /**/ <ctype.h>
+# endif /* UNIXWARE */
+
+# if defined (ACE_HAS_GETIFADDRS)
+# if defined (ACE_VXWORKS)
+# include /**/ <net/ifaddrs.h>
+# else
+# include /**/ <ifaddrs.h>
+# endif
+# endif /* ACE_HAS_GETIFADDRS */
+
+
+#endif /* WIN32 */
+
+#if defined (ACE_HAS_SHM_OPEN) && defined(INTEGRITY)
+#include "ace/os_include/sys/os_mman.h"
+#endif
+
+// ****************************************************************
+
diff --git a/ACE/ace/OS_Dirent.h b/ACE/ace/OS_Dirent.h
new file mode 100644
index 00000000000..b6e967297f1
--- /dev/null
+++ b/ACE/ace/OS_Dirent.h
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_Dirent.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ */
+//=============================================================================
+
+#ifndef ACE_OS_DIRENT_H
+#define ACE_OS_DIRENT_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_Errno.h"
+#include "ace/os_include/os_dirent.h"
+#include "ace/os_include/sys/os_types.h"
+
+#include "ace/OS_NS_dirent.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_DIRENT_H */
diff --git a/ACE/ace/OS_Errno.cpp b/ACE/ace/OS_Errno.cpp
new file mode 100644
index 00000000000..6f9905cad1f
--- /dev/null
+++ b/ACE/ace/OS_Errno.cpp
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+// $Id$
+
+#include "ace/OS_Errno.h"
+
+ACE_RCSID(ace, OS_Errno, "$Id$")
+
+// Inlining this class on debug builds with gcc on Solaris can cause
+// deadlocks during static initialization. On non debug builds it
+// causes compilation errors.
+#if !defined (ACE_HAS_INLINED_OSCALLS) || \
+ (defined (__GNUG__) && defined (__sun__))
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE
+# include "ace/OS_Errno.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
+
+#include "ace/OS_Memory.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_CE_Errno *ACE_CE_Errno::instance_ = 0;
+DWORD ACE_CE_Errno::errno_key_ = 0xffffffff;
+
+void
+ACE_CE_Errno::init ()
+{
+ ACE_NEW (ACE_CE_Errno::instance_,
+ ACE_CE_Errno ());
+ ACE_CE_Errno::errno_key_ = TlsAlloc ();
+}
+
+void
+ACE_CE_Errno::fini ()
+{
+ TlsFree (ACE_CE_Errno::errno_key_);
+ delete ACE_CE_Errno::instance_;
+ ACE_CE_Errno::instance_ = 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
diff --git a/ACE/ace/OS_Errno.h b/ACE/ace/OS_Errno.h
new file mode 100644
index 00000000000..2827a162b93
--- /dev/null
+++ b/ACE/ace/OS_Errno.h
@@ -0,0 +1,101 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_Errno.h
+ *
+ * $Id$
+ *
+ * @author (Originally in OS.h)Doug Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_ERRNO_H
+#define ACE_OS_ERRNO_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Errno_Guard
+ *
+ * @brief Provides a wrapper to improve performance when thread-specific
+ * errno must be saved and restored in a block of code.
+ *
+ * The typical use-case for this is the following:
+ * int error = errno;
+ * call_some_function_that_might_change_errno ();
+ * errno = error;
+ * This can be replaced with
+ * {
+ * ACE_Errno_Guard guard (errno);
+ * call_some_function_that_might_change_errno ();
+ * }
+ * This implementation is more elegant and more efficient since it
+ * avoids an unnecessary second access to thread-specific storage
+ * by caching a pointer to the value of errno in TSS.
+ */
+class ACE_Export ACE_Errno_Guard
+{
+public:
+ /// Stash the value of <error> into <error_> and initialize the
+ /// <errno_ptr_> to the address of <errno_ref>.
+ ACE_Errno_Guard (ACE_ERRNO_TYPE &errno_ref,
+ int error);
+
+ /// Stash the value of @c errno into <error_> and initialize the
+ /// <errno_ptr_> to the address of <errno_ref>.
+ ACE_Errno_Guard (ACE_ERRNO_TYPE &errno_ref);
+
+ /// Reset the value of @c errno to <error>.
+ ~ACE_Errno_Guard (void);
+
+#if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
+ /// Assign <errno_ref> to <error_>.
+ int operator= (const ACE_ERRNO_TYPE &errno_ref);
+#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
+
+ /// Assign <error> to <error_>.
+ int operator= (int error);
+
+ /// Compare <error> with <error_> for equality.
+ bool operator== (int error);
+
+ /// Compare <error> with <error_> for inequality.
+ bool operator!= (int error);
+
+private:
+ // Prevent copying
+ ACE_Errno_Guard (const ACE_Errno_Guard &);
+ ACE_Errno_Guard &operator= (const ACE_Errno_Guard &);
+
+#if defined (ACE_MT_SAFE)
+ ACE_ERRNO_TYPE *errno_ptr_;
+#endif /* ACE_MT_SAFE */
+ int error_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Inlining this class on debug builds with gcc on Solaris can cause
+// deadlocks during static initialization. On non debug builds it
+// causes compilation errors.
+#if defined (ACE_HAS_INLINED_OSCALLS) && \
+ (!defined (__GNUG__) || !defined (__sun__))
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_Errno.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_ERRNO_H */
diff --git a/ACE/ace/OS_Errno.inl b/ACE/ace/OS_Errno.inl
new file mode 100644
index 00000000000..2fe5e6c54e2
--- /dev/null
+++ b/ACE/ace/OS_Errno.inl
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Errno_Guard::ACE_Errno_Guard (ACE_ERRNO_TYPE &errno_ref,
+ int error)
+ :
+#if defined (ACE_MT_SAFE)
+ errno_ptr_ (&errno_ref),
+#endif /* ACE_MT_SAFE */
+ error_ (error)
+{
+#if !defined(ACE_MT_SAFE)
+ ACE_UNUSED_ARG (errno_ref);
+#endif /* ACE_MT_SAFE */
+}
+
+ACE_INLINE
+ACE_Errno_Guard::ACE_Errno_Guard (ACE_ERRNO_TYPE &errno_ref)
+ :
+#if defined (ACE_MT_SAFE)
+ errno_ptr_ (&errno_ref),
+#endif /* ACE_MT_SAFE */
+ error_ (errno_ref)
+{
+}
+
+ACE_INLINE
+ACE_Errno_Guard::~ACE_Errno_Guard (void)
+{
+#if defined (ACE_MT_SAFE)
+ *errno_ptr_ = this->error_;
+#else
+ errno = this->error_;
+#endif /* ACE_MT_SAFE */
+}
+
+#if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
+ACE_INLINE int
+ACE_Errno_Guard::operator= (const ACE_ERRNO_TYPE &error)
+{
+ return this->error_ = error;
+}
+#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
+
+ACE_INLINE int
+ACE_Errno_Guard::operator= (int error)
+{
+ return this->error_ = error;
+}
+
+ACE_INLINE bool
+ACE_Errno_Guard::operator== (int error)
+{
+ return this->error_ == error;
+}
+
+ACE_INLINE bool
+ACE_Errno_Guard::operator!= (int error)
+{
+ return this->error_ != error;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_Log_Msg_Attributes.cpp b/ACE/ace/OS_Log_Msg_Attributes.cpp
new file mode 100644
index 00000000000..589782735e2
--- /dev/null
+++ b/ACE/ace/OS_Log_Msg_Attributes.cpp
@@ -0,0 +1,9 @@
+// $Id$
+
+#include "ace/OS_Log_Msg_Attributes.h"
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_Log_Msg_Attributes.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+ACE_RCSID(ace, OS_Log_Msg_Attributes, "$Id$")
diff --git a/ACE/ace/OS_Log_Msg_Attributes.h b/ACE/ace/OS_Log_Msg_Attributes.h
new file mode 100644
index 00000000000..072084f4bbc
--- /dev/null
+++ b/ACE/ace/OS_Log_Msg_Attributes.h
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_Log_Msg_Attributes.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan
+ */
+//=============================================================================
+
+#include /**/ "ace/config-all.h"
+
+#ifndef ACE_OS_LOG_MSG_ATTRIBUTES_H
+#define ACE_OS_LOG_MSG_ATTRIBUTES_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/os_include/os_stdio.h"
+#include "ace/iosfwd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_OS_Log_Msg_Attributes
+ *
+ * @brief The attributes required by ACE_Log_Msg.
+ *
+ * When a new thread is created the TSS resources for the Log_Msg
+ * class in the new thread may be inherited by the creator thread.
+ * The base_attributes are encapsulated in this class to simplify their
+ * manipulation and destruction.
+ * @par
+ * The contents of the class must be made available to the OS layer,
+ * because they are part of the thread descriptor.
+ */
+class ACE_Export ACE_OS_Log_Msg_Attributes
+{
+public:
+ /// Constructor
+ ACE_OS_Log_Msg_Attributes (void);
+
+protected:
+ friend class ACE_Log_Msg;
+
+ /// Ostream where the new TSS Log_Msg will use.
+ ACE_OSTREAM_TYPE *ostream_;
+
+ /// Priority_mask to be used in new TSS Log_Msg.
+ unsigned long priority_mask_;
+
+ /// Are we allowing tracing in this thread?
+ int tracing_enabled_;
+
+ /// Indicates whether we should restart system calls that are
+ /// interrupted.
+ int restart_;
+
+ /// Depth of the nesting for printing traces.
+ int trace_depth_;
+
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ /// Structured exception handling Callbacks, only used under Win32
+ ACE_SEH_EXCEPT_HANDLER seh_except_selector_;
+ ACE_SEH_EXCEPT_HANDLER seh_except_handler_;
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+private:
+ // Prevent copying
+ ACE_OS_Log_Msg_Attributes (const ACE_OS_Log_Msg_Attributes &);
+ ACE_OS_Log_Msg_Attributes &operator= (const ACE_OS_Log_Msg_Attributes &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_Log_Msg_Attributes.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_LOG_MSG_ATTRIBUTES_H */
diff --git a/ACE/ace/OS_Log_Msg_Attributes.inl b/ACE/ace/OS_Log_Msg_Attributes.inl
new file mode 100644
index 00000000000..29725ef4d7c
--- /dev/null
+++ b/ACE/ace/OS_Log_Msg_Attributes.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_OS_Log_Msg_Attributes::ACE_OS_Log_Msg_Attributes (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_Memory.h b/ACE/ace/OS_Memory.h
new file mode 100644
index 00000000000..0fda7fbb376
--- /dev/null
+++ b/ACE/ace/OS_Memory.h
@@ -0,0 +1,338 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_Memory.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ */
+//=============================================================================
+
+#ifndef ACE_OS_MEMORY_H
+#define ACE_OS_MEMORY_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_Errno.h"
+#include "ace/Basic_Types.h"
+#include "ace/os_include/os_stddef.h"
+
+// Allow an installation to replace the lowest-level allocation
+// functions without changing the source of ACE.
+//
+// To do this, simple #define ACE_*_FUNC macros in config.h to
+// the names of the site-specific functions, e.g.,
+//
+// #define ACE_MALLOC_FUNC dlmalloc
+// #define ACE_CALLOC_FUNC dlcalloc
+// #define ACE_FREE_FUNC dlfree
+// #define ACE_REALLOC_FUNC dlrealloc
+//
+// For completeness' sake, you should probably put
+// #define ACE_HAS_STRDUP_EMULATION
+// #define ACE_HAS_WCSDUP_EMULATION
+// too, so that you guarantee that strdup() and wcsdup() call your
+// desired mallocator and not the system mallocator.
+//
+#if !defined (ACE_MALLOC_FUNC)
+# define ACE_MALLOC_FUNC ::malloc
+#endif
+#if !defined (ACE_CALLOC_FUNC)
+# define ACE_CALLOC_FUNC ::calloc
+#endif
+#if !defined (ACE_FREE_FUNC)
+# define ACE_FREE_FUNC ::free
+#endif
+#if !defined (ACE_REALLOC_FUNC)
+# define ACE_REALLOC_FUNC ::realloc
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_OLD_MALLOC)
+typedef char * ACE_MALLOC_T;
+#else
+typedef void * ACE_MALLOC_T;
+#endif /* ACE_HAS_OLD_MALLOC */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// ============================================================================
+// ACE_NEW macros
+//
+// A useful abstraction for expressions involving operator new since
+// we can change memory allocation error handling policies (e.g.,
+// depending on whether ANSI/ISO exception handling semantics are
+// being used).
+// ============================================================================
+
+// If new(std::nothrow) is defined then, by definition, new throws exceptions.
+#if defined (ACE_HAS_NEW_NOTHROW)
+# if !defined (ACE_NEW_THROWS_EXCEPTIONS)
+# define ACE_NEW_THROWS_EXCEPTIONS
+# endif
+#endif
+
+// The Windows MFC exception mechanism requires that a caught CException
+// (including the CMemoryException in use here) be freed using its Delete()
+// method. Thus, when MFC is in use and we're catching exceptions as a result
+// of new(), the exception's Delete() method has to be called. No other
+// platform imposes this sort of restriction/requirement. The Windows
+// config stuff (at least for MSVC/MFC) defines a ACE_del_bad_alloc macro
+// that works with its ACE_bad_alloc macro to implement this cleanup
+// requirement. Since no other platform requires this, define it as
+// empty here.
+#if !defined (ACE_del_bad_alloc)
+# define ACE_del_bad_alloc
+#endif
+
+#if defined (ACE_NEW_THROWS_EXCEPTIONS)
+
+// Since new() throws exceptions, we need a way to avoid passing
+// exceptions past the call to new because ACE counts on having a 0
+// return value for a failed allocation. Some compilers offer the
+// new (nothrow) version, which does exactly what we want. Others
+// do not. For those that do not, this sets up what exception is thrown,
+// and then below we'll do a try/catch around the new to catch it and
+// return a 0 pointer instead.
+
+# if defined (__HP_aCC)
+ // I know this works for HP aC++... if <stdexcept> is used, it
+ // introduces other stuff that breaks things, like <memory>, which
+ // screws up auto_ptr.
+# include /**/ <new>
+ // _HP_aCC was first defined at aC++ 03.13 on HP-UX 11. Prior to that
+ // (03.10 and before) a failed new threw bad_alloc. After that (03.13
+ // and above) the exception thrown is dependent on the below settings.
+# if (HPUX_VERS >= 1100)
+# if ((__HP_aCC < 32500 && !defined (RWSTD_NO_NAMESPACE)) || \
+ defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB))
+# define ACE_bad_alloc ::std::bad_alloc
+# define ACE_nothrow ::std::nothrow
+# define ACE_nothrow_t ::std::nothrow_t
+# else
+# define ACE_bad_alloc bad_alloc
+# define ACE_nothrow nothrow
+# define ACE_nothrow_t nothrow_t
+# endif /* __HP_aCC */
+# elif ((__HP_aCC < 12500 && !defined (RWSTD_NO_NAMESPACE)) || \
+ defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB))
+# define ACE_bad_alloc ::std::bad_alloc
+# define ACE_nothrow ::std::nothrow
+# define ACE_nothrow_t ::std::nothrow_t
+# else
+# define ACE_bad_alloc bad_alloc
+# define ACE_nothrow nothrow
+# define ACE_nothrow_t nothrow_t
+# endif /* HPUX_VERS < 1100 */
+# define ACE_throw_bad_alloc throw ACE_bad_alloc ()
+# elif defined (__SUNPRO_CC)
+# if (__SUNPRO_CC < 0x500) || (__SUNPRO_CC_COMPAT == 4)
+# include /**/ <exception.h>
+ // Note: we catch ::xalloc rather than just xalloc because of
+ // a name clash with unsafe_ios::xalloc()
+# define ACE_bad_alloc ::xalloc
+# define ACE_throw_bad_alloc throw ACE_bad_alloc ("no more memory")
+# else
+# include /**/ <new>
+# define ACE_bad_alloc ::std::bad_alloc
+# if defined (ACE_HAS_NEW_NOTHROW)
+# if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+# define ACE_nothrow ::std::nothrow
+# define ACE_nothrow_t ::std::nothrow_t
+# else
+# define ACE_nothrow nothrow
+# define ACE_nothrow_t nothrow_t
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+# endif /* ACE_HAS_NEW_NOTHROW */
+# define ACE_throw_bad_alloc throw ACE_bad_alloc ()
+# endif /* __SUNPRO_CC < 0x500 */
+# elif defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+# include /**/ <new>
+# if !defined (ACE_bad_alloc)
+# define ACE_bad_alloc ::std::bad_alloc
+# endif
+# define ACE_nothrow ::std::nothrow
+# define ACE_nothrow_t ::std::nothrow_t
+ // MFC changes the behavior of operator new at all MSVC versions from 6 up.
+# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC == 1)
+# define ACE_throw_bad_alloc AfxThrowMemoryException ()
+# else
+# define ACE_throw_bad_alloc throw ACE_bad_alloc ()
+# endif
+# else
+# include /**/ <new>
+# if !defined (ACE_bad_alloc)
+# define ACE_bad_alloc bad_alloc
+# endif
+# define ACE_nothrow nothrow
+# define ACE_nothrow_t nothrow_t
+ // MFC changes the behavior of operator new at all MSVC versions from 6 up.
+# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC == 1)
+# define ACE_throw_bad_alloc AfxThrowMemoryException ()
+# else
+# define ACE_throw_bad_alloc throw ACE_bad_alloc ()
+# endif
+# endif /* __HP_aCC */
+
+# if defined (ACE_HAS_NEW_NOTHROW)
+# define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \
+ do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \
+ if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \
+ } while (0)
+# define ACE_NEW(POINTER,CONSTRUCTOR) \
+ do { POINTER = new(ACE_nothrow) CONSTRUCTOR; \
+ if (POINTER == 0) { errno = ENOMEM; return; } \
+ } while (0)
+# define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \
+ do { POINTER = new(ACE_nothrow) CONSTRUCTOR; \
+ if (POINTER == 0) { errno = ENOMEM; } \
+ } while (0)
+
+# else
+
+# define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \
+ do { try { POINTER = new CONSTRUCTOR; } \
+ catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return RET_VAL; } \
+ } while (0)
+
+# define ACE_NEW(POINTER,CONSTRUCTOR) \
+ do { try { POINTER = new CONSTRUCTOR; } \
+ catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return; } \
+ } while (0)
+
+# define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \
+ do { try { POINTER = new CONSTRUCTOR; } \
+ catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; } \
+ } while (0)
+# endif /* ACE_HAS_NEW_NOTHROW */
+
+#else /* ACE_NEW_THROWS_EXCEPTIONS */
+
+# define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \
+ do { POINTER = new CONSTRUCTOR; \
+ if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \
+ } while (0)
+# define ACE_NEW(POINTER,CONSTRUCTOR) \
+ do { POINTER = new CONSTRUCTOR; \
+ if (POINTER == 0) { errno = ENOMEM; return; } \
+ } while (0)
+# define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \
+ do { POINTER = new CONSTRUCTOR; \
+ if (POINTER == 0) { errno = ENOMEM; } \
+ } while (0)
+
+# define ACE_throw_bad_alloc \
+ void* gcc_will_complain_if_literal_0_is_returned = 0; \
+ return gcc_will_complain_if_literal_0_is_returned
+
+#endif /* ACE_NEW_THROWS_EXCEPTIONS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+//@{
+/**
+ * @name Efficiently compute aligned pointers to powers of 2 boundaries.
+ */
+
+/**
+ * Efficiently align "value" up to "alignment", knowing that all such
+ * boundaries are binary powers and that we're using two's complement
+ * arithmetic.
+ *
+ * Since the alignment is a power of two its binary representation is:
+ *
+ * alignment = 0...010...0
+ *
+ * hence
+ *
+ * alignment - 1 = 0...001...1 = T1
+ *
+ * so the complement is:
+ *
+ * ~(alignment - 1) = 1...110...0 = T2
+ *
+ * Notice that there is a multiple of <alignment> in the range
+ * [<value>,<value> + T1], also notice that if
+ *
+ * X = ( <value> + T1 ) & T2
+ *
+ * then
+ *
+ * <value> <= X <= <value> + T1
+ *
+ * because the & operator only changes the last bits, and since X is a
+ * multiple of <alignment> (its last bits are zero) we have found the
+ * multiple we wanted.
+ */
+/// Return the next integer aligned to a required boundary
+/**
+ * @param ptr the base pointer
+ * @param alignment the required alignment
+ */
+#if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
+inline unsigned int
+ACE_align_binary (unsigned int ptr, unsigned int alignment)
+{
+ unsigned int const tmp = alignment - 1;
+ return (ptr + tmp) & (~tmp);
+}
+#else
+inline uintptr_t
+ACE_align_binary (uintptr_t ptr, uintptr_t alignment)
+{
+ uintptr_t const tmp = alignment - 1;
+ return (ptr + tmp) & (~tmp);
+}
+#endif
+
+#if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
+/// Return the next address aligned to a required boundary
+inline char *
+ACE_ptr_align_binary (char const * ptr, unsigned int alignment)
+{
+ return
+ reinterpret_cast<char *> (
+ ACE_align_binary (reinterpret_cast<unsigned int> (ptr), alignment));
+}
+
+/// Return the next address aligned to a required boundary
+inline char *
+ACE_ptr_align_binary (unsigned char const * ptr, unsigned int alignment)
+{
+ return
+ ACE_ptr_align_binary (reinterpret_cast<char const *> (ptr), alignment);
+}
+#else
+/// Return the next address aligned to a required boundary
+inline char *
+ACE_ptr_align_binary (char const * ptr, uintptr_t alignment)
+{
+ return
+ reinterpret_cast<char *> (
+ ACE_align_binary (reinterpret_cast<uintptr_t> (ptr), alignment));
+}
+
+/// Return the next address aligned to a required boundary
+inline char *
+ACE_ptr_align_binary (unsigned char const * ptr, uintptr_t alignment)
+{
+ return
+ ACE_ptr_align_binary (reinterpret_cast<char const *> (ptr), alignment);
+}
+#endif /* ACE_OPENVMS && __INITIAL_POINTER_SIZE < 64 */
+//@}
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include "ace/OS_NS_stdlib.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_MEMORY_H */
diff --git a/ACE/ace/OS_NS_Thread.cpp b/ACE/ace/OS_NS_Thread.cpp
new file mode 100644
index 00000000000..eb56559be82
--- /dev/null
+++ b/ACE/ace/OS_NS_Thread.cpp
@@ -0,0 +1,5328 @@
+#include "ace/OS_NS_Thread.h"
+
+ACE_RCSID (ace,
+ OS_NS_Thread,
+ "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_Thread.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/Sched_Params.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_Thread_Adapter.h"
+#include "ace/Min_Max.h"
+#include "ace/Object_Manager_Base.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/Log_Msg.h" // for ACE_ASSERT
+// This is necessary to work around nasty problems with MVS C++.
+#include "ace/Auto_Ptr.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Condition_T.h"
+#include "ace/Guard_T.h"
+
+extern "C" void
+ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args)
+{
+ ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::mutex_lock_cleanup (args);
+}
+
+
+#if !defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
+# define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
+ (*THR_ID = ::_beginthreadex ((void(_Optlink*)(void*))ENTRY_POINT, STACK, STACKSIZE, ARGS), *THR_ID)
+#elif defined (ACE_HAS_WINCE) && defined (UNDER_CE) && (UNDER_CE >= 211)
+# define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
+ CreateThread (0, STACKSIZE, (unsigned long (__stdcall *) (void *)) ENTRY_POINT, ARGS, (FLAGS) & CREATE_SUSPENDED, (unsigned long *) THR_ID)
+#elif defined(ACE_HAS_WTHREADS)
+ // Green Hills compiler gets confused when __stdcall is imbedded in
+ // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it
+ // instead.
+ typedef unsigned (__stdcall *ACE_WIN32THRFUNC_T)(void*);
+# define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
+ ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID)
+#endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */
+
+/*****************************************************************************/
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Thread_ID::to_string (char *thr_string) const
+{
+ char format[128]; // Converted format string
+ char *fp = 0; // Current format pointer
+ fp = format;
+ *fp++ = '%'; // Copy in the %
+
+#if defined (ACE_WIN32)
+ ACE_OS::strcpy (fp, "u");
+ ACE_OS::sprintf (thr_string,
+ format,
+ static_cast <unsigned> (thread_id_));
+#elif defined (DIGITAL_UNIX)
+ ACE_OS::strcpy (fp, "u");
+ ACE_OS::sprintf (thr_string, format,
+# if defined (ACE_HAS_THREADS)
+ thread_id_
+# else
+ thread_id_
+# endif /* ACE_HAS_THREADS */
+ );
+#else
+
+# if defined (ACE_MVS) || defined (ACE_TANDEM_T1248_PTHREADS)
+ // MVS's pthread_t is a struct... yuck. So use the ACE 5.0
+ // code for it.
+ ACE_OS::strcpy (fp, "u");
+ ACE_OS::sprintf (thr_string, format, thread_handle_);
+# 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, "lu");
+ ACE_OS::sprintf (thr_string,
+ format,
+ (unsigned long) thread_handle_);
+# endif /* ACE_MVS || ACE_TANDEM_T1248_PTHREADS */
+
+#endif /* ACE_WIN32 */
+}
+
+/*****************************************************************************/
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
+
+#if defined (ACE_HAS_TSS_EMULATION)
+u_int ACE_TSS_Emulation::total_keys_ = 0;
+
+ACE_TSS_Keys* ACE_TSS_Emulation::tss_keys_used_ = 0;
+
+ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
+ACE_TSS_Emulation::tss_destructor_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]
+ = { 0 };
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+
+bool ACE_TSS_Emulation::key_created_ = false;
+
+ACE_OS_thread_key_t ACE_TSS_Emulation::native_tss_key_;
+
+/* static */
+# if defined (ACE_HAS_THR_C_FUNC)
+extern "C"
+void
+ACE_TSS_Emulation_cleanup (void *ptr)
+{
+ ACE_UNUSED_ARG (ptr);
+ // Really this must be used for ACE_TSS_Emulation code to make the TSS
+ // cleanup
+}
+# else
+void
+ACE_TSS_Emulation_cleanup (void *ptr)
+{
+ ACE_UNUSED_ARG (ptr);
+ // Really this must be used for ACE_TSS_Emulation code to make the TSS
+ // cleanup
+}
+# endif /* ACE_HAS_THR_C_FUNC */
+
+void **
+ACE_TSS_Emulation::tss_base (void* ts_storage[], u_int *ts_created)
+{
+ // TSS Singleton implementation.
+
+ // Create the one native TSS key, if necessary.
+ if (!key_created_)
+ {
+ // Double-checked lock . . .
+ ACE_TSS_BASE_GUARD
+
+ if (!key_created_)
+ {
+ ACE_NO_HEAP_CHECK;
+ if (ACE_OS::thr_keycreate_native (&native_tss_key_,
+ &ACE_TSS_Emulation_cleanup) != 0)
+ {
+ ACE_ASSERT (0);
+ return 0; // Major problems, this should *never* happen!
+ }
+ key_created_ = true;
+ }
+ }
+
+ void **old_ts_storage = 0;
+
+ // Get the tss_storage from thread-OS specific storage.
+ if (ACE_OS::thr_getspecific_native (native_tss_key_,
+ (void **) &old_ts_storage) == -1)
+ {
+ ACE_ASSERT (false);
+ return 0; // This should not happen!
+ }
+
+ // Check to see if this is the first time in for this thread.
+ // This block can also be entered after a fork () in the child process.
+ if (old_ts_storage == 0)
+ {
+ if (ts_created)
+ *ts_created = 1u;
+
+ // Use the ts_storage passed as argument, if non-zero. It is
+ // possible that this has been implemented in the stack. At the
+ // moment, this is unknown. The cleanup must not do nothing.
+ // If ts_storage is zero, allocate (and eventually leak) the
+ // storage array.
+ if (ts_storage == 0)
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_NEW_RETURN (ts_storage,
+ void*[ACE_TSS_THREAD_KEYS_MAX],
+ 0);
+
+ // Zero the entire TSS array. Do it manually instead of
+ // using memset, for optimum speed. Though, memset may be
+ // faster :-)
+ void **tss_base_p = ts_storage;
+
+ for (u_int i = 0;
+ i < ACE_TSS_THREAD_KEYS_MAX;
+ ++i)
+ *tss_base_p++ = 0;
+ }
+
+ // Store the pointer in thread-specific storage. It gets
+ // deleted via the ACE_TSS_Emulation_cleanup function when the
+ // thread terminates.
+ if (ACE_OS::thr_setspecific_native (native_tss_key_,
+ (void *) ts_storage) != 0)
+ {
+ ACE_ASSERT (false);
+ return 0; // This should not happen!
+ }
+ }
+ else
+ if (ts_created)
+ ts_created = 0;
+
+ return ts_storage ? ts_storage : old_ts_storage;
+}
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+u_int
+ACE_TSS_Emulation::total_keys ()
+{
+ ACE_OS_Recursive_Thread_Mutex_Guard (
+ *static_cast <ACE_recursive_thread_mutex_t *>
+ (ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
+
+ return total_keys_;
+}
+
+int
+ACE_TSS_Emulation::next_key (ACE_thread_key_t &key)
+{
+ ACE_OS_Recursive_Thread_Mutex_Guard (
+ *static_cast <ACE_recursive_thread_mutex_t *>
+ (ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
+
+ // Initialize the tss_keys_used_ pointer on first use.
+ if (tss_keys_used_ == 0)
+ {
+ ACE_NEW_RETURN (tss_keys_used_, ACE_TSS_Keys, -1);
+ }
+
+ if (total_keys_ < ACE_TSS_THREAD_KEYS_MAX)
+ {
+ u_int counter = 0;
+ // Loop through all possible keys and check whether a key is free
+ for ( ;counter < ACE_TSS_THREAD_KEYS_MAX; counter++)
+ {
+ ACE_thread_key_t localkey;
+# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
+ ACE_OS::memset (&localkey, 0, sizeof (ACE_thread_key_t));
+ ACE_OS::memcpy (&localkey, &counter_, sizeof (u_int));
+# else
+ localkey = counter;
+# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
+ // If the key is not set as used, we can give out this key, if not
+ // we have to search further
+ if (tss_keys_used_->is_set(localkey) == 0)
+ {
+ tss_keys_used_->test_and_set(localkey);
+ key = localkey;
+ break;
+ }
+ }
+
+ ++total_keys_;
+ return 0;
+ }
+ else
+ {
+ key = ACE_OS::NULL_key;
+ return -1;
+ }
+}
+
+int
+ACE_TSS_Emulation::release_key (ACE_thread_key_t key)
+{
+ ACE_OS_Recursive_Thread_Mutex_Guard (
+ *static_cast <ACE_recursive_thread_mutex_t *>
+ (ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
+
+ if (tss_keys_used_ != 0 &&
+ tss_keys_used_->test_and_clear (key) == 0)
+ {
+ --total_keys_;
+ return 0;
+ }
+ return 1;
+}
+
+int
+ACE_TSS_Emulation::is_key (ACE_thread_key_t key)
+{
+ ACE_OS_Recursive_Thread_Mutex_Guard (
+ *static_cast <ACE_recursive_thread_mutex_t *>
+ (ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
+
+ if (tss_keys_used_ != 0 &&
+ tss_keys_used_->is_set (key) == 1)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+void *
+ACE_TSS_Emulation::tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX])
+{
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ // On VxWorks, in particular, don't check to see if the field
+ // is 0. It isn't always, specifically, when a program is run
+ // directly by the shell (without spawning a new task) after
+ // another program has been run.
+
+ u_int ts_created = 0;
+ tss_base (ts_storage, &ts_created);
+ if (ts_created)
+ {
+# else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
+ tss_base () = ts_storage;
+# endif
+
+ // Zero the entire TSS array. Do it manually instead of using
+ // memset, for optimum speed. Though, memset may be faster :-)
+ void **tss_base_p = tss_base ();
+ for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
+ {
+ *tss_base_p = 0;
+ }
+
+ return tss_base ();
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ }
+ else
+ {
+ return 0;
+ }
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+}
+
+void
+ACE_TSS_Emulation::tss_close ()
+{
+#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ ACE_OS::thr_keyfree_native (native_tss_key_);
+#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+}
+
+#endif /* ACE_HAS_TSS_EMULATION */
+
+#endif /* WIN32 || ACE_HAS_TSS_EMULATION */
+
+/*****************************************************************************/
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
+
+// Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to
+// the single file of template instantiations.
+
+ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id)
+ : tid_(id)
+{
+ ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
+}
+
+ACE_TSS_Ref::ACE_TSS_Ref (void)
+{
+ ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
+}
+
+// Check for equality.
+bool
+ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) const
+{
+ ACE_OS_TRACE ("ACE_TSS_Ref::operator==");
+
+ return this->tid_ == info.tid_;
+}
+
+// Check for inequality.
+ACE_SPECIAL_INLINE
+bool
+ACE_TSS_Ref::operator != (const ACE_TSS_Ref &tss_ref) const
+{
+ ACE_OS_TRACE ("ACE_TSS_Ref::operator !=");
+
+ return !(*this == tss_ref);
+}
+
+// moved class ACE_TSS_Info declaration
+// to OS.h so it can be visible to the
+// single file of template instantiations
+
+ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key,
+ ACE_TSS_Info::Destructor dest)
+ : key_ (key),
+ destructor_ (dest),
+ thread_count_ (-1)
+{
+ ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
+}
+
+ACE_TSS_Info::ACE_TSS_Info (void)
+ : key_ (ACE_OS::NULL_key),
+ destructor_ (0),
+ thread_count_ (-1)
+{
+ ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
+}
+
+# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
+static inline bool operator== (const ACE_thread_key_t &lhs,
+ const ACE_thread_key_t &rhs)
+{
+ return ! ACE_OS::memcmp (&lhs, &rhs, sizeof (ACE_thread_key_t));
+}
+
+static inline bool operator!= (const ACE_thread_key_t &lhs,
+ const ACE_thread_key_t &rhs)
+{
+ return ! (lhs == rhs);
+}
+# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
+
+// Check for equality.
+bool
+ACE_TSS_Info::operator== (const ACE_TSS_Info &info) const
+{
+ ACE_OS_TRACE ("ACE_TSS_Info::operator==");
+
+ return this->key_ == info.key_;
+}
+
+// Check for inequality.
+bool
+ACE_TSS_Info::operator != (const ACE_TSS_Info &info) const
+{
+ ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
+
+ return !(*this == info);
+}
+
+void
+ACE_TSS_Info::dump (void)
+{
+# if defined (ACE_HAS_DUMP)
+ // ACE_OS_TRACE ("ACE_TSS_Info::dump");
+
+# if 0
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %u\n"), this->key_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("destructor_ = %u\n"), this->destructor_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+# endif /* 0 */
+# endif /* ACE_HAS_DUMP */
+}
+
+// Moved class ACE_TSS_Keys declaration to OS.h so it can be visible
+// to the single file of template instantiations.
+
+ACE_TSS_Keys::ACE_TSS_Keys (void)
+{
+ for (u_int i = 0; i < ACE_WORDS; ++i)
+ {
+ key_bit_words_[i] = 0;
+ }
+}
+
+ACE_SPECIAL_INLINE
+void
+ACE_TSS_Keys::find (const u_int key, u_int &word, u_int &bit)
+{
+ word = key / ACE_BITS_PER_WORD;
+ bit = key % ACE_BITS_PER_WORD;
+}
+
+int
+ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key)
+{
+ ACE_KEY_INDEX (key_index, key);
+ u_int word, bit;
+ find (key_index, word, bit);
+
+ if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
+ {
+ return 1;
+ }
+ else
+ {
+ ACE_SET_BITS (key_bit_words_[word], 1 << bit);
+ return 0;
+ }
+}
+
+int
+ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key)
+{
+ ACE_KEY_INDEX (key_index, key);
+ u_int word, bit;
+ find (key_index, word, bit);
+
+ if (word < ACE_WORDS && ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
+ {
+ ACE_CLR_BITS (key_bit_words_[word], 1 << bit);
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+int
+ACE_TSS_Keys::is_set (const ACE_thread_key_t key) const
+{
+ ACE_KEY_INDEX (key_index, key);
+ u_int word, bit;
+ find (key_index, word, bit);
+
+ return word < ACE_WORDS ? ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit) : 0;
+}
+
+/**
+ * @class ACE_TSS_Cleanup
+ * @brief Singleton that helps to manage the lifetime of TSS objects and keys.
+ */
+class ACE_TSS_Cleanup
+{
+public:
+ /// Register a newly-allocated key
+ /// @param key the key to be monitored
+ /// @param destructor the function to call to delete objects stored via this key
+ int insert (ACE_thread_key_t key, void (*destructor)(void *));
+
+ /// Mark a key as being used by this thread.
+ void thread_use_key (ACE_thread_key_t key);
+
+ /// This thread is no longer using this key
+ /// call destructor if appropriate
+ int thread_detach_key (ACE_thread_key_t key);
+
+ /// This key is no longer used
+ /// Release key if use count == 0
+ /// fail if use_count != 0;
+ /// @param key the key to be released
+ int free_key (ACE_thread_key_t key);
+
+ /// Cleanup the thread-specific objects. Does _NOT_ exit the thread.
+ /// For each used key perform the same actions as free_key.
+ void thread_exit (void);
+
+private:
+ void dump (void);
+
+ /// Release a key used by this thread
+ /// @param info reference to the info for this key
+ /// @param destructor out arg to receive destructor function ptr
+ /// @param tss_obj out arg to receive pointer to deletable object
+ void thread_release (
+ ACE_TSS_Info &info,
+ ACE_TSS_Info::Destructor & destructor,
+ void *& tss_obj);
+
+ /// remove key if it's unused (thread_count == 0)
+ /// @param info reference to the info for this key
+ int remove_key (ACE_TSS_Info &info);
+
+ /// Find the TSS keys (if any) for this thread.
+ /// @param thread_keys reference to pointer to be filled in by this function.
+ /// @return false if keys don't exist.
+ bool find_tss_keys (ACE_TSS_Keys *& thread_keys) const;
+
+ /// Accessor for this threads ACE_TSS_Keys instance.
+ /// Creates the keys if necessary.
+ ACE_TSS_Keys *tss_keys ();
+
+ /// Ensure singleton.
+ ACE_TSS_Cleanup (void);
+ ~ACE_TSS_Cleanup (void);
+
+ /// ACE_TSS_Cleanup access only via TSS_Cleanup_Instance
+ friend class TSS_Cleanup_Instance;
+
+private:
+ // Array of <ACE_TSS_Info> objects.
+ typedef ACE_TSS_Info ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS];
+ typedef ACE_TSS_Info *ACE_TSS_TABLE_ITERATOR;
+
+ /// Table of <ACE_TSS_Info>'s.
+ ACE_TSS_TABLE table_;
+
+ /// Key for the thread-specific ACE_TSS_Keys
+ /// Used by find_tss_keys() or tss_keys() to find the
+ /// bit array that records whether each TSS key is in
+ /// use by this thread.
+ ACE_thread_key_t in_use_;
+};
+
+
+/*****************************************************************************/
+/**
+ * @class TSS_Cleanup_Instance
+ * @A class to manage an instance pointer to ACE_TSS_Cleanup.
+ * Note: that the double checked locking pattern doesn't allow
+ * safe deletion.
+ * Callers who wish to access the singleton ACE_TSS_Cleanup must
+ * do so by instantiating a TSS_Cleanup_Instance, calling the valid
+ * method to be sure the ACE_TSS_Cleanup is available, then using
+ * the TSS_Cleanup_Instance as a pointer to the instance.
+ * Construction argument to the TSS_Cleanup_Instance determines how
+ * it is to be used:
+ * CREATE means allow this call to create an ACE_TSS_Cleanup if necessary.
+ * USE means use the existing ACE_TSS_Cleanup, but do not create a new one.
+ * DESTROY means provide exclusive access to the ACE_TSS_Cleanup, then
+ * delete it when the TSS_Cleanup_Instance goes out of scope.
+ */
+
+class TSS_Cleanup_Instance
+{
+public:
+ enum Purpose
+ {
+ CREATE,
+ USE,
+ DESTROY
+ };
+ TSS_Cleanup_Instance (Purpose purpose = USE);
+ ~TSS_Cleanup_Instance();
+
+ bool valid();
+ ACE_TSS_Cleanup * operator ->();
+
+private:
+
+ ACE_TSS_Cleanup * operator *();
+
+private:
+ static unsigned int reference_count_;
+ static ACE_TSS_Cleanup * instance_;
+ static ACE_Thread_Mutex* mutex_;
+ static ACE_Thread_Condition<ACE_Thread_Mutex>* condition_;
+
+private:
+ ACE_TSS_Cleanup * ptr_;
+ unsigned short flags_;
+ enum
+ {
+ FLAG_DELETING = 1,
+ FLAG_VALID_CHECKED = 2
+ };
+};
+
+TSS_Cleanup_Instance::TSS_Cleanup_Instance (Purpose purpose)
+ : ptr_(0)
+ , flags_(0)
+{
+ // During static construction or construction of the ACE_Object_Manager,
+ // there can be only one thread in this constructor at any one time, so
+ // it's safe to check for a zero mutex_. If it's zero, we create a new
+ // mutex and condition variable.
+ if (mutex_ == 0)
+ {
+ ACE_NEW (mutex_, ACE_Thread_Mutex ());
+ ACE_NEW (condition_, ACE_Thread_Condition<ACE_Thread_Mutex> (*mutex_));
+ }
+
+ ACE_Guard<ACE_Thread_Mutex> guard(*mutex_);
+
+ if (purpose == CREATE)
+ {
+ if (instance_ == 0)
+ {
+ instance_ = new ACE_TSS_Cleanup();
+ }
+ ptr_ = instance_;
+ ++reference_count_;
+ }
+ else if(purpose == DESTROY)
+ {
+ if (instance_ != 0)
+ {
+ ptr_ = instance_;
+ instance_ = 0;
+ ACE_SET_BITS(flags_, FLAG_DELETING);
+ while (reference_count_ > 0)
+ {
+ condition_->wait();
+ }
+ }
+ }
+ else // must be normal use
+ {
+ ACE_ASSERT(purpose == USE);
+ if (instance_ != 0)
+ {
+ ptr_ = instance_;
+ ++reference_count_;
+ }
+ }
+}
+
+TSS_Cleanup_Instance::~TSS_Cleanup_Instance (void)
+{
+ // Variable to hold the mutex_ to delete outside the scope of the
+ // guard.
+ ACE_Thread_Mutex *del_mutex = 0;
+
+ // scope the guard
+ {
+ ACE_Guard<ACE_Thread_Mutex> guard (*mutex_);
+ if (ptr_ != 0)
+ {
+ if (ACE_BIT_ENABLED (flags_, FLAG_DELETING))
+ {
+ ACE_ASSERT(instance_ == 0);
+ ACE_ASSERT(reference_count_ == 0);
+ delete ptr_;
+ del_mutex = mutex_ ;
+ mutex_ = 0;
+ }
+ else
+ {
+ ACE_ASSERT (reference_count_ > 0);
+ --reference_count_;
+ if (reference_count_ == 0 && instance_ == 0)
+ condition_->signal ();
+ }
+ }
+ }// end of guard scope
+
+ if (del_mutex != 0)
+ {
+ delete condition_;
+ condition_ = 0;
+ delete del_mutex;
+ }
+}
+
+bool
+TSS_Cleanup_Instance::valid()
+{
+ ACE_SET_BITS(flags_, FLAG_VALID_CHECKED);
+ return (this->instance_ != 0);
+}
+
+ACE_TSS_Cleanup *
+TSS_Cleanup_Instance::operator *()
+{
+ ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
+ return instance_;
+}
+
+ACE_TSS_Cleanup *
+TSS_Cleanup_Instance::operator ->()
+{
+ ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
+ return instance_;
+}
+
+// = Static object initialization.
+unsigned int TSS_Cleanup_Instance::reference_count_ = 0;
+ACE_TSS_Cleanup * TSS_Cleanup_Instance::instance_ = 0;
+ACE_Thread_Mutex* TSS_Cleanup_Instance::mutex_ = 0;
+ACE_Thread_Condition<ACE_Thread_Mutex>* TSS_Cleanup_Instance::condition_ = 0;
+
+ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void)
+{
+}
+
+void
+ACE_TSS_Cleanup::thread_exit (void)
+{
+ ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
+ // variables to hold the destructors, keys
+ // and pointers to the object to be destructed
+ // the actual destruction is deferred until the guard is released
+ ACE_TSS_Info::Destructor destructor[ACE_DEFAULT_THREAD_KEYS];
+ void * tss_obj[ACE_DEFAULT_THREAD_KEYS];
+ ACE_thread_key_t keys[ACE_DEFAULT_THREAD_KEYS];
+ // count of items to be destroyed
+ unsigned int d_count = 0;
+
+ // scope the guard
+ {
+ ACE_TSS_CLEANUP_GUARD
+
+ // if not initialized or already cleaned up
+ ACE_TSS_Keys *this_thread_keys = 0;
+ if (! find_tss_keys (this_thread_keys) )
+ {
+ return;
+ }
+
+ // Minor hack: Iterating in reverse order means the LOG buffer which is
+ // accidentally allocated first will be accidentally deallocated (almost)
+ // last -- in case someone logs something from the other destructors.
+ // applications should not count on this behavior because platforms which
+ // do not use ACE_TSS_Cleanup may delete objects in other orders.
+ unsigned int key_index = ACE_DEFAULT_THREAD_KEYS;
+ while( key_index > 0)
+ {
+ --key_index;
+ ACE_TSS_Info & info = this->table_[key_index];
+ // if this key is in use by this thread
+ if (info.key_in_use () && this_thread_keys->is_set(info.key_))
+ {
+ // defer deleting the in-use key until all others have been deleted
+ if(info.key_ != this->in_use_)
+ {
+ destructor[d_count] = 0;
+ tss_obj[d_count] = 0;
+ keys[d_count] = 0;
+ this->thread_release (info, destructor[d_count], tss_obj[d_count]);
+ if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
+ {
+ keys[d_count] = info.key_;
+ ++d_count;
+ }
+ }
+ }
+ }
+
+ // remove the in_use bit vector last
+ ACE_KEY_INDEX (use_index, this->in_use_);
+ ACE_TSS_Info & info = this->table_[use_index];
+ destructor[d_count] = 0;
+ tss_obj[d_count] = 0;
+ keys[d_count] = 0;
+ this->thread_release (info, destructor[d_count], tss_obj[d_count]);
+ if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
+ {
+ keys[d_count] = info.key_;
+ ++d_count;
+ }
+ } // end of guard scope
+ for (unsigned int d_index = 0; d_index < d_count; ++d_index)
+ {
+ (*destructor[d_index])(tss_obj[d_index]);
+#if defined (ACE_HAS_TSS_EMULATION)
+ ACE_TSS_Emulation::ts_object (keys[d_index]) = 0;
+#else // defined (ACE_HAS_TSS_EMULATION)
+ ACE_OS::thr_setspecific_native (keys[d_index], 0);
+#endif // defined (ACE_HAS_TSS_EMULATION)
+ }
+}
+
+extern "C" void
+ACE_TSS_Cleanup_keys_destroyer (void *tss_keys)
+{
+ delete static_cast <ACE_TSS_Keys *> (tss_keys);
+}
+
+ACE_TSS_Cleanup::ACE_TSS_Cleanup (void)
+ : in_use_ (ACE_OS::NULL_key)
+{
+ ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
+}
+
+int
+ACE_TSS_Cleanup::insert (ACE_thread_key_t key,
+ void (*destructor)(void *))
+{
+ ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
+ ACE_TSS_CLEANUP_GUARD
+
+ ACE_KEY_INDEX (key_index, key);
+ ACE_ASSERT (key_index < ACE_DEFAULT_THREAD_KEYS);
+ if (key_index < ACE_DEFAULT_THREAD_KEYS)
+ {
+ ACE_ASSERT (table_[key_index].thread_count_ == -1);
+ table_[key_index] = ACE_TSS_Info (key, destructor);
+ table_[key_index].thread_count_ = 0; // inserting it does not use it
+ // but it does "allocate" it
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+int
+ACE_TSS_Cleanup::free_key (ACE_thread_key_t key)
+{
+ ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
+ ACE_TSS_CLEANUP_GUARD
+ ACE_KEY_INDEX (key_index, key);
+ if (key_index < ACE_DEFAULT_THREAD_KEYS)
+ {
+ return remove_key (this->table_ [key_index]);
+ }
+ return -1;
+}
+
+int
+ACE_TSS_Cleanup::remove_key (ACE_TSS_Info &info)
+{
+ // assume CLEANUP_GUARD is held by caller
+ ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
+
+#if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
+ // When this is done, any existing TSS objects controlled by this key are leaked
+ // There is no "right thing" to do in this case
+
+ // only remove it if all threads are done with it
+ if (info.thread_count_ != 0)
+ {
+ return -1;
+ }
+#endif // 0
+
+#if !defined (ACE_HAS_TSS_EMULATION)
+ ACE_OS_thread_key_t temp_key = info.key_;
+ ACE_OS::thr_keyfree_native (temp_key);
+#endif /* !ACE_HAS_TSS_EMULATION */
+ if (info.key_ == this->in_use_)
+ {
+ this->in_use_ = ACE_OS::NULL_key;
+ }
+ info.key_in_use (0);
+ info.destructor_ = 0;
+ return 0;
+}
+
+int
+ACE_TSS_Cleanup::thread_detach_key (ACE_thread_key_t key)
+{
+ // variables to hold the destructor and the object to be destructed
+ // the actual call is deferred until the guard is released
+ ACE_TSS_Info::Destructor destructor = 0;
+ void * tss_obj = 0;
+
+ // scope the guard
+ {
+ ACE_TSS_CLEANUP_GUARD
+
+ ACE_KEY_INDEX (key_index, key);
+ ACE_ASSERT (key_index < sizeof(this->table_)/sizeof(this->table_[0])
+ && this->table_[key_index].key_ == key);
+ ACE_TSS_Info &info = this->table_ [key_index];
+
+ // sanity check
+ if (!info.key_in_use ())
+ {
+ return -1;
+ }
+
+ this->thread_release (info, destructor, tss_obj);
+ } // end of scope for the Guard
+ // if there's a destructor and an object to be destroyed
+ if (destructor != 0 && tss_obj != 0)
+ {
+ (*destructor) (tss_obj);
+ }
+ return 0;
+}
+
+void
+ACE_TSS_Cleanup::thread_release (
+ ACE_TSS_Info &info,
+ ACE_TSS_Info::Destructor & destructor,
+ void *& tss_obj)
+{
+ // assume guard is held by caller
+ // Find the TSS keys (if any) for this thread
+ // do not create them if they don't exist
+ ACE_TSS_Keys * thread_keys = 0;
+ if (find_tss_keys (thread_keys))
+ {
+ // if this key is in use by this thread
+ if (thread_keys->test_and_clear(info.key_) == 0)
+ {
+ // save destructor & pointer to tss object
+ // until after the guard is released
+ destructor = info.destructor_;
+ ACE_OS::thr_getspecific (info.key_, &tss_obj);
+ ACE_ASSERT (info.thread_count_ > 0);
+ --info.thread_count_;
+ }
+ }
+}
+
+void
+ACE_TSS_Cleanup::thread_use_key (ACE_thread_key_t key)
+{
+ // If the key's ACE_TSS_Info in-use bit for this thread is not set,
+ // set it and increment the key's thread_count_.
+ if (! tss_keys ()->test_and_set (key))
+ {
+ ACE_TSS_CLEANUP_GUARD
+
+ // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
+ ACE_KEY_INDEX (key_index, key);
+ ACE_TSS_Info &key_info = this->table_ [key_index];
+
+ ACE_ASSERT (key_info.key_in_use ());
+ ++key_info.thread_count_;
+ }
+}
+
+void
+ACE_TSS_Cleanup::dump (void)
+{
+# if defined (ACE_HAS_DUMP)
+ // Iterate through all the thread-specific items and dump them all.
+
+ ACE_TSS_TABLE_ITERATOR key_info = table_;
+ for (unsigned int i = 0;
+ i < ACE_DEFAULT_THREAD_KEYS;
+ ++key_info, ++i)
+ key_info->dump ();
+# endif /* ACE_HAS_DUMP */
+}
+
+bool
+ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys *& tss_keys) const
+{
+ if (this->in_use_ == ACE_OS::NULL_key)
+ return false;
+ if (ACE_OS::thr_getspecific (in_use_,
+ reinterpret_cast<void **> (&tss_keys)) == -1)
+ {
+ ACE_ASSERT (false);
+ return false; // This should not happen!
+ }
+ return tss_keys != 0;
+}
+
+ACE_TSS_Keys *
+ACE_TSS_Cleanup::tss_keys ()
+{
+ if (this->in_use_ == ACE_OS::NULL_key)
+ {
+ ACE_TSS_CLEANUP_GUARD
+ // Double-check;
+ if (in_use_ == ACE_OS::NULL_key)
+ {
+ // Initialize in_use_ with a new key.
+ if (ACE_OS::thr_keycreate (&in_use_,
+ &ACE_TSS_Cleanup_keys_destroyer))
+ {
+ ACE_ASSERT (false);
+ return 0; // Major problems, this should *never* happen!
+ }
+ }
+ }
+
+ void *ts_keys = 0;
+ if (ACE_OS::thr_getspecific (in_use_, &ts_keys) == -1)
+ {
+ ACE_ASSERT (false);
+ return 0; // This should not happen!
+ }
+
+ if (ts_keys == 0)
+ {
+ ACE_NEW_RETURN (ts_keys,
+ ACE_TSS_Keys,
+ 0);
+ // Store the dynamically allocated pointer in thread-specific
+ // storage.
+ if (ACE_OS::thr_setspecific (in_use_, ts_keys) == -1)
+ {
+ ACE_ASSERT (false);
+ delete reinterpret_cast <ACE_TSS_Keys*> (ts_keys);
+ return 0; // Major problems, this should *never* happen!
+ }
+ }
+
+ return reinterpret_cast <ACE_TSS_Keys*>(ts_keys);
+}
+
+#endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
+
+/*****************************************************************************/
+
+// = Static initialization.
+
+// This is necessary to deal with POSIX pthreads insanity. This
+// guarantees that we've got a "zero'd" thread id even when
+// ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented
+// as structures... Under no circumstances should these be given
+// initial values.
+// Note: these three objects require static construction.
+ACE_thread_t ACE_OS::NULL_thread;
+ACE_hthread_t ACE_OS::NULL_hthread;
+#if defined (ACE_HAS_TSS_EMULATION)
+ ACE_thread_key_t ACE_OS::NULL_key = static_cast <ACE_thread_key_t> (-1);
+#else /* ! ACE_HAS_TSS_EMULATION */
+ ACE_thread_key_t ACE_OS::NULL_key;
+#endif /* ! ACE_HAS_TSS_EMULATION */
+
+/*****************************************************************************/
+
+void
+ACE_OS::cleanup_tss (const u_int main_thread)
+{
+#if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32)
+ { // scope the cleanup instance
+ // Call TSS destructors for current thread.
+ TSS_Cleanup_Instance cleanup;
+ if (cleanup.valid ())
+ {
+ cleanup->thread_exit ();
+ }
+ }
+#endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 */
+
+ if (main_thread)
+ {
+#if !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_HAS_MINIMAL_ACE_OS)
+ // Just close the ACE_Log_Msg for the current (which should be
+ // main) thread. We don't have TSS emulation; if there's native
+ // TSS, it should call its destructors when the main thread
+ // exits.
+ ACE_Base_Thread_Adapter::close_log_msg ();
+#endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
+ // Finally, free up the ACE_TSS_Cleanup instance. This method gets
+ // called by the ACE_Object_Manager.
+ TSS_Cleanup_Instance cleanup(TSS_Cleanup_Instance::DESTROY);
+ if (cleanup.valid ())
+ {
+ ; // the pointer deletes the Cleanup when it goes out of scope
+ }
+
+#endif /* WIN32 || ACE_HAS_TSS_EMULATION */
+
+#if defined (ACE_HAS_TSS_EMULATION)
+ ACE_TSS_Emulation::tss_close ();
+#endif /* ACE_HAS_TSS_EMULATION */
+ }
+}
+
+/*****************************************************************************/
+// CONDITIONS BEGIN
+/*****************************************************************************/
+
+#if defined (ACE_LACKS_COND_T)
+// NOTE: The ACE_OS::cond_* functions for some non-Unix platforms are
+// defined here either because they're too big to be inlined, or
+// to avoid use before definition if they were inline.
+
+// @@ The following functions could be inlined if i could figure where
+// to put it among the #ifdefs!
+int
+ACE_OS::condattr_init (ACE_condattr_t &attributes, int type)
+{
+ attributes.type = type;
+ return 0;
+}
+
+int
+ACE_OS::condattr_destroy (ACE_condattr_t &)
+{
+ return 0;
+}
+
+int
+ACE_OS::cond_broadcast (ACE_cond_t *cv)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_broadcast");
+# if defined (ACE_HAS_THREADS)
+ // The <external_mutex> must be locked before this call is made.
+
+ // This is needed to ensure that <waiters_> and <was_broadcast_> are
+ // consistent relative to each other.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+ int have_waiters = 0;
+
+ if (cv->waiters_ > 0)
+ {
+ // We are broadcasting, even if there is just one waiter...
+ // Record the fact that we are broadcasting. This helps the
+ // cond_wait() method know how to optimize itself. Be sure to
+ // set this with the <waiters_lock_> held.
+ cv->was_broadcast_ = 1;
+ have_waiters = 1;
+ }
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+ int result = 0;
+ if (have_waiters)
+ {
+ // Wake up all the waiters.
+ if (ACE_OS::sema_post (&cv->sema_, cv->waiters_) == -1)
+ result = -1;
+ // Wait for all the awakened threads to acquire their part of
+ // the counting semaphore.
+# if defined (ACE_VXWORKS)
+ else if (ACE_OS::sema_wait (&cv->waiters_done_) == -1)
+# else
+ else if (ACE_OS::event_wait (&cv->waiters_done_) == -1)
+# endif /* ACE_VXWORKS */
+ result = -1;
+ // This is okay, even without the <waiters_lock_> held because
+ // no other waiter threads can wake up to access it.
+ cv->was_broadcast_ = 0;
+ }
+ return result;
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::cond_destroy (ACE_cond_t *cv)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_destroy");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_WTHREADS)
+ ACE_OS::event_destroy (&cv->waiters_done_);
+# elif defined (ACE_VXWORKS)
+ ACE_OS::sema_destroy (&cv->waiters_done_);
+# endif /* ACE_VXWORKS */
+ ACE_OS::thread_mutex_destroy (&cv->waiters_lock_);
+ return ACE_OS::sema_destroy (&cv->sema_);
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::cond_init (ACE_cond_t *cv,
+ ACE_condattr_t &attributes,
+ const char *name, void *arg)
+{
+ return
+ ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
+}
+
+# if defined (ACE_HAS_WCHAR)
+int
+ACE_OS::cond_init (ACE_cond_t *cv,
+ ACE_condattr_t &attributes,
+ const wchar_t *name, void *arg)
+{
+ return
+ ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
+}
+# endif /* ACE_HAS_WCHAR */
+
+int
+ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_init");
+# if defined (ACE_HAS_THREADS)
+ cv->waiters_ = 0;
+ cv->was_broadcast_ = 0;
+
+ int result = 0;
+ if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
+ result = -1;
+ else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
+ result = -1;
+# if defined (ACE_VXWORKS)
+ else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
+# else
+ else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
+# endif /* ACE_VXWORKS */
+ result = -1;
+ return result;
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+# if defined (ACE_HAS_WCHAR)
+int
+ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_init");
+# if defined (ACE_HAS_THREADS)
+ cv->waiters_ = 0;
+ cv->was_broadcast_ = 0;
+
+ int result = 0;
+ if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
+ result = -1;
+ else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
+ result = -1;
+# if defined (ACE_VXWORKS)
+ else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
+# else
+ else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
+# endif /* ACE_VXWORKS */
+ result = -1;
+ return result;
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+# endif /* ACE_HAS_WCHAR */
+
+int
+ACE_OS::cond_signal (ACE_cond_t *cv)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_signal");
+# if defined (ACE_HAS_THREADS)
+ // If there aren't any waiters, then this is a no-op. Note that
+ // this function *must* be called with the <external_mutex> held
+ // since other wise there is a race condition that can lead to the
+ // lost wakeup bug... This is needed to ensure that the <waiters_>
+ // value is not in an inconsistent internal state while being
+ // updated by another thread.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+ int have_waiters = cv->waiters_ > 0;
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+ if (have_waiters != 0)
+ return ACE_OS::sema_post (&cv->sema_);
+ else
+ return 0; // No-op
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::cond_wait (ACE_cond_t *cv,
+ ACE_mutex_t *external_mutex)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_wait");
+# if defined (ACE_HAS_THREADS)
+ // Prevent race conditions on the <waiters_> count.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+ ++cv->waiters_;
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+ int result = 0;
+
+# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
+ if (external_mutex->type_ == USYNC_PROCESS)
+ // This call will automatically release the mutex and wait on the semaphore.
+ ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_,
+ cv->sema_, INFINITE, FALSE),
+ result),
+ int, -1, result);
+ else
+# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
+ {
+ // We keep the lock held just long enough to increment the count of
+ // waiters by one. Note that we can't keep it held across the call
+ // to ACE_OS::sema_wait() since that will deadlock other calls to
+ // ACE_OS::cond_signal().
+ if (ACE_OS::mutex_unlock (external_mutex) != 0)
+ return -1;
+
+ // Wait to be awakened by a ACE_OS::cond_signal() or
+ // ACE_OS::cond_broadcast().
+ result = ACE_OS::sema_wait (&cv->sema_);
+ }
+
+ // Reacquire lock to avoid race conditions on the <waiters_> count.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+
+ // We're ready to return, so there's one less waiter.
+ --cv->waiters_;
+
+ int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
+
+ // Release the lock so that other collaborating threads can make
+ // progress.
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+ if (result == -1)
+ // Bad things happened, so let's just return below.
+ /* NOOP */;
+# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
+ else if (external_mutex->type_ == USYNC_PROCESS)
+ {
+ if (last_waiter)
+
+ // This call atomically signals the <waiters_done_> event and
+ // waits until it can acquire the mutex. This is important to
+ // prevent unfairness.
+ ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
+ external_mutex->proc_mutex_,
+ INFINITE, FALSE),
+ result),
+ int, -1, result);
+ else
+ // We must always regain the <external_mutex>, even when
+ // errors occur because that's the guarantee that we give to
+ // our callers.
+ ACE_OS::mutex_lock (external_mutex);
+
+ return result;
+ /* NOTREACHED */
+ }
+# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
+ // If we're the last waiter thread during this particular broadcast
+ // then let all the other threads proceed.
+ else if (last_waiter)
+# if defined (ACE_VXWORKS)
+ ACE_OS::sema_post (&cv->waiters_done_);
+# else
+ ACE_OS::event_signal (&cv->waiters_done_);
+# endif /* ACE_VXWORKS */
+
+ // We must always regain the <external_mutex>, even when errors
+ // occur because that's the guarantee that we give to our callers.
+ ACE_OS::mutex_lock (external_mutex);
+
+ return result;
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_UNUSED_ARG (external_mutex);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::cond_timedwait (ACE_cond_t *cv,
+ ACE_mutex_t *external_mutex,
+ ACE_Time_Value *timeout)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_timedwait");
+# if defined (ACE_HAS_THREADS)
+ // Handle the easy case first.
+ if (timeout == 0)
+ return ACE_OS::cond_wait (cv, external_mutex);
+# if defined (ACE_HAS_WTHREADS) || defined (ACE_VXWORKS)
+
+ // Prevent race conditions on the <waiters_> count.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+ cv->waiters_++;
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+ int result = 0;
+ ACE_Errno_Guard error (errno, 0);
+ int msec_timeout;
+
+ if (timeout->sec () == 0 && timeout->usec () == 0)
+ msec_timeout = 0; // Do a "poll."
+ else
+ {
+ // Note that we must convert between absolute time (which is
+ // passed as a parameter) and relative time (which is what
+ // WaitForSingleObjects() expects).
+ ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
+
+ // Watchout for situations where a context switch has caused the
+ // current time to be > the timeout.
+ if (relative_time < ACE_Time_Value::zero)
+ msec_timeout = 0;
+ else
+ msec_timeout = relative_time.msec ();
+ }
+
+# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
+ if (external_mutex->type_ == USYNC_PROCESS)
+ // This call will automatically release the mutex and wait on the
+ // semaphore.
+ result = ::SignalObjectAndWait (external_mutex->proc_mutex_,
+ cv->sema_,
+ msec_timeout,
+ FALSE);
+ else
+# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
+ {
+ // We keep the lock held just long enough to increment the count
+ // of waiters by one. Note that we can't keep it held across
+ // the call to WaitForSingleObject since that will deadlock
+ // other calls to ACE_OS::cond_signal().
+ if (ACE_OS::mutex_unlock (external_mutex) != 0)
+ return -1;
+
+ // Wait to be awakened by a ACE_OS::signal() or
+ // ACE_OS::broadcast().
+# if defined (ACE_WIN32)
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ result = ::WaitForSingleObject (cv->sema_, msec_timeout);
+# else /* ACE_USES_WINCE_SEMA_SIMULATION */
+ // Can't use Win32 API on our simulated semaphores.
+ result = ACE_OS::sema_wait (&cv->sema_,
+ timeout);
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# elif defined (ACE_VXWORKS)
+ // Inline the call to ACE_OS::sema_wait () because it takes an
+ // ACE_Time_Value argument. Avoid the cost of that conversion . . .
+ int const ticks_per_sec = ::sysClkRateGet ();
+ int const ticks = msec_timeout * ticks_per_sec / ACE_ONE_SECOND_IN_MSECS;
+ result = ::semTake (cv->sema_.sema_, ticks);
+# endif /* ACE_WIN32 || VXWORKS */
+ }
+
+ // Reacquire lock to avoid race conditions.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+ cv->waiters_--;
+
+ int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
+
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+# if defined (ACE_WIN32)
+ if (result != WAIT_OBJECT_0)
+ {
+ switch (result)
+ {
+ case WAIT_TIMEOUT:
+ error = ETIME;
+ break;
+ default:
+ error = ::GetLastError ();
+ break;
+ }
+ result = -1;
+ }
+# elif defined (ACE_VXWORKS)
+ if (result == ERROR)
+ {
+ switch (errno)
+ {
+ case S_objLib_OBJ_TIMEOUT:
+ error = ETIME;
+ break;
+ case S_objLib_OBJ_UNAVAILABLE:
+ if (msec_timeout == 0)
+ error = ETIME;
+ break;
+ default:
+ error = errno;
+ break;
+ }
+ result = -1;
+ }
+# endif /* ACE_WIN32 || VXWORKS */
+# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
+ if (external_mutex->type_ == USYNC_PROCESS)
+ {
+ if (last_waiter)
+ // This call atomically signals the <waiters_done_> event and
+ // waits until it can acquire the mutex. This is important to
+ // prevent unfairness.
+ ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
+ external_mutex->proc_mutex_,
+ INFINITE, FALSE),
+ result),
+ int, -1, result);
+ else
+ // We must always regain the <external_Mutex>, even when
+ // errors occur because that's the guarantee that we give to
+ // our callers.
+ ACE_OS::mutex_lock (external_mutex);
+
+ return result;
+ /* NOTREACHED */
+ }
+# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
+ // Note that this *must* be an "if" statement rather than an "else
+ // if" statement since the caller may have timed out and hence the
+ // result would have been -1 above.
+ if (last_waiter)
+ // Release the signaler/broadcaster if we're the last waiter.
+# if defined (ACE_WIN32)
+ ACE_OS::event_signal (&cv->waiters_done_);
+# else
+ ACE_OS::sema_post (&cv->waiters_done_);
+# endif /* ACE_WIN32 */
+
+ // We must always regain the <external_mutex>, even when errors
+ // occur because that's the guarantee that we give to our callers.
+ ACE_OS::mutex_lock (external_mutex);
+
+ return result;
+# endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS */
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_UNUSED_ARG (external_mutex);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+# if defined (ACE_HAS_WTHREADS)
+int
+ACE_OS::cond_timedwait (ACE_cond_t *cv,
+ ACE_thread_mutex_t *external_mutex,
+ ACE_Time_Value *timeout)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_timedwait");
+# if defined (ACE_HAS_THREADS)
+ // Handle the easy case first.
+ if (timeout == 0)
+ return ACE_OS::cond_wait (cv, external_mutex);
+
+ // Prevent race conditions on the <waiters_> count.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+ cv->waiters_++;
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+ int result = 0;
+ int error = 0;
+ int msec_timeout;
+
+ if (timeout->sec () == 0 && timeout->usec () == 0)
+ msec_timeout = 0; // Do a "poll."
+ else
+ {
+ // Note that we must convert between absolute time (which is
+ // passed as a parameter) and relative time (which is what
+ // WaitForSingleObjects() expects).
+ ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
+
+ // Watchout for situations where a context switch has caused the
+ // current time to be > the timeout.
+ if (relative_time < ACE_Time_Value::zero)
+ msec_timeout = 0;
+ else
+ msec_timeout = relative_time.msec ();
+ }
+
+ // We keep the lock held just long enough to increment the count of
+ // waiters by one. Note that we can't keep it held across the call
+ // to WaitForSingleObject since that will deadlock other calls to
+ // ACE_OS::cond_signal().
+ if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
+ return -1;
+
+ // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast().
+# if defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ // Can't use Win32 API on simulated semaphores.
+ result = ACE_OS::sema_wait (&cv->sema_,
+ timeout);
+
+ if (result == -1 && errno == ETIME)
+ result = WAIT_TIMEOUT;
+# else
+ result = ::WaitForSingleObject (cv->sema_, msec_timeout);
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+
+ // Reacquire lock to avoid race conditions.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+
+ cv->waiters_--;
+
+ int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
+
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+ if (result != WAIT_OBJECT_0)
+ {
+ switch (result)
+ {
+ case WAIT_TIMEOUT:
+ error = ETIME;
+ break;
+ default:
+ error = ::GetLastError ();
+ break;
+ }
+ result = -1;
+ }
+
+ if (last_waiter)
+ // Release the signaler/broadcaster if we're the last waiter.
+ ACE_OS::event_signal (&cv->waiters_done_);
+
+ // We must always regain the <external_mutex>, even when errors
+ // occur because that's the guarantee that we give to our callers.
+ ACE_OS::thread_mutex_lock (external_mutex);
+ errno = error;
+ return result;
+# else
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::cond_wait (ACE_cond_t *cv,
+ ACE_thread_mutex_t *external_mutex)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_wait");
+# if defined (ACE_HAS_THREADS)
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+ cv->waiters_++;
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+ int result = 0;
+ int error = 0;
+
+ // We keep the lock held just long enough to increment the count of
+ // waiters by one. Note that we can't keep it held across the call
+ // to ACE_OS::sema_wait() since that will deadlock other calls to
+ // ACE_OS::cond_signal().
+ if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
+ return -1;
+
+ // Wait to be awakened by a ACE_OS::cond_signal() or
+ // ACE_OS::cond_broadcast().
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ result = ::WaitForSingleObject (cv->sema_, INFINITE);
+# else
+ // Can't use Win32 API on simulated semaphores.
+ result = ACE_OS::sema_wait (&cv->sema_);
+
+ if (result != WAIT_OBJECT_0 && errno == ETIME)
+ result = WAIT_TIMEOUT;
+
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+
+ // Reacquire lock to avoid race conditions.
+ ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
+
+ cv->waiters_--;
+
+ int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
+
+ ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
+
+ if (result != WAIT_OBJECT_0)
+ {
+ switch (result)
+ {
+ case WAIT_TIMEOUT:
+ error = ETIME;
+ break;
+ default:
+ error = ::GetLastError ();
+ break;
+ }
+ }
+ else if (last_waiter)
+ // Release the signaler/broadcaster if we're the last waiter.
+ ACE_OS::event_signal (&cv->waiters_done_);
+
+ // We must always regain the <external_mutex>, even when errors
+ // occur because that's the guarantee that we give to our callers.
+ ACE_OS::thread_mutex_lock (external_mutex);
+
+ // Reset errno in case mutex_lock() also fails...
+ errno = error;
+ return result;
+# else
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+# endif /* ACE_HAS_WTHREADS */
+#else
+int
+ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
+{
+ ACE_condattr_t attributes;
+ if (ACE_OS::condattr_init (attributes, type) == 0
+ && ACE_OS::cond_init (cv, attributes, name, arg) == 0)
+ {
+ (void) ACE_OS::condattr_destroy (attributes);
+ return 0;
+ }
+ return -1;
+}
+#endif /* ACE_LACKS_COND_T */
+
+/*****************************************************************************/
+// CONDITIONS END
+/*****************************************************************************/
+
+/*****************************************************************************/
+// MUTEXES BEGIN
+/*****************************************************************************/
+
+int
+ACE_OS::mutex_init (ACE_mutex_t *m,
+ int lock_scope,
+ const char *name,
+ ACE_mutexattr_t *attributes,
+ LPSECURITY_ATTRIBUTES sa,
+ int lock_type)
+{
+ // ACE_OS_TRACE ("ACE_OS::mutex_init");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (sa);
+
+# if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
+ /* Tests show that VxWorks 6.x pthread lib does not only
+ * require zeroing of mutex/condition objects to function correctly
+ * but also of the attribute objects.
+ */
+ pthread_mutexattr_t l_attributes = {0};
+# else
+ pthread_mutexattr_t l_attributes;
+# endif
+
+ if (attributes == 0)
+ attributes = &l_attributes;
+ int result = 0;
+ int attr_init = 0; // have we initialized the local attributes.
+
+ // Only do these initializations if the <attributes> parameter
+ // wasn't originally set.
+ if (attributes == &l_attributes)
+ {
+ if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes), result) == 0)
+ {
+ result = 0;
+ attr_init = 1; // we have initialized these attributes
+ }
+ else
+ {
+ result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
+ }
+ }
+
+ if (result == 0 && lock_scope != 0)
+{
+# if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)
+ (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes,
+ lock_scope),
+ result);
+# endif /* _POSIX_THREAD_PROCESS_SHARED && !ACE_LACKS_MUTEXATTR_PSHARED */
+}
+
+ if (result == 0 && lock_type != 0)
+{
+# if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_settype (attributes,
+ lock_type),
+ result);
+# endif /* ACE_HAS_RECURSIVE_MUTEXES */
+}
+
+ if (result == 0)
+{
+# if defined (ACE_VXWORKS)&& (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
+ /* VxWorks 6.x API reference states:
+ * If the memory for the mutex variable object has been allocated
+ * dynamically, it is a good policy to always zero out the
+ * block of memory so as to avoid spurious EBUSY return code
+ * when calling this routine.
+ * Tests shows this to be necessary.
+ */
+ ACE_OS::memset (m, 0, sizeof (*m));
+# endif
+ if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m, attributes), result) == 0)
+ result = 0;
+ else
+ result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
+}
+
+ // Only do the deletions if the <attributes> parameter wasn't
+ // originally set.
+ if (attributes == &l_attributes && attr_init)
+ ::pthread_mutexattr_destroy (&l_attributes);
+
+ return result;
+# elif defined (ACE_HAS_STHREADS)
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (sa);
+ ACE_UNUSED_ARG (lock_type);
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m,
+ lock_scope,
+ attributes),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ m->type_ = lock_scope;
+
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+ switch (lock_scope)
+{
+ case USYNC_PROCESS:
+# if defined (ACE_HAS_WINCE)
+ // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
+ m->proc_mutex_ =
+ ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ FALSE,
+ ACE_Ascii_To_Wide (name).wchar_rep ());
+# else /* ACE_HAS_WINCE */
+ m->proc_mutex_ =
+ ::CreateMutexA (ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ FALSE,
+ name);
+# endif /* ACE_HAS_WINCE */
+ if (m->proc_mutex_ == 0)
+ ACE_FAIL_RETURN (-1);
+ else
+ {
+ // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
+ ACE_OS::set_errno_to_last_error ();
+ return 0;
+ }
+ case USYNC_THREAD:
+ return ACE_OS::thread_mutex_init (&m->thr_mutex_,
+ lock_type,
+ name,
+ attributes);
+ default:
+ errno = EINVAL;
+ return -1;
+}
+ /* NOTREACHED */
+
+# elif defined (ACE_VXWORKS)
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (attributes);
+ ACE_UNUSED_ARG (sa);
+ ACE_UNUSED_ARG (lock_type);
+
+ return (*m = ::semMCreate (lock_scope)) == 0 ? -1 : 0;
+# endif /* ACE_HAS_PTHREADS */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (lock_scope);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (attributes);
+ ACE_UNUSED_ARG (sa);
+ ACE_UNUSED_ARG (lock_type);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::mutex_destroy (ACE_mutex_t *m)
+{
+ ACE_OS_TRACE ("ACE_OS::mutex_destroy");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m),
+ result), int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m), result), int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ switch (m->type_)
+{
+ case USYNC_PROCESS:
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m->proc_mutex_),
+ ace_result_),
+ int, -1);
+ case USYNC_THREAD:
+ return ACE_OS::thread_mutex_destroy (&m->thr_mutex_);
+ default:
+ errno = EINVAL;
+ return -1;
+}
+ /* NOTREACHED */
+# elif defined (ACE_VXWORKS)
+ return ::semDelete (*m) == OK ? 0 : -1;
+# endif /* Threads variety case */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+#if defined (ACE_HAS_WCHAR)
+int
+ACE_OS::mutex_init (ACE_mutex_t *m,
+ int lock_scope,
+ const wchar_t *name,
+ ACE_mutexattr_t *attributes,
+ LPSECURITY_ATTRIBUTES sa,
+ int lock_type)
+{
+#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
+ m->type_ = lock_scope;
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+ switch (lock_scope)
+ {
+ case USYNC_PROCESS:
+ m->proc_mutex_ =
+ ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ FALSE,
+ name);
+ if (m->proc_mutex_ == 0)
+ ACE_FAIL_RETURN (-1);
+ else
+ return 0;
+ case USYNC_THREAD:
+ return ACE_OS::thread_mutex_init (&m->thr_mutex_,
+ lock_type,
+ name,
+ attributes);
+ }
+
+ errno = EINVAL;
+ return -1;
+#else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
+ return ACE_OS::mutex_init (m,
+ lock_scope,
+ ACE_Wide_To_Ascii (name).char_rep (),
+ attributes,
+ sa,
+ lock_type);
+#endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
+}
+#endif /* ACE_HAS_WCHAR */
+
+int
+ACE_OS::mutex_lock (ACE_mutex_t *m)
+{
+ // ACE_OS_TRACE ("ACE_OS::mutex_lock");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ // Note, don't use "::" here since the following call is often a macro.
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m), result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m), result), int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ switch (m->type_)
+{
+ case USYNC_PROCESS:
+ switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
+ {
+ //
+ // Timeout can't occur, so don't bother checking...
+ //
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ // We will ignore abandonments in this method
+ // Note that we still hold the lock
+ return 0;
+ default:
+ // This is a hack, we need to find an appropriate mapping...
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ case USYNC_THREAD:
+ return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
+ default:
+ errno = EINVAL;
+ return -1;
+}
+ /* NOTREACHED */
+# elif defined (ACE_VXWORKS)
+ return ::semTake (*m, WAIT_FOREVER) == OK ? 0 : -1;
+# endif /* Threads variety case */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::mutex_lock (ACE_mutex_t *m,
+ int &abandoned)
+{
+ ACE_OS_TRACE ("ACE_OS::mutex_lock");
+#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
+ abandoned = 0;
+ switch (m->type_)
+ {
+ case USYNC_PROCESS:
+ switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
+ {
+ //
+ // Timeout can't occur, so don't bother checking...
+ //
+ case WAIT_OBJECT_0:
+ return 0;
+ case WAIT_ABANDONED:
+ abandoned = 1;
+ return 0; // something goofed, but we hold the lock ...
+ default:
+ // This is a hack, we need to find an appropriate mapping...
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ case USYNC_THREAD:
+ return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ /* NOTREACHED */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (abandoned);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
+}
+
+int
+ACE_OS::mutex_lock (ACE_mutex_t *m,
+ const ACE_Time_Value &timeout)
+{
+#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS)
+
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+
+ // "timeout" should be an absolute time.
+
+ timespec_t ts = timeout; // Calls ACE_Time_Value::operator timespec_t().
+
+ // Note that the mutex should not be a recursive one, i.e., it
+ // should only be a standard mutex or an error checking mutex.
+
+ ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m, &ts), result), int, -1, result);
+
+ // We need to adjust this to make the errno values consistent.
+ if (result == -1 && errno == ETIMEDOUT)
+ errno = ETIME;
+ return result;
+
+# elif defined (ACE_HAS_WTHREADS)
+ // Note that we must convert between absolute time (which is passed
+ // as a parameter) and relative time (which is what the system call
+ // expects).
+ ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ());
+
+ switch (m->type_)
+ {
+ case USYNC_PROCESS:
+ switch (::WaitForSingleObject (m->proc_mutex_,
+ relative_time.msec ()))
+ {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ // We will ignore abandonments in this method
+ // Note that we still hold the lock
+ return 0;
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ return -1;
+ default:
+ // This is a hack, we need to find an appropriate mapping...
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ case USYNC_THREAD:
+ ACE_NOTSUP_RETURN (-1);
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ /* NOTREACHED */
+
+# elif defined (ACE_VXWORKS)
+
+ // Note that we must convert between absolute time (which is passed
+ // as a parameter) and relative time (which is what the system call
+ // expects).
+ ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ());
+
+ int ticks_per_sec = ::sysClkRateGet ();
+
+ int ticks = relative_time.sec() * ticks_per_sec +
+ relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
+ if (::semTake (*m, ticks) == ERROR)
+ {
+ if (errno == S_objLib_OBJ_TIMEOUT)
+ // Convert the VxWorks errno to one that's common for to ACE
+ // platforms.
+ errno = ETIME;
+ else if (errno == S_objLib_OBJ_UNAVAILABLE)
+ errno = EBUSY;
+ return -1;
+ }
+ else
+ return 0;
+# endif /* ACE_HAS_PTHREADS */
+
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */
+}
+
+int
+ACE_OS::mutex_trylock (ACE_mutex_t *m)
+{
+ ACE_OS_TRACE ("ACE_OS::mutex_trylock");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ // Note, don't use "::" here since the following call is often a macro.
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m), result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m), result), int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ switch (m->type_)
+{
+ case USYNC_PROCESS:
+ {
+ // Try for 0 milliseconds - i.e. nonblocking.
+ switch (::WaitForSingleObject (m->proc_mutex_, 0))
+ {
+ case WAIT_OBJECT_0:
+ return 0;
+ case WAIT_ABANDONED:
+ // We will ignore abandonments in this method. Note that
+ // we still hold the lock.
+ return 0;
+ case WAIT_TIMEOUT:
+ errno = EBUSY;
+ return -1;
+ default:
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ }
+ case USYNC_THREAD:
+ return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
+ default:
+ errno = EINVAL;
+ return -1;
+}
+ /* NOTREACHED */
+# elif defined (ACE_VXWORKS)
+ if (::semTake (*m, NO_WAIT) == ERROR)
+ if (errno == S_objLib_OBJ_UNAVAILABLE)
+{
+ // couldn't get the semaphore
+ errno = EBUSY;
+ return -1;
+}
+ else
+ // error
+ return -1;
+ else
+ // got the semaphore
+ return 0;
+# endif /* Threads variety case */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::mutex_trylock (ACE_mutex_t *m, int &abandoned)
+{
+#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
+ abandoned = 0;
+ switch (m->type_)
+ {
+ case USYNC_PROCESS:
+ {
+ // Try for 0 milliseconds - i.e. nonblocking.
+ switch (::WaitForSingleObject (m->proc_mutex_, 0))
+ {
+ case WAIT_OBJECT_0:
+ return 0;
+ case WAIT_ABANDONED:
+ abandoned = 1;
+ return 0; // something goofed, but we hold the lock ...
+ case WAIT_TIMEOUT:
+ errno = EBUSY;
+ return -1;
+ default:
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ }
+ case USYNC_THREAD:
+ return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ /* NOTREACHED */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (abandoned);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
+}
+
+int
+ACE_OS::mutex_unlock (ACE_mutex_t *m)
+{
+ ACE_OS_TRACE ("ACE_OS::mutex_unlock");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ // Note, don't use "::" here since the following call is often a macro.
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m), result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m), result), int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ switch (m->type_)
+{
+ case USYNC_PROCESS:
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m->proc_mutex_),
+ ace_result_),
+ int, -1);
+ case USYNC_THREAD:
+ return ACE_OS::thread_mutex_unlock (&m->thr_mutex_);
+ default:
+ errno = EINVAL;
+ return -1;
+}
+ /* NOTREACHED */
+# elif defined (ACE_VXWORKS)
+ return ::semGive (*m) == OK ? 0 : -1;
+# endif /* Threads variety case */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+void
+ACE_OS::mutex_lock_cleanup (void *mutex)
+{
+ ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex;
+ ACE_OS::mutex_unlock (p_lock);
+# else
+ ACE_UNUSED_ARG (mutex);
+# endif /* ACE_HAS_PTHREADS */
+#else
+ ACE_UNUSED_ARG (mutex);
+#endif /* ACE_HAS_THREADS */
+}
+
+/*****************************************************************************/
+// MUTEXES END
+/*****************************************************************************/
+
+/*****************************************************************************/
+// EVENTS BEGIN
+/*****************************************************************************/
+
+int
+ACE_OS::event_destroy (ACE_event_t *event)
+{
+#if defined (ACE_WIN32)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event), ace_result_), int, -1);
+#elif defined (ACE_HAS_THREADS)
+ if (event->eventdata_)
+ {
+ // mutex_destroy()/cond_destroy() are called in a loop if the object
+ // is BUSY. This avoids conditions where we fail to destroy these
+ // objects because at time of destroy they were just being used in
+ // another thread possibly causing deadlocks later on if they keep
+ // being used after we're gone.
+
+ if (event->eventdata_->type_ == USYNC_PROCESS)
+ {
+ if (event->name_)
+ {
+ // Only destroy the event data if we're the ones who initialized
+ // it.
+
+ int r1, r2;
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ // First destroy the mutex so locking after this will return
+ // errors.
+ while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
+ && errno == EBUSY)
+ {
+ ACE_OS::thr_yield ();
+ }
+# else
+ r1 = ACE_OS::sema_destroy(&event->lock_);
+# endif
+
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ // Now fix event to manual reset, raise signal and broadcast
+ // until is's possible to destroy the condition.
+ event->eventdata_->manual_reset_ = 1;
+ while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1
+ && errno == EBUSY)
+ {
+ event->eventdata_->is_signaled_ = 1;
+ ACE_OS::cond_broadcast (&event->eventdata_->condition_);
+ ACE_OS::thr_yield ();
+ }
+# else
+ r2 = ACE_OS::sema_destroy(&event->semaphore_);
+# endif
+ ACE_OS::munmap (event->eventdata_,
+ sizeof (ACE_eventdata_t));
+ ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR(event->name_));
+ ACE_OS::free (event->name_);
+ return r1 != 0 || r2 != 0 ? -1 : 0;
+ }
+ else
+ {
+ ACE_OS::munmap (event->eventdata_,
+ sizeof (ACE_eventdata_t));
+# if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || \
+ (defined (ACE_LACKS_MUTEXATTR_PSHARED) && defined (ACE_LACKS_CONDATTR_PSHARED))) && \
+ (defined (ACE_USES_FIFO_SEM) || \
+ (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ ACE_OS::sema_destroy(&event->lock_);
+# endif
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ return 0;
+# else
+ return ACE_OS::sema_destroy(&event->semaphore_);
+# endif
+ }
+ }
+ else
+ {
+ int r1, r2;
+ // First destroy the mutex so locking after this will return errors.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ // first destroy the mutex so locking after this will return errors
+ while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
+ && errno == EBUSY)
+ {
+ ACE_OS::thr_yield ();
+ }
+# else
+ r1 = ACE_OS::sema_destroy(&event->lock_);
+# endif
+
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ // Now fix event to manual reset, raise signal and broadcast until
+ // it's possible to destroy the condition.
+ event->eventdata_->manual_reset_ = 1;
+ while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1
+ && errno == EBUSY)
+ {
+ event->eventdata_->is_signaled_ = 1;
+ ACE_OS::cond_broadcast (&event->eventdata_->condition_);
+ ACE_OS::thr_yield ();
+ }
+# else
+ r2 = ACE_OS::sema_destroy(&event->semaphore_);
+# endif
+ delete event->eventdata_;
+ return r1 != 0 || r2 != 0 ? -1 : 0;
+ }
+ }
+
+ return 0;
+#else
+ ACE_UNUSED_ARG (event);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_OS::event_init (ACE_event_t *event,
+ int manual_reset,
+ int initial_state,
+ int type,
+ const char *name,
+ void *arg,
+ LPSECURITY_ATTRIBUTES sa)
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (arg);
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+# if defined (ACE_HAS_WINCE)
+ // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
+ *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ manual_reset,
+ initial_state,
+ ACE_Ascii_To_Wide (name).wchar_rep ());
+# else /* ACE_HAS_WINCE */
+ *event = ::CreateEventA (ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ manual_reset,
+ initial_state,
+ name);
+# endif /* ACE_HAS_WINCE */
+ if (*event == 0)
+ ACE_FAIL_RETURN (-1);
+ else
+ return 0;
+#elif defined (ACE_HAS_THREADS)
+ ACE_UNUSED_ARG (sa);
+ event->eventdata_ = 0;
+ ACE_eventdata_t* evtdata;
+
+ if (type == USYNC_PROCESS)
+ {
+ const char *name_p = 0;
+# if defined (ACE_SHM_OPEN_REQUIRES_ONE_SLASH)
+ char adj_name[MAXPATHLEN];
+ if (name[0] != '/')
+ {
+ adj_name[0] = '/';
+ ACE_OS::strsncpy (&adj_name[1], name, MAXPATHLEN-1);
+ name_p = adj_name;
+ }
+ else
+ {
+ name_p = name;
+ }
+# else
+ name_p = name;
+# endif /* ACE_SHM_OPEN_REQUIRES_ONE_SLASH */
+ int owner = 0;
+ // Let's see if the shared memory entity already exists.
+ ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p),
+ O_RDWR | O_CREAT | O_EXCL,
+ ACE_DEFAULT_FILE_PERMS);
+ if (fd == ACE_INVALID_HANDLE)
+ {
+ if (errno == EEXIST)
+ fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p),
+ O_RDWR | O_CREAT,
+ ACE_DEFAULT_FILE_PERMS);
+ if (fd == ACE_INVALID_HANDLE) // Still can't get it.
+ return -1;
+ }
+ else
+ {
+ // We own this shared memory object! Let's set its size.
+ if (ACE_OS::ftruncate (fd, sizeof (ACE_eventdata_t)) == -1)
+ {
+ ACE_OS::close (fd);
+ return -1;
+ }
+ owner = 1;
+ }
+
+ evtdata =
+ (ACE_eventdata_t *) ACE_OS::mmap (0,
+ sizeof (ACE_eventdata_t),
+ PROT_RDWR,
+ MAP_SHARED,
+ fd,
+ 0);
+ ACE_OS::close (fd);
+ if (evtdata == MAP_FAILED)
+ {
+ if (owner)
+ ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
+ return -1;
+ }
+
+ if (owner)
+ {
+ event->name_ = ACE_OS::strdup (name_p);
+ if (event->name_ == 0)
+ {
+ ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
+ return -1;
+ }
+ event->eventdata_ = evtdata;
+ event->eventdata_->type_ = type;
+ event->eventdata_->manual_reset_ = manual_reset;
+ event->eventdata_->is_signaled_ = initial_state;
+ event->eventdata_->auto_event_signaled_ = false;
+ event->eventdata_->waiting_threads_ = 0;
+ event->eventdata_->signal_count_ = 0;
+
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ int result = ACE_OS::cond_init (&event->eventdata_->condition_,
+ static_cast<short> (type),
+ name,
+ arg);
+# else
+ char sem_name[128];
+ ACE_OS::strncpy (sem_name,
+ name,
+ sizeof (sem_name) - (1 + sizeof ("._ACE_EVTSEM_")));
+ ACE_OS::strcat (sem_name, "._ACE_EVTSEM_");
+ int result = ACE_OS::sema_init (&event->semaphore_,
+ 0,
+ type,
+ sem_name,
+ arg);
+# endif
+ if (result == 0)
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ result = ACE_OS::mutex_init (&event->eventdata_->lock_,
+ type,
+ name,
+ (ACE_mutexattr_t *) arg);
+# else
+ {
+ char lck_name[128];
+ ACE_OS::strncpy
+ (lck_name,
+ name,
+ sizeof (lck_name) - (1 + sizeof ("._ACE_EVTLCK_")));
+ ACE_OS::strcat (lck_name, "._ACE_EVTLCK_");
+ result = ACE_OS::sema_init (&event->lock_,
+ 0,
+ type,
+ lck_name,
+ arg);
+ if (result == 0)
+ result = ACE_OS::sema_post (&event->lock_); /* Initially unlock */
+ }
+# endif
+ return result;
+ }
+ else
+ {
+ int result = 0;
+
+ event->name_ = 0;
+ event->eventdata_ = evtdata;
+#if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_CONDATTR_PSHARED)) && \
+ (defined (ACE_USES_FIFO_SEM) || \
+ (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ char sem_name[128];
+ ACE_OS::strncpy (sem_name,
+ name,
+ sizeof (sem_name) - (1 + sizeof ("._ACE_EVTSEM_")));
+ ACE_OS::strcat (sem_name, "._ACE_EVTSEM_");
+ result = ACE_OS::sema_init(&event->semaphore_,
+ 0,
+ type,
+ sem_name,
+ arg);
+# endif
+
+# if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || \
+ (defined (ACE_LACKS_MUTEXATTR_PSHARED) && defined (ACE_LACKS_CONDATTR_PSHARED))) && \
+ (defined (ACE_USES_FIFO_SEM) || \
+ (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (result == 0)
+ {
+ char lck_name[128];
+ ACE_OS::strncpy
+ (lck_name,
+ name,
+ sizeof (lck_name) - (1 + sizeof ("._ACE_EVTLCK_")));
+ ACE_OS::strcat (lck_name, "._ACE_EVTLCK_");
+ result = ACE_OS::sema_init (&event->lock_,
+ 0,
+ type,
+ lck_name,
+ arg);
+ }
+# endif
+ return result;
+ }
+ }
+ else
+ {
+ ACE_NEW_RETURN (evtdata, ACE_eventdata_t, -1);
+ event->name_ = 0;
+ event->eventdata_ = evtdata;
+ event->eventdata_->type_ = type;
+ event->eventdata_->manual_reset_ = manual_reset;
+ event->eventdata_->is_signaled_ = initial_state;
+ event->eventdata_->auto_event_signaled_ = false;
+ event->eventdata_->waiting_threads_ = 0;
+ event->eventdata_->signal_count_ = 0;
+
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ int result = ACE_OS::cond_init (&event->eventdata_->condition_,
+ static_cast<short> (type),
+ name,
+ arg);
+# else
+ int result = ACE_OS::sema_init (&event->semaphore_,
+ 0,
+ type,
+ name,
+ arg);
+# endif
+ if (result == 0)
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ result = ACE_OS::mutex_init (&event->eventdata_->lock_,
+ type,
+ name,
+ (ACE_mutexattr_t *) arg);
+# else
+ result = ACE_OS::sema_init (&event->lock_,
+ 0,
+ type,
+ name,
+ arg);
+ if (result == 0)
+ result = ACE_OS::sema_post(&event->lock_); /* initially unlock */
+# endif
+
+ return result;
+ }
+#else
+ ACE_UNUSED_ARG (event);
+ ACE_UNUSED_ARG (manual_reset);
+ ACE_UNUSED_ARG (initial_state);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_UNUSED_ARG (sa);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_OS::event_pulse (ACE_event_t *event)
+{
+#if defined (ACE_WIN32)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event), ace_result_), int, -1);
+#elif defined (ACE_HAS_THREADS)
+ int result = 0;
+ int error = 0;
+
+ // grab the lock first
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
+# else
+ if (ACE_OS::sema_wait (&event->lock_) == 0)
+# endif
+ {
+ if (event->eventdata_->waiting_threads_ > 0)
+ {
+ // Manual-reset event.
+ if (event->eventdata_->manual_reset_ == 1)
+ {
+ // Wakeup all waiters.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
+ {
+ result = -1;
+ error = errno;
+ }
+ if (result == 0)
+ event->eventdata_->signal_count_ = event->eventdata_->waiting_threads_;
+# else
+ event->eventdata_->signal_count_ = event->eventdata_->waiting_threads_;
+ for (unsigned long i=0; i<event->eventdata_->signal_count_ ;++i)
+ if (ACE_OS::sema_post(&event->semaphore_) != 0)
+ {
+ event->eventdata_->signal_count_ = 0;
+ result = -1;
+ error = errno;
+ }
+
+ if (result == 0)
+ while(event->eventdata_->signal_count_!=0 && event->eventdata_->waiting_threads_!=0)
+ ACE_OS::thr_yield ();
+# endif
+ }
+ // Auto-reset event: wakeup one waiter.
+ else
+ {
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::cond_signal (&event->eventdata_->condition_) != 0)
+# else
+ if (ACE_OS::sema_post(&event->semaphore_) != 0)
+# endif
+ {
+ result = -1;
+ error = errno;
+ }
+
+ event->eventdata_->auto_event_signaled_ = true;
+ }
+ }
+
+ // Reset event.
+ event->eventdata_->is_signaled_ = 0;
+
+ // Now we can let go of the lock.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ ACE_OS::mutex_unlock (&event->eventdata_->lock_);
+# else
+ ACE_OS::sema_post (&event->lock_);
+# endif
+ if (result == -1)
+ // Reset errno in case mutex_unlock() also fails...
+ errno = error;
+ }
+ else
+ result = -1;
+ return result;
+#else
+ ACE_UNUSED_ARG (event);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_OS::event_reset (ACE_event_t *event)
+{
+#if defined (ACE_WIN32)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event), ace_result_), int, -1);
+#elif defined (ACE_HAS_THREADS)
+ int result = 0;
+
+ // Grab the lock first.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
+# else
+ if (ACE_OS::sema_wait (&event->lock_) == 0)
+# endif
+ {
+ // Reset event.
+ event->eventdata_->is_signaled_ = 0;
+ event->eventdata_->auto_event_signaled_ = false;
+
+ // Now we can let go of the lock.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ ACE_OS::mutex_unlock (&event->eventdata_->lock_);
+# else
+ ACE_OS::sema_post (&event->lock_);
+# endif
+ }
+ else
+ result = -1;
+ return result;
+#else
+ ACE_UNUSED_ARG (event);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_OS::event_signal (ACE_event_t *event)
+{
+#if defined (ACE_WIN32)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event), ace_result_), int, -1);
+#elif defined (ACE_HAS_THREADS)
+ int result = 0;
+ int error = 0;
+
+ // grab the lock first
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
+# else
+ if (ACE_OS::sema_wait (&event->lock_) == 0)
+# endif
+ {
+ // Manual-reset event.
+ if (event->eventdata_->manual_reset_ == 1)
+ {
+ // wakeup all
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
+ {
+ result = -1;
+ error = errno;
+ }
+# else
+ if (ACE_OS::sema_post(&event->semaphore_) != 0)
+ {
+ result = -1;
+ error = errno;
+ }
+# endif
+
+ if (result == 0)
+ // signal event
+ event->eventdata_->is_signaled_ = 1;
+ }
+ // Auto-reset event
+ else
+ {
+ if (event->eventdata_->waiting_threads_ == 0)
+ // No waiters: signal event.
+ event->eventdata_->is_signaled_ = 1;
+ // Waiters: wakeup one waiter.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ else if (ACE_OS::cond_signal (&event->eventdata_->condition_) != 0)
+# else
+ else if (ACE_OS::sema_post(&event->semaphore_) != 0)
+# endif
+ {
+ result = -1;
+ error = errno;
+ }
+
+ event->eventdata_->auto_event_signaled_ = true;
+ }
+
+ // Now we can let go of the lock.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ ACE_OS::mutex_unlock (&event->eventdata_->lock_);
+# else
+ ACE_OS::sema_post (&event->lock_);
+# endif
+
+ if (result == -1)
+ // Reset errno in case mutex_unlock() also fails...
+ errno = error;
+ }
+ else
+ result = -1;
+
+ return result;
+#else
+ ACE_UNUSED_ARG (event);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_OS::event_timedwait (ACE_event_t *event,
+ ACE_Time_Value *timeout,
+ int use_absolute_time)
+{
+#if defined (ACE_WIN32)
+ DWORD result;
+
+ if (timeout == 0)
+ // Wait forever
+ result = ::WaitForSingleObject (*event, INFINITE);
+ else if (timeout->sec () == 0 && timeout->usec () == 0)
+ // Do a "poll".
+ result = ::WaitForSingleObject (*event, 0);
+ else
+ {
+ // Wait for upto <relative_time> number of milliseconds. Note
+ // that we must convert between absolute time (which is passed
+ // as a parameter) and relative time (which is what
+ // WaitForSingleObjects() expects).
+ // <timeout> parameter is given in absolute or relative value
+ // depending on parameter <use_absolute_time>.
+ int msec_timeout;
+ if (use_absolute_time)
+ {
+ // Time is given in absolute time, we should use
+ // gettimeofday() to calculate relative time
+ ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
+
+ // Watchout for situations where a context switch has caused
+ // the current time to be > the timeout. Thanks to Norbert
+ // Rapp <NRapp@nexus-informatics.de> for pointing this.
+ if (relative_time < ACE_Time_Value::zero)
+ msec_timeout = 0;
+ else
+ msec_timeout = relative_time.msec ();
+ }
+ else
+ // time is given in relative time, just convert it into
+ // milliseconds and use it
+ msec_timeout = timeout->msec ();
+ result = ::WaitForSingleObject (*event, msec_timeout);
+ }
+
+ switch (result)
+ {
+ case WAIT_OBJECT_0:
+ return 0;
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ return -1;
+ default:
+ // This is a hack, we need to find an appropriate mapping...
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+#elif defined (ACE_HAS_THREADS)
+ int result = 0;
+ int error = 0;
+
+ // grab the lock first
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
+# else
+ if (ACE_OS::sema_wait (&event->lock_) == 0)
+# endif
+ {
+ if (event->eventdata_->is_signaled_ == 1)
+ // event is currently signaled
+ {
+ if (event->eventdata_->manual_reset_ == 0)
+ {
+ // AUTO: reset state
+ event->eventdata_->is_signaled_ = 0;
+ event->eventdata_->auto_event_signaled_ = false;
+ }
+ }
+ else
+ // event is currently not signaled
+ {
+ event->eventdata_->waiting_threads_++;
+
+ ACE_Time_Value absolute_timeout = *timeout;
+
+ // cond_timewait() expects absolute time, check
+ // <use_absolute_time> flag.
+ if (use_absolute_time == 0)
+ absolute_timeout += ACE_OS::gettimeofday ();
+
+ while (event->eventdata_->is_signaled_ == 0 &&
+ event->eventdata_->auto_event_signaled_ == false)
+ {
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::cond_timedwait (&event->eventdata_->condition_,
+ &event->eventdata_->lock_,
+ &absolute_timeout) != 0)
+ {
+ result = -1;
+ error = errno;
+ break;
+ }
+
+ if (event->eventdata_->signal_count_ > 0)
+ {
+ event->eventdata_->signal_count_--;
+ break;
+ }
+# else
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_unlock (&event->eventdata_->lock_) != 0)
+# else
+ if (ACE_OS::sema_post (&event->lock_) != 0)
+# endif
+ {
+ event->eventdata_->waiting_threads_--;
+ return -1;
+ }
+
+ if (ACE_OS::sema_wait(&event->semaphore_, absolute_timeout) !=0)
+ {
+ result = -1;
+ if (errno == ETIMEDOUT) // Semaphores time out with ETIMEDOUT (POSIX)
+ error = ETIME;
+ else
+ error = errno;
+ }
+
+ bool signalled = false;
+ if (result == 0 && event->eventdata_->signal_count_ > 0)
+ {
+ event->eventdata_->signal_count_--;
+ signalled = true;
+ }
+
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_lock (&event->eventdata_->lock_) != 0)
+# else
+ if (ACE_OS::sema_wait (&event->lock_) != 0)
+# endif
+ {
+ event->eventdata_->waiting_threads_--; // yes, I know it's not save
+ return -1;
+ }
+
+ if (result)
+ break;
+
+ if (event->eventdata_->manual_reset_ == 1 && event->eventdata_->is_signaled_ == 1)
+ if (ACE_OS::sema_post(&event->semaphore_) != 0)
+ {
+ result = -1;
+ error = errno;
+ break;
+ }
+
+ if (signalled)
+ break;
+# endif
+ }
+
+ // Reset the auto_event_signaled_ to false now that we have
+ // woken up.
+ if (event->eventdata_->auto_event_signaled_ == true)
+ event->eventdata_->auto_event_signaled_ = false;
+
+ event->eventdata_->waiting_threads_--;
+ }
+
+ // Now we can let go of the lock.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ ACE_OS::mutex_unlock (&event->eventdata_->lock_);
+# else
+ ACE_OS::sema_post (&event->lock_);
+# endif
+
+ if (result == -1)
+ // Reset errno in case mutex_unlock() also fails...
+ errno = error;
+ }
+ else
+ result = -1;
+ return result;
+#else
+ ACE_UNUSED_ARG (event);
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (use_absolute_time);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_OS::event_wait (ACE_event_t *event)
+{
+#if defined (ACE_WIN32)
+ switch (::WaitForSingleObject (*event, INFINITE))
+{
+ case WAIT_OBJECT_0:
+ return 0;
+ default:
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+}
+#elif defined (ACE_HAS_THREADS)
+ int result = 0;
+ int error = 0;
+
+ // grab the lock first
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
+# else
+ if (ACE_OS::sema_wait (&event->lock_) == 0)
+# endif
+ {
+ if (event->eventdata_->is_signaled_ == 1)
+ // Event is currently signaled.
+ {
+ if (event->eventdata_->manual_reset_ == 0)
+ // AUTO: reset state
+ event->eventdata_->is_signaled_ = 0;
+ }
+ else // event is currently not signaled
+ {
+ event->eventdata_->waiting_threads_++;
+
+ while (event->eventdata_->is_signaled_ == 0 &&
+ event->eventdata_->auto_event_signaled_ == false)
+ {
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::cond_wait (&event->eventdata_->condition_,
+ &event->eventdata_->lock_) != 0)
+ {
+ result = -1;
+ error = errno;
+ // Something went wrong...
+ break;
+ }
+ if (event->eventdata_->signal_count_ > 0)
+ {
+ event->eventdata_->signal_count_--;
+ break;
+ }
+# else
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_unlock (&event->eventdata_->lock_) != 0)
+# else
+ if (ACE_OS::sema_post (&event->lock_) != 0)
+# endif
+ {
+ event->eventdata_->waiting_threads_--;
+ return -1;
+ }
+
+ if (ACE_OS::sema_wait(&event->semaphore_) !=0)
+ {
+ result = -1;
+ error = errno;
+ }
+
+ bool signalled = false;
+ if (result == 0 && event->eventdata_->signal_count_ > 0)
+ {
+ event->eventdata_->signal_count_--;
+ signalled = true;
+ }
+
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ if (ACE_OS::mutex_lock (&event->eventdata_->lock_) != 0)
+# else
+ if (ACE_OS::sema_wait (&event->lock_) != 0)
+# endif
+ {
+ event->eventdata_->waiting_threads_--;
+ return -1;
+ }
+
+ if (result)
+ break;
+
+ if (event->eventdata_->manual_reset_ == 1 && event->eventdata_->is_signaled_ == 1)
+ if (ACE_OS::sema_post(&event->semaphore_) != 0)
+ {
+ result = -1;
+ error = errno;
+ break;
+ }
+
+ if (signalled)
+ break;
+# endif
+ }
+
+ // Reset it since we have woken up.
+ if (event->eventdata_->auto_event_signaled_ == true)
+ event->eventdata_->auto_event_signaled_ = false;
+
+ event->eventdata_->waiting_threads_--;
+ }
+
+ // Now we can let go of the lock.
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
+ (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ ACE_OS::mutex_unlock (&event->eventdata_->lock_);
+# else
+ ACE_OS::sema_post (&event->lock_);
+# endif
+
+ if (result == -1)
+ // Reset errno in case mutex_unlock() also fails...
+ errno = error;
+}
+ else
+ result = -1;
+ return result;
+#else
+ ACE_UNUSED_ARG (event);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+/*****************************************************************************/
+// EVENTS END
+/*****************************************************************************/
+
+int
+ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params)
+{
+#if defined (ACE_HAS_STHREADS) || defined (sun)
+ // Get the class TS and RT class IDs.
+ ACE_id_t rt_id;
+ ACE_id_t ts_id;
+ if (ACE_OS::scheduling_class ("RT", rt_id) == -1
+ || ACE_OS::scheduling_class ("TS", ts_id) == -1)
+ return -1;
+
+ // Get this LWP's scheduling parameters.
+ pcparms_t pcparms;
+ // The following is just to avoid Purify warnings about unitialized
+ // memory reads.
+ ACE_OS::memset (&pcparms, 0, sizeof pcparms);
+ pcparms.pc_cid = PC_CLNULL;
+
+ if (ACE_OS::priority_control (P_LWPID,
+ P_MYID,
+ PC_GETPARMS,
+ (char *) &pcparms) == -1)
+ return -1;
+ else if (pcparms.pc_cid == rt_id)
+ {
+ // RT class.
+ rtparms_t rtparms;
+ ACE_OS::memcpy (&rtparms, pcparms.pc_clparms, sizeof rtparms);
+
+ sched_params.policy (ACE_SCHED_FIFO);
+ sched_params.priority (rtparms.rt_pri);
+ sched_params.scope (ACE_SCOPE_THREAD);
+ ACE_Time_Value quantum (rtparms.rt_tqsecs,
+ rtparms.rt_tqnsecs == RT_TQINF
+ ? 0 : rtparms.rt_tqnsecs * 1000);
+ sched_params.quantum (quantum);
+ return 0;
+ }
+ else if (pcparms.pc_cid == ts_id)
+ {
+ /* TS class */
+ tsparms_t tsparms;
+ ACE_OS::memcpy (&tsparms, pcparms.pc_clparms, sizeof tsparms);
+
+ sched_params.policy (ACE_SCHED_OTHER);
+ sched_params.priority (tsparms.ts_upri);
+ sched_params.scope (ACE_SCOPE_THREAD);
+ return 0;
+ }
+ else
+ return -1;
+
+#else /* ! ACE_HAS_STHREADS && ! sun */
+ ACE_UNUSED_ARG (sched_params);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ! ACE_HAS_STHREADS && ! sun */
+}
+
+int
+ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params)
+{
+#if defined (ACE_HAS_STHREADS) || defined (sun)
+ ACE_Sched_Params lwp_params (sched_params);
+ lwp_params.scope (ACE_SCOPE_LWP);
+ return ACE_OS::sched_params (lwp_params);
+#else /* ! ACE_HAS_STHREADS && ! sun */
+ ACE_UNUSED_ARG (sched_params);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ! ACE_HAS_STHREADS && ! sun */
+}
+
+#if !defined (ACE_HAS_THREADS) || (defined (ACE_LACKS_RWLOCK_T) && \
+ !defined (ACE_HAS_PTHREADS_UNIX98_EXT))
+int
+ACE_OS::rwlock_init (ACE_rwlock_t *rw,
+ int type,
+ const ACE_TCHAR *name,
+ void *arg)
+{
+ // ACE_OS_TRACE ("ACE_OS::rwlock_init");
+# if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T)
+ // NT, POSIX, and VxWorks don't support this natively.
+ ACE_UNUSED_ARG (name);
+ int result = -1;
+
+ // Since we cannot use the user specified name for all three
+ // objects, we will create three completely new names.
+ ACE_TCHAR name1[ACE_UNIQUE_NAME_LEN];
+ ACE_TCHAR name2[ACE_UNIQUE_NAME_LEN];
+ ACE_TCHAR name3[ACE_UNIQUE_NAME_LEN];
+ ACE_TCHAR name4[ACE_UNIQUE_NAME_LEN];
+
+ ACE_OS::unique_name ((const void *) &rw->lock_,
+ name1,
+ ACE_UNIQUE_NAME_LEN);
+ ACE_OS::unique_name ((const void *) &rw->waiting_readers_,
+ name2,
+ ACE_UNIQUE_NAME_LEN);
+ ACE_OS::unique_name ((const void *) &rw->waiting_writers_,
+ name3,
+ ACE_UNIQUE_NAME_LEN);
+ ACE_OS::unique_name ((const void *) &rw->waiting_important_writer_,
+ name4,
+ ACE_UNIQUE_NAME_LEN);
+
+ ACE_condattr_t attributes;
+ if (ACE_OS::condattr_init (attributes, type) == 0)
+ {
+ if (ACE_OS::mutex_init (&rw->lock_, type, name1,
+ (ACE_mutexattr_t *) arg) == 0
+ && ACE_OS::cond_init (&rw->waiting_readers_,
+ attributes, name2, arg) == 0
+ && ACE_OS::cond_init (&rw->waiting_writers_,
+ attributes, name3, arg) == 0
+ && ACE_OS::cond_init (&rw->waiting_important_writer_,
+ attributes, name4, arg) == 0)
+ {
+ // Success!
+ rw->ref_count_ = 0;
+ rw->num_waiting_writers_ = 0;
+ rw->num_waiting_readers_ = 0;
+ rw->important_writer_ = 0;
+ result = 0;
+ }
+ ACE_OS::condattr_destroy (attributes);
+ }
+
+ if (result == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_OS::mutex_destroy (&rw->lock_);
+ ACE_OS::cond_destroy (&rw->waiting_readers_);
+ ACE_OS::cond_destroy (&rw->waiting_writers_);
+ ACE_OS::cond_destroy (&rw->waiting_important_writer_);
+ }
+ return result;
+# else
+ ACE_UNUSED_ARG (rw);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+#endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */
+
+int
+ACE_OS::sched_params (const ACE_Sched_Params &sched_params,
+ ACE_id_t id)
+{
+ ACE_OS_TRACE ("ACE_OS::sched_params");
+#if defined (ACE_HAS_STHREADS)
+ return ACE_OS::set_scheduling_params (sched_params, id);
+#elif defined (ACE_HAS_PTHREADS) && \
+ (!defined (ACE_LACKS_SETSCHED) || defined (ACE_TANDEM_T1248_PTHREADS) || \
+ defined (ACE_HAS_PTHREAD_SCHEDPARAM))
+ if (sched_params.quantum () != ACE_Time_Value::zero)
+ {
+ // quantums not supported
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for
+ // providing this code for 1003.1c PThreads. Please note that this
+ // has only been tested for POSIX 1003.1c threads, and may cause
+ // problems with other PThreads flavors!
+
+ struct sched_param param;
+ param.sched_priority = sched_params.priority ();
+
+ if (sched_params.scope () == ACE_SCOPE_PROCESS)
+ {
+# if defined(ACE_TANDEM_T1248_PTHREADS) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
+ ACE_UNUSED_ARG (id);
+ ACE_NOTSUP_RETURN (-1);
+# else /* ! ACE_TANDEM_T1248_PTHREADS */
+ int result = ::sched_setscheduler (id == ACE_SELF ? 0 : id,
+ sched_params.policy (),
+ &param) == -1 ? -1 : 0;
+# if defined (DIGITAL_UNIX)
+ return result == 0
+ ? // Use priocntl (2) to set the process in the RT class,
+ // if using an RT policy.
+ ACE_OS::set_scheduling_params (sched_params)
+ : result;
+# else /* ! DIGITAL_UNIX */
+ return result;
+# endif /* ! DIGITAL_UNIX */
+# endif /* ! ACE_TANDEM_T1248_PTHREADS */
+ }
+ else if (sched_params.scope () == ACE_SCOPE_THREAD)
+ {
+ ACE_thread_t thr_id = ACE_OS::thr_self ();
+
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id,
+ sched_params.policy (),
+ &param),
+ result),
+ int, -1);
+ }
+# if defined (sun)
+ // We need to be able to set LWP priorities on Suns, even without
+ // ACE_HAS_STHREADS, to obtain preemption.
+ else if (sched_params.scope () == ACE_SCOPE_LWP)
+ return ACE_OS::set_scheduling_params (sched_params, id);
+# endif /* sun */
+ else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+#elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+
+ // PharLap ETS can act on the current thread - it can set the
+ // quantum also, unlike Win32. All this only works on the RT
+ // version.
+# if defined (ACE_HAS_PHARLAP_RT)
+ if (id != ACE_SELF)
+ ACE_NOTSUP_RETURN (-1);
+
+# if !defined (ACE_PHARLAP_LABVIEW_RT)
+ if (sched_params.quantum() != ACE_Time_Value::zero)
+ EtsSetTimeSlice (sched_params.quantum().msec());
+# endif
+
+# else
+
+ if (sched_params.quantum () != ACE_Time_Value::zero)
+ {
+ // I don't know of a way to set the quantum on Win32.
+ errno = EINVAL;
+ return -1;
+ }
+
+# endif /* ACE_HAS_PHARLAP_RT */
+
+ if (sched_params.scope () == ACE_SCOPE_THREAD)
+ {
+
+ // Setting the REALTIME_PRIORITY_CLASS on Windows is almost always
+ // a VERY BAD THING. This include guard will allow people
+ // to easily disable this feature in ACE.
+ // It won't work at all for Pharlap since there's no SetPriorityClass.
+#if !defined (ACE_HAS_PHARLAP) && \
+ !defined (ACE_DISABLE_WIN32_INCREASE_PRIORITY)
+ // Set the priority class of this process to the REALTIME process class
+ // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL.
+ if (!::SetPriorityClass (::GetCurrentProcess (),
+ (sched_params.policy () == ACE_SCHED_FIFO ||
+ sched_params.policy () == ACE_SCHED_RR)
+ ? REALTIME_PRIORITY_CLASS
+ : NORMAL_PRIORITY_CLASS))
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+#endif /* ACE_DISABLE_WIN32_INCREASE_PRIORITY */
+
+ // Now that we have set the priority class of the process, set the
+ // priority of the current thread to the desired value.
+ return ACE_OS::thr_setprio (sched_params.priority ());
+ }
+ else if (sched_params.scope () == ACE_SCOPE_PROCESS)
+ {
+
+# if defined (ACE_HAS_PHARLAP_RT)
+ ACE_NOTSUP_RETURN (-1);
+# else
+ HANDLE hProcess
+ = ::OpenProcess (PROCESS_SET_INFORMATION,
+ FALSE,
+ id == ACE_SELF ? ::GetCurrentProcessId() : id);
+ if (!hProcess)
+ {
+ ACE_OS::set_errno_to_last_error();
+ return -1;
+ }
+ // There is no way for us to set the priority of the thread when we
+ // are setting the priority of a different process. So just ignore
+ // the priority argument when ACE_SCOPE_PROCESS is specified.
+ // Setting the priority class will automatically increase the base
+ // priority of all the threads within a process while maintaining the
+ // relative priorities of the threads within it.
+ if (!::SetPriorityClass (hProcess,
+ (sched_params.policy () == ACE_SCHED_FIFO ||
+ sched_params.policy () == ACE_SCHED_RR)
+ ? REALTIME_PRIORITY_CLASS
+ : NORMAL_PRIORITY_CLASS))
+ {
+ ACE_OS::set_errno_to_last_error ();
+ ::CloseHandle (hProcess);
+ return -1;
+ }
+ ::CloseHandle (hProcess);
+ return 0;
+#endif /* ACE_HAS_PHARLAP_RT */
+
+ }
+ else
+ {
+ errno = EINVAL;
+ return -1;
+ }
+#elif defined (ACE_VXWORKS)
+ ACE_UNUSED_ARG (id);
+
+ // There is only one class of priorities on VxWorks, and no time
+ // quanta. So, just set the current thread's priority.
+
+ if (sched_params.policy () != ACE_SCHED_FIFO
+ || sched_params.scope () != ACE_SCOPE_PROCESS
+ || sched_params.quantum () != ACE_Time_Value::zero)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Set the thread priority on the current thread.
+ return ACE_OS::thr_setprio (sched_params.priority ());
+#else
+ ACE_UNUSED_ARG (sched_params);
+ ACE_UNUSED_ARG (id);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STHREADS */
+}
+
+int
+ACE_OS::scheduling_class (const char *class_name, ACE_id_t &id)
+{
+#if defined (ACE_HAS_PRIOCNTL)
+ // Get the priority class ID.
+ pcinfo_t pcinfo;
+ // The following is just to avoid Purify warnings about unitialized
+ // memory reads.
+ ACE_OS::memset (&pcinfo, 0, sizeof pcinfo);
+
+ ACE_OS::strcpy (pcinfo.pc_clname, class_name);
+ if (ACE_OS::priority_control (P_ALL /* ignored */,
+ P_MYID /* ignored */,
+ PC_GETCID,
+ (char *) &pcinfo) == -1)
+ {
+ return -1;
+ }
+ else
+ {
+ id = pcinfo.pc_cid;
+ return 0;
+ }
+#else /* ! ACE_HAS_PRIOCNTL */
+ ACE_UNUSED_ARG (class_name);
+ ACE_UNUSED_ARG (id);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ! ACE_HAS_PRIOCNTL */
+}
+
+int
+ACE_OS::set_scheduling_params (const ACE_Sched_Params &sched_params,
+ ACE_id_t id)
+{
+#if defined (ACE_HAS_PRIOCNTL)
+ // Set priority class, priority, and quantum of this LWP or process as
+ // specified in sched_params.
+
+ // Get the priority class ID.
+ ACE_id_t class_id;
+ if (ACE_OS::scheduling_class (sched_params.policy() == ACE_SCHED_OTHER ?
+ "TS" :
+ "RT", class_id) == -1)
+ {
+ return -1;
+ }
+
+ pcparms_t pcparms;
+ // The following is just to avoid Purify warnings about unitialized
+ // memory reads.
+ ACE_OS::memset (&pcparms, 0, sizeof pcparms);
+
+ pcparms.pc_cid = class_id;
+
+ if (sched_params.policy () == ACE_SCHED_OTHER &&
+ sched_params.quantum () == ACE_Time_Value::zero)
+ // SunOS doesn't support non-zero quantums in time-sharing class: use
+ // real-time class instead.
+ {
+ tsparms_t tsparms;
+ // The following is just to avoid Purify warnings about unitialized
+ // memory reads.
+ ACE_OS::memset (&tsparms, 0, sizeof tsparms);
+
+ // Don't change ts_uprilim (user priority limit)
+ tsparms.ts_uprilim = TS_NOCHANGE;
+ tsparms.ts_upri = sched_params.priority ();
+
+ // Package up the TS class ID and parameters for the
+ // priority_control () call.
+ ACE_OS::memcpy (pcparms.pc_clparms, &tsparms, sizeof tsparms);
+ }
+ else if (sched_params.policy () == ACE_SCHED_FIFO ||
+ (sched_params.policy () == ACE_SCHED_RR &&
+ sched_params.quantum () != ACE_Time_Value::zero))
+ // must have non-zero quantum for RR, to make it meaningful
+ // A zero quantum with FIFO has special significance: it actually
+ // means infinite time quantum, i.e., run-to-completion.
+ {
+ rtparms_t rtparms;
+ // The following is just to avoid Purify warnings about unitialized
+ // memory reads.
+ ACE_OS::memset (&rtparms, 0, sizeof rtparms);
+
+ rtparms.rt_pri = sched_params.priority ();
+
+ if (sched_params.quantum () == ACE_Time_Value::zero)
+ {
+ // rtparms.rt_tqsecs is ignored with RT_TQINF
+ rtparms.rt_tqnsecs = RT_TQINF;
+ }
+ else
+ {
+ rtparms.rt_tqsecs = (ulong) sched_params.quantum ().sec ();
+ rtparms.rt_tqnsecs = sched_params.quantum ().usec () * 1000;
+ }
+
+ // Package up the RT class ID and parameters for the
+ // priority_control () call.
+ ACE_OS::memcpy (pcparms.pc_clparms, &rtparms, sizeof rtparms);
+ }
+ else
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (ACE_OS::priority_control ((idtype_t) (sched_params.scope () == ACE_SCOPE_THREAD
+ ? ACE_SCOPE_PROCESS
+ : sched_params.scope ()),
+ id,
+ PC_SETPARMS,
+ (char *) &pcparms) < 0)
+ {
+ return ACE_OS::last_error ();
+ }
+
+ return 0;
+#else /* ! ACE_HAS_PRIOCNTL */
+ ACE_UNUSED_ARG (sched_params);
+ ACE_UNUSED_ARG (id);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ! ACE_HAS_PRIOCNTL */
+}
+
+int
+ACE_OS::thr_create (ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ ACE_thread_t *thr_id,
+ ACE_hthread_t *thr_handle,
+ long priority,
+ void *stack,
+ size_t stacksize,
+ ACE_Base_Thread_Adapter *thread_adapter,
+ const char** thr_name)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_create");
+
+ if (ACE_BIT_DISABLED (flags, THR_DETACHED) &&
+ ACE_BIT_DISABLED (flags, THR_JOINABLE))
+ ACE_SET_BITS (flags, THR_JOINABLE);
+
+#if defined (ACE_NO_THREAD_ADAPTER)
+# define ACE_THREAD_FUNCTION func
+# define ACE_THREAD_ARGUMENT args
+#else /* ! defined (ACE_NO_THREAD_ADAPTER) */
+# define ACE_THREAD_FUNCTION thread_args->entry_point ()
+# define ACE_THREAD_ARGUMENT thread_args
+#endif /* ! defined (ACE_NO_THREAD_ADAPTER) */
+
+ ACE_Base_Thread_Adapter *thread_args = 0;
+ if (thread_adapter == 0)
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_NEW_RETURN (thread_args,
+ ACE_OS_Thread_Adapter (func, args,
+ (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
+ ACE_OS_Object_Manager::seh_except_selector(),
+ ACE_OS_Object_Manager::seh_except_handler()),
+ -1);
+#else
+ ACE_NEW_RETURN (thread_args,
+ ACE_OS_Thread_Adapter (func, args,
+ (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME),
+ -1);
+
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ else
+ thread_args = thread_adapter;
+
+ auto_ptr <ACE_Base_Thread_Adapter> auto_thread_args;
+
+ if (thread_adapter == 0)
+ ACE_AUTO_PTR_RESET (auto_thread_args,
+ thread_args,
+ ACE_Base_Thread_Adapter);
+
+#if defined (ACE_HAS_THREADS)
+
+ // *** Set Stack Size
+# if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
+ if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE)
+ stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE;
+# endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
+
+ ACE_thread_t tmp_thr;
+ if (thr_id == 0)
+ thr_id = &tmp_thr;
+
+ ACE_hthread_t tmp_handle;
+ if (thr_handle == 0)
+ thr_handle = &tmp_handle;
+
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+# if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
+ /* Tests show that VxWorks 6.x pthread lib does not only
+ * require zeroing of mutex/condition objects to function correctly
+ * but also of the attribute objects.
+ */
+ pthread_attr_t attr = {0};
+# else
+ pthread_attr_t attr;
+# endif
+ if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr), result) != 0)
+ return -1;
+
+ if (stacksize != 0)
+ {
+ size_t size = stacksize;
+
+# if defined (PTHREAD_STACK_MIN)
+ if (size < static_cast <size_t> (PTHREAD_STACK_MIN))
+ size = PTHREAD_STACK_MIN;
+# endif /* PTHREAD_STACK_MIN */
+
+# if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE)
+# if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
+ int result;
+ if (stack != 0)
+ result = ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr, stack, size), result);
+ else
+ result = ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result);
+ if (result == -1)
+# else
+ if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result) == -1)
+# endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACK */
+ {
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+# else
+ ACE_UNUSED_ARG (size);
+# endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE */
+ }
+
+ // *** Set Stack Address
+# if defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
+# if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR)
+ if (stack != 0)
+ {
+ if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr, stack), result) != 0)
+ {
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+ }
+# else
+ ACE_UNUSED_ARG (stack);
+# endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR */
+# endif /* ACE_LACKS_PTHREAD_ATTR_SETSTACK */
+
+ // *** Deal with various attributes
+ if (flags != 0)
+ {
+ // *** Set Detach state
+# if !defined (ACE_LACKS_SETDETACH)
+ if (ACE_BIT_ENABLED (flags, THR_DETACHED)
+ || ACE_BIT_ENABLED (flags, THR_JOINABLE))
+ {
+ int dstate = PTHREAD_CREATE_JOINABLE;
+
+ if (ACE_BIT_ENABLED (flags, THR_DETACHED))
+ dstate = PTHREAD_CREATE_DETACHED;
+
+ if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate),
+ result) != 0)
+ {
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+ }
+
+ // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
+ // call ::pthread_detach () below. If THR_DETACHED is not
+ // enabled, we call ::pthread_detach () in the Thread_Manager,
+ // after joining with the thread.
+# endif /* ACE_LACKS_SETDETACH */
+
+ // *** Set Policy
+# if !defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
+ // If we wish to set the priority explicitly, we have to enable
+ // explicit scheduling, and a policy, too.
+ if (priority != ACE_DEFAULT_THREAD_PRIORITY)
+ {
+ ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
+ if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO)
+ && ACE_BIT_DISABLED (flags, THR_SCHED_RR)
+ && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT))
+ ACE_SET_BITS (flags, THR_SCHED_DEFAULT);
+ }
+
+ if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
+ || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
+ || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
+ {
+ int spolicy;
+
+# if defined (ACE_HAS_ONLY_SCHED_OTHER)
+ // SunOS, thru version 5.6, only supports SCHED_OTHER.
+ spolicy = SCHED_OTHER;
+# elif defined (ACE_HAS_ONLY_SCHED_FIFO)
+ // NonStop OSS standard pthread supports only SCHED_FIFO.
+ spolicy = SCHED_FIFO;
+# else
+ // Make sure to enable explicit scheduling, in case we didn't
+ // enable it above (for non-default priority).
+ ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
+
+ if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
+ spolicy = SCHED_OTHER;
+ else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
+ spolicy = SCHED_FIFO;
+# if defined (SCHED_IO)
+ else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
+ spolicy = SCHED_IO;
+# else
+ else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+# endif /* SCHED_IO */
+ else
+ spolicy = SCHED_RR;
+
+# endif /* ACE_HAS_ONLY_SCHED_OTHER */
+
+ (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy),
+ result);
+ if (result != 0)
+ {
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+ }
+
+ // *** Set Priority (use reasonable default priorities)
+# if defined(ACE_HAS_PTHREADS)
+ // If we wish to explicitly set a scheduling policy, we also
+ // have to specify a priority. We choose a "middle" priority as
+ // default. Maybe this is also necessary on other POSIX'ish
+ // implementations?
+ if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
+ || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
+ || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
+ && priority == ACE_DEFAULT_THREAD_PRIORITY)
+ {
+ if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
+ priority = ACE_THR_PRI_FIFO_DEF;
+ else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR))
+ priority = ACE_THR_PRI_RR_DEF;
+ else // THR_SCHED_DEFAULT
+ priority = ACE_THR_PRI_OTHER_DEF;
+ }
+# endif /* ACE_HAS_PTHREADS */
+ if (priority != ACE_DEFAULT_THREAD_PRIORITY)
+ {
+ struct sched_param sparam;
+ ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
+
+# if defined (ACE_HAS_IRIX62_THREADS)
+ sparam.sched_priority = ACE_MIN (priority,
+ (long) PTHREAD_MAX_PRIORITY);
+# elif defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS)
+ /* For MIT pthreads... */
+ sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY);
+# elif defined(ACE_HAS_PTHREADS) && !defined (ACE_HAS_STHREADS)
+ // The following code forces priority into range.
+ if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
+ sparam.sched_priority =
+ ACE_MIN (ACE_THR_PRI_FIFO_MAX,
+ ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority));
+ else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR))
+ sparam.sched_priority =
+ ACE_MIN (ACE_THR_PRI_RR_MAX,
+ ACE_MAX (ACE_THR_PRI_RR_MIN, priority));
+ else // Default policy, whether set or not
+ sparam.sched_priority =
+ ACE_MIN (ACE_THR_PRI_OTHER_MAX,
+ ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority));
+# elif defined (PRIORITY_MAX)
+ sparam.sched_priority = ACE_MIN (priority,
+ (long) PRIORITY_MAX);
+# else
+ sparam.sched_priority = priority;
+# endif /* ACE_HAS_IRIX62_THREADS */
+
+ {
+# if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
+ // SunOS, through 5.6, POSIX only allows priorities > 0 to
+ // ::pthread_attr_setschedparam. If a priority of 0 was
+ // requested, set the thread priority after creating it, below.
+ if (priority > 0)
+# endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
+ {
+ (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam),
+ result);
+ if (result != 0)
+ {
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+ }
+ }
+ }
+
+ // *** Set scheduling explicit or inherited
+ if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)
+ || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED))
+ {
+ int sched = PTHREAD_EXPLICIT_SCHED;
+ if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED))
+ sched = PTHREAD_INHERIT_SCHED;
+ if (ACE_ADAPT_RETVAL(::pthread_attr_setinheritsched (&attr, sched), result) != 0)
+ {
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+ }
+# else /* ACE_LACKS_SETSCHED */
+ ACE_UNUSED_ARG (priority);
+# endif /* ACE_LACKS_SETSCHED */
+
+ // *** Set pthread name
+# if defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
+ if (thr_name && *thr_name)
+ {
+ if (ACE_ADAPT_RETVAL(::pthread_attr_setname (&attr, const_cast<char*>(*thr_name)), result) != 0)
+ {
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+ }
+#else
+ ACE_UNUSED_ARG (thr_name);
+# endif
+
+ // *** Set Scope
+# if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
+ if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)
+ || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS))
+ {
+# if defined (ACE_CONFIG_LINUX_H) || defined (HPUX) || defined (ACE_VXWORKS)
+ // LinuxThreads do not have support for PTHREAD_SCOPE_PROCESS.
+ // Neither does HPUX (up to HP-UX 11.00, as far as I know).
+ // Also VxWorks only delivers scope system
+ int scope = PTHREAD_SCOPE_SYSTEM;
+# else /* ACE_CONFIG_LINUX_H */
+ int scope = PTHREAD_SCOPE_PROCESS;
+# endif /* ACE_CONFIG_LINUX_H */
+ if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM))
+ scope = PTHREAD_SCOPE_SYSTEM;
+
+ if (ACE_ADAPT_RETVAL(::pthread_attr_setscope (&attr, scope), result) != 0)
+ {
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+ }
+# endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
+
+# ifdef ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP
+ if (ACE_BIT_ENABLED (flags, THR_SUSPENDED))
+ {
+ if (ACE_ADAPT_RETVAL(::pthread_attr_setcreatesuspend_np(&attr), result) != 0)
+ {
+
+ ::pthread_attr_destroy (&attr);
+ return -1;
+ }
+ }
+# endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */
+
+# if ! defined(ACE_LACKS_THR_CONCURRENCY_FUNCS)
+ if (ACE_BIT_ENABLED (flags, THR_NEW_LWP))
+ {
+ // Increment the number of LWPs by one to emulate the
+ // SunOS semantics.
+ int lwps = ACE_OS::thr_getconcurrency ();
+ if (lwps == -1)
+ {
+ if (errno == ENOTSUP)
+ // Suppress the ENOTSUP because it's harmless.
+ errno = 0;
+ else
+ // This should never happen on SunOS:
+ // ::thr_getconcurrency () should always succeed.
+ return -1;
+ }
+ else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1)
+ {
+ if (errno == ENOTSUP)
+ {
+ // Unlikely: ::thr_getconcurrency () is supported
+ // but ::thr_setconcurrency () is not?
+ }
+ else
+ return -1;
+ }
+ }
+# endif /* ! ACE_LACKS_THR_CONCURRENCY_FUNCS */
+ }
+
+ ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id,
+ &attr,
+ thread_args->entry_point (),
+ thread_args),
+ result),
+ int, -1, result);
+ ::pthread_attr_destroy (&attr);
+
+ // This is a SunOS or POSIX implementation of pthreads, where we
+ // assume that ACE_thread_t and ACE_hthread_t are the same. If this
+ // *isn't* correct on some platform, please let us know.
+ if (result != -1)
+ *thr_handle = *thr_id;
+
+# if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
+ // SunOS prior to 5.7:
+
+ // If the priority is 0, then we might have to set it now because we
+ // couldn't set it with ::pthread_attr_setschedparam, as noted
+ // above. This doesn't provide strictly correct behavior, because
+ // the thread was created (above) with the priority of its parent.
+ // (That applies regardless of the inherit_sched attribute: if it
+ // was PTHREAD_INHERIT_SCHED, then it certainly inherited its
+ // parent's priority. If it was PTHREAD_EXPLICIT_SCHED, then "attr"
+ // was initialized by the SunOS ::pthread_attr_init () to contain
+ // NULL for the priority, which indicated to SunOS ::pthread_create
+ // () to inherit the parent priority.)
+ if (priority == 0)
+ {
+ // Check the priority of this thread, which is the parent
+ // of the newly created thread. If it is 0, then the
+ // newly created thread will have inherited the priority
+ // of 0, so there's no need to explicitly set it.
+ struct sched_param sparam;
+ int policy = 0;
+ ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (),
+ &policy,
+ &sparam),
+ result), int,
+ -1, result);
+
+ // The only policy supported by by SunOS, thru version 5.6,
+ // is SCHED_OTHER, so that's hard-coded here.
+ policy = ACE_SCHED_OTHER;
+
+ if (sparam.sched_priority != 0)
+ {
+ ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
+ // The memset to 0 sets the priority to 0, so we don't need
+ // to explicitly set sparam.sched_priority.
+
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (*thr_id,
+ policy,
+ &sparam),
+ result),
+ int, -1);
+ }
+ }
+
+# if defined (ACE_NEEDS_LWP_PRIO_SET)
+# if 0
+ // It would be useful if we could make this work. But, it requires
+ // a mechanism for determining the ID of an LWP to which another
+ // thread is bound. Is there a way to do that? Instead, just rely
+ // on the code in ACE_Thread_Adapter::invoke () to set the LWP
+ // priority.
+
+ // If the thread is bound, then set the priority on its LWP.
+ if (ACE_BIT_ENABLED (flags, THR_BOUND))
+ {
+ ACE_Sched_Params sched_params (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) ||
+ ACE_BIT_ENABLED (flags, THR_SCHED_RR) ?
+ ACE_SCHED_FIFO :
+ ACE_SCHED_OTHER,
+ priority);
+ result = ACE_OS::lwp_setparams (sched_params,
+ /* ? How do we find the ID of the LWP
+ to which *thr_id is bound? */);
+ }
+# endif /* 0 */
+# endif /* ACE_NEEDS_LWP_PRIO_SET */
+
+# endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
+ auto_thread_args.release ();
+ return result;
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
+
+ if (priority != ACE_DEFAULT_THREAD_PRIORITY)
+ // If we need to set the priority, then we need to start the
+ // thread in a suspended mode.
+ ACE_SET_BITS (flags, THR_SUSPENDED);
+
+ ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize,
+ thread_args->entry_point (),
+ thread_args,
+ flags, thr_id), result),
+ int, -1, result);
+
+ if (result != -1)
+ {
+ // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same.
+ *thr_handle = *thr_id;
+
+ if (priority != ACE_DEFAULT_THREAD_PRIORITY)
+ {
+ // Set the priority of the new thread and then let it
+ // continue, but only if the user didn't start it suspended
+ // in the first place!
+ result = ACE_OS::thr_setprio (*thr_id, priority);
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ if (start_suspended == 0)
+ {
+ result = ACE_OS::thr_continue (*thr_id);
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+ }
+ }
+ }
+ auto_thread_args.release ();
+ return result;
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (thr_name);
+ ACE_UNUSED_ARG (stack);
+# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+ if (ACE_BIT_ENABLED (flags, THR_USE_AFX))
+ {
+ CWinThread *cwin_thread =
+ ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (),
+ thread_args,
+ priority,
+ 0,
+ flags | THR_SUSPENDED);
+ // Have to duplicate the handle because
+ // CWinThread::~CWinThread() closes the original handle.
+# if !defined (ACE_HAS_WINCE)
+ (void) ::DuplicateHandle (::GetCurrentProcess (),
+ cwin_thread->m_hThread,
+ ::GetCurrentProcess (),
+ thr_handle,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS);
+# endif /* ! ACE_HAS_WINCE */
+ *thr_id = cwin_thread->m_nThreadID;
+
+ if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0)
+ cwin_thread->ResumeThread ();
+ // cwin_thread will be deleted in AfxThreadExit()
+ // Warning: If AfxThreadExit() is called from within the
+ // thread, ACE_TSS_Cleanup->thread_exit() never gets called !
+ }
+ else
+# endif /* ACE_HAS_MFC */
+ {
+ int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
+
+ if (priority != ACE_DEFAULT_THREAD_PRIORITY)
+ // If we need to set the priority, then we need to start the
+ // thread in a suspended mode.
+ ACE_SET_BITS (flags, THR_SUSPENDED);
+
+ *thr_handle = (void *) ACE_BEGINTHREADEX (0,
+ static_cast <u_int> (stacksize),
+ thread_args->entry_point (),
+ thread_args,
+ flags,
+ thr_id);
+
+ if (priority != ACE_DEFAULT_THREAD_PRIORITY && *thr_handle != 0)
+ {
+ // Set the priority of the new thread and then let it
+ // continue, but only if the user didn't start it suspended
+ // in the first place!
+ ACE_OS::thr_setprio (*thr_handle, priority);
+
+ if (start_suspended == 0)
+ ACE_OS::thr_continue (*thr_handle);
+ }
+ }
+# if 0
+ *thr_handle = ::CreateThread
+ (0,
+ stacksize,
+ LPTHREAD_START_ROUTINE (thread_args->entry_point ()),
+ thread_args,
+ flags,
+ thr_id);
+# endif /* 0 */
+
+ // Close down the handle if no one wants to use it.
+ if (thr_handle == &tmp_handle && tmp_handle != 0)
+ ::CloseHandle (tmp_handle);
+
+ if (*thr_handle != 0)
+ {
+ auto_thread_args.release ();
+ return 0;
+ }
+ else
+ ACE_FAIL_RETURN (-1);
+ /* NOTREACHED */
+
+# elif defined (ACE_VXWORKS)
+ // The hard-coded values below are what ::sp () would use. (::sp ()
+ // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
+ // 20,000.) stacksize should be an even integer. If a stack is not
+ // specified, ::taskSpawn () is used so that we can set the
+ // priority, flags, and stacksize. If a stack is specified,
+ // ::taskInit ()/::taskActivate() are used.
+
+ // If called with thr_create() defaults, use same default values as ::sp ():
+ if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100;
+ // Assumes that there is a floating point coprocessor. As noted
+ // above, ::sp () hardcodes this, so we should be safe with it.
+ if (flags == 0) flags = VX_FP_TASK;
+ if (stacksize == 0) stacksize = 20000;
+
+ ACE_thread_t tid;
+# if 0 /* Don't support setting of stack, because it doesn't seem to work. */
+ if (stack == 0)
+ {
+# else
+ ACE_UNUSED_ARG (stack);
+# endif /* 0 */
+ // The call below to ::taskSpawn () causes VxWorks to assign a
+ // unique task name of the form: "t" + an integer, because the
+ // first argument is 0.
+ tid = ::taskSpawn (thr_name && *thr_name ? const_cast <char*> (*thr_name) : 0,
+ priority,
+ (int) flags,
+ (int) stacksize,
+ thread_args->entry_point (),
+ (int) thread_args,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+# if 0 /* Don't support setting of stack, because it doesn't seem to work. */
+ }
+ else
+ {
+ // If a task name (thr_id) was not supplied, then the task will
+ // not have a unique name. That's VxWorks' behavior.
+
+ // Carve out a TCB at the beginning of the stack space. The TCB
+ // occupies 400 bytes with VxWorks 5.3.1/I386.
+ WIND_TCB *tcb = (WIND_TCB *) stack;
+
+ // The TID is defined to be the address of the TCB.
+ int status = ::taskInit (tcb,
+ thr_name && *thr_name ? const_cast <char*>(*thr_name) : 0,
+ priority,
+ (int) flags,
+ (char *) stack + sizeof (WIND_TCB),
+ (int) (stacksize - sizeof (WIND_TCB)),
+ thread_args->entry_point (),
+ (int) thread_args,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ if (status == OK)
+ {
+ // The task was successfully initialized, now activate it.
+ status = ::taskActivate ((ACE_hthread_t) tcb);
+ }
+
+ tid = status == OK ? (ACE_thread_t) tcb : ERROR;
+ }
+# endif /* 0 */
+
+ if (tid == ERROR)
+ return -1;
+ else
+ {
+ if (thr_id)
+ *thr_id = tid;
+
+ if (thr_handle)
+ *thr_handle = tid;
+
+ if (thr_name && !(*thr_name))
+ *thr_name = ::taskName (tid);
+
+ auto_thread_args.release ();
+ return 0;
+ }
+
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (func);
+ ACE_UNUSED_ARG (args);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (thr_id);
+ ACE_UNUSED_ARG (thr_handle);
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (stack);
+ ACE_UNUSED_ARG (stacksize);
+ ACE_UNUSED_ARG (thr_name);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+void
+ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_exit");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ ::pthread_exit (status);
+# elif defined (ACE_HAS_STHREADS)
+ ::thr_exit (status);
+# elif defined (ACE_HAS_WTHREADS)
+ // Can't call it here because on NT, the thread is exited
+ // directly by ACE_Thread_Adapter::invoke ().
+ // ACE_TSS_Cleanup::instance ()->thread_exit (status);
+
+# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+ int using_afx = -1;
+ // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
+ // But without #including ace/Thread_Manager.h, we don't know that.
+ ACE_OS_Thread_Descriptor *td =
+ ACE_Base_Thread_Adapter::thr_desc_log_msg ();
+ if (td)
+ using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX);
+# endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
+
+ // Call TSS destructors.
+ ACE_OS::cleanup_tss (0 /* not main thread */);
+
+ // Exit the thread.
+ // Allow CWinThread-destructor to be invoked from AfxEndThread.
+ // _endthreadex will be called from AfxEndThread so don't exit the
+ // thread now if we are running an MFC thread.
+# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+ if (using_afx != -1)
+ {
+ if (using_afx)
+ ::AfxEndThread (status);
+ else
+ ACE_ENDTHREADEX (status);
+ }
+ else
+ {
+ // Not spawned by ACE_Thread_Manager, use the old buggy
+ // version. You should seriously consider using
+ // ACE_Thread_Manager to spawn threads. The following code is
+ // know to cause some problem.
+ CWinThread *pThread = ::AfxGetThread ();
+ if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
+ ACE_ENDTHREADEX (status);
+ else
+ ::AfxEndThread (status);
+ }
+# else
+ ACE_ENDTHREADEX (status);
+# endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
+
+# elif defined (ACE_HAS_VXTHREADS)
+ ACE_thread_t tid = ACE_OS::thr_self ();
+ *((int *) status) = ::taskDelete (tid);
+# endif /* ACE_HAS_PTHREADS */
+#else
+ ACE_UNUSED_ARG (status);
+#endif /* ACE_HAS_THREADS */
+}
+
+#if defined (ACE_HAS_VXTHREADS)
+// Leave this in the global scope to allow
+// users to adjust the delay value.
+int ACE_THR_JOIN_DELAY = 5;
+
+int
+ACE_OS::thr_join (ACE_hthread_t thr_handle,
+ ACE_THR_FUNC_RETURN *status)
+{
+ // We can't get the status of the thread
+ if (status != 0)
+ {
+ *status = 0;
+ }
+
+ // This method can not support joining all threads
+ if (ACE_OS::thr_cmp (thr_handle, ACE_OS::NULL_hthread))
+ {
+ ACE_NOTSUP_RETURN (-1);
+ }
+
+ int retval = ESRCH;
+ ACE_thread_t current = ACE_OS::thr_self ();
+
+ // Make sure we are not joining ourself
+ if (ACE_OS::thr_cmp (thr_handle, current))
+ {
+ retval = EDEADLK;
+ }
+ else
+ {
+ // Whether the task exists or not
+ // we will return a successful value
+ retval = 0;
+
+ // Verify that the task id still exists
+ while (taskIdVerify (thr_handle) == OK)
+ {
+ // Wait a bit to see if the task is still active.
+ ACE_OS::sleep (ACE_THR_JOIN_DELAY);
+ }
+ }
+
+ // Adapt the return value into errno and return value.
+ // The ACE_ADAPT_RETVAL macro doesn't exactly do what
+ // we need to do here, so we do it manually.
+ if (retval != 0)
+ {
+ errno = retval;
+ retval = -1;
+ }
+
+ return retval;
+}
+
+int
+ACE_OS::thr_join (ACE_thread_t waiter_id,
+ ACE_thread_t *thr_id,
+ ACE_THR_FUNC_RETURN *status)
+{
+ thr_id = 0;
+ return ACE_OS::thr_join (waiter_id, status);
+}
+#endif /* ACE_HAS_VXTHREADS */
+
+int
+ACE_OS::thr_key_detach (ACE_thread_key_t key, void *)
+{
+#if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_TSS_EMULATION)
+ TSS_Cleanup_Instance cleanup;
+ if (cleanup.valid ())
+ {
+ return cleanup->thread_detach_key (key);
+ }
+ else
+ {
+ return -1;
+ }
+#else
+ ACE_UNUSED_ARG (key);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_WTHREADS || ACE_HAS_TSS_EMULATION */
+}
+
+int
+ACE_OS::thr_get_affinity (ACE_hthread_t thr_id,
+ size_t cpu_set_size,
+ cpu_set_t * cpu_mask)
+{
+#if defined (ACE_HAS_PTHREAD_GETAFFINITY_NP)
+ // Handle of the thread, which is NPTL thread-id, normally a big number
+ if (::pthread_getaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
+ {
+ return -1;
+ }
+ return 0;
+#elif defined (ACE_HAS_2_PARAM_SCHED_GETAFFINITY)
+ // The process-id is expected as <thr_id>, which can be a thread-id of
+ // linux-thread, thus making binding to cpu of that particular thread only.
+ // If you are using this flag for NPTL-threads, however, please pass as a
+ // thr_id process id obtained by ACE_OS::getpid ()
+ ACE_UNUSED_ARG (cpu_set_size);
+ if (::sched_getaffinity(thr_id, cpu_mask) == -1)
+ {
+ return -1;
+ }
+ return 0;
+#elif defined (ACE_HAS_SCHED_GETAFFINITY)
+ // The process-id is expected as <thr_id>, which can be a thread-id of
+ // linux-thread, thus making binding to cpu of that particular thread only.
+ // If you are using this flag for NPTL-threads, however, please pass as a
+ // thr_id process id obtained by ACE_OS::getpid ()
+ if (::sched_getaffinity(thr_id, cpu_set_size, cpu_mask) == -1)
+ {
+ return -1;
+ }
+ return 0;
+#else
+ ACE_UNUSED_ARG (thr_id);
+ ACE_UNUSED_ARG (cpu_set_size);
+ ACE_UNUSED_ARG (cpu_mask);
+ ACE_NOTSUP_RETURN (-1);
+#endif
+}
+
+int
+ACE_OS::thr_set_affinity (ACE_hthread_t thr_id,
+ size_t cpu_set_size,
+ const cpu_set_t * cpu_mask)
+{
+#if defined (ACE_HAS_PTHREAD_SETAFFINITY_NP)
+ if (::pthread_setaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
+ {
+ return -1;
+ }
+ return 0;
+#elif defined (ACE_HAS_2_PARAM_SCHED_SETAFFINITY)
+ // The process-id is expected as <thr_id>, which can be a thread-id of
+ // linux-thread, thus making binding to cpu of that particular thread only.
+ // If you are using this flag for NPTL-threads, however, please pass as a
+ // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
+ //
+ ACE_UNUSED_ARG (cpu_set_size);
+ if (::sched_setaffinity (thr_id, cpu_mask) == -1)
+ {
+ return -1;
+ }
+ return 0;
+#elif defined (ACE_HAS_SCHED_SETAFFINITY)
+ // The process-id is expected as <thr_id>, which can be a thread-id of
+ // linux-thread, thus making binding to cpu of that particular thread only.
+ // If you are using this flag for NPTL-threads, however, please pass as a
+ // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
+ //
+ if (::sched_setaffinity (thr_id, cpu_set_size, cpu_mask) == -1)
+ {
+ return -1;
+ }
+ return 0;
+#else
+ ACE_UNUSED_ARG (thr_id);
+ ACE_UNUSED_ARG (cpu_set_size);
+ ACE_UNUSED_ARG (cpu_mask);
+ ACE_NOTSUP_RETURN (-1);
+#endif
+}
+
+int
+ACE_OS::thr_key_used (ACE_thread_key_t key)
+{
+#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
+ TSS_Cleanup_Instance cleanup;
+ if (cleanup.valid ())
+ {
+ cleanup->thread_use_key (key);
+ return 0;
+ }
+ return -1;
+#else
+ ACE_UNUSED_ARG (key);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
+}
+
+#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+int
+ACE_OS::thr_keycreate_native (ACE_OS_thread_key_t *key,
+# if defined (ACE_HAS_THR_C_DEST)
+ ACE_THR_C_DEST dest
+# else
+ ACE_THR_DEST dest
+# endif /* ACE_HAS_THR_C_DEST */
+ )
+{
+ // can't trace here. Trace uses TSS
+ // ACE_OS_TRACE ("ACE_OS::thr_keycreate_native");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (dest);
+ *key = ::TlsAlloc ();
+
+ if (*key == ACE_SYSCALL_FAILED)
+ ACE_FAIL_RETURN (-1);
+ return 0;
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (dest);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+int
+ACE_OS::thr_keycreate (ACE_thread_key_t *key,
+# if defined (ACE_HAS_THR_C_DEST)
+ ACE_THR_C_DEST dest,
+# else
+ ACE_THR_DEST dest,
+# endif /* ACE_HAS_THR_C_DEST */
+ void *)
+{
+ // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_TSS_EMULATION)
+ if (ACE_TSS_Emulation::next_key (*key) == 0)
+ {
+ ACE_TSS_Emulation::tss_destructor (*key, dest);
+
+ // Extract out the thread-specific table instance and stash away
+ // the key and destructor so that we can free it up later on...
+ TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
+ if (cleanup.valid ())
+ {
+ return cleanup->insert (*key, dest);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ return -1;
+# elif defined (ACE_HAS_WTHREADS)
+ if (ACE_OS::thr_keycreate_native (key, dest) == 0)
+ {
+ // Extract out the thread-specific table instance and stash away
+ // the key and destructor so that we can free it up later on...
+ TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
+ if (cleanup.valid ())
+ {
+ return cleanup->insert (*key, dest);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ return -1;
+ /* NOTREACHED */
+# elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ return ACE_OS::thr_keycreate_native (key, dest);
+# else
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (dest);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_TSS_EMULATION */
+# else /* ACE_HAS_THREADS */
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (dest);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+int
+ACE_OS::thr_keyfree_native (ACE_OS_thread_key_t key)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_keyfree_native");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_BROKEN_THREAD_KEYFREE) || defined (ACE_HAS_THR_KEYDELETE)
+ // For some systems, e.g. LynxOS, we need to ensure that
+ // any registered thread destructor action for this slot
+ // is now disabled. Otherwise in the event of a dynamic library
+ // unload of libACE, by a program not linked with libACE,
+ // ACE_TSS_cleanup will be invoked again at the thread exit
+ // after libACE has been actually been unmapped from memory.
+ (void) ACE_OS::thr_setspecific (key, 0);
+# endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
+# if defined (ACE_HAS_PTHREADS)
+ return ::pthread_key_delete (key);
+# elif defined (ACE_HAS_THR_KEYDELETE)
+ return ::thr_keydelete (key);
+# elif defined (ACE_HAS_STHREADS)
+ ACE_UNUSED_ARG (key);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1);
+# else
+ ACE_UNUSED_ARG (key);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PTHREADS */
+# else
+ ACE_UNUSED_ARG (key);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+int
+ACE_OS::thr_keyfree (ACE_thread_key_t key)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_keyfree");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_TSS_EMULATION)
+ // Release the key in the TSS_Emulation administration
+ ACE_TSS_Emulation::release_key (key);
+ TSS_Cleanup_Instance cleanup;
+ if (cleanup.valid ())
+ {
+ return cleanup->free_key (key);
+ }
+ return -1;
+# elif defined (ACE_HAS_WTHREADS)
+ // Extract out the thread-specific table instance and free up
+ // the key and destructor.
+ TSS_Cleanup_Instance cleanup;
+ if (cleanup.valid ())
+ {
+ return cleanup->free_key (key);
+ }
+ return -1;
+# elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ return ACE_OS::thr_keyfree_native (key);
+# else
+ ACE_UNUSED_ARG (key);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_TSS_EMULATION */
+# else /* ACE_HAS_THREADS */
+ ACE_UNUSED_ARG (key);
+ ACE_NOTSUP_RETURN (-1);
+ return 0;
+# endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_OS::thr_setprio (const ACE_Sched_Priority prio)
+{
+ // Set the thread priority on the current thread.
+ ACE_hthread_t my_thread_id;
+ ACE_OS::thr_self (my_thread_id);
+
+ int const status = ACE_OS::thr_setprio (my_thread_id, prio);
+
+#if defined (ACE_NEEDS_LWP_PRIO_SET)
+ // If the thread is in the RT class, then set the priority on its
+ // LWP. (Instead of doing this if the thread is in the RT class, it
+ // should be done for all bound threads. But, there doesn't appear
+ // to be an easy way to determine if the thread is bound.)
+
+ if (status == 0)
+ {
+ // Find what scheduling class the thread's LWP is in.
+ ACE_Sched_Params sched_params (ACE_SCHED_OTHER, 0);
+ if (ACE_OS::lwp_getparams (sched_params) == -1)
+ {
+ return -1;
+ }
+ else if (sched_params.policy () == ACE_SCHED_FIFO ||
+ sched_params.policy () == ACE_SCHED_RR)
+ {
+ // This thread's LWP is in the RT class, so we need to set
+ // its priority.
+ sched_params.priority (prio);
+ return ACE_OS::lwp_setparams (sched_params);
+ }
+ // else this is not an RT thread. Nothing more needs to be
+ // done.
+ }
+#endif /* ACE_NEEDS_LWP_PRIO_SET */
+
+ return status;
+}
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+int
+ACE_OS::thr_setspecific_native (ACE_OS_thread_key_t key, void *data)
+{
+ // ACE_OS_TRACE ("ACE_OS::thr_setspecific_native");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key, data),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), result), int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ ::TlsSetValue (key, data);
+ return 0;
+# else /* ACE_HAS_STHREADS */
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (data);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (data);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+int
+ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data)
+{
+ // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_TSS_EMULATION)
+ if (ACE_TSS_Emulation::is_key (key) == 0)
+ {
+ errno = EINVAL;
+ data = 0;
+ return -1;
+ }
+ else
+ {
+ ACE_TSS_Emulation::ts_object (key) = data;
+ TSS_Cleanup_Instance cleanup;
+ if (cleanup.valid ())
+ {
+ cleanup->thread_use_key (key);
+ // for TSS_Cleanup purposes treat stetting data to zero
+ // like detaching. This is a consequence of POSIX allowing
+ // deletion of a "used" key.
+ if (data == 0)
+ {
+ cleanup->thread_detach_key (key);
+ }
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+# elif defined (ACE_HAS_WTHREADS)
+ if (ACE_OS::thr_setspecific_native (key, data) == 0)
+ {
+ TSS_Cleanup_Instance cleanup;
+ if (cleanup.valid ())
+ {
+ cleanup->thread_use_key (key);
+ // for TSS_Cleanup purposes treat stetting data to zero
+ // like detaching. This is a consequence of POSIX allowing
+ // deletion of a "used" key.
+ if (data == 0)
+ {
+ cleanup->thread_detach_key (key);
+ }
+ return 0;
+ }
+ return -1;
+ }
+ return -1;
+# elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ return ACE_OS::thr_setspecific_native (key, data);
+# else /* ACE_HAS_TSS_EMULATION */
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (data);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_TSS_EMULATION */
+# else /* ACE_HAS_THREADS */
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (data);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+void
+ACE_OS::unique_name (const void *object,
+ char *name,
+ size_t length)
+{
+ // The process ID will provide uniqueness between processes on the
+ // same machine. The "this" pointer of the <object> will provide
+ // uniqueness between other "live" objects in the same process. The
+ // uniqueness of this name is therefore only valid for the life of
+ // <object>.
+ char temp_name[ACE_UNIQUE_NAME_LEN];
+ ACE_OS::sprintf (temp_name,
+ "%p%d",
+ object,
+ static_cast <int> (ACE_OS::getpid ()));
+ ACE_OS::strsncpy (name,
+ temp_name,
+ length);
+}
+
+#if defined (ACE_USES_WCHAR)
+void
+ACE_OS::unique_name (const void *object,
+ wchar_t *name,
+ size_t length)
+{
+ // The process ID will provide uniqueness between processes on the
+ // same machine. The "this" pointer of the <object> will provide
+ // uniqueness between other "live" objects in the same process. The
+ // uniqueness of this name is therefore only valid for the life of
+ // <object>.
+ wchar_t temp_name[ACE_UNIQUE_NAME_LEN];
+ ACE_OS::sprintf (temp_name,
+ ACE_TEXT ("%p%d"),
+ object,
+ static_cast <int> (ACE_OS::getpid ()));
+ ACE_OS::strsncpy (name,
+ temp_name,
+ length);
+}
+#endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_VXWORKS) && !defined (__RTP__)
+# include /**/ <usrLib.h> /* for ::sp() */
+# include /**/ <sysLib.h> /* for ::sysClkRateGet() */
+
+// This global function can be used from the VxWorks shell to pass
+// arguments to a C main () function.
+//
+// usage: -> spa main, "arg1", "arg2"
+//
+// All arguments must be quoted, even numbers.
+int
+spa (FUNCPTR entry, ...)
+{
+ static const unsigned int ACE_MAX_ARGS = 10;
+ static char *argv[ACE_MAX_ARGS];
+ va_list pvar;
+ unsigned int argc;
+
+ // Hardcode a program name because the real one isn't available
+ // through the VxWorks shell.
+ argv[0] = "ace_main";
+
+ // Peel off arguments to spa () and put into argv. va_arg () isn't
+ // necessarily supposed to return 0 when done, though since the
+ // VxWorks shell uses a fixed number (10) of arguments, it might 0
+ // the unused ones. This function could be used to increase that
+ // limit, but then it couldn't depend on the trailing 0. So, the
+ // number of arguments would have to be passed.
+ va_start (pvar, entry);
+
+ for (argc = 1; argc <= ACE_MAX_ARGS; ++argc)
+ {
+ argv[argc] = va_arg (pvar, char *);
+
+ if (argv[argc] == 0)
+ break;
+ }
+
+ if (argc > ACE_MAX_ARGS && argv[argc-1] != 0)
+ {
+ // try to read another arg, and warn user if the limit was exceeded
+ if (va_arg (pvar, char *) != 0)
+ ACE_OS::fprintf (stderr, "spa(): number of arguments limited to %d\n",
+ ACE_MAX_ARGS);
+ }
+ else
+ {
+ // fill unused argv slots with 0 to get rid of leftovers
+ // from previous invocations
+ for (unsigned int i = argc; i <= ACE_MAX_ARGS; ++i)
+ argv[i] = 0;
+ }
+
+ // The hard-coded options are what ::sp () uses, except for the
+ // larger stack size (instead of ::sp ()'s 20000).
+ int const ret = ::taskSpawn (argv[0], // task name
+ 100, // task priority
+ VX_FP_TASK, // task options
+ ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
+ entry, // entry point
+ argc, // first argument to main ()
+ (int) argv, // second argument to main ()
+ 0, 0, 0, 0, 0, 0, 0, 0);
+ va_end (pvar);
+
+ // ::taskSpawn () returns the taskID on success: return 0 instead if
+ // successful
+ return ret > 0 ? 0 : ret;
+}
+
+// A helper function for the extended spa functions
+static void
+add_to_argv (int& argc, char** argv, int max_args, char* string)
+{
+ char indouble = 0;
+ size_t previous = 0;
+ size_t length = ACE_OS::strlen (string);
+
+ // We use <= to make sure that we get the last argument
+ for (size_t i = 0; i <= length; i++)
+ {
+ // Is it a double quote that hasn't been escaped?
+ if (string[i] == '\"' && (i == 0 || string[i - 1] != '\\'))
+ {
+ indouble ^= 1;
+ if (indouble)
+ {
+ // We have just entered a double quoted string, so
+ // save the starting position of the contents.
+ previous = i + 1;
+ }
+ else
+ {
+ // We have just left a double quoted string, so
+ // zero out the ending double quote.
+ string[i] = '\0';
+ }
+ }
+ else if (string[i] == '\\') // Escape the next character
+ {
+ // The next character is automatically
+ // skipped because of the strcpy
+ ACE_OS::strcpy (string + i, string + i + 1);
+ length--;
+ }
+ else if (!indouble &&
+ (ACE_OS::ace_isspace (string[i]) || string[i] == '\0'))
+ {
+ string[i] = '\0';
+ if (argc < max_args)
+ {
+ argv[argc] = string + previous;
+ argc++;
+ }
+ else
+ {
+ ACE_OS::fprintf (stderr, "spae(): number of arguments "
+ "limited to %d\n", max_args);
+ }
+
+ // Skip over whitespace in between arguments
+ for(++i; i < length && ACE_OS::ace_isspace (string[i]); ++i)
+ {
+ }
+
+ // Save the starting point for the next time around
+ previous = i;
+
+ // Make sure we don't skip over a character due
+ // to the above loop to skip over whitespace
+ i--;
+ }
+ }
+}
+
+// This global function can be used from the VxWorks shell to pass
+// arguments to a C main () function.
+//
+// usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
+//
+// All arguments must be within double quotes, even numbers.
+int
+spae (FUNCPTR entry, ...)
+{
+ static int const WINDSH_ARGS = 10;
+ static int const ACE_MAX_ARGS = 128;
+ static char* argv[ACE_MAX_ARGS] = { "ace_main", 0 };
+ va_list pvar;
+ int argc = 1;
+
+ // Peel off arguments to spa () and put into argv. va_arg () isn't
+ // necessarily supposed to return 0 when done, though since the
+ // VxWorks shell uses a fixed number (10) of arguments, it might 0
+ // the unused ones.
+ va_start (pvar, entry);
+
+ int i = 0;
+ for (char* str = va_arg (pvar, char*);
+ str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
+ {
+ add_to_argv(argc, argv, ACE_MAX_ARGS, str);
+ }
+
+ // fill unused argv slots with 0 to get rid of leftovers
+ // from previous invocations
+ for (i = argc; i < ACE_MAX_ARGS; ++i)
+ argv[i] = 0;
+
+ // The hard-coded options are what ::sp () uses, except for the
+ // larger stack size (instead of ::sp ()'s 20000).
+ int const ret = ::taskSpawn (argv[0], // task name
+ 100, // task priority
+ VX_FP_TASK, // task options
+ ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
+ entry, // entry point
+ argc, // first argument to main ()
+ (int) argv, // second argument to main ()
+ 0, 0, 0, 0, 0, 0, 0, 0);
+ va_end (pvar);
+
+ // ::taskSpawn () returns the taskID on success: return 0 instead if
+ // successful
+ return ret > 0 ? 0 : ret;
+}
+
+// This global function can be used from the VxWorks shell to pass
+// arguments to a C main () function. The function will be run
+// within the shells task.
+//
+// usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
+//
+// All arguments must be within double quotes, even numbers.
+// Unlike the spae function, this fuction executes the supplied
+// routine in the foreground, rather than spawning it in a separate
+// task.
+int
+spaef (FUNCPTR entry, ...)
+{
+ static int const WINDSH_ARGS = 10;
+ static int const ACE_MAX_ARGS = 128;
+ static char* argv[ACE_MAX_ARGS] = { "ace_main", 0 };
+ va_list pvar;
+ int argc = 1;
+
+ // Peel off arguments to spa () and put into argv. va_arg () isn't
+ // necessarily supposed to return 0 when done, though since the
+ // VxWorks shell uses a fixed number (10) of arguments, it might 0
+ // the unused ones.
+ va_start (pvar, entry);
+
+ int i = 0;
+ for (char* str = va_arg (pvar, char*);
+ str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
+ {
+ add_to_argv(argc, argv, ACE_MAX_ARGS, str);
+ }
+
+ // fill unused argv slots with 0 to get rid of leftovers
+ // from previous invocations
+ for (i = argc; i < ACE_MAX_ARGS; ++i)
+ argv[i] = 0;
+
+ int ret = entry (argc, argv);
+
+ va_end (pvar);
+
+ // Return the return value of the invoked ace_main routine.
+ return ret;
+}
+
+// This global function can be used from the VxWorks shell to pass
+// arguments to and run a main () function (i.e. ace_main).
+//
+// usage: -> vx_execae ace_main, "arg1 arg2 \"arg3 with spaces\"", [prio, [opt, [stacksz]]]
+//
+// All arguments must be within double quotes, even numbers.
+// This routine spawns the main () function in a separate task and waits till the
+// task has finished.
+static int _vx_call_rc = 0;
+
+static int
+_vx_call_entry(FUNCPTR entry, int argc, char* argv[])
+{
+ _vx_call_rc = entry (argc, argv);
+ return _vx_call_rc;
+}
+
+int
+vx_execae (FUNCPTR entry, char* arg, int prio, int opt, int stacksz, ...)
+{
+ static int const ACE_MAX_ARGS = 128;
+ static char* argv[ACE_MAX_ARGS] = { "ace_main", 0 };
+ int argc = 1;
+
+ // Peel off arguments to run_main () and put into argv.
+
+ if (arg)
+ add_to_argv(argc, argv, ACE_MAX_ARGS, arg);
+
+ // fill unused argv slots with 0 to get rid of leftovers
+ // from previous invocations
+ for (int i = argc; i < ACE_MAX_ARGS; ++i)
+ argv[i] = 0;
+
+ // The hard-coded options are what ::sp () uses, except for the
+ // larger stack size (instead of ::sp ()'s 20000).
+ int const ret = ::taskSpawn (argv[0], // task name
+ prio==0 ? 100 : prio, // task priority
+ opt==0 ? VX_FP_TASK : opt, // task options
+ stacksz==0 ? ACE_NEEDS_HUGE_THREAD_STACKSIZE : stacksz, // stack size
+ (FUNCPTR)_vx_call_entry, // entrypoint caller
+ (int)entry, // entry point
+ argc, // first argument to main ()
+ (int) argv, // second argument to main ()
+ 0, 0, 0, 0, 0, 0, 0);
+
+ if (ret == ERROR)
+ return 255;
+
+ while( ret > 0 && ::taskIdVerify (ret) != ERROR )
+ ::taskDelay (3 * ::sysClkRateGet ());
+
+ // ::taskSpawn () returns the taskID on success: return _vx_call_rc instead if
+ // successful
+ return ret > 0 ? _vx_call_rc : 255;
+}
+#endif /* ACE_VXWORKS && !__RTP__ */
diff --git a/ACE/ace/OS_NS_Thread.h b/ACE/ace/OS_NS_Thread.h
new file mode 100644
index 00000000000..69ccf83bd00
--- /dev/null
+++ b/ACE/ace/OS_NS_Thread.h
@@ -0,0 +1,2026 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_Thread.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_THREAD_H
+# define ACE_OS_NS_THREAD_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/Global_Macros.h"
+# include "ace/Basic_Types.h"
+# include "ace/Default_Constants.h"
+# include "ace/os_include/os_pthread.h"
+# include "ace/os_include/os_sched.h"
+# include "ace/Base_Thread_Adapter.h"
+# include "ace/os_include/sys/os_sem.h"
+# include "ace/os_include/os_semaphore.h"
+# include "ace/OS_Memory.h"
+# include "ace/OS_NS_signal.h"
+# include "ace/ACE_export.h"
+# include "ace/Object_Manager_Base.h"
+
+# if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+# endif
+# define ACE_EXPORT_MACRO ACE_Export
+
+# if defined (ACE_HAS_PRIOCNTL)
+ // Need to #include thread.h before #defining THR_BOUND, etc.,
+ // when building without threads on SunOS 5.x.
+# if defined (sun)
+# include /**/ <thread.h>
+# endif /* sun */
+
+ // Need to #include these before #defining USYNC_PROCESS on SunOS 5.x.
+# include /**/ <sys/rtpriocntl.h>
+# include /**/ <sys/tspriocntl.h>
+# endif /* ACE_HAS_PRIOCNTL */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_WIN32)
+typedef DWORD ACE_thread_t;
+typedef HANDLE ACE_hthread_t;
+// Native TSS key type
+typedef DWORD ACE_OS_thread_key_t;
+// Application TSS key type (use this type except in TSS Emulation)
+# if defined (ACE_HAS_TSS_EMULATION)
+ typedef u_int ACE_thread_key_t;
+# else /* ! ACE_HAS_TSS_EMULATION */
+ typedef ACE_OS_thread_key_t ACE_thread_key_t;
+# endif /* ! ACE_HAS_TSS_EMULATION */
+# endif /* ACE_WIN32 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if !defined (ACE_HAS_POSIX_SEM) && defined (ACE_USES_FIFO_SEM)
+
+extern "C" {
+ typedef struct
+ {
+ char* name_;
+ ACE_HANDLE fd_[2];
+ } ACE_sema_t;
+}
+
+#endif /* !ACE_HAS_POSIX_SEM && ACE_USES_FIFO_SEM */
+
+# if defined (ACE_HAS_THREADS)
+
+# if defined (ACE_HAS_STHREADS)
+# include /**/ <synch.h>
+# include /**/ <thread.h>
+# define ACE_SCOPE_PROCESS P_PID
+# define ACE_SCOPE_LWP P_LWPID
+# define ACE_SCOPE_THREAD (ACE_SCOPE_LWP + 1)
+# else
+# define ACE_SCOPE_PROCESS 0
+# define ACE_SCOPE_LWP 1
+# define ACE_SCOPE_THREAD 2
+# endif /* ACE_HAS_STHREADS */
+
+# if !defined (ACE_HAS_PTHREADS)
+# define ACE_SCHED_OTHER 0
+# define ACE_SCHED_FIFO 1
+# define ACE_SCHED_RR 2
+# endif /* ! ACE_HAS_PTHREADS */
+
+# if defined (ACE_HAS_PTHREADS)
+// moved to pthread.h
+# elif defined (ACE_HAS_STHREADS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Solaris threads, without PTHREADS.
+// Typedefs to help compatibility with Windows NT and Pthreads.
+typedef thread_t ACE_thread_t;
+// Native TSS key type (not for general use)
+typedef thread_key_t ACE_OS_thread_key_t;
+// Application TSS key type (use this type except in TSS Emulation)
+# if defined (ACE_HAS_TSS_EMULATION)
+ typedef u_int ACE_thread_key_t;
+# else /* ! ACE_HAS_TSS_EMULATION */
+ typedef ACE_OS_thread_key_t ACE_thread_key_t;
+# endif /* ! ACE_HAS_TSS_EMULATION */
+typedef mutex_t ACE_mutex_t;
+# if !defined (ACE_LACKS_RWLOCK_T)
+typedef rwlock_t ACE_rwlock_t;
+# endif /* !ACE_LACKS_RWLOCK_T */
+# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_USES_FIFO_SEM)
+typedef sema_t ACE_sema_t;
+# endif /* !ACE_HAS_POSIX_SEM */
+
+typedef cond_t ACE_cond_t;
+struct ACE_Export ACE_condattr_t
+{
+ int type;
+};
+struct ACE_Export ACE_mutexattr_t
+{
+ int type;
+};
+typedef ACE_thread_t ACE_hthread_t;
+typedef ACE_mutex_t ACE_thread_mutex_t;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# define THR_CANCEL_DISABLE 0
+# define THR_CANCEL_ENABLE 0
+# define THR_CANCEL_DEFERRED 0
+# define THR_CANCEL_ASYNCHRONOUS 0
+# define THR_JOINABLE 0
+# define THR_SCHED_FIFO 0
+# define THR_SCHED_RR 0
+# define THR_SCHED_DEFAULT 0
+# define THR_INHERIT_SCHED 0
+# define THR_SCOPE_PROCESS 0
+
+# elif defined (ACE_VXWORKS)
+# include /**/ <sysLib.h> // for sysClkRateGet()
+# if !defined (__RTP__)
+# include /**/ <taskLib.h>
+# include /**/ <taskHookLib.h>
+# endif
+
+// make sure these are included for VXWORKS.
+// @todo move these to a common place, perhaps the top of the file.
+# include "ace/os_include/os_fcntl.h"
+# include "ace/os_include/os_netdb.h"
+# include "ace/os_include/os_semaphore.h"
+# include "ace/os_include/os_signal.h"
+# include "ace/os_include/os_stdio.h"
+# include "ace/os_include/os_stdlib.h"
+# include "ace/os_include/os_stropts.h"
+# include "ace/os_include/os_unistd.h"
+# include "ace/os_include/arpa/os_inet.h"
+# include "ace/os_include/sys/os_select.h"
+# include "ace/os_include/sys/os_socket.h"
+
+// task options: the other options are either obsolete, internal, or for
+// Fortran or Ada support
+# define VX_UNBREAKABLE 0x0002 /* breakpoints ignored */
+# if !defined (VX_FP_TASK)
+# define VX_FP_TASK 0x0008 /* floating point coprocessor */
+# endif
+# define VX_PRIVATE_ENV 0x0080 /* private environment support */
+# define VX_NO_STACK_FILL 0x0100 /* do not stack fill for
+ checkstack () */
+
+# define THR_CANCEL_DISABLE 0
+# define THR_CANCEL_ENABLE 0
+# define THR_CANCEL_DEFERRED 0
+# define THR_CANCEL_ASYNCHRONOUS 0
+# define THR_BOUND 0
+# define THR_NEW_LWP 0
+# define THR_DETACHED 0
+# define THR_SUSPENDED 0
+# define THR_DAEMON 0
+# define THR_JOINABLE 0
+# define THR_SCHED_FIFO 0
+# define THR_SCHED_RR 0
+# define THR_SCHED_DEFAULT 0
+# define THR_INHERIT_SCHED 0
+# define THR_EXPLICIT_SCHED 0
+# define THR_SCHED_IO 0
+# define THR_SCOPE_SYSTEM 0
+# define THR_SCOPE_PROCESS 0
+# define USYNC_THREAD 0
+# define USYNC_PROCESS 1 /* It's all global on VxWorks
+ (without MMU option). */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+typedef SEM_ID ACE_mutex_t;
+// Implement ACE_thread_mutex_t with ACE_mutex_t because there's just
+// one process . . .
+typedef ACE_mutex_t ACE_thread_mutex_t;
+# if !defined (ACE_HAS_POSIX_SEM)
+// Use VxWorks semaphores, wrapped ...
+typedef struct
+{
+ /// Semaphore handle. This is allocated by VxWorks.
+ SEM_ID sema_;
+
+ /// Name of the semaphore: always NULL with VxWorks.
+ char *name_;
+} ACE_sema_t;
+# endif /* !ACE_HAS_POSIX_SEM */
+typedef int ACE_thread_t;
+typedef int ACE_hthread_t;
+// Key type: the ACE TSS emulation requires the key type be unsigned,
+// for efficiency. (Current POSIX and Solaris TSS implementations also
+// use u_int, so the ACE TSS emulation is compatible with them.)
+// Native TSS key type
+typedef u_int ACE_OS_thread_key_t;
+// Application TSS key type (use this type except in TSS Emulation)
+# if defined (ACE_HAS_TSS_EMULATION)
+ typedef u_int ACE_thread_key_t;
+# else /* ! ACE_HAS_TSS_EMULATION */
+ typedef ACE_OS_thread_key_t ACE_thread_key_t;
+# endif /* ! ACE_HAS_TSS_EMULATION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# elif defined (ACE_HAS_WTHREADS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+typedef CRITICAL_SECTION ACE_thread_mutex_t;
+
+typedef struct
+{
+ /// Either USYNC_THREAD or USYNC_PROCESS
+ int type_;
+ union
+ {
+ HANDLE proc_mutex_;
+ CRITICAL_SECTION thr_mutex_;
+ };
+} ACE_mutex_t;
+
+// Wrapper for NT Events.
+typedef HANDLE ACE_event_t;
+
+# if defined (ACE_WIN32)
+//@@ ACE_USES_WINCE_SEMA_SIMULATION is used to debug
+// semaphore simulation on WinNT. It should be
+// changed to ACE_USES_HAS_WINCE at some later point.
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+typedef HANDLE ACE_sema_t;
+# else
+/**
+ * @class ACE_sema_t
+ *
+ * @brief Semaphore simulation for Windows CE.
+ */
+class ACE_Export ACE_sema_t
+{
+public:
+ /// Serializes access to @c count_.
+ ACE_thread_mutex_t lock_;
+
+ /// This event is signaled whenever the count becomes non-zero.
+ ACE_event_t count_nonzero_;
+
+ /// Current count of the semaphore.
+ u_int count_;
+};
+
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# endif /* defined (ACE_WIN32) */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// These need to be different values, neither of which can be 0...
+# define USYNC_THREAD 1
+# define USYNC_PROCESS 2
+
+# define THR_CANCEL_DISABLE 0
+# define THR_CANCEL_ENABLE 0
+# define THR_CANCEL_DEFERRED 0
+# define THR_CANCEL_ASYNCHRONOUS 0
+# define THR_DETACHED 0x02000000 /* ignore in most places */
+# define THR_BOUND 0 /* ignore in most places */
+# define THR_NEW_LWP 0 /* ignore in most places */
+# define THR_DAEMON 0 /* ignore in most places */
+# define THR_JOINABLE 0 /* ignore in most places */
+# define THR_SUSPENDED CREATE_SUSPENDED
+# define THR_USE_AFX 0x01000000
+# define THR_SCHED_FIFO 0
+# define THR_SCHED_RR 0
+# define THR_SCHED_DEFAULT 0
+# define THR_INHERIT_SCHED 0
+# define THR_EXPLICIT_SCHED 0
+# define THR_SCOPE_PROCESS 0
+# define THR_SCOPE_SYSTEM 0
+# endif /* ACE_HAS_PTHREADS / STHREADS / VXWORKS / WTHREADS **********/
+
+# if defined (ACE_LACKS_COND_T)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_cond_t
+ *
+ * @brief This structure is used to implement condition variables on
+ * platforms that lack it natively, such as VxWorks, and Win32.
+ *
+ * At the current time, this stuff only works for threads
+ * within the same process.
+ */
+class ACE_Export ACE_cond_t
+{
+public:
+
+ /// Returns the number of waiters.
+ long waiters (void) const;
+
+//protected:
+ /// Number of waiting threads.
+ long waiters_;
+
+ /// Serialize access to the waiters count.
+ ACE_thread_mutex_t waiters_lock_;
+
+ /// Queue up threads waiting for the condition to become signaled.
+ ACE_sema_t sema_;
+
+# if defined (ACE_VXWORKS)
+ /**
+ * A semaphore used by the broadcast/signal thread to wait for all
+ * the waiting thread(s) to wake up and be released from the
+ * semaphore.
+ */
+ ACE_sema_t waiters_done_;
+# elif defined (ACE_WIN32)
+ /**
+ * An auto reset event used by the broadcast/signal thread to wait
+ * for the waiting thread(s) to wake up and get a chance at the
+ * semaphore.
+ */
+ HANDLE waiters_done_;
+# else
+# error "Please implement this feature or check your config.h file!"
+# endif /* ACE_VXWORKS */
+
+ /// Keeps track of whether we were broadcasting or just signaling.
+ size_t was_broadcast_;
+};
+
+struct ACE_Export ACE_condattr_t
+{
+ int type;
+};
+
+struct ACE_Export ACE_mutexattr_t
+{
+ int type;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# endif /* ACE_LACKS_COND_T */
+
+# if defined (ACE_LACKS_RWLOCK_T) && !defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_rwlock_t
+ *
+ * @brief This is used to implement readers/writer locks on NT,
+ * VxWorks, and POSIX pthreads.
+ *
+ * At the current time, this stuff only works for threads
+ * within the same process.
+ */
+struct ACE_Export ACE_rwlock_t
+{
+public:
+//protected:
+
+ /// Serialize access to internal state.
+ ACE_mutex_t lock_;
+
+ /// Reader threads waiting to acquire the lock.
+ ACE_cond_t waiting_readers_;
+
+ /// Number of waiting readers.
+ int num_waiting_readers_;
+
+ /// Writer threads waiting to acquire the lock.
+ ACE_cond_t waiting_writers_;
+
+ /// Number of waiting writers.
+ int num_waiting_writers_;
+
+ /// Value is -1 if writer has the lock, else this keeps track of the
+ /// number of readers holding the lock.
+ int ref_count_;
+
+ /// Indicate that a reader is trying to upgrade
+ int important_writer_;
+
+ /// Condition for the upgrading reader
+ ACE_cond_t waiting_important_writer_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# elif defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef pthread_rwlock_t ACE_rwlock_t;
+ACE_END_VERSIONED_NAMESPACE_DECL
+# elif defined (ACE_HAS_STHREADS)
+# include /**/ <synch.h>
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef rwlock_t ACE_rwlock_t;
+ACE_END_VERSIONED_NAMESPACE_DECL
+# endif /* ACE_LACKS_RWLOCK_T */
+
+// Define some default thread priorities on all threaded platforms, if
+// not defined above or in the individual platform config file.
+// ACE_THR_PRI_FIFO_DEF should be used by applications for default
+// real-time thread priority. ACE_THR_PRI_OTHER_DEF should be used
+// for non-real-time priority.
+# if !defined(ACE_THR_PRI_FIFO_DEF)
+# if defined (ACE_WTHREADS)
+ // It would be more in spirit to use THREAD_PRIORITY_NORMAL. But,
+ // using THREAD_PRIORITY_ABOVE_NORMAL should give preference to the
+ // threads in this process, even if the process is not in the
+ // REALTIME_PRIORITY_CLASS.
+# define ACE_THR_PRI_FIFO_DEF THREAD_PRIORITY_ABOVE_NORMAL
+# else /* ! ACE_WTHREADS */
+# define ACE_THR_PRI_FIFO_DEF 0
+# endif /* ! ACE_WTHREADS */
+# endif /* ! ACE_THR_PRI_FIFO_DEF */
+
+# if !defined(ACE_THR_PRI_OTHER_DEF)
+# if defined (ACE_WTHREADS)
+ // It would be more in spirit to use THREAD_PRIORITY_NORMAL. But,
+ // using THREAD_PRIORITY_ABOVE_NORMAL should give preference to the
+ // threads in this process, even if the process is not in the
+ // REALTIME_PRIORITY_CLASS.
+# define ACE_THR_PRI_OTHER_DEF THREAD_PRIORITY_NORMAL
+# else /* ! ACE_WTHREADS */
+# define ACE_THR_PRI_OTHER_DEF 0
+# endif /* ! ACE_WTHREADS */
+# endif /* ! ACE_THR_PRI_OTHER_DEF */
+
+// Recursive mutex support.
+//
+// There are two parts to this:
+// 1. The mutex type itself. This is based on whether or not the
+// platform supports recursive mutexes natively or they're emulated.
+// 2. Support for using the recursive mutex with a condition variable.
+// When a thread waits on a condition variable, it has to relinquish
+// the lock and wait atomically, then reacquire it after the condition
+// variable is signaled. In non-recursive mutexes, the platform
+// handles this automatically. But in recursive mutexes, especially
+// when emulated, the recursion count needs to be maintained across
+// the wait. Since another thread needs to be able to acquire the
+// lock, it needs to appear free, even if the waiting thread had done
+// multiple acquires. Thus, there's another structure to hold this
+// information, and is used with the recursive_mutex_cond_unlock()
+// and recursive_mutex_cond_relock() methods to maintain the expected
+// state when the wait finishes.
+# if defined (ACE_HAS_RECURSIVE_MUTEXES)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+typedef ACE_thread_mutex_t ACE_recursive_thread_mutex_t;
+# if defined (ACE_WIN32)
+// Windows has recursive mutexes, but doesn't have condition variables,
+// so there's no built-in support for this. Thus, the condition-related
+// unlock/relock is augmented in ACE.
+struct ACE_recursive_mutex_state
+{
+ // On Windows the augmented processing is simply unlocking/relocking
+ // the recursive locks - the condition handles a single lock ok.
+ LONG relock_count_;
+};
+# else
+// No need for special handling; just need a type for method signatures.
+typedef int ACE_recursive_mutex_state;
+# endif /* ACE_WIN32 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# else
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_recursive_thread_mutex_t
+ *
+ * @brief Implement a thin C++ wrapper that allows nested acquisition
+ * and release of a mutex that occurs in the same thread.
+ *
+ * This implementation is based on an algorithm sketched by Dave
+ * Butenhof <butenhof@zko.dec.com>. Naturally, I take the
+ * credit for any mistakes ;-)
+ */
+class ACE_recursive_thread_mutex_t
+{
+public:
+ /// Guards the state of the nesting level and thread id.
+ ACE_thread_mutex_t nesting_mutex_;
+
+ /// This condition variable suspends other waiting threads until the
+ /// mutex is available.
+ ACE_cond_t lock_available_;
+
+ /// Current nesting level of the recursion.
+ int nesting_level_;
+
+ /// Current owner of the lock.
+ ACE_thread_t owner_id_;
+};
+
+// Since recursive mutex is emulated, the state saving needs to be handled
+// in ACE as well. These members save those from ACE_recursive_thread_mutex_t.
+struct ACE_recursive_mutex_state
+{
+ int nesting_level_;
+ ACE_thread_t owner_id_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# endif /* ACE_HAS_RECURSIVE_MUTEXES */
+
+# else /* !ACE_HAS_THREADS, i.e., the OS/platform doesn't support threading. */
+
+// Give these things some reasonable value...
+# define ACE_SCOPE_PROCESS 0
+# define ACE_SCOPE_LWP 1
+# define ACE_SCOPE_THREAD 2
+# define ACE_SCHED_OTHER 0
+# define ACE_SCHED_FIFO 1
+# define ACE_SCHED_RR 2
+# if !defined (THR_CANCEL_DISABLE)
+# define THR_CANCEL_DISABLE 0
+# endif /* ! THR_CANCEL_DISABLE */
+# if !defined (THR_CANCEL_ENABLE)
+# define THR_CANCEL_ENABLE 0
+# endif /* ! THR_CANCEL_ENABLE */
+# if !defined (THR_CANCEL_DEFERRED)
+# define THR_CANCEL_DEFERRED 0
+# endif /* ! THR_CANCEL_DEFERRED */
+# if !defined (THR_CANCEL_ASYNCHRONOUS)
+# define THR_CANCEL_ASYNCHRONOUS 0
+# endif /* ! THR_CANCEL_ASYNCHRONOUS */
+# if !defined (THR_JOINABLE)
+# define THR_JOINABLE 0 /* ignore in most places */
+# endif /* ! THR_JOINABLE */
+# if !defined (THR_DETACHED)
+# define THR_DETACHED 0 /* ignore in most places */
+# endif /* ! THR_DETACHED */
+# if !defined (THR_DAEMON)
+# define THR_DAEMON 0 /* ignore in most places */
+# endif /* ! THR_DAEMON */
+# if !defined (THR_BOUND)
+# define THR_BOUND 0 /* ignore in most places */
+# endif /* ! THR_BOUND */
+# if !defined (THR_NEW_LWP)
+# define THR_NEW_LWP 0 /* ignore in most places */
+# endif /* ! THR_NEW_LWP */
+# if !defined (THR_SUSPENDED)
+# define THR_SUSPENDED 0 /* ignore in most places */
+# endif /* ! THR_SUSPENDED */
+# if !defined (THR_SCHED_FIFO)
+# define THR_SCHED_FIFO 0
+# endif /* ! THR_SCHED_FIFO */
+# if !defined (THR_SCHED_RR)
+# define THR_SCHED_RR 0
+# endif /* ! THR_SCHED_RR */
+# if !defined (THR_SCHED_DEFAULT)
+# define THR_SCHED_DEFAULT 0
+# endif /* ! THR_SCHED_DEFAULT */
+# if !defined (THR_INHERIT_SCHED)
+# define THR_INHERIT_SCHED 0
+# endif /* ! THR_INHERIT_SCHED */
+# if !defined (USYNC_THREAD)
+# define USYNC_THREAD 0
+# endif /* ! USYNC_THREAD */
+# if !defined (USYNC_PROCESS)
+# define USYNC_PROCESS 0
+# endif /* ! USYNC_PROCESS */
+# if !defined (THR_SCOPE_PROCESS)
+# define THR_SCOPE_PROCESS 0
+# endif /* ! THR_SCOPE_PROCESS */
+# if !defined (THR_SCOPE_SYSTEM)
+# define THR_SCOPE_SYSTEM 0
+# endif /* ! THR_SCOPE_SYSTEM */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// These are dummies needed for class OS.h
+typedef int ACE_cond_t;
+struct ACE_Export ACE_condattr_t
+{
+ int type;
+};
+struct ACE_Export ACE_mutexattr_t
+{
+ int type;
+};
+typedef int ACE_mutex_t;
+typedef int ACE_thread_mutex_t;
+typedef int ACE_recursive_thread_mutex_t;
+typedef int ACE_recursive_mutex_state;
+# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_USES_FIFO_SEM)
+typedef int ACE_sema_t;
+# endif /* !ACE_HAS_POSIX_SEM && !ACE_USES_FIFO_SEM */
+typedef int ACE_rwlock_t;
+typedef int ACE_thread_t;
+typedef int ACE_hthread_t;
+// Native TSS key type
+typedef unsigned int ACE_OS_thread_key_t;
+// Application TSS key type (use this type except in TSS Emulation)
+# if defined (ACE_HAS_TSS_EMULATION)
+ typedef u_int ACE_thread_key_t;
+# else /* ! ACE_HAS_TSS_EMULATION */
+ typedef ACE_OS_thread_key_t ACE_thread_key_t;
+# endif /* ! ACE_HAS_TSS_EMULATION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Ensure that ACE_THR_PRI_FIFO_DEF and ACE_THR_PRI_OTHER_DEF are
+// defined on non-threaded platforms, to support application source
+// code compatibility. ACE_THR_PRI_FIFO_DEF should be used by
+// applications for default real-time thread priority.
+// ACE_THR_PRI_OTHER_DEF should be used for non-real-time priority.
+# if !defined(ACE_THR_PRI_FIFO_DEF)
+# define ACE_THR_PRI_FIFO_DEF 0
+# endif /* ! ACE_THR_PRI_FIFO_DEF */
+# if !defined(ACE_THR_PRI_OTHER_DEF)
+# define ACE_THR_PRI_OTHER_DEF 0
+# endif /* ! ACE_THR_PRI_OTHER_DEF */
+
+# endif /* ACE_HAS_THREADS ***********************************************/
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Thread_ID
+ *
+ * @brief Defines a platform-independent thread ID class. Note that
+ * this class should be defined within the scope of a thread, rather
+ * than at global scope!
+ */
+class ACE_Export ACE_Thread_ID
+{
+public:
+ /// Initialize the object using the thread id and thread handle
+ /// passed as parameters.
+ ACE_Thread_ID (ACE_thread_t thr_id,
+ ACE_hthread_t thr_handle);
+
+ /// Initialize the object using calls to ACE_OS::thr_self().
+ ACE_Thread_ID (void);
+
+ /// Copy constructor.
+ ACE_Thread_ID (const ACE_Thread_ID &rhs);
+
+ /// Get the thread id.
+ ACE_thread_t id (void) const;
+
+ /// Set the thread id.
+ void id (ACE_thread_t);
+
+ /// Get the thread handle.
+ ACE_hthread_t handle (void) const;
+
+ /// Set the thread handle.
+ void handle (ACE_hthread_t);
+
+ // Create a string representation of the thread id.
+ void to_string (char *thr_string) const;
+
+ /// Equality operator.
+ bool operator== (const ACE_Thread_ID &) const;
+
+ /// Inequality operator.
+ bool operator!= (const ACE_Thread_ID &) const;
+
+private:
+ /// Identify the thread.
+ ACE_thread_t thread_id_;
+
+ /// Handle to the thread (typically used to "wait" on Win32).
+ ACE_hthread_t thread_handle_;
+};
+
+// = The ACE_Sched_Priority type should be used for platform-
+// independent thread and process priorities, by convention.
+// int should be used for OS-specific priorities.
+typedef int ACE_Sched_Priority;
+
+# if !defined (ACE_DEFAULT_SYNCH_TYPE)
+# if defined (ACE_VXWORKS)
+ // Types include these options: SEM_Q_PRIORITY, SEM_Q_FIFO,
+ // SEM_DELETE_SAFE, and SEM_INVERSION_SAFE. SEM_Q_FIFO is
+ // used as the default because that is VxWorks' default.
+# define ACE_DEFAULT_SYNCH_TYPE SEM_Q_FIFO
+# else
+# define ACE_DEFAULT_SYNCH_TYPE USYNC_THREAD
+# endif /* ACE_VXWORKS */
+#endif /* ! ACE_DEFAULT_SYNCH_TYPE */
+
+// forward declaration
+class ACE_Sched_Params;
+class ACE_Time_Value;
+
+#if defined (ACE_WIN32)
+typedef int ACE_idtype_t;
+typedef DWORD ACE_id_t;
+typedef int ACE_pri_t;
+# define ACE_SELF (0)
+#else /* !defined (ACE_WIN32) */
+# if defined (ACE_HAS_IDTYPE_T)
+ typedef idtype_t ACE_idtype_t;
+# else
+ typedef int ACE_idtype_t;
+# endif /* ACE_HAS_IDTYPE_T */
+# if defined (ACE_HAS_STHREADS) || defined (DIGITAL_UNIX)
+# if defined (ACE_LACKS_PRI_T)
+ typedef int pri_t;
+# endif /* ACE_LACKS_PRI_T */
+ typedef id_t ACE_id_t;
+# define ACE_SELF P_MYID
+ typedef pri_t ACE_pri_t;
+# else /* ! ACE_HAS_STHREADS && ! DIGITAL_UNIX */
+ typedef long ACE_id_t;
+# define ACE_SELF (-1)
+ typedef short ACE_pri_t;
+# endif /* ! ACE_HAS_STHREADS && ! DIGITAL_UNIX */
+#endif /* !defined (ACE_WIN32) */
+
+# if defined (ACE_HAS_TSS_EMULATION)
+ // Allow config.h to set the default number of thread keys.
+# if !defined (ACE_DEFAULT_THREAD_KEYS)
+# define ACE_DEFAULT_THREAD_KEYS 64
+# endif /* ! ACE_DEFAULT_THREAD_KEYS */
+
+// forward declaration
+class ACE_TSS_Keys;
+
+/**
+ * @class ACE_TSS_Emulation
+ *
+ * @brief Thread-specific storage emulation.
+ *
+ * This provides a thread-specific storage implementation.
+ * It is intended for use on platforms that don't have a
+ * native TSS, or have a TSS with limitations such as the
+ * number of keys or lack of support for removing keys.
+ */
+class ACE_Export ACE_TSS_Emulation
+{
+public:
+ typedef void (*ACE_TSS_DESTRUCTOR)(void *value) /* throw () */;
+
+ /// Maximum number of TSS keys allowed over the life of the program.
+ enum { ACE_TSS_THREAD_KEYS_MAX = ACE_DEFAULT_THREAD_KEYS };
+
+ /// Returns the total number of keys allocated so far.
+ static u_int total_keys ();
+
+ /// Sets the argument to the next available key. Returns 0 on success,
+ /// -1 if no keys are available.
+ static int next_key (ACE_thread_key_t &key);
+
+ /// Release a key that was used. This way the key can be given out in a
+ /// new request. Returns 0 on success, 1 if the key was not reserved.
+ static int release_key (ACE_thread_key_t key);
+
+ /// Check a key for validity.
+ static int is_key (ACE_thread_key_t key);
+
+ /// Returns the exit hook associated with the key. Does _not_ check
+ /// for a valid key.
+ static ACE_TSS_DESTRUCTOR tss_destructor (const ACE_thread_key_t key);
+
+ /// Associates the TSS destructor with the key. Does _not_ check
+ /// for a valid key.
+ static void tss_destructor (const ACE_thread_key_t key,
+ ACE_TSS_DESTRUCTOR destructor);
+
+ /// Accesses the object referenced by key in the current thread's TSS array.
+ /// Does _not_ check for a valid key.
+ static void *&ts_object (const ACE_thread_key_t key);
+
+ /**
+ * Setup an array to be used for local TSS. Returns the array
+ * address on success. Returns 0 if local TSS had already been
+ * setup for this thread. There is no corresponding tss_close ()
+ * because it is not needed.
+ * @note tss_open () is called by ACE for threads that it spawns.
+ * If your application spawns threads without using ACE, and it uses
+ * ACE's TSS emulation, each of those threads should call tss_open
+ * (). See the ace_thread_adapter () implementation for an example.
+ */
+ static void *tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX]);
+
+ /// Shutdown TSS emulation. For use only by ACE_OS::cleanup_tss ().
+ static void tss_close ();
+
+private:
+ // Global TSS structures.
+ /// Contains the possible value of the next key to be allocated. Which key
+ /// is actually allocated is based on the tss_keys_used
+ static u_int total_keys_;
+
+ /// Array of thread exit hooks (TSS destructors) that are called for each
+ /// key (that has one) when the thread exits.
+ static ACE_TSS_DESTRUCTOR tss_destructor_ [ACE_TSS_THREAD_KEYS_MAX];
+
+ /// TSS_Keys instance to administrate whether a specific key is in used
+ /// or not.
+ /// or not.
+ // Static construction in VxWorks 5.4 and later is slightly broken.
+ // If the static object is more complex than an integral type, static
+ // construction will occur twice. The tss_keys_used_ object is
+ // statically constructed and then modified by ACE_Log_Msg::instance()
+ // when two keys are created and TSS data is stored. However, at
+ // the end of static construction the tss_keys_used_ object is again
+ // initialized and therefore it will appear to next_key() that no
+ // TSS keys have been handed out. That is all true unless the
+ // tss_keys_used object is a static pointer instead of a static object.
+ static ACE_TSS_Keys* tss_keys_used_;
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ /// Location of current thread's TSS array.
+ static void **tss_base (void* ts_storage[] = 0, u_int *ts_created = 0);
+# else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
+ /// Location of current thread's TSS array.
+ static void **&tss_base ();
+# endif /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ // Rely on native thread specific storage for the implementation,
+ // but just use one key.
+ static ACE_OS_thread_key_t native_tss_key_;
+
+ // Used to indicate if native tss key has been allocated
+ static bool key_created_;
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+};
+# endif /* ACE_HAS_TSS_EMULATION */
+
+// moved ACE_TSS_Ref, ACE_TSS_Info, and ACE_TSS_Keys class
+// declarations from OS.cpp so they are visible to the single
+// file of template instantiations.
+# if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
+/**
+ * @class ACE_TSS_Ref
+ *
+ * @brief "Reference count" for thread-specific storage keys.
+ *
+ * Since the <ACE_Unbounded_Stack> doesn't allow duplicates, the
+ * "reference count" is the identify of the thread_id.
+ */
+class ACE_TSS_Ref
+{
+public:
+ /// Constructor
+ ACE_TSS_Ref (ACE_thread_t id);
+
+ /// Default constructor
+ ACE_TSS_Ref (void);
+
+ /// Check for equality.
+ bool operator== (const ACE_TSS_Ref &) const;
+
+ /// Check for inequality.
+ bool operator!= (const ACE_TSS_Ref &) const;
+
+// private:
+
+ /// ID of thread using a specific key.
+ ACE_thread_t tid_;
+};
+
+/**
+ * @class ACE_TSS_Info
+ *
+ * @brief Thread Specific Key management.
+ *
+ * This class maps a key to a "destructor."
+ */
+class ACE_TSS_Info
+{
+public:
+ /// Declare pointer to function to destroy tss object.
+ typedef void (*Destructor)(void *);
+
+ /// Constructor
+ ACE_TSS_Info (ACE_thread_key_t key,
+ Destructor dest = 0);
+
+ /// Default constructor
+ ACE_TSS_Info (void);
+
+ /// Returns 1 if the key is in use, 0 if not.
+ int key_in_use (void) const { return thread_count_ != -1; }
+
+ /// Mark the key as being in use if the flag is non-zero, or
+ /// not in use if the flag is 0.
+ void key_in_use (int flag) { thread_count_ = flag == 0 ? -1 : 1; }
+
+ /// Check for equality.
+ bool operator== (const ACE_TSS_Info &) const;
+
+ /// Check for inequality.
+ bool operator!= (const ACE_TSS_Info &) const;
+
+ /// Dump the state.
+ void dump (void);
+
+private:
+ /// Key to the thread-specific storage item.
+ ACE_thread_key_t key_;
+
+ /// "Destructor" that gets called when the item is finally released.
+ Destructor destructor_;
+
+ /// Count of threads that are using this key. Contains -1 when the
+ /// key is not in use.
+ int thread_count_;
+
+ friend class ACE_TSS_Cleanup;
+};
+
+/**
+ * @class ACE_TSS_Keys
+ *
+ * @brief Collection of in-use flags for a thread's TSS keys.
+ * For internal use only by ACE_TSS_Cleanup; it is public because
+ * some compilers can't use nested classes for template instantiation
+ * parameters.
+ *
+ * Wrapper around array of whether each key is in use. A simple
+ * typedef doesn't work with Sun C++ 4.2.
+ */
+class ACE_TSS_Keys
+{
+public:
+ /// Default constructor, to initialize all bits to zero (unused).
+ ACE_TSS_Keys (void);
+
+ /// Mark the specified key as being in use, if it was not already so marked.
+ /// Returns 1 if the had already been marked, 0 if not.
+ int test_and_set (const ACE_thread_key_t key);
+
+ /// Mark the specified key as not being in use, if it was not already so
+ /// cleared. Returns 1 if the key had already been cleared, 0 if not.
+ int test_and_clear (const ACE_thread_key_t key);
+
+ /// Return whether the specific key is marked as in use.
+ /// Returns 1 if the key is been marked, 0 if not.
+ int is_set (const ACE_thread_key_t key) const;
+
+private:
+ /// For a given key, find the word and bit number that represent it.
+ static void find (const u_int key, u_int &word, u_int &bit);
+
+ enum
+ {
+# if ACE_SIZEOF_LONG == 8
+ ACE_BITS_PER_WORD = 64,
+# elif ACE_SIZEOF_LONG == 4
+ ACE_BITS_PER_WORD = 32,
+# else
+# error ACE_TSS_Keys only supports 32 or 64 bit longs.
+# endif /* ACE_SIZEOF_LONG == 8 */
+ ACE_WORDS = (ACE_DEFAULT_THREAD_KEYS - 1) / ACE_BITS_PER_WORD + 1
+ };
+
+ /// Bit flag collection. A bit value of 1 indicates that the key is in
+ /// use by this thread.
+ u_long key_bit_words_[ACE_WORDS];
+};
+
+# endif /* defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) */
+
+// Support non-scalar thread keys, such as with some POSIX
+// implementations, e.g., MVS.
+# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
+# define ACE_KEY_INDEX(OBJ,KEY) \
+ u_int OBJ; \
+ ACE_OS::memcpy (&OBJ, &KEY, sizeof (u_int))
+# else
+# define ACE_KEY_INDEX(OBJ,KEY) u_int OBJ = KEY
+# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
+# define ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ace_mutex_lock_cleanup_adapter)
+#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+
+# if defined (ACE_HAS_THR_C_FUNC)
+// This is necessary to work around nasty problems with MVS C++.
+extern "C" ACE_Export void ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args);
+# define ACE_PTHREAD_CLEANUP_PUSH(A) pthread_cleanup_push (ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME, (void *) A);
+# define ACE_PTHREAD_CLEANUP_POP(A) pthread_cleanup_pop(A)
+# elif defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CLEANUP)
+// Though we are defining a extern "C" function to match the prototype of
+// pthread_cleanup_push, it is undone by the Solaris header file
+// /usr/include/pthread.h. So this macro generates a warning under Solaris
+// with SunCC. This is a bug in the Solaris header file.
+extern "C" ACE_Export void ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args);
+# define ACE_PTHREAD_CLEANUP_PUSH(A) pthread_cleanup_push (ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME, (void *) A);
+# define ACE_PTHREAD_CLEANUP_POP(A) pthread_cleanup_pop(A)
+# else
+# define ACE_PTHREAD_CLEANUP_PUSH(A)
+# define ACE_PTHREAD_CLEANUP_POP(A)
+# endif /* ACE_HAS_THR_C_FUNC */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if !defined (ACE_WIN32)
+// forward decl's
+class ACE_event_t;
+# endif
+
+class ACE_Base_Thread_Adapter;
+
+namespace ACE_OS {
+ //@{ @name A set of wrappers for threads
+
+ /// This is necessary to deal with POSIX pthreads and their use of
+ /// structures for thread ids.
+ extern ACE_Export ACE_thread_t NULL_thread;
+
+ /// This is necessary to deal with POSIX pthreads and their use of
+ /// structures for thread handles.
+ extern ACE_Export ACE_hthread_t NULL_hthread;
+
+ /// This is necessary to deal with POSIX pthreads and their use of
+ /// structures for TSS keys.
+ extern ACE_Export ACE_thread_key_t NULL_key;
+ //@}
+
+ /**
+ * Call TSS destructors for the current thread. If the current
+ * thread is the main thread, then the argument must be 1.
+ * For private use of ACE_Object_Manager and ACE_Thread_Adapter only.
+ */
+ extern ACE_Export
+ void cleanup_tss (const u_int main_thread);
+
+ //@{ @name A set of wrappers for condition variables.
+#if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_LACKS_COND_T */
+ int condattr_init (ACE_condattr_t &attributes,
+ int type = ACE_DEFAULT_SYNCH_TYPE);
+
+#if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_LACKS_COND_T */
+ int condattr_destroy (ACE_condattr_t &attributes);
+
+#if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_LACKS_COND_T */
+ int cond_broadcast (ACE_cond_t *cv);
+
+#if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_LACKS_COND_T */
+ int cond_destroy (ACE_cond_t *cv);
+
+ extern ACE_Export
+ int cond_init (ACE_cond_t *cv,
+ short type = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ void *arg = 0);
+
+#if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_LACKS_COND_T */
+ int cond_init (ACE_cond_t *cv,
+ ACE_condattr_t &attributes,
+ const char *name = 0,
+ void *arg = 0);
+
+# if defined (ACE_HAS_WCHAR)
+# if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+# else
+ ACE_NAMESPACE_INLINE_FUNCTION
+# endif /* ACE_LACKS_COND_T */
+ int cond_init (ACE_cond_t *cv,
+ short type,
+ const wchar_t *name,
+ void *arg = 0);
+
+# if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+# else
+ ACE_NAMESPACE_INLINE_FUNCTION
+# endif /* ACE_LACKS_COND_T */
+ int cond_init (ACE_cond_t *cv,
+ ACE_condattr_t &attributes,
+ const wchar_t *name,
+ void *arg = 0);
+# endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_LACKS_COND_T */
+ int cond_signal (ACE_cond_t *cv);
+
+#if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_LACKS_COND_T */
+ int cond_timedwait (ACE_cond_t *cv,
+ ACE_mutex_t *m,
+ ACE_Time_Value *);
+
+#if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_LACKS_COND_T */
+ int cond_wait (ACE_cond_t *cv,
+ ACE_mutex_t *m);
+
+# if defined (ACE_WIN32) && defined (ACE_HAS_WTHREADS)
+# if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+# else
+ ACE_NAMESPACE_INLINE_FUNCTION
+# endif /* ACE_LACKS_COND_T */
+ int cond_timedwait (ACE_cond_t *cv,
+ ACE_thread_mutex_t *m,
+ ACE_Time_Value *);
+
+# if defined (ACE_LACKS_COND_T)
+ extern ACE_Export
+# else
+ ACE_NAMESPACE_INLINE_FUNCTION
+# endif /* ACE_LACKS_COND_T */
+ int cond_wait (ACE_cond_t *cv,
+ ACE_thread_mutex_t *m);
+# endif /* ACE_WIN32 && ACE_HAS_WTHREADS */
+
+ //@{ @name A set of wrappers for auto-reset and manual events.
+
+ extern ACE_Export
+ int event_destroy (ACE_event_t *event);
+
+ extern ACE_Export
+ int event_init (ACE_event_t *event,
+ int manual_reset = 0,
+ int initial_state = 0,
+ int type = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ void *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int event_init (ACE_event_t *event,
+ int manual_reset,
+ int initial_state,
+ int type,
+ const wchar_t *name,
+ void *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+# endif /* ACE_HAS_WCHAR */
+
+ extern ACE_Export
+ int event_pulse (ACE_event_t *event);
+
+ extern ACE_Export
+ int event_reset (ACE_event_t *event);
+
+ extern ACE_Export
+ int event_signal (ACE_event_t *event);
+
+ extern ACE_Export
+ int event_timedwait (ACE_event_t *event,
+ ACE_Time_Value *timeout,
+ int use_absolute_time = 1);
+
+ extern ACE_Export
+ int event_wait (ACE_event_t *event);
+
+ //@}
+
+ extern ACE_Export
+ int lwp_getparams (ACE_Sched_Params &);
+
+ extern ACE_Export
+ int lwp_setparams (const ACE_Sched_Params &);
+
+
+ //@{ @name A set of wrappers for mutex locks.
+
+ extern ACE_Export
+ int mutex_destroy (ACE_mutex_t *m);
+
+ extern ACE_Export
+ int mutex_init (ACE_mutex_t *m,
+ int lock_scope = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ ACE_mutexattr_t *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ int lock_type = 0);
+
+#if defined (ACE_HAS_WCHAR)
+ extern ACE_Export
+ int mutex_init (ACE_mutex_t *m,
+ int lock_scope,
+ const wchar_t *name,
+ ACE_mutexattr_t *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ int lock_type = 0);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Win32 note: Abandoned mutexes are not treated differently. 0 is
+ /// returned since the calling thread does get the ownership.
+ extern ACE_Export
+ int mutex_lock (ACE_mutex_t *m);
+
+ /// This method is only implemented for Win32. For abandoned
+ /// mutexes, @a abandoned is set to 1 and 0 is returned.
+ extern ACE_Export
+ int mutex_lock (ACE_mutex_t *m,
+ int &abandoned);
+
+ /**
+ * This method attempts to acquire a lock, but gives up if the lock
+ * has not been acquired by the given time. If the lock is not
+ * acquired within the given amount of time, then this method
+ * returns -1 with an @c ETIME errno on platforms that actually
+ * support timed mutexes. The timeout should be an absolute time.
+ * Note that the mutex should not be a recursive one, i.e., it
+ * should only be a standard mutex or an error checking mutex since
+ * some implementations of this method don't support recursive
+ * mutexes. If you want to use a recursive mutex see the methods
+ * below.
+ */
+ extern ACE_Export
+ int mutex_lock (ACE_mutex_t *m,
+ const ACE_Time_Value &timeout);
+
+ /**
+ * If <timeout> == 0, calls <ACE_OS::mutex_lock(m)>. Otherwise,
+ * this method attempts to acquire a lock, but gives up if the lock
+ * has not been acquired by the given time, in which case it returns
+ * -1 with an @c ETIME errno on platforms that actually support timed
+ * mutexes. The timeout should be an absolute time. Note that the
+ * mutex should not be a recursive one, i.e., it should only be a
+ * standard mutex or an error checking mutex since some
+ * implementations of this method don't support recursive mutexes.
+ * If you want to use a recursive mutex see the methods below.
+ */
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int mutex_lock (ACE_mutex_t *m,
+ const ACE_Time_Value *timeout);
+
+ /// Handle asynchronous thread cancellation cleanup.
+ extern ACE_Export
+ void mutex_lock_cleanup (void *mutex);
+
+ /// Win32 note: Abandoned mutexes are not treated differently. 0 is
+ /// returned since the calling thread does get the ownership.
+ extern ACE_Export
+ int mutex_trylock (ACE_mutex_t *m);
+
+ /// This method is only implemented for Win32. For abandoned
+ /// mutexes, <abandoned> is set to 1 and 0 is returned.
+ extern ACE_Export
+ int mutex_trylock (ACE_mutex_t *m,
+ int &abandoned);
+
+ extern ACE_Export
+ int mutex_unlock (ACE_mutex_t *m);
+
+ //@}
+
+ /// Low-level interface to <priocntl>(2).
+ /**
+ * Can't call the following priocntl, because that's a macro on
+ * Solaris.
+ */
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long priority_control (ACE_idtype_t, ACE_id_t, int, void *);
+
+ //@{ @name A set of wrappers for recursive mutex locks.
+
+ // These two methods are primarily in support of
+ // ACE_Condition<ACE_Recursive_Thread_Mutex> and should probably not
+ // be called outside that context.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int recursive_mutex_cond_unlock (ACE_recursive_thread_mutex_t *m,
+ ACE_recursive_mutex_state &state);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void recursive_mutex_cond_relock (ACE_recursive_thread_mutex_t *m,
+ ACE_recursive_mutex_state &state);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int recursive_mutex_init (ACE_recursive_thread_mutex_t *m,
+ const ACE_TCHAR *name = 0,
+ ACE_mutexattr_t *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int recursive_mutex_lock (ACE_recursive_thread_mutex_t *m);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
+ const ACE_Time_Value &timeout);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
+ const ACE_Time_Value *timeout);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m);
+
+ //@}
+
+
+ //@{ @name A set of wrappers for readers/writer locks.
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rw_rdlock (ACE_rwlock_t *rw);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rw_tryrdlock (ACE_rwlock_t *rw);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rw_trywrlock (ACE_rwlock_t *rw);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rw_trywrlock_upgrade (ACE_rwlock_t *rw);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rw_unlock (ACE_rwlock_t *rw);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rw_wrlock (ACE_rwlock_t *rw);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rwlock_destroy (ACE_rwlock_t *rw);
+
+ extern ACE_Export
+ int rwlock_init (ACE_rwlock_t *rw,
+ int type = ACE_DEFAULT_SYNCH_TYPE,
+ const ACE_TCHAR *name = 0,
+ void *arg = 0);
+
+ //@}
+
+ //@{ @name Thread scheduler interface.
+ /// Set scheduling parameters. An id of ACE_SELF indicates, e.g.,
+ /// set the parameters on the calling thread.
+ extern ACE_Export
+ int sched_params (const ACE_Sched_Params &, ACE_id_t id = ACE_SELF);
+ //@}
+
+ /// Find the schedling class ID that corresponds to the class name.
+ extern ACE_Export
+ int scheduling_class (const char *class_name, ACE_id_t &);
+
+ //@{ @name A set of wrappers for semaphores.
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_destroy (ACE_sema_t *s);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_init (ACE_sema_t *s,
+ u_int count,
+ int type = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ void *arg = 0,
+ int max = 0x7fffffff,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_init (ACE_sema_t *s,
+ u_int count,
+ int type,
+ const wchar_t *name,
+ void *arg = 0,
+ int max = 0x7fffffff,
+ LPSECURITY_ATTRIBUTES sa = 0);
+# endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_post (ACE_sema_t *s);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_post (ACE_sema_t *s,
+ u_int release_count);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_trywait (ACE_sema_t *s);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_wait (ACE_sema_t *s);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_wait (ACE_sema_t *s,
+ ACE_Time_Value &tv);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sema_wait (ACE_sema_t *s,
+ ACE_Time_Value *tv);
+
+ //@}
+
+ //@{ @name A set of wrappers for System V semaphores.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int semctl (int int_id,
+ int semnum,
+ int cmd,
+ semun);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int semget (key_t key,
+ int nsems,
+ int flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int semop (int int_id,
+ struct sembuf *sops,
+ size_t nsops);
+ //@}
+
+ /// Friendly interface to <priocntl>(2).
+ extern ACE_Export
+ int set_scheduling_params (const ACE_Sched_Params &,
+ ACE_id_t id = ACE_SELF);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigtimedwait (const sigset_t *set,
+ siginfo_t *info,
+ const ACE_Time_Value *timeout);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigwait (sigset_t *set,
+ int *sig = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigwaitinfo (const sigset_t *set,
+ siginfo_t *info);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_cancel (ACE_thread_t t_id);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_cmp (ACE_hthread_t t1,
+ ACE_hthread_t t2);
+
+ // These are non-portable since they use ACE_thread_t and
+ // ACE_hthread_t and will go away in a future release.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_continue (ACE_hthread_t target_thread);
+
+ /*
+ * Creates a new thread having @a flags attributes and running @a func
+ * with @a args (if @a thread_adapter is non-0 then @a func and @a args
+ * are ignored and are obtained from @a thread_adapter). @a thr_id
+ * and @a t_handle are set to the thread's ID and handle (?),
+ * respectively. The thread runs at @a priority priority (see
+ * below).
+ *
+ * The @a flags are a bitwise-OR of the following:
+ * = BEGIN<INDENT>
+ * THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED,
+ * THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED,
+ * THR_SUSPENDED, THR_DAEMON, THR_JOINABLE, THR_SCHED_FIFO,
+ * THR_SCHED_RR, THR_SCHED_DEFAULT, THR_EXPLICIT_SCHED,
+ * THR_SCOPE_SYSTEM, THR_SCOPE_PROCESS
+ * = END<INDENT>
+ *
+ * By default, or if @a priority is set to
+ * ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for
+ * the given scheduling policy (specified in @a flags, e.g.,
+ * @c THR_SCHED_DEFAULT) is used. This value is calculated
+ * dynamically, and is the median value between the minimum and
+ * maximum priority values for the given policy. If an explicit
+ * value is given, it is used. Note that actual priority values are
+ * EXTREMEMLY implementation-dependent, and are probably best
+ * avoided.
+ *
+ * Note that @a thread_adapter is always deleted by @c thr_create,
+ * therefore it must be allocated with global operator new.
+ *
+ * At the moment for @a thr_name a valid string is passed then this
+ * will be used on VxWorks to set the task name. If we just pass a pointer
+ * the name of the task is returned
+ */
+ extern ACE_Export
+ int thr_create (ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ ACE_thread_t *thr_id,
+ ACE_hthread_t *t_handle = 0,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ void *stack = 0,
+ size_t stacksize = ACE_DEFAULT_THREAD_STACKSIZE,
+ ACE_Base_Thread_Adapter *thread_adapter = 0,
+ const char** thr_name = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_equal (ACE_thread_t t1,
+ ACE_thread_t t2);
+
+ extern ACE_Export
+ void thr_exit (ACE_THR_FUNC_RETURN status = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_getconcurrency (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_getprio (ACE_hthread_t id,
+ int &priority);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_getprio (ACE_hthread_t id,
+ int &priority,
+ int &policy);
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ /// for internal use only. Applications should call thr_getspecific
+ int thr_getspecific_native (ACE_OS_thread_key_t key,
+ void **data);
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_getspecific (ACE_thread_key_t key,
+ void **data);
+
+#if defined (ACE_HAS_VXTHREADS)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_HAS_VXTHREADS */
+ int thr_join (ACE_hthread_t waiter_id,
+ ACE_THR_FUNC_RETURN *status);
+
+#if defined (ACE_HAS_VXTHREADS)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_HAS_VXTHREADS */
+ int thr_join (ACE_thread_t waiter_id,
+ ACE_thread_t *thr_id,
+ ACE_THR_FUNC_RETURN *status);
+
+ /**
+ * Get the thread affinity
+ *
+ * @param thr_id For NPTL-threads, when ACE_HAS_PTHREAD_SETAFFINITY_NP
+ * defined, this is the thread-id. For linux-threads, when
+ * ACE_HAS_SCHED_SETAFFINITY defined, it expects a process-id. Since for
+ * linux-threads a thread is seen as a process, it does the job.
+ * @param cpu_set_size The size of the cpu_mask
+ * @param cpu_mask Is a bitmask of CPUs to bind to, e.g value 1 binds the
+ * thread to the "CPU 0", etc
+ */
+ extern ACE_Export
+ int thr_get_affinity (ACE_hthread_t thr_id,
+ size_t cpu_set_size,
+ cpu_set_t * cpu_mask);
+
+
+ /**
+ * Set the thread affinity
+ *
+ * @param thr_id For NPTL-threads, when ACE_HAS_PTHREAD_SETAFFINITY_NP
+ * defined, this is the thread-id. For linux-threads, when
+ * ACE_HAS_SCHED_SETAFFINITY defined, it expects a process-id. Since for
+ * linux-threads a thread is seen as a process, it does the job.
+ * @param cpu_set_size The size of the cpu_mask
+ * @param cpu_mask Is a bitmask of CPUs to bind to, e.g value 1 binds the
+ * thread to the "CPU 0", etc
+ */
+ extern ACE_Export
+ int thr_set_affinity (ACE_hthread_t thr_id,
+ size_t cpu_set_size,
+ const cpu_set_t * cpu_mask);
+
+ /**
+ * @note the "inst" arg is deprecated. It will be ignored.
+ */
+ extern ACE_Export
+ int thr_key_detach (ACE_thread_key_t key, void * inst);
+
+ extern ACE_Export
+ int thr_key_used (ACE_thread_key_t key);
+
+# if defined (ACE_HAS_THR_C_DEST)
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ /// @internal Applications should call thr_keycreate
+ extern ACE_Export
+ int thr_keycreate_native (ACE_OS_thread_key_t *key,
+ ACE_THR_C_DEST);
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+ /**
+ * @note the "inst" arge is deprecated. It will be ignored.
+ */
+ extern ACE_Export
+ int thr_keycreate (ACE_thread_key_t *key,
+ ACE_THR_C_DEST,
+ void *inst = 0);
+# else
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ /// @internal Applications should call thr_keycreate instead
+ extern ACE_Export
+ int thr_keycreate_native (ACE_OS_thread_key_t *key,
+ ACE_THR_DEST);
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+ /**
+ * @note the "inst" arge is deprecated. It will be ignored.
+ */
+ extern ACE_Export
+ int thr_keycreate (ACE_thread_key_t *key,
+ ACE_THR_DEST,
+ void *inst = 0);
+
+# endif /* ACE_HAS_THR_C_DEST */
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ /// @internal Applications should call thr_keyfree instead
+ extern ACE_Export
+ int thr_keyfree_native (ACE_OS_thread_key_t key);
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+ extern ACE_Export
+ int thr_keyfree (ACE_thread_key_t key);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_kill (ACE_thread_t thr_id,
+ int signum);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t thr_min_stack (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_thread_t thr_self (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void thr_self (ACE_hthread_t &);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const char* thr_name (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_setcancelstate (int new_state,
+ int *old_state);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_setcanceltype (int new_type,
+ int *old_type);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_setconcurrency (int hint);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_setprio (ACE_hthread_t ht_id,
+ int priority,
+ int policy = -1);
+
+ extern ACE_Export
+ int thr_setprio (const ACE_Sched_Priority prio);
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ /// @internal Applications should call thr_setspecific
+ extern ACE_Export
+ int thr_setspecific_native (ACE_OS_thread_key_t key,
+ void *data);
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+ extern ACE_Export
+ int thr_setspecific (ACE_thread_key_t key,
+ void *data);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_sigsetmask (int how,
+ const sigset_t *nsm,
+ sigset_t *osm);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thr_suspend (ACE_hthread_t target_thread);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void thr_testcancel (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void thr_yield (void);
+
+ //@{ @name A set of wrappers for mutex locks that only work within a single process.
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thread_mutex_destroy (ACE_thread_mutex_t *m);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thread_mutex_init (ACE_thread_mutex_t *m,
+ int lock_type = 0,
+ const char *name = 0,
+ ACE_mutexattr_t *arg = 0);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thread_mutex_init (ACE_thread_mutex_t *m,
+ int lock_type,
+ const wchar_t *name,
+ ACE_mutexattr_t *arg = 0);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thread_mutex_lock (ACE_thread_mutex_t *m);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thread_mutex_lock (ACE_thread_mutex_t *m,
+ const ACE_Time_Value &timeout);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thread_mutex_lock (ACE_thread_mutex_t *m,
+ const ACE_Time_Value *timeout);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thread_mutex_trylock (ACE_thread_mutex_t *m);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int thread_mutex_unlock (ACE_thread_mutex_t *m);
+
+ //@}
+
+ /**
+ * This method uses process id and object pointer to come up with a
+ * machine wide unique name. The process ID will provide uniqueness
+ * between processes on the same machine. The "this" pointer of the
+ * @a object will provide uniqueness between other "live" objects in
+ * the same process. The uniqueness of this name is therefore only
+ * valid for the life of @a object.
+ */
+ extern ACE_Export
+ void unique_name (const void *object,
+ char *name,
+ size_t length);
+#if defined (ACE_USES_WCHAR)
+ extern ACE_Export
+ void unique_name (const void *object,
+ wchar_t *name,
+ size_t length);
+#endif /* ACE_USES_WCHAR */
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if !defined (ACE_WIN32)
+
+extern "C"
+{
+ typedef struct
+ {
+#if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && \
+ (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ /// Protect critical section.
+ ACE_mutex_t lock_;
+ /// Keeps track of waiters.
+ ACE_cond_t condition_;
+#else
+# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
+ (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ /// Protect critical section.
+ ACE_mutex_t lock_;
+# endif
+#endif
+
+ /// Object type.
+ int type_;
+
+ /// Specifies if this is an auto- or manual-reset event.
+ int manual_reset_;
+
+ /// "True" if signaled.
+ int is_signaled_;
+
+ /// Special bool for auto_events alone
+ /**
+ * The semantics of auto events forces us to introduce this extra
+ * variable to ensure that the thread is not woken up
+ * spuriously. Please see event_wait and event_timedwait () to see
+ * how this is used for auto_events.
+ * @todo This is a hack that needs revisiting after x.4
+ */
+ bool auto_event_signaled_;
+
+ /// Number of waiting threads.
+ unsigned long waiting_threads_;
+
+ /// Signal count
+ unsigned long signal_count_;
+ } ACE_eventdata_t;
+}
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_event_t
+ *
+ * @brief Wrapper for NT events on UNIX.
+ */
+class ACE_Export ACE_event_t
+{
+ friend int ACE_OS::event_init(ACE_event_t*, int, int, int, const char*, void*,int);
+ friend int ACE_OS::event_destroy(ACE_event_t*);
+ friend int ACE_OS::event_wait(ACE_event_t*);
+ friend int ACE_OS::event_timedwait(ACE_event_t*, ACE_Time_Value*, int);
+ friend int ACE_OS::event_signal(ACE_event_t*);
+ friend int ACE_OS::event_pulse(ACE_event_t*);
+ friend int ACE_OS::event_reset(ACE_event_t*);
+protected:
+
+ /// Event name if process shared.
+ char* name_;
+
+ /// Event data
+ ACE_eventdata_t* eventdata_;
+
+#if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_CONDATTR_PSHARED)) && \
+ (defined (ACE_USES_FIFO_SEM) || \
+ (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ /// Keeps track of waiters.
+ ACE_sema_t semaphore_;
+
+# if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_MUTEXATTR_PSHARED)) && \
+ (defined (ACE_USES_FIFO_SEM) || (defined (ACE_HAS_POSIX_SEM) && !defined (ACE_LACKS_NAMED_POSIX_SEM)))
+ /// Protect critical section.
+ ACE_sema_t lock_;
+# endif
+#endif
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_OS_Thread_Mutex_Guard
+ *
+ * This data structure is meant to be used within an ACE_OS
+ * function. It performs automatic aquisition and release of
+ * an ACE_thread_mutex_t.
+ *
+ * If an object of this class is instantiated before ACE_Object_Manager is
+ * initialized, it will not do anything. This is because this class is
+ * used only with the ACE_OS_GUARD macro which is passing a reference to
+ * one of the preallocated Object Manager locks. If the object manager
+ * hasn't been initialized yet, the lock reference is bogus. This is an
+ * acceptable tradeoff since in cases where the lock reference is bogus,
+ * there isn't multithreaded access. Please see detailed comments in
+ * Object_Manager.h for further information.
+ *
+ * For internal use only by ACE_OS.
+ */
+class ACE_OS_Thread_Mutex_Guard
+{
+public:
+ /// Implicitly and automatically acquire the lock.
+ ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m);
+
+ /// Implicitly release the lock.
+ ~ACE_OS_Thread_Mutex_Guard (void);
+
+ /// Explicitly acquire the lock.
+ int acquire (void);
+
+ /// Explicitly release the lock.
+ int release (void);
+
+protected:
+ /// Reference to the mutex.
+ ACE_thread_mutex_t &lock_;
+
+ /// Keeps track of whether we acquired the lock or failed.
+ int owner_;
+
+ // = Prevent assignment and initialization.
+ ACE_OS_Thread_Mutex_Guard &operator= (const ACE_OS_Thread_Mutex_Guard &);
+ ACE_OS_Thread_Mutex_Guard (const ACE_OS_Thread_Mutex_Guard &);
+};
+
+/**
+ * @class ACE_OS_Recursive_Thread_Mutex_Guard
+ *
+ * @brief For internal use only by ACE_OS.
+ *
+ * This data structure is meant to be used within an ACE_OS
+ * function. It performs automatic aquisition and release of
+ * an ACE_recursive_thread_mutex_t.
+ *
+ * If an object of this class is instantiated before ACE_Object_Manager is
+ * initialized, it will not do anything. This is because this class is
+ * used only with the ACE_TSS_GUARD macro which is passing a reference to
+ * one of the preallocated Object Manager locks. If the object manager
+ * hasn't been initialized yet, the lock reference is bogus. This is an
+ * acceptable tradeoff since in cases where the lock reference is bogus,
+ * there isn't multithreaded access. Please see detailed comments in
+ * Object_Manager.h for further information.
+ */
+class ACE_OS_Recursive_Thread_Mutex_Guard
+{
+public:
+ /// Implicitly and automatically acquire the lock.
+ ACE_OS_Recursive_Thread_Mutex_Guard (ACE_recursive_thread_mutex_t &m);
+
+ /// Implicitly release the lock.
+ ~ACE_OS_Recursive_Thread_Mutex_Guard (void);
+
+ /// Explicitly acquire the lock.
+ int acquire (void);
+
+ /// Explicitly release the lock.
+ int release (void);
+
+protected:
+ /// Reference to the mutex.
+ ACE_recursive_thread_mutex_t &lock_;
+
+ /// Keeps track of whether we acquired the lock or failed.
+ int owner_;
+
+ // = Prevent assignment and initialization.
+ ACE_OS_Recursive_Thread_Mutex_Guard &operator= (
+ const ACE_OS_Recursive_Thread_Mutex_Guard &);
+ ACE_OS_Recursive_Thread_Mutex_Guard (
+ const ACE_OS_Recursive_Thread_Mutex_Guard &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// used in time and unistd
+# define ACE_OS_GUARD \
+ ACE_OS_Thread_Mutex_Guard ace_os_guard__ (*(ACE_thread_mutex_t *) \
+ ACE_OS_Object_Manager::preallocated_object[ \
+ ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
+
+// used in Thread
+# define ACE_TSS_CLEANUP_GUARD \
+ ACE_OS_Recursive_Thread_Mutex_Guard ace_tss_cleanup_guard__ (*(ACE_recursive_thread_mutex_t *) \
+ ACE_OS_Object_Manager::preallocated_object[ \
+ ACE_OS_Object_Manager::ACE_TSS_CLEANUP_LOCK]);
+
+// used in Thread
+# define ACE_TSS_BASE_GUARD \
+ ACE_OS_Recursive_Thread_Mutex_Guard ace_tss_base_guard__ (*(ACE_recursive_thread_mutex_t *) \
+ ACE_OS_Object_Manager::preallocated_object[ \
+ ACE_OS_Object_Manager::ACE_TSS_BASE_LOCK]);
+
+#else /* ! ACE_MT_SAFE */
+# define ACE_OS_GUARD
+# define ACE_TSS_CLEANUP_GUARD
+# define ACE_TSS_BASE_GUARD
+#endif /* ! ACE_MT_SAFE */
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_Thread.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_THREAD_H */
diff --git a/ACE/ace/OS_NS_Thread.inl b/ACE/ace/OS_NS_Thread.inl
new file mode 100644
index 00000000000..d4bba743c56
--- /dev/null
+++ b/ACE/ace/OS_NS_Thread.inl
@@ -0,0 +1,3636 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_macros.h"
+// for timespec_t, perhaps move it to os_time.h
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_sys_mman.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_errno.h"
+
+#if defined (ACE_USES_FIFO_SEM)
+# include "ace/OS_NS_sys_stat.h"
+# include "ace/OS_NS_sys_select.h"
+# include "ace/OS_NS_fcntl.h"
+# include "ace/Handle_Set.h"
+# endif /* ACE_USES_FIFO_SEM */
+
+#if defined (ACE_HAS_PRIOCNTL)
+# include /**/ <sys/priocntl.h>
+#endif /* ACE_HAS_PRIOCNTL */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/*****************************************************************************/
+
+#if defined (ACE_LACKS_COND_T) && defined (ACE_HAS_THREADS)
+ACE_INLINE long
+ACE_cond_t::waiters (void) const
+{
+ return this->waiters_;
+}
+#endif /* ACE_LACKS_COND_T && ACE_HAS_THREADS */
+
+/*****************************************************************************/
+
+#if defined (ACE_HAS_TSS_EMULATION)
+
+# if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ACE_INLINE
+void **&
+ACE_TSS_Emulation::tss_base ()
+{
+# if defined (ACE_HAS_VXTHREADS)
+ int &spare = taskIdCurrent->ACE_VXWORKS_SPARE;
+ return reinterpret_cast <void **&> (spare);
+# else
+ // Uh oh.
+ ACE_NOTSUP_RETURN (0);
+# endif /* ACE_HAS_VXTHREADS */
+}
+# endif /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+ACE_INLINE
+ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
+ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key)
+{
+ ACE_KEY_INDEX (key_index, key);
+ return tss_destructor_ [key_index];
+}
+
+ACE_INLINE
+void
+ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key,
+ ACE_TSS_DESTRUCTOR destructor)
+{
+ ACE_KEY_INDEX (key_index, key);
+ tss_destructor_ [key_index] = destructor;
+}
+
+ACE_INLINE
+void *&
+ACE_TSS_Emulation::ts_object (const ACE_thread_key_t key)
+{
+ ACE_KEY_INDEX (key_index, key);
+
+# if defined (ACE_HAS_VXTHREADS)
+ /* If someone wants tss_base make sure they get one. This
+ gets used if someone spawns a VxWorks task directly, not
+ through ACE. The allocated array will never be deleted! */
+ if (0 == taskIdCurrent->ACE_VXWORKS_SPARE)
+ {
+ taskIdCurrent->ACE_VXWORKS_SPARE =
+ reinterpret_cast<int> (new void *[ACE_TSS_THREAD_KEYS_MAX]);
+
+ // Zero the entire TSS array. Do it manually instead of using
+ // memset, for optimum speed. Though, memset may be faster :-)
+ void **tss_base_p =
+ reinterpret_cast<void **> (taskIdCurrent->ACE_VXWORKS_SPARE);
+ for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
+ {
+ *tss_base_p = 0;
+ }
+ }
+# endif /* ACE_HAS_VXTHREADS */
+
+ return tss_base ()[key_index];
+}
+
+#endif /* ACE_HAS_TSS_EMULATION */
+
+/*****************************************************************************/
+
+ACE_INLINE int
+ACE_OS::thr_equal (ACE_thread_t t1, ACE_thread_t t2)
+{
+#if defined (ACE_HAS_PTHREADS)
+# if defined (pthread_equal)
+ // If it's a macro we can't say "pthread_equal"...
+ return pthread_equal (t1, t2);
+# else
+ return pthread_equal (t1, t2);
+# endif /* pthread_equal */
+#else /* For both STHREADS and WTHREADS... */
+ // Hum, Do we need to treat WTHREAD differently?
+ // levine 13 oct 98 % I don't think so, ACE_thread_t is a DWORD.
+ return t1 == t2;
+#endif /* ACE_HAS_PTHREADS */
+}
+
+#if !defined (ACE_LACKS_COND_T)
+// NOTE: The ACE_OS::cond_* functions for Unix platforms are defined
+// here because the ACE_OS::sema_* functions below need them.
+// However, ACE_WIN32 and VXWORKS define the ACE_OS::cond_* functions
+// using the ACE_OS::sema_* functions. So, they are defined in OS.cpp.
+
+ACE_INLINE int
+ACE_OS::condattr_destroy (ACE_condattr_t &attributes)
+{
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+
+ pthread_condattr_destroy (&attributes);
+
+# elif defined (ACE_HAS_STHREADS)
+ attributes.type = 0;
+
+# endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS */
+ return 0;
+# else
+ ACE_UNUSED_ARG (attributes);
+ return 0;
+# endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::condattr_init (ACE_condattr_t &attributes,
+ int type)
+{
+ ACE_UNUSED_ARG (type);
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result = -1;
+
+# if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
+ /* Tests show that VxWorks 6.x pthread lib does not only
+ * require zeroing of mutex/condition objects to function correctly
+ * but also of the attribute objects.
+ */
+ ACE_OS::memset (&attributes, 0, sizeof (attributes));
+# endif
+ if (
+ ACE_ADAPT_RETVAL (pthread_condattr_init (&attributes), result) == 0
+# if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)
+ && ACE_ADAPT_RETVAL (pthread_condattr_setpshared (&attributes, type),
+ result) == 0
+# endif /* _POSIX_THREAD_PROCESS_SHARED && ! ACE_LACKS_CONDATTR_PSHARED */
+ )
+ result = 0;
+ else
+ result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
+
+ return result;
+# elif defined (ACE_HAS_STHREADS)
+ attributes.type = type;
+
+ return 0;
+
+# else
+ ACE_UNUSED_ARG (attributes);
+ ACE_UNUSED_ARG (type);
+ ACE_NOTSUP_RETURN (-1);
+
+# endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS */
+
+# else
+ ACE_UNUSED_ARG (attributes);
+ ACE_UNUSED_ARG (type);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::cond_broadcast (ACE_cond_t *cv)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_broadcast");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_broadcast (cv),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_broadcast (cv),
+ result),
+ int, -1);
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::cond_destroy (ACE_cond_t *cv)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_destroy");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_destroy (cv), result), int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_destroy (cv), result), int, -1);
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::cond_init (ACE_cond_t *cv,
+ ACE_condattr_t &attributes,
+ const char *name,
+ void *arg)
+{
+ // ACE_OS_TRACE ("ACE_OS::cond_init");
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result = -1;
+
+# if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
+ /* VxWorks 6.x API reference states:
+ * If the memory for the condition variable object has been allocated
+ * dynamically, it is a good policy to always zero out the
+ * block of memory so as to avoid spurious EBUSY return code
+ * when calling this routine.
+ */
+ ACE_OS::memset (cv, 0, sizeof (*cv));
+# endif
+
+ if (ACE_ADAPT_RETVAL (pthread_cond_init (cv, &attributes), result) == 0)
+ result = 0;
+ else
+ result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
+
+ return result;
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_init (cv,
+ attributes.type,
+ arg),
+ result),
+ int, -1);
+# endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_UNUSED_ARG (attributes);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::cond_init (ACE_cond_t *cv,
+ ACE_condattr_t &attributes,
+ const wchar_t *name,
+ void *arg)
+{
+ return ACE_OS::cond_init (cv, attributes, ACE_Wide_To_Ascii (name).char_rep (), arg);
+}
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
+{
+ return ACE_OS::cond_init (cv, type, ACE_Wide_To_Ascii (name).char_rep (), arg);
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::cond_signal (ACE_cond_t *cv)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_signal");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_signal (cv), result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_signal (cv), result), int, -1);
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::cond_wait (ACE_cond_t *cv,
+ ACE_mutex_t *external_mutex)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_wait");
+# if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_wait (cv, external_mutex), result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_wait (cv, external_mutex), result),
+ int, -1);
+# endif /* ACE_HAS_PTHREADS */
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_UNUSED_ARG (external_mutex);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::cond_timedwait (ACE_cond_t *cv,
+ ACE_mutex_t *external_mutex,
+ ACE_Time_Value *timeout)
+{
+ ACE_OS_TRACE ("ACE_OS::cond_timedwait");
+# if defined (ACE_HAS_THREADS)
+ int result;
+ timespec_t ts;
+
+ if (timeout != 0)
+ ts = *timeout; // Calls ACE_Time_Value::operator timespec_t().
+
+# if defined (ACE_HAS_PTHREADS)
+
+ ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0
+ ? pthread_cond_wait (cv, external_mutex)
+ : pthread_cond_timedwait (cv, external_mutex,
+ (ACE_TIMESPEC_PTR) &ts),
+ result),
+ int, -1, result);
+ // We need to adjust this to make the POSIX and Solaris return
+ // values consistent. EAGAIN is from Pthreads DRAFT4 (HP-UX 10.20 and down)
+ if (result == -1 &&
+ (errno == ETIMEDOUT || errno == EAGAIN))
+ errno = ETIME;
+
+# elif defined (ACE_HAS_STHREADS)
+ ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0
+ ? ::cond_wait (cv, external_mutex)
+ : ::cond_timedwait (cv,
+ external_mutex,
+ (timestruc_t*)&ts),
+ result),
+ int, -1, result);
+# endif /* ACE_HAS_STHREADS */
+ if (timeout != 0)
+ timeout->set (ts); // Update the time value before returning.
+
+ return result;
+# else
+ ACE_UNUSED_ARG (cv);
+ ACE_UNUSED_ARG (external_mutex);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_THREADS */
+}
+#endif /* !ACE_LACKS_COND_T */
+
+ACE_INLINE int
+ACE_OS::mutex_lock (ACE_mutex_t *m,
+ const ACE_Time_Value *timeout)
+{
+ return timeout == 0 ? ACE_OS::mutex_lock (m) : ACE_OS::mutex_lock (m, *timeout);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::event_init (ACE_event_t *event,
+ int manual_reset,
+ int initial_state,
+ int type,
+ const wchar_t *name,
+ void *arg,
+ LPSECURITY_ATTRIBUTES sa)
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (arg);
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+ *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ manual_reset,
+ initial_state,
+ name);
+ if (*event == 0)
+ ACE_FAIL_RETURN (-1);
+
+ return 0;
+#else /* ACE_WIN32 */
+ return ACE_OS::event_init (event,
+ manual_reset,
+ initial_state,
+ type,
+ ACE_Wide_To_Ascii (name).char_rep (),
+ arg,
+ sa);
+#endif /* ACE_WIN32 */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE long
+ACE_OS::priority_control (ACE_idtype_t idtype, ACE_id_t identifier, int cmd, void *arg)
+{
+ ACE_OS_TRACE ("ACE_OS::priority_control");
+#if defined (ACE_HAS_PRIOCNTL)
+ ACE_OSCALL_RETURN (priocntl (idtype, identifier, cmd, static_cast<caddr_t> (arg)),
+ long, -1);
+#else /* ! ACE_HAS_PRIOCNTL*/
+ ACE_UNUSED_ARG (idtype);
+ ACE_UNUSED_ARG (identifier);
+ ACE_UNUSED_ARG (cmd);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ! ACE_HAS_PRIOCNTL*/
+}
+
+// This method is used to prepare the recursive mutex for releasing
+// when waiting on a condition variable. If the platform doesn't have
+// native recursive mutex and condition variable support, then ACE needs
+// to save the recursion state around the wait and also ensure that the
+// wait and lock release are atomic. recursive_mutex_cond_relock()
+// is the inverse of this method.
+ACE_INLINE int
+ACE_OS::recursive_mutex_cond_unlock (ACE_recursive_thread_mutex_t *m,
+ ACE_recursive_mutex_state &state)
+{
+#if defined (ACE_HAS_THREADS)
+ ACE_OS_TRACE ("ACE_OS::recursive_mutex_cond_unlock");
+# if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ // Windows need special handling since it has recursive mutexes, but
+ // does not integrate them into a condition variable.
+# if defined (ACE_WIN32)
+ // For Windows, the OS takes care of the mutex and its recursion. We just
+ // need to release the lock one fewer times than this thread has acquired
+ // it. Remember how many times, and reacquire it that many more times when
+ // the condition is signaled.
+ //
+ // For WinCE, the situation is a bit trickier. CE doesn't have
+ // RecursionCount, and LockCount has changed semantics over time.
+ // In CE 3 (and maybe 4?) LockCount is not an indicator of recursion;
+ // instead, see when it's unlocked by watching the OwnerThread, which will
+ // change to something other than the current thread when it's been
+ // unlocked "enough" times. Note that checking for 0 (unlocked) is not
+ // sufficient. Another thread may acquire the lock between our unlock and
+ // checking the OwnerThread. So grab our thread ID value first, then
+ // compare to it in the loop condition. NOTE - the problem with this
+ // scheme is that we really want to unlock the mutex one _less_ times than
+ // required to release it for another thread to acquire. With CE 5 we
+ // can do this by watching LockCount alone. I _think_ it can be done by
+ // watching LockCount on CE 4 as well (though its meaning is different),
+ // but I'm leary of changing this code since a user reported success
+ // with it.
+ //
+ // We're using undocumented fields in the CRITICAL_SECTION structure
+ // and they've been known to change across Windows variants and versions./
+ // So be careful if you need to change these - there may be other
+ // Windows variants that depend on existing values and limits.
+# if defined (ACE_HAS_WINCE) && (UNDER_CE < 500)
+ ACE_thread_t me = ACE_OS::thr_self ();
+# endif /* ACE_HAS_WINCE && CE 4 or earlier */
+
+ state.relock_count_ = 0;
+ while (
+# if !defined (ACE_HAS_WINCE)
+ m->LockCount > 0 && m->RecursionCount > 1
+# else
+ // WinCE doesn't have RecursionCount and the LockCount semantic
+ // has changed between versions; pre-Mobile 5 the LockCount
+ // was 0-indexed, and Mobile 5 has it 1-indexed.
+# if (UNDER_CE < 500)
+ m->LockCount > 0 && m->OwnerThread == (HANDLE)me
+# else
+ m->LockCount > 1
+# endif /* UNDER_CE < 500 */
+# endif /* ACE_HAS_WINCE */
+ )
+ {
+ // This may fail if the current thread doesn't own the mutex. If it
+ // does fail, it'll be on the first try, so don't worry about resetting
+ // the state.
+ if (ACE_OS::recursive_mutex_unlock (m) == -1)
+ return -1;
+ ++state.relock_count_;
+ }
+# else /* not ACE_WIN32 */
+ // prevent warnings for unused variables
+ ACE_UNUSED_ARG (state);
+ ACE_UNUSED_ARG (m);
+# endif /* ACE_WIN32 */
+ return 0;
+# else /* ACE_HAS_RECURSIVE_MUTEXES */
+ // For platforms without recursive mutexes, we obtain the nesting mutex
+ // to gain control over the mutex internals. Then set the internals to say
+ // the mutex is available. If there are waiters, signal the condition
+ // to notify them (this is mostly like the recursive_mutex_unlock() method).
+ // Then, return with the nesting mutex still held. The condition wait
+ // will release it atomically, allowing mutex waiters to continue.
+ // Note that this arrangement relies on the fact that on return from
+ // the condition wait, this thread will again own the nesting mutex
+ // and can either set the mutex internals directly or get in line for
+ // the mutex... this part is handled in recursive_mutex_cond_relock().
+ if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
+ return -1;
+
+# if !defined (ACE_NDEBUG)
+ if (m->nesting_level_ == 0
+ || ACE_OS::thr_equal (ACE_OS::thr_self (), m->owner_id_) == 0)
+ {
+ ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
+ errno = EINVAL;
+ return -1;
+ }
+# endif /* ACE_NDEBUG */
+
+ // To make error recovery a bit easier, signal the condition now. Any
+ // waiter won't regain control until the mutex is released, which won't
+ // be until the caller returns and does the wait on the condition.
+ if (ACE_OS::cond_signal (&m->lock_available_) == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
+ return -1;
+ }
+
+ // Ok, the nesting_mutex_ lock is still held, the condition has been
+ // signaled... reset the nesting info and return _WITH_ the lock
+ // held. The lock will be released when the condition waits, in the
+ // caller.
+ state.nesting_level_ = m->nesting_level_;
+ state.owner_id_ = m->owner_id_;
+ m->nesting_level_ = 0;
+ m->owner_id_ = ACE_OS::NULL_thread;
+ return 0;
+# endif /* ACE_HAS_RECURSIVE_MUTEXES */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (state);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+
+// This method is called after waiting on a condition variable when a
+// recursive mutex must be reacquired. If the platform doesn't natively
+// integrate recursive mutexes and condition variables, it's taken care
+// of here (inverse of ACE_OS::recursive_mutex_cond_unlock).
+ACE_INLINE void
+ACE_OS::recursive_mutex_cond_relock (ACE_recursive_thread_mutex_t *m,
+ ACE_recursive_mutex_state &state)
+{
+#if defined (ACE_HAS_THREADS)
+ ACE_OS_TRACE ("ACE_OS::recursive_mutex_cond_relock");
+# if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ // Windows need special handling since it has recursive mutexes, but
+ // does not integrate them into a condition variable.
+ // On entry, the OS has already reacquired the lock for us. Just
+ // reacquire it the proper number of times so the recursion is the same as
+ // before waiting on the condition.
+# if defined (ACE_WIN32)
+ while (state.relock_count_ > 0)
+ {
+ ACE_OS::recursive_mutex_lock (m);
+ --state.relock_count_;
+ }
+ return;
+# else /* not ACE_WIN32 */
+ // prevent warnings for unused variables
+ ACE_UNUSED_ARG (state);
+ ACE_UNUSED_ARG (m);
+
+# endif /* ACE_WIN32 */
+# else
+ // Without recursive mutex support, it's somewhat trickier. On entry,
+ // the current thread holds the nesting_mutex_, but another thread may
+ // still be holding the ACE_recursive_mutex_t. If so, mimic the code
+ // in ACE_OS::recursive_mutex_lock that waits to acquire the mutex.
+ // After acquiring it, restore the nesting counts and release the
+ // nesting mutex. This will restore the conditions to what they were
+ // before calling ACE_OS::recursive_mutex_cond_unlock().
+ while (m->nesting_level_ > 0)
+ ACE_OS::cond_wait (&m->lock_available_, &m->nesting_mutex_);
+
+ // At this point, we still have nesting_mutex_ and the mutex is free.
+ m->nesting_level_ = state.nesting_level_;
+ m->owner_id_ = state.owner_id_;
+ ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
+ return;
+# endif /* ACE_HAS_RECURSIVE_MUTEXES */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (state);
+ return;
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m)
+{
+#if defined (ACE_HAS_THREADS)
+#if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ return ACE_OS::thread_mutex_destroy (m);
+#else
+ if (ACE_OS::thread_mutex_destroy (&m->nesting_mutex_) == -1)
+ return -1;
+ else if (ACE_OS::cond_destroy (&m->lock_available_) == -1)
+ return -1;
+ else
+ return 0;
+#endif /* ACE_HAS_RECURSIVE_MUTEXES */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::recursive_mutex_init (ACE_recursive_thread_mutex_t *m,
+ const ACE_TCHAR *name,
+ ACE_mutexattr_t *arg,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_UNUSED_ARG (sa);
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_RECURSIVE_MUTEXES)
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ return ACE_OS::thread_mutex_init (m, PTHREAD_MUTEX_RECURSIVE, name, arg);
+# else
+ return ACE_OS::thread_mutex_init (m, 0, name, arg);
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+# else
+ if (ACE_OS::thread_mutex_init (&m->nesting_mutex_, 0, name, arg) == -1)
+ return -1;
+ else if (ACE_OS::cond_init (&m->lock_available_,
+ (short) USYNC_THREAD,
+ name,
+ 0) == -1)
+ return -1;
+ else
+ {
+ m->nesting_level_ = 0;
+ m->owner_id_ = ACE_OS::NULL_thread;
+ return 0;
+ }
+# endif /* ACE_HAS_RECURSIVE_MUTEXES */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m)
+{
+#if defined (ACE_HAS_THREADS)
+#if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ return ACE_OS::thread_mutex_lock (m);
+#else
+ ACE_thread_t const t_id = ACE_OS::thr_self ();
+ int result = 0;
+
+ // Acquire the guard.
+ if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
+ result = -1;
+ else
+ {
+ // If there's no contention, just grab the lock immediately
+ // (since this is the common case we'll optimize for it).
+ if (m->nesting_level_ == 0)
+ m->owner_id_ = t_id;
+ // If we already own the lock, then increment the nesting level
+ // and return.
+ else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
+ {
+ // Wait until the nesting level has dropped to zero, at
+ // which point we can acquire the lock.
+ while (m->nesting_level_ > 0)
+ ACE_OS::cond_wait (&m->lock_available_,
+ &m->nesting_mutex_);
+
+ // At this point the nesting_mutex_ is held...
+ m->owner_id_ = t_id;
+ }
+
+ // At this point, we can safely increment the nesting_level_ no
+ // matter how we got here!
+ ++m->nesting_level_;
+ }
+
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
+ }
+ return result;
+#endif /* ACE_HAS_RECURSIVE_MUTEXES */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
+ const ACE_Time_Value &timeout)
+{
+#if defined (ACE_HAS_THREADS)
+#if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ return ACE_OS::thread_mutex_lock (m, timeout);
+#else
+ ACE_thread_t t_id = ACE_OS::thr_self ();
+ int result = 0;
+
+ // Try to acquire the guard.
+ if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_, timeout) == -1)
+ result = -1;
+ else
+ {
+ // If there's no contention, just grab the lock immediately
+ // (since this is the common case we'll optimize for it).
+ if (m->nesting_level_ == 0)
+ m->owner_id_ = t_id;
+ // If we already own the lock, then increment the nesting level
+ // and return.
+ else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
+ {
+ // Wait until the nesting level has dropped to zero, at
+ // which point we can acquire the lock.
+ while (m->nesting_level_ > 0)
+ {
+ result = ACE_OS::cond_timedwait (&m->lock_available_,
+ &m->nesting_mutex_,
+ const_cast <ACE_Time_Value *> (&timeout));
+
+ // The mutex is reacquired even in the case of a timeout
+ // release the mutex to prevent a deadlock
+ if (result == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
+
+ return result;
+ }
+ }
+
+ // At this point the nesting_mutex_ is held...
+ m->owner_id_ = t_id;
+ }
+
+ // At this point, we can safely increment the nesting_level_ no
+ // matter how we got here!
+ m->nesting_level_++;
+
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
+ }
+ return result;
+#endif /* ACE_HAS_RECURSIVE_MUTEXES */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
+ const ACE_Time_Value *timeout)
+{
+ return timeout == 0
+ ? ACE_OS::recursive_mutex_lock (m)
+ : ACE_OS::recursive_mutex_lock (m, *timeout);
+}
+
+ACE_INLINE int
+ACE_OS::recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m)
+{
+#if defined (ACE_HAS_THREADS)
+#if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ return ACE_OS::thread_mutex_trylock (m);
+#else
+ ACE_thread_t t_id = ACE_OS::thr_self ();
+ int result = 0;
+
+ // Acquire the guard.
+ if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
+ result = -1;
+ else
+ {
+ // If there's no contention, just grab the lock immediately.
+ if (m->nesting_level_ == 0)
+ {
+ m->owner_id_ = t_id;
+ m->nesting_level_ = 1;
+ }
+ // If we already own the lock, then increment the nesting level
+ // and proceed.
+ else if (ACE_OS::thr_equal (t_id, m->owner_id_))
+ m->nesting_level_++;
+ else
+ {
+ errno = EBUSY;
+ result = -1;
+ }
+ }
+
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
+ }
+ return result;
+#endif /* ACE_HAS_RECURSIVE_MUTEXES */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m)
+{
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ return ACE_OS::thread_mutex_unlock (m);
+# else
+ ACE_OS_TRACE ("ACE_OS::recursive_mutex_unlock");
+# if !defined (ACE_NDEBUG)
+ ACE_thread_t t_id = ACE_OS::thr_self ();
+# endif /* ACE_NDEBUG */
+ int result = 0;
+
+ if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
+ result = -1;
+ else
+ {
+# if !defined (ACE_NDEBUG)
+ if (m->nesting_level_ == 0
+ || ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
+{
+ errno = EINVAL;
+ result = -1;
+}
+ else
+# endif /* ACE_NDEBUG */
+{
+ m->nesting_level_--;
+ if (m->nesting_level_ == 0)
+ {
+ // This may not be strictly necessary, but it does put
+ // the mutex into a known state...
+ m->owner_id_ = ACE_OS::NULL_thread;
+
+ // Inform a waiter that the lock is free.
+ if (ACE_OS::cond_signal (&m->lock_available_) == -1)
+ result = -1;
+ }
+}
+ }
+
+{
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
+}
+ return result;
+# endif /* ACE_HAS_RECURSIVE_MUTEXES */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::rw_rdlock (ACE_rwlock_t *rw)
+{
+ ACE_OS_TRACE ("ACE_OS::rw_rdlock");
+#if defined (ACE_HAS_THREADS)
+# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_rdlock (rw),
+ result),
+ int, -1);
+# else /* Solaris */
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_rdlock (rw), result), int, -1);
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+# else /* NT, POSIX, and VxWorks don't support this natively. */
+# if defined (ACE_HAS_PTHREADS)
+ ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
+# endif /* ACE_HAS_PTHREADS */
+ int result = 0;
+ if (ACE_OS::mutex_lock (&rw->lock_) == -1)
+ result = -1; // -1 means didn't get the mutex.
+ else
+ {
+ // Give preference to writers who are waiting.
+ while (rw->ref_count_ < 0 || rw->num_waiting_writers_ > 0)
+ {
+ rw->num_waiting_readers_++;
+ if (ACE_OS::cond_wait (&rw->waiting_readers_, &rw->lock_) == -1)
+ {
+ result = -2; // -2 means that we need to release the mutex.
+ break;
+ }
+ rw->num_waiting_readers_--;
+ }
+ }
+ if (result == 0)
+ rw->ref_count_++;
+ if (result != -1)
+ ACE_OS::mutex_unlock (&rw->lock_);
+# if defined (ACE_HAS_PTHREADS)
+ ACE_PTHREAD_CLEANUP_POP (0);
+# endif /* defined (ACE_HAS_PTHREADS) */
+ return 0;
+# endif /* ! ACE_LACKS_RWLOCK_T */
+#else
+ ACE_UNUSED_ARG (rw);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::rw_tryrdlock (ACE_rwlock_t *rw)
+{
+ ACE_OS_TRACE ("ACE_OS::rw_tryrdlock");
+#if defined (ACE_HAS_THREADS)
+# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_tryrdlock (rw),
+ result),
+ int, -1);
+# else /* Solaris */
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_tryrdlock (rw), result), int, -1);
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+# else /* NT, POSIX, and VxWorks don't support this natively. */
+ int result = -1;
+
+ if (ACE_OS::mutex_lock (&rw->lock_) != -1)
+ {
+ ACE_Errno_Guard error (errno);
+
+ if (rw->ref_count_ == -1 || rw->num_waiting_writers_ > 0)
+ {
+ error = EBUSY;
+ result = -1;
+ }
+ else
+ {
+ rw->ref_count_++;
+ result = 0;
+ }
+
+ ACE_OS::mutex_unlock (&rw->lock_);
+ }
+ return result;
+# endif /* ! ACE_LACKS_RWLOCK_T */
+#else
+ ACE_UNUSED_ARG (rw);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::rw_trywrlock (ACE_rwlock_t *rw)
+{
+ ACE_OS_TRACE ("ACE_OS::rw_trywrlock");
+#if defined (ACE_HAS_THREADS)
+# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw),
+ result),
+ int, -1);
+# else /* Solaris */
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_trywrlock (rw), result), int, -1);
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+# else /* NT, POSIX, and VxWorks don't support this natively. */
+ int result = -1;
+
+ if (ACE_OS::mutex_lock (&rw->lock_) != -1)
+ {
+ ACE_Errno_Guard error (errno);
+
+ if (rw->ref_count_ != 0)
+ {
+ error = EBUSY;
+ result = -1;
+ }
+ else
+ {
+ rw->ref_count_ = -1;
+ result = 0;
+ }
+
+ ACE_OS::mutex_unlock (&rw->lock_);
+ }
+ return result;
+# endif /* ! ACE_LACKS_RWLOCK_T */
+#else
+ ACE_UNUSED_ARG (rw);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+// Note that the caller of this method *must* already possess this
+// lock as a read lock.
+// return {-1 and no errno set means: error,
+// -1 and errno==EBUSY set means: could not upgrade,
+// 0 means: upgraded successfully}
+
+ACE_INLINE int
+ACE_OS::rw_trywrlock_upgrade (ACE_rwlock_t *rw)
+{
+ ACE_OS_TRACE ("ACE_OS::rw_trywrlock_upgrade");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ // This will probably result in -1, EDEADLK, at least on HP-UX, but let it
+ // go - it's a more descriptive error than ENOTSUP.
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw),
+ result),
+ int, -1);
+# elif !defined (ACE_LACKS_RWLOCK_T)
+ // Some native rwlocks, such as those on Solaris, don't
+ // support the upgrade feature . . .
+ ACE_UNUSED_ARG (rw);
+ ACE_NOTSUP_RETURN (-1);
+# else /* NT, POSIX, and VxWorks don't support this natively. */
+ // The ACE rwlock emulation does support upgrade . . .
+ int result = 0;
+
+# if defined (ACE_HAS_PTHREADS)
+ ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
+# endif /* defined (ACE_HAS_PTHREADS) */
+
+ if (ACE_OS::mutex_lock (&rw->lock_) == -1)
+ return -1;
+ // -1 means didn't get the mutex, error
+ else if (rw->important_writer_)
+ // an other reader upgrades already
+ {
+ result = -1;
+ errno = EBUSY;
+ }
+ else
+ {
+ while (rw->ref_count_ > 1) // wait until only I am left
+ {
+ rw->num_waiting_writers_++; // prohibit any more readers
+ rw->important_writer_ = 1;
+
+ if (ACE_OS::cond_wait (&rw->waiting_important_writer_, &rw->lock_) == -1)
+ {
+ result = -1;
+ // we know that we have the lock again, we have this guarantee,
+ // but something went wrong
+ }
+ rw->important_writer_ = 0;
+ rw->num_waiting_writers_--;
+ }
+ if (result == 0)
+ {
+ // nothing bad happend
+ rw->ref_count_ = -1;
+ // now I am a writer
+ // everything is O.K.
+ }
+ }
+
+ ACE_OS::mutex_unlock (&rw->lock_);
+
+# if defined (ACE_HAS_PTHREADS)
+ ACE_PTHREAD_CLEANUP_POP (0);
+# endif /* defined (ACE_HAS_PTHREADS) */
+
+ return result;
+
+# endif /* ! ACE_LACKS_RWLOCK_T */
+#else
+ ACE_UNUSED_ARG (rw);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::rw_unlock (ACE_rwlock_t *rw)
+{
+ ACE_OS_TRACE ("ACE_OS::rw_unlock");
+#if defined (ACE_HAS_THREADS)
+# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_unlock (rw),
+ result),
+ int, -1);
+# else /* Solaris */
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_unlock (rw), result), int, -1);
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+# else /* NT, POSIX, and VxWorks don't support this natively. */
+ if (ACE_OS::mutex_lock (&rw->lock_) == -1)
+ return -1;
+
+ if (rw->ref_count_ > 0) // Releasing a reader.
+ rw->ref_count_--;
+ else if (rw->ref_count_ == -1) // Releasing a writer.
+ rw->ref_count_ = 0;
+ else
+ {
+ (void) ACE_OS::mutex_unlock (&rw->lock_);
+ return -1; // @@ ACE_ASSERT (!"count should not be 0!\n");
+ }
+
+ int result = 0;
+ ACE_Errno_Guard error (errno);
+
+ if (rw->important_writer_ && rw->ref_count_ == 1)
+ // only the reader requesting to upgrade its lock is left over.
+ {
+ result = ACE_OS::cond_signal (&rw->waiting_important_writer_);
+ error = errno;
+ }
+ else if (rw->num_waiting_writers_ > 0 && rw->ref_count_ == 0)
+ // give preference to writers over readers...
+ {
+ result = ACE_OS::cond_signal (&rw->waiting_writers_);
+ error = errno;
+ }
+ else if (rw->num_waiting_readers_ > 0 && rw->num_waiting_writers_ == 0)
+ {
+ result = ACE_OS::cond_broadcast (&rw->waiting_readers_);
+ error = errno;
+ }
+
+ (void) ACE_OS::mutex_unlock (&rw->lock_);
+ return result;
+# endif /* ! ace_lacks_rwlock_t */
+#else
+ ACE_UNUSED_ARG (rw);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ace_has_threads */
+}
+
+ACE_INLINE int
+ACE_OS::rw_wrlock (ACE_rwlock_t *rw)
+{
+ ACE_OS_TRACE ("ACE_OS::rw_wrlock");
+#if defined (ACE_HAS_THREADS)
+# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_wrlock (rw),
+ result),
+ int, -1);
+# else /* Solaris */
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_wrlock (rw), result), int, -1);
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+# else /* NT, POSIX, and VxWorks don't support this natively. */
+# if defined (ACE_HAS_PTHREADS)
+ ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
+# endif /* defined (ACE_HAS_PTHREADS) */
+ int result = 0;
+
+ if (ACE_OS::mutex_lock (&rw->lock_) == -1)
+ result = -1; // -1 means didn't get the mutex.
+ else
+ {
+ while (rw->ref_count_ != 0)
+ {
+ rw->num_waiting_writers_++;
+
+ if (ACE_OS::cond_wait (&rw->waiting_writers_, &rw->lock_) == -1)
+ {
+ result = -2; // -2 means we need to release the mutex.
+ break;
+ }
+
+ rw->num_waiting_writers_--;
+ }
+ }
+ if (result == 0)
+ rw->ref_count_ = -1;
+ if (result != -1)
+ ACE_OS::mutex_unlock (&rw->lock_);
+# if defined (ACE_HAS_PTHREADS)
+ ACE_PTHREAD_CLEANUP_POP (0);
+# endif /* defined (ACE_HAS_PTHREADS) */
+ return 0;
+# endif /* ! ACE_LACKS_RWLOCK_T */
+#else
+ ACE_UNUSED_ARG (rw);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::rwlock_destroy (ACE_rwlock_t *rw)
+{
+ ACE_OS_TRACE ("ACE_OS::rwlock_destroy");
+#if defined (ACE_HAS_THREADS)
+# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_destroy (rw),
+ result),
+ int, -1);
+# else /* Solaris */
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_destroy (rw), result), int, -1);
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+# else /* NT, POSIX, and VxWorks don't support this natively. */
+ ACE_OS::mutex_destroy (&rw->lock_);
+ ACE_OS::cond_destroy (&rw->waiting_readers_);
+ ACE_OS::cond_destroy (&rw->waiting_important_writer_);
+ return ACE_OS::cond_destroy (&rw->waiting_writers_);
+# endif /* ACE_HAS_STHREADS && !defined (ACE_LACKS_RWLOCK_T) */
+#else
+ ACE_UNUSED_ARG (rw);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+#if defined (ACE_HAS_THREADS) && (!defined (ACE_LACKS_RWLOCK_T) || \
+ defined (ACE_HAS_PTHREADS_UNIX98_EXT))
+ACE_INLINE int
+ACE_OS::rwlock_init (ACE_rwlock_t *rw,
+ int type,
+ const ACE_TCHAR *name,
+ void *arg)
+{
+ // ACE_OS_TRACE ("ACE_OS::rwlock_init");
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+
+ int status;
+ pthread_rwlockattr_t attr;
+ pthread_rwlockattr_init (&attr);
+# if !defined (ACE_LACKS_RWLOCKATTR_PSHARED)
+ pthread_rwlockattr_setpshared (&attr, (type == USYNC_THREAD ?
+ PTHREAD_PROCESS_PRIVATE :
+ PTHREAD_PROCESS_SHARED));
+# else
+ ACE_UNUSED_ARG (type);
+# endif /* !ACE_LACKS_RWLOCKATTR_PSHARED */
+ status = ACE_ADAPT_RETVAL (pthread_rwlock_init (rw, &attr), status);
+ pthread_rwlockattr_destroy (&attr);
+
+ return status;
+
+# else
+ type = type;
+ name = name;
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_init (rw, type, arg), result), int, -1);
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+}
+#endif /* ACE_HAS THREADS && !defined (ACE_LACKS_RWLOCK_T) */
+
+ACE_INLINE int
+ACE_OS::sema_destroy (ACE_sema_t *s)
+{
+ ACE_OS_TRACE ("ACE_OS::sema_destroy");
+# if defined (ACE_HAS_POSIX_SEM)
+ int result;
+# if !defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
+ ACE_OS::mutex_destroy (&s->lock_);
+ ACE_OS::cond_destroy (&s->count_nonzero_);
+# endif /* !ACE_HAS_POSIX_SEM_TIMEOUT && !ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
+# if defined (ACE_LACKS_NAMED_POSIX_SEM)
+ if (s->name_)
+ {
+ // Only destroy the semaphore if we're the ones who
+ // initialized it.
+ ACE_OSCALL (::sem_destroy (s->sema_),int, -1, result);
+ ACE_OS::shm_unlink (s->name_);
+ delete s->name_;
+ return result;
+ }
+# else
+ if (s->name_)
+ {
+ ACE_OSCALL (::sem_unlink (s->name_), int, -1, result);
+ ACE_OS::free ((void *) s->name_);
+ ACE_OSCALL_RETURN (::sem_close (s->sema_), int, -1);
+ }
+# endif /* ACE_LACKS_NAMED_POSIX_SEM */
+ else
+ {
+ ACE_OSCALL (::sem_destroy (s->sema_), int, -1, result);
+# if defined (ACE_LACKS_NAMED_POSIX_SEM)
+ if (s->new_sema_)
+# endif /* ACE_LACKS_NAMED_POSIX_SEM */
+ delete s->sema_;
+ s->sema_ = 0;
+ return result;
+ }
+# elif defined (ACE_USES_FIFO_SEM)
+ int r0 = 0;
+ if (s->name_)
+ {
+ r0 = ACE_OS::unlink (s->name_);
+ ACE_OS::free (s->name_);
+ s->name_ = 0;
+ }
+ int r1 = ACE_OS::close (s->fd_[0]); /* ignore error */
+ int r2 = ACE_OS::close (s->fd_[1]); /* ignore error */
+ return r0 != 0 || r1 != 0 || r2 != 0 ? -1 : 0;
+# elif defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_destroy (s), result), int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+ int r1 = ACE_OS::mutex_destroy (&s->lock_);
+ int r2 = ACE_OS::cond_destroy (&s->count_nonzero_);
+ return r1 != 0 || r2 != 0 ? -1 : 0;
+# elif defined (ACE_HAS_WTHREADS)
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*s), ace_result_), int, -1);
+# else /* ACE_USES_WINCE_SEMA_SIMULATION */
+ // Free up underlying objects of the simulated semaphore.
+ int r1 = ACE_OS::thread_mutex_destroy (&s->lock_);
+ int r2 = ACE_OS::event_destroy (&s->count_nonzero_);
+ return r1 != 0 || r2 != 0 ? -1 : 0;
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# elif defined (ACE_VXWORKS)
+ int result;
+ ACE_OSCALL (::semDelete (s->sema_), int, -1, result);
+ s->sema_ = 0;
+ return result;
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (s);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_POSIX_SEM */
+}
+
+// NOTE: The previous four function definitions must appear before
+// ACE_OS::sema_init ().
+
+ACE_INLINE int
+ACE_OS::sema_init (ACE_sema_t *s,
+ u_int count,
+ int type,
+ const char *name,
+ void *arg,
+ int max,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_OS_TRACE ("ACE_OS::sema_init");
+#if defined (ACE_HAS_POSIX_SEM)
+ ACE_UNUSED_ARG (max);
+ ACE_UNUSED_ARG (sa);
+
+ s->name_ = 0;
+# if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
+ ACE_UNUSED_ARG (arg);
+# else
+ int result = -1;
+
+ if (ACE_OS::mutex_init (&s->lock_, type, name,
+ (ACE_mutexattr_t *) arg) == 0
+ && ACE_OS::cond_init (&s->count_nonzero_, (short)type, name, arg) == 0
+ && ACE_OS::mutex_lock (&s->lock_) == 0)
+ {
+ if (ACE_OS::mutex_unlock (&s->lock_) == 0)
+ result = 0;
+ }
+
+ if (result == -1)
+ {
+ ACE_OS::mutex_destroy (&s->lock_);
+ ACE_OS::cond_destroy (&s->count_nonzero_);
+ return result;
+ }
+# endif /* ACE_HAS_POSIX_SEM_TIMEOUT || ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
+
+# if defined (ACE_LACKS_NAMED_POSIX_SEM)
+ s->new_sema_ = false;
+ if (type == USYNC_PROCESS)
+ {
+ // Let's see if it already exists.
+ ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
+ O_RDWR | O_CREAT | O_EXCL,
+ ACE_DEFAULT_FILE_PERMS);
+ if (fd == ACE_INVALID_HANDLE)
+ {
+ if (errno == EEXIST)
+ fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
+ O_RDWR | O_CREAT,
+ ACE_DEFAULT_FILE_PERMS);
+ else
+ return -1;
+ }
+ else
+ {
+ // We own this shared memory object! Let's set its
+ // size.
+ if (ACE_OS::ftruncate (fd,
+ sizeof (ACE_sema_t)) == -1)
+ return -1;
+ s->name_ = ACE_OS::strdup (name);
+ if (s->name_ == 0)
+ return -1;
+ }
+ if (fd == -1)
+ return -1;
+
+ s->sema_ = (sem_t *)
+ ACE_OS::mmap (0,
+ sizeof (ACE_sema_t),
+ PROT_RDWR,
+ MAP_SHARED,
+ fd,
+ 0);
+ ACE_OS::close (fd);
+ if (s->sema_ == (sem_t *) MAP_FAILED)
+ return -1;
+ if (s->name_
+ // @@ According UNIX Network Programming V2 by Stevens,
+ // sem_init() is currently not required to return zero on
+ // success, but it *does* return -1 upon failure. For
+ // this reason, check for failure by comparing to -1,
+ // instead of checking for success by comparing to zero.
+ // -Ossama
+ // Only initialize it if we're the one who created it.
+ && ::sem_init (s->sema_, type == USYNC_PROCESS, count) == -1)
+ return -1;
+ return 0;
+ }
+# else
+ if (name)
+ {
+# if defined (sun) || defined (HPUX)
+ // Solaris and HP-UX require the name to start with a slash. Solaris
+ // further requires that there be no other slashes than the first.
+ const char *last_slash = ACE_OS::strrchr (name, '/');
+ char name2[MAXPATHLEN];
+ if (0 == last_slash)
+ {
+ ACE_OS::strcpy (name2, "/");
+ ACE_OS::strcat (name2, name);
+ name = name2;
+ }
+# if defined (sun)
+ else
+ name = last_slash; // Chop off chars preceding last slash
+# endif /* sun */
+# endif /* sun || HPUX */
+
+ ACE_ALLOCATOR_RETURN (s->name_,
+ ACE_OS::strdup (name),
+ -1);
+ s->sema_ = ::sem_open (s->name_,
+ O_CREAT,
+ ACE_DEFAULT_FILE_PERMS,
+ count);
+ if (s->sema_ == (sem_t *) SEM_FAILED)
+ return -1;
+ else
+ return 0;
+ }
+# endif /* ACE_LACKS_NAMED_POSIX_SEM */
+ else
+ {
+ ACE_NEW_RETURN (s->sema_,
+ sem_t,
+ -1);
+# if defined (ACE_LACKS_NAMED_POSIX_SEM)
+ s->new_sema_ = true;
+# endif /* ACE_LACKS_NAMED_POSIX_SEM */
+ ACE_OSCALL_RETURN (::sem_init (s->sema_,
+ type != USYNC_THREAD,
+ count), int, -1);
+ }
+
+#elif defined (ACE_USES_FIFO_SEM)
+ ACE_UNUSED_ARG (arg);
+ ACE_UNUSED_ARG (max);
+ ACE_UNUSED_ARG (sa);
+ int flags = 0;
+ mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
+
+ if (type == USYNC_THREAD)
+ {
+ // Create systemwide unique name for semaphore
+ char uname[ACE_UNIQUE_NAME_LEN];
+ ACE_OS::unique_name ((const void *) s,
+ uname,
+ ACE_UNIQUE_NAME_LEN);
+ name = &uname[0];
+ }
+
+ s->name_ = 0;
+ s->fd_[0] = s->fd_[1] = ACE_INVALID_HANDLE;
+ bool creator = false;
+
+ if (ACE_OS::mkfifo (ACE_TEXT_CHAR_TO_TCHAR (name), mode) < 0)
+ {
+ if (errno != EEXIST) /* already exists OK else ERR */
+ return -1;
+ // check if this is a real FIFO, not just some other existing file
+ ACE_stat fs;
+ if (ACE_OS::stat (name, &fs))
+ return -1;
+ if (!S_ISFIFO (fs.st_mode))
+ {
+ // existing file is not a FIFO
+ errno = EEXIST;
+ return -1;
+ }
+ }
+ else
+ creator = true; // remember we created it for initialization at end
+
+ // for processshared semaphores remember who we are to be able to remove
+ // the FIFO when we're done with it
+ if (type == USYNC_PROCESS)
+ {
+ s->name_ = ACE_OS::strdup (name);
+ if (s->name_ == 0)
+ {
+ if (creator)
+ ACE_OS::unlink (name);
+ return -1;
+ }
+ }
+
+ if ((s->fd_[0] = ACE_OS::open (name, O_RDONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE
+ || (s->fd_[1] = ACE_OS::open (name, O_WRONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE)
+ return (-1);
+
+ /* turn off nonblocking for fd_[0] */
+ if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0)
+ return (-1);
+
+ flags &= ~O_NONBLOCK;
+ if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0)
+ return (-1);
+
+ //if (s->name_ && count)
+ if (creator && count)
+ {
+ char c = 1;
+ for (u_int i=0; i<count ;++i)
+ if (ACE_OS::write (s->fd_[1], &c, sizeof (char)) != 1)
+ return (-1);
+ }
+
+ // In the case of process scope semaphores we can already unlink the FIFO now that
+ // we completely set it up (the opened handles will keep it active until we close
+ // thos down). This way we're protected against unexpected crashes as far as removal
+ // is concerned.
+ // Unfortunately this does not work for processshared FIFOs since as soon as we
+ // have unlinked the semaphore no other process will be able to open it anymore.
+ if (type == USYNC_THREAD)
+ {
+ ACE_OS::unlink (name);
+ }
+
+ return (0);
+#elif defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (max);
+ ACE_UNUSED_ARG (sa);
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_init (s, count, type, arg), result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+ ACE_UNUSED_ARG (max);
+ ACE_UNUSED_ARG (sa);
+ int result = -1;
+
+ if (ACE_OS::mutex_init (&s->lock_, type, name,
+ (ACE_mutexattr_t *) arg) == 0
+ && ACE_OS::cond_init (&s->count_nonzero_, type, name, arg) == 0
+ && ACE_OS::mutex_lock (&s->lock_) == 0)
+ {
+ s->count_ = count;
+ s->waiters_ = 0;
+
+ if (ACE_OS::mutex_unlock (&s->lock_) == 0)
+ result = 0;
+ }
+
+ if (result == -1)
+ {
+ ACE_OS::mutex_destroy (&s->lock_);
+ ACE_OS::cond_destroy (&s->count_nonzero_);
+ }
+ return result;
+# elif defined (ACE_HAS_WTHREADS)
+# if ! defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (arg);
+ // Create the semaphore with its value initialized to <count> and
+ // its maximum value initialized to <max>.
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+ *s = ::CreateSemaphoreA
+ (ACE_OS::default_win32_security_attributes_r (sa, &sa_buffer, &sd_buffer),
+ count,
+ max,
+ name);
+
+ if (*s == 0)
+ ACE_FAIL_RETURN (-1);
+ /* NOTREACHED */
+ else
+ return 0;
+# else /* ACE_USES_WINCE_SEMA_SIMULATION */
+ int result = -1;
+
+ // Initialize internal object for semaphore simulation.
+ // Grab the lock as soon as possible when we initializing
+ // the semaphore count. Notice that we initialize the
+ // event object as "manually reset" so we can amortize the
+ // cost for singling/reseting the event.
+ // @@ I changed the mutex type to thread_mutex. Notice that this
+ // is basically a CriticalSection object and doesn't not has
+ // any security attribute whatsoever. However, since this
+ // semaphore implementation only works within a process, there
+ // shouldn't any security issue at all.
+ if (ACE_OS::thread_mutex_init (&s->lock_, type, name, (ACE_mutexattr_t *)arg) == 0
+ && ACE_OS::event_init (&s->count_nonzero_, 1,
+ count > 0, type, name, arg, sa) == 0
+ && ACE_OS::thread_mutex_lock (&s->lock_) == 0)
+ {
+ s->count_ = count;
+
+ if (ACE_OS::thread_mutex_unlock (&s->lock_) == 0)
+ result = 0;
+ }
+
+ // Destroy the internal objects if we didn't initialize
+ // either of them successfully. Don't bother to check
+ // for errors.
+ if (result == -1)
+ {
+ ACE_OS::thread_mutex_destroy (&s->lock_);
+ ACE_OS::event_destroy (&s->count_nonzero_);
+ }
+ return result;
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# elif defined (ACE_VXWORKS)
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_UNUSED_ARG (max);
+ ACE_UNUSED_ARG (sa);
+ s->name_ = 0;
+ s->sema_ = ::semCCreate (type, count);
+ return s->sema_ ? 0 : -1;
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (s);
+ ACE_UNUSED_ARG (count);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_UNUSED_ARG (max);
+ ACE_UNUSED_ARG (sa);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_POSIX_SEM */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::sema_init (ACE_sema_t *s,
+ u_int count,
+ int type,
+ const wchar_t *name,
+ void *arg,
+ int max,
+ LPSECURITY_ATTRIBUTES sa)
+{
+# if defined (ACE_HAS_WTHREADS)
+# if ! defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (arg);
+ // Create the semaphore with its value initialized to <count> and
+ // its maximum value initialized to <max>.
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+ *s = ::CreateSemaphoreW
+ (ACE_OS::default_win32_security_attributes_r (sa, &sa_buffer, &sd_buffer),
+ count,
+ max,
+ name);
+
+ if (*s == 0)
+ ACE_FAIL_RETURN (-1);
+ /* NOTREACHED */
+ else
+ return 0;
+# else /* ACE_USES_WINCE_SEMA_SIMULATION */
+ int result = -1;
+
+ // Initialize internal object for semaphore simulation.
+ // Grab the lock as soon as possible when we initializing
+ // the semaphore count. Notice that we initialize the
+ // event object as "manually reset" so we can amortize the
+ // cost for singling/reseting the event.
+ // @@ I changed the mutex type to thread_mutex. Notice that this
+ // is basically a CriticalSection object and doesn't not has
+ // any security attribute whatsoever. However, since this
+ // semaphore implementation only works within a process, there
+ // shouldn't any security issue at all.
+ if (ACE_OS::thread_mutex_init (&s->lock_, type, name, (ACE_mutexattr_t *)arg) == 0
+ && ACE_OS::event_init (&s->count_nonzero_, 1,
+ count > 0, type, name, arg, sa) == 0
+ && ACE_OS::thread_mutex_lock (&s->lock_) == 0)
+ {
+ s->count_ = count;
+
+ if (ACE_OS::thread_mutex_unlock (&s->lock_) == 0)
+ result = 0;
+ }
+
+ // Destroy the internal objects if we didn't initialize
+ // either of them successfully. Don't bother to check
+ // for errors.
+ if (result == -1)
+ {
+ ACE_OS::thread_mutex_destroy (&s->lock_);
+ ACE_OS::event_destroy (&s->count_nonzero_);
+ }
+ return result;
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# else /* ACE_HAS_WTHREADS */
+ // Just call the normal char version.
+ return ACE_OS::sema_init (s, count, type, ACE_Wide_To_Ascii (name).char_rep (), arg, max, sa);
+# endif /* ACE_HAS_WTHREADS */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::sema_post (ACE_sema_t *s)
+{
+ ACE_OS_TRACE ("ACE_OS::sema_post");
+# if defined (ACE_HAS_POSIX_SEM)
+# if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
+ ACE_OSCALL_RETURN (::sem_post (s->sema_), int, -1);
+# else
+ int result = -1;
+
+ if (ACE_OS::mutex_lock (&s->lock_) == 0)
+ {
+ if (::sem_post (s->sema_) == 0)
+ result = ACE_OS::cond_signal (&s->count_nonzero_);
+
+ ACE_OS::mutex_unlock (&s->lock_);
+ }
+ return result;
+# endif /* ACE_HAS_POSIX_SEM_TIMEOUT || ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
+# elif defined (ACE_USES_FIFO_SEM)
+ char c = 1;
+ if (ACE_OS::write (s->fd_[1], &c, sizeof (char)) == sizeof (char))
+ return (0);
+ return (-1);
+# elif defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_post (s), result), int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+ int result = -1;
+
+ if (ACE_OS::mutex_lock (&s->lock_) == 0)
+ {
+ // Always allow a waiter to continue if there is one.
+ if (s->waiters_ > 0)
+ result = ACE_OS::cond_signal (&s->count_nonzero_);
+ else
+ result = 0;
+
+ s->count_++;
+ ACE_OS::mutex_unlock (&s->lock_);
+ }
+ return result;
+# elif defined (ACE_HAS_WTHREADS)
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, 1, 0),
+ ace_result_),
+ int, -1);
+# else /* ACE_USES_WINCE_SEMA_SIMULATION */
+ int result = -1;
+
+ // Since we are simulating semaphores, we need to update semaphore
+ // count manually. Grab the lock to prevent race condition first.
+ if (ACE_OS::thread_mutex_lock (&s->lock_) == 0)
+ {
+ // Check the original state of event object. Single the event
+ // object in transition from semaphore not available to
+ // semaphore available.
+ if (s->count_++ <= 0)
+ result = ACE_OS::event_signal (&s->count_nonzero_);
+ else
+ result = 0;
+
+ ACE_OS::thread_mutex_unlock (&s->lock_);
+ }
+ return result;
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# elif defined (ACE_VXWORKS)
+ ACE_OSCALL_RETURN (::semGive (s->sema_), int, -1);
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (s);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_POSIX_SEM */
+}
+
+ACE_INLINE int
+ACE_OS::sema_post (ACE_sema_t *s, u_int release_count)
+{
+#if defined (ACE_WIN32) && !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ // Win32 supports this natively.
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, release_count, 0),
+ ace_result_), int, -1);
+#else
+ // On POSIX platforms we need to emulate this ourselves.
+ // @@ We can optimize on this implementation. However,
+ // the semaphore promitive on Win32 doesn't allow one
+ // to increase a semaphore to more than the count it was
+ // first initialized. Posix and solaris don't seem to have
+ // this restriction. Should we impose the restriction in
+ // our semaphore simulation?
+ for (size_t i = 0; i < release_count; i++)
+ if (ACE_OS::sema_post (s) == -1)
+ return -1;
+
+ return 0;
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_OS::sema_trywait (ACE_sema_t *s)
+{
+ ACE_OS_TRACE ("ACE_OS::sema_trywait");
+# if defined (ACE_HAS_POSIX_SEM)
+ // POSIX semaphores set errno to EAGAIN if trywait fails
+ ACE_OSCALL_RETURN (::sem_trywait (s->sema_), int, -1);
+# elif defined (ACE_USES_FIFO_SEM)
+ char c;
+ int rc, flags;
+
+ /* turn on nonblocking for s->fd_[0] */
+ if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0)
+ return (-1);
+ flags |= O_NONBLOCK;
+ if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0)
+ return (-1);
+
+ // read sets errno to EAGAIN if no input
+ rc = ACE_OS::read (s->fd_[0], &c, sizeof (char));
+
+ /* turn off nonblocking for fd_[0] */
+ if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) >= 0)
+ {
+ flags &= ~O_NONBLOCK;
+ ACE_OS::fcntl (s->fd_[0], F_SETFL, flags);
+ }
+
+ return rc == 1 ? 0 : (-1);
+# elif defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ // STHREADS semaphores set errno to EBUSY if trywait fails.
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_trywait (s),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+
+ int result = -1;
+
+ if (ACE_OS::mutex_lock (&s->lock_) == 0)
+ {
+ if (s->count_ > 0)
+ {
+ --s->count_;
+ result = 0;
+ }
+ else
+ errno = EBUSY;
+
+ ACE_OS::mutex_unlock (&s->lock_);
+ }
+ return result;
+# elif defined (ACE_HAS_WTHREADS)
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ DWORD result = ::WaitForSingleObject (*s, 0);
+
+ if (result == WAIT_OBJECT_0)
+ return 0;
+ else
+ {
+ if (result == WAIT_TIMEOUT)
+ errno = EBUSY;
+ else
+ ACE_OS::set_errno_to_last_error ();
+ // This is a hack, we need to find an appropriate mapping...
+ return -1;
+ }
+# else /* ACE_USES_WINCE_SEMA_SIMULATION */
+ // Check the status of semaphore first. Return immediately
+ // if the semaphore is not available and avoid grabing the
+ // lock.
+ DWORD result = ::WaitForSingleObject (s->count_nonzero_, 0);
+
+ if (result == WAIT_OBJECT_0) // Proceed when it is available.
+ {
+ ACE_OS::thread_mutex_lock (&s->lock_);
+
+ // Need to double check if the semaphore is still available.
+ // The double checking scheme will slightly affect the
+ // efficiency if most of the time semaphores are not blocked.
+ result = ::WaitForSingleObject (s->count_nonzero_, 0);
+ if (result == WAIT_OBJECT_0)
+ {
+ // Adjust the semaphore count. Only update the event
+ // object status when the state changed.
+ s->count_--;
+ if (s->count_ <= 0)
+ ACE_OS::event_reset (&s->count_nonzero_);
+ result = 0;
+ }
+
+ ACE_OS::thread_mutex_unlock (&s->lock_);
+ }
+
+ // Translate error message to errno used by ACE.
+ if (result == WAIT_TIMEOUT)
+ errno = EBUSY;
+ else
+ ACE_OS::set_errno_to_last_error ();
+ // This is taken from the hack above. ;)
+ return -1;
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# elif defined (ACE_VXWORKS)
+ if (::semTake (s->sema_, NO_WAIT) == ERROR)
+ if (errno == S_objLib_OBJ_UNAVAILABLE)
+ {
+ // couldn't get the semaphore
+ errno = EBUSY;
+ return -1;
+ }
+ else
+ // error
+ return -1;
+ else
+ // got the semaphore
+ return 0;
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (s);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_POSIX_SEM */
+}
+
+ACE_INLINE int
+ACE_OS::sema_wait (ACE_sema_t *s)
+{
+ ACE_OS_TRACE ("ACE_OS::sema_wait");
+# if defined (ACE_HAS_POSIX_SEM)
+ ACE_OSCALL_RETURN (::sem_wait (s->sema_), int, -1);
+# elif defined (ACE_USES_FIFO_SEM)
+ char c;
+ if (ACE_OS::read (s->fd_[0], &c, sizeof (char)) == 1)
+ return (0);
+ return (-1);
+# elif defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_wait (s), result), int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+ int result = 0;
+
+ ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
+
+ if (ACE_OS::mutex_lock (&s->lock_) != 0)
+ result = -1;
+ else
+ {
+ // Keep track of the number of waiters so that we can signal
+ // them properly in <ACE_OS::sema_post>.
+ s->waiters_++;
+
+ // Wait until the semaphore count is > 0.
+ while (s->count_ == 0)
+ if (ACE_OS::cond_wait (&s->count_nonzero_,
+ &s->lock_) == -1)
+ {
+ result = -2; // -2 means that we need to release the mutex.
+ break;
+ }
+
+ --s->waiters_;
+ }
+
+ if (result == 0)
+ --s->count_;
+
+ if (result != -1)
+ ACE_OS::mutex_unlock (&s->lock_);
+ ACE_PTHREAD_CLEANUP_POP (0);
+ return result < 0 ? -1 : result;
+
+# elif defined (ACE_HAS_WTHREADS)
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ switch (::WaitForSingleObject (*s, INFINITE))
+ {
+ case WAIT_OBJECT_0:
+ return 0;
+ default:
+ // This is a hack, we need to find an appropriate mapping...
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ /* NOTREACHED */
+# else /* ACE_USES_WINCE_SEMA_SIMULATION */
+ // Timed wait.
+ int result = -1;
+ for (;;)
+ // Check if the semaphore is avialable or not and wait forever.
+ // Don't bother to grab the lock if it is not available (to avoid
+ // deadlock.)
+ switch (::WaitForSingleObject (s->count_nonzero_, INFINITE))
+ {
+ case WAIT_OBJECT_0:
+ ACE_OS::thread_mutex_lock (&s->lock_);
+
+ // Need to double check if the semaphore is still available.
+ // This time, we shouldn't wait at all.
+ if (::WaitForSingleObject (s->count_nonzero_, 0) == WAIT_OBJECT_0)
+ {
+ // Decrease the internal counter. Only update the event
+ // object's status when the state changed.
+ s->count_--;
+ if (s->count_ <= 0)
+ ACE_OS::event_reset (&s->count_nonzero_);
+ result = 0;
+ }
+
+ ACE_OS::thread_mutex_unlock (&s->lock_);
+ // if we didn't get a hold on the semaphore, the result won't
+ // be 0 and thus, we'll start from the beginning again.
+ if (result == 0)
+ return 0;
+ break;
+
+ default:
+ // Since we wait indefinitely, anything other than
+ // WAIT_OBJECT_O indicates an error.
+ ACE_OS::set_errno_to_last_error ();
+ // This is taken from the hack above. ;)
+ return -1;
+ }
+ /* NOTREACHED */
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# elif defined (ACE_VXWORKS)
+ ACE_OSCALL_RETURN (::semTake (s->sema_, WAIT_FOREVER), int, -1);
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (s);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_POSIX_SEM */
+}
+
+ACE_INLINE int
+ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value &tv)
+{
+ ACE_OS_TRACE ("ACE_OS::sema_wait");
+# if defined (ACE_HAS_POSIX_SEM)
+# if defined (ACE_HAS_POSIX_SEM_TIMEOUT)
+ int rc;
+ timespec_t ts;
+ ts = tv; // Calls ACE_Time_Value::operator timespec_t().
+ ACE_OSCALL (::sem_timedwait (s->sema_, &ts), int, -1, rc);
+ if (rc == -1 && errno == ETIMEDOUT)
+ errno = ETIME; /* POSIX returns ETIMEDOUT but we need ETIME */
+ return rc;
+# elif !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
+ int result = 0;
+ bool expired = false;
+ ACE_Errno_Guard error (errno);
+
+ ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
+
+ if (ACE_OS::mutex_lock (&s->lock_) != 0)
+ result = -2;
+ else
+ {
+ bool finished = true;
+ do
+ {
+ result = ACE_OS::sema_trywait (s);
+ if (result == -1 && errno == EAGAIN)
+ expired = ACE_OS::gettimeofday () > tv;
+ else
+ expired = false;
+
+ finished = result != -1 || expired ||
+ (result == -1 && errno != EAGAIN);
+ if (!finished)
+ {
+ if (ACE_OS::cond_timedwait (&s->count_nonzero_,
+ &s->lock_,
+ &tv) == -1)
+ {
+ error = errno;
+ result = -1;
+ break;
+ }
+ }
+ } while (!finished);
+
+ if (expired)
+ error = ETIME;
+
+# if defined (ACE_LACKS_COND_TIMEDWAIT_RESET)
+ tv = ACE_OS::gettimeofday ();
+# endif /* ACE_LACKS_COND_TIMEDWAIT_RESET */
+ }
+
+ if (result != -2)
+ ACE_OS::mutex_unlock (&s->lock_);
+ ACE_PTHREAD_CLEANUP_POP (0);
+ return result < 0 ? -1 : result;
+# else /* No native sem_timedwait(), and emulation disabled */
+ ACE_UNUSED_ARG (s);
+ ACE_UNUSED_ARG (tv);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_POSIX_SEM_TIMEOUT */
+# elif defined (ACE_USES_FIFO_SEM)
+ int rc;
+ ACE_Time_Value now = ACE_OS::gettimeofday ();
+
+ while (tv > now)
+ {
+ ACE_Time_Value timeout = tv;
+ timeout -= now;
+
+ ACE_Handle_Set fds_;
+
+ fds_.set_bit (s->fd_[0]);
+ if ((rc = ACE_OS::select (ACE_Handle_Set::MAXSIZE, fds_, 0, 0, timeout)) != 1)
+ {
+ if (rc == 0 || errno != EAGAIN)
+ {
+ if (rc == 0)
+ errno = ETIME;
+ return (-1);
+ }
+ }
+
+ // try to read the signal *but* do *not* block
+ if (rc == 1 && ACE_OS::sema_trywait (s) == 0)
+ return (0);
+
+ // we were woken for input but someone beat us to it
+ // so we wait again if there is still time
+ now = ACE_OS::gettimeofday ();
+ }
+
+ // make sure errno is set right
+ errno = ETIME;
+
+ return (-1);
+# elif defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ ACE_UNUSED_ARG (s);
+ ACE_UNUSED_ARG (tv);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_HAS_PTHREADS)
+ int result = 0;
+ ACE_Errno_Guard error (errno);
+
+ ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
+
+ if (ACE_OS::mutex_lock (&s->lock_) != 0)
+ result = -1;
+ else
+ {
+ // Keep track of the number of waiters so that we can signal
+ // them properly in <ACE_OS::sema_post>.
+ s->waiters_++;
+
+ // Wait until the semaphore count is > 0 or until we time out.
+ while (s->count_ == 0)
+ if (ACE_OS::cond_timedwait (&s->count_nonzero_,
+ &s->lock_,
+ &tv) == -1)
+ {
+ error = errno;
+ result = -2; // -2 means that we need to release the mutex.
+ break;
+ }
+
+ --s->waiters_;
+ }
+
+ if (result == 0)
+ {
+# if defined (ACE_LACKS_COND_TIMEDWAIT_RESET)
+ tv = ACE_OS::gettimeofday ();
+# endif /* ACE_LACKS_COND_TIMEDWAIT_RESET */
+ --s->count_;
+ }
+
+ if (result != -1)
+ ACE_OS::mutex_unlock (&s->lock_);
+ ACE_PTHREAD_CLEANUP_POP (0);
+ return result < 0 ? -1 : result;
+# elif defined (ACE_HAS_WTHREADS)
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+ int msec_timeout;
+
+ if (tv.sec () == 0 && tv.usec () == 0)
+ msec_timeout = 0; // Do a "poll."
+ else
+ {
+ // Note that we must convert between absolute time (which is
+ // passed as a parameter) and relative time (which is what
+ // <WaitForSingleObjects> expects).
+ ACE_Time_Value relative_time (tv - ACE_OS::gettimeofday ());
+
+ // Watchout for situations where a context switch has caused the
+ // current time to be > the timeout.
+ if (relative_time < ACE_Time_Value::zero)
+ msec_timeout = 0;
+ else
+ msec_timeout = relative_time.msec ();
+ }
+
+ switch (::WaitForSingleObject (*s, msec_timeout))
+ {
+ case WAIT_OBJECT_0:
+ tv = ACE_OS::gettimeofday (); // Update time to when acquired
+ return 0;
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ return -1;
+ default:
+ // This is a hack, we need to find an appropriate mapping...
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ /* NOTREACHED */
+# else /* ACE_USES_WINCE_SEMA_SIMULATION */
+ // Note that in this mode, the acquire is done in two steps, and
+ // we may get signaled but cannot grab the semaphore before
+ // timeout. In that case, we'll need to restart the process with
+ // updated timeout value.
+
+ // tv is an absolute time, but we need relative to work with the Windows
+ // API. Also, some users have become accustomed to using a 0 time value
+ // as a shortcut for "now", which works on non-Windows because 0 is
+ // always earlier than now. However, the need to convert to relative time
+ // means we need to watch out for this case.
+ ACE_Time_Value end_time = tv;
+ if (tv == ACE_Time_Value::zero)
+ end_time = ACE_OS::gettimeofday ();
+ ACE_Time_Value relative_time = end_time - ACE_OS::gettimeofday ();
+ int result = -1;
+
+ // While we are not timeout yet. >= 0 will let this go through once
+ // and if not able to get the object, it should hit WAIT_TIMEOUT
+ // right away.
+ while (relative_time >= ACE_Time_Value::zero)
+ {
+ // Wait for our turn to get the object.
+ switch (::WaitForSingleObject (s->count_nonzero_, relative_time.msec ()))
+ {
+ case WAIT_OBJECT_0:
+ ACE_OS::thread_mutex_lock (&s->lock_);
+
+ // Need to double check if the semaphore is still available.
+ // We can only do a "try lock" styled wait here to avoid
+ // blocking threads that want to signal the semaphore.
+ if (::WaitForSingleObject (s->count_nonzero_, 0) == WAIT_OBJECT_0)
+ {
+ // As before, only reset the object when the semaphore
+ // is no longer available.
+ s->count_--;
+ if (s->count_ <= 0)
+ ACE_OS::event_reset (&s->count_nonzero_);
+ result = 0;
+ }
+
+ ACE_OS::thread_mutex_unlock (&s->lock_);
+
+ // Only return when we successfully get the semaphore.
+ if (result == 0)
+ {
+ tv = ACE_OS::gettimeofday (); // Update to time acquired
+ return 0;
+ }
+ break;
+
+ // We have timed out.
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ return -1;
+
+ // What?
+ default:
+ ACE_OS::set_errno_to_last_error ();
+ // This is taken from the hack above. ;)
+ return -1;
+ };
+
+ // Haven't been able to get the semaphore yet, update the
+ // timeout value to reflect the remaining time we want to wait.
+ relative_time = end_time - ACE_OS::gettimeofday ();
+ }
+
+ // We have timed out.
+ errno = ETIME;
+ return -1;
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# elif defined (ACE_VXWORKS)
+ // Note that we must convert between absolute time (which is
+ // passed as a parameter) and relative time (which is what
+ // the system call expects).
+ ACE_Time_Value relative_time (tv - ACE_OS::gettimeofday ());
+
+ int ticks_per_sec = ::sysClkRateGet ();
+
+ int ticks = relative_time.sec () * ticks_per_sec +
+ relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
+ if (::semTake (s->sema_, ticks) == ERROR)
+ {
+ if (errno == S_objLib_OBJ_TIMEOUT)
+ // Convert the VxWorks errno to one that's common for to ACE
+ // platforms.
+ errno = ETIME;
+ else if (errno == S_objLib_OBJ_UNAVAILABLE)
+ errno = EBUSY;
+ return -1;
+ }
+ else
+ {
+ tv = ACE_OS::gettimeofday (); // Update to time acquired
+ return 0;
+ }
+# endif /* ACE_HAS_STHREADS */
+# else
+ ACE_UNUSED_ARG (s);
+ ACE_UNUSED_ARG (tv);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_POSIX_SEM */
+}
+
+ACE_INLINE int
+ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value *tv)
+{
+ return tv == 0 ? ACE_OS::sema_wait (s) : ACE_OS::sema_wait (s, *tv);
+}
+
+ACE_INLINE int
+ACE_OS::semctl (int int_id, int semnum, int cmd, semun value)
+{
+ ACE_OS_TRACE ("ACE_OS::semctl");
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_OSCALL_RETURN (::semctl (int_id, semnum, cmd, value), int, -1);
+#else
+ ACE_UNUSED_ARG (int_id);
+ ACE_UNUSED_ARG (semnum);
+ ACE_UNUSED_ARG (cmd);
+ ACE_UNUSED_ARG (value);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE int
+ACE_OS::semget (key_t key, int nsems, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::semget");
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_OSCALL_RETURN (::semget (key, nsems, flags), int, -1);
+#else
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (nsems);
+ ACE_UNUSED_ARG (flags);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE int
+ACE_OS::semop (int int_id, struct sembuf *sops, size_t nsops)
+{
+ ACE_OS_TRACE ("ACE_OS::semop");
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_OSCALL_RETURN (::semop (int_id, sops, nsops), int, -1);
+#else
+ ACE_UNUSED_ARG (int_id);
+ ACE_UNUSED_ARG (sops);
+ ACE_UNUSED_ARG (nsops);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE int
+ACE_OS::sigtimedwait (const sigset_t *sset,
+ siginfo_t *info,
+ const ACE_Time_Value *timeout)
+{
+ ACE_OS_TRACE ("ACE_OS::sigtimedwait");
+#if defined (ACE_HAS_SIGTIMEDWAIT)
+ timespec_t ts;
+ timespec_t *tsp;
+
+ if (timeout != 0)
+ {
+ ts = *timeout; // Calls ACE_Time_Value::operator timespec_t().
+ tsp = &ts;
+ }
+ else
+ tsp = 0;
+
+ ACE_OSCALL_RETURN (::sigtimedwait (sset, info, tsp),
+ int, -1);
+#else
+ ACE_UNUSED_ARG (sset);
+ ACE_UNUSED_ARG (info);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SIGTIMEDWAIT */
+}
+
+ACE_INLINE int
+ACE_OS::sigwait (sigset_t *sset, int *sig)
+{
+ ACE_OS_TRACE ("ACE_OS::sigwait");
+ int local_sig;
+ if (sig == 0)
+ sig = &local_sig;
+#if defined (ACE_HAS_THREADS)
+# if (defined (__FreeBSD__) && (__FreeBSD__ < 3))
+ ACE_UNUSED_ARG (sset);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_HAS_STHREADS)
+ # if (_POSIX_C_SOURCE - 0 >= 199506L) || defined (_POSIX_PTHREAD_SEMANTICS)
+ errno = ::sigwait (sset, sig);
+ return errno == 0 ? *sig : -1;
+ #else
+ *sig = ::sigwait (sset);
+ return *sig;
+ #endif /* _POSIX_C_SOURCE - 0 >= 199506L || _POSIX_PTHREAD_SEMANTICS */
+# elif defined (ACE_HAS_PTHREADS)
+ // LynxOS and Digital UNIX have their own hoops to jump through.
+# if defined (__Lynx__)
+ // Second arg is a void **, which we don't need (the selected
+ // signal number is returned).
+ *sig = ::sigwait (sset, 0);
+ return *sig;
+# elif defined (DIGITAL_UNIX) && defined (__DECCXX_VER)
+ // DEC cxx (but not g++) needs this direct call to its internal
+ // sigwait (). This allows us to #undef sigwait, so that we can
+ // have ACE_OS::sigwait. cxx gets confused by ACE_OS::sigwait
+ // if sigwait is _not_ #undef'ed.
+ errno = ::_Psigwait (sset, sig);
+ return errno == 0 ? *sig : -1;
+# else /* ! __Lynx __ && ! (DIGITAL_UNIX && __DECCXX_VER) */
+# if defined (CYGWIN32)
+ // Cygwin has sigwait definition, but it is not implemented
+ ACE_UNUSED_ARG (sset);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_TANDEM_T1248_PTHREADS)
+ errno = ::spt_sigwait (sset, sig);
+ return errno == 0 ? *sig : -1;
+# else /* this is draft 7 or std */
+ errno = ::sigwait (sset, sig);
+ return errno == 0 ? *sig : -1;
+# endif /* CYGWIN32 */
+# endif /* ! __Lynx__ && ! (DIGITAL_UNIX && __DECCXX_VER) */
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (sset);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_VXWORKS)
+ // Second arg is a struct siginfo *, which we don't need (the
+ // selected signal number is returned). Third arg is timeout: 0
+ // means forever.
+ *sig = ::sigtimedwait (sset, 0, 0);
+ return *sig;
+# endif /* __FreeBSD__ */
+#else
+ ACE_UNUSED_ARG (sset);
+ ACE_UNUSED_ARG (sig);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::sigwaitinfo (const sigset_t *sset,
+ siginfo_t *info)
+{
+ ACE_OS_TRACE ("ACE_OS::sigwaitinfo");
+ // If this platform has sigtimedwait, it should have sigwaitinfo as well.
+ // If this isn't true somewhere, let me know and I'll fix this.
+ // -Steve Huston <shuston@riverace.com>.
+#if defined (ACE_HAS_SIGTIMEDWAIT)
+ ACE_OSCALL_RETURN (::sigwaitinfo (sset, info), int, -1);
+#else
+ ACE_UNUSED_ARG (sset);
+ ACE_UNUSED_ARG (info);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SIGTIMEDWAIT */
+}
+
+ACE_INLINE int
+ACE_OS::thr_cancel (ACE_thread_t thr_id)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_cancel");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cancel (thr_id),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_VXTHREADS)
+ ACE_OSCALL_RETURN (::taskDelete (thr_id), int, -1);
+# else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
+ ACE_UNUSED_ARG (thr_id);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PTHREADS */
+#else
+ ACE_UNUSED_ARG (thr_id);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_cmp (ACE_hthread_t t1, ACE_hthread_t t2)
+{
+#if defined (ACE_HAS_PTHREADS)
+# if defined (pthread_equal)
+ // If it's a macro we can't say "pthread_equal"...
+ return pthread_equal (t1, t2);
+# else
+ return pthread_equal (t1, t2);
+# endif /* pthread_equal */
+#else /* For STHREADS, WTHREADS, and VXWORKS ... */
+ // Hum, Do we need to treat WTHREAD differently?
+ // levine 13 oct 98 % Probably, ACE_hthread_t is a HANDLE.
+ return t1 == t2;
+#endif /* ACE_HAS_PTHREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_continue (ACE_hthread_t target_thread)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_continue");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_continue (target_thread), result), int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+# if defined (ACE_HAS_PTHREAD_CONTINUE)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue (target_thread),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREAD_CONTINUE_NP)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue_np (target_thread),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREAD_RESUME_NP)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_resume_np (target_thread),
+ result),
+ int, -1);
+# else
+ ACE_UNUSED_ARG (target_thread);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PTHREAD_CONTINUE */
+# elif defined (ACE_HAS_WTHREADS)
+ DWORD result = ::ResumeThread (target_thread);
+ if (result == ACE_SYSCALL_FAILED)
+ ACE_FAIL_RETURN (-1);
+ else
+ return 0;
+# elif defined (ACE_HAS_VXTHREADS)
+ ACE_OSCALL_RETURN (::taskResume (target_thread), int, -1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (target_thread);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_getconcurrency (void)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_getconcurrency");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ return ::thr_getconcurrency ();
+# elif defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_PTHREAD_GETCONCURRENCY)
+ return pthread_getconcurrency ();
+# else
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_getprio (ACE_hthread_t ht_id, int &priority, int &policy)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_getprio");
+ ACE_UNUSED_ARG (policy);
+#if defined (ACE_HAS_THREADS)
+# if (defined (ACE_HAS_PTHREADS) && \
+ (!defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)))
+
+ struct sched_param param;
+ int result;
+
+ ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_getschedparam (ht_id, &policy, &param),
+ result), int,
+ -1, result);
+ priority = param.sched_priority;
+ return result;
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getprio (ht_id, &priority), result), int, -1);
+# elif defined (ACE_HAS_WTHREADS) && !defined (ACE_HAS_WINCE)
+ ACE_Errno_Guard error (errno);
+
+ priority = ::GetThreadPriority (ht_id);
+
+# if defined (ACE_HAS_PHARLAP)
+# if defined (ACE_PHARLAP_LABVIEW_RT)
+ policy = ACE_SCHED_FIFO;
+# else
+ DWORD timeslice = ::EtsGetTimeSlice ();
+ policy = timeslice == 0 ? ACE_SCHED_OTHER : ACE_SCHED_FIFO;
+# endif /* ACE_PHARLAP_LABVIEW_RT */
+# else
+ DWORD priority_class = ::GetPriorityClass (::GetCurrentProcess ());
+ if (priority_class == 0 && (error = ::GetLastError ()) != NO_ERROR)
+ ACE_FAIL_RETURN (-1);
+
+ policy =
+ (priority_class ==
+ REALTIME_PRIORITY_CLASS) ? ACE_SCHED_FIFO : ACE_SCHED_OTHER;
+# endif /* ACE_HAS_PHARLAP */
+
+ return 0;
+# elif defined (ACE_HAS_VXTHREADS)
+ ACE_OSCALL_RETURN (::taskPriorityGet (ht_id, &priority), int, -1);
+# else
+ ACE_UNUSED_ARG (ht_id);
+ ACE_UNUSED_ARG (priority);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (ht_id);
+ ACE_UNUSED_ARG (priority);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_getprio (ACE_hthread_t ht_id, int &priority)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_getprio");
+ int policy = 0;
+ return ACE_OS::thr_getprio (ht_id, priority, policy);
+}
+
+#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ACE_INLINE int
+ACE_OS::thr_getspecific_native (ACE_OS_thread_key_t key, void **data)
+{
+// ACE_OS_TRACE ("ACE_OS::thr_getspecific_native");
+# if defined (ACE_HAS_PTHREADS)
+ *data = pthread_getspecific (key);
+ return 0;
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getspecific (key, data), result), int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ *data = ::TlsGetValue (key);
+ if (*data == 0 && ::GetLastError () != NO_ERROR)
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ else
+ return 0;
+# else /* ACE_HAS_PTHREADS etc.*/
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (data);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PTHREADS etc.*/
+}
+#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+ACE_INLINE int
+ACE_OS::thr_getspecific (ACE_thread_key_t key, void **data)
+{
+// ACE_OS_TRACE ("ACE_OS::thr_getspecific");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_TSS_EMULATION)
+ if (ACE_TSS_Emulation::is_key (key) == 0)
+ {
+ errno = EINVAL;
+ data = 0;
+ return -1;
+ }
+ else
+ {
+ *data = ACE_TSS_Emulation::ts_object (key);
+ return 0;
+ }
+# elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ return ACE_OS::thr_getspecific_native (key, data);
+#else
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (data);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_TSS_EMULATION */
+#else
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (data);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+#if !defined (ACE_HAS_VXTHREADS)
+ACE_INLINE int
+ACE_OS::thr_join (ACE_hthread_t thr_handle,
+ ACE_THR_FUNC_RETURN *status)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_join");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (thr_handle, 0, status), result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_join (thr_handle, status), result),
+ int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_THR_FUNC_RETURN local_status = 0;
+
+ // Make sure that status is non-NULL.
+ if (status == 0)
+ status = &local_status;
+
+ if (::WaitForSingleObject (thr_handle, INFINITE) == WAIT_OBJECT_0
+ && ::GetExitCodeThread (thr_handle, status) != FALSE)
+ {
+ ::CloseHandle (thr_handle);
+ return 0;
+ }
+ ACE_FAIL_RETURN (-1);
+ /* NOTREACHED */
+# else
+ ACE_UNUSED_ARG (thr_handle);
+ ACE_UNUSED_ARG (status);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (thr_handle);
+ ACE_UNUSED_ARG (status);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_join (ACE_thread_t waiter_id,
+ ACE_thread_t *thr_id,
+ ACE_THR_FUNC_RETURN *status)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_join");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (waiter_id, thr_id, status), result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+ ACE_UNUSED_ARG (thr_id);
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_join (waiter_id, status), result),
+ int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (waiter_id);
+ ACE_UNUSED_ARG (thr_id);
+ ACE_UNUSED_ARG (status);
+
+ // This could be implemented if the DLL-Main function or the
+ // task exit base class some log the threads which have exited
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (waiter_id);
+ ACE_UNUSED_ARG (thr_id);
+ ACE_UNUSED_ARG (status);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+#endif /* !VXWORKS */
+
+ACE_INLINE int
+ACE_OS::thr_kill (ACE_thread_t thr_id, int signum)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_kill");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+# if defined (ACE_LACKS_PTHREAD_KILL)
+ ACE_UNUSED_ARG (signum);
+ ACE_UNUSED_ARG (thr_id);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_kill (thr_id, signum),
+ result),
+ int, -1);
+# endif /* ACE_LACKS_PTHREAD_KILL */
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_kill (thr_id, signum),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_VXTHREADS)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (::kill (thr_id, signum), int, -1);
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ ACE_UNUSED_ARG (thr_id);
+ ACE_UNUSED_ARG (signum);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (thr_id);
+ ACE_UNUSED_ARG (signum);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE size_t
+ACE_OS::thr_min_stack (void)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_min_stack");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+# if defined (ACE_HAS_THR_MINSTACK)
+ // Tandem did some weirdo mangling of STHREAD names...
+ return ::thr_minstack ();
+# else
+ return ::thr_min_stack ();
+# endif /* !ACE_HAS_THR_MINSTACK */
+# elif defined (ACE_HAS_PTHREADS)
+# if defined (_SC_THREAD_STACK_MIN)
+ return (size_t) ACE_OS::sysconf (_SC_THREAD_STACK_MIN);
+# elif defined (PTHREAD_STACK_MIN)
+ return PTHREAD_STACK_MIN;
+# else
+ ACE_NOTSUP_RETURN (0);
+# endif /* _SC_THREAD_STACK_MIN */
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_NOTSUP_RETURN (0);
+# elif defined (ACE_HAS_VXTHREADS)
+ TASK_DESC taskDesc;
+ STATUS status;
+
+ ACE_thread_t tid = ACE_OS::thr_self ();
+
+ ACE_OSCALL (ACE_ADAPT_RETVAL (::taskInfoGet (tid, &taskDesc),
+ status),
+ STATUS, -1, status);
+ return status == OK ? taskDesc.td_stackSize : 0;
+# else /* Should not happen... */
+ ACE_NOTSUP_RETURN (0);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE ACE_thread_t
+ACE_OS::thr_self (void)
+{
+ // ACE_OS_TRACE ("ACE_OS::thr_self");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ // Note, don't use "::" here since the following call is often a macro.
+ return pthread_self ();
+# elif defined (ACE_HAS_STHREADS)
+ ACE_OSCALL_RETURN (::thr_self (), int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ return ::GetCurrentThreadId ();
+# elif defined (ACE_HAS_VXTHREADS)
+ return ::taskIdSelf ();
+# endif /* ACE_HAS_STHREADS */
+#else
+ return 1; // Might as well make it the first thread ;-)
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE const char*
+ACE_OS::thr_name (void)
+{
+#if defined (ACE_HAS_THREADS)
+#if defined (ACE_HAS_VXTHREADS)
+ return ::taskName (ACE_OS::thr_self ());
+#else
+ ACE_NOTSUP_RETURN (0);
+#endif
+#else
+ ACE_NOTSUP_RETURN (0);
+#endif
+}
+
+ACE_INLINE void
+ACE_OS::thr_self (ACE_hthread_t &self)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_self");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ // Note, don't use "::" here since the following call is often a macro.
+ self = pthread_self ();
+# elif defined (ACE_HAS_THREAD_SELF)
+ self = ::thread_self ();
+# elif defined (ACE_HAS_STHREADS)
+ self = ::thr_self ();
+# elif defined (ACE_HAS_WTHREADS)
+ self = ::GetCurrentThread ();
+# elif defined (ACE_HAS_VXTHREADS)
+ self = ::taskIdSelf ();
+# endif /* ACE_HAS_STHREADS */
+#else
+ self = 1; // Might as well make it the main thread ;-)
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_setcancelstate (int new_state, int *old_state)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_setcancelstate");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setcancelstate (new_state,
+ old_state),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ ACE_UNUSED_ARG (new_state);
+ ACE_UNUSED_ARG (old_state);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (new_state);
+ ACE_UNUSED_ARG (old_state);
+ ACE_NOTSUP_RETURN (-1);
+# else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
+ ACE_UNUSED_ARG (new_state);
+ ACE_UNUSED_ARG (old_state);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PTHREADS */
+#else
+ ACE_UNUSED_ARG (new_state);
+ ACE_UNUSED_ARG (old_state);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_setcanceltype (int new_type, int *old_type)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_setcanceltype");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setcanceltype (new_type,
+ old_type),
+ result),
+ int, -1);
+# else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
+ ACE_UNUSED_ARG (new_type);
+ ACE_UNUSED_ARG (old_type);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PTHREADS */
+#else
+ ACE_UNUSED_ARG (new_type);
+ ACE_UNUSED_ARG (old_type);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_setconcurrency (int hint)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_setconcurrency");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setconcurrency (hint),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_PTHREAD_SETCONCURRENCY)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setconcurrency (hint),
+ result),
+ int, -1);
+# else
+ ACE_UNUSED_ARG (hint);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (hint);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_setprio (ACE_hthread_t ht_id, int priority, int policy)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_setprio");
+ ACE_UNUSED_ARG (policy);
+#if defined (ACE_HAS_THREADS)
+# if (defined (ACE_HAS_PTHREADS) && \
+ (!defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)))
+
+ int result;
+ struct sched_param param;
+ ACE_OS::memset ((void *) &param, 0, sizeof param);
+
+ // If <policy> is -1, we don't want to use it for
+ // pthread_setschedparam(). Instead, obtain policy from
+ // pthread_getschedparam().
+ if (policy == -1)
+ {
+ ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_getschedparam (ht_id, &policy, &param),
+ result),
+ int, -1, result);
+ if (result == -1)
+ return result;
+ }
+
+ param.sched_priority = priority;
+
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setschedparam (ht_id,
+ policy,
+ &param),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setprio (ht_id, priority),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetThreadPriority (ht_id, priority),
+ ace_result_),
+ int, -1);
+# elif defined (ACE_HAS_VXTHREADS)
+ ACE_OSCALL_RETURN (::taskPrioritySet (ht_id, priority), int, -1);
+# else
+ // For example, platforms that support Pthreads but LACK_SETSCHED.
+ ACE_UNUSED_ARG (ht_id);
+ ACE_UNUSED_ARG (priority);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (ht_id);
+ ACE_UNUSED_ARG (priority);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_sigsetmask (int how,
+ const sigset_t *nsm,
+ sigset_t *osm)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_sigsetmask");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
+ // DCE threads and Solaris 2.4 have no such function.
+ ACE_UNUSED_ARG (osm);
+ ACE_UNUSED_ARG (nsm);
+ ACE_UNUSED_ARG (how);
+
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_HAS_SIGTHREADMASK)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigthreadmask (how, nsm, osm),
+ result), int, -1);
+# elif defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_sigsetmask (how, nsm, osm),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+# if !defined (ACE_LACKS_PTHREAD_SIGMASK)
+ int result;
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsm, osm),
+ result), int, -1);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* !ACE_LACKS_PTHREAD_SIGMASK */
+
+#if 0
+ /* Don't know if any platform actually needs this... */
+ // as far as I can tell, this is now pthread_sigaction() -- jwr
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_sigaction (how, nsm, osm),
+ result), int, -1);
+#endif /* 0 */
+
+# elif defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (osm);
+ ACE_UNUSED_ARG (nsm);
+ ACE_UNUSED_ARG (how);
+
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_VXWORKS)
+ int old_mask = 0;
+ switch (how)
+ {
+ case SIG_BLOCK:
+ case SIG_UNBLOCK:
+ {
+ // get the old mask
+ old_mask = ::sigsetmask (*nsm);
+ // create a new mask: the following assumes that sigset_t is 4 bytes,
+ // which it is on VxWorks 5.2, so bit operations are done simply . . .
+ ::sigsetmask (how == SIG_BLOCK ? (old_mask |= *nsm) : (old_mask &= ~*nsm));
+ if (osm)
+ *osm = old_mask;
+ break;
+ }
+ case SIG_SETMASK:
+ old_mask = ::sigsetmask (*nsm);
+ if (osm)
+ *osm = old_mask;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+# else /* Should not happen. */
+ ACE_UNUSED_ARG (how);
+ ACE_UNUSED_ARG (nsm);
+ ACE_UNUSED_ARG (osm);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
+#else
+ ACE_UNUSED_ARG (how);
+ ACE_UNUSED_ARG (nsm);
+ ACE_UNUSED_ARG (osm);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thr_suspend (ACE_hthread_t target_thread)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_suspend");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_STHREADS)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_suspend (target_thread), result), int, -1);
+# elif defined (ACE_HAS_PTHREADS)
+# if defined (ACE_HAS_PTHREAD_SUSPEND)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend (target_thread),
+ result),
+ int, -1);
+# elif defined (ACE_HAS_PTHREAD_SUSPEND_NP)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend_np (target_thread),
+ result),
+ int, -1);
+# else
+ ACE_UNUSED_ARG (target_thread);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PTHREAD_SUSPEND */
+# elif defined (ACE_HAS_WTHREADS)
+ if (::SuspendThread (target_thread) != ACE_SYSCALL_FAILED)
+ return 0;
+ else
+ ACE_FAIL_RETURN (-1);
+ /* NOTREACHED */
+# elif defined (ACE_HAS_VXTHREADS)
+ ACE_OSCALL_RETURN (::taskSuspend (target_thread), int, -1);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ACE_UNUSED_ARG (target_thread);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE void
+ACE_OS::thr_testcancel (void)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_testcancel");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
+ pthread_testcancel ();
+# elif defined (ACE_HAS_STHREADS)
+# elif defined (ACE_HAS_WTHREADS)
+# elif defined (ACE_HAS_VXTHREADS)
+# else
+ // no-op: can't use ACE_NOTSUP_RETURN because there is no return value
+# endif /* ACE_HAS_PTHREADS */
+#else
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE void
+ACE_OS::thr_yield (void)
+{
+ ACE_OS_TRACE ("ACE_OS::thr_yield");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_PTHREADS)
+ ::sched_yield ();
+# elif defined (ACE_HAS_STHREADS)
+ ::thr_yield ();
+# elif defined (ACE_HAS_WTHREADS)
+ ::Sleep (0);
+# elif defined (ACE_HAS_VXTHREADS)
+ // An argument of 0 to ::taskDelay doesn't appear to yield the
+ // current thread.
+ // Now, it does seem to work. The context_switch_time test
+ // works fine with task_delay set to 0.
+ ::taskDelay (0);
+# endif /* ACE_HAS_STHREADS */
+#else
+ ;
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thread_mutex_destroy (ACE_thread_mutex_t *m)
+{
+ ACE_OS_TRACE ("ACE_OS::thread_mutex_destroy");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_WTHREADS)
+ ::DeleteCriticalSection (m);
+ return 0;
+# else
+ return ACE_OS::mutex_destroy (m);
+# endif /* ACE_HAS_WTHREADS */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m,
+ int lock_type,
+ const char *name,
+ ACE_mutexattr_t *arg)
+{
+ // ACE_OS_TRACE ("ACE_OS::thread_mutex_init");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (lock_type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+
+ ACE_SEH_TRY
+ {
+ ::InitializeCriticalSection (m);
+ }
+ ACE_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ return 0;
+
+# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS)
+ // Force the use of USYNC_THREAD!
+ return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg, 0, lock_type);
+# elif defined (ACE_HAS_VXTHREADS)
+ return mutex_init (m, lock_type, name, arg);
+
+# endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */
+
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (lock_type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+
+#endif /* ACE_HAS_THREADS */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m,
+ int lock_type,
+ const wchar_t *name,
+ ACE_mutexattr_t *arg)
+{
+ // ACE_OS_TRACE ("ACE_OS::thread_mutex_init");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (lock_type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+
+ ACE_SEH_TRY
+ {
+ ::InitializeCriticalSection (m);
+ }
+ ACE_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ return 0;
+
+# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS)
+ // Force the use of USYNC_THREAD!
+ return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg, 0, lock_type);
+# elif defined (ACE_HAS_VXTHREADS)
+ return mutex_init (m, lock_type, name, arg);
+# endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (lock_type);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+
+#endif /* ACE_HAS_THREADS */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m)
+{
+ // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_WTHREADS)
+ ::EnterCriticalSection (m);
+ return 0;
+# else
+ return ACE_OS::mutex_lock (m);
+# endif /* ACE_HAS_WTHREADS */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m,
+ const ACE_Time_Value &timeout)
+{
+ // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock");
+
+ // For all platforms, except MS Windows, this method is equivalent
+ // to calling ACE_OS::mutex_lock() since ACE_thread_mutex_t and
+ // ACE_mutex_t are the same type. However, those typedefs evaluate
+ // to different types on MS Windows. The "thread mutex"
+ // implementation in ACE for MS Windows cannot readily support
+ // timeouts due to a lack of timeout features for this type of MS
+ // Windows synchronization mechanism.
+
+#if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_WTHREADS)
+ return ACE_OS::mutex_lock (m, timeout);
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m,
+ const ACE_Time_Value *timeout)
+{
+ return timeout == 0
+ ? ACE_OS::thread_mutex_lock (m)
+ : ACE_OS::thread_mutex_lock (m, *timeout);
+}
+
+ACE_INLINE int
+ACE_OS::thread_mutex_trylock (ACE_thread_mutex_t *m)
+{
+ ACE_OS_TRACE ("ACE_OS::thread_mutex_trylock");
+
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_WTHREADS)
+# if defined (ACE_HAS_WIN32_TRYLOCK)
+ BOOL result = ::TryEnterCriticalSection (m);
+ if (result == TRUE)
+ return 0;
+ else
+ {
+ errno = EBUSY;
+ return -1;
+ }
+# else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_WIN32_TRYLOCK */
+# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_VXWORKS)
+ return ACE_OS::mutex_trylock (m);
+#endif /* Threads variety case */
+
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_INLINE int
+ACE_OS::thread_mutex_unlock (ACE_thread_mutex_t *m)
+{
+ ACE_OS_TRACE ("ACE_OS::thread_mutex_unlock");
+#if defined (ACE_HAS_THREADS)
+# if defined (ACE_HAS_WTHREADS)
+ ::LeaveCriticalSection (m);
+ return 0;
+# else
+ return ACE_OS::mutex_unlock (m);
+# endif /* ACE_HAS_WTHREADS */
+#else
+ ACE_UNUSED_ARG (m);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+/*****************************************************************************/
+
+# if defined (ACE_IS_SPLITTING)
+# define ACE_SPECIAL_INLINE
+# else
+# define ACE_SPECIAL_INLINE ACE_INLINE
+//# define ACE_SPECIAL_INLINE inline
+# endif
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ACE_INLINE
+int
+ACE_OS_Thread_Mutex_Guard::acquire (void)
+{
+ return owner_ = ACE_OS::thread_mutex_lock (&lock_);
+}
+
+ACE_INLINE
+int
+ACE_OS_Thread_Mutex_Guard::release (void)
+{
+ if (owner_ == -1)
+ return 0;
+ else
+ {
+ owner_ = -1;
+ return ACE_OS::thread_mutex_unlock (&lock_);
+ }
+}
+
+ACE_INLINE
+ACE_OS_Thread_Mutex_Guard::ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m)
+ : lock_ (m), owner_ (-1)
+{
+ if (!ACE_OS_Object_Manager::starting_up ())
+ acquire ();
+}
+
+ACE_INLINE
+ACE_OS_Thread_Mutex_Guard::~ACE_OS_Thread_Mutex_Guard ()
+{
+ release ();
+}
+
+/*****************************************************************************/
+
+ACE_INLINE
+int
+ACE_OS_Recursive_Thread_Mutex_Guard::acquire (void)
+{
+ return owner_ = ACE_OS::recursive_mutex_lock (&lock_);
+}
+
+ACE_INLINE
+int
+ACE_OS_Recursive_Thread_Mutex_Guard::release (void)
+{
+ if (owner_ == -1)
+ return 0;
+ else
+ {
+ owner_ = -1;
+ return ACE_OS::recursive_mutex_unlock (&lock_);
+ }
+}
+
+ACE_INLINE
+ACE_OS_Recursive_Thread_Mutex_Guard::ACE_OS_Recursive_Thread_Mutex_Guard (
+ ACE_recursive_thread_mutex_t &m)
+ : lock_ (m),
+ owner_ (-1)
+{
+ if (!ACE_OS_Object_Manager::starting_up ())
+ acquire ();
+}
+
+ACE_INLINE
+ACE_OS_Recursive_Thread_Mutex_Guard::~ACE_OS_Recursive_Thread_Mutex_Guard ()
+{
+ release ();
+}
+
+#endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+
+
+/*****************************************************************************/
+
+ACE_INLINE
+ACE_Thread_ID::ACE_Thread_ID (ACE_thread_t thread_id,
+ ACE_hthread_t thread_handle)
+ : thread_id_ (thread_id),
+ thread_handle_ (thread_handle)
+{
+}
+
+ACE_INLINE
+ACE_Thread_ID::ACE_Thread_ID (const ACE_Thread_ID &id)
+ : thread_id_ (id.thread_id_),
+ thread_handle_ (id.thread_handle_)
+{
+}
+
+ACE_INLINE
+ACE_Thread_ID::ACE_Thread_ID (void)
+ : thread_id_ (ACE_OS::thr_self ())
+{
+ ACE_OS::thr_self (thread_handle_);
+}
+
+ACE_INLINE
+ACE_thread_t
+ACE_Thread_ID::id (void) const
+{
+ return this->thread_id_;
+}
+
+ACE_INLINE void
+ACE_Thread_ID::id (ACE_thread_t thread_id)
+{
+ this->thread_id_ = thread_id;
+}
+
+ACE_INLINE ACE_hthread_t
+ACE_Thread_ID::handle (void) const
+{
+ return this->thread_handle_;
+}
+
+ACE_INLINE void
+ACE_Thread_ID::handle (ACE_hthread_t thread_handle)
+{
+ this->thread_handle_ = thread_handle;
+}
+
+ACE_INLINE bool
+ACE_Thread_ID::operator== (const ACE_Thread_ID &rhs) const
+{
+ return
+ ACE_OS::thr_cmp (this->thread_handle_, rhs.thread_handle_)
+ && ACE_OS::thr_equal (this->thread_id_, rhs.thread_id_);
+}
+
+ACE_INLINE bool
+ACE_Thread_ID::operator!= (const ACE_Thread_ID &rhs) const
+{
+ return !(*this == rhs);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_arpa_inet.cpp b/ACE/ace/OS_NS_arpa_inet.cpp
new file mode 100644
index 00000000000..0ebf8a3dcc6
--- /dev/null
+++ b/ACE/ace/OS_NS_arpa_inet.cpp
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+// $Id$
+
+#include "ace/OS_NS_arpa_inet.h"
+
+ACE_RCSID(ace, OS_NS_arpa_inet, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_arpa_inet.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_OS::inet_aton (const char *host_name, struct in_addr *addr)
+{
+#if defined (ACE_LACKS_INET_ATON)
+# if defined (ACE_WIN32)
+ // Windows Server 2003 changed the behavior of a zero-length input
+ // string to inet_addr(). It used to return 0 (INADDR_ANY) but now
+ // returns -1 (INADDR_NONE). It will return INADDR_ANY for a 1-space
+ // string, though, as do previous versions of Windows.
+ if (host_name == 0 || host_name[0] == '\0')
+ host_name = " ";
+# endif /* ACE_WIN32 */
+ unsigned long ip_addr = ACE_OS::inet_addr (host_name);
+
+ if (ip_addr == INADDR_NONE
+ // Broadcast addresses are weird...
+ && ACE_OS::strcmp (host_name, "255.255.255.255") != 0)
+ return 0;
+ else if (addr == 0)
+ return 0;
+ else
+ {
+ addr->s_addr = ip_addr; // Network byte ordered
+ return 1;
+ }
+#elif defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x660)
+ // inet_aton() returns OK (0) on success and ERROR (-1) on failure.
+ // Must reset errno first. Refer to WindRiver SPR# 34949, SPR# 36026
+ ::errnoSet(0);
+ int result = ERROR;
+ ACE_OSCALL (::inet_aton (const_cast <char*>(host_name), addr), int, ERROR, result);
+ return (result == ERROR) ? 0 : 1;
+#else
+ // inet_aton() returns 0 upon failure, not -1 since -1 is a valid
+ // address (255.255.255.255).
+ ACE_OSCALL_RETURN (::inet_aton (host_name, addr), int, 0);
+#endif /* ACE_LACKS_INET_ATON */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_arpa_inet.h b/ACE/ace/OS_NS_arpa_inet.h
new file mode 100644
index 00000000000..9cf4d5c426f
--- /dev/null
+++ b/ACE/ace/OS_NS_arpa_inet.h
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_arpa_inet.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_ARPA_INET_H
+# define ACE_OS_NS_ARPA_INET_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/os_include/arpa/os_inet.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ unsigned long inet_addr (const char *name);
+
+ extern ACE_Export
+ int inet_aton (const char *strptr,
+ struct in_addr *addr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *inet_ntoa (const struct in_addr addr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const char *inet_ntop (int family,
+ const void *addrptr,
+ char *strptr,
+ size_t len);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int inet_pton (int family,
+ const char *strptr,
+ void *addrptr);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_arpa_inet.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_ARPA_INET_H */
diff --git a/ACE/ace/OS_NS_arpa_inet.inl b/ACE/ace/OS_NS_arpa_inet.inl
new file mode 100644
index 00000000000..3f0b768adff
--- /dev/null
+++ b/ACE/ace/OS_NS_arpa_inet.inl
@@ -0,0 +1,98 @@
+// -*- C++ -*-
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_stdio.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE unsigned long
+ACE_OS::inet_addr (const char *name)
+{
+ ACE_OS_TRACE ("ACE_OS::inet_addr");
+#if defined (ACE_LACKS_INET_ADDR)
+ ACE_UNUSED_ARG (name);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_HAS_NONCONST_GETBY)
+ return ::inet_addr (const_cast <char*> (name));
+#else
+ return ::inet_addr (name);
+#endif /* ACE_HAS_NONCONST_GETBY */
+}
+
+ACE_INLINE char *
+ACE_OS::inet_ntoa (const struct in_addr addr)
+{
+ ACE_OS_TRACE ("ACE_OS::inet_ntoa");
+#if defined (ACE_LACKS_INET_NTOA)
+ ACE_UNUSED_ARG (addr);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN (::inet_ntoa (addr),
+ char *,
+ 0);
+#endif
+}
+
+ACE_INLINE const char *
+ACE_OS::inet_ntop (int family, const void *addrptr, char *strptr, size_t len)
+{
+ ACE_OS_TRACE ("ACE_OS::inet_ntop");
+
+#if defined (ACE_HAS_IPV6) && !defined (ACE_WIN32)
+ ACE_OSCALL_RETURN (::inet_ntop (family, addrptr, strptr, len), const char *, 0);
+#else
+ const u_char *p = reinterpret_cast<const u_char *> (addrptr);
+
+ if (family == AF_INET)
+ {
+ char temp[INET_ADDRSTRLEN];
+
+ // Stevens uses snprintf() in his implementation but snprintf()
+ // doesn't appear to be very portable. For now, hope that using
+ // sprintf() will not cause any string/memory overrun problems.
+ ACE_OS::sprintf (temp,
+ "%d.%d.%d.%d",
+ p[0], p[1], p[2], p[3]);
+
+ if (ACE_OS::strlen (temp) >= len)
+ {
+ errno = ENOSPC;
+ return 0; // Failure
+ }
+
+ ACE_OS::strcpy (strptr, temp);
+ return strptr;
+ }
+
+ ACE_NOTSUP_RETURN(0);
+#endif /* ACE_HAS_IPV6 */
+}
+
+ACE_INLINE int
+ACE_OS::inet_pton (int family, const char *strptr, void *addrptr)
+{
+ ACE_OS_TRACE ("ACE_OS::inet_pton");
+
+#if defined (ACE_HAS_IPV6) && !defined (ACE_WIN32)
+ ACE_OSCALL_RETURN (::inet_pton (family, strptr, addrptr), int, -1);
+#else
+ if (family == AF_INET)
+ {
+ struct in_addr in_val;
+
+ if (ACE_OS::inet_aton (strptr, &in_val))
+ {
+ ACE_OS::memcpy (addrptr, &in_val, sizeof (struct in_addr));
+ return 1; // Success
+ }
+
+ return 0; // Input is not a valid presentation format
+ }
+
+ ACE_NOTSUP_RETURN(-1);
+#endif /* ACE_HAS_IPV6 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_ctype.cpp b/ACE/ace/OS_NS_ctype.cpp
new file mode 100644
index 00000000000..6fd300d4672
--- /dev/null
+++ b/ACE/ace/OS_NS_ctype.cpp
@@ -0,0 +1,11 @@
+// -*- C++ -*-
+// $Id$
+
+#include "ace/OS_NS_ctype.h"
+
+ACE_RCSID(ace, OS_NS_ctype, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_ctype.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_ctype.h b/ACE/ace/OS_NS_ctype.h
new file mode 100644
index 00000000000..98f69623ba2
--- /dev/null
+++ b/ACE/ace/OS_NS_ctype.h
@@ -0,0 +1,130 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_ctype.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_CTYPE_H
+# define ACE_OS_NS_CTYPE_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/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ // these are non-standard names...
+
+ /** @name Functions from <cctype>
+ *
+ * Included are the functions defined in <cctype> and their <cwctype>
+ * equivalents.
+ *
+ * Since they are often implemented as macros, we don't use the same name
+ * here. Instead, we change by prepending "ace_".
+ */
+ //@{
+
+ /// Returns true if the character is an alphanumeric character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_isalnum (ACE_TCHAR c);
+
+ /// Returns true if the character is an alphabetic character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_isalpha (ACE_TCHAR c);
+
+ /// Returns true if the character is a control character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_iscntrl (ACE_TCHAR c);
+
+ /// Returns true if the character is a decimal-digit character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_isdigit (ACE_TCHAR c);
+
+ /// Returns true if the character is a printable character other than a space.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_isgraph (ACE_TCHAR c);
+
+ /// Returns true if the character is a lowercase character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_islower (ACE_TCHAR c);
+
+ /// Returns true if the character is a printable character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_isprint (ACE_TCHAR c);
+
+ /// Returns true if the character is a punctuation character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_ispunct (ACE_TCHAR c);
+
+ /// Returns true if the character is a space character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_isspace (ACE_TCHAR c);
+
+ /// Returns true if the character is an uppercase character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_isupper (ACE_TCHAR c);
+
+ /// Returns true if the character is a hexadecimal-digit character.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_isxdigit (ACE_TCHAR c);
+
+ /// Converts a character to lower case (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_tolower (int c);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Converts a character to lower case (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wint_t ace_towlower (wint_t c);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Converts a character to upper case (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ace_toupper (int c);
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_TOWUPPER)
+ /// Converts a character to upper case (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wint_t ace_towupper (wint_t c);
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_TOWUPPER */
+
+ //@}
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_ctype.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_CTYPE_H */
diff --git a/ACE/ace/OS_NS_ctype.inl b/ACE/ace/OS_NS_ctype.inl
new file mode 100644
index 00000000000..5d2177d102a
--- /dev/null
+++ b/ACE/ace/OS_NS_ctype.inl
@@ -0,0 +1,163 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/os_include/os_ctype.h"
+#if defined ACE_HAS_WCHAR
+# include "ace/os_include/os_wctype.h"
+#endif /* ACE_HAS_WCHAR */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::ace_isalnum (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+# if defined (_MSC_VER) && (_MSC_VER >= 1300)
+ // For MSVC 7.x, we need to prevent "illegal" character getting into
+ // isalnum, otherwise, it will crash the program.
+ return c > 0 && c < 256 && iswalnum (c);
+# else
+ return iswalnum (c);
+# endif /* _MSC_VER && _MSC_VER >= 1300 */
+#else /* ACE_USES_WCHAR */
+ return isalnum ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_isalpha (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswalpha (c);
+#else /* ACE_USES_WCHAR */
+ return isalpha ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_iscntrl (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswcntrl (c);
+#else /* ACE_USES_WCHAR */
+ return iscntrl ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_isdigit (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswdigit (c);
+#else /* ACE_USES_WCHAR */
+ return isdigit ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_isgraph (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswgraph (c);
+#else /* ACE_USES_WCHAR */
+ return isgraph ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_islower (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswlower (c);
+#else /* ACE_USES_WCHAR */
+ return islower ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_isprint (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswprint (c);
+#else /* ACE_USES_WCHAR */
+ return isprint ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_ispunct (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswpunct (c);
+#else /* ACE_USES_WCHAR */
+ return ispunct ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_isspace (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswspace (c);
+#else /* ACE_USES_WCHAR */
+ return isspace ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_isupper (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswupper (c);
+#else /* ACE_USES_WCHAR */
+ return isupper ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_isxdigit (ACE_TCHAR c)
+{
+#if defined (ACE_USES_WCHAR)
+ return iswxdigit (c);
+#else /* ACE_USES_WCHAR */
+ return isxdigit ((unsigned char) c);
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::ace_tolower (int c)
+{
+ return tolower (c);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wint_t
+ACE_OS::ace_towlower (wint_t c)
+{
+#if defined (ACE_LACKS_TOWLOWER)
+ if (c < 256)
+ return tolower (static_cast<int> (c));
+ else
+ return c;
+#else
+ return towlower (c);
+#endif /* ACE_LACKS_TOWLOWER */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::ace_toupper (int c)
+{
+ return toupper (c);
+}
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_TOWUPPER)
+ACE_INLINE wint_t
+ACE_OS::ace_towupper (wint_t c)
+{
+ return towupper (c);
+}
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_TOWUPPER */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_dirent.cpp b/ACE/ace/OS_NS_dirent.cpp
new file mode 100644
index 00000000000..b8c3f3401a6
--- /dev/null
+++ b/ACE/ace/OS_NS_dirent.cpp
@@ -0,0 +1,274 @@
+// $Id$
+
+#include "ace/OS_NS_dirent.h"
+
+ACE_RCSID(ace, OS_NS_dirent, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_dirent.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_LACKS_CLOSEDIR)
+void
+ACE_OS::closedir_emulation (ACE_DIR *d)
+{
+#if defined (ACE_WIN32)
+ if (d->current_handle_ != INVALID_HANDLE_VALUE)
+ ::FindClose (d->current_handle_);
+
+ d->current_handle_ = INVALID_HANDLE_VALUE;
+ d->started_reading_ = 0;
+ if (d->dirent_ != 0)
+ {
+ ACE_OS::free (d->dirent_->d_name);
+ ACE_OS::free (d->dirent_);
+ }
+#else /* ACE_WIN32 */
+ ACE_UNUSED_ARG (d);
+#endif /* ACE_WIN32 */
+}
+#endif /* ACE_LACKS_CLOSEDIR */
+
+#if defined (ACE_LACKS_OPENDIR)
+ACE_DIR *
+ACE_OS::opendir_emulation (const ACE_TCHAR *filename)
+{
+#if defined (ACE_WIN32)
+# if defined (ACE_HAS_WINCE) && !defined (INVALID_FILE_ATTRIBUTES)
+# define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
+# endif
+
+ ACE_DIR *dir;
+ ACE_TCHAR extra[3] = {0,0,0};
+
+ // Check if filename is a directory.
+ DWORD fileAttribute = ACE_TEXT_GetFileAttributes (filename);
+ if (fileAttribute == INVALID_FILE_ATTRIBUTES
+ || !(fileAttribute & FILE_ATTRIBUTE_DIRECTORY))
+ return 0;
+
+/*
+ Note: the semantics of the win32 function FindFirstFile take the
+ basename(filename) as a pattern to be matched within the dirname(filename).
+ This is contrary to the behavior of the posix function readdir which treats
+ basename(filename) as a directory to be opened and read.
+
+ For this reason, we append a slash-star or backslash-star to the supplied
+ filename so the result is that FindFirstFile will do what we need.
+
+ According to the documentation for FindFirstFile, either a '/' or a '\' may
+ be used as a directory name separator.
+
+ Of course, it is necessary to ensure that this is only done if the trailing
+ filespec is not already there.
+
+ Phil Mesnier
+*/
+
+ size_t lastchar = ACE_OS::strlen (filename);
+ if (lastchar > 0)
+ {
+ if (filename[lastchar-1] != '*')
+ {
+ if (filename[lastchar-1] != '/' && filename[lastchar-1] != '\\')
+ ACE_OS::strcpy (extra, ACE_TEXT ("/*"));
+ else
+ ACE_OS::strcpy (extra, ACE_TEXT ("*"));
+ }
+ }
+
+ ACE_NEW_RETURN (dir, ACE_DIR, 0);
+ ACE_NEW_RETURN (dir->directory_name_,
+ ACE_TCHAR[lastchar + ACE_OS::strlen (extra) + 1],
+ 0);
+ ACE_OS::strcpy (dir->directory_name_, filename);
+ if (extra[0])
+ ACE_OS::strcat (dir->directory_name_, extra);
+ dir->current_handle_ = INVALID_HANDLE_VALUE;
+ dir->started_reading_ = 0;
+ dir->dirent_ = 0;
+ return dir;
+#else /* WIN32 */
+ ACE_UNUSED_ARG (filename);
+ ACE_NOTSUP_RETURN (0);
+#endif /* WIN32 */
+}
+#endif /* ACE_LACKS_CLOSEDIR */
+
+#if defined (ACE_LACKS_READDIR)
+struct ACE_DIRENT *
+ACE_OS::readdir_emulation (ACE_DIR *d)
+{
+#if defined (ACE_WIN32)
+ if (d->dirent_ != 0)
+ {
+ ACE_OS::free (d->dirent_->d_name);
+ ACE_OS::free (d->dirent_);
+ d->dirent_ = 0;
+ }
+
+ if (!d->started_reading_)
+ {
+ d->current_handle_ = ACE_TEXT_FindFirstFile (d->directory_name_,
+ &d->fdata_);
+ d->started_reading_ = 1;
+ }
+ else
+ {
+ int retval = ACE_TEXT_FindNextFile (d->current_handle_,
+ &d->fdata_);
+ if (retval == 0)
+ {
+ // Make sure to close the handle explicitly to avoid a leak!
+ ::FindClose (d->current_handle_);
+ d->current_handle_ = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ if (d->current_handle_ != INVALID_HANDLE_VALUE)
+ {
+ d->dirent_ = (ACE_DIRENT *)
+ ACE_OS::malloc (sizeof (ACE_DIRENT));
+
+ if (d->dirent_ != 0)
+ {
+ d->dirent_->d_name = (ACE_TCHAR*)
+ ACE_OS::malloc ((ACE_OS::strlen (d->fdata_.cFileName) + 1)
+ * sizeof (ACE_TCHAR));
+ ACE_OS::strcpy (d->dirent_->d_name, d->fdata_.cFileName);
+ d->dirent_->d_reclen = sizeof (ACE_DIRENT);
+ }
+
+ return d->dirent_;
+ }
+ else
+ return 0;
+#else /* ACE_WIN32 */
+ ACE_UNUSED_ARG (d);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_WIN32 */
+}
+#endif /* ACE_LACKS_READDIR */
+
+#if !defined (ACE_HAS_SCANDIR)
+int
+ACE_OS::scandir_emulation (const ACE_TCHAR *dirname,
+ ACE_DIRENT **namelist[],
+ ACE_SCANDIR_SELECTOR selector,
+ ACE_SCANDIR_COMPARATOR comparator)
+{
+ ACE_DIR *dirp = ACE_OS::opendir (dirname);
+
+ if (dirp == 0)
+ return -1;
+ // A sanity check here. "namelist" had better not be zero.
+ else if (namelist == 0)
+ return -1;
+
+ ACE_DIRENT **vector = 0;
+ ACE_DIRENT *dp = 0;
+ int arena_size = 0;
+
+ int nfiles = 0;
+ int fail = 0;
+
+ // @@ This code shoulduse readdir_r() rather than readdir().
+ for (dp = ACE_OS::readdir (dirp);
+ dp != 0;
+ dp = ACE_OS::readdir (dirp))
+ {
+ if (selector && (*selector)(dp) == 0)
+ continue;
+
+ // If we get here, we have a dirent that the user likes.
+ if (nfiles == arena_size)
+ {
+ ACE_DIRENT **newv = 0;
+ if (arena_size == 0)
+ arena_size = 10;
+ else
+ arena_size *= 2;
+
+ newv = (ACE_DIRENT **) ACE_OS::realloc (vector,
+ arena_size * sizeof (ACE_DIRENT *));
+ if (newv == 0)
+ {
+ fail = 1;
+ break;
+ }
+ vector = newv;
+ }
+
+#if defined (ACE_LACKS_STRUCT_DIR)
+ ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_OS::malloc (sizeof (ACE_DIRENT));
+#else
+ size_t dsize =
+ sizeof (ACE_DIRENT) +
+ ((ACE_OS::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
+ ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_OS::malloc (dsize);
+#endif /* ACE_LACKS_STRUCT_DIR */
+
+ if (newdp == 0)
+ {
+ fail = 1;
+ break;
+ }
+
+#if defined (ACE_LACKS_STRUCT_DIR)
+ newdp->d_name = (ACE_TCHAR*) ACE_OS::malloc (
+ (ACE_OS::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
+
+ if (newdp->d_name == 0)
+ {
+ fail = 1;
+ ACE_OS::free (newdp);
+ break;
+ }
+
+ // Don't use memcpy here since d_name is now a pointer
+ newdp->d_ino = dp->d_ino;
+ newdp->d_off = dp->d_off;
+ newdp->d_reclen = dp->d_reclen;
+ ACE_OS::strcpy (newdp->d_name, dp->d_name);
+ vector[nfiles++] = newdp;
+#else
+ vector[nfiles++] = (ACE_DIRENT *) ACE_OS::memcpy (newdp, dp, dsize);
+#endif /* ACE_LACKS_STRUCT_DIR */
+ }
+
+ if (fail)
+ {
+ ACE_OS::closedir (dirp);
+ while (vector && nfiles-- > 0)
+ {
+#if defined (ACE_LACKS_STRUCT_DIR)
+ ACE_OS::free (vector[nfiles]->d_name);
+#endif /* ACE_LACKS_STRUCT_DIR */
+ ACE_OS::free (vector[nfiles]);
+ }
+ ACE_OS::free (vector);
+ return -1;
+ }
+
+ ACE_OS::closedir (dirp);
+
+ *namelist = vector;
+
+ if (comparator)
+ ACE_OS::qsort (*namelist,
+ nfiles,
+ sizeof (ACE_DIRENT *),
+ (ACE_COMPARE_FUNC) comparator);
+
+ return nfiles;
+}
+#endif /* !ACE_HAS_SCANDIR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_dirent.h b/ACE/ace/OS_NS_dirent.h
new file mode 100644
index 00000000000..c9f581549a2
--- /dev/null
+++ b/ACE/ace/OS_NS_dirent.h
@@ -0,0 +1,153 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_dirent.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_DIRENT_H
+# define ACE_OS_NS_DIRENT_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/os_include/os_dirent.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+// Define the scandir() selector and comparator function types. Many platforms
+// define these in terms of const pointers to dirent arrays/structs. Some
+// platforms use void pointers instead. The ACE-exported API is defined in
+// terms of the dirent-using function types, and if the OS-native scandir()
+// uses void*, that's handled internal to the ACE_OS::scandir() wrapper using
+// the ACE_SCANDIR_OS_COMPARATOR.
+extern "C" {
+#if defined (ACE_SCANDIR_CMP_USES_VOIDPTR)
+ typedef int (*ACE_SCANDIR_OS_COMPARATOR)(void *f1, void *f2);
+#elif defined (ACE_SCANDIR_CMP_USES_CONST_VOIDPTR)
+ typedef int (*ACE_SCANDIR_OS_COMPARATOR)(const void *f1, const void *f2);
+#endif /* ACE_SCANDIR_CMP_USES_VOIDPTR */
+ typedef int (*ACE_SCANDIR_COMPARATOR)(const ACE_DIRENT **f1,
+ const ACE_DIRENT **f2);
+
+#if defined (ACE_SCANDIR_SEL_LACKS_CONST)
+ typedef int (*ACE_SCANDIR_OS_SELECTOR)(ACE_DIRENT *filename);
+#endif /* ACE_SCANDIR_SEL_LACKS_CONST */
+ typedef int (*ACE_SCANDIR_SELECTOR)(const ACE_DIRENT *filename);
+}
+
+/*
+ * We inline and undef some functions that may be implemented
+ * as macros on some platforms. This way macro definitions will
+ * be usable later as there is no way to save the macro definition
+ * using the pre-processor.
+ *
+ */
+
+#if !defined (ACE_LACKS_REWINDDIR)
+# if !defined (ACE_HAS_WREWINDDIR) || !defined (ACE_USES_WCHAR)
+inline void ace_rewinddir_helper (ACE_DIR *dir)
+{
+# if defined (rewinddir)
+ rewinddir (dir);
+# undef rewinddir
+# else
+ ::rewinddir (dir);
+# endif /* defined (rewinddir) */
+}
+# endif /* !defined (ACE_HAS_WREWINDDIR) && !defined (ACE_USES_WCHAR) */
+#endif /* ACE_LACKS_REWINDDIR */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void closedir (ACE_DIR *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_DIR *opendir (const ACE_TCHAR *filename);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct ACE_DIRENT *readdir (ACE_DIR *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int readdir_r (ACE_DIR *dirp,
+ struct ACE_DIRENT *entry,
+ struct ACE_DIRENT **result);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void rewinddir (ACE_DIR *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int scandir (const ACE_TCHAR *dirname,
+ struct ACE_DIRENT **namelist[],
+ ACE_SCANDIR_SELECTOR selector,
+ ACE_SCANDIR_COMPARATOR comparator);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int alphasort (const void *, const void *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void seekdir (ACE_DIR *,
+ long loc);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long telldir (ACE_DIR *);
+
+ // Win32 emulation functions
+#if defined (ACE_LACKS_OPENDIR)
+ extern ACE_Export
+ ACE_DIR *opendir_emulation (const ACE_TCHAR *filename);
+#endif /* ACE_LACKS_OPENDIR */
+
+#if !defined (ACE_HAS_SCANDIR)
+ extern ACE_Export
+ int scandir_emulation (const ACE_TCHAR *dirname,
+ ACE_DIRENT **namelist[],
+ ACE_SCANDIR_SELECTOR selector,
+ ACE_SCANDIR_COMPARATOR comparator);
+#endif /* !ACE_HAS_SCANDIR */
+
+#if defined (ACE_LACKS_CLOSEDIR)
+ extern ACE_Export
+ void closedir_emulation (ACE_DIR *);
+#endif /* ACE_LACKS_CLOSEDIR */
+
+#if defined (ACE_LACKS_READDIR)
+ extern ACE_Export
+ struct ACE_DIRENT *readdir_emulation (ACE_DIR *);
+#endif /* ACE_LACKS_READDIR */
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_dirent.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_DIRENT_H */
diff --git a/ACE/ace/OS_NS_dirent.inl b/ACE/ace/OS_NS_dirent.inl
new file mode 100644
index 00000000000..b32b98ac87a
--- /dev/null
+++ b/ACE/ace/OS_NS_dirent.inl
@@ -0,0 +1,184 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_Memory.h"
+
+#if defined (ACE_LACKS_ALPHASORT)
+# include "ace/OS_NS_string.h"
+#endif /* ACE_LACKS_ALPHASORT */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ACE_INLINE void
+closedir (ACE_DIR *d)
+{
+#if defined (ACE_HAS_DIRENT)
+# if defined (ACE_WIN32) && defined (ACE_LACKS_CLOSEDIR)
+ ACE_OS::closedir_emulation (d);
+ delete [] d->directory_name_;
+ delete d;
+# elif defined (ACE_HAS_WCLOSEDIR) && defined (ACE_USES_WCHAR)
+ ::wclosedir (d);
+# else /* ACE_WIN32 && ACE_LACKS_CLOSEDIR */
+ ::closedir (d);
+# endif /* ACE_WIN32 && ACE_LACKS_CLOSEDIR */
+
+#else /* ACE_HAS_DIRENT */
+ ACE_UNUSED_ARG (d);
+#endif /* ACE_HAS_DIRENT */
+}
+
+ACE_INLINE ACE_DIR *
+opendir (const ACE_TCHAR *filename)
+{
+#if defined (ACE_HAS_DIRENT)
+# if defined (ACE_WIN32) && defined (ACE_LACKS_OPENDIR)
+ return ::ACE_OS::opendir_emulation (filename);
+# elif defined (ACE_HAS_WOPENDIR) && defined (ACE_USES_WCHAR)
+ return ::wopendir (filename);
+# elif defined (ACE_HAS_NONCONST_OPENDIR)
+ return ::opendir (const_cast<char *> (filename));
+# else /* ! ACE_WIN32 && ACE_LACKS_OPENDIR */
+ return ::opendir (ACE_TEXT_ALWAYS_CHAR (filename));
+# endif /* ACE_WIN32 && ACE_LACKS_OPENDIR */
+#else
+ ACE_UNUSED_ARG (filename);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_DIRENT */
+}
+
+ACE_INLINE struct ACE_DIRENT *
+readdir (ACE_DIR *d)
+{
+#if defined (ACE_HAS_DIRENT)
+# if defined (ACE_WIN32) && defined (ACE_LACKS_READDIR)
+ return ACE_OS::readdir_emulation (d);
+# elif defined (ACE_HAS_WREADDIR) && defined (ACE_USES_WCHAR)
+ return ::wreaddir (d);
+# else /* ACE_WIN32 && ACE_LACKS_READDIR */
+ return ::readdir (d);
+# endif /* ACE_WIN32 && ACE_LACKS_READDIR */
+#else
+ ACE_UNUSED_ARG (d);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_DIRENT */
+}
+
+ACE_INLINE int
+readdir_r (ACE_DIR *dirp,
+ struct ACE_DIRENT *entry,
+ struct ACE_DIRENT **result)
+{
+#if !defined (ACE_HAS_REENTRANT_FUNCTIONS)
+ ACE_UNUSED_ARG (entry);
+ // <result> has better not be 0!
+ *result = ACE_OS::readdir (dirp);
+ if (*result)
+ return 0; // Keep iterating
+ else
+ return 1; // Oops, some type of error!
+#elif defined (ACE_HAS_DIRENT) && !defined (ACE_LACKS_READDIR_R)
+# if defined (ACE_HAS_3_PARAM_READDIR_R)
+ return ::readdir_r (dirp, entry, result);
+# else
+ // <result> had better not be 0!
+ *result = ::readdir_r (dirp, entry);
+ return 0;
+# endif /* sun */
+#else /* ! ACE_HAS_DIRENT || ACE_LACKS_READDIR_R */
+ ACE_UNUSED_ARG (dirp);
+ ACE_UNUSED_ARG (entry);
+ ACE_UNUSED_ARG (result);
+ ACE_NOTSUP_RETURN (0);
+
+#endif /* ACE_HAS_REENTRANT_FUNCTIONS */
+}
+
+ACE_INLINE void
+rewinddir (ACE_DIR *d)
+{
+#if defined (ACE_HAS_DIRENT)
+# if defined (ACE_HAS_WREWINDDIR) && defined (ACE_USES_WCHAR)
+ ::wrewinddir (d);
+# elif !defined (ACE_LACKS_REWINDDIR)
+ ace_rewinddir_helper (d);
+# else
+ ACE_UNUSED_ARG (d);
+# endif /* !defined (ACE_LACKS_REWINDDIR) */
+#endif /* ACE_HAS_DIRENT */
+}
+
+ACE_INLINE int
+scandir (const ACE_TCHAR *dirname,
+ struct ACE_DIRENT **namelist[],
+ ACE_SCANDIR_SELECTOR selector,
+ ACE_SCANDIR_COMPARATOR comparator)
+{
+#if defined (ACE_HAS_SCANDIR)
+ return ::scandir (ACE_TEXT_ALWAYS_CHAR (dirname),
+ namelist,
+# if defined (ACE_SCANDIR_SEL_LACKS_CONST)
+ reinterpret_cast<ACE_SCANDIR_OS_SELECTOR> (selector),
+# else
+ selector,
+# endif /* ACE_SCANDIR_SEL_LACKS_CONST */
+# if defined (ACE_SCANDIR_CMP_USES_VOIDPTR) || \
+ defined (ACE_SCANDIR_CMP_USES_CONST_VOIDPTR)
+ reinterpret_cast<ACE_SCANDIR_OS_COMPARATOR> (comparator));
+# else
+ comparator);
+# endif /* ACE_SCANDIR_CMP_USES_VOIDPTR */
+
+#else /* ! defined ( ACE_HAS_SCANDIR) */
+ return ACE_OS::scandir_emulation (dirname, namelist, selector, comparator);
+#endif /* ACE_HAS_SCANDIR */
+}
+
+ACE_INLINE int
+alphasort (const void *a, const void *b)
+{
+#if defined (ACE_LACKS_ALPHASORT)
+ return ACE_OS::strcmp ((*static_cast<const struct ACE_DIRENT * const *>(a))->d_name,
+ (*static_cast<const struct ACE_DIRENT * const *>(b))->d_name);
+#else
+# if defined (ACE_SCANDIR_CMP_USES_VOIDPTR)
+ return ::alphasort (const_cast<void *>(a),
+ const_cast<void *>(b));
+# elif defined (ACE_SCANDIR_CMP_USES_CONST_VOIDPTR)
+ return ::alphasort (a, b);
+# else
+ return ::alphasort ((const struct ACE_DIRENT **)a,
+ (const struct ACE_DIRENT **)b);
+# endif
+#endif
+}
+
+ACE_INLINE void
+seekdir (ACE_DIR *d, long loc)
+{
+#if defined (ACE_HAS_DIRENT) && !defined (ACE_LACKS_SEEKDIR)
+ ::seekdir (d, loc);
+#else /* ! ACE_HAS_DIRENT || ACE_LACKS_SEEKDIR */
+ ACE_UNUSED_ARG (d);
+ ACE_UNUSED_ARG (loc);
+#endif /* ! ACE_HAS_DIRENT || ACE_LACKS_SEEKDIR */
+}
+
+ACE_INLINE long
+telldir (ACE_DIR *d)
+{
+#if defined (ACE_HAS_DIRENT) && !defined (ACE_LACKS_TELLDIR)
+ return ::telldir (d);
+#else /* ! ACE_HAS_DIRENT || ACE_LACKS_TELLDIR */
+ ACE_UNUSED_ARG (d);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ! ACE_HAS_DIRENT || ACE_LACKS_TELLDIR */
+}
+
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_dlfcn.cpp b/ACE/ace/OS_NS_dlfcn.cpp
new file mode 100644
index 00000000000..1bf2b9c532e
--- /dev/null
+++ b/ACE/ace/OS_NS_dlfcn.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_dlfcn.h"
+
+ACE_RCSID(ace, OS_NS_dlfcn, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_dlfcn.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_dlfcn.h b/ACE/ace/OS_NS_dlfcn.h
new file mode 100644
index 00000000000..80bb1ec689c
--- /dev/null
+++ b/ACE/ace/OS_NS_dlfcn.h
@@ -0,0 +1,69 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_dlfcn.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_DLFCN_H
+# define ACE_OS_NS_DLFCN_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/os_include/os_dlfcn.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ //@{ @name A set of wrappers for explicit dynamic linking.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int dlclose (ACE_SHLIB_HANDLE handle);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_TCHAR *dlerror (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_SHLIB_HANDLE dlopen (const ACE_TCHAR *filename,
+ int mode = ACE_DEFAULT_SHLIB_MODE);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *dlsym (ACE_SHLIB_HANDLE handle,
+ const ACE_TCHAR *symbol);
+ //@}
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_dlfcn.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_DLFCN_H */
diff --git a/ACE/ace/OS_NS_dlfcn.inl b/ACE/ace/OS_NS_dlfcn.inl
new file mode 100644
index 00000000000..5b5e4142bb3
--- /dev/null
+++ b/ACE/ace/OS_NS_dlfcn.inl
@@ -0,0 +1,286 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_macros.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Default_Constants.h"
+#include "ace/os_include/os_fcntl.h"
+#include "ace/os_include/os_string.h"
+
+#if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
+# include "ace/OS_NS_stdio.h"
+#endif
+
+#if defined (ACE_USES_ASM_SYMBOL_IN_DLSYM)
+# include "ace/OS_Memory.h"
+# include "ace/OS_NS_string.h"
+#endif /* ACE_USES_ASM_SYMBOL_IN_DLSYM */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::dlclose (ACE_SHLIB_HANDLE handle)
+{
+ ACE_OS_TRACE ("ACE_OS::dlclose");
+#if defined (ACE_LACKS_DLCLOSE)
+ ACE_UNUSED_ARG (handle);
+ return 0;
+#elif defined (ACE_HAS_SVR4_DYNAMIC_LINKING)
+
+# if !defined (ACE_HAS_AUTOMATIC_INIT_FINI)
+ // SunOS4 does not automatically call _fini()!
+ void *ptr;
+
+ ACE_OSCALL (::dlsym (handle, ACE_TEXT ("_fini")), void *, 0, ptr);
+
+ if (ptr != 0)
+ (*((int (*)(void)) ptr)) (); // Call _fini hook explicitly.
+# endif /* ACE_HAS_AUTOMATIC_INIT_FINI */
+#if defined (_M_UNIX)
+ ACE_OSCALL_RETURN (::_dlclose (handle), int, -1);
+#else /* _MUNIX */
+ ACE_OSCALL_RETURN (::dlclose (handle), int, -1);
+#endif /* _M_UNIX */
+#elif defined (ACE_WIN32)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::FreeLibrary (handle), ace_result_), int, -1);
+#elif defined (__hpux)
+ // HP-UX 10.x and 32-bit 11.00 do not pay attention to the ref count
+ // when unloading a dynamic lib. So, if the ref count is more than
+ // 1, do not unload the lib. This will cause a library loaded more
+ // than once to not be unloaded until the process runs down, but
+ // that's life. It's better than unloading a library that's in use.
+ // So far as I know, there's no way to decrement the refcnt that the
+ // kernel is looking at - the shl_descriptor is a copy of what the
+ // kernel has, not the actual struct. On 64-bit HP-UX using dlopen,
+ // this problem has been fixed.
+ struct shl_descriptor desc;
+ if (shl_gethandle_r (handle, &desc) == -1)
+ return -1;
+ if (desc.ref_count > 1)
+ return 0;
+# if defined(__GNUC__) || __cplusplus >= 199707L
+ ACE_OSCALL_RETURN (::shl_unload (handle), int, -1);
+# else
+ ACE_OSCALL_RETURN (::cxxshl_unload (handle), int, -1);
+# endif /* aC++ vs. Hp C++ */
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */
+}
+
+ACE_INLINE ACE_TCHAR *
+ACE_OS::dlerror (void)
+{
+ ACE_OS_TRACE ("ACE_OS::dlerror");
+# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING)
+ const char *err;
+# if defined(_M_UNIX)
+ ACE_OSCALL (::_dlerror (), const char *, 0, err);
+# else /* _M_UNIX */
+ ACE_OSCALL (::dlerror (), const char *, 0, err);
+# endif /* _M_UNIX */
+ if (err == 0)
+ return 0;
+# if defined (ACE_USES_WCHAR)
+ const size_t BufLen = 256;
+ static wchar_t buf[BufLen];
+ ACE_OS::strncpy (buf, ACE_TEXT_CHAR_TO_TCHAR (err), BufLen);
+ return buf;
+# else
+ return const_cast <char *> (err);
+# endif /* ACE_USES_WCHAR */
+# elif defined (__hpux) || defined (ACE_VXWORKS)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (::strerror(errno), char *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# elif defined (ACE_WIN32)
+ static ACE_TCHAR buf[128];
+# if defined (ACE_HAS_PHARLAP)
+ ACE_OS::sprintf (buf, "error code %d", GetLastError());
+# else
+ ACE_TEXT_FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ ::GetLastError (),
+ 0,
+ buf,
+ sizeof buf / sizeof buf[0],
+ 0);
+# endif /* ACE_HAS_PHARLAP */
+ return buf;
+# else
+ ACE_NOTSUP_RETURN (0);
+# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */
+}
+
+ACE_INLINE ACE_SHLIB_HANDLE
+ACE_OS::dlopen (const ACE_TCHAR *fname,
+ int mode)
+{
+ ACE_OS_TRACE ("ACE_OS::dlopen");
+
+# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING)
+ void *handle;
+# if defined (ACE_HAS_SGIDLADD)
+ ACE_OSCALL
+ (::sgidladd (ACE_TEXT_ALWAYS_CHAR (fname), mode), void *, 0, handle);
+# elif defined (_M_UNIX)
+ ACE_OSCALL
+ (::_dlopen (ACE_TEXT_ALWAYS_CHAR (fname), mode), void *, 0, handle);
+# else
+ ACE_OSCALL
+ (::dlopen (ACE_TEXT_ALWAYS_CHAR (fname), mode), void *, 0, handle);
+# endif /* ACE_HAS_SGIDLADD */
+# if !defined (ACE_HAS_AUTOMATIC_INIT_FINI)
+ if (handle != 0)
+ {
+ void *ptr;
+ // Some systems (e.g., SunOS4) do not automatically call _init(), so
+ // we'll have to call it manually.
+
+ ACE_OSCALL (::dlsym (handle, ACE_TEXT ("_init")), void *, 0, ptr);
+
+ if (ptr != 0 && (*((int (*)(void)) ptr)) () == -1) // Call _init hook explicitly.
+ {
+ // Close down the handle to prevent leaks.
+ ::dlclose (handle);
+ return 0;
+ }
+ }
+# endif /* ACE_HAS_AUTOMATIC_INIT_FINI */
+ return handle;
+# elif defined (ACE_WIN32)
+ ACE_UNUSED_ARG (mode);
+
+ ACE_WIN32CALL_RETURN (ACE_TEXT_LoadLibrary (fname), ACE_SHLIB_HANDLE, 0);
+# elif defined (__hpux)
+
+# if defined(__GNUC__) || __cplusplus >= 199707L
+ ACE_OSCALL_RETURN (::shl_load(fname, mode, 0L), ACE_SHLIB_HANDLE, 0);
+# else
+ ACE_OSCALL_RETURN (::cxxshl_load(fname, mode, 0L), ACE_SHLIB_HANDLE, 0);
+# endif /* aC++ vs. Hp C++ */
+# elif defined (ACE_VXWORKS) && !defined (__RTP__)
+ MODULE* handle = 0;
+ // Open readonly
+ ACE_HANDLE filehandle = ACE_OS::open (fname,
+ O_RDONLY,
+ ACE_DEFAULT_FILE_PERMS);
+
+ if (filehandle != ACE_INVALID_HANDLE)
+ {
+ ACE_OS::last_error(0);
+ ACE_OSCALL ( ::loadModule (filehandle, LOAD_GLOBAL_SYMBOLS|LOAD_COMMON_MATCH_ALL ), MODULE *, 0, handle);
+ int loaderror = ACE_OS::last_error();
+ ACE_OS::close (filehandle);
+
+ if ( (loaderror != 0) && (handle != 0) )
+ {
+ // ouch something went wrong most likely unresolved externals
+ if (handle)
+ ::unldByModuleId ( handle, 0 );
+ handle = 0;
+ }
+ }
+ else
+ {
+ // couldn't open file
+ handle = 0;
+ }
+ return handle;
+# else
+ ACE_UNUSED_ARG (fname);
+ ACE_UNUSED_ARG (mode);
+ ACE_NOTSUP_RETURN (0);
+# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */
+}
+
+ACE_INLINE void *
+ACE_OS::dlsym (ACE_SHLIB_HANDLE handle,
+ const ACE_TCHAR *sname)
+{
+ ACE_OS_TRACE ("ACE_OS::dlsym");
+
+#if defined (ACE_HAS_DLSYM_SEGFAULT_ON_INVALID_HANDLE)
+ // Check if the handle is valid before making any calls using it.
+ if (handle == ACE_SHLIB_INVALID_HANDLE)
+ return 0;
+#endif /* ACE_HAS_DLSYM_SEGFAULT_ON_INVALID_HANDLE */
+
+ // Get the correct OS type.
+#if defined (ACE_HAS_WINCE)
+ // CE (at least thru Pocket PC 2003) offers GetProcAddressW, not ...A, so
+ // we always need a wide-char string.
+ const wchar_t *symbolname = 0;
+# if defined (ACE_USES_WCHAR)
+ symbolname = sname;
+# else
+ ACE_Ascii_To_Wide sname_xlate (sname);
+ symbolname = sname_xlate.wchar_rep ();
+# endif /* ACE_USES_WCHAR */
+#elif defined (ACE_USES_WCHAR)
+ // WinCE is WCHAR always; other platforms need a char * symbol name
+ ACE_Wide_To_Ascii w_sname (sname);
+ char *symbolname = w_sname.char_rep ();
+#elif defined (ACE_VXWORKS)
+ char *symbolname = const_cast<char *> (sname);
+#else
+ const char *symbolname = sname;
+#endif /* ACE_HAS_WINCE */
+
+# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING)
+
+# if defined (ACE_USES_ASM_SYMBOL_IN_DLSYM)
+ int l = ACE_OS::strlen (symbolname) + 2;
+ char *asm_symbolname = 0;
+ ACE_NEW_RETURN (asm_symbolname, char[l], 0);
+ ACE_OS::strcpy (asm_symbolname, "_") ;
+ ACE_OS::strcpy (asm_symbolname + 1, symbolname) ;
+ void *ace_result;
+ ACE_OSCALL (::dlsym (handle, asm_symbolname), void *, 0, ace_result);
+ delete [] asm_symbolname;
+ return ace_result;
+# elif defined (_M_UNIX)
+ ACE_OSCALL_RETURN (::_dlsym (handle, symbolname), void *, 0);
+# else
+ ACE_OSCALL_RETURN (::dlsym (handle, symbolname), void *, 0);
+# endif /* ACE_USES_ASM_SYMBOL_IN_DLSYM */
+
+# elif defined (ACE_WIN32)
+
+ ACE_WIN32CALL_RETURN (::GetProcAddress (handle, symbolname), void *, 0);
+
+# elif defined (__hpux)
+
+ void *value = 0;
+ int status;
+ shl_t _handle = handle;
+ ACE_OSCALL (::shl_findsym(&_handle, symbolname, TYPE_UNDEFINED, &value), int, -1, status);
+ return status == 0 ? value : 0;
+
+# elif defined (ACE_VXWORKS) && !defined (__RTP__)
+
+ // For now we use the VxWorks global symbol table
+ // which resolves the most recently loaded symbols .. which resolve mostly what we want..
+ ACE_UNUSED_ARG (handle);
+ SYM_TYPE symtype;
+ char *value = 0;
+ STATUS status;
+ ACE_OSCALL (::symFindByName(sysSymTbl, symbolname, &value, &symtype), int, -1, status);
+
+ return status == OK ? reinterpret_cast <void*>(value) : 0;
+
+# else
+
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (symbolname);
+ ACE_NOTSUP_RETURN (0);
+
+# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_errno.cpp b/ACE/ace/OS_NS_errno.cpp
new file mode 100644
index 00000000000..f8f60c0565f
--- /dev/null
+++ b/ACE/ace/OS_NS_errno.cpp
@@ -0,0 +1,11 @@
+// -*- C++ -*-
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+
+ACE_RCSID(ace, OS_NS_errno, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_errno.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_errno.h b/ACE/ace/OS_NS_errno.h
new file mode 100644
index 00000000000..85e85735b2c
--- /dev/null
+++ b/ACE/ace/OS_NS_errno.h
@@ -0,0 +1,100 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_errno.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_ERRNO_H
+# define ACE_OS_NS_ERRNO_H
+
+# include /**/ "ace/pre.h"
+
+# include "ace/config-lite.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_errno.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int last_error (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void last_error (int);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int set_errno_to_last_error (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int set_errno_to_wsa_last_error (void);
+
+} /* namespace ACE_OS */
+
+#if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
+/**
+ * @class ACE_CE_Errno
+ *
+ * Some versions of CE don't support @c errno and some versions'
+ * implementations are busted. So we implement our own.
+ * Our implementation takes up one Tls key, however, it does not
+ * allocate memory fromt the heap so there's no problem with cleanin
+ * up the errno when a thread exit.
+ */
+class ACE_Export ACE_CE_Errno
+{
+public:
+ ACE_CE_Errno () {}
+ static void init ();
+ static void fini ();
+ static ACE_CE_Errno *instance ();
+
+ operator int (void) const;
+ int operator= (int);
+
+private:
+ static ACE_CE_Errno *instance_;
+ static DWORD errno_key_;
+};
+
+# define errno (* (ACE_CE_Errno::instance ()))
+#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
+
+#if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
+# define ACE_ERRNO_TYPE ACE_CE_Errno
+#else
+# define ACE_ERRNO_TYPE int
+#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_errno.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_ERRNO_H */
diff --git a/ACE/ace/OS_NS_errno.inl b/ACE/ace/OS_NS_errno.inl
new file mode 100644
index 00000000000..9e8ce9e7bc2
--- /dev/null
+++ b/ACE/ace/OS_NS_errno.inl
@@ -0,0 +1,83 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/config-all.h" /* Need ACE_TRACE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::last_error (void)
+{
+ // ACE_OS_TRACE ("ACE_OS::last_error");
+
+#if defined (ACE_WIN32)
+ // ACE_OS::last_error() prefers errnor since started out as a way to
+ // avoid directly accessing errno in ACE code - particularly the ACE
+ // C++ socket wrapper facades. On Windows, some things that would
+ // use errno on UNIX require ::GetLastError(), so this method tries
+ // to shield the rest of ACE from having to know about this.
+ int lerror = ::GetLastError ();
+ int lerrno = errno;
+ return lerrno == 0 ? lerror : lerrno;
+#else
+ return errno;
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE void
+ACE_OS::last_error (int error)
+{
+ ACE_OS_TRACE ("ACE_OS::last_error");
+#if defined (ACE_WIN32)
+ ::SetLastError (error);
+#endif /* ACE_WIN32 */
+ errno = error;
+}
+
+ACE_INLINE int
+ACE_OS::set_errno_to_last_error (void)
+{
+# if defined (ACE_WIN32)
+ return errno = ::GetLastError ();
+#else
+ return errno;
+# endif /* defined(ACE_WIN32) */
+}
+
+ACE_INLINE int
+ACE_OS::set_errno_to_wsa_last_error (void)
+{
+# if defined (ACE_WIN32)
+ return errno = ::WSAGetLastError ();
+#else
+ return errno;
+# endif /* defined(ACE_WIN32) */
+}
+
+#if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
+
+ACE_INLINE ACE_CE_Errno *
+ACE_CE_Errno::instance ()
+{
+ // This should be inlined.
+ return ACE_CE_Errno::instance_;
+}
+
+ACE_INLINE
+ACE_CE_Errno::operator int (void) const
+{
+ return (int) TlsGetValue (ACE_CE_Errno::errno_key_);
+}
+
+ACE_INLINE int
+ACE_CE_Errno::operator= (int x)
+{
+ // error checking?
+ TlsSetValue (ACE_CE_Errno::errno_key_, (void *) x);
+ return x;
+}
+
+#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_fcntl.cpp b/ACE/ace/OS_NS_fcntl.cpp
new file mode 100644
index 00000000000..2ab9fbbdf1d
--- /dev/null
+++ b/ACE/ace/OS_NS_fcntl.cpp
@@ -0,0 +1,245 @@
+// $Id$
+
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID(ace, OS_NS_fcntl, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_fcntl.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_Thread.h"
+#include "ace/OS_NS_macros.h"
+#include "ace/Object_Manager_Base.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_HANDLE
+ACE_OS::open (const char *filename,
+ int mode,
+ mode_t perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_OS_TRACE ("ACE_OS::open");
+
+#if defined (ACE_WIN32)
+ DWORD access = GENERIC_READ;
+ if (ACE_BIT_ENABLED (mode, O_WRONLY))
+ access = GENERIC_WRITE;
+ else if (ACE_BIT_ENABLED (mode, O_RDWR))
+ access = GENERIC_READ | GENERIC_WRITE;
+
+ DWORD creation = OPEN_EXISTING;
+
+ if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
+ creation = CREATE_NEW;
+ else if ((mode & (_O_CREAT | _O_TRUNC)) == (_O_CREAT | _O_TRUNC))
+ creation = CREATE_ALWAYS;
+ else if (ACE_BIT_ENABLED (mode, _O_CREAT))
+ creation = OPEN_ALWAYS;
+ else if (ACE_BIT_ENABLED (mode, _O_TRUNC))
+ creation = TRUNCATE_EXISTING;
+
+ DWORD flags = 0;
+
+ if (ACE_BIT_ENABLED (mode, _O_TEMPORARY))
+ flags |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
+
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_WRITE_THROUGH))
+ flags |= FILE_FLAG_WRITE_THROUGH;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_OVERLAPPED))
+ flags |= FILE_FLAG_OVERLAPPED;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_NO_BUFFERING))
+ flags |= FILE_FLAG_NO_BUFFERING;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_RANDOM_ACCESS))
+ flags |= FILE_FLAG_RANDOM_ACCESS;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_SEQUENTIAL_SCAN))
+ flags |= FILE_FLAG_SEQUENTIAL_SCAN;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_DELETE_ON_CLOSE))
+ flags |= FILE_FLAG_DELETE_ON_CLOSE;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_BACKUP_SEMANTICS))
+ flags |= FILE_FLAG_BACKUP_SEMANTICS;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_POSIX_SEMANTICS))
+ flags |= FILE_FLAG_POSIX_SEMANTICS;
+
+ ACE_MT (ACE_thread_mutex_t *ace_os_monitor_lock = 0;)
+
+ if (ACE_BIT_ENABLED (mode, _O_APPEND))
+ {
+ ACE_MT
+ (
+ ace_os_monitor_lock = static_cast <ACE_thread_mutex_t *> (
+ ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
+ ACE_OS::thread_mutex_lock (ace_os_monitor_lock);
+ )
+ }
+
+ DWORD shared_mode = perms;
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+
+#if defined (ACE_HAS_WINCE)
+ ACE_HANDLE h = ::CreateFileW (ACE_Ascii_To_Wide (filename).wchar_rep (),
+ access,
+ shared_mode,
+ ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ creation,
+ flags,
+ 0);
+#else /* ACE_HAS_WINCE */
+ ACE_HANDLE h = ::CreateFileA (filename,
+ access,
+ shared_mode,
+ ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ creation,
+ flags,
+ 0);
+#endif /* ACE_HAS_WINCE */
+
+ if (ACE_BIT_ENABLED (mode, _O_APPEND))
+ {
+ LONG high_size = 0;
+ if (h != ACE_INVALID_HANDLE
+ && ::SetFilePointer (h,
+ 0,
+ &high_size,
+ FILE_END) == INVALID_SET_FILE_POINTER
+ && GetLastError () != NO_ERROR)
+ {
+ ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);)
+ ACE_FAIL_RETURN (ACE_INVALID_HANDLE);
+ }
+
+ ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);)
+ }
+
+ if (h == ACE_INVALID_HANDLE)
+ ACE_FAIL_RETURN (h);
+ else
+ return h;
+#elif defined (INTEGRITY)
+ ACE_UNUSED_ARG (sa);
+ if(!strcmp(filename,ACE_DEV_NULL)) {
+ ACE_OSCALL_RETURN (::AllocateNullConsoleDescriptor(), ACE_HANDLE, -1);
+ }
+ else {
+ ACE_OSCALL_RETURN (::open (filename, mode, perms), ACE_HANDLE, -1);
+ }
+#else
+ ACE_UNUSED_ARG (sa);
+ ACE_OSCALL_RETURN (::open (filename, mode, perms), ACE_HANDLE, ACE_INVALID_HANDLE);
+#endif /* ACE_WIN32 */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_HANDLE
+ACE_OS::open (const wchar_t *filename,
+ int mode,
+ mode_t perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+#if defined (ACE_WIN32)
+ // @@ (brunsch) Yuck, maybe there is a way to combine the code
+ // here with the char version
+
+ DWORD access = GENERIC_READ;
+ if (ACE_BIT_ENABLED (mode, O_WRONLY))
+ access = GENERIC_WRITE;
+ else if (ACE_BIT_ENABLED (mode, O_RDWR))
+ access = GENERIC_READ | GENERIC_WRITE;
+
+ DWORD creation = OPEN_EXISTING;
+
+ if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
+ creation = CREATE_NEW;
+ else if ((mode & (_O_CREAT | _O_TRUNC)) == (_O_CREAT | _O_TRUNC))
+ creation = CREATE_ALWAYS;
+ else if (ACE_BIT_ENABLED (mode, _O_CREAT))
+ creation = OPEN_ALWAYS;
+ else if (ACE_BIT_ENABLED (mode, _O_TRUNC))
+ creation = TRUNCATE_EXISTING;
+
+ DWORD flags = 0;
+
+ if (ACE_BIT_ENABLED (mode, _O_TEMPORARY))
+ flags |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
+
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_WRITE_THROUGH))
+ flags |= FILE_FLAG_WRITE_THROUGH;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_OVERLAPPED))
+ flags |= FILE_FLAG_OVERLAPPED;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_NO_BUFFERING))
+ flags |= FILE_FLAG_NO_BUFFERING;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_RANDOM_ACCESS))
+ flags |= FILE_FLAG_RANDOM_ACCESS;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_SEQUENTIAL_SCAN))
+ flags |= FILE_FLAG_SEQUENTIAL_SCAN;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_DELETE_ON_CLOSE))
+ flags |= FILE_FLAG_DELETE_ON_CLOSE;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_BACKUP_SEMANTICS))
+ flags |= FILE_FLAG_BACKUP_SEMANTICS;
+ if (ACE_BIT_ENABLED (mode, FILE_FLAG_POSIX_SEMANTICS))
+ flags |= FILE_FLAG_POSIX_SEMANTICS;
+
+ ACE_MT (ACE_thread_mutex_t *ace_os_monitor_lock = 0;)
+
+ if (ACE_BIT_ENABLED (mode, _O_APPEND))
+ {
+ ACE_MT
+ (
+ ace_os_monitor_lock = static_cast <ACE_thread_mutex_t *> (
+ ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
+ ACE_OS::thread_mutex_lock (ace_os_monitor_lock);
+ )
+ }
+
+ DWORD shared_mode = perms;
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+
+ ACE_HANDLE h = ::CreateFileW (filename,
+ access,
+ shared_mode,
+ ACE_OS::default_win32_security_attributes_r
+ (sa, &sa_buffer, &sd_buffer),
+ creation,
+ flags,
+ 0);
+
+ if (ACE_BIT_ENABLED (mode, _O_APPEND))
+ {
+ LONG high_size = 0;
+ if (h != ACE_INVALID_HANDLE
+ && ::SetFilePointer (h,
+ 0,
+ &high_size,
+ FILE_END) == INVALID_SET_FILE_POINTER
+ && GetLastError () != NO_ERROR)
+ {
+ ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);)
+ ACE_FAIL_RETURN (ACE_INVALID_HANDLE);
+ }
+
+ ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);)
+ }
+
+ if (h == ACE_INVALID_HANDLE)
+ ACE_FAIL_RETURN (h);
+ else
+ return h;
+#else /* ACE_WIN32 */
+ // Just emulate with ascii version
+ return ACE_OS::open (ACE_Wide_To_Ascii (filename).char_rep (),
+ mode,
+ perms,
+ sa);
+#endif /* ACE_WIN32 */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_fcntl.h b/ACE/ace/OS_NS_fcntl.h
new file mode 100644
index 00000000000..dcfa1eec934
--- /dev/null
+++ b/ACE/ace/OS_NS_fcntl.h
@@ -0,0 +1,83 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_fcntl.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_FCNTL_H
+# define ACE_OS_NS_FCNTL_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/os_include/os_fcntl.h"
+#include "ace/Global_Macros.h" // for LPSECURITY_ATTRIBUTES :-(
+#include "ace/Default_Constants.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fcntl (ACE_HANDLE handle,
+ int cmd,
+ long arg = 0);
+
+#if !defined (ACE_DEFAULT_OPEN_PERMS)
+# define ACE_DEFAULT_OPEN_PERMS ACE_DEFAULT_FILE_PERMS
+#endif /* ACE_DEFAULT_OPEN_PERMS */
+
+ /// 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.
+ extern ACE_Export
+ ACE_HANDLE open (const char *filename,
+ int mode,
+ mode_t perms = ACE_DEFAULT_OPEN_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+#if defined (ACE_HAS_WCHAR)
+ extern ACE_Export
+ ACE_HANDLE open (const wchar_t *filename,
+ int mode,
+ mode_t perms = ACE_DEFAULT_OPEN_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+#endif /* ACE_HAS_WCHAR */
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_fcntl.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_FCNTL_H */
diff --git a/ACE/ace/OS_NS_fcntl.inl b/ACE/ace/OS_NS_fcntl.inl
new file mode 100644
index 00000000000..6714b0fe389
--- /dev/null
+++ b/ACE/ace/OS_NS_fcntl.inl
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::fcntl (ACE_HANDLE handle, int cmd, long arg)
+{
+ ACE_OS_TRACE ("ACE_OS::fcntl");
+# if defined (ACE_LACKS_FCNTL)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (cmd);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ ACE_OSCALL_RETURN (::fcntl (handle, cmd, arg), int, -1);
+# endif /* ACE_LACKS_FCNTL */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_macros.h b/ACE/ace/OS_NS_macros.h
new file mode 100644
index 00000000000..8f47d150679
--- /dev/null
+++ b/ACE/ace/OS_NS_macros.h
@@ -0,0 +1,114 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_macros.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_MACROS_H
+# define ACE_OS_NS_MACROS_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)
+# define ACE_SOCKCALL_RETURN(OP,TYPE,FAILVALUE) \
+ do { TYPE ace_result_ = (TYPE) OP; \
+ if (ace_result_ == FAILVALUE) { int ___ = ::WSAGetLastError (); errno = ___; return (TYPE) FAILVALUE; } else return ace_result_; \
+ } while (0)
+# define ACE_SOCKCALL(OP,TYPE,FAILVALUE,RESULT) \
+ do { RESULT = (TYPE) OP; \
+ if (RESULT == FAILVALUE) { int ___ = ::WSAGetLastError (); errno = ___; RESULT = FAILVALUE; } \
+ } while (0)
+#else
+# define ACE_SOCKCALL_RETURN(OP,TYPE,FAILVALUE) ACE_OSCALL_RETURN(OP,TYPE,FAILVALUE)
+# define ACE_SOCKCALL(OP,TYPE,FAILVALUE,RESULT) ACE_OSCALL(OP,TYPE,FAILVALUE,RESULT)
+#endif /* ACE_WIN32 */
+
+#if !defined (ACE_WIN32)
+
+// Adapt the weird threading and synchronization routines (which
+// return errno rather than -1) so that they return -1 and set errno.
+// This is more consistent with the rest of ACE_OS and enables us to
+// use the ACE_OSCALL* macros.
+# if defined (ACE_VXWORKS)
+# define ACE_ADAPT_RETVAL(OP,RESULT) ((RESULT = (OP)) != OK ? (errno = RESULT, -1) : 0)
+# else
+# define ACE_ADAPT_RETVAL(OP,RESULT) ((RESULT = (OP)) != 0 ? (errno = RESULT, -1) : 0)
+# endif /* ACE_VXWORKS */
+
+#else /* ACE_WIN32 */
+
+// Adapt the Win32 System Calls (which return BOOLEAN values of TRUE
+// and FALSE) into int values expected by the ACE_OSCALL macros.
+# define ACE_ADAPT_RETVAL(OP,RESULT) ((RESULT = (OP)) == FALSE ? -1 : 0)
+
+// Perform a mapping of Win32 error numbers into POSIX errnos.
+# define ACE_FAIL_RETURN(RESULT) do { \
+ switch (ACE_OS::set_errno_to_last_error ()) { \
+ case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; \
+ case ERROR_FILE_EXISTS: errno = EEXIST; break; \
+ case ERROR_SHARING_VIOLATION: errno = EACCES; break; \
+ case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; \
+ } \
+ return RESULT; } while (0)
+
+#endif /* !ACE_WIN32 */
+
+// Helper functions to split large intergers into smaller high-order
+// and low-order parts, and reconstitute them again. These are
+// required primarily for supporting _FILE_OFFSET_BITS==64 on windows.
+
+#if defined(ACE_WIN32)
+# if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS==64)
+# include "ace/Basic_Types.h"
+
+# define ACE_LOW_PART(X) static_cast<DWORD>(X)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+LONG
+inline ACE_High_Part (ACE_OFF_T value)
+{
+ LARGE_INTEGER new_value;
+ new_value.QuadPart = value;
+ return new_value.HighPart;
+}
+# define ACE_HIGH_PART(X) ACE_High_Part(X)
+
+LONGLONG
+inline ACE_Combine_Parts (LONG high, DWORD low)
+{
+ LARGE_INTEGER value;
+ value.LowPart = low; // DWORD
+ value.HighPart = high; // LONG
+ return value.QuadPart;
+}
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# define ACE_COMBINE_PARTS(X,Y) ACE_Combine_Parts(X,Y)
+# else /* _FILE_OFFSET_BITS==64 */
+# define ACE_LOW_PART(X) X
+# define ACE_HIGH_PART(X) 0
+# define ACE_COMBINE_PARTS(X,Y) X
+# endif /* _FILE_OFFSET_BITS==64 */
+#endif /* ACE_WIN32 */
+
+
+
+# include /**/ "ace/post.h"
+
+#endif /* ACE_OS_NS_MACROS_H */
diff --git a/ACE/ace/OS_NS_math.cpp b/ACE/ace/OS_NS_math.cpp
new file mode 100644
index 00000000000..da5e748370e
--- /dev/null
+++ b/ACE/ace/OS_NS_math.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_math.h"
+
+ACE_RCSID(ace, OS_NS_math, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_math.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_math.h b/ACE/ace/OS_NS_math.h
new file mode 100644
index 00000000000..49143738a79
--- /dev/null
+++ b/ACE/ace/OS_NS_math.h
@@ -0,0 +1,115 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_math.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_MATH_H
+# define ACE_OS_NS_MATH_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/os_include/os_math.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+
+/*
+ * We inline and undef some functions that may be implemented
+ * as macros on some platforms. This way macro definitions will
+ * be usable later as there is no way to save the macro definition
+ * using the pre-processor.
+ *
+ */
+inline double ace_log2_helper (double x)
+{
+#if defined (log2)
+ return log2 (x);
+#undef log2
+#else
+# if !defined (ACE_LACKS_LOG2)
+ return ACE_STD_NAMESPACE::log2 (x);
+# else
+ /*
+ ==================================================================
+
+ log (x)
+ k
+ log (x) = -------
+ b log (b)
+ k
+
+ meaning the binary logarithm of x using the natural logarithm, for
+ example, is:
+
+
+ log (x)
+ e
+ log (x) = -------
+ 2 log (2)
+ e
+
+ ==================================================================
+ */
+
+ // Precomputed value of 1/log(2.0). Saves an expensive division and
+ // computing log(2.0) in each call.
+ double const _1_ln2 = 1.442695040888963407359924681002;
+
+ return log (x) * _1_ln2;
+# endif /* !ACE_LACKS_LOG2 */
+#endif /* defined (log2) */
+}
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+ /// This method computes the largest integral value not greater than x.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ double floor (double x);
+
+ /// This method computes the smallest integral value not less than x.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ double ceil (double x);
+
+ /// This method computes the base-2 logarithm of x.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ double log2 (double x);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_math.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_MATH_H */
diff --git a/ACE/ace/OS_NS_math.inl b/ACE/ace/OS_NS_math.inl
new file mode 100644
index 00000000000..3cc3e37a5b5
--- /dev/null
+++ b/ACE/ace/OS_NS_math.inl
@@ -0,0 +1,41 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ ACE_INLINE double
+ floor (double x)
+ {
+ // This method computes the largest integral value not greater than x.
+ if(x > 0)
+ return static_cast<long> (x);
+ else if (static_cast<long> (x) == x)
+ return x;
+ else
+ return static_cast<long>(x) - 1;
+ }
+
+ ACE_INLINE double
+ ceil (double x)
+ {
+ // This method computes the smallest integral value not less than x.
+ if (x < 0)
+ return static_cast<long> (x);
+ else if (static_cast<long> (x) == x)
+ return x;
+ else
+ return static_cast<long> (x) + 1;
+ }
+
+ ACE_INLINE double
+ log2 (double x)
+ {
+ return ace_log2_helper (x);
+ }
+
+} // ACE_OS namespace
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_netdb.cpp b/ACE/ace/OS_NS_netdb.cpp
new file mode 100644
index 00000000000..019a58dc0c1
--- /dev/null
+++ b/ACE/ace/OS_NS_netdb.cpp
@@ -0,0 +1,421 @@
+// -*- C++ -*-
+// $Id$
+
+#include "ace/OS_NS_netdb.h"
+
+ACE_RCSID(ace, OS_NS_netdb, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_netdb.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include "ace/os_include/net/os_if.h"
+#include "ace/OS_NS_unistd.h"
+#if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
+#include "ace/OS_NS_stdio.h"
+#endif
+#include "ace/OS_NS_stropts.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYADDR)
+
+struct hostent *
+ACE_OS::gethostbyaddr (const char *addr, int length, int type)
+{
+ ACE_OS_TRACE ("ACE_OS::gethostbyaddr");
+
+ if (length != 4 || type != AF_INET)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+
+ // not thread safe!
+ static hostent ret;
+ static char name [MAXNAMELEN + 1];
+ static char *hostaddr[2];
+ static char *aliases[1];
+
+ if (::hostGetByAddr (*(int *) addr, name) != 0)
+ {
+ // errno will have been set to S_hostLib_UNKNOWN_HOST.
+ return 0;
+ }
+
+ // Might not be official: just echo input arg.
+ hostaddr[0] = (char *) addr;
+ hostaddr[1] = 0;
+ aliases[0] = 0;
+
+ ret.h_name = name;
+ ret.h_addrtype = AF_INET;
+ ret.h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN;
+ ret.h_addr_list = hostaddr;
+ ret.h_aliases = aliases;
+
+ return &ret;
+}
+
+#endif /* ACE_VXWORKS && ACE_LACKS_GETHOSTBYADDR */
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYADDR)
+
+struct hostent *
+ACE_OS::gethostbyaddr_r (const char *addr, int length, int type,
+ hostent *result, ACE_HOSTENT_DATA buffer,
+ int *h_errnop)
+{
+ ACE_OS_TRACE ("ACE_OS::gethostbyaddr_r");
+ if (length != 4 || type != AF_INET)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+
+ if (ACE_OS::netdb_acquire ())
+ return 0;
+ else
+ {
+ // buffer layout:
+ // buffer[0-3]: h_addr_list[0], the first (and only) addr.
+ // buffer[4-7]: h_addr_list[1], the null terminator for the h_addr_list.
+ // buffer[8]: the name of the host, null terminated.
+
+ // Call ::hostGetByAddr (), which puts the (one) hostname into
+ // buffer.
+ if (::hostGetByAddr (*(int *) addr, &buffer[8]) == 0)
+ {
+ // Store the return values in result.
+ result->h_name = &buffer[8]; // null-terminated host name
+ result->h_addrtype = AF_INET;
+ result->h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN.
+
+ result->h_addr_list = (char **) buffer;
+ // Might not be official: just echo input arg.
+ result->h_addr_list[0] = (char *) addr;
+ // Null-terminate the list of addresses.
+ result->h_addr_list[1] = 0;
+ // And no aliases, so null-terminate h_aliases.
+ result->h_aliases = &result->h_addr_list[1];
+ }
+ else
+ {
+ // errno will have been set to S_hostLib_UNKNOWN_HOST.
+ result = 0;
+ }
+ }
+
+ ACE_OS::netdb_release ();
+ *h_errnop = errno;
+ return result;
+}
+
+#endif /* ACE_VXWORKS && ACE_LACKS_GETHOSTBYADDR */
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYNAME)
+
+struct hostent *
+ACE_OS::gethostbyname (const char *name)
+{
+ ACE_OS_TRACE ("ACE_OS::gethostbyname");
+
+ // not thread safe!
+ static hostent ret;
+ static int first_addr;
+ static char *hostaddr[2];
+ static char *aliases[1];
+
+ if (0 == name || '\0' == name[0])
+ return 0;
+
+ ACE_OSCALL (::hostGetByName (const_cast <char *> (name)), int, -1, first_addr);
+ if (first_addr == -1)
+ return 0;
+
+ hostaddr[0] = (char *) &first_addr;
+ hostaddr[1] = 0;
+ aliases[0] = 0;
+
+ // Might not be official: just echo input arg.
+ ret.h_name = (char *) name;
+ ret.h_addrtype = AF_INET;
+ ret.h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN;
+ ret.h_addr_list = hostaddr;
+ ret.h_aliases = aliases;
+
+ return &ret;
+}
+
+#endif /* ACE_VXWORKS && ACE_LACKS_GETHOSTBYNAME */
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYNAME)
+
+struct hostent *
+ACE_OS::gethostbyname_r (const char *name, hostent *result,
+ ACE_HOSTENT_DATA buffer,
+ int *h_errnop)
+{
+ ACE_OS_TRACE ("ACE_OS::gethostbyname_r");
+
+ if (0 == name || '\0' == name[0])
+ return 0;
+
+ if (ACE_OS::netdb_acquire ())
+ return 0;
+ else
+ {
+ int addr;
+ ACE_OSCALL (::hostGetByName (const_cast <char *> (name)), int, -1, addr);
+
+ if (addr == -1)
+ {
+ // errno will have been set to S_hostLib_UNKNOWN_HOST
+ result = 0;
+ }
+ else
+ {
+ // Might not be official: just echo input arg.
+ result->h_name = (char *) name;
+ result->h_addrtype = AF_INET;
+ result->h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN;
+
+ // buffer layout:
+ // buffer[0-3]: h_addr_list[0], pointer to the addr.
+ // buffer[4-7]: h_addr_list[1], null terminator for the h_addr_list.
+ // buffer[8-11]: the first (and only) addr.
+
+ // Store the address list in buffer.
+ result->h_addr_list = (char **) buffer;
+ // Store the actual address _after_ the address list.
+ result->h_addr_list[0] = (char *) &result->h_addr_list[2];
+ result->h_addr_list[2] = (char *) addr;
+ // Null-terminate the list of addresses.
+ result->h_addr_list[1] = 0;
+ // And no aliases, so null-terminate h_aliases.
+ result->h_aliases = &result->h_addr_list[1];
+ }
+ }
+
+ ACE_OS::netdb_release ();
+ *h_errnop = errno;
+ return result;
+}
+
+#endif /* ACE_VXWORKS && ACE_LACKS_GETHOSTBYNAME*/
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Include if_arp so that getmacaddr can use the
+// arp structure.
+#if defined (sun)
+# include /**/ <net/if_arp.h>
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_OS::getmacaddress (struct macaddr_node_t *node)
+{
+ ACE_OS_TRACE ("ACE_OS::getmacaddress");
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+# if !defined (ACE_HAS_PHARLAP)
+ /** Define a structure for use with the netbios routine */
+ struct ADAPTERSTAT
+ {
+ ADAPTER_STATUS adapt;
+ NAME_BUFFER NameBuff [30];
+ };
+
+ NCB ncb;
+ LANA_ENUM lenum;
+ unsigned char result;
+
+ ACE_OS::memset (&ncb, 0, sizeof(ncb));
+ ncb.ncb_command = NCBENUM;
+ ncb.ncb_buffer = reinterpret_cast<unsigned char*> (&lenum);
+ ncb.ncb_length = sizeof(lenum);
+
+ result = Netbios (&ncb);
+
+ for(int i = 0; i < lenum.length; i++)
+ {
+ ACE_OS::memset (&ncb, 0, sizeof(ncb));
+ ncb.ncb_command = NCBRESET;
+ ncb.ncb_lana_num = lenum.lana [i];
+
+ /** Reset the netbios */
+ result = Netbios (&ncb);
+
+ if (ncb.ncb_retcode != NRC_GOODRET)
+ {
+ return -1;
+ }
+
+ ADAPTERSTAT adapter;
+ ACE_OS::memset (&ncb, 0, sizeof (ncb));
+ ACE_OS::strcpy (reinterpret_cast<char*> (ncb.ncb_callname), "*");
+ ncb.ncb_command = NCBASTAT;
+ ncb.ncb_lana_num = lenum.lana[i];
+ ncb.ncb_buffer = reinterpret_cast<unsigned char*> (&adapter);
+ ncb.ncb_length = sizeof (adapter);
+
+ result = Netbios (&ncb);
+
+ if (result == 0)
+ {
+ ACE_OS::memcpy (node->node,
+ adapter.adapt.adapter_address,
+ 6);
+ return 0;
+ }
+ }
+ return 0;
+# else
+# if defined (ACE_HAS_PHARLAP_RT)
+ DEVHANDLE ip_dev = (DEVHANDLE)0;
+ EK_TCPIPCFG *devp;
+ size_t i;
+ ACE_TCHAR dev_name[16];
+
+ for (i = 0; i < 10; i++)
+ {
+ // Ethernet.
+ ACE_OS::sprintf (dev_name,
+ "ether%d",
+ i);
+ ip_dev = EtsTCPGetDeviceHandle (dev_name);
+ if (ip_dev != 0)
+ break;
+ }
+ if (ip_dev == 0)
+ return -1;
+ devp = EtsTCPGetDeviceCfg (ip_dev);
+ if (devp == 0)
+ return -1;
+ ACE_OS::memcpy (node->node,
+ &devp->EthernetAddress[0],
+ 6);
+ return 0;
+# else
+ ACE_UNUSED_ARG (node);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PHARLAP_RT */
+# endif /* ACE_HAS_PHARLAP */
+#elif defined (sun)
+
+ /** obtain the local host name */
+ char hostname [MAXHOSTNAMELEN];
+ ACE_OS::hostname (hostname, sizeof (hostname));
+
+ /** Get the hostent to use with ioctl */
+ struct hostent *phost =
+ ACE_OS::gethostbyname (hostname);
+
+ if (phost == 0)
+ return -1;
+
+ ACE_HANDLE handle =
+ ACE_OS::socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (handle == ACE_INVALID_HANDLE)
+ return -1;
+
+ char **paddrs = phost->h_addr_list;
+
+ struct arpreq ar;
+
+ struct sockaddr_in *psa =
+ (struct sockaddr_in *)&(ar.arp_pa);
+
+ ACE_OS::memset (&ar,
+ 0,
+ sizeof (struct arpreq));
+
+ psa->sin_family = AF_INET;
+
+ ACE_OS::memcpy (&(psa->sin_addr),
+ *paddrs,
+ sizeof (struct in_addr));
+
+ if (ACE_OS::ioctl (handle,
+ SIOCGARP,
+ &ar) == -1)
+ {
+ ACE_OS::close (handle);
+ return -1;
+ }
+
+ ACE_OS::close (handle);
+
+ ACE_OS::memcpy (node->node,
+ ar.arp_ha.sa_data,
+ 6);
+
+ return 0;
+
+#elif defined (linux) && !defined (ACE_LACKS_NETWORKING)
+
+ struct ifreq ifr;
+
+ ACE_HANDLE handle =
+ ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
+
+ if (handle == ACE_INVALID_HANDLE)
+ return -1;
+
+ ACE_OS::strcpy (ifr.ifr_name, "eth0");
+
+ if (ACE_OS::ioctl (handle/*s*/, SIOCGIFHWADDR, &ifr) < 0)
+ {
+ ACE_OS::close (handle);
+ return -1;
+ }
+
+ struct sockaddr* sa =
+ (struct sockaddr *) &ifr.ifr_addr;
+
+ ACE_OS::close (handle);
+
+ ACE_OS::memcpy (node->node,
+ sa->sa_data,
+ 6);
+
+ return 0;
+
+#else
+ ACE_UNUSED_ARG (node);
+ ACE_NOTSUP_RETURN (-1);
+#endif
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) && defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
+# include "ace/OS_NS_Thread.h"
+# include "ace/Object_Manager_Base.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_OS::netdb_acquire (void)
+{
+ return ACE_OS::thread_mutex_lock ((ACE_thread_mutex_t *)
+ ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
+}
+
+int
+ACE_OS::netdb_release (void)
+{
+ return ACE_OS::thread_mutex_unlock ((ACE_thread_mutex_t *)
+ ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# endif /* defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) */
+
diff --git a/ACE/ace/OS_NS_netdb.h b/ACE/ace/OS_NS_netdb.h
new file mode 100644
index 00000000000..b7e03936c85
--- /dev/null
+++ b/ACE/ace/OS_NS_netdb.h
@@ -0,0 +1,146 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_netdb.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_NETDB_H
+#define ACE_OS_NS_NETDB_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/os_include/os_netdb.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYADDR)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_VXWORKS */
+ struct hostent *gethostbyaddr (const char *addr,
+ int length,
+ int type);
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYADDR)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_VXWORKS */
+ struct hostent *gethostbyaddr_r (const char *addr,
+ int length,
+ int type,
+ struct hostent *result,
+ ACE_HOSTENT_DATA buffer,
+ int *h_errnop);
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYNAME)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_VXWORKS */
+ struct hostent *gethostbyname (const char *name);
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYNAME)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_VXWORKS */
+ struct hostent *gethostbyname_r (const char *name,
+ struct hostent *result,
+ ACE_HOSTENT_DATA buffer,
+ int *h_errnop);
+
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct hostent *getipnodebyaddr (const void *src, size_t len,
+ int family);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct hostent *getipnodebyname (const char *name, int family,
+ int flags = 0);
+
+ /**
+ * Get the first adapter found on the machine.
+ * @todo: this is really useless except for UUID, move there? dhinton
+ */
+ struct macaddr_node_t {
+ unsigned char node[6];
+ };
+
+ extern ACE_Export
+ int getmacaddress (struct macaddr_node_t *node);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct protoent *getprotobyname (const char *name);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct protoent *getprotobyname_r (const char *name,
+ struct protoent *result,
+ ACE_PROTOENT_DATA buffer);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct protoent *getprotobynumber (int proto);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct protoent *getprotobynumber_r (int proto,
+ struct protoent *result,
+ ACE_PROTOENT_DATA buffer);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct servent *getservbyname (const char *svc,
+ const char *proto);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct servent *getservbyname_r (const char *svc,
+ const char *proto,
+ struct servent *result,
+ ACE_SERVENT_DATA buf);
+
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) && defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
+ extern ACE_Export
+ int netdb_acquire (void);
+
+ extern ACE_Export
+ int netdb_release (void);
+# endif /* defined (ACE_MT_SAFE) && ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_netdb.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_NETDB_H */
diff --git a/ACE/ace/OS_NS_netdb.inl b/ACE/ace/OS_NS_netdb.inl
new file mode 100644
index 00000000000..f86db157149
--- /dev/null
+++ b/ACE/ace/OS_NS_netdb.inl
@@ -0,0 +1,750 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_macros.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+
+#if defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# define ACE_NETDBCALL_RETURN(OP,TYPE,FAILVALUE,TARGET,SIZE) \
+ do \
+ { \
+ if (ACE_OS::netdb_acquire ()) \
+ return FAILVALUE; \
+ else \
+ { \
+ TYPE ace_result_; \
+ ACE_OSCALL (OP, TYPE, FAILVALUE, ace_result_); \
+ if (ace_result_ != FAILVALUE) \
+ ACE_OS::memcpy (TARGET, \
+ ace_result_, \
+ SIZE < sizeof (TYPE) ? SIZE : sizeof (TYPE)); \
+ ACE_OS::netdb_release (); \
+ return ace_result_; \
+ } \
+ } while(0)
+# else /* ! (ACE_MT_SAFE && ACE_MT_SAFE != 0) */
+# define ACE_NETDBCALL_RETURN(OP,TYPE,FAILVALUE,TARGET,SIZE) \
+ do \
+ { \
+ TYPE ace_result_; \
+ ACE_OSCALL(OP,TYPE,FAILVALUE,ace_result_); \
+ if (ace_result_ != FAILVALUE) \
+ ACE_OS::memcpy (TARGET, \
+ ace_result_, \
+ SIZE < sizeof (TYPE) ? SIZE : sizeof (TYPE)); \
+ return ace_result_; \
+ } while(0)
+# endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+#endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if !(defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYADDR))
+
+ACE_INLINE struct hostent *
+ACE_OS::gethostbyaddr (const char *addr, int length, int type)
+{
+ ACE_OS_TRACE ("ACE_OS::gethostbyaddr");
+# if defined (ACE_LACKS_GETHOSTBYADDR)
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (length);
+ ACE_UNUSED_ARG (type);
+ ACE_NOTSUP_RETURN (0);
+# else
+
+ if (0 == addr || '\0' == addr[0])
+ return 0;
+
+# if defined (ACE_VXWORKS)
+ // VxWorks 6.x has a gethostbyaddr() that is threadsafe and
+ // returns an heap-allocated hostentry structure.
+ // just call ACE_OS::gethostbyaddr_r () which knows how to handle this.
+ struct hostent hentry;
+ ACE_HOSTENT_DATA buf;
+ int h_error; // Not the same as errno!
+ return ACE_OS::gethostbyaddr_r (addr, length, type, &hentry, buf, &h_error);
+# elif defined (ACE_HAS_NONCONST_GETBY)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyaddr (const_cast<char *> (addr),
+ (ACE_SOCKET_LEN) length,
+ type),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyaddr (addr,
+ (ACE_SOCKET_LEN) length,
+ type),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_HAS_NONCONST_GETBY */
+# endif /* !ACE_LACKS_GETHOSTBYADDR */
+}
+
+#endif
+
+#if !(defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYADDR))
+
+ACE_INLINE struct hostent *
+ACE_OS::gethostbyaddr_r (const char *addr,
+ int length,
+ int type,
+ struct hostent *result,
+ ACE_HOSTENT_DATA buffer,
+ int *h_errnop)
+{
+ ACE_OS_TRACE ("ACE_OS::gethostbyaddr_r");
+# if defined (ACE_LACKS_GETHOSTBYADDR_R)
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (length);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (h_errnop);
+ ACE_NOTSUP_RETURN (0);
+# elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE)
+
+ if (0 == addr || '\0' == addr[0])
+ return 0;
+
+# if defined (AIX) || defined (DIGITAL_UNIX)
+ ACE_OS::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA));
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::gethostbyaddr_r ((char *) addr, length, type, result,
+ (struct hostent_data *) buffer)== 0)
+ return result;
+ //FUZZ: enable check_for_lack_ACE_OS
+ else
+ {
+ *h_errnop = h_errno;
+ return (struct hostent *) 0;
+ }
+# elif defined (__GLIBC__)
+ // GNU C library has a different signature
+ ACE_OS::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA));
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::gethostbyaddr_r ((char *) addr,
+ length,
+ type,
+ result,
+ buffer,
+ sizeof (ACE_HOSTENT_DATA),
+ &result,
+ h_errnop) == 0)
+ return result;
+ //FUZZ: enable check_for_lack_ACE_OS
+ else
+ return (struct hostent *) 0;
+# elif defined (ACE_VXWORKS)
+ // VxWorks 6.x has a threadsafe gethostbyaddr() which returns a heap-allocated
+ // data structure which needs to be freed with hostentFree()
+ //FUZZ: disable check_for_lack_ACE_OS
+ struct hostent* hp = ::gethostbyaddr (addr, length, type);
+ //FUZZ: enable check_for_lack_ACE_OS
+
+ if (hp)
+ {
+ result->h_addrtype = hp->h_addrtype;
+ result->h_length = hp->h_length;
+
+ // buffer layout:
+ // buffer[0-3]: h_addr_list[0], pointer to the addr.
+ // buffer[4-7]: h_addr_list[1], null terminator for the h_addr_list.
+ // buffer[8..(8+h_length)]: the first (and only) addr.
+ // buffer[(8+h_length)...]: hostname
+
+ // Store the address list in buffer.
+ result->h_addr_list = (char **) buffer;
+ // Store the actual address _after_ the address list.
+ result->h_addr_list[0] = (char *) &result->h_addr_list[2];
+ ACE_OS::memcpy (result->h_addr_list[0], hp->h_addr_list[0], hp->h_length);
+ // Null-terminate the list of addresses.
+ result->h_addr_list[1] = 0;
+ // And no aliases, so null-terminate h_aliases.
+ result->h_aliases = &result->h_addr_list[1];
+
+ if (((2*sizeof(char*))+hp->h_length+ACE_OS::strlen (hp->h_name)+1) <= sizeof (ACE_HOSTENT_DATA))
+ {
+ result->h_name = (char *) result->h_addr_list[0] + hp->h_length;
+ ACE_OS::strcpy (result->h_name, hp->h_name);
+ }
+ else
+ {
+ result->h_name = (char *)0;
+ }
+
+ // free hostent memory
+ ::hostentFree (hp);
+
+ return result;
+ }
+ else
+ {
+ return (struct hostent *) 0;
+ }
+# else
+# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (h_errnop);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_NETDBCALL_RETURN (::gethostbyaddr (addr, (ACE_SOCKET_LEN) length, type),
+ struct hostent *, 0,
+ buffer, sizeof (ACE_HOSTENT_DATA));
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyaddr_r (addr, length, type, result,
+ buffer, sizeof (ACE_HOSTENT_DATA),
+ h_errnop),
+ struct hostent *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */
+# endif /* defined (AIX) || defined (DIGITAL_UNIX) */
+# elif defined (ACE_HAS_NONCONST_GETBY)
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (h_errnop);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyaddr (const_cast<char *> (addr),
+ (ACE_SOCKET_LEN) length,
+ type),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ ACE_UNUSED_ARG (h_errnop);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (result);
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyaddr (addr,
+ (ACE_SOCKET_LEN) length,
+ type),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_LACKS_GETHOSTBYADDR_R */
+}
+
+#endif
+
+#if !(defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYNAME))
+
+ACE_INLINE struct hostent *
+ACE_OS::gethostbyname (const char *name)
+{
+ ACE_OS_TRACE ("ACE_OS::gethostbyname");
+# if defined (ACE_LACKS_GETHOSTBYNAME)
+ ACE_UNUSED_ARG (name);
+ ACE_NOTSUP_RETURN (0);
+# else
+
+ if (0 == name || '\0' == name[0])
+ return 0;
+
+# if defined (ACE_VXWORKS)
+ // VxWorks 6.x has a gethostbyname() that is threadsafe and
+ // returns an heap-allocated hostentry structure.
+ // just call ACE_OS::gethostbyname_r () which knows how to handle this.
+ struct hostent hentry;
+ ACE_HOSTENT_DATA buf;
+ int h_error; // Not the same as errno!
+ return ACE_OS::gethostbyname_r (name, &hentry, buf, &h_error);
+# elif defined (ACE_HAS_NONCONST_GETBY)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyname (const_cast<char *> (name)),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyname (name),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_HAS_NONCONST_GETBY */
+# endif /* !ACE_LACKS_GETHOSTBYNAME */
+}
+
+#endif
+
+#if !(defined (ACE_VXWORKS) && defined (ACE_LACKS_GETHOSTBYNAME))
+
+ACE_INLINE struct hostent *
+ACE_OS::gethostbyname_r (const char *name,
+ struct hostent *result,
+ ACE_HOSTENT_DATA buffer,
+ int *h_errnop)
+{
+ ACE_OS_TRACE ("ACE_OS::gethostbyname_r");
+#if defined (ACE_LACKS_GETHOSTBYNAME)
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (h_errnop);
+ ACE_NOTSUP_RETURN (0);
+# elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE)
+
+ if (0 == name || '\0' == name[0])
+ return (struct hostent *)0;
+
+# if defined (DIGITAL_UNIX) || \
+ (defined (ACE_AIX_MINOR_VERS) && (ACE_AIX_MINOR_VERS > 2))
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (h_errnop);
+
+ // gethostbyname returns thread-specific storage on Digital Unix and
+ // AIX 4.3
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyname (name), struct hostent *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# elif defined (AIX)
+ ACE_OS::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA));
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::gethostbyname_r (name, result, (struct hostent_data *) buffer) == 0)
+ return result;
+ //FUZZ: enable check_for_lack_ACE_OS
+ else
+ {
+ *h_errnop = h_errno;
+ return (struct hostent *) 0;
+ }
+# elif defined (__GLIBC__)
+ // GNU C library has a different signature
+ ACE_OS::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA));
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::gethostbyname_r (name,
+ result,
+ buffer,
+ sizeof (ACE_HOSTENT_DATA),
+ &result,
+ h_errnop) == 0)
+ return result;
+ //FUZZ: enable check_for_lack_ACE_OS
+ else
+ return (struct hostent *) 0;
+# elif defined (ACE_VXWORKS)
+ // VxWorks 6.x has a threadsafe gethostbyname() which returns a heap-allocated
+ // data structure which needs to be freed with hostentFree()
+ //FUZZ: disable check_for_lack_ACE_OS
+ struct hostent* hp = ::gethostbyname (name);
+ //FUZZ: enable check_for_lack_ACE_OS
+
+ if (hp)
+ {
+ result->h_addrtype = hp->h_addrtype;
+ result->h_length = hp->h_length;
+
+ // buffer layout:
+ // buffer[0-3]: h_addr_list[0], pointer to the addr.
+ // buffer[4-7]: h_addr_list[1], null terminator for the h_addr_list.
+ // buffer[8...]: the first (and only) addr.
+
+ // Store the address list in buffer.
+ result->h_addr_list = (char **) buffer;
+ // Store the actual address _after_ the address list.
+ result->h_addr_list[0] = (char *) &result->h_addr_list[2];
+ ACE_OS::memcpy (result->h_addr_list[0], hp->h_addr_list[0], hp->h_length);
+ // Null-terminate the list of addresses.
+ result->h_addr_list[1] = 0;
+ // And no aliases, so null-terminate h_aliases.
+ result->h_aliases = &result->h_addr_list[1];
+
+ if (((2*sizeof(char*))+hp->h_length+ACE_OS::strlen (hp->h_name)+1) <= sizeof (ACE_HOSTENT_DATA))
+ {
+ result->h_name = (char *) result->h_addr_list[0] + hp->h_length;
+ ACE_OS::strcpy (result->h_name, hp->h_name);
+ }
+ else
+ {
+ result->h_name = (char *)0;
+ }
+
+ // free hostent memory
+ ::hostentFree (hp);
+
+ return result;
+ }
+ else
+ {
+ return (struct hostent *) 0;
+ }
+# else
+# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (h_errnop);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_NETDBCALL_RETURN (::gethostbyname (name),
+ struct hostent *, 0,
+ buffer, sizeof (ACE_HOSTENT_DATA));
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyname_r (name, result, buffer,
+ sizeof (ACE_HOSTENT_DATA),
+ h_errnop),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */
+# endif /* defined (AIX) || defined (DIGITAL_UNIX) */
+# elif defined (ACE_HAS_NONCONST_GETBY)
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (h_errnop);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyname (const_cast<char *> (name)),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (h_errnop);
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::gethostbyname (name),
+ struct hostent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) */
+}
+
+#endif
+
+ACE_INLINE struct hostent *
+ACE_OS::getipnodebyaddr (const void *src, size_t len, int family)
+{
+#if defined (ACE_HAS_IPV6) && !defined (ACE_WIN32)
+# if defined (ACE_LACKS_GETIPNODEBYADDR)
+ ACE_UNUSED_ARG (src);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (family);
+ ACE_NOTSUP_RETURN (0);
+# else
+ struct hostent *hptr = 0;
+ int errnum;
+ //FUZZ: disable check_for_lack_ACE_OS
+ if ((hptr = ::getipnodebyaddr (src, len, family, &errnum)) == 0)
+ {
+ errno = errnum;
+ }
+ //FUZZ: enable check_for_lack_ACE_OS
+ return hptr;
+# endif /* ACE_LACKS_GETIPNODEBYADDR */
+#else
+ // IPv4-only implementation
+ if (family == AF_INET)
+ return ACE_OS::gethostbyaddr (static_cast<const char *> (src),
+ static_cast<int> (len),
+ family);
+
+ ACE_NOTSUP_RETURN (0);
+# endif /* defined (ACE_HAS_IPV6) && !defined (ACE_WIN32) */
+}
+
+ACE_INLINE struct hostent *
+ACE_OS::getipnodebyname (const char *name, int family, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::getipnodebyname");
+# if defined (ACE_HAS_IPV6) && !defined (ACE_LACKS_GETIPNODEBYNAME_IPV6)
+# if defined (ACE_LACKS_GETIPNODEBYNAME)
+ ACE_UNUSED_ARG (flags);
+# if defined (ACE_HAS_NONCONST_GETBY)
+ ACE_SOCKCALL_RETURN (::gethostbyname2 (const_cast<char *> (name),
+ family),
+ struct hostent *, 0);
+# else
+ ACE_SOCKCALL_RETURN (::gethostbyname2 (name, family),
+ struct hostent *, 0);
+# endif /* ACE_HAS_NONCONST_GETBY */
+# else
+ struct hostent *hptr = 0;
+ int errnum;
+ //FUZZ: disable check_for_lack_ACE_OS
+ if ((hptr = ::getipnodebyname (name, family, flags, &errnum)) == 0)
+ {
+ errno = errnum;
+ }
+ //FUZZ: enable check_for_lack_ACE_OS
+ return hptr;
+# endif /* ACE_LACKS_GETIPNODEBYNAME */
+# else
+ // IPv4-only implementation
+ ACE_UNUSED_ARG (flags);
+ if (family == AF_INET)
+ return ACE_OS::gethostbyname (name);
+
+ ACE_NOTSUP_RETURN (0);
+# endif /* defined (ACE_HAS_IPV6) && !ACE_LACKS_GETIPNODEBYNAME_IPV6 */
+}
+
+ACE_INLINE struct protoent *
+ACE_OS::getprotobyname (const char *name)
+{
+#if defined (ACE_LACKS_GETPROTOBYNAME)
+ ACE_UNUSED_ARG (name);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_HAS_NONCONST_GETBY)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getprotobyname (const_cast<char *> (name)),
+ struct protoent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getprotobyname (name),
+ struct protoent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#endif /* ACE_LACKS_GETPROTOBYNAME */
+}
+
+ACE_INLINE struct protoent *
+ACE_OS::getprotobyname_r (const char *name,
+ struct protoent *result,
+ ACE_PROTOENT_DATA buffer)
+{
+#if defined (ACE_LACKS_GETPROTOBYNAME)
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE)
+# if defined (AIX) || defined (DIGITAL_UNIX)
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::getprotobyname_r (name, result, (struct protoent_data *) buffer) == 0)
+ return result;
+ else
+ return 0;
+ //FUZZ: enable check_for_lack_ACE_OS
+# elif defined (__GLIBC__)
+ // GNU C library has a different signature
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::getprotobyname_r (name,
+ result,
+ buffer,
+ sizeof (ACE_PROTOENT_DATA),
+ &result) == 0)
+ //FUZZ: enable check_for_lack_ACE_OS
+ return result;
+ else
+ return 0;
+# else
+# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
+ ACE_UNUSED_ARG (result);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_NETDBCALL_RETURN (::getprotobyname (name),
+ struct protoent *, 0,
+ buffer, sizeof (ACE_PROTOENT_DATA));
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getprotobyname_r (name,
+ result,
+ buffer,
+ sizeof (ACE_PROTOENT_DATA)),
+ struct protoent *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */
+# endif /* defined (AIX) || defined (DIGITAL_UNIX) */
+#elif defined (ACE_HAS_NONCONST_GETBY)
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getprotobyname (const_cast<char *> (name)),
+ struct protoent *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#else
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (result);
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getprotobyname (name),
+ struct protoent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) !defined (UNIXWARE) */
+}
+
+ACE_INLINE struct protoent *
+ACE_OS::getprotobynumber (int proto)
+{
+#if defined (ACE_LACKS_GETPROTOBYNUMBER)
+ ACE_UNUSED_ARG (proto);
+ ACE_NOTSUP_RETURN (0);
+#else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getprotobynumber (proto),
+ struct protoent *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#endif /* ACE_LACKS_GETPROTOBYNUMBER */
+}
+
+ACE_INLINE struct protoent *
+ACE_OS::getprotobynumber_r (int proto,
+ struct protoent *result,
+ ACE_PROTOENT_DATA buffer)
+{
+#if defined (ACE_LACKS_GETPROTOBYNUMBER)
+ ACE_UNUSED_ARG (proto);
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buffer);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE)
+# if defined (AIX) || defined (DIGITAL_UNIX)
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::getprotobynumber_r (proto, result, (struct protoent_data *) buffer) == 0)
+ return result;
+ //FUZZ: enable check_for_lack_ACE_OS
+ else
+ return 0;
+# elif defined (__GLIBC__)
+ // GNU C library has a different signature
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::getprotobynumber_r (proto,
+ result,
+ buffer,
+ sizeof (ACE_PROTOENT_DATA),
+ &result) == 0)
+ //FUZZ: enable check_for_lack_ACE_OS
+ return result;
+ else
+ return 0;
+# else
+# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
+ ACE_UNUSED_ARG (result);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_NETDBCALL_RETURN (::getprotobynumber (proto),
+ struct protoent *, 0,
+ buffer, sizeof (ACE_PROTOENT_DATA));
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getprotobynumber_r (proto, result, buffer, sizeof (ACE_PROTOENT_DATA)),
+ struct protoent *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */
+# endif /* defined (AIX) || defined (DIGITAL_UNIX) */
+#else
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (result);
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getprotobynumber (proto),
+ struct protoent *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) */
+}
+
+ACE_INLINE struct servent *
+ACE_OS::getservbyname (const char *svc, const char *proto)
+{
+ ACE_OS_TRACE ("ACE_OS::getservbyname");
+#if defined (ACE_LACKS_GETSERVBYNAME)
+ ACE_UNUSED_ARG (svc);
+ ACE_UNUSED_ARG (proto);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_HAS_NONCONST_GETBY)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getservbyname (const_cast<char *> (svc),
+ const_cast<char *> (proto)),
+ struct servent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getservbyname (svc,
+ proto),
+ struct servent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#endif /* ACE_HAS_NONCONST_GETBY */
+}
+
+ACE_INLINE struct servent *
+ACE_OS::getservbyname_r (const char *svc,
+ const char *proto,
+ struct servent *result,
+ ACE_SERVENT_DATA buf)
+{
+ ACE_OS_TRACE ("ACE_OS::getservbyname_r");
+#if defined (ACE_LACKS_GETSERVBYNAME)
+ ACE_UNUSED_ARG (svc);
+ ACE_UNUSED_ARG (proto);
+ ACE_UNUSED_ARG (result);
+ ACE_UNUSED_ARG (buf);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE)
+# if defined (AIX) || defined (DIGITAL_UNIX)
+ ACE_OS::memset (buf, 0, sizeof (ACE_SERVENT_DATA));
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::getservbyname_r (svc, proto, result, (struct servent_data *) buf) == 0)
+ return result;
+ //FUZZ: enable check_for_lack_ACE_OS
+ else
+ return (struct servent *) 0;
+# elif defined (__GLIBC__)
+ // GNU C library has a different signature
+ ACE_OS::memset (buf, 0, sizeof (ACE_SERVENT_DATA));
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ if (::getservbyname_r (svc,
+ proto,
+ result,
+ buf,
+ sizeof (ACE_SERVENT_DATA),
+ &result) == 0)
+ return result;
+ //FUZZ: enable check_for_lack_ACE_OS
+ else
+ return (struct servent *) 0;
+# else
+# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
+ ACE_UNUSED_ARG (result);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_NETDBCALL_RETURN (::getservbyname (svc, proto),
+ struct servent *, 0,
+ buf, sizeof (ACE_SERVENT_DATA));
+ //FUZZ: enable check_for_lack_ACE_OS
+# else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getservbyname_r (svc, proto, result, buf,
+ sizeof (ACE_SERVENT_DATA)),
+ struct servent *, 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */
+# endif /* defined (AIX) || defined (DIGITAL_UNIX) */
+#elif defined (ACE_HAS_NONCONST_GETBY)
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (result);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getservbyname (const_cast<char *> (svc),
+ const_cast<char *> (proto)),
+ struct servent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#else
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (result);
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_SOCKCALL_RETURN (::getservbyname (svc,
+ proto),
+ struct servent *,
+ 0);
+ //FUZZ: enable check_for_lack_ACE_OS
+#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_poll.cpp b/ACE/ace/OS_NS_poll.cpp
new file mode 100644
index 00000000000..d95979f1216
--- /dev/null
+++ b/ACE/ace/OS_NS_poll.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_poll.h"
+
+ACE_RCSID(ace, OS_NS_poll, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_poll.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_poll.h b/ACE/ace/OS_NS_poll.h
new file mode 100644
index 00000000000..37001564a61
--- /dev/null
+++ b/ACE/ace/OS_NS_poll.h
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_poll.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_POLL_H
+# define ACE_OS_NS_POLL_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/os_include/os_poll.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+namespace ACE_OS
+{
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int poll (struct pollfd *pollfds,
+ unsigned long len,
+ const ACE_Time_Value *tv = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int poll (struct pollfd *pollfds,
+ unsigned long len,
+ const ACE_Time_Value &tv);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_poll.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_POLL_H */
diff --git a/ACE/ace/OS_NS_poll.inl b/ACE/ace/OS_NS_poll.inl
new file mode 100644
index 00000000000..ab1b2d8b54e
--- /dev/null
+++ b/ACE/ace/OS_NS_poll.inl
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::poll (struct pollfd *pollfds,
+ unsigned long len,
+ const ACE_Time_Value *timeout)
+{
+ ACE_OS_TRACE ("ACE_OS::poll");
+#if defined (ACE_HAS_POLL)
+ int to = timeout == 0 ? -1 : int (timeout->msec ());
+ ACE_OSCALL_RETURN (::poll (pollfds, len, to), int, -1);
+#else
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (pollfds);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_POLL */
+}
+
+ACE_INLINE int
+ACE_OS::poll (struct pollfd *pollfds,
+ unsigned long len,
+ const ACE_Time_Value &timeout)
+{
+ ACE_OS_TRACE ("ACE_OS::poll");
+#if defined (ACE_HAS_POLL)
+ ACE_OSCALL_RETURN (::poll (pollfds, len, int (timeout.msec ())), int, -1);
+#else
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (pollfds);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_POLL */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_pwd.cpp b/ACE/ace/OS_NS_pwd.cpp
new file mode 100644
index 00000000000..64d3100c94b
--- /dev/null
+++ b/ACE/ace/OS_NS_pwd.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_pwd.h"
+
+ACE_RCSID(ace, OS_NS_pwd, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_pwd.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_pwd.h b/ACE/ace/OS_NS_pwd.h
new file mode 100644
index 00000000000..821582b449d
--- /dev/null
+++ b/ACE/ace/OS_NS_pwd.h
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_pwd.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_PWD_H
+#define ACE_OS_NS_PWD_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/os_include/os_pwd.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+# if defined (ACE_HAS_BROKEN_R_ROUTINES)
+# undef getpwnam_r
+# endif /* ACE_HAS_BROKEN_R_ROUTINES */
+
+struct passwd;
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+
+ //@{ @name A set of wrappers for password routines.
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void endpwent (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct passwd *getpwent (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct passwd *getpwnam (const char *user);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct passwd *getpwnam_r (const char *name,
+ struct passwd *pwent,
+ char *buffer,
+ int buflen);
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void setpwent (void);
+ //@}
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_pwd.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_PWD_H */
diff --git a/ACE/ace/OS_NS_pwd.inl b/ACE/ace/OS_NS_pwd.inl
new file mode 100644
index 00000000000..029dd034d51
--- /dev/null
+++ b/ACE/ace/OS_NS_pwd.inl
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Accessors to PWD file.
+
+ACE_INLINE void
+ACE_OS::endpwent (void)
+{
+#if !defined (ACE_LACKS_PWD_FUNCTIONS)
+ ::endpwent ();
+#endif /* ! ACE_LACKS_PWD_FUNCTIONS */
+}
+
+ACE_INLINE struct passwd *
+ACE_OS::getpwent (void)
+{
+#if !defined (ACE_LACKS_PWD_FUNCTIONS)
+ return ::getpwent ();
+#else
+ ACE_NOTSUP_RETURN (0);
+#endif /* ! ACE_LACKS_PWD_FUNCTIONS */
+}
+
+ACE_INLINE struct passwd *
+ACE_OS::getpwnam (const char *name)
+{
+#if !defined (ACE_LACKS_PWD_FUNCTIONS)
+ return ::getpwnam (name);
+# else
+ ACE_UNUSED_ARG (name);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_LACKS_PWD_FUNCTIONS */
+}
+
+ACE_INLINE struct passwd *
+ACE_OS::getpwnam_r (const char *name, struct passwd *pwent,
+ char *buffer, int buflen)
+{
+#if defined (ACE_HAS_POSIX_GETPWNAM_R)
+ struct passwd *result = 0;
+
+ int const status = ::getpwnam_r (name, pwent, buffer, buflen, &result);
+
+ if (status != 0)
+ {
+ errno = status;
+ result = 0;
+ }
+ return result;
+#elif !defined (ACE_LACKS_PWD_FUNCTIONS)
+# if defined (ACE_HAS_REENTRANT_FUNCTIONS)
+# if !defined (ACE_LACKS_PWD_REENTRANT_FUNCTIONS)
+# if defined (ACE_HAS_PTHREADS) && \
+ !defined (ACE_HAS_STHREADS) || \
+ defined (HPUX_11) || \
+ defined (__USLC__) // Added by Roland Gigler for SCO UnixWare 7.
+ struct passwd *result;
+ int status;
+# if defined (DIGITAL_UNIX)
+ ::_Pgetpwnam_r (name, pwent, buffer, buflen, &result);
+# else
+ // VAC++ doesn't correctly grok the ::getpwnam_r - the function is redefined
+ // in pwd.h, and that redefinition is used here
+# if defined (__IBMCPP__) && (__IBMCPP__ >= 400) /* VAC++ 4 */
+ status = _posix_getpwnam_r (name, pwent, buffer, buflen, &result);
+# else
+ status = ::getpwnam_r (name, pwent, buffer, buflen, &result);
+# endif /* __IBMCPP__ && (__IBMCPP__ >= 400) */
+ if (status != 0)
+ {
+ errno = status;
+ result = 0;
+ }
+# endif /* (DIGITAL_UNIX) */
+ return result;
+# elif defined (AIX)
+ if (::getpwnam_r (name, pwent, buffer, buflen) == -1)
+ return 0;
+ else
+ return pwent;
+# else
+ return ::getpwnam_r (name, pwent, buffer, buflen);
+# endif /* ACE_HAS_PTHREADS */
+# else
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (pwent);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (buflen);
+ ACE_NOTSUP_RETURN (0);
+# endif /* ! ACE_LACKS_PWD_REENTRANT_FUNCTIONS */
+# else
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (pwent);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (buflen);
+ ACE_NOTSUP_RETURN (0);
+# endif /* ACE_HAS_REENTRANT_FUNCTIONS */
+#else
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (pwent);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (buflen);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_POSIX_GETPWNAM_R */
+}
+
+ACE_INLINE void
+ACE_OS::setpwent (void)
+{
+#if !defined (ACE_LACKS_PWD_FUNCTIONS)
+ ::setpwent ();
+#endif /* ! ACE_LACKS_PWD_FUNCTIONS */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_regex.cpp b/ACE/ace/OS_NS_regex.cpp
new file mode 100644
index 00000000000..7bf54e28655
--- /dev/null
+++ b/ACE/ace/OS_NS_regex.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_regex.h"
+
+ACE_RCSID(ace, OS_NS_regex, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_regex.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_regex.h b/ACE/ace/OS_NS_regex.h
new file mode 100644
index 00000000000..011109052e6
--- /dev/null
+++ b/ACE/ace/OS_NS_regex.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_regex.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_REGEX_H
+# define ACE_OS_NS_REGEX_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/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ // non=standard..
+ //@{ @name A set of wrappers for regular expressions.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *compile (const char *instring,
+ char *expbuf,
+ char *endbuf);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int step (const char *str,
+ char *expbuf);
+ //@}
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_regex.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_REGEX_H */
diff --git a/ACE/ace/OS_NS_regex.inl b/ACE/ace/OS_NS_regex.inl
new file mode 100644
index 00000000000..884bd88c718
--- /dev/null
+++ b/ACE/ace/OS_NS_regex.inl
@@ -0,0 +1,39 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+#include "ace/os_include/os_regex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE char *
+ACE_OS::compile (const char *instring, char *expbuf, char *endbuf)
+{
+ ACE_OS_TRACE ("ACE_OS::compile");
+#if defined (ACE_HAS_REGEX)
+ ACE_OSCALL_RETURN (::compile (instring, expbuf, endbuf), char *, 0);
+#else
+ ACE_UNUSED_ARG (instring);
+ ACE_UNUSED_ARG (expbuf);
+ ACE_UNUSED_ARG (endbuf);
+
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_REGEX */
+}
+
+ACE_INLINE int
+ACE_OS::step (const char *str, char *expbuf)
+{
+ ACE_OS_TRACE ("ACE_OS::step");
+#if defined (ACE_HAS_REGEX)
+ ACE_OSCALL_RETURN (::step (str, expbuf), int, -1);
+#else
+ ACE_UNUSED_ARG (str);
+ ACE_UNUSED_ARG (expbuf);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_REGEX */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_signal.cpp b/ACE/ace/OS_NS_signal.cpp
new file mode 100644
index 00000000000..9acf69c2e78
--- /dev/null
+++ b/ACE/ace/OS_NS_signal.cpp
@@ -0,0 +1,26 @@
+// $Id$
+
+#include "ace/OS_NS_signal.h"
+
+ACE_RCSID(ace, OS_NS_signal, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_signal.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if !defined (ACE_HAS_SIGINFO_T)
+siginfo_t::siginfo_t (ACE_HANDLE handle)
+ : si_handle_ (handle),
+ si_handles_ (&handle)
+{
+}
+
+siginfo_t::siginfo_t (ACE_HANDLE *handles)
+ : si_handle_ (handles[0]),
+ si_handles_ (handles)
+{
+}
+#endif /* ACE_HAS_SIGINFO_T */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_signal.h b/ACE/ace/OS_NS_signal.h
new file mode 100644
index 00000000000..bb5b03b1c0d
--- /dev/null
+++ b/ACE/ace/OS_NS_signal.h
@@ -0,0 +1,153 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_signal.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SIGNAL_H
+# define ACE_OS_NS_SIGNAL_H
+
+# include /**/ "ace/pre.h"
+
+# include "ace/config-lite.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_signal.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+# if !defined (SIG_BLOCK)
+# define SIG_BLOCK 1
+# endif /* SIG_BLOCK */
+
+# if !defined (SIG_UNBLOCK)
+# define SIG_UNBLOCK 2
+# endif /* SIG_UNBLOCK */
+
+# if !defined (SIG_SETMASK)
+# define SIG_SETMASK 3
+# endif /* SIG_SETMASK */
+
+// Create some useful typedefs.
+
+# if !defined (ACE_HAS_SIGINFO_T)
+struct ACE_Export siginfo_t
+{
+ siginfo_t (ACE_HANDLE handle);
+ siginfo_t (ACE_HANDLE *handles); // JCEJ 12/23/96
+
+ /// Win32 HANDLE that has become signaled.
+ ACE_HANDLE si_handle_;
+
+ /// Array of Win32 HANDLEs all of which have become signaled.
+ ACE_HANDLE *si_handles_;
+};
+# endif /* ACE_HAS_SIGINFO_T */
+
+#if !defined (ACE_WIN32)
+extern "C"
+{
+ typedef void (*ACE_SIGNAL_C_FUNC)(int, siginfo_t *, void *);
+}
+#endif /* ACE_WIN32 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This hack is needed to get around an odd and hard-to-reproduce problem
+// with HP aC++. If struct sigaction is defined extern "C" and the sigaction
+// function in namespace ACE_OS, the compiler sometimes gets confused.
+// If we help it with this typedef, it's fine. User code should not use
+// the ACE typedef - it will be removed without warning as soon as we can
+// either drop support for the broken compilers or figure out how to reproduce
+// it so it can be reported to HP and fixed.
+// There's a similar hack in OS_TLI.h for struct t_optmgmt.
+// Also see ChangeLog entries:
+// Mon Jan 23 16:35:40 UTC 2006 Steve Huston <shuston@riverace.com>
+// Mon Jan 23 22:08:56 UTC 2006 Steve Huston <shuston@riverace.com>
+#if defined (__HP_aCC) && (__HP_aCC <= 37300)
+typedef extern "C" struct sigaction ACE_SIGACTION;
+#else
+typedef struct sigaction ACE_SIGACTION;
+#endif
+
+namespace ACE_OS {
+
+ //@{ @name A set of wrappers for Signals.
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int kill (pid_t pid,
+ int signum);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int pthread_sigmask (int how,
+ const sigset_t *nsp,
+ sigset_t *osp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigaction (int signum,
+ const ACE_SIGACTION *nsa,
+ ACE_SIGACTION *osa);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigaddset (sigset_t *s,
+ int signum);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigdelset (sigset_t *s,
+ int signum);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigemptyset (sigset_t *s);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigfillset (sigset_t *s);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigismember (sigset_t *s,
+ int signum);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_SignalHandler signal (int signum,
+ ACE_SignalHandler);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigprocmask (int how,
+ const sigset_t *nsp,
+ sigset_t *osp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sigsuspend (const sigset_t *set);
+
+ //@}
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_signal.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SIGNAL_H */
diff --git a/ACE/ace/OS_NS_signal.inl b/ACE/ace/OS_NS_signal.inl
new file mode 100644
index 00000000000..98f02459494
--- /dev/null
+++ b/ACE/ace/OS_NS_signal.inl
@@ -0,0 +1,232 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_macros.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ACE_INLINE int
+kill (pid_t pid, int signum)
+{
+ ACE_OS_TRACE ("ACE_OS::kill");
+#if defined (ACE_LACKS_KILL)
+ ACE_UNUSED_ARG (pid);
+ ACE_UNUSED_ARG (signum);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::kill (pid, signum), int, -1);
+#endif /* ACE_LACKS_KILL */
+}
+
+ACE_INLINE int
+pthread_sigmask (int how, const sigset_t *nsp, sigset_t *osp)
+{
+#if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_SIGMASK)
+ int result;
+ ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsp, osp),
+ result),
+ int,
+ -1);
+#else /* !ACE_HAS_PTHREADS && !ACE_LACKS_PTHREAD_SIGMASK */
+ ACE_UNUSED_ARG (how);
+ ACE_UNUSED_ARG (nsp);
+ ACE_UNUSED_ARG (osp);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_PTHREADS && !ACE_LACKS_PTHREAD_SIGMASK */
+}
+
+ACE_INLINE int
+sigaction (int signum, const ACE_SIGACTION *nsa, ACE_SIGACTION *osa)
+{
+ ACE_OS_TRACE ("ACE_OS::sigaction");
+ if (signum == 0)
+ return 0;
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ struct sigaction sa;
+
+ if (osa == 0)
+ osa = &sa;
+
+ if (nsa == 0)
+ {
+ osa->sa_handler = ::signal (signum, SIG_IGN);
+ ::signal (signum, osa->sa_handler);
+ }
+ else
+ osa->sa_handler = ::signal (signum, nsa->sa_handler);
+ return osa->sa_handler == SIG_ERR ? -1 : 0;
+#elif defined (ACE_LACKS_SIGACTION)
+ ACE_UNUSED_ARG (nsa);
+ ACE_UNUSED_ARG (osa);
+ ACE_NOTSUP_RETURN (-1);
+#elif !defined (ACE_HAS_SIGACTION_CONSTP2)
+ ACE_OSCALL_RETURN (::sigaction (signum,
+ const_cast<ACE_SIGACTION*> (nsa),
+ osa),
+ int, -1);
+#else
+ ACE_OSCALL_RETURN (::sigaction (signum, nsa, osa), int, -1);
+#endif /* ACE_WIN32 !ACE_HAS_WINCE */
+}
+
+ACE_INLINE int
+sigaddset (sigset_t *s, int signum)
+{
+ ACE_OS_TRACE ("ACE_OS::sigaddset");
+#if defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS)
+ if (s == 0)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ else if (signum < 1 || signum >= ACE_NSIG)
+ {
+ errno = EINVAL;
+ return -1; // Invalid signum, return error
+ }
+ *s |= (1 << (signum - 1)) ;
+ return 0 ;
+#else
+ ACE_OSCALL_RETURN (::sigaddset (s, signum), int, -1);
+#endif /* ACE_LACKS_SIGSET || ACE_LACKS_SIGSET_DEFINITIONS */
+}
+
+ACE_INLINE int
+sigdelset (sigset_t *s, int signum)
+{
+#if defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS)
+ if (s == 0)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ else if (signum < 1 || signum >= ACE_NSIG)
+ {
+ errno = EINVAL;
+ return -1; // Invalid signum, return error
+ }
+ *s &= ~(1 << (signum - 1)) ;
+ return 0;
+#else
+ ACE_OSCALL_RETURN (::sigdelset (s, signum), int, -1);
+#endif /* ACE_LACKS_SIGSET || ACE_LACKS_SIGSET_DEFINITIONS */
+}
+
+ACE_INLINE int
+sigemptyset (sigset_t *s)
+{
+#if defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS)
+ if (s == 0)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ *s = 0 ;
+ return 0;
+#else
+ ACE_OSCALL_RETURN (::sigemptyset (s), int, -1);
+#endif /* ACE_LACKS_SIGSET || ACE_LACKS_SIGSET_DEFINITIONS */
+}
+
+ACE_INLINE int
+sigfillset (sigset_t *s)
+{
+#if defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS)
+ if (s == 0)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ *s = ~(sigset_t) 0;
+ return 0 ;
+#else
+ ACE_OSCALL_RETURN (::sigfillset (s), int, -1);
+#endif /* ACE_LACKS_SIGSET || ACE_LACKS_SIGSET_DEFINITIONS */
+}
+
+ACE_INLINE int
+sigismember (sigset_t *s, int signum)
+{
+#if defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS)
+ if (s == 0)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ else if (signum < 1 || signum >= ACE_NSIG)
+ {
+ errno = EINVAL;
+ return -1; // Invalid signum, return error
+ }
+ return ((*s & (1 << (signum - 1))) != 0) ;
+#else
+# if defined (ACE_HAS_SIGISMEMBER_BUG)
+ if (signum < 1 || signum >= ACE_NSIG)
+ {
+ errno = EINVAL;
+ return -1; // Invalid signum, return error
+ }
+# endif /* ACE_HAS_SIGISMEMBER_BUG */
+ ACE_OSCALL_RETURN (::sigismember (s, signum), int, -1);
+#endif /* ACE_LACKS_SIGSET || ACE_LACKS_SIGSET_DEFINITIONS */
+}
+
+ACE_INLINE ACE_SignalHandler
+signal (int signum, ACE_SignalHandler func)
+{
+ if (signum == 0)
+ return 0;
+ else
+# if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) || !defined (ACE_LACKS_UNIX_SIGNALS)
+# if !defined (ACE_HAS_TANDEM_SIGNALS) && !defined (ACE_HAS_LYNXOS_SIGNALS)
+ return ::signal (signum, func);
+# else
+ return (ACE_SignalHandler) ::signal (signum, (void (*)(int)) func);
+# endif /* !ACE_HAS_TANDEM_SIGNALS */
+#else
+ // @@ WINCE: Don't know how to implement signal on WinCE (yet.)
+ ACE_UNUSED_ARG (signum);
+ ACE_UNUSED_ARG (func);
+ ACE_NOTSUP_RETURN (0); // Should return SIG_ERR but it is not defined on WinCE.
+#endif /* defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) || !defined (ACE_LACKS_UNIX_SIGNALS) */
+}
+
+ACE_INLINE int
+sigprocmask (int how, const sigset_t *nsp, sigset_t *osp)
+{
+#if defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS)
+ ACE_UNUSED_ARG (how);
+ ACE_UNUSED_ARG (nsp);
+ ACE_UNUSED_ARG (osp);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::sigprocmask (how, nsp, osp), int, -1);
+#endif /* ACE_LACKS_SIGSET || ACE_LACKS_SIGSET_DEFINITIONS */
+}
+
+ACE_INLINE int
+sigsuspend (const sigset_t *sigset)
+{
+#if defined (ACE_HAS_SIGSUSPEND)
+ sigset_t s;
+
+ if (sigset == 0)
+ {
+ sigset = &s;
+ ACE_OS::sigemptyset (&s);
+ }
+ ACE_OSCALL_RETURN (::sigsuspend (sigset), int, -1);
+#else
+ ACE_UNUSED_ARG (sigset);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SIGSUSPEND */
+}
+
+} /* end namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_stdio.cpp b/ACE/ace/OS_NS_stdio.cpp
new file mode 100644
index 00000000000..633dbf3a366
--- /dev/null
+++ b/ACE/ace/OS_NS_stdio.cpp
@@ -0,0 +1,456 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_RCSID (ace,
+ OS_NS_stdio,
+ "$Id$")
+
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_stdio.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+# if defined (ACE_WIN32)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+ACE_TEXT_OSVERSIONINFO ACE_OS::win32_versioninfo_;
+HINSTANCE ACE_OS::win32_resource_module_;
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_DLL) && (ACE_HAS_DLL == 1) && !defined (ACE_HAS_WINCE)
+// This function is called by the OS when the ACE DLL is loaded. We
+// use it to determine the default module containing ACE's resources.
+extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID)
+{
+ if (reason == DLL_PROCESS_ATTACH)
+ {
+# if defined (ACE_DISABLES_THREAD_LIBRARY_CALLS) && (ACE_DISABLES_THREAD_LIBRARY_CALLS == 1)
+ ::DisableThreadLibraryCalls (instance);
+# endif /* ACE_DISABLES_THREAD_LIBRARY_CALLS */
+ ACE_OS::set_win32_resource_module(instance);
+ }
+ else if (reason == DLL_THREAD_DETACH)
+ {
+ ACE_OS::cleanup_tss (0);
+ }
+ return TRUE;
+}
+# endif /* ACE_HAS_DLL && ACE_HAS_DLL == 1 */
+# endif /* ACE_WIN32 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_OS::ace_flock_t::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_OS_TRACE ("ACE_OS::ace_flock_t::dump");
+
+# if 0
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("handle_ = %u"), this->handle_));
+# if defined (ACE_WIN32)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nInternal = %d"),
+ this->overlapped_.Internal));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nInternalHigh = %d"),
+ this->overlapped_.InternalHigh));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nOffsetHigh = %d"),
+ this->overlapped_.OffsetHigh));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhEvent = %d"),
+ this->overlapped_.hEvent));
+# else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nl_whence = %d"),
+ this->lock_.l_whence));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nl_start = %d"), this->lock_.l_start));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nl_len = %d"), this->lock_.l_len));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nl_type = %d"), this->lock_.l_type));
+# endif /* ACE_WIN32 */
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+# endif /* 0 */
+#endif /* ACE_HAS_DUMP */
+}
+
+/*****************************************************************************/
+
+#if defined (ACE_USES_WCHAR)
+void ACE_OS::checkUnicodeFormat (FILE* fp)
+{
+ if (fp != 0)
+ {
+ // Due to the ACE_TCHAR definition, all default input files, such as
+ // svc.conf, have to be in Unicode format (small endian) on WinCE
+ // because ACE has all 'char' converted into ACE_TCHAR.
+ // However, for TAO, ASCII files, such as IOR file, can still be read
+ // and be written without any error since given buffers are all in 'char'
+ // type instead of ACE_TCHAR. Therefore, it is user's reponsibility to
+ // select correct buffer type.
+
+ // At this point, check if the file is Unicode or not.
+ ACE_UINT16 first_two_bytes;
+ size_t numRead =
+ ACE_OS::fread(&first_two_bytes, sizeof (first_two_bytes), 1, fp);
+
+ if (numRead == 1)
+ {
+ if ((first_two_bytes != 0xFFFE) && // not a small endian Unicode file
+ (first_two_bytes != 0xFEFF)) // not a big endian Unicode file
+ {
+ // set file pointer back to the beginning
+#if defined (ACE_WIN32)
+ ACE_OS::fseek(fp, 0, FILE_BEGIN);
+#else
+ ACE_OS::fseek(fp, 0, SEEK_SET);
+#endif /* ACE_WIN32 */
+ }
+ }
+ // if it is a Unicode file, file pointer will be right next to the first
+ // two-bytes
+ }
+}
+#endif // ACE_USES_WCHAR
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+namespace
+{
+ /// Translate fopen's mode char to open's mode. This helper function
+ /// is here to avoid maintaining several pieces of identical code.
+ void
+ fopen_mode_to_open_mode_converter (ACE_TCHAR x, int & hmode)
+ {
+ switch (x)
+ {
+ case ACE_TEXT ('r'):
+ if (ACE_BIT_DISABLED (hmode, _O_RDWR))
+ {
+ ACE_CLR_BITS (hmode, _O_WRONLY);
+ ACE_SET_BITS (hmode, _O_RDONLY);
+ }
+ break;
+ case ACE_TEXT ('w'):
+ if (ACE_BIT_DISABLED (hmode, _O_RDWR))
+ {
+ ACE_CLR_BITS (hmode, _O_RDONLY);
+ ACE_SET_BITS (hmode, _O_WRONLY);
+ }
+ ACE_SET_BITS (hmode, _O_CREAT | _O_TRUNC);
+ break;
+ case ACE_TEXT ('a'):
+ if (ACE_BIT_DISABLED (hmode, _O_RDWR))
+ {
+ ACE_CLR_BITS (hmode, _O_RDONLY);
+ ACE_SET_BITS (hmode, _O_WRONLY);
+ }
+ ACE_SET_BITS (hmode, _O_CREAT | _O_APPEND);
+ break;
+ case ACE_TEXT ('+'):
+ ACE_CLR_BITS (hmode, _O_RDONLY | _O_WRONLY);
+ ACE_SET_BITS (hmode, _O_RDWR);
+ break;
+ case ACE_TEXT ('t'):
+ ACE_CLR_BITS (hmode, _O_BINARY);
+ ACE_SET_BITS (hmode, _O_TEXT);
+ break;
+ case ACE_TEXT ('b'):
+ ACE_CLR_BITS (hmode, _O_TEXT);
+ ACE_SET_BITS (hmode, _O_BINARY);
+ break;
+ }
+ }
+} // Close anonymous namespace
+
+FILE *
+ACE_OS::fopen (const char *filename,
+ const ACE_TCHAR *mode)
+{
+ ACE_OS_TRACE ("ACE_OS::fopen");
+ int hmode = _O_TEXT;
+
+ // Let the chips fall where they may if the user passes in a NULL
+ // mode string. Convert to an empty mode string to prevent a
+ // crash.
+ ACE_TCHAR const empty_mode[] = ACE_TEXT ("");
+ if (!mode)
+ mode = empty_mode;
+
+ for (ACE_TCHAR const* mode_ptr = mode; *mode_ptr != 0; ++mode_ptr)
+ fopen_mode_to_open_mode_converter (*mode_ptr, hmode);
+
+ ACE_HANDLE const handle = ACE_OS::open (filename, hmode);
+ if (handle != ACE_INVALID_HANDLE)
+ {
+ hmode &= _O_TEXT | _O_RDONLY | _O_APPEND;
+
+ int const fd = ::_open_osfhandle (intptr_t (handle), hmode);
+
+ if (fd != -1)
+ {
+# if defined (__BORLANDC__) && !defined (ACE_USES_WCHAR)
+ FILE * const fp = ::_fdopen (fd, const_cast<ACE_TCHAR *> (mode));
+# elif defined (__BORLANDC__) && defined (ACE_USES_WCHAR)
+ FILE * const fp = ::_wfdopen (fd, const_cast<ACE_TCHAR *> (mode));
+# elif defined (ACE_USES_WCHAR)
+ FILE * const fp = ::_wfdopen (fd, mode);
+# else
+ FILE * const fp = ::fdopen (fd, mode);
+# endif /* defined(__BORLANDC__) && !defined (ACE_USES_WCHAR)) */
+ if (fp != 0)
+ {
+# if defined (ACE_USES_WCHAR)
+ checkUnicodeFormat(fp);
+# endif // ACE_USES_WCHAR
+ return fp;
+ }
+ ::_close (fd);
+ }
+
+ ACE_OS::close (handle);
+ }
+ return 0;
+}
+
+#if defined (ACE_HAS_WCHAR)
+FILE *
+ACE_OS::fopen (const wchar_t *filename,
+ const ACE_TCHAR *mode)
+{
+ ACE_OS_TRACE ("ACE_OS::fopen");
+ int hmode = _O_TEXT;
+
+ for (const ACE_TCHAR *mode_ptr = mode; *mode_ptr != 0; mode_ptr++)
+ fopen_mode_to_open_mode_converter (*mode_ptr, hmode);
+
+ ACE_HANDLE handle = ACE_OS::open (filename, hmode);
+ if (handle != ACE_INVALID_HANDLE)
+ {
+ hmode &= _O_TEXT | _O_RDONLY | _O_APPEND;
+
+ int const fd = ::_open_osfhandle (intptr_t (handle), hmode);
+
+ if (fd != -1)
+ {
+# if defined (__BORLANDC__) && !defined (ACE_USES_WCHAR)
+ FILE *fp = ::_fdopen (fd, const_cast<char *> (mode));
+# elif defined (__BORLANDC__) && defined (ACE_USES_WCHAR)
+ FILE *fp = ::_wfdopen (fd, const_cast<wchar_t *> (mode));
+# elif defined (ACE_USES_WCHAR)
+ FILE *fp = ::_wfdopen (fd, mode);
+# else
+ FILE *fp = ::fdopen (fd, mode);
+# endif /* defined(__BORLANDC__) && !defined (ACE_USES_WCHAR)) */
+ if (fp != 0)
+ {
+# if defined (ACE_USES_WCHAR)
+ checkUnicodeFormat(fp);
+# endif // ACE_USES_WCHAR
+ return fp;
+ }
+ ::_close (fd);
+ }
+
+ ACE_OS::close (handle);
+ }
+ return 0;
+}
+#endif /* ACE_HAS_WCHAR */
+
+#endif /* ACE_WIN32 */
+
+// The following *printf functions aren't inline because
+// they use varargs.
+
+int
+ACE_OS::fprintf (FILE *fp, const char *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::fprintf");
+ int result = 0;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vfprintf (fp, format, ap);
+ va_end (ap);
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+int
+ACE_OS::fprintf (FILE *fp, const wchar_t *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::fprintf");
+ int result = 0;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vfprintf (fp, format, ap);
+ va_end (ap);
+ return result;
+}
+#endif /* ACE_HAS_WCHAR */
+
+int
+ACE_OS::asprintf (char **bufp, const char *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::asprintf");
+ int result;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vasprintf (bufp, format, ap);
+ va_end (ap);
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+int
+ACE_OS::asprintf (wchar_t **bufp, const wchar_t *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::asprintf");
+ int result;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vasprintf (bufp, format, ap);
+ va_end (ap);
+ return result;
+}
+#endif /* ACE_HAS_WCHAR */
+
+int
+ACE_OS::printf (const char *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::printf");
+ int result;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vprintf (format, ap);
+ va_end (ap);
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+int
+ACE_OS::printf (const wchar_t *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::printf");
+ int result;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vprintf (format, ap);
+ va_end (ap);
+ return result;
+}
+#endif /* ACE_HAS_WCHAR */
+
+int
+ACE_OS::snprintf (char *buf, size_t maxlen, const char *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::snprintf");
+ int result;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vsnprintf (buf, maxlen, format, ap);
+ va_end (ap);
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+int
+ACE_OS::snprintf (wchar_t *buf, size_t maxlen, const wchar_t *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::snprintf");
+ int result;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vsnprintf (buf, maxlen, format, ap);
+ va_end (ap);
+ return result;
+}
+#endif /* ACE_HAS_WCHAR */
+
+int
+ACE_OS::sprintf (char *buf, const char *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::sprintf");
+ int result;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vsprintf (buf, format, ap);
+ va_end (ap);
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+int
+ACE_OS::sprintf (wchar_t *buf, const wchar_t *format, ...)
+{
+ // ACE_OS_TRACE ("ACE_OS::sprintf");
+ int result;
+ va_list ap;
+ va_start (ap, format);
+ result = ACE_OS::vsprintf (buf, format, ap);
+ va_end (ap);
+ return result;
+}
+#endif /* ACE_HAS_WCHAR */
+
+#if !defined (ACE_HAS_VASPRINTF)
+int
+ACE_OS::vasprintf_emulation(char **bufp, const char *format, va_list argptr)
+{
+ int size;
+
+ va_list ap;
+ va_copy (ap, argptr);
+ size = ACE_OS::vsnprintf(0, 0, format, ap);
+ va_end (ap);
+
+ if (size != -1)
+ {
+ char *buf = reinterpret_cast<char*>(ACE_OS::malloc(size + 1));
+ if (!buf)
+ return -1;
+
+ va_list aq;
+ va_copy (aq, argptr);
+ size = ACE_OS::vsnprintf(buf, size + 1, format, aq);
+ va_end (aq);
+
+ if (size != -1)
+ *bufp = buf;
+ }
+
+ return size;
+}
+#endif /* !ACE_HAS_VASPRINTF */
+
+#if defined (ACE_HAS_WCHAR)
+#if !defined (ACE_HAS_VASWPRINTF)
+int
+ACE_OS::vaswprintf_emulation(wchar_t **bufp, const wchar_t *format, va_list argptr)
+{
+ int size;
+
+ va_list ap;
+ va_copy (ap, argptr);
+ size = ACE_OS::vsnprintf(0, 0, format, ap);
+ va_end (ap);
+
+ if (size != -1)
+ {
+ wchar_t *buf = reinterpret_cast<wchar_t*>
+ (ACE_OS::malloc((size + 1) * sizeof(wchar_t)));
+ if (!buf)
+ return -1;
+
+ va_list aq;
+ va_copy (aq, argptr);
+ size = ACE_OS::vsnprintf(buf, size + 1, format, aq);
+ va_end (aq);
+
+ if (size != -1)
+ *bufp = buf;
+ }
+
+ return size;
+}
+#endif /* !ACE_HAS_VASWPRINTF */
+#endif /* ACE_HAS_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_stdio.h b/ACE/ace/OS_NS_stdio.h
new file mode 100644
index 00000000000..e96a08df650
--- /dev/null
+++ b/ACE/ace/OS_NS_stdio.h
@@ -0,0 +1,530 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_stdio.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_STDIO_H
+# define ACE_OS_NS_STDIO_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/os_include/os_stdio.h"
+#include "ace/os_include/os_fcntl.h"
+#include /**/ "ace/ACE_export.h"
+
+/* OPENVMS needs unistd for cuserid() */
+#if defined (CYGWIN32) || defined (ACE_OPENVMS)
+# include "ace/os_include/os_unistd.h"
+#endif /* CYGWIN32 || ACE_OPENVMS */
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+/*
+ * We inline and undef some functions that may be implemented
+ * as macros on some platforms. This way macro definitions will
+ * be usable later as there is no way to save the macro definition
+ * using the pre-processor.
+ *
+ */
+#if !defined (ACE_LACKS_CLEARERR)
+inline void ace_clearerr_helper (FILE *stream)
+{
+# if defined (clearerr)
+ clearerr (stream);
+# undef clearerr
+# else
+ ACE_STD_NAMESPACE::clearerr (stream);
+# endif /* defined (clearerr) */
+}
+#endif /* !ACE_LACKS_CLEARERR */
+
+inline int ace_fgetc_helper (FILE *fp)
+{
+#if defined (fgetc)
+ return fgetc (fp);
+#undef fgetc
+#else
+ return ACE_STD_NAMESPACE::fgetc (fp);
+#endif /* defined (fgetc) */
+}
+
+inline int ace_fputc_helper (int ch, FILE *fp)
+{
+#if defined (fputc)
+ return fputc (ch, fp);
+#undef fputc
+#else
+ return ACE_STD_NAMESPACE::fputc (ch, fp);
+#endif /* defined (fputc) */
+}
+
+inline int ace_getc_helper (FILE *fp)
+{
+#if defined (getc)
+ return getc (fp);
+#undef getc
+#else
+ return ACE_STD_NAMESPACE::getc (fp);
+#endif /* defined (getc) */
+}
+
+inline int ace_putc_helper (int ch, FILE *fp)
+{
+#if defined (putc)
+ return putc (ch, fp);
+#undef putc
+#else
+ return ACE_STD_NAMESPACE::putc (ch, fp);
+#endif /* defined (putc) */
+}
+
+inline int ace_ungetc_helper (int ch, FILE *fp)
+{
+#if defined (ungetc)
+ return ungetc (ch, fp);
+#undef ungetc
+#else
+ return ACE_STD_NAMESPACE::ungetc (ch, fp);
+#endif /* defined (ungetc) */
+}
+
+
+#if !defined (ACE_LACKS_CUSERID) && !defined(ACE_HAS_ALT_CUSERID) \
+ && !defined(ACE_WIN32) && !defined (ACE_VXWORKS)
+/// Helper for the ACE_OS::cuserid() function
+/**
+ * On some platforms cuserid is a macro. Defining ACE_OS::cuserid()
+ * becomes really hard, as there is no way to save the macro
+ * definition using the pre-processor.
+ * This inline function achieves the same effect, without namespace
+ * pollution or performance penalties.
+ *
+ * @todo We maybe should move a lot of the code in ACE_OS::cuserid here so
+ * it is treated the same as the above ace_difftime and ace_timezone.
+ * But since there is a good deal more code in ACE_OS::cuserid, we
+ * probably need to move some of it off into some sort of emulation
+ * function.
+ */
+inline char *ace_cuserid(char *user)
+{
+ return cuserid(user);
+}
+#endif /* !ACE_LACKS_CUSERID && !ACE_HAS_ALT_CUSERID && ... */
+
+# if defined (ACE_LACKS_FILELOCKS)
+# if ! defined (ACE_VXWORKS) && ! defined (ACE_HAS_RTEMS) && !defined (INTEGRITY)
+// VxWorks defines struct flock in sys/fcntlcom.h. But it doesn't
+// appear to support flock (). RTEMS defines struct flock but
+// currently does not support locking.
+struct flock
+{
+ short l_type;
+ short l_whence;
+ ACE_OFF_T l_start;
+ ACE_OFF_T l_len; /* len == 0 means until end of file */
+ long l_sysid;
+ pid_t l_pid;
+ long l_pad[4]; /* reserve area */
+};
+# endif /* ! VXWORKS */
+# endif /* ACE_LACKS_FILELOCKS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ /**
+ * @class ace_flock_t
+ *
+ * @brief OS file locking structure.
+ */
+ class ACE_Export ace_flock_t
+ {
+ public:
+ /// Dump state of the object.
+ void dump (void) const;
+
+# if defined (ACE_WIN32)
+ ACE_OVERLAPPED overlapped_;
+# else
+ struct flock lock_;
+# endif /* ACE_WIN32 */
+
+ /// Name of this filelock.
+ const ACE_TCHAR *lockname_;
+
+ /// Handle to the underlying file.
+ ACE_HANDLE handle_;
+ };
+
+# if defined (ACE_USES_WCHAR)
+ // If fp points to the Unicode format file, the file pointer will be moved right next
+ // to the Unicode header (2 types). Otherwise, file pointer will be at the beginning.
+ extern ACE_Export
+ void checkUnicodeFormat (FILE* fp);
+# endif // ACE_USES_WCHAR
+
+# if !defined (ACE_LACKS_CLEARERR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void clearerr (FILE* fp);
+# endif /* !ACE_LACKS_CLEARERR */
+
+ //@{ @name Wrappers to obtain the current user id
+ // Legacy as per SUSV3
+# if !defined (ACE_LACKS_CUSERID)
+# if defined(cuserid)
+# undef cuserid
+# endif /* cuserid */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *cuserid (char *user,
+ size_t maxlen = ACE_MAX_USERID);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *cuserid (wchar_t *user,
+ size_t maxlen = ACE_MAX_USERID);
+# endif /* ACE_HAS_WCHAR */
+# endif /* ACE_LACKS_CUSERID */
+ //@}
+
+ extern ACE_Export
+ int asprintf (char **bufp, const char* format, ...);
+
+# if defined (ACE_HAS_WCHAR)
+ extern ACE_Export
+ int asprintf (wchar_t **bufp, const wchar_t* format, ...);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fclose (FILE *fp);
+
+# if defined (fdopen)
+# undef fdopen
+# endif /* fdopen */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ FILE *fdopen (ACE_HANDLE handle, const ACE_TCHAR *mode);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fflush (FILE *fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fgetc (FILE* fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getc (FILE* fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fgetpos (FILE* fp, fpos_t* pos);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *fgets (char *buf, int size, FILE *fp);
+
+# if defined (ACE_HAS_WCHAR) && !defined(ACE_LACKS_FGETWS)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *fgets (wchar_t *buf, int size, FILE *fp);
+# endif /* ACE_HAS_WCHAR && !ACE_LACKS_FGETWS */
+
+ //@{ @name A set of wrappers for file locks.
+
+# if defined (ACE_WIN32)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void flock_adjust_params (ace_flock_t *lock,
+ short whence,
+ ACE_OFF_T &start,
+ ACE_OFF_T &len);
+# endif /* ACE_WIN32 */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int flock_init (ace_flock_t *lock,
+ int flags = 0,
+ const ACE_TCHAR *name = 0,
+ mode_t perms = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int flock_destroy (ace_flock_t *lock,
+ int unlink_file = 1);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int flock_rdlock (ace_flock_t *lock,
+ short whence = 0,
+ ACE_OFF_T start = 0,
+ ACE_OFF_T len = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int flock_tryrdlock (ace_flock_t *lock,
+ short whence = 0,
+ ACE_OFF_T start = 0,
+ ACE_OFF_T len = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int flock_trywrlock (ace_flock_t *lock,
+ short whence = 0,
+ ACE_OFF_T start = 0,
+ ACE_OFF_T len = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int flock_unlock (ace_flock_t *lock,
+ short whence = 0,
+ ACE_OFF_T start = 0,
+ ACE_OFF_T len = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int flock_wrlock (ace_flock_t *lock,
+ short whence = 0,
+ ACE_OFF_T start = 0,
+ ACE_OFF_T len = 0);
+
+ //@}
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_WIN32 */
+ FILE *fopen (const char *filename, const ACE_TCHAR *mode);
+
+#if defined (ACE_HAS_WCHAR)
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ extern ACE_Export
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif /* ACE_WIN32 */
+ FILE *fopen (const wchar_t *filename, const ACE_TCHAR *mode);
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_WIN32)
+ /// Default Win32 Security Attributes definition.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ LPSECURITY_ATTRIBUTES default_win32_security_attributes (LPSECURITY_ATTRIBUTES);
+ ACE_NAMESPACE_INLINE_FUNCTION
+ LPSECURITY_ATTRIBUTES default_win32_security_attributes_r (LPSECURITY_ATTRIBUTES,
+ LPSECURITY_ATTRIBUTES,
+ SECURITY_DESCRIPTOR*);
+
+ // = Win32 OS version determination function.
+ /// Return the win32 OSVERSIONINFO structure.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const ACE_TEXT_OSVERSIONINFO &get_win32_versioninfo (void);
+
+ // = A pair of functions for modifying ACE's Win32 resource usage.
+ /// Return the handle of the module containing ACE's resources. By
+ /// default, for a DLL build of ACE this is a handle to the ACE DLL
+ /// itself, and for a static build it is a handle to the executable.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ HINSTANCE get_win32_resource_module (void);
+
+ /// Allow an application to modify which module contains ACE's
+ /// resources. This is mainly useful for a static build of ACE where
+ /// the required resources reside somewhere other than the executable.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void set_win32_resource_module (HINSTANCE);
+
+ extern ACE_Export ACE_TEXT_OSVERSIONINFO win32_versioninfo_;
+
+ extern ACE_Export HINSTANCE win32_resource_module_;
+
+#endif /* ACE_WIN32 */
+
+ extern ACE_Export
+ int fprintf (FILE *fp, const char *format, ...);
+
+# if defined (ACE_HAS_WCHAR)
+ extern ACE_Export
+ int fprintf (FILE *fp, const wchar_t *format, ...);
+# endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ungetc (int c,
+ FILE *fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fputc (int c,
+ FILE *fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int putc (int c,
+ FILE *fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fputs (const char *s,
+ FILE *stream);
+
+# if defined (ACE_HAS_WCHAR) && !defined(ACE_LACKS_FPUTWS)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fputs (const wchar_t *s,
+ FILE *stream);
+# endif /* ACE_HAS_WCHAR && !ACE_LACKS_FPUTWS */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t fread (void *ptr,
+ size_t size,
+ size_t nelems,
+ FILE *fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ FILE *freopen (const ACE_TCHAR *filename,
+ const ACE_TCHAR *mode,
+ FILE* stream);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fseek (FILE *fp,
+ long offset,
+ int ptrname);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fsetpos (FILE* fp, fpos_t* pos);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long ftell (FILE* fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t fwrite (const void *ptr,
+ size_t size,
+ size_t nitems,
+ FILE *fp);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void perror (const char *s);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void perror (const wchar_t *s);
+#endif /* ACE_HAS_WCHAR */
+
+ extern ACE_Export
+ int printf (const char *format, ...);
+
+#if defined (ACE_HAS_WCHAR)
+ extern ACE_Export
+ int printf (const wchar_t *format, ...);
+#endif
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int puts (const char *s);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int puts (const wchar_t *s);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rename (const char *old_name,
+ const char *new_name,
+ int flags = -1);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rename (const wchar_t *old_name,
+ const wchar_t *new_name,
+ int flags = -1);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void rewind (FILE *fp);
+
+ extern ACE_Export
+ int snprintf (char *buf, size_t maxlen, const char *format, ...);
+
+# if defined (ACE_HAS_WCHAR)
+ extern ACE_Export
+ int snprintf (wchar_t *buf, size_t maxlen, const wchar_t *format, ...);
+# endif /* ACE_HAS_WCHAR */
+
+ extern ACE_Export
+ int sprintf (char *buf, const char *format, ...);
+
+# if defined (ACE_HAS_WCHAR)
+ extern ACE_Export
+ int sprintf (wchar_t *buf, const wchar_t *format, ...);
+# endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *tempnam (const char *dir = 0,
+ const char *pfx = 0);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *tempnam (const wchar_t *dir,
+ const wchar_t *pfx = 0);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vasprintf (char **bufp, const char *format, va_list argptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vprintf (const char *format, va_list argptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vfprintf (FILE *fp, const char *format, va_list argptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vsprintf (char *buffer, const char *format, va_list argptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vsnprintf (char *buffer, size_t maxlen, const char *format, va_list argptr);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vasprintf (wchar_t **bufp, const wchar_t *format, va_list argptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vprintf (const wchar_t *format, va_list argptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vfprintf (FILE *fp, const wchar_t *format, va_list argptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vsprintf (wchar_t *buffer, const wchar_t *format, va_list argptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int vsnprintf (wchar_t *buffer, size_t maxlen, const wchar_t *format, va_list argptr);
+# endif /* ACE_HAS_WCHAR */
+
+#if !defined (ACE_HAS_VASPRINTF)
+ extern ACE_Export
+ int vasprintf_emulation (char **bufp, const char *format, va_list argptr);
+#endif /* !ACE_HAS_VASPRINTF */
+
+#if defined (ACE_HAS_WCHAR)
+#if !defined (ACE_HAS_VASWPRINTF)
+ extern ACE_Export
+ int vaswprintf_emulation (wchar_t **bufp, const wchar_t *format, va_list argptr);
+#endif /* !ACE_HAS_VASWPRINTF */
+#endif /* ACE_HAS_WCHAR */
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_stdio.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_STDIO_H */
diff --git a/ACE/ace/OS_NS_stdio.inl b/ACE/ace/OS_NS_stdio.inl
new file mode 100644
index 00000000000..b134e754afe
--- /dev/null
+++ b/ACE/ace/OS_NS_stdio.inl
@@ -0,0 +1,1224 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_pwd.h"
+#include "ace/OS_NS_macros.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_Memory.h"
+
+#if defined (ACE_HAS_TRIO)
+# include <trio.h>
+#endif /* ACE_HAS_TRIO */
+
+/*****************************************************************************/
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_WIN32)
+ACE_INLINE void
+ACE_OS::flock_adjust_params (ACE_OS::ace_flock_t *lock,
+ short whence,
+ ACE_OFF_T &start,
+ ACE_OFF_T &len)
+{
+ switch (whence)
+ {
+ case SEEK_SET:
+ break;
+ case SEEK_CUR:
+ {
+ LARGE_INTEGER offset;
+# if !defined (ACE_LACKS_WIN32_SETFILEPOINTEREX)
+ LARGE_INTEGER distance;
+ distance.QuadPart = 0;
+ if (!::SetFilePointerEx (lock->handle_,
+ distance,
+ &offset,
+ FILE_CURRENT))
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return;
+ }
+# else
+ offset.LowPart = ::SetFilePointer (lock->handle_,
+ 0,
+ &offset.HighPart,
+ FILE_CURRENT);
+ if (offset.LowPart == INVALID_SET_FILE_POINTER &&
+ ::GetLastError() != NO_ERROR)
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return;
+ }
+# endif /* ACE_LACKS_WIN32_SETFILEPOINTEREX */
+
+# if defined (_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
+ start += offset.QuadPart;
+# else
+ start += offset.LowPart;
+# endif /* _FILE_OFFSET_BITS == 64 */
+ }
+ break;
+ case SEEK_END:
+ {
+ ACE_OFF_T const size = ACE_OS::filesize (lock->handle_);
+ if (size == -1)
+ return;
+
+ start += size;
+ }
+ break;
+ }
+ lock->overlapped_.Offset = ACE_LOW_PART (start);
+ lock->overlapped_.OffsetHigh = ACE_HIGH_PART (start);
+ if (len == 0)
+ {
+ ACE_OFF_T const tlen = ACE_OS::filesize (lock->handle_);
+ if (tlen != -1)
+ len = tlen - start;
+ }
+}
+#endif /* ACE_WIN32 */
+
+ACE_INLINE int
+ACE_OS::flock_init (ACE_OS::ace_flock_t *lock,
+ int flags,
+ const ACE_TCHAR *name,
+ mode_t perms)
+{
+ ACE_OS_TRACE ("ACE_OS::flock_init");
+#if defined (ACE_WIN32)
+ // Once initialized, these values are never changed.
+ lock->overlapped_.Internal = 0;
+ lock->overlapped_.InternalHigh = 0;
+ lock->overlapped_.OffsetHigh = 0;
+ lock->overlapped_.hEvent = 0;
+#endif /* ACE_WIN32 */
+ lock->handle_ = ACE_INVALID_HANDLE;
+ lock->lockname_ = 0;
+
+ if (name != 0)
+ {
+ ACE_OSCALL (ACE_OS::open (name, flags, perms),
+ ACE_HANDLE,
+ ACE_INVALID_HANDLE,
+ lock->handle_);
+ if (lock->handle_ != ACE_INVALID_HANDLE)
+ lock->lockname_ = ACE_OS::strdup (name);
+ return lock->handle_ == ACE_INVALID_HANDLE ? -1 : 0;
+ }
+ else
+ return 0;
+}
+
+ACE_INLINE int
+ACE_OS::flock_unlock (ACE_OS::ace_flock_t *lock,
+ short whence,
+ ACE_OFF_T start,
+ ACE_OFF_T len)
+{
+ ACE_OS_TRACE ("ACE_OS::flock_unlock");
+#if defined (ACE_LACKS_FILELOCKS)
+ ACE_UNUSED_ARG (lock);
+ ACE_UNUSED_ARG (whence);
+ ACE_UNUSED_ARG (start);
+ ACE_UNUSED_ARG (len);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+ ACE_OS::flock_adjust_params (lock, whence, start, len);
+ DWORD low_len = ACE_LOW_PART (len);
+ DWORD high_len = ACE_HIGH_PART (len);
+ ACE_WIN32CALL_RETURN (
+ ACE_ADAPT_RETVAL (::UnlockFile (lock->handle_,
+ lock->overlapped_.Offset,
+ lock->overlapped_.OffsetHigh,
+ low_len,
+ high_len),
+ ace_result_), int, -1);
+#else
+ lock->lock_.l_whence = whence;
+ lock->lock_.l_start = start;
+ lock->lock_.l_len = len;
+ lock->lock_.l_type = F_UNLCK; // Unlock file.
+
+ // release lock
+ ACE_OSCALL_RETURN (ACE_OS::fcntl (lock->handle_, F_SETLK,
+ reinterpret_cast<long> (&lock->lock_)),
+ int, -1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_OS::flock_destroy (ACE_OS::ace_flock_t *lock,
+ int unlink_file)
+{
+ ACE_OS_TRACE ("ACE_OS::flock_destroy");
+ if (lock->handle_ != ACE_INVALID_HANDLE)
+ {
+ ACE_OS::flock_unlock (lock);
+ // Close the handle.
+ ACE_OS::close (lock->handle_);
+ lock->handle_ = ACE_INVALID_HANDLE;
+ if (lock->lockname_ != 0)
+ {
+ if (unlink_file)
+ ACE_OS::unlink (lock->lockname_);
+ ACE_OS::free (
+ static_cast<void *> (const_cast<ACE_TCHAR *> (lock->lockname_)));
+ }
+ lock->lockname_ = 0;
+ }
+ return 0;
+}
+
+ACE_INLINE int
+ACE_OS::flock_rdlock (ACE_OS::ace_flock_t *lock,
+ short whence,
+ ACE_OFF_T start,
+ ACE_OFF_T len)
+{
+ ACE_OS_TRACE ("ACE_OS::flock_rdlock");
+#if defined (ACE_LACKS_FILELOCKS)
+ ACE_UNUSED_ARG (lock);
+ ACE_UNUSED_ARG (whence);
+ ACE_UNUSED_ARG (start);
+ ACE_UNUSED_ARG (len);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+ ACE_OS::flock_adjust_params (lock, whence, start, len);
+ DWORD low_len = ACE_LOW_PART (len);
+ DWORD high_len = ACE_HIGH_PART (len);
+# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_,
+ 0,
+ 0,
+ low_len,
+ high_len,
+ &lock->overlapped_),
+ ace_result_), int, -1);
+# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
+ ACE_WIN32CALL_RETURN (
+ ACE_ADAPT_RETVAL (::LockFile (lock->handle_,
+ lock->overlapped_.Offset,
+ lock->overlapped_.OffsetHigh,
+ low_len,
+ high_len),
+ ace_result_), int, -1);
+# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
+#else
+ lock->lock_.l_whence = whence;
+ lock->lock_.l_start = start;
+ lock->lock_.l_len = len;
+ lock->lock_.l_type = F_RDLCK; // set read lock
+ // block, if no access
+ ACE_OSCALL_RETURN (ACE_OS::fcntl (lock->handle_, F_SETLKW,
+ reinterpret_cast<long> (&lock->lock_)),
+ int, -1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_OS::flock_tryrdlock (ACE_OS::ace_flock_t *lock,
+ short whence,
+ ACE_OFF_T start,
+ ACE_OFF_T len)
+{
+ ACE_OS_TRACE ("ACE_OS::ace_flock_tryrdlock");
+#if defined (ACE_LACKS_FILELOCKS)
+ ACE_UNUSED_ARG (lock);
+ ACE_UNUSED_ARG (whence);
+ ACE_UNUSED_ARG (start);
+ ACE_UNUSED_ARG (len);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)
+ ACE_OS::flock_adjust_params (lock, whence, start, len);
+ DWORD low_len = ACE_LOW_PART (len);
+ DWORD high_len = ACE_HIGH_PART (len);
+ ACE_WIN32CALL_RETURN (
+ ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_,
+ LOCKFILE_FAIL_IMMEDIATELY,
+ 0,
+ low_len,
+ high_len,
+ &lock->overlapped_),
+ ace_result_), int, -1);
+# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
+ ACE_UNUSED_ARG (lock);
+ ACE_UNUSED_ARG (whence);
+ ACE_UNUSED_ARG (start);
+ ACE_UNUSED_ARG (len);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
+#else
+ lock->lock_.l_whence = whence;
+ lock->lock_.l_start = start;
+ lock->lock_.l_len = len;
+ lock->lock_.l_type = F_RDLCK; // set read lock
+
+ int result = 0;
+ // Does not block, if no access, returns -1 and set errno = EBUSY;
+ ACE_OSCALL (ACE_OS::fcntl (lock->handle_, F_SETLK,
+ reinterpret_cast<long> (&lock->lock_)),
+ int, -1, result);
+
+ if (result == -1 && (errno == EACCES || errno == EAGAIN))
+ errno = EBUSY;
+
+ return result;
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_OS::flock_trywrlock (ACE_OS::ace_flock_t *lock,
+ short whence,
+ ACE_OFF_T start,
+ ACE_OFF_T len)
+{
+ ACE_OS_TRACE ("ACE_OS::ace_flock_trywrlock");
+#if defined (ACE_LACKS_FILELOCKS)
+ ACE_UNUSED_ARG (lock);
+ ACE_UNUSED_ARG (whence);
+ ACE_UNUSED_ARG (start);
+ ACE_UNUSED_ARG (len);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)
+ ACE_OS::flock_adjust_params (lock, whence, start, len);
+ DWORD low_len = ACE_LOW_PART (len);
+ DWORD high_len = ACE_HIGH_PART (len);
+ ACE_WIN32CALL_RETURN (
+ ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_,
+ LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK,
+ 0,
+ low_len,
+ high_len,
+ &lock->overlapped_),
+ ace_result_), int, -1);
+# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
+ ACE_UNUSED_ARG (lock);
+ ACE_UNUSED_ARG (whence);
+ ACE_UNUSED_ARG (start);
+ ACE_UNUSED_ARG (len);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
+#else
+ lock->lock_.l_whence = whence;
+ lock->lock_.l_start = start;
+ lock->lock_.l_len = len;
+ lock->lock_.l_type = F_WRLCK; // set write lock
+
+ int result = 0;
+ // Does not block, if no access, returns -1 and set errno = EBUSY;
+ ACE_OSCALL (ACE_OS::fcntl (lock->handle_,
+ F_SETLK,
+ reinterpret_cast<long> (&lock->lock_)),
+ int, -1, result);
+
+ if (result == -1 && (errno == EACCES || errno == EAGAIN))
+ errno = EBUSY;
+
+ return result;
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_OS::flock_wrlock (ACE_OS::ace_flock_t *lock,
+ short whence,
+ ACE_OFF_T start,
+ ACE_OFF_T len)
+{
+ ACE_OS_TRACE ("ACE_OS::flock_wrlock");
+#if defined (ACE_LACKS_FILELOCKS)
+ ACE_UNUSED_ARG (lock);
+ ACE_UNUSED_ARG (whence);
+ ACE_UNUSED_ARG (start);
+ ACE_UNUSED_ARG (len);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+ ACE_OS::flock_adjust_params (lock, whence, start, len);
+ DWORD low_len = ACE_LOW_PART (len);
+ DWORD high_len = ACE_HIGH_PART (len);
+# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)
+ ACE_WIN32CALL_RETURN (
+ ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_,
+ LOCKFILE_EXCLUSIVE_LOCK,
+ 0,
+ low_len,
+ high_len,
+ &lock->overlapped_),
+ ace_result_), int, -1);
+# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
+ ACE_WIN32CALL_RETURN (
+ ACE_ADAPT_RETVAL (::LockFile (lock->handle_,
+ lock->overlapped_.Offset,
+ lock->overlapped_.OffsetHigh,
+ low_len,
+ high_len),
+ ace_result_), int, -1);
+# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
+#else
+ lock->lock_.l_whence = whence;
+ lock->lock_.l_start = start;
+ lock->lock_.l_len = len;
+ lock->lock_.l_type = F_WRLCK; // set write lock
+ // block, if no access
+ ACE_OSCALL_RETURN (ACE_OS::fcntl (lock->handle_, F_SETLKW,
+ reinterpret_cast<long> (&lock->lock_)),
+ int, -1);
+#endif /* ACE_WIN32 */
+}
+
+#if !defined (ACE_LACKS_CLEARERR)
+ACE_INLINE void
+ACE_OS::clearerr (FILE* fp)
+{
+ ace_clearerr_helper (fp);
+}
+#endif /* !ACE_LACKS_CLEARERR */
+
+#if !defined (ACE_LACKS_CUSERID)
+ACE_INLINE char *
+ACE_OS::cuserid (char *user, size_t maxlen)
+{
+ ACE_OS_TRACE ("ACE_OS::cuserid");
+#if defined (ACE_VXWORKS)
+ ACE_UNUSED_ARG (maxlen);
+ if (user == 0)
+ {
+ // Require that the user field be non-null, i.e., don't
+ // allocate or use static storage.
+ ACE_NOTSUP_RETURN (0);
+ }
+ else
+ {
+ ::remCurIdGet (user, 0);
+ return user;
+ }
+#elif defined (__QNXNTO__) || defined (ACE_HAS_PHARLAP) || defined (ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (user);
+ ACE_UNUSED_ARG (maxlen);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_WIN32)
+ BOOL result = GetUserNameA (user, (u_long *) &maxlen);
+ if (result == FALSE)
+ ACE_FAIL_RETURN (0);
+ else
+ return user;
+#elif defined (ACE_HAS_ALT_CUSERID)
+# if defined (ACE_LACKS_PWD_FUNCTIONS)
+# error Cannot use alternate cuserid() without POSIX password functions!
+# endif /* ACE_LACKS_PWD_FUNCTIONS */
+
+ // POSIX.1 dropped the cuserid() function.
+ // GNU GLIBC and other platforms correctly deprecate the cuserid()
+ // function.
+
+ if (maxlen == 0)
+ {
+ // It doesn't make sense to have a zero length user ID.
+ errno = EINVAL;
+ return 0;
+ }
+
+ struct passwd *pw = 0;
+
+ // Make sure the file pointer is at the beginning of the password file
+ ACE_OS::setpwent ();
+ // Should use ACE_OS::setpwent() but I didn't want to move this
+ // method after it.
+
+ // Use the effective user ID to determine the user name.
+ pw = ::getpwuid (ACE_OS::geteuid ());
+
+ // Make sure the password file is closed.
+ ACE_OS::endpwent ();
+
+ if (pw == 0)
+ {
+ errno = ENOENT;
+ return 0;
+ }
+
+ size_t max_length = 0;
+ char *userid = 0;
+
+ if (user == 0)
+ {
+ // Not reentrant/thread-safe, but nothing else can be done if a
+ // zero pointer was passed in as the destination.
+
+#if defined (_POSIX_SOURCE) && defined (L_cuserid)
+ const size_t ACE_L_cuserid = L_cuserid;
+#else
+ const size_t ACE_L_cuserid = 9; // 8 character user ID + NULL
+#endif /* _POSIX_SOURCE */
+
+ static char tmp[ACE_L_cuserid] = { '\0' };
+ max_length = ACE_L_cuserid - 1; // Do not include NULL in length
+
+ userid = tmp;
+ }
+ else
+ {
+ max_length = maxlen;
+ userid = user;
+ }
+
+ // Extract the user name from the passwd structure.
+ if (ACE_OS::strlen (pw->pw_name) <= max_length)
+ {
+ return ACE_OS::strcpy (userid, pw->pw_name);
+ }
+ else
+ {
+ errno = ENOSPC; // Buffer is not large enough.
+ return 0;
+ }
+#else
+ // Hackish because of missing buffer size!
+ ACE_UNUSED_ARG (maxlen);
+ ACE_OSCALL_RETURN (::ace_cuserid(user), char*, 0);
+#endif /* ACE_VXWORKS */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::cuserid (wchar_t *user, size_t maxlen)
+{
+# if defined (ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (user);
+ ACE_UNUSED_ARG (maxlen);
+ ACE_NOTSUP_RETURN (0);
+# elif defined (ACE_WIN32)
+ BOOL result = GetUserNameW (user, (u_long *) &maxlen);
+ if (result == FALSE)
+ ACE_FAIL_RETURN (0);
+ else
+ return user;
+# else /* ACE_WIN32 */
+ char *char_user;
+ wchar_t *result = 0;
+
+ ACE_NEW_RETURN (char_user, char[maxlen + 1], 0);
+
+ if (ACE_OS::cuserid (char_user, maxlen))
+ {
+ ACE_OS::strcpy (user, ACE_Ascii_To_Wide (char_user).wchar_rep ());
+ result = user;
+ }
+
+ delete [] char_user;
+
+ return result;
+# endif /* ACE_WIN32 */
+}
+#endif /* ACE_HAS_WCHAR */
+#endif /* ACE_LACKS_CUSERID */
+
+ACE_INLINE int
+ACE_OS::fclose (FILE *fp)
+{
+ ACE_OS_TRACE ("ACE_OS::fclose");
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fclose (fp), int, -1);
+}
+
+ACE_INLINE FILE *
+ACE_OS::fdopen (ACE_HANDLE handle, const ACE_TCHAR *mode)
+{
+ ACE_OS_TRACE ("ACE_OS::fdopen");
+#if defined (ACE_HAS_WINCE)
+ ACE_OSCALL_RETURN (::_wfdopen (handle, ACE_TEXT_ALWAYS_WCHAR (mode)),
+ FILE*,
+ 0);
+#elif defined (ACE_WIN32)
+ // kernel file handle -> FILE* conversion...
+ // Options: _O_APPEND, _O_RDONLY and _O_TEXT are lost
+
+ FILE * file = 0;
+
+ int const crt_handle = ::_open_osfhandle (intptr_t (handle), 0);
+
+ if (crt_handle != -1)
+ {
+# if defined(ACE_HAS_NONCONST_FDOPEN) && !defined (ACE_USES_WCHAR)
+ file = ::_fdopen (crt_handle, const_cast<ACE_TCHAR *> (mode));
+# elif defined (ACE_HAS_NONCONST_FDOPEN) && defined (ACE_USES_WCHAR)
+ file = ::_wfdopen (crt_handle, const_cast<ACE_TCHAR *> (mode));
+# elif defined (ACE_USES_WCHAR)
+ file = ::_wfdopen (crt_handle, mode);
+# else
+ file = ::_fdopen (crt_handle, mode);
+# endif /* __BORLANDC__ */
+
+ if (!file)
+ {
+# if defined(__BORLANDC__)
+ ::_rtl_close (crt_handle);
+# else
+ ::_close (crt_handle);
+# endif /* defined(__BORLANDC__) */
+ }
+ }
+
+ return file;
+#elif defined (ACE_LACKS_FDOPEN)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (mode);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN
+ (::fdopen (handle, ACE_TEXT_ALWAYS_CHAR (mode)), FILE *, 0);
+#endif /* ACE_HAS_WINCE */
+}
+
+ACE_INLINE int
+ACE_OS::fflush (FILE *fp)
+{
+ ACE_OS_TRACE ("ACE_OS::fflush");
+#if defined (ACE_VXWORKS)
+ if (fp == 0)
+ {
+ // Do not allow fflush(0) on VxWorks
+ return 0;
+ }
+#endif /* ACE_VXWORKS */
+
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fflush (fp), int, -1);
+}
+
+ACE_INLINE int
+ACE_OS::fgetc (FILE* fp)
+{
+ return ace_fgetc_helper (fp);
+}
+
+ACE_INLINE int
+ACE_OS::getc (FILE* fp)
+{
+ return ace_getc_helper (fp);
+}
+
+ACE_INLINE int
+ACE_OS::fgetpos (FILE* fp, fpos_t* pos)
+{
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fgetpos (fp, pos), int, -1);
+}
+
+ACE_INLINE char *
+ACE_OS::fgets (char *buf, int size, FILE *fp)
+{
+ ACE_OS_TRACE ("ACE_OS::fgets");
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fgets (buf, size, fp), char *, 0);
+}
+
+#if defined (ACE_HAS_WCHAR) && !defined(ACE_LACKS_FGETWS)
+ACE_INLINE wchar_t *
+ACE_OS::fgets (wchar_t *buf, int size, FILE *fp)
+{
+ ACE_OS_TRACE ("ACE_OS::fgets");
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fgetws (buf, size, fp), wchar_t *, 0);
+}
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_FGETWS */
+
+#if !(defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+// Win32 PC implementation of fopen () is in OS_NS_stdio.cpp.
+ACE_INLINE FILE *
+ACE_OS::fopen (const char *filename, const ACE_TCHAR *mode)
+{
+ ACE_OS_TRACE ("ACE_OS::fopen");
+ ACE_OSCALL_RETURN
+ (::fopen (filename, ACE_TEXT_ALWAYS_CHAR (mode)), FILE *, 0);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE FILE *
+ACE_OS::fopen (const wchar_t *filename, const ACE_TCHAR *mode)
+{
+ ACE_OS_TRACE ("ACE_OS::fopen");
+#if defined (ACE_HAS_WINCE)
+ ACE_OSCALL_RETURN
+ (::_wfopen (filename, ACE_TEXT_ALWAYS_WCHAR (mode)), FILE *, 0);
+#else
+ // Non-Windows doesn't use wchar_t file systems.
+ ACE_Wide_To_Ascii n_filename (filename);
+ ACE_OSCALL_RETURN
+ (::fopen (n_filename.char_rep (), ACE_TEXT_ALWAYS_CHAR (mode)), FILE*, 0);
+#endif /* ACE_HAS_WINCE */
+}
+#endif /* ACE_HAS_WCHAR */
+
+#endif /* ACE_WIN32 */
+
+ACE_INLINE int
+ACE_OS::ungetc (int c, FILE *fp)
+{
+ return ace_ungetc_helper (c, fp);
+}
+
+ACE_INLINE int
+ACE_OS::fputc (int c, FILE *fp)
+{
+ return ace_fputc_helper (c, fp);
+}
+
+ACE_INLINE int
+ACE_OS::putc (int c, FILE *fp)
+{
+ return ace_putc_helper (c, fp);
+}
+
+ACE_INLINE int
+ACE_OS::fputs (const char *s, FILE *stream)
+{
+ ACE_OS_TRACE ("ACE_OS::fputs");
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fputs (s, stream), int, -1);
+}
+
+#if defined (ACE_HAS_WCHAR) && !defined(ACE_LACKS_FPUTWS)
+ACE_INLINE int
+ACE_OS::fputs (const wchar_t *s, FILE *stream)
+{
+ ACE_OS_TRACE ("ACE_OS::fputs");
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fputws (s, stream), int, -1);
+}
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_FPUTWS */
+
+ACE_INLINE size_t
+ACE_OS::fread (void *ptr, size_t size, size_t nelems, FILE *fp)
+{
+ ACE_OS_TRACE ("ACE_OS::fread");
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fread (ptr, size, nelems, fp),
+ size_t,
+ 0);
+}
+
+ACE_INLINE FILE *
+ACE_OS::freopen (const ACE_TCHAR *filename, const ACE_TCHAR *mode, FILE* stream)
+{
+ ACE_OS_TRACE ("ACE_OS::freopen");
+#if defined (ACE_WIN32) && (defined(ACE_USES_WCHAR) || defined(ACE_HAS_WINCE))
+ ACE_OSCALL_RETURN (::_wfreopen (ACE_TEXT_ALWAYS_WCHAR (filename),
+ ACE_TEXT_ALWAYS_WCHAR (mode),
+ stream),
+ FILE *, 0);
+#else
+ ACE_OSCALL_RETURN
+ (ACE_STD_NAMESPACE::freopen (ACE_TEXT_ALWAYS_CHAR (filename),
+ ACE_TEXT_ALWAYS_CHAR (mode),
+ stream),
+ FILE *, 0);
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+}
+
+ACE_INLINE int
+ACE_OS::fseek (FILE *fp, long offset, int whence)
+{
+# if defined (ACE_WIN32)
+# if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END
+ //#error Windows NT is evil AND rude!
+ switch (whence)
+ {
+ case SEEK_SET:
+ whence = FILE_BEGIN;
+ break;
+ case SEEK_CUR:
+ whence = FILE_CURRENT;
+ break;
+ case SEEK_END:
+ whence = FILE_END;
+ break;
+ default:
+ errno = EINVAL;
+ return -1; // rather safe than sorry
+ }
+# endif /* SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END */
+# endif /* ACE_WIN32 */
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fseek (fp, offset, whence), int, -1);
+}
+
+ACE_INLINE int
+ACE_OS::fsetpos (FILE* fp, fpos_t* pos)
+{
+ ACE_OSCALL_RETURN (::fsetpos (fp, pos), int, -1);
+}
+
+ACE_INLINE long
+ACE_OS::ftell (FILE* fp)
+{
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::ftell (fp), long, -1);
+}
+
+ACE_INLINE size_t
+ACE_OS::fwrite (const void *ptr, size_t size, size_t nitems, FILE *fp)
+{
+ ACE_OS_TRACE ("ACE_OS::fwrite");
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fwrite (ptr, size, nitems, fp),
+ size_t,
+ 0);
+}
+
+ACE_INLINE void
+ACE_OS::perror (const char *s)
+{
+ ACE_OS_TRACE ("ACE_OS::perror");
+#if defined (ACE_LACKS_PERROR)
+ ACE_UNUSED_ARG (s);
+#else
+ ::perror (s);
+#endif /* ACE_HAS_WINCE */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE void
+ACE_OS::perror (const wchar_t *s)
+{
+ ACE_OS_TRACE ("ACE_OS::perror");
+#if defined (ACE_LACKS_PERROR)
+ ACE_UNUSED_ARG (s);
+#elif defined (ACE_WIN32)
+ ::_wperror (s);
+#else
+ ACE_Wide_To_Ascii n_s (s);
+ ::perror (n_s.char_rep ());
+#endif /* ACE_HAS_WINCE */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::puts (const char *s)
+{
+ ACE_OS_TRACE ("ACE_OS::puts");
+ ACE_OSCALL_RETURN (::puts (s), int, -1);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::puts (const wchar_t *s)
+{
+ ACE_OS_TRACE ("ACE_OS::puts");
+#if defined (ACE_WIN32)
+ ACE_OSCALL_RETURN (::_putws (s), int, -1);
+#else /* ACE_WIN32 */
+ // There's no putws()...
+ ACE_Wide_To_Ascii n_s (s);
+ ACE_OSCALL_RETURN (::puts (n_s.char_rep ()), int, -1);
+#endif /* ACE_WIN32 */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::rename (const char *old_name,
+ const char *new_name,
+ int flags)
+{
+# if defined (ACE_LACKS_RENAME)
+ ACE_UNUSED_ARG (old_name);
+ ACE_UNUSED_ARG (new_name);
+ ACE_UNUSED_ARG (flags);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_HAS_WINCE)
+ // Win CE is always wide-char.
+ ACE_UNUSED_ARG (flags);
+ if (0 != MoveFile (ACE_TEXT_CHAR_TO_TCHAR (old_name),
+ ACE_TEXT_CHAR_TO_TCHAR (new_name)))
+ ACE_FAIL_RETURN (-1);
+ return 0;
+# elif defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_MOVEFILEEX)
+ // NT4 (and up) provides a way to rename/move a file with similar semantics
+ // to what's usually done on UNIX - if there's an existing file with
+ // <new_name> it is removed before the file is renamed/moved. The
+ // MOVEFILE_COPY_ALLOWED is specified to allow such a rename across drives.
+ if (flags == -1)
+ flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
+ if (::MoveFileExA (old_name, new_name, flags) == 0)
+ ACE_FAIL_RETURN (-1);
+ return 0;
+# else /* ACE_LACKS_RENAME */
+ ACE_UNUSED_ARG (flags);
+ ACE_OSCALL_RETURN (::rename (old_name, new_name), int, -1);
+# endif /* ACE_LACKS_RENAME */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::rename (const wchar_t *old_name,
+ const wchar_t *new_name,
+ int flags)
+{
+# if defined (ACE_LACKS_RENAME)
+ ACE_UNUSED_ARG (old_name);
+ ACE_UNUSED_ARG (new_name);
+ ACE_UNUSED_ARG (flags);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (flags);
+ if (MoveFileW (old_name, new_name) != 0)
+ ACE_FAIL_RETURN (-1);
+ return 0;
+# elif defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_MOVEFILEEX)
+ // NT4 (and up) provides a way to rename/move a file with similar semantics
+ // to what's usually done on UNIX - if there's an existing file with
+ // <new_name> it is removed before the file is renamed/moved. The
+ // MOVEFILE_COPY_ALLOWED is specified to allow such a rename across drives.
+ if (flags == -1)
+ flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
+ if (::MoveFileExW (old_name, new_name, flags) == 0)
+ ACE_FAIL_RETURN (-1);
+ return 0;
+# elif defined (ACE_WIN32)
+ ACE_UNUSED_ARG (flags);
+ ACE_OSCALL_RETURN (::_wrename (old_name, new_name), int, -1);
+# else /* ACE_LACKS_RENAME */
+ ACE_Wide_To_Ascii nold_name (old_name);
+ ACE_Wide_To_Ascii nnew_name (new_name);
+ return ACE_OS::rename (nold_name.char_rep (), nnew_name.char_rep (), flags);
+# endif /* ACE_LACKS_RENAME */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE void
+ACE_OS::rewind (FILE *fp)
+{
+#if !defined (ACE_HAS_WINCE)
+ ACE_OS_TRACE ("ACE_OS::rewind");
+ ::rewind (fp);
+#else
+ // This isn't perfect since it doesn't reset EOF, but it's probably
+ // the closest we can get on WINCE.
+ (void) fseek (fp, 0L, SEEK_SET);
+#endif /* ACE_HAS_WINCE */
+}
+
+ACE_INLINE char *
+ACE_OS::tempnam (const char *dir, const char *pfx)
+{
+ ACE_OS_TRACE ("ACE_OS::tempnam");
+#if defined (ACE_LACKS_TEMPNAM)
+ ACE_UNUSED_ARG (dir);
+ ACE_UNUSED_ARG (pfx);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_HAS_NONCONST_TEMPNAM)
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::tempnam (const_cast <char *> (dir), const_cast<char *> (pfx)), char *, 0);
+#else /* ACE_LACKS_TEMPNAM */
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::tempnam (dir, pfx), char *, 0);
+#endif /* ACE_LACKS_TEMPNAM */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::tempnam (const wchar_t *dir, const wchar_t *pfx)
+{
+ ACE_OS_TRACE ("ACE_OS::tempnam");
+#if defined (ACE_LACKS_TEMPNAM)
+ ACE_UNUSED_ARG (dir);
+ ACE_UNUSED_ARG (pfx);
+ ACE_NOTSUP_RETURN (0);
+#elif defined(ACE_WIN32)
+# if defined (ACE_HAS_NONCONST_TEMPNAM)
+ ACE_OSCALL_RETURN (::_wtempnam (const_cast <wchar_t*> (dir), const_cast <wchar_t*> (pfx)), wchar_t *, 0);
+# else
+ ACE_OSCALL_RETURN (::_wtempnam (dir, pfx), wchar_t *, 0);
+# endif /* __BORLANDC__ */
+#else /* ACE_LACKS_TEMPNAM */
+ // No native wide-char support; convert to narrow and call the char* variant.
+ char *ndir = ACE_Wide_To_Ascii (dir).char_rep ();
+ char *npfx = ACE_Wide_To_Ascii (pfx).char_rep ();
+ char *name = ACE_OS::tempnam (ndir, npfx);
+ // ACE_OS::tempnam returns a pointer to a malloc()-allocated space.
+ // Convert that string to wide-char and free() the original.
+ wchar_t *wname = 0;
+ if (name != 0)
+ {
+ size_t namelen = ACE_OS::strlen (name) + 1;
+ wname = reinterpret_cast<wchar_t *>
+ (ACE_OS::malloc (namelen * sizeof (wchar_t)));
+ if (wname != 0)
+ ACE_OS::strcpy (wname, ACE_Ascii_To_Wide (name).wchar_rep ());
+ ACE_OS::free (name);
+ }
+ return wname;
+#endif /* ACE_LACKS_TEMPNAM */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::vasprintf (char **bufp, const char* format, va_list argptr)
+{
+#if defined (ACE_HAS_VASPRINTF)
+ return ::vasprintf (bufp, format, argptr);
+#else
+ return ACE_OS::vasprintf_emulation (bufp, format, argptr);
+#endif /* ACE_HAS_VASPRINTF */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::vasprintf (wchar_t **bufp, const wchar_t* format, va_list argptr)
+{
+#if defined (ACE_HAS_VASWPRINTF)
+ return ::vaswprintf (bufp, format, argptr);
+#else
+ return ACE_OS::vaswprintf_emulation (bufp, format, argptr);
+#endif /* ACE_HAS_VASWPRINTF */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::vprintf (const char *format, va_list argptr)
+{
+ return ::vprintf (format, argptr);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::vprintf (const wchar_t *format, va_list argptr)
+{
+#if defined (ACE_HAS_VWPRINTF)
+ return ::vwprintf (format, argptr);
+#else
+ ACE_UNUSED_ARG (format);
+ ACE_UNUSED_ARG (argptr);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_VWPRINTF */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::vfprintf (FILE *fp, const char *format, va_list argptr)
+{
+ return ACE_STD_NAMESPACE::vfprintf (fp, format, argptr);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::vfprintf (FILE *fp, const wchar_t *format, va_list argptr)
+{
+#if defined (ACE_HAS_VFWPRINTF)
+ return ::vfwprintf (fp, format, argptr);
+#else
+ ACE_UNUSED_ARG (fp);
+ ACE_UNUSED_ARG (format);
+ ACE_UNUSED_ARG (argptr);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_VFWPRINTF */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::vsprintf (char *buffer, const char *format, va_list argptr)
+{
+ return ::vsprintf (buffer, format, argptr);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::vsprintf (wchar_t *buffer, const wchar_t *format, va_list argptr)
+{
+# if (defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 500) || \
+ (defined (sun) && !(defined(_XOPEN_SOURCE) && (_XOPEN_VERSION-0==4))) || \
+ defined (ACE_HAS_DINKUM_STL) || defined (__DMC__) || \
+ defined (ACE_HAS_VSWPRINTF) || defined (ACE_WIN32_VC9) || \
+ (defined (ACE_WIN32_VC8) && !defined (ACE_HAS_WINCE) && \
+ _MSC_FULL_VER > 140050000)
+
+ // The XPG4/UNIX98/C99 signature of the wide-char sprintf has a
+ // maxlen argument. Since this method doesn't supply one, pass in
+ // a length that works (ULONG_MAX doesn't on all platform since some check
+ // to see if the operation will remain in bounds). If this isn't ok, use
+ // ACE_OS::snprintf().
+ return vswprintf (buffer, 4096, format, argptr);
+
+# elif defined (ACE_WIN32)
+ // Windows has vswprintf, but the pre-VC8 signature is from the older
+ // ISO C standard. Also see ACE_OS::snprintf() for more info on this.
+
+ return vswprintf (buffer, format, argptr);
+
+# else
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (format);
+ ACE_UNUSED_ARG (argptr);
+ ACE_NOTSUP_RETURN (-1);
+
+# endif /* XPG5 || ACE_HAS_DINKUM_STL */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::vsnprintf (char *buffer, size_t maxlen, const char *format, va_list ap)
+{
+#if !defined (ACE_LACKS_VSNPRINTF)
+ int result;
+# if 0 /* defined (ACE_HAS_TR24731_2005_CRT) */
+ // _vsnprintf_s() doesn't report the length needed when it truncates. This
+ // info is needed and relied on by others things in ACE+TAO, so don't use
+ // this. There's adequate protection via the maxlen.
+ result = _vsnprintf_s (buffer, maxlen, _TRUNCATE, format, ap);
+# elif !defined (ACE_WIN32)
+ result = ::vsnprintf (buffer, maxlen, format, ap);
+# else
+ result = ::_vsnprintf (buffer, maxlen, format, ap);
+
+ // Win32 doesn't regard a full buffer with no 0-terminate as an overrun.
+ if (result == static_cast<int> (maxlen))
+ buffer[maxlen-1] = '\0';
+
+ // Win32 doesn't 0-terminate the string if it overruns maxlen.
+ if (result == -1)
+ buffer[maxlen-1] = '\0';
+# endif
+ // In out-of-range conditions, C99 defines vsnprintf() to return the number
+ // of characters that would have been written if enough space was available.
+ // Earlier variants of the vsnprintf() (e.g. UNIX98) defined it to return
+ // -1. This method follows the C99 standard, but needs to guess at the
+ // value; uses maxlen + 1.
+ if (result == -1)
+ {
+ result = static_cast <int> (maxlen + 1);
+ }
+
+ return result;
+#elif defined (ACE_HAS_TRIO)
+ return trio_vsnprintf (buffer, maxlen, format, ap);
+#else
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (maxlen);
+ ACE_UNUSED_ARG (format);
+ ACE_UNUSED_ARG (ap);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_LACKS_VSNPRINTF */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::vsnprintf (wchar_t *buffer, size_t maxlen, const wchar_t *format, va_list ap)
+{
+# if (defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 500) || \
+ (defined (sun) && !(defined(_XOPEN_SOURCE) && (_XOPEN_VERSION-0==4))) || \
+ (defined (ACE_HAS_DINKUM_STL) || defined (__DMC__)) || \
+ defined (ACE_HAS_VSWPRINTF) || \
+ defined (ACE_WIN32)
+
+ int result;
+
+# if defined (ACE_WIN32)
+ // Microsoft's vswprintf() doesn't have the maxlen argument that
+ // XPG4/UNIX98 define. They do, however, recommend use of _vsnwprintf()
+ // as a substitute, which does have the same signature as the UNIX98 one.
+ result = ::_vsnwprintf (buffer, maxlen, format, ap);
+
+ // Win32 doesn't regard a full buffer with no 0-terminate as an overrun.
+ if (result == static_cast<int> (maxlen))
+ buffer[maxlen-1] = '\0';
+
+ // Win32 doesn't 0-terminate the string if it overruns maxlen.
+ if (result == -1)
+ buffer[maxlen-1] = '\0';
+# else
+ result = vswprintf (buffer, maxlen, format, ap);
+#endif
+
+ // In out-of-range conditions, C99 defines vsnprintf() to return the number
+ // of characters that would have been written if enough space was available.
+ // Earlier variants of the vsnprintf() (e.g. UNIX98) defined it to return
+ // -1. This method follows the C99 standard, but needs to guess at the
+ // value; uses maxlen + 1.
+ if (result == -1)
+ {
+ result = static_cast <int> (maxlen + 1);
+ }
+
+ return result;
+
+# else
+
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (maxlen);
+ ACE_UNUSED_ARG (format);
+ ACE_UNUSED_ARG (ap);
+ ACE_NOTSUP_RETURN (-1);
+
+# endif /* platforms with a variant of vswprintf */
+}
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+#if defined (ACE_WIN32)
+ACE_INLINE const ACE_TEXT_OSVERSIONINFO &
+ACE_OS::get_win32_versioninfo ()
+{
+ return ACE_OS::win32_versioninfo_;
+}
+
+ACE_INLINE HINSTANCE
+ACE_OS::get_win32_resource_module ()
+{
+ return ACE_OS::win32_resource_module_;
+}
+
+ACE_INLINE void
+ACE_OS::set_win32_resource_module (HINSTANCE instance)
+{
+ ACE_OS::win32_resource_module_ = instance;
+}
+
+ACE_INLINE LPSECURITY_ATTRIBUTES
+ACE_OS::default_win32_security_attributes (LPSECURITY_ATTRIBUTES sa)
+{
+#if defined (ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES)
+ if (sa == 0)
+ {
+ // @@ This is a good place to use pthread_once.
+ static SECURITY_ATTRIBUTES default_sa;
+ static SECURITY_DESCRIPTOR sd;
+ InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE);
+ default_sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ default_sa.lpSecurityDescriptor = &sd;
+ default_sa.bInheritHandle = TRUE;
+ sa = &default_sa;
+ }
+ return sa;
+#else /* !ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES */
+ return sa;
+#endif /* ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES */
+}
+
+ACE_INLINE LPSECURITY_ATTRIBUTES
+ACE_OS::default_win32_security_attributes_r (LPSECURITY_ATTRIBUTES sa,
+ LPSECURITY_ATTRIBUTES sa_buffer,
+ SECURITY_DESCRIPTOR* sd_buffer)
+{
+#if defined (ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES)
+ if (sa == 0)
+ {
+ if (sa_buffer != 0 && sd_buffer != 0)
+ {
+ InitializeSecurityDescriptor
+ (sd_buffer, SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl (sd_buffer, TRUE, 0, FALSE);
+ sa_buffer->nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa_buffer->lpSecurityDescriptor = sd_buffer;
+ sa_buffer->bInheritHandle = TRUE;
+ sa = sa_buffer;
+ }
+ }
+ return sa;
+#else /* !ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES */
+ ACE_UNUSED_ARG(sa_buffer);
+ ACE_UNUSED_ARG(sd_buffer);
+ return sa;
+#endif /* ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES */
+}
+
+#endif /* ACE_WIN32 */
+#endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_stdlib.cpp b/ACE/ace/OS_NS_stdlib.cpp
new file mode 100644
index 00000000000..a04086d8a2b
--- /dev/null
+++ b/ACE/ace/OS_NS_stdlib.cpp
@@ -0,0 +1,801 @@
+// $Id$
+
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID (ace,
+ OS_NS_stdlib,
+ "$Id$")
+
+#include "ace/Default_Constants.h"
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_stdlib.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include "ace/OS_Memory.h"
+
+#include "ace/OS_NS_unistd.h"
+
+#if defined (ACE_LACKS_MKTEMP) \
+ || defined (ACE_LACKS_MKSTEMP) \
+ || defined (ACE_LACKS_REALPATH)
+# include "ace/OS_NS_stdio.h"
+# include "ace/OS_NS_sys_stat.h"
+#endif /* ACE_LACKS_MKTEMP || ACE_LACKS_MKSTEMP || ACE_LACKS_REALPATH */
+
+#if defined (ACE_LACKS_MKSTEMP)
+# include "ace/OS_NS_fcntl.h"
+# include "ace/OS_NS_ctype.h"
+# include "ace/OS_NS_sys_time.h"
+# include "ace/OS_NS_Thread.h"
+# include "ace/Numeric_Limits.h"
+#endif /* ACE_LACKS_MKSTEMP */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_EXIT_HOOK ACE_OS::exit_hook_ = 0;
+
+void *
+ACE_OS::calloc (size_t elements, size_t sizeof_elements)
+{
+#if !defined (ACE_HAS_WINCE)
+ return ACE_CALLOC_FUNC (elements, sizeof_elements);
+#else
+ // @@ This will probably not work since it doesn't consider
+ // alignment properly.
+ return ACE_MALLOC_FUNC (elements * sizeof_elements);
+#endif /* ACE_HAS_WINCE */
+}
+
+void
+ACE_OS::exit (int status)
+{
+ ACE_OS_TRACE ("ACE_OS::exit");
+
+#if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_HAS_WINCE) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
+ // Shut down the ACE_Object_Manager, if it had registered its exit_hook.
+ // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is
+ // instantiated on the main's stack. ::exit () doesn't destroy it.
+ if (exit_hook_)
+ (*exit_hook_) ();
+#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */
+
+#if !defined (ACE_HAS_WINCE)
+# if defined (ACE_WIN32)
+ ::ExitProcess ((UINT) status);
+# else
+ ::exit (status);
+# endif /* ACE_WIN32 */
+#else
+ // @@ This is not exactly the same as ExitProcess. But this is the
+ // closest one I can get.
+ ::TerminateProcess (::GetCurrentProcess (), status);
+#endif /* ACE_HAS_WINCE */
+}
+
+void
+ACE_OS::free (void *ptr)
+{
+ ACE_FREE_FUNC (ACE_MALLOC_T (ptr));
+}
+
+// You may be asking yourself, why are we doing this? Well, in winbase.h,
+// MS didn't follow their normal Api_FunctionA and Api_FunctionW style,
+// so we have to #undef their define to get access to the unicode version.
+// And because we don't want to #undef this for the users code, we keep
+// this method in the .cpp file.
+#if defined (ACE_WIN32) && defined (UNICODE) && !defined (ACE_USES_TCHAR)
+#undef GetEnvironmentStrings
+#endif /* ACE_WIN32 && UNICODE !ACE_USES_TCHAR */
+
+ACE_TCHAR *
+ACE_OS::getenvstrings (void)
+{
+#if defined (ACE_LACKS_ENV)
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ return ::GetEnvironmentStringsW ();
+# else /* ACE_USES_WCHAR */
+ return ::GetEnvironmentStrings ();
+# endif /* ACE_USES_WCHAR */
+#else /* ACE_WIN32 */
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_WIN32 */
+}
+
+// Return a dynamically allocated duplicate of <str>, substituting the
+// environment variables of form $VAR_NAME. Note that the pointer is
+// allocated with <ACE_OS::malloc> and must be freed by
+// <ACE_OS::free>.
+
+ACE_TCHAR *
+ACE_OS::strenvdup (const ACE_TCHAR *str)
+{
+#if defined (ACE_HAS_WINCE)
+ // WinCE doesn't have environment variables so we just skip it.
+ return ACE_OS::strdup (str);
+#elif defined (ACE_LACKS_ENV)
+ ACE_UNUSED_ARG (str);
+ ACE_NOTSUP_RETURN (0);
+#else
+ const ACE_TCHAR * start = 0;
+ if ((start = ACE_OS::strchr (str, ACE_TEXT ('$'))) != 0)
+ {
+ ACE_TCHAR buf[ACE_DEFAULT_ARGV_BUFSIZ];
+ size_t var_len = ACE_OS::strcspn (&start[1],
+ ACE_TEXT ("$~!#%^&*()-+=\\|/?,.;:'\"`[]{} \t\n\r"));
+ ACE_OS::strncpy (buf, &start[1], var_len);
+ buf[var_len++] = ACE_TEXT ('\0');
+# if defined (ACE_WIN32)
+ // Always use the ACE_TCHAR for Windows.
+ ACE_TCHAR *temp = ACE_OS::getenv (buf);
+# else
+ // Use char * for environment on non-Windows.
+ char *temp = ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (buf));
+# endif /* ACE_WIN32 */
+ size_t buf_len = ACE_OS::strlen (str) + 1;
+ if (temp != 0)
+ buf_len += ACE_OS::strlen (temp) - var_len;
+ ACE_TCHAR * buf_p = buf;
+ if (buf_len > ACE_DEFAULT_ARGV_BUFSIZ)
+ {
+ buf_p =
+ (ACE_TCHAR *) ACE_OS::malloc (buf_len * sizeof (ACE_TCHAR));
+ if (buf_p == 0)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+ }
+ ACE_TCHAR * p = buf_p;
+ size_t len = start - str;
+ ACE_OS::strncpy (p, str, len);
+ p += len;
+ if (temp != 0)
+ {
+# if defined (ACE_WIN32)
+ p = ACE_OS::strecpy (p, temp) - 1;
+# else
+ p = ACE_OS::strecpy (p, ACE_TEXT_CHAR_TO_TCHAR (temp)) - 1;
+# endif /* ACE_WIN32 */
+ }
+ else
+ {
+ ACE_OS::strncpy (p, start, var_len);
+ p += var_len;
+ *p = ACE_TEXT ('\0');
+ }
+ ACE_OS::strcpy (p, &start[var_len]);
+ return (buf_p == buf) ? ACE_OS::strdup (buf) : buf_p;
+ }
+ else
+ return ACE_OS::strdup (str);
+#endif /* ACE_HAS_WINCE */
+}
+
+#if !defined (ACE_HAS_ITOA)
+char *
+ACE_OS::itoa_emulation (int value, char *string, int radix)
+{
+ char *e = string;
+ char *b = string;
+
+ // Short circuit if 0
+
+ if (value == 0)
+ {
+ string[0] = '0';
+ string[1] = 0;
+ return string;
+ }
+
+ // If negative and base 10, print a - and then do the
+ // number.
+
+ if (value < 0 && radix == 10)
+ {
+ string[0] = '-';
+ ++b;
+ ++e; // Don't overwrite the negative sign.
+ value = -value; // Drop negative sign so character selection is correct.
+ }
+
+ // Convert to base <radix>, but in reverse order
+
+ while (value != 0)
+ {
+ int mod = value % radix;
+ value = value / radix;
+
+ *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10;
+ }
+
+ *e-- = 0;
+
+ // Now reverse the string to get the correct result
+
+ while (e > b)
+ {
+ char temp = *e;
+ *e = *b;
+ *b = temp;
+ ++b;
+ --e;
+ }
+
+ return string;
+}
+#endif /* !ACE_HAS_ITOA */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_ITOW)
+wchar_t *
+ACE_OS::itow_emulation (int value, wchar_t *string, int radix)
+{
+ wchar_t *e = string;
+ wchar_t *b = string;
+
+ // Short circuit if 0
+
+ if (value == 0)
+ {
+ string[0] = '0';
+ string[1] = 0;
+ return string;
+ }
+
+ // If negative and base 10, print a - and then do the
+ // number.
+
+ if (value < 0 && radix == 10)
+ {
+ string[0] = '-';
+ b++;
+ }
+
+ // Convert to base <radix>, but in reverse order
+
+ while (value != 0)
+ {
+ int mod = value % radix;
+ value = value / radix;
+
+ *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10;
+ }
+
+ *e-- = 0;
+
+ // Now reverse the string to get the correct result
+
+ while (e > b)
+ {
+ wchar_t temp = *e;
+ *e = *b;
+ *b = temp;
+ ++b;
+ --e;
+ }
+
+ return string;
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_ITOW */
+
+void *
+ACE_OS::malloc (size_t nbytes)
+{
+ return ACE_MALLOC_FUNC (nbytes);
+}
+
+#if defined (ACE_LACKS_MKTEMP)
+ACE_TCHAR *
+ACE_OS::mktemp (ACE_TCHAR *s)
+{
+ ACE_OS_TRACE ("ACE_OS::mktemp");
+ if (s == 0)
+ // check for null template string failed!
+ return 0;
+ else
+ {
+ ACE_TCHAR *xxxxxx = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
+
+ if (xxxxxx == 0)
+ // the template string doesn't contain "XXXXXX"!
+ return s;
+ else
+ {
+ ACE_TCHAR unique_letter = ACE_TEXT ('a');
+ ACE_stat sb;
+
+ // Find an unused filename for this process. It is assumed
+ // that the user will open the file immediately after
+ // getting this filename back (so, yes, there is a race
+ // condition if multiple threads in a process use the same
+ // template). This appears to match the behavior of the
+ // SunOS 5.5 mktemp().
+ ACE_OS::sprintf (xxxxxx,
+ ACE_TEXT ("%05d%c"),
+ ACE_OS::getpid (),
+ unique_letter);
+ while (ACE_OS::stat (s, &sb) >= 0)
+ {
+ if (++unique_letter <= ACE_TEXT ('z'))
+ ACE_OS::sprintf (xxxxxx,
+ ACE_TEXT ("%05d%c"),
+ ACE_OS::getpid (),
+ unique_letter);
+ else
+ {
+ // maximum of 26 unique files per template, per process
+ ACE_OS::sprintf (xxxxxx, ACE_TEXT ("%s"), ACE_TEXT (""));
+ return s;
+ }
+ }
+ }
+ return s;
+ }
+}
+#endif /* ACE_LACKS_MKTEMP */
+
+void *
+ACE_OS::realloc (void *ptr, size_t nbytes)
+{
+ return ACE_REALLOC_FUNC (ACE_MALLOC_T (ptr), nbytes);
+}
+
+#if defined (ACE_LACKS_REALPATH) && !defined (ACE_HAS_WINCE)
+char *
+ACE_OS::realpath (const char *file_name,
+ char *resolved_name)
+{
+ ACE_OS_TRACE ("ACE_OS::realpath");
+
+ if (file_name == 0)
+ {
+ // Single Unix Specification V3:
+ // Return an error if parameter is a null pointer.
+ errno = EINVAL;
+ return 0;
+ }
+
+ if (*file_name == '\0')
+ {
+ // Single Unix Specification V3:
+ // Return an error if the file_name argument points
+ // to an empty string.
+ errno = ENOENT;
+ return 0;
+ }
+
+ char* rpath;
+
+ if (resolved_name == 0)
+ {
+ // Single Unix Specification V3:
+ // Return an error if parameter is a null pointer.
+ //
+ // To match glibc realpath() and Win32 _fullpath() behavior,
+ // allocate room for the return value if resolved_name is
+ // a null pointer.
+ rpath = static_cast<char*>(ACE_OS::malloc (PATH_MAX));
+ if (rpath == 0)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+ }
+ else
+ {
+ rpath = resolved_name;
+ }
+
+ char* dest;
+
+ if (*file_name != '/')
+ {
+ // file_name is relative path so CWD needs to be added
+ if (ACE_OS::getcwd (rpath, PATH_MAX) == 0)
+ {
+ if (resolved_name == 0)
+ ACE_OS::free (rpath);
+ return 0;
+ }
+ dest = ACE_OS::strchr (rpath, '\0');
+ }
+ else
+ {
+ dest = rpath;
+ }
+
+#if !defined (ACE_LACKS_SYMLINKS)
+ char expand_buf[PATH_MAX]; // Extra buffer needed to expand symbolic links
+ int nlinks = 0;
+#endif
+
+ while (*file_name)
+ {
+ *dest++ = '/';
+
+ // Skip multiple separators
+ while (*file_name == '/')
+ ++file_name;
+
+ char* start = dest;
+
+ // Process one path component
+ while (*file_name && *file_name != '/')
+ {
+ *dest++ = *file_name++;
+ if (dest - rpath > PATH_MAX)
+ {
+ errno = ENAMETOOLONG;
+ if (resolved_name == 0)
+ ACE_OS::free (rpath);
+ return 0;
+ }
+ }
+
+ if (start == dest) // Are we done?
+ {
+ if (dest - rpath > 1)
+ --dest; // Remove trailing separator if not at root
+ break;
+ }
+ else if (dest - start == 1 && *start == '.')
+ {
+ dest -= 2; // Remove "./"
+ }
+ else if (dest - start == 2 && *start == '.' && *(start +1) == '.')
+ {
+ dest -= 3; // Remove "../"
+ if (dest > rpath) // Remove the last path component if not at root
+ while (*--dest != '/')
+ ;
+ }
+# if !defined (ACE_LACKS_SYMLINKS)
+ else
+ {
+ ACE_stat st;
+
+ *dest = '\0';
+ if (ACE_OS::lstat(rpath, &st) < 0)
+ {
+ if (resolved_name == 0)
+ ACE_OS::free (rpath);
+ return 0;
+ }
+
+ // Check if current path is a link
+ if (S_ISLNK (st.st_mode))
+ {
+ if (++nlinks > MAXSYMLINKS)
+ {
+ errno = ELOOP;
+ if (resolved_name == 0)
+ ACE_OS::free (rpath);
+ return 0;
+ }
+
+ char link_buf[PATH_MAX];
+
+ ssize_t link_len = ACE_OS::readlink (rpath, link_buf, PATH_MAX);
+ int tail_len = ACE_OS::strlen (file_name) + 1;
+
+ // Check if there is room to expand link?
+ if (link_len + tail_len > PATH_MAX)
+ {
+ errno = ENAMETOOLONG;
+ if (resolved_name == 0)
+ ACE_OS::free (rpath);
+ return 0;
+ }
+
+ // Move tail and prefix it with expanded link
+ ACE_OS::memmove (expand_buf + link_len, file_name, tail_len);
+ ACE_OS::memcpy (expand_buf, link_buf, link_len);
+
+ if (*link_buf == '/') // Absolute link?
+ {
+ dest = rpath;
+ }
+ else // Relative link, remove expanded link component
+ {
+ --dest;
+ while (*--dest != '/')
+ ;
+ }
+ file_name = expand_buf; // Source path is now in expand_buf
+ }
+ }
+# endif /* ACE_LACKS_SYMLINKS */
+ }
+
+ *dest = '\0';
+
+ return rpath;
+}
+#endif /* ACE_LACKS_REALPATH && !ACE_HAS_WINCE */
+
+#if defined (ACE_LACKS_STRTOL)
+long
+ACE_OS::strtol_emulation (const char *nptr, char **endptr, int base)
+{
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = any ? (char *)s - 1 : (char *)nptr;
+ return (acc);
+}
+#endif /* ACE_LACKS_STRTOL */
+
+#if defined (ACE_LACKS_STRTOUL)
+unsigned long
+ACE_OS::strtoul_emulation (const char *nptr,
+ char **endptr,
+ register int base)
+{
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do
+ c = *s++;
+ while (isspace(c));
+ if (c == '-')
+ {
+ neg = 1;
+ c = *s++;
+ }
+ else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X'))
+ {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long) ULONG_MAX / (unsigned long) base;
+ cutlim = (unsigned long) ULONG_MAX % (unsigned long) base;
+
+ for (acc = 0, any = 0;; c = *s++)
+ {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else
+ {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0)
+ {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = any ? (char *) s - 1 : (char *) nptr;
+ return (acc);
+}
+#endif /* ACE_LACKS_STRTOUL */
+
+
+#if defined (ACE_LACKS_MKSTEMP)
+ACE_HANDLE
+ACE_OS::mkstemp_emulation (ACE_TCHAR * s)
+{
+ if (s == 0)
+ {
+ errno = EINVAL;
+ return ACE_INVALID_HANDLE;
+ }
+
+ // The "XXXXXX" template to be filled in.
+ ACE_TCHAR * const t = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
+
+ if (t == 0)
+ {
+ errno = EINVAL;
+ return ACE_INVALID_HANDLE;
+ }
+
+ static unsigned int const NUM_RETRIES = 50;
+ static unsigned int const NUM_CHARS = 6; // Do not change!
+
+ // Use ACE_Time_Value::msec(ACE_UINT64&) as opposed to
+ // ACE_Time_Value::msec(void) to avoid truncation.
+ ACE_UINT64 msec;
+
+ // Use a const ACE_Time_Value to resolve ambiguity between
+ // ACE_Time_Value::msec (long) and ACE_Time_Value::msec(ACE_UINT64&) const.
+ ACE_Time_Value const now = ACE_OS::gettimeofday();
+ now.msec (msec);
+
+ // Add the process and thread ids to ensure uniqueness.
+ msec += ACE_OS::getpid();
+ msec += (size_t) ACE_OS::thr_self();
+
+ // ACE_thread_t may be a char* (returned by ACE_OS::thr_self()) so
+ // we need to use a C-style cast as a catch-all in order to use a
+ // static_cast<> to an integral type.
+ ACE_RANDR_TYPE seed = static_cast<ACE_RANDR_TYPE> (msec);
+
+ // We only care about UTF-8 / ASCII characters in generated
+ // filenames. A UTF-16 or UTF-32 character could potentially cause
+ // a very large space to be searched in the below do/while() loop,
+ // greatly slowing down this mkstemp() implementation. It is more
+ // practical to limit the search space to UTF-8 / ASCII characters
+ // (i.e. 127 characters).
+ //
+ // Note that we can't make this constant static since the compiler
+ // may not inline the return value of ACE_Numeric_Limits::max(),
+ // meaning multiple threads could potentially initialize this value
+ // in parallel.
+ float const MAX_VAL =
+ static_cast<float> (ACE_Numeric_Limits<char>::max ());
+
+ // Use high-order bits rather than low-order ones (e.g. rand() %
+ // MAX_VAL). See Numerical Recipes in C: The Art of Scientific
+ // Computing (William H. Press, Brian P. Flannery, Saul
+ // A. Teukolsky, William T. Vetterling; New York: Cambridge
+ // University Press, 1992 (2nd ed., p. 277).
+ //
+ // e.g.: MAX_VAL * rand() / (RAND_MAX + 1.0)
+
+ // Factor out the constant coefficient.
+ float const coefficient =
+ static_cast<float> (MAX_VAL / (RAND_MAX + 1.0f));
+
+ // @@ These nested loops may be ineffecient. Improvements are
+ // welcome.
+ for (unsigned int i = 0; i < NUM_RETRIES; ++i)
+ {
+ for (unsigned int n = 0; n < NUM_CHARS; ++n)
+ {
+ ACE_TCHAR r;
+
+ // This do/while() loop allows this alphanumeric character
+ // selection to work for EBCDIC, as well.
+ do
+ {
+ r = static_cast<ACE_TCHAR> (coefficient * ACE_OS::rand_r (seed));
+ }
+ while (!ACE_OS::ace_isalnum (r));
+
+ t[n] = r;
+ }
+
+ static int const perms =
+#if defined (ACE_WIN32)
+ 0; /* Do not share while open. */
+#else
+ 0600; /* S_IRUSR | S_IWUSR */
+#endif /* ACE_WIN32 */
+
+ // Create the file with the O_EXCL bit set to ensure that we're
+ // not subject to a symbolic link attack.
+ //
+ // Note that O_EXCL is subject to a race condition over NFS
+ // filesystems.
+ ACE_HANDLE const handle = ACE_OS::open (s,
+ O_RDWR | O_CREAT | O_EXCL,
+ perms);
+
+ if (handle != ACE_INVALID_HANDLE)
+ return handle;
+ }
+
+ errno = EEXIST; // Couldn't create a unique temporary file.
+ return ACE_INVALID_HANDLE;
+}
+#endif /* ACE_LACKS_MKSTEMP */
+
+#if !defined (ACE_HAS_GETPROGNAME) && !defined (ACE_HAS_SETPROGNAME)
+static const char *__progname = "";
+#endif /* !ACE_HAS_GETPROGNAME && !ACE_HAS_SETPROGNAME */
+
+#if !defined (ACE_HAS_GETPROGNAME)
+const char*
+ACE_OS::getprogname_emulation ()
+{
+ return __progname;
+}
+#endif /* !ACE_HAS_GETPROGNAME */
+
+#if !defined (ACE_HAS_SETPROGNAME)
+void
+ACE_OS::setprogname_emulation (const char* progname)
+{
+ const char *p = ACE_OS::strrchr (progname, '/');
+ if (p != 0)
+ __progname = p + 1;
+ else
+ __progname = progname;
+}
+#endif /* !ACE_HAS_SETPROGNAME */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_stdlib.h b/ACE/ace/OS_NS_stdlib.h
new file mode 100644
index 00000000000..28a0bbdf072
--- /dev/null
+++ b/ACE/ace/OS_NS_stdlib.h
@@ -0,0 +1,313 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_stdlib.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_STDLIB_H
+# define ACE_OS_NS_STDLIB_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/os_include/os_stdlib.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+# if defined (ACE_HAS_BROKEN_R_ROUTINES)
+# undef rand_r
+# endif /* ACE_HAS_BROKEN_R_ROUTINES */
+
+// We need this for MVS... as well as Linux, etc...
+// On Windows, we explicitly set this up as __cdecl so it's correct even
+// if building with another calling convention, such as __stdcall.
+#if defined (ACE_WIN32) && defined (_MSC_VER)
+extern "C" {
+ typedef int (__cdecl *ACE_COMPARE_FUNC)(const void *, const void *);
+}
+#else
+extern "C" {
+ typedef int (*ACE_COMPARE_FUNC)(const void *, const void *);
+}
+#endif /* ACE_WIN32 && _MSC_VER */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ /** @name Non-standard functions
+ *
+ * These functions aren't in the standard.
+ *
+ */
+ //@{
+
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void _exit (int status = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void abort (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int atexit (ACE_EXIT_HOOK func);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int atoi (const char *s);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int atoi (const wchar_t *s);
+# endif /* ACE_HAS_WCHAR */
+
+ // atop not in spec
+# if defined (atop)
+# undef atop
+# endif /* atop */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *atop (const char *s);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *atop (const wchar_t *s);
+# endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *bsearch (const void *key,
+ const void *base,
+ size_t nel,
+ size_t size,
+ ACE_COMPARE_FUNC);
+
+ extern ACE_Export
+ void *calloc (size_t elements, size_t sizeof_elements);
+
+ extern ACE_Export
+ void exit (int status = 0);
+
+ extern ACE_Export
+ void free (void *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *getenv (const char *symbol);
+
+# if defined (ACE_HAS_WCHAR) && defined (ACE_WIN32)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *getenv (const wchar_t *symbol);
+# endif /* ACE_HAS_WCHAR && ACE_WIN32 */
+
+ // not in spec
+ extern ACE_Export
+ ACE_TCHAR *getenvstrings (void);
+
+ // itoa not in spec
+ /// Converts an integer to a string.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *itoa (int value, char *string, int radix);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Converts an integer to a string.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *itoa (int value, wchar_t *string, int radix);
+#endif /* ACE_HAS_WCHAR */
+
+#if !defined (ACE_HAS_ITOA)
+ /// Emulated itoa - Converts an integer to a string.
+ extern ACE_Export
+ char *itoa_emulation (int value, char *string, int radix);
+#endif /* !ACE_HAS_ITOA */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_ITOW)
+ /// Emulated itow - Converts an integer to a string.
+ extern ACE_Export
+ wchar_t *itow_emulation (int value, wchar_t *string, int radix);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_ITOW */
+
+ extern ACE_Export
+ void *malloc (size_t);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE mkstemp (char *s);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE mkstemp (wchar_t *s);
+# endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_LACKS_MKSTEMP)
+ extern ACE_Export
+ ACE_HANDLE mkstemp_emulation (ACE_TCHAR * s);
+#endif /* ACE_LACKS_MKSTEMP */
+
+#if !defined (ACE_LACKS_MKTEMP)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *mktemp (char *s);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *mktemp (wchar_t *s);
+# endif /* ACE_HAS_WCHAR */
+#else
+ extern ACE_Export
+ ACE_TCHAR *mktemp (ACE_TCHAR *s);
+#endif /* !ACE_LACKS_MSTEMP */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int putenv (const char *string);
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_WIN32)
+ // Windows is the only platform that supports a wchar_t environment.
+ // Since other platforms make @a string part of the environment, it's
+ // a certain memory leak to copy and transform wchar_t to char for
+ // emulating this, so it's not attempted.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int putenv (const wchar_t *string);
+#endif /* ACE_HAS_WCHAR && ACE_WIN32 */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void qsort (void *base,
+ size_t nel,
+ size_t width,
+ ACE_COMPARE_FUNC);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rand (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rand_r (ACE_RANDR_TYPE &seed);
+
+ extern ACE_Export
+ void *realloc (void *, size_t);
+
+#if !defined (ACE_HAS_WINCE)
+# if !defined (ACE_LACKS_REALPATH)
+ ACE_NAMESPACE_INLINE_FUNCTION
+# else
+ extern ACE_Export
+# endif /* !ACE_LACKS_REALPATH */
+ char *realpath (const char *file_name, char *resolved_name);
+
+# if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *realpath (const wchar_t *file_name, wchar_t *resolved_name);
+# endif /* ACE_HAS_WCHAR */
+#endif /* ACE_HAS_WINCE */
+
+ // exit_hook and set_exit_hook not in spec
+ /// Function that is called by <ACE_OS::exit>, if non-null.
+ extern ACE_Export ACE_EXIT_HOOK exit_hook_;
+
+ /// For use by ACE_Object_Manager only, to register its exit hook..
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_EXIT_HOOK set_exit_hook (ACE_EXIT_HOOK hook);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void srand (u_int seed);
+
+ // not in spec
+ extern ACE_Export
+ ACE_TCHAR *strenvdup (const ACE_TCHAR *str);
+
+#if !defined (ACE_LACKS_STRTOD)
+ /// Converts a string to a double value (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ double strtod (const char *s, char **endptr);
+#endif /* !ACE_LACKS_STRTOD */
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOD)
+ /// Converts a string to a double value (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ double strtod (const wchar_t *s, wchar_t **endptr);
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOD */
+
+ /// Converts a string to a long value (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long strtol (const char *s, char **ptr, int base);
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOL)
+ /// Converts a string to a long value (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long strtol (const wchar_t *s, wchar_t **ptr, int base);
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOL */
+
+#if defined (ACE_LACKS_STRTOL)
+ extern ACE_Export
+ long strtol_emulation (const char *nptr, char **endptr, int base);
+#endif /* ACE_LACKS_STRTOL */
+
+ /// Converts a string to an unsigned long value (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ unsigned long strtoul (const char *s, char **ptr, int base);
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOUL)
+ /// Converts a string to an unsigned long value (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ unsigned long strtoul (const wchar_t *s, wchar_t **ptr, int base);
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOUL */
+
+#if defined (ACE_LACKS_STRTOUL)
+ extern ACE_Export
+ unsigned long strtoul_emulation (const char *nptr,
+ char **endptr,
+ int base);
+#endif /* ACE_LACKS_STRTOUL */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int system (const ACE_TCHAR *s);
+
+ /// Get the name of the current program
+ ///
+ /// Originally from NetBSD, now found in *BSD, Cygwin, Darwin, etc.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const char *getprogname ();
+
+#if !defined (ACE_HAS_GETPROGNAME)
+ extern ACE_Export
+ const char *getprogname_emulation ();
+#endif /* !ACE_HAS_GETPROGNAME */
+
+ /// Set the name of the current program
+ ///
+ /// Originally from NetBSD, now found in *BSD, Cygwin, Darwin, etc.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void setprogname (const char* name);
+
+#if !defined (ACE_HAS_SETPROGNAME)
+ extern ACE_Export
+ void setprogname_emulation (const char* name);
+#endif /* !ACE_HAS_SETPROGNAME */
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_stdlib.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_STDLIB_H */
diff --git a/ACE/ace/OS_NS_stdlib.inl b/ACE/ace/OS_NS_stdlib.inl
new file mode 100644
index 00000000000..2896fef63d4
--- /dev/null
+++ b/ACE/ace/OS_NS_stdlib.inl
@@ -0,0 +1,499 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/config-all.h" /* Need ACE_TRACE */
+#include "ace/Object_Manager_Base.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Global_Macros.h"
+#include "ace/Basic_Types.h" /* intptr_t */
+#include "ace/os_include/os_errno.h"
+#include "ace/os_include/os_search.h"
+
+#if defined (ACE_WCHAR_IN_STD_NAMESPACE)
+# define ACE_WCHAR_STD_NAMESPACE std
+#else
+# define ACE_WCHAR_STD_NAMESPACE ACE_STD_NAMESPACE
+#endif /* ACE_WCHAR_IN_STD_NAMESPACE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Doesn't need a macro since it *never* returns!
+
+ACE_INLINE void
+ACE_OS::_exit (int status)
+{
+ ACE_OS_TRACE ("ACE_OS::_exit");
+#if defined (ACE_VXWORKS)
+ ::exit (status);
+#elif !defined (ACE_HAS_WINCE)
+ ::_exit (status);
+#else
+ ::TerminateProcess (::GetCurrentProcess (), status);
+#endif /* ACE_VXWORKS */
+}
+
+ACE_INLINE void
+ACE_OS::abort (void)
+{
+#if !defined (ACE_HAS_WINCE)
+ ::abort ();
+#else
+ // @@ CE doesn't support abort?
+ exit (1);
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_INLINE int
+ACE_OS::atexit (ACE_EXIT_HOOK func)
+{
+ return ACE_OS_Object_Manager::instance ()->at_exit (func);
+}
+
+ACE_INLINE int
+ACE_OS::atoi (const char *s)
+{
+ ACE_OSCALL_RETURN (::atoi (s), int, -1);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::atoi (const wchar_t *s)
+{
+#if defined (ACE_WIN32)
+ ACE_OSCALL_RETURN (::_wtoi (s), int, -1);
+#else /* ACE_WIN32 */
+ return ACE_OS::atoi (ACE_Wide_To_Ascii (s).char_rep ());
+#endif /* ACE_WIN32 */
+}
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (atop)
+# undef atop
+#endif /* atop */
+
+ACE_INLINE void *
+ACE_OS::atop (const char *s)
+{
+ ACE_TRACE ("ACE_OS::atop");
+#if defined (ACE_WIN64)
+ intptr_t ip = ::_atoi64 (s);
+#elif defined (ACE_OPENVMS)
+# if !defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64)
+ int ip = ::atoi (s);
+# else
+ intptr_t ip = ::atoi (s);
+# endif
+#else
+ intptr_t ip = ::atoi (s);
+#endif /* ACE_WIN64 */
+ void * p = reinterpret_cast<void *> (ip);
+ return p;
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE void *
+ACE_OS::atop (const wchar_t *s)
+{
+# if defined (ACE_WIN64)
+ intptr_t ip = ::_wtoi64 (s);
+# elif defined (ACE_OPENVMS)
+# if !defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64)
+ int ip = ACE_OS::atoi (s);
+# else
+ intptr_t ip = ACE_OS::atoi (s);
+# endif
+# else
+ intptr_t ip = ACE_OS::atoi (s);
+# endif /* ACE_WIN64 */
+ void * p = reinterpret_cast<void *> (ip);
+ return p;
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE void *
+ACE_OS::bsearch (const void *key,
+ const void *base,
+ size_t nel,
+ size_t size,
+ ACE_COMPARE_FUNC compar)
+{
+#if !defined (ACE_LACKS_BSEARCH)
+ return ::bsearch (key, base, nel, size, compar);
+#else
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (base);
+ ACE_UNUSED_ARG (nel);
+ ACE_UNUSED_ARG (size);
+ ACE_UNUSED_ARG (compar);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_LACKS_BSEARCH */
+}
+
+ACE_INLINE char *
+ACE_OS::getenv (const char *symbol)
+{
+ ACE_OS_TRACE ("ACE_OS::getenv");
+#if defined (ACE_LACKS_ENV)
+ ACE_UNUSED_ARG (symbol);
+ ACE_NOTSUP_RETURN (0);
+#else /* ACE_LACKS_ENV */
+ ACE_OSCALL_RETURN (::getenv (symbol), char *, 0);
+#endif /* ACE_LACKS_ENV */
+}
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_WIN32)
+ACE_INLINE wchar_t *
+ACE_OS::getenv (const wchar_t *symbol)
+{
+#if defined (ACE_LACKS_ENV)
+ ACE_UNUSED_ARG (symbol);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN (::_wgetenv (symbol), wchar_t *, 0);
+#endif /* ACE_LACKS_ENV */
+}
+#endif /* ACE_HAS_WCHAR && ACE_WIN32 */
+
+ACE_INLINE char *
+ACE_OS::itoa (int value, char *string, int radix)
+{
+#if !defined (ACE_HAS_ITOA)
+ return ACE_OS::itoa_emulation (value, string, radix);
+#elif defined (ACE_ITOA_EQUIVALENT)
+ return ACE_ITOA_EQUIVALENT (value, string, radix);
+#else /* !ACE_HAS_ITOA */
+ return ::itoa (value, string, radix);
+#endif /* !ACE_HAS_ITOA */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::itoa (int value, wchar_t *string, int radix)
+{
+#if defined (ACE_LACKS_ITOW)
+ return ACE_OS::itow_emulation (value, string, radix);
+#else /* ACE_LACKS_ITOW */
+ return ::_itow (value, string, radix);
+#endif /* ACE_LACKS_ITOW */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE ACE_HANDLE
+ACE_OS::mkstemp (char *s)
+{
+#if !defined (ACE_LACKS_MKSTEMP)
+ return ::mkstemp (s);
+#else
+ return ACE_OS::mkstemp_emulation (ACE_TEXT_CHAR_TO_TCHAR (s));
+#endif /* !ACE_LACKS_MKSTEMP */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE ACE_HANDLE
+ACE_OS::mkstemp (wchar_t *s)
+{
+# if !defined (ACE_LACKS_MKSTEMP)
+ return ::mkstemp (ACE_TEXT_WCHAR_TO_TCHAR (ACE_TEXT_ALWAYS_CHAR (s)));
+# else
+ return ACE_OS::mkstemp_emulation (ACE_TEXT_WCHAR_TO_TCHAR (s));
+# endif /* !ACE_LACKS_MKSTEMP */
+}
+#endif /* ACE_HAS_WCHAR */
+
+#if !defined (ACE_LACKS_MKTEMP)
+ACE_INLINE char *
+ACE_OS::mktemp (char *s)
+{
+# if defined (ACE_WIN32)
+ return ::_mktemp (s);
+# else /* ACE_WIN32 */
+ return ::mktemp (s);
+# endif /* ACE_WIN32 */
+}
+
+# if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::mktemp (wchar_t *s)
+{
+# if defined (ACE_WIN32)
+ return ::_wmktemp (s);
+# else
+ // For narrow-char filesystems, we must convert the wide-char input to
+ // a narrow-char string for mktemp (), then convert the name back to
+ // wide-char for the caller.
+ ACE_Wide_To_Ascii narrow_s (s);
+ if (::mktemp (narrow_s.char_rep ()) == 0)
+ return 0;
+ ACE_Ascii_To_Wide wide_s (narrow_s.char_rep ());
+ ACE_OS::strcpy (s, wide_s.wchar_rep ());
+ return s;
+# endif
+}
+# endif /* ACE_HAS_WCHAR */
+
+#endif /* !ACE_LACKS_MKTEMP */
+
+#if defined (INTEGRITY)
+extern "C" {
+ int putenv (char *string);
+}
+#endif
+
+ACE_INLINE int
+ACE_OS::putenv (const char *string)
+{
+ ACE_OS_TRACE ("ACE_OS::putenv");
+#if defined (ACE_HAS_WINCE)
+ // WinCE don't have the concept of environment variables.
+ ACE_UNUSED_ARG (string);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_LACKS_PUTENV) && defined (ACE_HAS_SETENV)
+ int result = 0;
+ char *sp = ACE_OS::strchr (const_cast <char *> (string), '=');
+ if (sp)
+ {
+ char *stmp = ACE_OS::strdup (string);
+ if (stmp)
+ {
+ stmp[sp - string] = '\0';
+ ACE_OSCALL (::setenv (stmp, sp+sizeof (char), 1), int, -1, result);
+ ACE_OS::free (stmp);
+ }
+ else
+ {
+ errno = ENOMEM;
+ result = -1;
+ }
+ }
+ else
+ ACE_OSCALL (::setenv (string, "", 1), int, -1, result);
+
+ return result;
+#elif defined (ACE_LACKS_ENV) || defined (ACE_LACKS_PUTENV)
+ ACE_UNUSED_ARG (string);
+ ACE_NOTSUP_RETURN (0);
+#else /* ! ACE_HAS_WINCE */
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::putenv (const_cast <char *> (string)), int, -1);
+#endif /* ACE_HAS_WINCE */
+}
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_WIN32)
+ACE_INLINE int
+ACE_OS::putenv (const wchar_t *string)
+{
+ ACE_OS_TRACE ("ACE_OS::putenv");
+#if defined (ACE_HAS_WINCE)
+ // WinCE doesn't have the concept of environment variables.
+ ACE_UNUSED_ARG (string);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::_wputenv (string), int, -1);
+#endif /* ACE_HAS_WINCE */
+}
+#endif /* ACE_HAS_WCHAR && ACE_WIN32 */
+
+ACE_INLINE void
+ACE_OS::qsort (void *base,
+ size_t nel,
+ size_t width,
+ ACE_COMPARE_FUNC compar)
+{
+#if !defined (ACE_LACKS_QSORT)
+ ::qsort (base, nel, width, compar);
+#else
+ ACE_UNUSED_ARG (base);
+ ACE_UNUSED_ARG (nel);
+ ACE_UNUSED_ARG (width);
+ ACE_UNUSED_ARG (compar);
+#endif /* !ACE_LACKS_QSORT */
+}
+
+ACE_INLINE int
+ACE_OS::rand (void)
+{
+ ACE_OS_TRACE ("ACE_OS::rand");
+ ACE_OSCALL_RETURN (::rand (), int, -1);
+}
+
+#if !defined (ACE_WIN32)
+
+ACE_INLINE int
+ACE_OS::rand_r (ACE_RANDR_TYPE &seed)
+{
+ ACE_OS_TRACE ("ACE_OS::rand_r");
+# if defined (ACE_HAS_REENTRANT_FUNCTIONS) && \
+ !defined (ACE_LACKS_RAND_REENTRANT_FUNCTIONS)
+# if defined (DIGITAL_UNIX)
+ ACE_OSCALL_RETURN (::_Prand_r (&seed), int, -1);
+# elif defined (ACE_HAS_BROKEN_RANDR)
+ ACE_OSCALL_RETURN (::rand_r (seed), int, -1);
+# else
+ ACE_OSCALL_RETURN (::rand_r (&seed), int, -1);
+# endif /* DIGITAL_UNIX */
+# else
+ ACE_UNUSED_ARG (seed);
+ ACE_OSCALL_RETURN (::rand (), int, -1);
+# endif /* ACE_HAS_REENTRANT_FUNCTIONS */
+}
+
+#else /* ACE_WIN32 */
+
+ACE_INLINE int
+ACE_OS::rand_r (ACE_RANDR_TYPE& seed)
+{
+ ACE_OS_TRACE ("ACE_OS::rand_r");
+
+ long new_seed = (long) (seed);
+ if (new_seed == 0)
+ new_seed = 0x12345987;
+ long temp = new_seed / 127773;
+ new_seed = 16807 * (new_seed - temp * 127773) - 2836 * temp;
+ if (new_seed < 0)
+ new_seed += 2147483647;
+ (seed) = (unsigned int)new_seed;
+ return (int) (new_seed & RAND_MAX);
+}
+
+#endif /* !ACE_WIN32 */
+
+#if !defined (ACE_HAS_WINCE)
+# if !defined (ACE_LACKS_REALPATH)
+ACE_INLINE char *
+ACE_OS::realpath (const char *file_name,
+ char *resolved_name)
+{
+# if defined (ACE_WIN32)
+ return ::_fullpath (resolved_name, file_name, PATH_MAX);
+# else /* ACE_WIN32 */
+ return ::realpath (file_name, resolved_name);
+# endif /* ! ACE_WIN32 */
+}
+# endif /* !ACE_LACKS_REALPATH */
+
+# if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::realpath (const wchar_t *file_name,
+ wchar_t *resolved_name)
+{
+# if defined (ACE_WIN32)
+ return ::_wfullpath (resolved_name, file_name, PATH_MAX);
+# else /* ACE_WIN32 */
+ ACE_Wide_To_Ascii n_file_name (file_name);
+ char n_resolved[PATH_MAX];
+ if (0 != ACE_OS::realpath (n_file_name.char_rep (), n_resolved))
+ {
+ ACE_Ascii_To_Wide w_resolved (n_resolved);
+ ACE_OS::strcpy (resolved_name, w_resolved.wchar_rep ());
+ return resolved_name;
+ }
+ return 0;
+# endif /* ! ACE_WIN32 */
+}
+# endif /* ACE_HAS_WCHAR */
+#endif /* ACE_HAS_WINCE */
+
+ACE_INLINE ACE_EXIT_HOOK
+ACE_OS::set_exit_hook (ACE_EXIT_HOOK exit_hook)
+{
+ ACE_EXIT_HOOK old_hook = exit_hook_;
+ exit_hook_ = exit_hook;
+ return old_hook;
+}
+
+ACE_INLINE void
+ACE_OS::srand (u_int seed)
+{
+ ACE_OS_TRACE ("ACE_OS::srand");
+ ::srand (seed);
+}
+
+#if !defined (ACE_LACKS_STRTOD)
+ACE_INLINE double
+ACE_OS::strtod (const char *s, char **endptr)
+{
+ return ::strtod (s, endptr);
+}
+#endif /* !ACE_LACKS_STRTOD */
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOD)
+ACE_INLINE double
+ACE_OS::strtod (const wchar_t *s, wchar_t **endptr)
+{
+ return ACE_WCHAR_STD_NAMESPACE::wcstod (s, endptr);
+}
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOD */
+
+ACE_INLINE long
+ACE_OS::strtol (const char *s, char **ptr, int base)
+{
+#if defined (ACE_LACKS_STRTOL)
+ return ACE_OS::strtol_emulation (s, ptr, base);
+#else /* ACE_LACKS_STRTOL */
+ return ::strtol (s, ptr, base);
+#endif /* ACE_LACKS_STRTOL */
+}
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOL)
+ACE_INLINE long
+ACE_OS::strtol (const wchar_t *s, wchar_t **ptr, int base)
+{
+ return ACE_WCHAR_STD_NAMESPACE::wcstol (s, ptr, base);
+}
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOL */
+
+ACE_INLINE unsigned long
+ACE_OS::strtoul (const char *s, char **ptr, int base)
+{
+#if defined (ACE_LACKS_STRTOUL)
+ return ACE_OS::strtoul_emulation (s, ptr, base);
+#else /* ACE_LACKS_STRTOUL */
+ return ::strtoul (s, ptr, base);
+#endif /* ACE_LACKS_STRTOUL */
+}
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOUL)
+ACE_INLINE unsigned long
+ACE_OS::strtoul (const wchar_t *s, wchar_t **ptr, int base)
+{
+ return ACE_WCHAR_STD_NAMESPACE::wcstoul (s, ptr, base);
+}
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOUL */
+
+ACE_INLINE int
+ACE_OS::system (const ACE_TCHAR *s)
+{
+ // ACE_OS_TRACE ("ACE_OS::system");
+#if defined (ACE_LACKS_SYSTEM)
+ ACE_UNUSED_ARG (s);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OSCALL_RETURN (::_wsystem (s), int, -1);
+#elif defined (ACE_TANDEM_T1248_PTHREADS)
+ ACE_OSCALL_RETURN (::spt_system (s), int, -1);
+#else
+ ACE_OSCALL_RETURN (::system (ACE_TEXT_ALWAYS_CHAR (s)), int, -1);
+#endif /* ACE_LACKS_SYSTEM */
+}
+
+ACE_INLINE const char*
+ACE_OS::getprogname ()
+{
+#if defined (ACE_HAS_GETPROGNAME)
+ return ::getprogname ();
+#else
+ return ACE_OS::getprogname_emulation ();
+#endif /* ACE_HAS_GETPROGNAME */
+}
+
+ACE_INLINE void
+ACE_OS::setprogname (const char* name)
+{
+#if defined (ACE_HAS_SETPROGNAME)
+ ::setprogname (name);
+#else
+ ACE_OS::setprogname_emulation (name);
+#endif /* ACE_HAS_SETPROGNAME */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_string.cpp b/ACE/ace/OS_NS_string.cpp
new file mode 100644
index 00000000000..be63e28e450
--- /dev/null
+++ b/ACE/ace/OS_NS_string.cpp
@@ -0,0 +1,377 @@
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/ACE.h"
+
+ACE_RCSID (ace,
+ OS_NS_string,
+ "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_string.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if defined (ACE_HAS_WCHAR)
+# include "ace/OS_NS_stdlib.h"
+#endif /* ACE_HAS_WCHAR */
+
+#if !defined (ACE_LACKS_STRERROR)
+# include "ace/OS_NS_stdio.h"
+#endif /* ACE_LACKS_STRERROR */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_LACKS_MEMCHR)
+const void *
+ACE_OS::memchr_emulation (const void *s, int c, size_t len)
+{
+ const unsigned char *t = (const unsigned char *) s;
+ const unsigned char *e = (const unsigned char *) s + len;
+
+ while (t < e)
+ if (((int) *t) == c)
+ return t;
+ else
+ ++t;
+
+ return 0;
+}
+#endif /* ACE_LACKS_MEMCHR */
+
+#if (defined (ACE_LACKS_STRDUP) && !defined (ACE_STRDUP_EQUIVALENT)) \
+ || defined (ACE_HAS_STRDUP_EMULATION)
+char *
+ACE_OS::strdup_emulation (const char *s)
+{
+ char *t = (char *) ACE_OS::malloc (ACE_OS::strlen (s) + 1);
+ if (t == 0)
+ return 0;
+
+ return ACE_OS::strcpy (t, s);
+}
+#endif /* (ACE_LACKS_STRDUP && !ACE_STRDUP_EQUIVALENT) || ... */
+
+#if defined (ACE_HAS_WCHAR)
+#if (defined (ACE_LACKS_WCSDUP) && !defined (ACE_WCSDUP_EQUIVALENT)) \
+ || defined (ACE_HAS_WCSDUP_EMULATION)
+wchar_t *
+ACE_OS::strdup_emulation (const wchar_t *s)
+{
+ wchar_t *buffer =
+ (wchar_t *) ACE_OS::malloc ((ACE_OS::strlen (s) + 1)
+ * sizeof (wchar_t));
+ if (buffer == 0)
+ return 0;
+
+ return ACE_OS::strcpy (buffer, s);
+}
+#endif /* (ACE_LACKS_WCSDUP && !ACE_WCSDUP_EQUIVALENT) || ... */
+#endif /* ACE_HAS_WCHAR */
+
+char *
+ACE_OS::strecpy (char *s, const char *t)
+{
+ register char *dscan = s;
+ register const char *sscan = t;
+
+ while ((*dscan++ = *sscan++) != '\0')
+ continue;
+
+ return dscan;
+}
+
+#if defined (ACE_HAS_WCHAR)
+wchar_t *
+ACE_OS::strecpy (wchar_t *s, const wchar_t *t)
+{
+ register wchar_t *dscan = s;
+ register const wchar_t *sscan = t;
+
+ while ((*dscan++ = *sscan++) != ACE_TEXT_WIDE ('\0'))
+ continue;
+
+ return dscan;
+}
+#endif /* ACE_HAS_WCHAR */
+
+char *
+ACE_OS::strerror (int errnum)
+{
+ static char ret_errortext[128];
+
+ if (ACE::is_sock_error (errnum))
+ {
+ const ACE_TCHAR *errortext = ACE::sock_error (errnum);
+ ACE_OS::strncpy (ret_errortext,
+ ACE_TEXT_ALWAYS_CHAR (errortext),
+ sizeof (ret_errortext));
+ return ret_errortext;
+ }
+#if defined (ACE_LACKS_STRERROR)
+ errno = EINVAL;
+ return ACE_OS::strerror_emulation (errnum);
+#else /* ACE_LACKS_STRERROR */
+ // Adapt to the various ways that strerror() indicates a bad errnum.
+ // Most modern systems set errno to EINVAL. Some older platforms return
+ // a pointer to a NULL string. This code makes the behavior more consistent
+ // across platforms. On a bad errnum, we make a string with the error number
+ // and set errno to EINVAL.
+ ACE_Errno_Guard g (errno);
+ errno = 0;
+ char *errmsg = 0;
+
+#if defined (ACE_HAS_TR24731_2005_CRT)
+ errmsg = ret_errortext;
+ ACE_SECURECRTCALL (strerror_s (ret_errortext, sizeof(ret_errortext), errnum),
+ char *, 0, errmsg);
+ return errmsg;
+#elif defined (ACE_WIN32)
+ if (errnum < 0 || errnum >= _sys_nerr)
+ errno = EINVAL;
+#endif /* ACE_WIN32 */
+ errmsg = ::strerror (errnum);
+
+ if (errno == EINVAL || errmsg == 0 || errmsg[0] == 0)
+ {
+ ACE_OS::sprintf (ret_errortext, "Unknown error %d", errnum);
+ errmsg = ret_errortext;
+ g = EINVAL;
+ }
+ return errmsg;
+#endif /* ACE_LACKS_STRERROR */
+}
+
+#if defined (ACE_LACKS_STRERROR)
+/**
+ * Just returns "Unknown Error" all the time.
+ */
+char *
+ACE_OS::strerror_emulation (int errnum)
+{
+ return "Unknown Error";
+}
+#endif /* ACE_LACKS_STRERROR */
+
+const char *
+ACE_OS::strnchr (const char *s, int c, size_t len)
+{
+ for (size_t i = 0; i < len; ++i)
+ if (s[i] == c)
+ return s + i;
+
+ return 0;
+}
+
+const ACE_WCHAR_T *
+ACE_OS::strnchr (const ACE_WCHAR_T *s, ACE_WCHAR_T c, size_t len)
+{
+ for (size_t i = 0; i < len; ++i)
+ if (s[i] == c)
+ return s + i;
+
+ return 0;
+}
+
+const char *
+ACE_OS::strnstr (const char *s1, const char *s2, size_t len2)
+{
+ // Substring length
+ size_t const len1 = ACE_OS::strlen (s1);
+
+ // Check if the substring is longer than the string being searched.
+ if (len2 > len1)
+ return 0;
+
+ // Go upto <len>
+ size_t const len = len1 - len2;
+
+ for (size_t i = 0; i <= len; i++)
+ {
+ if (ACE_OS::memcmp (s1 + i, s2, len2) == 0)
+ // Found a match! Return the index.
+ return s1 + i;
+ }
+
+ return 0;
+}
+
+const ACE_WCHAR_T *
+ACE_OS::strnstr (const ACE_WCHAR_T *s1, const ACE_WCHAR_T *s2, size_t len2)
+{
+ // Substring length
+ const size_t len1 = ACE_OS::strlen (s1);
+
+ // Check if the substring is longer than the string being searched.
+ if (len2 > len1)
+ return 0;
+
+ // Go upto <len>
+ const size_t len = len1 - len2;
+
+ for (size_t i = 0; i <= len; i++)
+ {
+ if (ACE_OS::memcmp (s1 + i, s2, len2 * sizeof (ACE_WCHAR_T)) == 0)
+ // Found a match! Return the index.
+ return s1 + i;
+ }
+
+ return 0;
+}
+
+#if defined (ACE_HAS_MEMCPY_LOOP_UNROLL)
+void *
+ACE_OS::fast_memcpy (void *t, const void *s, size_t len)
+{
+ unsigned char* to = static_cast<unsigned char*> (t) ;
+ const unsigned char* from = static_cast<const unsigned char*> (s) ;
+ // Unroll the loop...
+ switch (len)
+ {
+ case 16: to[15] = from[15];
+ case 15: to[14] = from[14];
+ case 14: to[13] = from[13];
+ case 13: to[12] = from[12];
+ case 12: to[11] = from[11];
+ case 11: to[10] = from[10];
+ case 10: to[9] = from[9];
+ case 9: to[8] = from[8];
+ case 8: to[7] = from[7];
+ case 7: to[6] = from[6];
+ case 6: to[5] = from[5];
+ case 5: to[4] = from[4];
+ case 4: to[3] = from[3];
+ case 3: to[2] = from[2];
+ case 2: to[1] = from[1];
+ case 1: to[0] = from[0];
+ case 0: return t;
+ default: return ::memcpy (t, s, len);
+ }
+}
+#endif /* ACE_HAS_MEMCPY_LOOP_UNROLL */
+
+#if defined (ACE_LACKS_STRRCHR)
+char *
+ACE_OS::strrchr_emulation (char *s, int c)
+{
+ char *p = s + ACE_OS::strlen (s);
+
+ while (*p != c)
+ if (p == s)
+ return 0;
+ else
+ --p;
+
+ return p;
+}
+
+const char *
+ACE_OS::strrchr_emulation (const char *s, int c)
+{
+ const char *p = s + ACE_OS::strlen (s);
+
+ while (*p != c)
+ if (p == s)
+ return 0;
+ else
+ --p;
+
+ return p;
+}
+#endif /* ACE_LACKS_STRRCHR */
+
+char *
+ACE_OS::strsncpy (char *dst, const char *src, size_t maxlen)
+{
+ register char *rdst = dst;
+ register const char *rsrc = src;
+ register size_t rmaxlen = maxlen;
+
+ if (rmaxlen > 0)
+ {
+ if (rdst!=rsrc)
+ {
+ *rdst = '\0';
+ if (rsrc != 0)
+ strncat (rdst, rsrc, --rmaxlen);
+ }
+ else
+ {
+ rdst += (rmaxlen - 1);
+ *rdst = '\0';
+ }
+ }
+ return dst;
+}
+
+ACE_WCHAR_T *
+ACE_OS::strsncpy (ACE_WCHAR_T *dst, const ACE_WCHAR_T *src, size_t maxlen)
+{
+ register ACE_WCHAR_T *rdst = dst;
+ register const ACE_WCHAR_T *rsrc = src;
+ register size_t rmaxlen = maxlen;
+
+ if (rmaxlen > 0)
+ {
+ if (rdst!=rsrc)
+ {
+ *rdst = ACE_TEXT_WIDE ('\0');
+ if (rsrc != 0)
+ strncat (rdst, rsrc, --rmaxlen);
+ }
+ else
+ {
+ rdst += (rmaxlen - 1);
+ *rdst = ACE_TEXT_WIDE ('\0');
+ }
+ }
+ return dst;
+}
+
+#if (!defined (ACE_HAS_REENTRANT_FUNCTIONS) || defined (ACE_LACKS_STRTOK_R)) \
+ && !defined (ACE_HAS_TR24731_2005_CRT)
+char *
+ACE_OS::strtok_r_emulation (char *s, const char *tokens, char **lasts)
+{
+ if (s == 0)
+ s = *lasts;
+ else
+ *lasts = s;
+ if (*s == 0) // We have reached the end
+ return 0;
+ size_t l_org = ACE_OS::strlen (s);
+ s = ::strtok (s, tokens);
+ if (s == 0)
+ return 0;
+ const size_t l_sub = ACE_OS::strlen (s);
+ if (s + l_sub < *lasts + l_org)
+ *lasts = s + l_sub + 1;
+ else
+ *lasts = s + l_sub;
+ return s ;
+}
+#endif /* !ACE_HAS_REENTRANT_FUNCTIONS */
+
+# if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOK)
+wchar_t*
+ACE_OS::strtok_r_emulation (ACE_WCHAR_T *s,
+ const ACE_WCHAR_T *tokens,
+ ACE_WCHAR_T **lasts)
+{
+ ACE_WCHAR_T* sbegin = s ? s : *lasts;
+ sbegin += ACE_OS::strspn(sbegin, tokens);
+ if (*sbegin == 0)
+ {
+ static ACE_WCHAR_T empty[1] = { 0 };
+ *lasts = empty;
+ return 0;
+ }
+ ACE_WCHAR_T*send = sbegin + ACE_OS::strcspn(sbegin, tokens);
+ if (*send != 0)
+ *send++ = 0;
+ *lasts = send;
+ return sbegin;
+}
+# endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOK */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_string.h b/ACE/ace/OS_NS_string.h
new file mode 100644
index 00000000000..0c5214c06de
--- /dev/null
+++ b/ACE/ace/OS_NS_string.h
@@ -0,0 +1,471 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_string.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_STRING_H
+#define ACE_OS_NS_STRING_H
+
+# include /**/ "ace/pre.h"
+
+# include "ace/config-lite.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Basic_Types.h" // to get ACE_WCHAR_T,
+ // should be in os_stddef.h or not used like this.
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ /** @name Functions from <cstring>
+ *
+ * Included are the functions defined in <cstring> and their <cwchar>
+ * equivalents.
+ *
+ * @todo To be complete, we should add strcoll, and strxfrm.
+ */
+ //@{
+
+ /// Finds characters in a buffer (const void version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const void *memchr (const void *s, int c, size_t len);
+
+ /// Finds characters in a buffer (void version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *memchr (void *s, int c, size_t len);
+
+#if defined (ACE_LACKS_MEMCHR)
+ /// Emulated memchr - Finds a character in a buffer.
+ extern ACE_Export
+ const void *memchr_emulation (const void *s, int c, size_t len);
+#endif /* ACE_LACKS_MEMCHR */
+
+ /// Compares two buffers.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int memcmp (const void *t, const void *s, size_t len);
+
+ /// Copies one buffer to another.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *memcpy (void *t, const void *s, size_t len);
+
+#if defined (ACE_HAS_MEMCPY_LOOP_UNROLL)
+/*
+ * Version of memcpy where the copy loop is unrolled.
+ * On certain platforms this results in better performance.
+ * This is determined and set via autoconf.
+ */
+ extern ACE_Export
+ void *fast_memcpy (void *t, const void *s, size_t len);
+#endif
+
+ /// Moves one buffer to another.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *memmove (void *t, const void *s, size_t len);
+
+ /// Fills a buffer with a character value.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *memset (void *s, int c, size_t len);
+
+ /// Appends a string to another string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strcat (char *s, const char *t);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Appends a string to another string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strcat (wchar_t *s, const wchar_t *t);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Finds the first occurance of a character in a string (const char
+ /// version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const char *strchr (const char *s, int c);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Finds the first occurance of a character in a string (const wchar_t
+ /// version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const wchar_t *strchr (const wchar_t *s, wchar_t c);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Finds the first occurance of a character in a string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strchr (char *s, int c);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Finds the first occurance of a character in a string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strchr (wchar_t *s, wchar_t c);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Compares two strings (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int strcmp (const char *s, const char *t);
+
+ /// Compares two strings (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int strcmp (const ACE_WCHAR_T *s, const ACE_WCHAR_T *t);
+
+ /// Copies a string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strcpy (char *s, const char *t);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Copies a string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strcpy (wchar_t *s, const wchar_t *t);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Searches for the first substring without any of the specified
+ /// characters and returns the size of the substring (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strcspn (const char *s, const char *reject);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Searches for the first substring without any of the specified
+ /// characters and returns the size of the substring (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strcspn (const wchar_t *s, const wchar_t *reject);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Returns a malloced duplicated string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strdup (const char *s);
+
+#if (defined (ACE_LACKS_STRDUP) && !defined(ACE_STRDUP_EQUIVALENT)) \
+ || defined (ACE_HAS_STRDUP_EMULATION)
+ extern ACE_Export
+ char *strdup_emulation (const char *s);
+#endif
+
+#if defined (ACE_HAS_WCHAR)
+ /// Returns a malloced duplicated string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strdup (const wchar_t *s);
+
+#if (defined (ACE_LACKS_WCSDUP) && !defined(ACE_WCSDUP_EQUIVALENT)) \
+ || defined (ACE_HAS_WCSDUP_EMULATION)
+ extern ACE_Export
+ wchar_t *strdup_emulation (const wchar_t *s);
+#endif
+#endif /* ACE_HAS_WCHAR */
+
+ /// Copies a string, but returns a pointer to the end of the
+ /// copied region (char version).
+ extern ACE_Export
+ char *strecpy (char *des, const char *src);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Copies a string, but returns a pointer to the end of the
+ /// copied region (wchar_t version).
+ extern ACE_Export
+ wchar_t *strecpy (wchar_t *s, const wchar_t *t);
+#endif /* ACE_HAS_WCHAR */
+
+ /*
+ ** Returns a system error message. If the supplied errnum is out of range,
+ ** a string of the form "Unknown error %d" is used to format the string
+ ** whose pointer is returned and errno is set to EINVAL.
+ */
+ extern ACE_Export
+ char *strerror (int errnum);
+
+#if defined (ACE_LACKS_STRERROR)
+ /// Emulated strerror - Returns a system error message.
+ extern ACE_Export
+ char *strerror_emulation (int errnum);
+#endif /* ACE_LACKS_STRERROR */
+
+ /// Finds the length of a string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strlen (const char *s);
+
+ /// Finds the length of a string (ACE_WCHAR_T version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strlen (const ACE_WCHAR_T *s);
+
+ /// Appends part of a string to another string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strncat (char *s, const char *t, size_t len);
+
+ /// Appends part of a string to another string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_WCHAR_T *strncat (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len);
+
+ /// Finds the first occurance of a character in an array (const char
+ /// version).
+ extern ACE_Export
+ const char *strnchr (const char *s, int c, size_t len);
+
+ /// Finds the first occurance of a character in an array (const ACE_WCHAR_T
+ /// version).
+ extern ACE_Export
+ const ACE_WCHAR_T *strnchr (const ACE_WCHAR_T *s, ACE_WCHAR_T c, size_t len);
+
+ /// Finds the first occurance of a character in an array (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strnchr (char *s, int c, size_t len);
+
+ /// Finds the first occurance of a character in an array (ACE_WCHAR_T version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_WCHAR_T *strnchr (ACE_WCHAR_T *s, ACE_WCHAR_T c, size_t len);
+
+ /// Compares two arrays (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int strncmp (const char *s, const char *t, size_t len);
+
+ /// Compares two arrays (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int strncmp (const ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len);
+
+ /// Copies an array (char version)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strncpy (char *s, const char *t, size_t len);
+
+ /// Copies an array (ACE_WCHAR_T version)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_WCHAR_T *strncpy (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len);
+
+ /// Finds the length of a limited-length string (char version).
+ /**
+ * @param s The character string to find the length of.
+ * @param maxlen The maximum number of characters that will be
+ * scanned for the terminating nul character.
+ *
+ * @return The length of @arg s, if the terminating nul character
+ * is located, else @arg maxlen.
+ */
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strnlen (const char *s, size_t maxlen);
+
+ /// Finds the length of a limited-length string (ACE_WCHAR_T version).
+ /**
+ * @param s The character string to find the length of.
+ * @param maxlen The maximum number of characters that will be
+ * scanned for the terminating nul character.
+ *
+ * @return The length of @arg s, if the terminating nul character
+ * is located, else @arg maxlen.
+ */
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strnlen (const ACE_WCHAR_T *s, size_t maxlen);
+
+ /// Finds the first occurance of a substring in an array (const char
+ /// version).
+ extern ACE_Export
+ const char *strnstr (const char *s, const char *t, size_t len);
+
+ /// Finds the first occurance of a substring in an array (const wchar_t
+ /// version).
+ extern ACE_Export
+ const ACE_WCHAR_T *strnstr (const ACE_WCHAR_T *s,
+ const ACE_WCHAR_T *t,
+ size_t len);
+
+ /// Finds the first occurance of a substring in an array (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strnstr (char *s, const char *t, size_t len);
+
+ /// Finds the first occurance of a substring in an array (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_WCHAR_T *strnstr (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len);
+
+ /// Searches for characters in a string (const char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const char *strpbrk (const char *s1, const char *s2);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Searches for characters in a string (const wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const wchar_t *strpbrk (const wchar_t *s1, const wchar_t *s2);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Searches for characters in a string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strpbrk (char *s1, const char *s2);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Searches for characters in a string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strpbrk (wchar_t *s1, const wchar_t *s2);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Finds the last occurance of a character in a string (const char
+ /// version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const char *strrchr (const char *s, int c);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Finds the last occurance of a character in a string (const wchar_t
+ /// version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const wchar_t *strrchr (const wchar_t *s, wchar_t c);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Finds the last occurance of a character in a string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strrchr (char *s, int c);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Finds the last occurance of a character in a string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strrchr (wchar_t *s, wchar_t c);
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_LACKS_STRRCHR)
+ /// Emulated strrchr (char version) - Finds the last occurance of a
+ /// character in a string.
+ extern ACE_Export
+ char *strrchr_emulation (char *s, int c);
+
+ /// Emulated strrchr (const char version) - Finds the last occurance of a
+ /// character in a string.
+ extern ACE_Export
+ const char *strrchr_emulation (const char *s, int c);
+#endif /* ACE_LACKS_STRRCHR */
+
+ /// This is a "safe" c string copy function (char version).
+ /**
+ * Unlike strncpy() this function will always add a terminating '\0'
+ * char if maxlen > 0. So the user doesn't has to provide an extra
+ * '\0' if the user wants a '\0' terminated dst. The function
+ * doesn't check for a 0 @a dst, because this will give problems
+ * anyway. When @a src is 0 an empty string is made. We do not
+ * "touch" * @a dst if maxlen is 0. Returns @a dst. Care should be
+ * taken when replacing strncpy() calls, because in some cases a
+ * strncpy() user is using the "not '\0' terminating" feature from
+ * strncpy(). This happens most when the call to strncpy() was
+ * optimized by using a maxlen which is 1 smaller than the size
+ * because there's always written a '\0' inside this last position.
+ * Very seldom it's possible that the '\0' padding feature from
+ * strncpy() is needed.
+ */
+ extern ACE_Export
+ char *strsncpy (char *dst,
+ const char *src,
+ size_t maxlen);
+
+ /// This is a "safe" c string copy function (wchar_t version).
+ /**
+ * Unlike strncpy() this function will always add a terminating '\0'
+ * char if maxlen > 0. So the user doesn't has to provide an extra
+ * '\0' if the user wants a '\0' terminated dst. The function
+ * doesn't check for a 0 @a dst, because this will give problems
+ * anyway. When @a src is 0 an empty string is made. We do not
+ * "touch" * @a dst if maxlen is 0. Returns @a dst. Care should be
+ * taken when replacing strncpy() calls, because in some cases a
+ * strncpy() user is using the "not '\0' terminating" feature from
+ * strncpy(). This happens most when the call to strncpy() was
+ * optimized by using a maxlen which is 1 smaller than the size
+ * because there's always written a '\0' inside this last position.
+ * Very seldom it's possible that the '\0' padding feature from
+ * strncpy() is needed.
+ */
+ extern ACE_Export
+ ACE_WCHAR_T *strsncpy (ACE_WCHAR_T *dst,
+ const ACE_WCHAR_T *src,
+ size_t maxlen);
+
+ /// Searches for the first substring containing only the specified
+ /// characters and returns the size of the substring (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strspn (const char *s1, const char *s2);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Searches for the first substring containing only the specified
+ /// characters and returns the size of the substring (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strspn (const wchar_t *s1, const wchar_t *s2);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Finds the first occurance of a substring in a string (const char
+ /// version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const char *strstr (const char *s, const char *t);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Finds the first occurance of a substring in a string (const wchar_t
+ /// version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ const wchar_t *strstr (const wchar_t *s, const wchar_t *t);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Finds the first occurance of a substring in a string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strstr (char *s, const char *t);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Finds the first occurance of a substring in a string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strstr (wchar_t *s, const wchar_t *t);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Finds the next token in a string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strtok (char *s, const char *tokens);
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOK)
+ /// Finds the next token in a string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strtok (wchar_t *s, const wchar_t *tokens);
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOK */
+
+ //@}
+
+ /// Finds the next token in a string (safe char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strtok_r (char *s, const char *tokens, char **lasts);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Finds the next token in a string (wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *strtok_r (ACE_WCHAR_T *s, const ACE_WCHAR_T *tokens, ACE_WCHAR_T **lasts);
+#endif // ACE_HAS_WCHAR
+
+#if !defined (ACE_HAS_REENTRANT_FUNCTIONS) || defined (ACE_LACKS_STRTOK_R)
+ /// Emulated strtok_r.
+ extern ACE_Export
+ char *strtok_r_emulation (char *s, const char *tokens, char **lasts);
+#endif /* !ACE_HAS_REENTRANT_FUNCTIONS */
+
+# if defined (ACE_HAS_WCHAR) && defined(ACE_LACKS_WCSTOK)
+ /// Emulated strtok_r (wchar_t version).
+ extern ACE_Export
+ wchar_t *strtok_r_emulation (ACE_WCHAR_T *s, const ACE_WCHAR_T *tokens, ACE_WCHAR_T **lasts);
+# endif // ACE_HAS_WCHAR && ACE_LACKS_WCSTOK
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_string.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_STRING_H */
diff --git a/ACE/ace/OS_NS_string.inl b/ACE/ace/OS_NS_string.inl
new file mode 100644
index 00000000000..4c57bfc0da3
--- /dev/null
+++ b/ACE/ace/OS_NS_string.inl
@@ -0,0 +1,560 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// OS_NS_wchar.h is only needed to get the emulation methods.
+// Perhaps they should be moved. dhinton
+#include "ace/OS_NS_wchar.h"
+#include "ace/os_include/os_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE const void *
+ACE_OS::memchr (const void *s, int c, size_t len)
+{
+#if !defined (ACE_LACKS_MEMCHR)
+ return ::memchr (s, c, len);
+#else /* ACE_LACKS_MEMCHR */
+ return ACE_OS::memchr_emulation (s, c, len);
+#endif /* !ACE_LACKS_MEMCHR */
+}
+
+ACE_INLINE void *
+ACE_OS::memchr (void *s, int c, size_t len)
+{
+ return const_cast<void *> (ACE_OS::memchr (static_cast<const void *> (s),
+ c,
+ len));
+}
+
+ACE_INLINE int
+ACE_OS::memcmp (const void *t, const void *s, size_t len)
+{
+ return ::memcmp (t, s, len);
+}
+
+ACE_INLINE void *
+ACE_OS::memcpy (void *t, const void *s, size_t len)
+{
+#if defined (ACE_HAS_MEMCPY_LOOP_UNROLL)
+ return fast_memcpy (t, s, len);
+#else
+ return ::memcpy (t, s, len);
+#endif /* ACE_HAS_MEMCPY_LOOP_UNROLL */
+}
+
+ACE_INLINE void *
+ACE_OS::memmove (void *t, const void *s, size_t len)
+{
+ return ::memmove (t, s, len);
+}
+
+ACE_INLINE void *
+ACE_OS::memset (void *s, int c, size_t len)
+{
+#if defined (ACE_HAS_SLOW_MEMSET)
+ // This section requires a high optimization level (-xO4 with SunCC)
+ // in order to actually be inlined.
+ char* ptr = static_cast<char*> (s);
+ switch (len)
+ {
+ case 16:
+ ptr[15] = c;
+ case 15:
+ ptr[14] = c;
+ case 14:
+ ptr[13] = c;
+ case 13:
+ ptr[12] = c;
+ case 12:
+ ptr[11] = c;
+ case 11:
+ ptr[10] = c;
+ case 10:
+ ptr[9] = c;
+ case 9:
+ ptr[8] = c;
+ case 8:
+ ptr[7] = c;
+ case 7:
+ ptr[6] = c;
+ case 6:
+ ptr[5] = c;
+ case 5:
+ ptr[4] = c;
+ case 4:
+ ptr[3] = c;
+ case 3:
+ ptr[2] = c;
+ case 2:
+ ptr[1] = c;
+ case 1:
+ ptr[0] = c;
+ break;
+ default:
+ for (size_t i = 0; i < len; ++i)
+ {
+ ptr[i] = c;
+ }
+ }
+
+ return s;
+#else
+ return ::memset (s, c, len);
+#endif /* ACE_HAS_SLOW_MEMSET */
+}
+
+ACE_INLINE char *
+ACE_OS::strcat (char *s, const char *t)
+{
+ return ::strcat (s, t);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::strcat (wchar_t *s, const wchar_t *t)
+{
+# if defined (ACE_LACKS_WCSCAT)
+ return ACE_OS::wcscat_emulation (s, t);
+# else /* ACE_LACKS_WCSCAT */
+ return ::wcscat (s, t);
+# endif /* ACE_LACKS_WCSCAT */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE const char *
+ACE_OS::strchr (const char *s, int c)
+{
+ return const_cast <const char *> (::strchr (s, c));
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE const wchar_t *
+ACE_OS::strchr (const wchar_t *s, wchar_t c)
+{
+# if defined (ACE_LACKS_WCSCHR)
+ return ACE_OS::wcschr_emulation (s, c);
+# else /* ACE_LACKS_WCSCHR */
+ return ::wcschr (s, c);
+# endif /* ACE_LACKS_WCSCHR */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE char *
+ACE_OS::strchr (char *s, int c)
+{
+ return ::strchr (s, c);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::strchr (wchar_t *s, wchar_t c)
+{
+ return
+ const_cast<wchar_t *> (ACE_OS::strchr (const_cast<const wchar_t *> (s),
+ c));
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::strcmp (const char *s, const char *t)
+{
+ return ::strcmp (s, t);
+}
+
+ACE_INLINE int
+ACE_OS::strcmp (const ACE_WCHAR_T *s, const ACE_WCHAR_T *t)
+{
+# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSCMP)
+ return ACE_OS::wcscmp_emulation (s, t);
+# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCMP */
+ return ::wcscmp (s, t);
+# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCMP */
+}
+
+ACE_INLINE char *
+ACE_OS::strcpy (char *s, const char *t)
+{
+ return ::strcpy (s, t);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::strcpy (wchar_t *s, const wchar_t *t)
+{
+# if defined (ACE_LACKS_WCSCPY)
+ return ACE_OS::wcscpy_emulation (s, t);
+# else /* ACE_LACKS_WCSCPY */
+ return ::wcscpy (s, t);
+# endif /* ACE_LACKS_WCSCPY */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE size_t
+ACE_OS::strcspn (const char *s, const char *reject)
+{
+ return ::strcspn (s, reject);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE size_t
+ACE_OS::strcspn (const wchar_t *s, const wchar_t *reject)
+{
+# if defined (ACE_LACKS_WCSCSPN)
+ return ACE_OS::wcscspn_emulation (s, reject);
+# else /* ACE_LACKS_WCSCSPN */
+ return ::wcscspn (s, reject);
+# endif /* ACE_LACKS_WCSCSPN */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE char *
+ACE_OS::strdup (const char *s)
+{
+# if (defined (ACE_LACKS_STRDUP) && !defined(ACE_STRDUP_EQUIVALENT)) \
+ || defined (ACE_HAS_STRDUP_EMULATION)
+ return ACE_OS::strdup_emulation (s);
+# elif defined (ACE_STRDUP_EQUIVALENT)
+ return ACE_STRDUP_EQUIVALENT (s);
+# elif defined (ACE_HAS_NONCONST_STRDUP)
+ return ::strdup (const_cast<char *> (s));
+#else
+ return ::strdup (s);
+# endif /* (ACE_LACKS_STRDUP && !ACE_STRDUP_EQUIVALENT) || ... */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::strdup (const wchar_t *s)
+{
+# if (defined (ACE_LACKS_WCSDUP) && !defined (ACE_WCSDUP_EQUIVALENT)) \
+ || defined (ACE_HAS_WCSDUMP_EMULATION)
+ return ACE_OS::strdup_emulation (s);
+# elif defined (ACE_WCSDUP_EQUIVALENT)
+ return ACE_WCSDUP_EQUIVALENT (s);
+# elif defined (ACE_HAS_NONCONST_WCSDUP)
+ return ::wcsdup (const_cast<wchar_t*> (s));
+# else
+ return ::wcsdup (s);
+# endif /* (ACE_LACKS_WCSDUP && !ACE_WCSDUP_EQUIVALENT) || ... */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE size_t
+ACE_OS::strlen (const char *s)
+{
+ return ::strlen (s);
+}
+
+ACE_INLINE size_t
+ACE_OS::strlen (const ACE_WCHAR_T *s)
+{
+# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSLEN)
+ return ACE_OS::wcslen_emulation (s);
+# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSLEN */
+ return ::wcslen (s);
+# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSLEN */
+}
+
+ACE_INLINE char *
+ACE_OS::strncat (char *s, const char *t, size_t len)
+{
+#if 0 /* defined (ACE_HAS_TR24731_2005_CRT) */
+ strncat_s (s, len + 1, t, _TRUNCATE);
+ return s;
+#else
+ return ::strncat (s, t, len);
+#endif /* ACE_HAS_TR24731_2005_CRT */
+}
+
+ACE_INLINE ACE_WCHAR_T *
+ACE_OS::strncat (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len)
+{
+# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCAT)
+ return ACE_OS::wcsncat_emulation (s, t, len);
+# elif 0 /* defined (ACE_HAS_TR24731_2005_CRT) */
+ wcsncat_s (s, len + 1, t, _TRUNCATE);
+ return s;
+# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCAT */
+ return ::wcsncat (s, t, len);
+# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCAT */
+}
+
+ACE_INLINE char *
+ACE_OS::strnchr (char *s, int c, size_t len)
+{
+ return const_cast<char *> (ACE_OS::strnchr (static_cast<const char *> (s),
+ c,
+ len));
+}
+
+ACE_INLINE ACE_WCHAR_T *
+ACE_OS::strnchr (ACE_WCHAR_T *s, ACE_WCHAR_T c, size_t len)
+{
+ return
+ const_cast<ACE_WCHAR_T *> (ACE_OS::strnchr (
+ const_cast<const ACE_WCHAR_T *> (s),
+ c,
+ len));
+}
+
+ACE_INLINE int
+ACE_OS::strncmp (const char *s, const char *t, size_t len)
+{
+ return ::strncmp (s, t, len);
+}
+
+ACE_INLINE int
+ACE_OS::strncmp (const ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len)
+{
+# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCMP)
+ return ACE_OS::wcsncmp_emulation (s, t, len);
+# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCMP */
+ return ::wcsncmp (s, t, len);
+# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCMP */
+}
+
+ACE_INLINE char *
+ACE_OS::strncpy (char *s, const char *t, size_t len)
+{
+ return ::strncpy (s, t, len);
+}
+
+ACE_INLINE ACE_WCHAR_T *
+ACE_OS::strncpy (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len)
+{
+# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCPY)
+ return ACE_OS::wcsncpy_emulation (s, t, len);
+# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCPY */
+ return ::wcsncpy (s, t, len);
+# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCPY */
+}
+
+ACE_INLINE size_t
+ACE_OS::strnlen (const char *s, size_t maxlen)
+{
+#if defined (ACE_HAS_STRNLEN)
+ return ::strnlen (s, maxlen);
+#else /* ACE_HAS_STRNLEN */
+ size_t i;
+ for (i = 0; i < maxlen; ++i)
+ if (s[i] == '\0')
+ break;
+ return i;
+#endif /* ACE_HAS_STRNLEN */
+}
+
+ACE_INLINE size_t
+ACE_OS::strnlen (const ACE_WCHAR_T *s, size_t maxlen)
+{
+#if defined (ACE_HAS_WCHAR) && defined (ACE_HAS_WCSNLEN)
+ return wcsnlen (s, maxlen);
+#else /* ACE_HAS_WCSNLEN */
+ size_t i;
+ for (i = 0; i < maxlen; ++i)
+ if (s[i] == '\0')
+ break;
+ return i;
+#endif /* ACE_HAS_WCSNLEN */
+}
+
+ACE_INLINE char *
+ACE_OS::strnstr (char *s, const char *t, size_t len)
+{
+ return
+ const_cast <char *> (ACE_OS::strnstr (const_cast <const char *> (s), t, len));
+}
+
+ACE_INLINE ACE_WCHAR_T *
+ACE_OS::strnstr (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len)
+{
+ return
+ const_cast<ACE_WCHAR_T *> (ACE_OS::strnstr (
+ static_cast<const ACE_WCHAR_T *> (s),
+ t,
+ len));
+}
+
+ACE_INLINE const char *
+ACE_OS::strpbrk (const char *s1, const char *s2)
+{
+ return const_cast <const char *> (::strpbrk (s1, s2));
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE const wchar_t *
+ACE_OS::strpbrk (const wchar_t *s, const wchar_t *t)
+{
+# if defined (ACE_LACKS_WCSPBRK)
+ return ACE_OS::wcspbrk_emulation (s, t);
+# else /* ACE_LACKS_WCSPBRK */
+ return ::wcspbrk (s, t);
+# endif /* ACE_LACKS_WCSPBRK */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE char *
+ACE_OS::strpbrk (char *s1, const char *s2)
+{
+ return ::strpbrk (s1, s2);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::strpbrk (wchar_t *s, const wchar_t *t)
+{
+ return const_cast<wchar_t *> (ACE_OS::strpbrk (
+ const_cast<const wchar_t *> (s), t));
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE const char *
+ACE_OS::strrchr (const char *s, int c)
+{
+#if defined (ACE_LACKS_STRRCHR)
+ return ACE_OS::strrchr_emulation (s, c);
+#else /* ! ACE_LACKS_STRRCHR */
+ return (const char *) ::strrchr (s, c);
+#endif /* ! ACE_LACKS_STRRCHR */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE const wchar_t *
+ACE_OS::strrchr (const wchar_t *s, wchar_t c)
+{
+#if defined (ACE_LACKS_WCSRCHR)
+ return ACE_OS::wcsrchr_emulation (s, c);
+#else /* ! ACE_LACKS_WCSRCHR */
+ return const_cast <const wchar_t *> (::wcsrchr (s, c));
+#endif /* ! ACE_LACKS_WCSRCHR */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE char *
+ACE_OS::strrchr (char *s, int c)
+{
+#if defined (ACE_LACKS_STRRCHR)
+ return ACE_OS::strrchr_emulation (s, c);
+#else /* ! ACE_LACKS_STRRCHR */
+ return ::strrchr (s, c);
+#endif /* ! ACE_LACKS_STRRCHR */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::strrchr (wchar_t *s, wchar_t c)
+{
+ return const_cast<wchar_t *> (ACE_OS::strrchr (
+ const_cast<const wchar_t *> (s), c));
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE size_t
+ACE_OS::strspn (const char *s, const char *t)
+{
+ return ::strspn (s, t);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE size_t
+ACE_OS::strspn (const wchar_t *s, const wchar_t *t)
+{
+# if defined (ACE_LACKS_WCSSPN)
+ return ACE_OS::wcsspn_emulation (s, t);
+# else /* ACE_LACKS_WCSSPN */
+ return ::wcsspn (s, t);
+# endif /* ACE_LACKS_WCSSPN */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE const char *
+ACE_OS::strstr (const char *s, const char *t)
+{
+ return (const char *) ::strstr (s, t);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE const wchar_t *
+ACE_OS::strstr (const wchar_t *s, const wchar_t *t)
+{
+# if defined (ACE_LACKS_WCSSTR)
+ return ACE_OS::wcsstr_emulation (s, t);
+# elif defined (HPUX)
+ return const_cast <const wchar_t *> (::wcswcs (s, t));
+# else /* ACE_LACKS_WCSSTR */
+ return const_cast <const wchar_t *> (::wcsstr (s, t));
+# endif /* ACE_LACKS_WCSSTR */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE char *
+ACE_OS::strstr (char *s, const char *t)
+{
+ return ::strstr (s, t);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::strstr (wchar_t *s, const wchar_t *t)
+{
+# if defined (ACE_LACKS_WCSSTR)
+ return ACE_OS::wcsstr_emulation (s, t);
+# elif defined (HPUX)
+ return ::wcswcs (s, t);
+# else /* ACE_LACKS_WCSSTR */
+ return ::wcsstr (s, t);
+# endif /* ACE_LACKS_WCSSTR */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE char *
+ACE_OS::strtok (char *s, const char *tokens)
+{
+ return ::strtok (s, tokens);
+}
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOK)
+ACE_INLINE wchar_t *
+ACE_OS::strtok (wchar_t *s, const wchar_t *tokens)
+{
+#if defined (ACE_HAS_3_PARAM_WCSTOK)
+ static wchar_t *lasts = 0;
+ return ::wcstok (s, tokens, &lasts);
+#else
+ return ::wcstok (s, tokens);
+#endif /* ACE_HAS_3_PARAM_WCSTOK */
+}
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOK */
+
+ACE_INLINE char *
+ACE_OS::strtok_r (char *s, const char *tokens, char **lasts)
+{
+#if defined (ACE_HAS_TR24731_2005_CRT)
+ return strtok_s (s, tokens, lasts);
+#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (ACE_LACKS_STRTOK_R)
+ return ::strtok_r (s, tokens, lasts);
+#else
+ return ACE_OS::strtok_r_emulation (s, tokens, lasts);
+#endif /* (ACE_HAS_REENTRANT_FUNCTIONS) */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t*
+ACE_OS::strtok_r (ACE_WCHAR_T *s, const ACE_WCHAR_T *tokens, ACE_WCHAR_T **lasts)
+{
+#if defined (ACE_HAS_TR24731_2005_CRT)
+ return wcstok_s (s, tokens, lasts);
+#elif defined (ACE_LACKS_WCSTOK)
+ return ACE_OS::strtok_r_emulation (s, tokens, lasts);
+#else
+# if defined (ACE_HAS_3_PARAM_WCSTOK)
+ return ::wcstok (s, tokens, lasts);
+# else /* ACE_HAS_3_PARAM_WCSTOK */
+ *lasts = ::wcstok (s, tokens);
+ return *lasts;
+# endif /* ACE_HAS_3_PARAM_WCSTOK */
+#endif /* ACE_LACKS_WCSTOK */
+}
+#endif // ACE_HAS_WCHAR
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_strings.cpp b/ACE/ace/OS_NS_strings.cpp
new file mode 100644
index 00000000000..e7f4c80c462
--- /dev/null
+++ b/ACE/ace/OS_NS_strings.cpp
@@ -0,0 +1,84 @@
+// $Id$
+
+#include "ace/OS_NS_strings.h"
+
+ACE_RCSID(ace, OS_NS_strings, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_strings.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if defined (ACE_LACKS_STRCASECMP)
+# include "ace/OS_NS_ctype.h"
+#endif /* ACE_LACKS_STRCASECMP */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_LACKS_STRCASECMP)
+int
+ACE_OS::strcasecmp_emulation (const char *s, const char *t)
+{
+ const char *scan1 = s;
+ const char *scan2 = t;
+
+ while (*scan1 != 0
+ && ACE_OS::ace_tolower (*scan1)
+ == ACE_OS::ace_tolower (*scan2))
+ {
+ ++scan1;
+ ++scan2;
+ }
+
+ // The following case analysis is necessary so that characters which
+ // look negative collate low against normal characters but high
+ // against the end-of-string NUL.
+
+ if (*scan1 == '\0' && *scan2 == '\0')
+ return 0;
+ else if (*scan1 == '\0')
+ return -1;
+ else if (*scan2 == '\0')
+ return 1;
+ else
+ return ACE_OS::ace_tolower (*scan1) - ACE_OS::ace_tolower (*scan2);
+}
+#endif /* ACE_LACKS_STRCASECMP */
+
+#if defined (ACE_LACKS_STRCASECMP)
+int
+ACE_OS::strncasecmp_emulation (const char *s,
+ const char *t,
+ size_t len)
+{
+ const char *scan1 = s;
+ const char *scan2 = t;
+ size_t count = 0;
+
+ while (count++ < len
+ && *scan1 != 0
+ && ACE_OS::ace_tolower (*scan1)
+ == ACE_OS::ace_tolower (*scan2))
+ {
+ ++scan1;
+ ++scan2;
+ }
+
+ if (count > len)
+ return 0;
+
+ // The following case analysis is necessary so that characters which
+ // look negative collate low against normal characters but high
+ // against the end-of-string NUL.
+
+ if (*scan1 == '\0' && *scan2 == '\0')
+ return 0;
+ else if (*scan1 == '\0')
+ return -1;
+ else if (*scan2 == '\0')
+ return 1;
+ else
+ return ACE_OS::ace_tolower (*scan1) - ACE_OS::ace_tolower (*scan2);
+}
+#endif /* ACE_LACKS_STRCASECMP */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_strings.h b/ACE/ace/OS_NS_strings.h
new file mode 100644
index 00000000000..f2f3577997e
--- /dev/null
+++ b/ACE/ace/OS_NS_strings.h
@@ -0,0 +1,86 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_strings.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_STRINGS_H
+#define ACE_OS_NS_STRINGS_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/os_include/os_strings.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+namespace ACE_OS
+{
+
+ /// Compares two strings (case insensitive const char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int strcasecmp (const char *s, const char *t);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Compares two strings (case insensitive const wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int strcasecmp (const wchar_t *s, const wchar_t *t);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Compares two arrays (case insensitive const char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int strncasecmp (const char *s, const char *t, size_t len);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Compares two arrays (case insensitive const wchar_t version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int strncasecmp (const wchar_t *s, const wchar_t *t, size_t len);
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_LACKS_STRCASECMP)
+ /// Emulated strcasecmp - Performs a case insensitive comparison of strings.
+ extern ACE_Export
+ int strcasecmp_emulation (const char *s, const char *t);
+
+ /// Emulated strncasecmp - Performs a case insensitvie comparison of arrays.
+ extern ACE_Export
+ int strncasecmp_emulation (const char *s, const char *t, size_t len);
+#endif /* ACE_LACKS_STRCASECMP */
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_strings.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_STRINGS_H */
diff --git a/ACE/ace/OS_NS_strings.inl b/ACE/ace/OS_NS_strings.inl
new file mode 100644
index 00000000000..2b2012b2f38
--- /dev/null
+++ b/ACE/ace/OS_NS_strings.inl
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_WCHAR)
+# include "ace/OS_NS_wchar.h"
+#endif /* ACE_HAS_WCHAR */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::strcasecmp (const char *s, const char *t)
+{
+#if defined (ACE_LACKS_STRCASECMP)
+ return ACE_OS::strcasecmp_emulation (s, t);
+#elif defined (ACE_STRCASECMP_EQUIVALENT)
+ return ACE_STRCASECMP_EQUIVALENT (s, t);
+#else /* ACE_LACKS_STRCASECMP */
+ return ::strcasecmp (s, t);
+#endif /* ACE_LACKS_STRCASECMP */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::strcasecmp (const wchar_t *s, const wchar_t *t)
+{
+# if defined (ACE_LACKS_WCSICMP)
+ return ACE_OS::wcsicmp_emulation (s, t);
+# else /* ACE_LACKS_WCSICMP */
+ return ::_wcsicmp (s, t);
+# endif /* ACE_LACKS_WCSICMP */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::strncasecmp (const char *s, const char *t, size_t len)
+{
+#if defined (ACE_LACKS_STRCASECMP)
+ return ACE_OS::strncasecmp_emulation (s, t, len);
+#elif defined (ACE_STRNCASECMP_EQUIVALENT)
+ return ACE_STRNCASECMP_EQUIVALENT (s, t, len);
+#else /* ACE_LACKS_STRCASECMP */
+ return ::strncasecmp (s, t, len);
+#endif /* ACE_LACKS_STRCASECMP */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::strncasecmp (const wchar_t *s, const wchar_t *t, size_t len)
+{
+#if defined (ACE_LACKS_WCSNICMP)
+ return ACE_OS::wcsnicmp_emulation (s, t, len);
+#else /* ACE_LACKS_WCSNICMP */
+ return ::_wcsnicmp (s, t, len);
+#endif /* ACE_LACKS_WCSNICMP */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_stropts.cpp b/ACE/ace/OS_NS_stropts.cpp
new file mode 100644
index 00000000000..4bde7d4ae9c
--- /dev/null
+++ b/ACE/ace/OS_NS_stropts.cpp
@@ -0,0 +1,195 @@
+// $Id$
+
+#include "ace/OS_NS_stropts.h"
+
+ACE_RCSID(ace, OS_NS_stropts, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_stropts.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_OS::ioctl (ACE_HANDLE socket,
+ unsigned long io_control_code,
+ void *in_buffer_p,
+ unsigned long in_buffer,
+ void *out_buffer_p,
+ unsigned long out_buffer,
+ unsigned long *bytes_returned,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func)
+{
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ ACE_SOCKCALL_RETURN (::WSAIoctl ((ACE_SOCKET) socket,
+ io_control_code,
+ in_buffer_p,
+ in_buffer,
+ out_buffer_p,
+ out_buffer,
+ bytes_returned,
+ (WSAOVERLAPPED *) overlapped,
+ func),
+ int,
+ SOCKET_ERROR);
+# else
+ ACE_UNUSED_ARG (socket);
+ ACE_UNUSED_ARG (io_control_code);
+ ACE_UNUSED_ARG (in_buffer_p);
+ ACE_UNUSED_ARG (in_buffer);
+ ACE_UNUSED_ARG (out_buffer_p);
+ ACE_UNUSED_ARG (out_buffer);
+ ACE_UNUSED_ARG (bytes_returned);
+ ACE_UNUSED_ARG (overlapped);
+ ACE_UNUSED_ARG (func);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_WINSOCK2 */
+}
+
+#if !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500))
+int
+ACE_OS::ioctl (ACE_HANDLE socket,
+ unsigned long io_control_code,
+ ACE_QoS &ace_qos,
+ unsigned long *bytes_returned,
+ void *buffer_p,
+ unsigned long buffer,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func)
+{
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+
+ QOS qos;
+ unsigned long qos_len = sizeof (QOS);
+
+ if (io_control_code == SIO_SET_QOS)
+ {
+ qos.SendingFlowspec = *(ace_qos.sending_flowspec ());
+ qos.ReceivingFlowspec = *(ace_qos.receiving_flowspec ());
+ qos.ProviderSpecific = (WSABUF) ace_qos.provider_specific ();
+
+ qos_len += ace_qos.provider_specific ().iov_len;
+
+ ACE_SOCKCALL_RETURN (::WSAIoctl ((ACE_SOCKET) socket,
+ io_control_code,
+ &qos,
+ qos_len,
+ buffer_p,
+ buffer,
+ bytes_returned,
+ (WSAOVERLAPPED *) overlapped,
+ func),
+ int,
+ SOCKET_ERROR);
+ }
+ else
+ {
+ unsigned long dwBufferLen = 0;
+
+ // Query for the buffer size.
+ int result = ::WSAIoctl ((ACE_SOCKET) socket,
+ io_control_code,
+ 0,
+ 0,
+ &dwBufferLen,
+ sizeof (dwBufferLen),
+ bytes_returned,
+ 0,
+ 0);
+
+
+ if (result == SOCKET_ERROR)
+ {
+ unsigned long dwErr = ::WSAGetLastError ();
+
+ if (dwErr == WSAEWOULDBLOCK)
+ {
+ errno = dwErr;
+ return -1;
+ }
+ else
+ if (dwErr != WSAENOBUFS)
+ {
+ errno = dwErr;
+ return -1;
+ }
+ }
+
+ char *qos_buf = 0;
+ ACE_NEW_RETURN (qos_buf,
+ char [dwBufferLen],
+ -1);
+
+ QOS *qos = reinterpret_cast<QOS*> (qos_buf);
+
+ result = ::WSAIoctl ((ACE_SOCKET) socket,
+ io_control_code,
+ 0,
+ 0,
+ qos,
+ dwBufferLen,
+ bytes_returned,
+ 0,
+ 0);
+
+ if (result == SOCKET_ERROR)
+ return result;
+
+ ACE_Flow_Spec sending_flowspec (qos->SendingFlowspec.TokenRate,
+ qos->SendingFlowspec.TokenBucketSize,
+ qos->SendingFlowspec.PeakBandwidth,
+ qos->SendingFlowspec.Latency,
+ qos->SendingFlowspec.DelayVariation,
+# if defined(ACE_HAS_WINSOCK2_GQOS)
+ qos->SendingFlowspec.ServiceType,
+ qos->SendingFlowspec.MaxSduSize,
+ qos->SendingFlowspec.MinimumPolicedSize,
+# else /* ACE_HAS_WINSOCK2_GQOS */
+ 0,
+ 0,
+ 0,
+# endif /* ACE_HAS_WINSOCK2_GQOS */
+ 0,
+ 0);
+
+ ACE_Flow_Spec receiving_flowspec (qos->ReceivingFlowspec.TokenRate,
+ qos->ReceivingFlowspec.TokenBucketSize,
+ qos->ReceivingFlowspec.PeakBandwidth,
+ qos->ReceivingFlowspec.Latency,
+ qos->ReceivingFlowspec.DelayVariation,
+# if defined(ACE_HAS_WINSOCK2_GQOS)
+ qos->ReceivingFlowspec.ServiceType,
+ qos->ReceivingFlowspec.MaxSduSize,
+ qos->ReceivingFlowspec.MinimumPolicedSize,
+# else /* ACE_HAS_WINSOCK2_GQOS */
+ 0,
+ 0,
+ 0,
+# endif /* ACE_HAS_WINSOCK2_GQOS */
+ 0,
+ 0);
+
+ ace_qos.sending_flowspec (&sending_flowspec);
+ ace_qos.receiving_flowspec (&receiving_flowspec);
+ ace_qos.provider_specific (*((struct iovec *) (&qos->ProviderSpecific)));
+
+
+ return result;
+ }
+
+# else
+ ACE_UNUSED_ARG (socket);
+ ACE_UNUSED_ARG (io_control_code);
+ ACE_UNUSED_ARG (ace_qos);
+ ACE_UNUSED_ARG (bytes_returned);
+ ACE_UNUSED_ARG (buffer_p);
+ ACE_UNUSED_ARG (buffer);
+ ACE_UNUSED_ARG (overlapped);
+ ACE_UNUSED_ARG (func);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_WINSOCK2 */
+}
+#endif /* !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500)) */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_stropts.h b/ACE/ace/OS_NS_stropts.h
new file mode 100644
index 00000000000..f713801f80c
--- /dev/null
+++ b/ACE/ace/OS_NS_stropts.h
@@ -0,0 +1,172 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_stropts.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_STROPTS_H
+#define ACE_OS_NS_STROPTS_H
+
+# include /**/ "ace/pre.h"
+
+# include "ace/config-all.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+# ifndef ACE_IOCTL_TYPE_ARG2
+# define ACE_IOCTL_TYPE_ARG2 int
+# endif
+
+#include "ace/os_include/os_stropts.h"
+#include "ace/os_include/os_stdio.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+typedef WSAPROTOCOL_INFO ACE_Protocol_Info;
+
+// Callback function that's used by the QoS-enabled <ACE_OS::ioctl>
+// method.
+typedef LPWSAOVERLAPPED_COMPLETION_ROUTINE ACE_OVERLAPPED_COMPLETION_FUNC;
+typedef GROUP ACE_SOCK_GROUP;
+#else /* (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
+struct ACE_Protocol_Info
+{
+ unsigned long dwServiceFlags1;
+ int iAddressFamily;
+ int iProtocol;
+ char szProtocol[255+1];
+};
+
+// Callback function that's used by the QoS-enabled <ACE_OS::ioctl>
+// method.
+typedef void (*ACE_OVERLAPPED_COMPLETION_FUNC) (unsigned long error,
+ unsigned long bytes_transferred,
+ ACE_OVERLAPPED *overlapped,
+ unsigned long flags);
+typedef unsigned long ACE_SOCK_GROUP;
+
+#endif /* (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
+
+// @todo: move this to it's own file... dhinton
+/**
+ * @class ACE_Str_Buf
+ *
+ * @brief Simple wrapper for STREAM pipes strbuf.
+ */
+class ACE_Export ACE_Str_Buf : public strbuf
+{
+public:
+ // = Initialization method
+ /// Constructor.
+ ACE_Str_Buf (void *b = 0, int l = 0, int max = 0);
+
+ /// Constructor.
+ ACE_Str_Buf (strbuf &);
+};
+
+class ACE_QoS;
+
+namespace ACE_OS {
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getmsg (ACE_HANDLE handle,
+ struct strbuf *ctl,
+ struct strbuf
+ *data, int *flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getpmsg (ACE_HANDLE handle,
+ struct strbuf *ctl,
+ struct strbuf
+ *data,
+ int *band,
+ int *flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fattach (int handle,
+ const char *path);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fdetach (const char *file);
+
+ /// UNIX-style <ioctl>.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ioctl (ACE_HANDLE handle,
+ ACE_IOCTL_TYPE_ARG2 cmd,
+ void * = 0);
+
+ /// QoS-enabled <ioctl>.
+ extern ACE_Export
+ int ioctl (ACE_HANDLE socket,
+ unsigned long io_control_code,
+ void *in_buffer_p,
+ unsigned long in_buffer,
+ void *out_buffer_p,
+ unsigned long out_buffer,
+ unsigned long *bytes_returned,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func);
+
+#if !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500))
+ /// QoS-enabled <ioctl> when the I/O control code is either
+ /// SIO_SET_QOS or SIO_GET_QOS.
+ extern ACE_Export
+ int ioctl (ACE_HANDLE socket,
+ unsigned long io_control_code,
+ ACE_QoS &ace_qos,
+ unsigned long *bytes_returned,
+ void *buffer_p = 0,
+ unsigned long buffer = 0,
+ ACE_OVERLAPPED *overlapped = 0,
+ ACE_OVERLAPPED_COMPLETION_FUNC func = 0);
+#endif /* !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500)) */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int isastream (ACE_HANDLE handle);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int putmsg (ACE_HANDLE handle,
+ const struct strbuf *ctl,
+ const struct strbuf *data,
+ int flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int putpmsg (ACE_HANDLE handle,
+ const struct strbuf *ctl,
+ const struct strbuf *data,
+ int band,
+ int flags);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_stropts.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_STROPTS_H */
diff --git a/ACE/ace/OS_NS_stropts.inl b/ACE/ace/OS_NS_stropts.inl
new file mode 100644
index 00000000000..e6feea48f1d
--- /dev/null
+++ b/ACE/ace/OS_NS_stropts.inl
@@ -0,0 +1,201 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/os_include/os_errno.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_macros.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_QoS.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_LACKS_CONST_STRBUF_PTR)
+typedef struct strbuf *ACE_STRBUF_TYPE;
+#else
+typedef const struct strbuf *ACE_STRBUF_TYPE;
+#endif /* ACE_LACKS_CONST_STRBUF_PTR */
+
+ACE_INLINE
+ACE_Str_Buf::ACE_Str_Buf (void *b, int l, int max)
+{
+ this->maxlen = max;
+ this->len = l;
+ this->buf = (char *) b;
+}
+
+ACE_INLINE
+ACE_Str_Buf::ACE_Str_Buf (strbuf &sb)
+{
+ this->maxlen = sb.maxlen;
+ this->len = sb.len;
+ this->buf = sb.buf;
+}
+
+/*****************************************************************************/
+
+ACE_INLINE int
+ACE_OS::getmsg (ACE_HANDLE handle,
+ struct strbuf *ctl,
+ struct strbuf *data,
+ int *flags)
+{
+ ACE_OS_TRACE ("ACE_OS::getmsg");
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_OSCALL_RETURN (::getmsg (handle, ctl, data, flags), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (ctl);
+ ACE_UNUSED_ARG (data);
+ ACE_UNUSED_ARG (flags);
+
+ // I'm not sure how to implement this correctly.
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_INLINE int
+ACE_OS::getpmsg (ACE_HANDLE handle,
+ struct strbuf *ctl,
+ struct strbuf *data,
+ int *band,
+ int *flags)
+{
+ ACE_OS_TRACE ("ACE_OS::getpmsg");
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_OSCALL_RETURN (::getpmsg (handle, ctl, data, band, flags), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (ctl);
+ ACE_UNUSED_ARG (data);
+ ACE_UNUSED_ARG (band);
+ ACE_UNUSED_ARG (flags);
+
+ // I'm not sure how to implement this correctly.
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_INLINE int
+ACE_OS::fattach (int handle, const char *path)
+{
+ ACE_OS_TRACE ("ACE_OS::fattach");
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_OSCALL_RETURN (::fattach (handle, path), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (path);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_INLINE int
+ACE_OS::fdetach (const char *file)
+{
+ ACE_OS_TRACE ("ACE_OS::fdetach");
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_OSCALL_RETURN (::fdetach (file), int, -1);
+#else
+ ACE_UNUSED_ARG (file);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_INLINE int
+ACE_OS::ioctl (ACE_HANDLE handle,
+ ACE_IOCTL_TYPE_ARG2 cmd,
+ void *val)
+{
+ ACE_OS_TRACE ("ACE_OS::ioctl");
+
+#if defined (ACE_WIN32)
+ ACE_SOCKET sock = (ACE_SOCKET) handle;
+ ACE_SOCKCALL_RETURN (::ioctlsocket (sock, cmd, reinterpret_cast<unsigned long *> (val)), int, -1);
+#elif defined (ACE_HAS_IOCTL_INT_3_PARAM)
+ ACE_OSCALL_RETURN (::ioctl (handle, cmd, reinterpret_cast<int> (val)),
+ int, -1);
+#else
+ ACE_OSCALL_RETURN (::ioctl (handle, cmd, val), int, -1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_OS::isastream (ACE_HANDLE handle)
+{
+ ACE_OS_TRACE ("ACE_OS::isastream");
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_OSCALL_RETURN (::isastream (handle), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_INLINE int
+ACE_OS::putmsg (ACE_HANDLE handle, const struct strbuf *ctl,
+ const struct strbuf *data, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::putmsg");
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_OSCALL_RETURN (::putmsg (handle,
+ (ACE_STRBUF_TYPE) ctl,
+ (ACE_STRBUF_TYPE) data,
+ flags), int, -1);
+#else
+ ACE_UNUSED_ARG (flags);
+ ssize_t result;
+ if (ctl == 0 && data == 0)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+ // Handle the two easy cases.
+ else if (ctl != 0)
+ {
+ result = ACE_OS::write (handle, ctl->buf, ctl->len);
+ return static_cast<int> (result);
+ }
+ else if (data != 0)
+ {
+ result = ACE_OS::write (handle, data->buf, data->len);
+ return static_cast<int> (result);
+ }
+ else
+ {
+ // This is the hard case.
+ char *buf;
+ ACE_NEW_RETURN (buf, char [ctl->len + data->len], -1);
+ ACE_OS::memcpy (buf, ctl->buf, ctl->len);
+ ACE_OS::memcpy (buf + ctl->len, data->buf, data->len);
+ result = ACE_OS::write (handle, buf, ctl->len + data->len);
+ delete [] buf;
+ return static_cast<int> (result);
+ }
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_INLINE int
+ACE_OS::putpmsg (ACE_HANDLE handle,
+ const struct strbuf *ctl,
+ const struct strbuf *data,
+ int band,
+ int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::putpmsg");
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_OSCALL_RETURN (::putpmsg (handle,
+ (ACE_STRBUF_TYPE) ctl,
+ (ACE_STRBUF_TYPE) data,
+ band, flags), int, -1);
+#else
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (band);
+ return ACE_OS::putmsg (handle, ctl, data, flags);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_mman.cpp b/ACE/ace/OS_NS_sys_mman.cpp
new file mode 100644
index 00000000000..245f670fd27
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_mman.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_sys_mman.h"
+
+ACE_RCSID(ace, OS_NS_sys_mman, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_mman.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_sys_mman.h b/ACE/ace/OS_NS_sys_mman.h
new file mode 100644
index 00000000000..be2ca3e7294
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_mman.h
@@ -0,0 +1,97 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_mman.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_MMAN_H
+# define ACE_OS_NS_SYS_MMAN_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/Global_Macros.h"
+#include "ace/os_include/sys/os_types.h"
+#include "ace/os_include/sys/os_mman.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ //@{ @name A set of wrappers for memory mapped files.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int madvise (caddr_t addr,
+ size_t len,
+ int map_advice);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *mmap (void *addr,
+ size_t len,
+ int prot,
+ int flags,
+ ACE_HANDLE handle,
+ ACE_OFF_T off = 0,
+ ACE_HANDLE *file_mapping = 0,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ const ACE_TCHAR *file_mapping_name = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int mprotect (void *addr,
+ size_t len,
+ int prot);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int msync (void *addr,
+ size_t len,
+ int sync);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int munmap (void *addr,
+ size_t len);
+ //@}
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE shm_open (const ACE_TCHAR *filename,
+ int mode,
+ mode_t perms = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int shm_unlink (const ACE_TCHAR *path);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_mman.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_MMAN_H */
diff --git a/ACE/ace/OS_NS_sys_mman.inl b/ACE/ace/OS_NS_sys_mman.inl
new file mode 100644
index 00000000000..9846eba43e0
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_mman.inl
@@ -0,0 +1,302 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_macros.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_VOIDPTR_MMAP)
+// Needed for some odd OS's (e.g., SGI).
+typedef void *ACE_MMAP_TYPE;
+#else
+typedef char *ACE_MMAP_TYPE;
+#endif /* ACE_HAS_VOIDPTR_MMAP */
+
+ACE_INLINE int
+ACE_OS::madvise (caddr_t addr, size_t len, int map_advice)
+{
+ ACE_OS_TRACE ("ACE_OS::madvise");
+#if !defined (ACE_LACKS_MADVISE)
+ ACE_OSCALL_RETURN (::madvise (addr, len, map_advice), int, -1);
+#else
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (map_advice);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE void *
+ACE_OS::mmap (void *addr,
+ size_t len,
+ int prot,
+ int flags,
+ ACE_HANDLE file_handle,
+ ACE_OFF_T off,
+ ACE_HANDLE *file_mapping,
+ LPSECURITY_ATTRIBUTES sa,
+ const ACE_TCHAR *file_mapping_name)
+{
+ ACE_OS_TRACE ("ACE_OS::mmap");
+#if !defined (ACE_WIN32) || defined (ACE_HAS_PHARLAP)
+ ACE_UNUSED_ARG (file_mapping_name);
+#endif /* !defined (ACE_WIN32) || defined (ACE_HAS_PHARLAP) */
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+
+# if defined(ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (addr);
+ if (ACE_BIT_ENABLED (flags, MAP_FIXED)) // not supported
+ {
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+# else
+ if (!ACE_BIT_ENABLED (flags, MAP_FIXED))
+ addr = 0;
+ else if (addr == 0) // can not map to address 0
+ {
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+# endif
+
+ int nt_flags = 0;
+ ACE_HANDLE local_handle = ACE_INVALID_HANDLE;
+
+ // Ensure that file_mapping is non-zero.
+ if (file_mapping == 0)
+ file_mapping = &local_handle;
+
+ if (ACE_BIT_ENABLED (flags, MAP_PRIVATE))
+ {
+# if !defined(ACE_HAS_WINCE)
+ prot = PAGE_WRITECOPY;
+# endif // ACE_HAS_WINCE
+ nt_flags = FILE_MAP_COPY;
+ }
+ else if (ACE_BIT_ENABLED (flags, MAP_SHARED))
+ {
+ if (ACE_BIT_ENABLED (prot, PAGE_READONLY))
+ nt_flags = FILE_MAP_READ;
+ if (ACE_BIT_ENABLED (prot, PAGE_READWRITE))
+ nt_flags = FILE_MAP_WRITE;
+ }
+
+ // Only create a new handle if we didn't have a valid one passed in.
+ if (*file_mapping == ACE_INVALID_HANDLE)
+ {
+ SECURITY_ATTRIBUTES sa_buffer;
+ SECURITY_DESCRIPTOR sd_buffer;
+ const LPSECURITY_ATTRIBUTES attr =
+ ACE_OS::default_win32_security_attributes_r (sa,
+ &sa_buffer,
+ &sd_buffer);
+
+ *file_mapping = ACE_TEXT_CreateFileMapping (file_handle,
+ attr,
+ prot,
+ 0,
+ 0,
+ file_mapping_name);
+ }
+
+ if (*file_mapping == 0)
+ ACE_FAIL_RETURN (MAP_FAILED);
+
+# if defined (ACE_OS_EXTRA_MMAP_FLAGS)
+ nt_flags |= ACE_OS_EXTRA_MMAP_FLAGS;
+# endif /* ACE_OS_EXTRA_MMAP_FLAGS */
+
+ DWORD low_off = ACE_LOW_PART (off);
+ DWORD high_off = ACE_HIGH_PART (off);
+
+# if !defined (ACE_HAS_WINCE)
+ void *addr_mapping = ::MapViewOfFileEx (*file_mapping,
+ nt_flags,
+ high_off,
+ low_off,
+ len,
+ addr);
+# else
+ void *addr_mapping = ::MapViewOfFile (*file_mapping,
+ nt_flags,
+ high_off,
+ low_off,
+ len);
+# endif /* ! ACE_HAS_WINCE */
+
+ // Only close this down if we used the temporary.
+ if (file_mapping == &local_handle)
+ ::CloseHandle (*file_mapping);
+
+ if (addr_mapping == 0)
+ ACE_FAIL_RETURN (MAP_FAILED);
+ else
+ return addr_mapping;
+#elif !defined (ACE_LACKS_MMAP)
+ ACE_UNUSED_ARG (sa);
+
+# if defined (ACE_OS_EXTRA_MMAP_FLAGS)
+ flags |= ACE_OS_EXTRA_MMAP_FLAGS;
+# endif /* ACE_OS_EXTRA_MMAP_FLAGS */
+ ACE_UNUSED_ARG (file_mapping);
+# if defined (ACE_OPENVMS)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ::fsync(file_handle);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN ((void *) ::mmap ((ACE_MMAP_TYPE) addr,
+ len,
+ prot,
+ flags,
+ file_handle,
+ off),
+ void *, MAP_FAILED);
+ //FUZZ: enable check_for_lack_ACE_OS
+#else
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (prot);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (file_handle);
+ ACE_UNUSED_ARG (off);
+ ACE_UNUSED_ARG (file_mapping);
+ ACE_UNUSED_ARG (sa);
+ ACE_NOTSUP_RETURN (MAP_FAILED);
+#endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */
+}
+
+// Implements simple read/write control for pages. Affects a page if
+// part of the page is referenced. Currently PROT_READ, PROT_WRITE,
+// and PROT_RDWR has been mapped in OS.h. This needn't have anything
+// to do with a mmap region.
+
+ACE_INLINE int
+ACE_OS::mprotect (void *addr, size_t len, int prot)
+{
+ ACE_OS_TRACE ("ACE_OS::mprotect");
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+ DWORD dummy; // Sigh!
+ return ::VirtualProtect(addr, len, prot, &dummy) ? 0 : -1;
+#elif !defined (ACE_LACKS_MPROTECT)
+ ACE_OSCALL_RETURN (::mprotect ((ACE_MMAP_TYPE) addr, len, prot), int, -1);
+#else
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (prot);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */
+}
+
+ACE_INLINE int
+ACE_OS::msync (void *addr, size_t len, int sync)
+{
+ ACE_OS_TRACE ("ACE_OS::msync");
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+ ACE_UNUSED_ARG (sync);
+
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::FlushViewOfFile (addr, len), ace_result_), int, -1);
+#elif !defined (ACE_LACKS_MSYNC)
+# if !defined (ACE_HAS_BROKEN_NETBSD_MSYNC)
+ ACE_OSCALL_RETURN (::msync ((ACE_MMAP_TYPE) addr, len, sync), int, -1);
+# else
+ ACE_OSCALL_RETURN (::msync ((ACE_MMAP_TYPE) addr, len), int, -1);
+ ACE_UNUSED_ARG (sync);
+# endif /* ACE_HAS_BROKEN_NETBSD_MSYNC */
+#else
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (sync);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */
+}
+
+ACE_INLINE int
+ACE_OS::munmap (void *addr, size_t len)
+{
+ ACE_OS_TRACE ("ACE_OS::munmap");
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (len);
+
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::UnmapViewOfFile (addr), ace_result_), int, -1);
+#elif !defined (ACE_LACKS_MMAP)
+ ACE_OSCALL_RETURN (::munmap ((ACE_MMAP_TYPE) addr, len), int, -1);
+#else
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (len);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_OS::shm_open (const ACE_TCHAR *filename,
+ int mode,
+ mode_t perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_OS_TRACE ("ACE_OS::shm_open");
+#if defined (ACE_HAS_SHM_OPEN)
+ ACE_UNUSED_ARG (sa);
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x650)
+ // With VxWorks the file should just start with / and no other
+ // slashes, so replace all other / by _
+ ACE_TCHAR buf [MAXPATHLEN + 1];
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("%s"),
+ filename);
+ for (size_t i = 1; i < MAXPATHLEN + 1; i++)
+ {
+ if (buf[i] == '/')
+ {
+ buf[i] = '_';
+ }
+ }
+ filename = buf;
+#endif
+ ACE_OSCALL_RETURN (::shm_open (ACE_TEXT_ALWAYS_CHAR(filename), mode, perms), ACE_HANDLE, ACE_INVALID_HANDLE);
+#elif defined (ACE_OPENVMS)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (::open (filename, mode, perms, ACE_TEXT("shr=get,put,upd")), ACE_HANDLE, ACE_INVALID_HANDLE);
+ //FUZZ: enable check_for_lack_ACE_OS
+#else /* ! ACE_HAS_SHM_OPEN */
+ // Just use ::open.
+ return ACE_OS::open (filename, mode, perms, sa);
+#endif /* ACE_HAS_SHM_OPEN */
+}
+
+ACE_INLINE int
+ACE_OS::shm_unlink (const ACE_TCHAR *path)
+{
+ ACE_OS_TRACE ("ACE_OS::shm_unlink");
+#if defined (ACE_HAS_SHM_OPEN)
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x650)
+ // With VxWorks the file should just start with / and no other
+ // slashes, so replace all other / by _
+ ACE_TCHAR buf [MAXPATHLEN + 1];
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("%s"),
+ path);
+ for (size_t i = 1; i < MAXPATHLEN + 1; i++)
+ {
+ if (buf[i] == '/')
+ {
+ buf[i] = '_';
+ }
+ }
+ path = buf;
+#endif
+ ACE_OSCALL_RETURN (::shm_unlink (ACE_TEXT_ALWAYS_CHAR(path)), int, -1);
+#else /* ! ACE_HAS_SHM_OPEN */
+ // Just use ::unlink.
+ return ACE_OS::unlink (path);
+#endif /* ACE_HAS_SHM_OPEN */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_msg.cpp b/ACE/ace/OS_NS_sys_msg.cpp
new file mode 100644
index 00000000000..77d3caa7b17
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_msg.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_sys_msg.h"
+
+ACE_RCSID(ace, OS_NS_sys_msg, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_msg.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_sys_msg.h b/ACE/ace/OS_NS_sys_msg.h
new file mode 100644
index 00000000000..3ad88fd1c2e
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_msg.h
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_msg.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_MSG_H
+# define ACE_OS_NS_SYS_MSG_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/os_include/sys/os_msg.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ //@{ @name A set of wrappers for System V message queues.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int msgctl (int msqid,
+ int cmd,
+ struct msqid_ds *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int msgget (key_t key,
+ int msgflg);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t msgrcv (int int_id,
+ void *buf,
+ size_t len,
+ long type,
+ int flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int msgsnd (int int_id,
+ const void *buf,
+ size_t len,
+ int flags);
+ //@}
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_msg.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_MSG_H */
diff --git a/ACE/ace/OS_NS_sys_msg.inl b/ACE/ace/OS_NS_sys_msg.inl
new file mode 100644
index 00000000000..129b4c389c1
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_msg.inl
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::msgctl (int msqid, int cmd, struct msqid_ds *val)
+{
+ ACE_OS_TRACE ("ACE_OS::msgctl");
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_OSCALL_RETURN (::msgctl (msqid, cmd, val), int, -1);
+#else
+ ACE_UNUSED_ARG (msqid);
+ ACE_UNUSED_ARG (cmd);
+ ACE_UNUSED_ARG (val);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE int
+ACE_OS::msgget (key_t key, int msgflg)
+{
+ ACE_OS_TRACE ("ACE_OS::msgget");
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_OSCALL_RETURN (::msgget (key, msgflg), int, -1);
+#else
+ ACE_UNUSED_ARG (key);
+ ACE_UNUSED_ARG (msgflg);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::msgrcv (int int_id, void *buf, size_t len,
+ long type, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::msgrcv");
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_OSCALL_RETURN (::msgrcv (int_id, buf, len, type, flags),
+ int, -1);
+#else
+ ACE_UNUSED_ARG (int_id);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (flags);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE int
+ACE_OS::msgsnd (int int_id, const void *buf, size_t len, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::msgsnd");
+#if defined (ACE_HAS_SYSV_IPC)
+# if defined (ACE_HAS_NONCONST_MSGSND)
+ ACE_OSCALL_RETURN (::msgsnd (int_id,
+ const_cast<void *> (buf), len, flags), int, -1);
+# else
+ ACE_OSCALL_RETURN (::msgsnd (int_id, buf, len, flags), int, -1);
+# endif /* ACE_HAS_NONCONST_MSGSND */
+#else
+ ACE_UNUSED_ARG (int_id);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (flags);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_resource.cpp b/ACE/ace/OS_NS_sys_resource.cpp
new file mode 100644
index 00000000000..7f50303e8e5
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_resource.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_sys_resource.h"
+
+ACE_RCSID(ace, OS_NS_sys_resource, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_resource.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_sys_resource.h b/ACE/ace/OS_NS_sys_resource.h
new file mode 100644
index 00000000000..9811db79326
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_resource.h
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_resource.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_RESOURCE_H
+# define ACE_OS_NS_SYS_RESOURCE_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/os_include/sys/os_resource.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getrlimit (int resource,
+ struct rlimit *rl);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getrusage (int who,
+ struct rusage *rusage);
+
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int setrlimit (int resource,
+ const struct rlimit *rl);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_resource.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_RESOURCE_H */
diff --git a/ACE/ace/OS_NS_sys_resource.inl b/ACE/ace/OS_NS_sys_resource.inl
new file mode 100644
index 00000000000..510923300a8
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_resource.inl
@@ -0,0 +1,98 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::getrlimit (int resource, struct rlimit *rl)
+{
+ ACE_OS_TRACE ("ACE_OS::getrlimit");
+
+#if defined (ACE_LACKS_RLIMIT)
+ ACE_UNUSED_ARG (resource);
+ ACE_UNUSED_ARG (rl);
+
+ ACE_NOTSUP_RETURN (-1);
+#else
+# if defined (ACE_HAS_RLIMIT_RESOURCE_ENUM)
+ ACE_OSCALL_RETURN (::getrlimit ((ACE_HAS_RLIMIT_RESOURCE_ENUM) resource, rl), int, -1);
+# else
+ ACE_OSCALL_RETURN (::getrlimit (resource, rl), int, -1);
+# endif /* ACE_HAS_RLIMIT_RESOURCE_ENUM */
+#endif /* ACE_LACKS_RLIMIT */
+}
+
+ACE_INLINE int
+ACE_OS::getrusage (int who, struct rusage *ru)
+{
+ ACE_OS_TRACE ("ACE_OS::getrusage");
+
+#if defined (ACE_HAS_GETRUSAGE)
+# if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (who);
+
+# if defined (ACE_LACKS_GETPROCESSTIMES)
+ ACE_UNUSED_ARG (ru);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ FILETIME dummy_1;
+ FILETIME dummy_2;
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::GetProcessTimes (::GetCurrentProcess(),
+ &dummy_1, // start
+ &dummy_2, // exited
+ &ru->ru_stime,
+ &ru->ru_utime),
+ ace_result_),
+ int, -1);
+# endif /* ACE_LACKS_WIN32_GETPROCESSTIMES */
+# else
+# if defined (ACE_HAS_RUSAGE_WHO_ENUM)
+ ACE_OSCALL_RETURN (::getrusage ((ACE_HAS_RUSAGE_WHO_ENUM) who, ru), int, -1);
+# else
+ ACE_OSCALL_RETURN (::getrusage (who, ru), int, -1);
+# endif /* ACE_HAS_RUSAGE_WHO_ENUM */
+# endif /* ACE_WIN32 */
+#else
+ ACE_UNUSED_ARG (who);
+ ACE_UNUSED_ARG (ru);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_GETRUSAGE */
+}
+
+ACE_INLINE int
+ACE_OS::setrlimit (int resource, const struct rlimit *rl)
+{
+ ACE_OS_TRACE ("ACE_OS::setrlimit");
+
+#if defined (ACE_LACKS_RLIMIT)
+ ACE_UNUSED_ARG (resource);
+ ACE_UNUSED_ARG (rl);
+
+ ACE_NOTSUP_RETURN (-1);
+#else
+# if defined (ACE_HAS_RLIMIT_RESOURCE_ENUM)
+# if defined (ACE_HAS_NONCONST_SETRLIMIT)
+ ACE_OSCALL_RETURN (::setrlimit ((ACE_HAS_RLIMIT_RESOURCE_ENUM) resource,
+ const_cast<struct rlimit *>(rl)
+ ), int, -1);
+# else
+ ACE_OSCALL_RETURN (::setrlimit ((ACE_HAS_RLIMIT_RESOURCE_ENUM) resource,
+ rl
+ ), int, -1);
+# endif /* ACE_HAS_NONCONST_SETRLIMIT */
+# else /* ACE_HAS_RLIMIT_RESOURCE_ENUM */
+# if defined (ACE_HAS_NONCONST_SETRLIMIT)
+ ACE_OSCALL_RETURN (::setrlimit (resource, const_cast<struct rlimit *>(rl)
+ ), int, -1);
+# else
+ ACE_OSCALL_RETURN (::setrlimit (resource, rl), int, -1);
+# endif /* ACE_HAS_NONCONST_SETRLIMIT */
+# endif /* ACE_HAS_RLIMIT_RESOURCE_ENUM */
+#endif /* ACE_LACKS_RLIMIT */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_select.cpp b/ACE/ace/OS_NS_sys_select.cpp
new file mode 100644
index 00000000000..fea3f79ee63
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_select.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_sys_select.h"
+
+ACE_RCSID(ace, OS_NS_sys_select, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_select.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_sys_select.h b/ACE/ace/OS_NS_sys_select.h
new file mode 100644
index 00000000000..a8118f5fddf
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_select.h
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_select.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_SELECT_H
+# define ACE_OS_NS_SYS_SELECT_H
+
+# include /**/ "ace/pre.h"
+
+# include "ace/config-all.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// The following is needed for Mac OSX 10.2 (Jaguar). Mac OSX 10.3 (Panther)
+// doesn't seem to have this issue.
+
+#if defined (ACE_SYS_SELECT_NEEDS_UNISTD_H)
+ #include "ace/OS_NS_unistd.h"
+#endif
+
+#include "ace/os_include/sys/os_select.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+namespace ACE_OS
+{
+ // Should be moved to cpp or inl.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int select (int width,
+ fd_set *rfds,
+ fd_set *wfds = 0,
+ fd_set *efds = 0,
+ const ACE_Time_Value *tv = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int select (int width,
+ fd_set *rfds,
+ fd_set *wfds,
+ fd_set *efds,
+ const ACE_Time_Value &tv);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_select.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_SELECT_H */
diff --git a/ACE/ace/OS_NS_sys_select.inl b/ACE/ace/OS_NS_sys_select.inl
new file mode 100644
index 00000000000..d905837d992
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_select.inl
@@ -0,0 +1,80 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_macros.h"
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// It would be really cool to add another version of select that would
+// function like the one we're defending against below!
+ACE_INLINE int
+ACE_OS::select (int width,
+ fd_set *rfds, fd_set *wfds, fd_set *efds,
+ const ACE_Time_Value *timeout)
+{
+ ACE_OS_TRACE ("ACE_OS::select");
+#if defined (ACE_HAS_NONCONST_SELECT_TIMEVAL)
+ // We must defend against non-conformity!
+ timeval copy;
+ timeval *timep = 0;
+
+ if (timeout != 0)
+ {
+ copy = *timeout;
+ timep = &copy;
+ }
+ else
+ timep = 0;
+#else
+ const timeval *timep = (timeout == 0 ? (const timeval *)0 : *timeout);
+#endif /* ACE_HAS_NONCONST_SELECT_TIMEVAL */
+#if defined (ACE_LACKS_SELECT)
+ ACE_UNUSED_ARG (width);
+ ACE_UNUSED_ARG (rfds);
+ ACE_UNUSED_ARG (wfds);
+ ACE_UNUSED_ARG (efds);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined(ACE_TANDEM_T1248_PTHREADS)
+ ACE_SOCKCALL_RETURN (::spt_select (width, rfds, wfds, efds, timep),
+ int, -1);
+#else
+ ACE_SOCKCALL_RETURN (::select (width, rfds, wfds, efds, timep),
+ int, -1);
+#endif
+}
+
+ACE_INLINE int
+ACE_OS::select (int width,
+ fd_set *rfds, fd_set *wfds, fd_set *efds,
+ const ACE_Time_Value &timeout)
+{
+ ACE_OS_TRACE ("ACE_OS::select");
+#if defined (ACE_HAS_NONCONST_SELECT_TIMEVAL)
+# define ___ACE_TIMEOUT &copy
+ timeval copy = timeout;
+#else
+# define ___ACE_TIMEOUT timep
+ const timeval *timep = timeout;
+#endif /* ACE_HAS_NONCONST_SELECT_TIMEVAL */
+#if defined (ACE_LACKS_SELECT)
+ ACE_UNUSED_ARG (width);
+ ACE_UNUSED_ARG (rfds);
+ ACE_UNUSED_ARG (wfds);
+ ACE_UNUSED_ARG (efds);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined(ACE_TANDEM_T1248_PTHREADS)
+ ACE_SOCKCALL_RETURN (::spt_select (width, rfds, wfds, efds, ___ACE_TIMEOUT),
+ int, -1);
+#else
+ ACE_SOCKCALL_RETURN (::select (width, rfds, wfds, efds, ___ACE_TIMEOUT),
+ int, -1);
+#endif
+#undef ___ACE_TIMEOUT
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_sendfile.cpp b/ACE/ace/OS_NS_sys_sendfile.cpp
new file mode 100644
index 00000000000..9bd3537e54d
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_sendfile.cpp
@@ -0,0 +1,53 @@
+// $Id$
+
+#include "ace/OS_NS_sys_sendfile.h"
+#include "ace/OS_NS_sys_mman.h"
+
+#if defined (ACE_WIN32) || defined (HPUX)
+# include "ace/OS_NS_sys_socket.h"
+#else
+# include "ace/OS_NS_unistd.h"
+#endif /* ACE_WIN32 || HPUX */
+
+#ifndef ACE_HAS_INLINED_OSCALLS
+# include "ace/OS_NS_sys_sendfile.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#ifndef ACE_HAS_SENDFILE
+ssize_t
+ACE_OS::sendfile_emulation (ACE_HANDLE out_fd,
+ ACE_HANDLE in_fd,
+ off_t * offset,
+ size_t count)
+{
+ // @@ Is it possible to inline a call to ::TransmitFile() on
+ // MS Windows instead of emulating here?
+
+ // @@ We may want set up a signal lease (or oplock) if supported by
+ // the platform so that we don't get a bus error if the mmap()ed
+ // file is truncated.
+ void * const buf =
+ ACE_OS::mmap (0, count, PROT_READ, MAP_SHARED, in_fd, *offset);
+
+ if (buf == MAP_FAILED)
+ return -1;
+
+#if defined (ACE_WIN32) || defined (HPUX)
+ ssize_t const r =
+ ACE_OS::send (out_fd, static_cast<const char *> (buf), count);
+#else
+ ssize_t const r = ACE_OS::write (out_fd, buf, count);
+#endif /* ACE_WIN32 */
+
+ (void) ACE_OS::munmap (buf, count);
+
+ if (r > 0)
+ *offset += static_cast<off_t> (r);
+
+ return r;
+}
+#endif /* !ACE_HAS_SENDFILE */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_sendfile.h b/ACE/ace/OS_NS_sys_sendfile.h
new file mode 100644
index 00000000000..a7983dadec9
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_sendfile.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_sendfile.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@dre.vanderbilt.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_SENDFILE_H
+#define ACE_OS_NS_SYS_SENDFILE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Basic_Types.h" /* For ssize_t and off_t. */
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+ /// Finds the length of a string (char version).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t sendfile (ACE_HANDLE out_fd,
+ ACE_HANDLE in_fd,
+ off_t * offset,
+ size_t count);
+
+#ifndef ACE_HAS_SENDFILE
+ extern ACE_Export
+ ssize_t sendfile_emulation (ACE_HANDLE out_fd,
+ ACE_HANDLE in_fd,
+ off_t * offset,
+ size_t count);
+#endif /* !ACE_HAS_SENDFILE */
+
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_sendfile.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_OS_NS_SYS_SENDFILE_H */
diff --git a/ACE/ace/OS_NS_sys_sendfile.inl b/ACE/ace/OS_NS_sys_sendfile.inl
new file mode 100644
index 00000000000..1c468354b3e
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_sendfile.inl
@@ -0,0 +1,24 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifdef ACE_HAS_SENDFILE
+# include <sys/sendfile.h>
+#endif /* ACE_HAS_SENDFILE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ssize_t
+ACE_OS::sendfile (ACE_HANDLE out_fd,
+ ACE_HANDLE in_fd,
+ off_t * offset,
+ size_t count)
+{
+#ifdef ACE_HAS_SENDFILE
+ return ::sendfile (out_fd, in_fd, offset, count);
+#else
+ return ACE_OS::sendfile_emulation (out_fd, in_fd, offset, count);
+#endif /* ACE_HAS_SENDFILE */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_shm.cpp b/ACE/ace/OS_NS_sys_shm.cpp
new file mode 100644
index 00000000000..82ac65e1b54
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_shm.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_sys_shm.h"
+
+ACE_RCSID(ace, OS_NS_sys_shm, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_shm.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_sys_shm.h b/ACE/ace/OS_NS_sys_shm.h
new file mode 100644
index 00000000000..0d2a5a49d32
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_shm.h
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_shm.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_SHM_H
+# define ACE_OS_NS_SYS_SHM_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/os_include/sys/os_shm.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ //@{ @name A set of wrappers for System V shared memory.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *shmat (int int_id,
+ const void *shmaddr,
+ int shmflg);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int shmctl (int int_id,
+ int cmd,
+ struct shmid_ds *buf);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int shmdt (const void *shmaddr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int shmget (key_t key,
+ size_t size,
+ int flags);
+ ///@}
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_shm.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_SHM_H */
diff --git a/ACE/ace/OS_NS_sys_shm.inl b/ACE/ace/OS_NS_sys_shm.inl
new file mode 100644
index 00000000000..ef7fef59847
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_shm.inl
@@ -0,0 +1,76 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void *
+ACE_OS::shmat (int int_id, const void *shmaddr, int shmflg)
+{
+ ACE_OS_TRACE ("ACE_OS::shmat");
+#if defined (ACE_HAS_SYSV_IPC)
+# if defined (ACE_HAS_CHARPTR_SHMAT)
+ ACE_OSCALL_RETURN (::shmat (int_id, static_cast <char*> (const_cast <void *>(shmaddr)), shmflg), void *, (void *) -1);
+# else
+ ACE_OSCALL_RETURN (::shmat (int_id, shmaddr, shmflg), void *, (void *) -1);
+# endif /* ACE_HAS_CHARPTR_SHMAT */
+#else
+ ACE_UNUSED_ARG (int_id);
+ ACE_UNUSED_ARG (shmaddr);
+ ACE_UNUSED_ARG (shmflg);
+
+ ACE_NOTSUP_RETURN ((void *) -1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE int
+ACE_OS::shmctl (int int_id, int cmd, struct shmid_ds *buf)
+{
+ ACE_OS_TRACE ("ACE_OS::shmctl");
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_OSCALL_RETURN (::shmctl (int_id, cmd, buf), int, -1);
+#else
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (cmd);
+ ACE_UNUSED_ARG (int_id);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE int
+ACE_OS::shmdt (const void *shmaddr)
+{
+ ACE_OS_TRACE ("ACE_OS::shmdt");
+#if defined (ACE_HAS_SYSV_IPC)
+# if defined (ACE_HAS_CHARPTR_SHMDT)
+ ACE_OSCALL_RETURN (::shmdt (
+ static_cast <char*> (const_cast <void *>(shmaddr))), int, -1);
+# else
+ ACE_OSCALL_RETURN (::shmdt (shmaddr), int, -1);
+# endif /* ACE_HAS_CHARPTR_SHMDT */
+#else
+ ACE_UNUSED_ARG (shmaddr);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_INLINE int
+ACE_OS::shmget (key_t key, size_t size, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::shmget");
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_OSCALL_RETURN (::shmget (key, size, flags), int, -1);
+#else
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (size);
+ ACE_UNUSED_ARG (key);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_socket.cpp b/ACE/ace/OS_NS_sys_socket.cpp
new file mode 100644
index 00000000000..bbf468f4e63
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_socket.cpp
@@ -0,0 +1,161 @@
+// $Id$
+
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_RCSID(ace, OS_NS_sys_socket, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_socket.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_WIN32)
+int ACE_OS::socket_initialized_;
+#endif /* ACE_WIN32 */
+
+#if !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500))
+ACE_HANDLE
+ACE_OS::accept (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int *addrlen,
+ const ACE_Accept_QoS_Params &qos_params)
+{
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ ACE_SOCKCALL_RETURN (::WSAAccept ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen,
+ (LPCONDITIONPROC) qos_params.qos_condition_callback (),
+ qos_params.callback_data ()),
+ ACE_HANDLE,
+ ACE_INVALID_HANDLE);
+# else
+ ACE_UNUSED_ARG (qos_params);
+ return ACE_OS::accept (handle,
+ addr,
+ addrlen);
+# endif /* ACE_HAS_WINSOCK2 */
+}
+
+int
+ACE_OS::connect (ACE_HANDLE handle,
+ const sockaddr *addr,
+ int addrlen,
+ const ACE_QoS_Params &qos_params)
+{
+ ACE_OS_TRACE ("ACE_OS::connect");
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ ACE_SOCKCALL_RETURN (::WSAConnect ((ACE_SOCKET) handle,
+ (const sockaddr *) addr,
+ (ACE_SOCKET_LEN) addrlen,
+ (WSABUF *) qos_params.caller_data (),
+ (WSABUF *) qos_params.callee_data (),
+ (QOS *) qos_params.socket_qos (),
+ (QOS *) qos_params.group_socket_qos ()),
+ int, -1);
+# else
+ ACE_UNUSED_ARG (qos_params);
+ return ACE_OS::connect (handle,
+ const_cast <sockaddr *> (addr),
+ addrlen);
+# endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_HANDLE
+ACE_OS::join_leaf (ACE_HANDLE socket,
+ const sockaddr *name,
+ int namelen,
+ const ACE_QoS_Params &qos_params)
+{
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+
+ QOS qos;
+ // Construct the WinSock2 QOS structure.
+
+ qos.SendingFlowspec = *(qos_params.socket_qos ()->sending_flowspec ());
+ qos.ReceivingFlowspec = *(qos_params.socket_qos ()->receiving_flowspec ());
+ qos.ProviderSpecific = (WSABUF) qos_params.socket_qos ()->provider_specific ();
+
+ ACE_SOCKCALL_RETURN (::WSAJoinLeaf ((ACE_SOCKET) socket,
+ name,
+ namelen,
+ (WSABUF *) qos_params.caller_data (),
+ (WSABUF *) qos_params.callee_data (),
+ &qos,
+ (QOS *) qos_params.group_socket_qos (),
+ qos_params.flags ()),
+ ACE_HANDLE,
+ ACE_INVALID_HANDLE);
+
+# else
+ ACE_UNUSED_ARG (socket);
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (namelen);
+ ACE_UNUSED_ARG (qos_params);
+ ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE);
+# endif /* ACE_HAS_WINSOCK2 */
+}
+#endif /* !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500)) */
+
+int
+ACE_OS::socket_init (int version_high, int version_low)
+{
+# if defined (ACE_WIN32) && !defined(ACE_DONT_INIT_WINSOCK)
+ if (ACE_OS::socket_initialized_ == 0)
+ {
+ WORD version_requested = MAKEWORD (version_high, version_low);
+ WSADATA wsa_data;
+ int error = WSAStartup (version_requested, &wsa_data);
+
+ if (error != 0)
+# if defined (ACE_HAS_WINCE)
+ {
+ ACE_TCHAR fmt[] = ACE_TEXT ("%s failed, WSAGetLastError returned %d");
+ ACE_TCHAR buf[80]; // @@ Eliminate magic number.
+ ACE_OS::sprintf (buf, fmt, ACE_TEXT ("WSAStartup"), error);
+ ::MessageBox (0, buf, ACE_TEXT ("WSAStartup failed!"), MB_OK);
+ }
+# else
+ ACE_OS::fprintf (stderr,
+ "ACE_OS::socket_init; WSAStartup failed, "
+ "WSAGetLastError returned %d\n",
+ error);
+# endif /* ACE_HAS_WINCE */
+
+ ACE_OS::socket_initialized_ = 1;
+ }
+# else
+ ACE_UNUSED_ARG (version_high);
+ ACE_UNUSED_ARG (version_low);
+# endif /* ACE_WIN32 */
+ return 0;
+}
+
+int
+ACE_OS::socket_fini (void)
+{
+# if defined (ACE_WIN32)
+ if (ACE_OS::socket_initialized_ != 0)
+ {
+ if (WSACleanup () != 0)
+ {
+ int error = ::WSAGetLastError ();
+# if defined (ACE_HAS_WINCE)
+ ACE_TCHAR fmt[] = ACE_TEXT ("%s failed, WSAGetLastError returned %d");
+ ACE_TCHAR buf[80]; // @@ Eliminate magic number.
+ ACE_OS::sprintf (buf, fmt, ACE_TEXT ("WSACleanup"), error);
+ ::MessageBox (0, buf , ACE_TEXT ("WSACleanup failed!"), MB_OK);
+# else
+ ACE_OS::fprintf (stderr,
+ "ACE_OS::socket_fini; WSACleanup failed, "
+ "WSAGetLastError returned %d\n",
+ error);
+# endif /* ACE_HAS_WINCE */
+ }
+ ACE_OS::socket_initialized_ = 0;
+ }
+# endif /* ACE_WIN32 */
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_socket.h b/ACE/ace/OS_NS_sys_socket.h
new file mode 100644
index 00000000000..036ba2e8e29
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_socket.h
@@ -0,0 +1,302 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_socket.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_SOCKET_H
+# define ACE_OS_NS_SYS_SOCKET_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/os_include/sys/os_socket.h"
+#include "ace/os_include/net/os_if.h"
+#include "ace/OS_NS_stropts.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+/// These are available values for the @a how argument to ACE_OS::shutdown().
+#if defined (SD_RECEIVE)
+#define ACE_SHUTDOWN_READ SD_RECEIVE
+#elif defined (SHUT_RD)
+#define ACE_SHUTDOWN_READ SHUT_RD
+#else
+#define ACE_SHUTDOWN_READ 0
+#endif /* SD_RECEIVE */
+
+#if defined (SD_SEND)
+#define ACE_SHUTDOWN_WRITE SD_SEND
+#elif defined (SHUT_WR)
+#define ACE_SHUTDOWN_WRITE SHUT_WR
+#else
+#define ACE_SHUTDOWN_WRITE 1
+#endif /* SD_SEND */
+
+#if defined (SD_BOTH)
+#define ACE_SHUTDOWN_BOTH SD_BOTH
+#elif defined (SHUT_RDWR)
+#define ACE_SHUTDOWN_BOTH SHUT_RDWR
+#else
+#define ACE_SHUTDOWN_BOTH 2
+#endif /* SD_BOTH */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Accept_QoS_Params;
+class ACE_QoS_Params;
+
+namespace ACE_OS
+{
+
+# if defined (ACE_WIN32)
+ /// Keeps track of whether we've already initialized WinSock...
+ extern ACE_Export int socket_initialized_;
+# endif /* ACE_WIN32 */
+
+ //@{ @name A set of wrappers for sockets.
+ /// BSD-style <accept> (no QoS).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE accept (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int *addrlen);
+
+#if !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500))
+ /**
+ * QoS-enabled <accept>, which passes @a qos_params to <accept>. If
+ * the OS platform doesn't support QoS-enabled <accept> then the
+ * @a qos_params are ignored and the BSD-style <accept> is called.
+ */
+ extern ACE_Export
+ ACE_HANDLE accept (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int *addrlen,
+ const ACE_Accept_QoS_Params &qos_params);
+#endif /* !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500)) */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int bind (ACE_HANDLE s,
+ struct sockaddr *name,
+ int namelen);
+
+ /// Takes care of windows specific requirement to call closesocket
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int closesocket (ACE_HANDLE s);
+
+ /// BSD-style <connect> (no QoS).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int connect (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int addrlen);
+
+#if !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500))
+ /**
+ * QoS-enabled <connect>, which passes @a qos_params to <connect>.
+ * If the OS platform doesn't support QoS-enabled <connect> then the
+ * @a qos_params are ignored and the BSD-style <connect> is called.
+ */
+ extern ACE_Export
+ int connect (ACE_HANDLE handle,
+ const sockaddr *addr,
+ int addrlen,
+ const ACE_QoS_Params &qos_params);
+#endif /* !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500)) */
+
+ /// Retrieve information about available transport protocols
+ /// installed on the local machine. Windows specific...
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int enum_protocols (int *protocols,
+ ACE_Protocol_Info *protocol_buffer,
+ u_long *buffer_length);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getpeername (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int *addrlen);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getsockname (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int *addrlen);
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getsockopt (ACE_HANDLE handle,
+ int level,
+ int optname,
+ char *optval,
+ int *optlen);
+
+#if !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500))
+ /// Joins a leaf node into a QoS-enabled multi-point session.
+ extern ACE_Export
+ ACE_HANDLE join_leaf (ACE_HANDLE socket,
+ const sockaddr *name,
+ int namelen,
+ const ACE_QoS_Params &qos_params);
+#endif /* !(defined (ACE_HAS_WINCE) && (UNDER_CE < 500)) */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int listen (ACE_HANDLE handle,
+ int backlog);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t recv (ACE_HANDLE handle,
+ char *buf,
+ size_t len,
+ int flags = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t recvfrom (ACE_HANDLE handle,
+ char *buf,
+ size_t len,
+ int flags,
+ struct sockaddr *addr,
+ int *addrlen);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t recvfrom (ACE_HANDLE handle,
+ iovec *buffers,
+ int buffer_count,
+ size_t &number_of_bytes_recvd,
+ int &flags,
+ struct sockaddr *addr,
+ int *addrlen,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t recvmsg (ACE_HANDLE handle,
+ struct msghdr *msg,
+ int flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t recvv (ACE_HANDLE handle,
+ iovec *iov,
+ int iovlen);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t send (ACE_HANDLE handle,
+ const char *buf,
+ size_t len,
+ int flags = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t sendmsg (ACE_HANDLE handle,
+ const struct msghdr *msg,
+ int flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t sendto (ACE_HANDLE handle,
+ const char *buf,
+ size_t len,
+ int flags,
+ const struct sockaddr *addr,
+ int addrlen);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t sendto (ACE_HANDLE handle,
+ const iovec *buffers,
+ int buffer_count,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const struct sockaddr *addr,
+ int addrlen,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t sendv (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt);
+
+
+ /// Manipulate the options associated with a socket.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int setsockopt (ACE_HANDLE handle,
+ int level,
+ int optname,
+ const char *optval,
+ int optlen);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int shutdown (ACE_HANDLE handle,
+ int how);
+
+#if defined (__linux__) && defined (ACE_HAS_IPV6)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ unsigned int if_nametoindex (const char *ifname);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *if_indextoname (unsigned int ifindex, char *ifname);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct if_nameindex *if_nameindex (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void if_freenameindex (struct if_nameindex *ptr);
+#endif /* __linux__ && ACE_HAS_IPV6 */
+
+ /// Initialize WinSock before first use (e.g., when a DLL is first
+ /// loaded or the first use of a socket() call.
+ extern ACE_Export
+ int socket_init (int version_high = 1,
+ int version_low = 1);
+
+ /// Finalize WinSock after last use (e.g., when a DLL is unloaded).
+ extern ACE_Export
+ int socket_fini (void);
+
+ /// Create a BSD-style socket (no QoS).
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE socket (int protocol_family,
+ int type,
+ int proto);
+
+ /// Create a QoS-enabled socket. If the OS platform doesn't support
+ /// QoS-enabled <socket> then the BSD-style <socket> is called.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE socket (int protocol_family,
+ int type,
+ int proto,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int socketpair (int domain,
+ int type,
+ int protocol,
+ ACE_HANDLE sv[2]);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_socket.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_SOCKET_H */
diff --git a/ACE/ace/OS_NS_sys_socket.inl b/ACE/ace/OS_NS_sys_socket.inl
new file mode 100644
index 00000000000..a983d34e7e4
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_socket.inl
@@ -0,0 +1,993 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_macros.h"
+#include "ace/OS_NS_sys_uio.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_QoS.h"
+#include "ace/Global_Macros.h"
+#include "ace/os_include/netinet/os_in.h"
+
+#if defined (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO) \
+ && (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO == 1)
+#include "ace/OS_NS_string.h"
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_VOIDPTR_SOCKOPT)
+typedef void *ACE_SOCKOPT_TYPE1;
+#elif defined (ACE_HAS_CHARPTR_SOCKOPT)
+typedef char *ACE_SOCKOPT_TYPE1;
+#else
+typedef const char *ACE_SOCKOPT_TYPE1;
+#endif /* ACE_HAS_VOIDPTR_SOCKOPT */
+
+ACE_INLINE ACE_HANDLE
+ACE_OS::accept (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int *addrlen)
+{
+ ACE_OS_TRACE ("ACE_OS::accept");
+ // On a non-blocking socket with no connections to accept, this
+ // system call will return EWOULDBLOCK or EAGAIN, depending on the
+ // platform. UNIX 98 allows either errno, and they may be the same
+ // numeric value. So to make life easier for upper ACE layers as
+ // well as application programmers, always change EAGAIN to
+ // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's
+ // handled explicitly here. If the ACE_OSCALL macro ever changes,
+ // this function needs to be reviewed. On Win32, the regular macros
+ // can be used, as this is not an issue.
+
+#if defined (ACE_LACKS_ACCEPT)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE);
+#elif defined (ACE_WIN32)
+ ACE_SOCKCALL_RETURN (::accept ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen),
+ ACE_HANDLE,
+ ACE_INVALID_HANDLE);
+#else
+# if defined (ACE_HAS_BROKEN_ACCEPT_ADDR)
+ // Apparently some platforms like VxWorks can't correctly deal with
+ // a NULL addr.
+
+ sockaddr_in fake_addr;
+ int fake_addrlen;
+
+ if (addrlen == 0)
+ addrlen = &fake_addrlen;
+
+ if (addr == 0)
+ {
+ addr = (sockaddr *) &fake_addr;
+ *addrlen = sizeof fake_addr;
+ }
+# endif /* ACE_HAS_BROKEN_ACCEPT_ADDR */
+ ACE_HANDLE ace_result = ::accept ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen);
+
+# if !(defined (EAGAIN) && defined (EWOULDBLOCK) && EAGAIN == EWOULDBLOCK)
+ // Optimize this code out if we can detect that EAGAIN ==
+ // EWOULDBLOCK at compile time. If we cannot detect equality at
+ // compile-time (e.g. if EAGAIN or EWOULDBLOCK are not preprocessor
+ // macros) perform the check at run-time. The goal is to avoid two
+ // TSS accesses in the _REENTRANT case when EAGAIN == EWOULDBLOCK.
+ if (ace_result == ACE_INVALID_HANDLE
+# if !defined (EAGAIN) || !defined (EWOULDBLOCK)
+ && EAGAIN != EWOULDBLOCK
+# endif /* !EAGAIN || !EWOULDBLOCK */
+ && errno == EAGAIN)
+ {
+ errno = EWOULDBLOCK;
+ }
+# endif /* EAGAIN != EWOULDBLOCK*/
+
+ return ace_result;
+
+#endif /* defined (ACE_WIN32) */
+}
+
+ACE_INLINE int
+ACE_OS::bind (ACE_HANDLE handle, struct sockaddr *addr, int addrlen)
+{
+ ACE_OS_TRACE ("ACE_OS::bind");
+#if defined (ACE_LACKS_BIND)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x640)
+ // VxWorks clears the sin_port member after a succesfull bind when
+ // sin_addr != INADDR_ANY, so after the bind we do retrieve the
+ // original address so that user code can safely check the addr
+ // after the bind. See bugzilla 3107 for more details
+ int result;
+ ACE_SOCKCALL (::bind ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN) addrlen), int, -1, result);
+ if (result == -1)
+ return -1;
+ else
+ return ACE_OS::getsockname (handle, addr, &addrlen);
+#else
+ ACE_SOCKCALL_RETURN (::bind ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN) addrlen), int, -1);
+#endif
+}
+
+ACE_INLINE int
+ACE_OS::closesocket (ACE_HANDLE handle)
+{
+ ACE_OS_TRACE ("ACE_OS::closesocket");
+#if defined (ACE_WIN32)
+ // @note Do not shutdown the write end here. Doing so will break
+ // applications that duplicate a handle on fork(), for
+ // example, and expect to continue writing in the fork()ed
+ // process.
+
+ ACE_SOCKCALL_RETURN (::closesocket ((SOCKET) handle), int, -1);
+#else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (::close (handle), int, -1);
+ //FUZZ: enable check_for_lack_ACE_OS
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_OS::connect (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int addrlen)
+{
+ ACE_OS_TRACE ("ACE_OS::connect");
+#if defined (ACE_LACKS_CONNECT)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_SOCKCALL_RETURN (::connect ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN) addrlen), int, -1);
+#endif /* ACE_LACKS_CONNECT */
+}
+
+ACE_INLINE int
+ACE_OS::enum_protocols (int *protocols,
+ ACE_Protocol_Info *protocol_buffer,
+ u_long *buffer_length)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+
+ ACE_SOCKCALL_RETURN (::WSAEnumProtocols (protocols,
+ protocol_buffer,
+ buffer_length),
+ int,
+ SOCKET_ERROR);
+
+#else
+ ACE_UNUSED_ARG (protocols);
+ ACE_UNUSED_ARG (protocol_buffer);
+ ACE_UNUSED_ARG (buffer_length);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_INLINE int
+ACE_OS::getpeername (ACE_HANDLE handle, struct sockaddr *addr,
+ int *addrlen)
+{
+ ACE_OS_TRACE ("ACE_OS::getpeername");
+
+#if defined (ACE_LACKS_GETPEERNAME)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO) \
+ && (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO == 1)
+ int result;
+ ACE_SOCKCALL (::getpeername ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen),
+ int,
+ -1,
+ result);
+
+ // Some platforms, like older versions of the Linux kernel, do not
+ // initialize the sin_zero field since that field is generally only
+ // used for padding/alignment purposes. On those platforms
+ // memcmp()-based comparisons of the sockaddr_in structure, such as
+ // the one in the ACE_INET_Addr equality operator, may fail due to
+ // random bytes in the sin_zero field even though that field is
+ // unused. Prevent equality comparison of two different sockaddr_in
+ // instances that refer to the same socket from failing by
+ // explicitly initializing the sockaddr_in::sin_zero field to a
+ // consistent value, e.g. zero.
+ if (result != -1 && addr->sa_family == AF_INET)
+ {
+ ACE_OS::memset (reinterpret_cast<struct sockaddr_in *> (addr)->sin_zero,
+ 0,
+ sizeof (reinterpret_cast<struct sockaddr_in *> (addr)->sin_zero));
+ }
+
+ return result;
+#else
+ ACE_SOCKCALL_RETURN (::getpeername ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen),
+ int,
+ -1);
+#endif /* ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO */
+}
+
+ACE_INLINE int
+ACE_OS::getsockname (ACE_HANDLE handle,
+ struct sockaddr *addr,
+ int *addrlen)
+{
+ ACE_OS_TRACE ("ACE_OS::getsockname");
+#if defined (ACE_LACKS_GETSOCKNAME)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO) \
+ && (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO == 1)
+ int result;
+ ACE_SOCKCALL (::getsockname ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen),
+ int, -1, result);
+
+ // Some platforms, like older versions of the Linux kernel, do not
+ // initialize the sin_zero field since that field is generally only
+ // used for padding/alignment purposes. On those platforms
+ // memcmp()-based comparisons of the sockaddr_in structure, such as
+ // the one in the ACE_INET_Addr equality operator, may fail due to
+ // random bytes in the sin_zero field even though that field is
+ // unused. Prevent equality comparison of two different sockaddr_in
+ // instances that refer to the same socket from failing by
+ // explicitly initializing the sockaddr_in::sin_zero field to a
+ // consistent value, e.g. zero.
+ if (result != -1 && addr->sa_family == AF_INET)
+ {
+ ACE_OS::memset (reinterpret_cast<struct sockaddr_in *> (addr)->sin_zero,
+ 0,
+ sizeof (reinterpret_cast<struct sockaddr_in *> (addr)->sin_zero));
+ }
+
+ return result;
+#else
+ ACE_SOCKCALL_RETURN (::getsockname ((ACE_SOCKET) handle,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen),
+ int, -1);
+#endif /* ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO */
+}
+
+ACE_INLINE int
+ACE_OS::getsockopt (ACE_HANDLE handle,
+ int level,
+ int optname,
+ char *optval,
+ int *optlen)
+{
+ ACE_OS_TRACE ("ACE_OS::getsockopt");
+#if defined (ACE_LACKS_GETSOCKOPT)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (level);
+ ACE_UNUSED_ARG (optname);
+ ACE_UNUSED_ARG (optval);
+ ACE_UNUSED_ARG (optlen);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_SOCKCALL_RETURN (::getsockopt ((ACE_SOCKET) handle,
+ level,
+ optname,
+ optval,
+ (ACE_SOCKET_LEN *) optlen),
+ int,
+ -1);
+#endif /* ACE_LACKS_GETSOCKOPT */
+}
+
+ACE_INLINE int
+ACE_OS::listen (ACE_HANDLE handle, int backlog)
+{
+ ACE_OS_TRACE ("ACE_OS::listen");
+#if defined (ACE_LACKS_LISTEN)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (backlog);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_SOCKCALL_RETURN (::listen ((ACE_SOCKET) handle, backlog), int, -1);
+#endif /* ACE_LACKS_LISTEN */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::recv (ACE_HANDLE handle, char *buf, size_t len, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::recv");
+
+ // On UNIX, a non-blocking socket with no data to receive, this
+ // system call will return EWOULDBLOCK or EAGAIN, depending on the
+ // platform. UNIX 98 allows either errno, and they may be the same
+ // numeric value. So to make life easier for upper ACE layers as
+ // well as application programmers, always change EAGAIN to
+ // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's
+ // handled explicitly here. If the ACE_OSCALL macro ever changes,
+ // this function needs to be reviewed. On Win32, the regular macros
+ // can be used, as this is not an issue.
+#if defined (ACE_LACKS_RECV)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (flags);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+ ACE_SOCKCALL_RETURN (::recv ((ACE_SOCKET) handle, buf,
+ static_cast<int> (len), flags), ssize_t, -1);
+#else
+ ssize_t ace_result_;
+ ace_result_ = ::recv ((ACE_SOCKET) handle, buf, len, flags);
+
+# if !(defined (EAGAIN) && defined (EWOULDBLOCK) && EAGAIN == EWOULDBLOCK)
+ // Optimize this code out if we can detect that EAGAIN ==
+ // EWOULDBLOCK at compile time. If we cannot detect equality at
+ // compile-time (e.g. if EAGAIN or EWOULDBLOCK are not preprocessor
+ // macros) perform the check at run-time. The goal is to avoid two
+ // TSS accesses in the _REENTRANT case when EAGAIN == EWOULDBLOCK.
+ if (ace_result_ == -1
+# if !defined (EAGAIN) || !defined (EWOULDBLOCK)
+ && EAGAIN != EWOULDBLOCK
+# endif /* !EAGAIN || !EWOULDBLOCK */
+ && errno == EAGAIN)
+ {
+ errno = EWOULDBLOCK;
+ }
+# endif /* EAGAIN != EWOULDBLOCK*/
+
+ return ace_result_;
+#endif /* ACE_LACKS_RECV */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::recvfrom (ACE_HANDLE handle,
+ char *buf,
+ size_t len,
+ int flags,
+ struct sockaddr *addr,
+ int *addrlen)
+{
+ ACE_OS_TRACE ("ACE_OS::recvfrom");
+#if defined (ACE_LACKS_RECVFROM)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+ int const shortened_len = static_cast<int> (len);
+ int const result = ::recvfrom ((ACE_SOCKET) handle,
+ buf,
+ shortened_len,
+ flags,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen);
+ if (result == SOCKET_ERROR)
+ {
+ ACE_OS::set_errno_to_wsa_last_error ();
+ if (errno == WSAEMSGSIZE &&
+ ACE_BIT_ENABLED (flags, MSG_PEEK))
+ return shortened_len;
+ else
+ return -1;
+ }
+ else
+ return result;
+#else /* non Win32 */
+ ACE_SOCKCALL_RETURN (::recvfrom ((ACE_SOCKET) handle,
+ buf,
+ len,
+ flags,
+ addr,
+ (ACE_SOCKET_LEN *) addrlen),
+ ssize_t, -1);
+#endif /* ACE_LACKS_RECVFROM */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::recvfrom (ACE_HANDLE handle,
+ iovec *buffers,
+ int buffer_count,
+ size_t &number_of_bytes_recvd,
+ int &flags,
+ struct sockaddr *addr,
+ int *addrlen,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func)
+{
+ ACE_OS_TRACE ("ACE_OS::recvfrom");
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ DWORD bytes_recvd;
+ DWORD the_flags = flags;
+ int result = ::WSARecvFrom ((SOCKET) handle,
+ (WSABUF*)buffers,
+ buffer_count,
+ &bytes_recvd,
+ &the_flags,
+ addr,
+ addrlen,
+ overlapped,
+ func);
+ if (result != 0) {
+ ACE_OS::set_errno_to_wsa_last_error ();
+ }
+ flags = the_flags;
+ number_of_bytes_recvd = static_cast<size_t> (bytes_recvd);
+ return result;
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buffers);
+ ACE_UNUSED_ARG (buffer_count);
+ ACE_UNUSED_ARG (number_of_bytes_recvd);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ ACE_UNUSED_ARG (overlapped);
+ ACE_UNUSED_ARG (func);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::recvmsg (ACE_HANDLE handle, struct msghdr *msg, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::recvmsg");
+#if !defined (ACE_LACKS_RECVMSG)
+# if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+ DWORD bytes_received = 0;
+
+ int result = ::WSARecvFrom ((SOCKET) handle,
+ (WSABUF *) msg->msg_iov,
+ msg->msg_iovlen,
+ &bytes_received,
+ (DWORD *) &flags,
+ msg->msg_name,
+ &msg->msg_namelen,
+ 0,
+ 0);
+
+ if (result != 0)
+ {
+ ACE_OS::set_errno_to_wsa_last_error ();
+ return -1;
+ }
+ else
+ return bytes_received;
+# else /* ACE_HAS_WINSOCK2 */
+ ACE_SOCKCALL_RETURN (::recvmsg (handle, msg, flags), ssize_t, -1);
+# endif /* ACE_HAS_WINSOCK2 */
+#else
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (msg);
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_LACKS_RECVMSG */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::recvv (ACE_HANDLE handle,
+ iovec *buffers,
+ int n)
+{
+#if defined (ACE_HAS_WINSOCK2)
+
+ DWORD bytes_received = 0;
+ int result = 1;
+
+ // Winsock 2 has WSARecv and can do this directly, but Winsock 1 needs
+ // to do the recvs piece-by-piece.
+
+# if (ACE_HAS_WINSOCK2 != 0)
+ DWORD flags = 0;
+ result = ::WSARecv ((SOCKET) handle,
+ (WSABUF *) buffers,
+ n,
+ &bytes_received,
+ &flags,
+ 0,
+ 0);
+# else
+ int i, chunklen;
+ char *chunkp = 0;
+
+ // Step through the buffers requested by caller; for each one, cycle
+ // through reads until it's filled or an error occurs.
+ for (i = 0; i < n && result > 0; ++i)
+ {
+ chunkp = buffers[i].iov_base; // Point to part of chunk being read
+ chunklen = buffers[i].iov_len; // Track how much to read to chunk
+ while (chunklen > 0 && result > 0)
+ {
+ result = ::recv ((SOCKET) handle, chunkp, chunklen, 0);
+ if (result > 0)
+ {
+ chunkp += result;
+ chunklen -= result;
+ bytes_received += result;
+ }
+ }
+ }
+# endif /* ACE_HAS_WINSOCK2 != 0 */
+
+ if (result == SOCKET_ERROR)
+ {
+ ACE_OS::set_errno_to_wsa_last_error ();
+ return -1;
+ }
+ else
+ return (ssize_t) bytes_received;
+#else
+ return ACE_OS::readv (handle, buffers, n);
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::send (ACE_HANDLE handle, const char *buf, size_t len, int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::send");
+
+ // On UNIX, a non-blocking socket with no data to receive, this
+ // system call will return EWOULDBLOCK or EAGAIN, depending on the
+ // platform. UNIX 98 allows either errno, and they may be the same
+ // numeric value. So to make life easier for upper ACE layers as
+ // well as application programmers, always change EAGAIN to
+ // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's
+ // handled explicitly here. If the ACE_OSCALL macro ever changes,
+ // this function needs to be reviewed. On Win32, the regular macros
+ // can be used, as this is not an issue.
+#if defined (ACE_LACKS_SEND)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (flags);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+ ACE_SOCKCALL_RETURN (::send ((ACE_SOCKET) handle,
+ buf,
+ static_cast<int> (len),
+ flags), ssize_t, -1);
+#else
+ ssize_t const ace_result_ = ::send ((ACE_SOCKET) handle, buf, len, flags);
+
+# if !(defined (EAGAIN) && defined (EWOULDBLOCK) && EAGAIN == EWOULDBLOCK)
+ // Optimize this code out if we can detect that EAGAIN ==
+ // EWOULDBLOCK at compile time. If we cannot detect equality at
+ // compile-time (e.g. if EAGAIN or EWOULDBLOCK are not preprocessor
+ // macros) perform the check at run-time. The goal is to avoid two
+ // TSS accesses in the _REENTRANT case when EAGAIN == EWOULDBLOCK.
+ if (ace_result_ == -1
+# if !defined (EAGAIN) || !defined (EWOULDBLOCK)
+ && EAGAIN != EWOULDBLOCK
+# endif /* !EAGAIN || !EWOULDBLOCK */
+ && errno == EAGAIN)
+ {
+ errno = EWOULDBLOCK;
+ }
+# endif /* EAGAIN != EWOULDBLOCK*/
+
+ return ace_result_;
+#endif /* defined (ACE_WIN32) */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::sendmsg (ACE_HANDLE handle,
+ const struct msghdr *msg,
+ int flags)
+{
+ ACE_OS_TRACE ("ACE_OS::sendmsg");
+#if !defined (ACE_LACKS_SENDMSG)
+# if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+ DWORD bytes_sent = 0;
+ int result = ::WSASendTo ((SOCKET) handle,
+ (WSABUF *) msg->msg_iov,
+ msg->msg_iovlen,
+ &bytes_sent,
+ flags,
+ msg->msg_name,
+ msg->msg_namelen,
+ 0,
+ 0);
+
+ if (result != 0)
+ {
+ ACE_OS::set_errno_to_wsa_last_error ();
+ return -1;
+ }
+ else
+ return (ssize_t) bytes_sent;
+# elif defined (ACE_HAS_NONCONST_SENDMSG)
+ ACE_SOCKCALL_RETURN (::sendmsg (handle,
+ const_cast<struct msghdr *>(msg),
+ flags), ssize_t, -1);
+# else
+ ACE_SOCKCALL_RETURN (::sendmsg (handle, msg, flags), ssize_t, -1);
+# endif
+#else
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (msg);
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_LACKS_SENDMSG */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::sendto (ACE_HANDLE handle,
+ const char *buf,
+ size_t len,
+ int flags,
+ const struct sockaddr *addr,
+ int addrlen)
+{
+ ACE_OS_TRACE ("ACE_OS::sendto");
+#if defined (ACE_LACKS_SENDTO)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (len);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (addrlen);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_VXWORKS)
+ ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle,
+ const_cast <char *> (buf),
+ len,
+ flags,
+ const_cast<struct sockaddr *> (addr),
+ addrlen),
+ ssize_t, -1);
+#elif defined (ACE_WIN32)
+ ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle,
+ buf,
+ static_cast<int> (len),
+ flags,
+ const_cast<struct sockaddr *> (addr),
+ addrlen),
+ ssize_t, -1);
+#else
+ ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle,
+ buf,
+ len,
+ flags,
+ const_cast<struct sockaddr *> (addr),
+ addrlen),
+ ssize_t, -1);
+#endif /* ACE_LACKS_SENDTO */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::sendto (ACE_HANDLE handle,
+ const iovec *buffers,
+ int buffer_count,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const struct sockaddr *addr,
+ int addrlen,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func)
+{
+ ACE_OS_TRACE ("ACE_OS::sendto");
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ DWORD bytes_sent = 0;
+ int result = ::WSASendTo ((SOCKET) handle,
+ (WSABUF*) buffers,
+ buffer_count,
+ &bytes_sent,
+ flags,
+ addr,
+ addrlen,
+ overlapped,
+ func);
+ if (result != 0) {
+ ACE_OS::set_errno_to_wsa_last_error ();
+ }
+ number_of_bytes_sent = static_cast<size_t> (bytes_sent);
+ return (ssize_t) result;
+#else
+ ACE_UNUSED_ARG (overlapped);
+ ACE_UNUSED_ARG (func);
+
+ number_of_bytes_sent = 0;
+
+ ssize_t result = 0;
+
+ for (int i = 0; i < buffer_count; ++i)
+ {
+ result = ACE_OS::sendto (handle,
+ reinterpret_cast<char *> (
+ buffers[i].iov_base),
+ buffers[i].iov_len,
+ flags,
+ addr,
+ addrlen);
+ if (result == -1)
+ break;
+ number_of_bytes_sent += static_cast<size_t> (result);
+ }
+
+ return result;
+#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::sendv (ACE_HANDLE handle,
+ const iovec *buffers,
+ int n)
+{
+#if defined (ACE_HAS_WINSOCK2)
+ DWORD bytes_sent = 0;
+ ssize_t result = 0;
+
+ // Winsock 2 has WSASend and can do this directly, but Winsock 1
+ // needs to do the sends one-by-one.
+# if (ACE_HAS_WINSOCK2 != 0)
+ result = ::WSASend ((SOCKET) handle,
+ (WSABUF *) buffers,
+ n,
+ &bytes_sent,
+ 0,
+ 0,
+ 0);
+ if (result == SOCKET_ERROR)
+ {
+ ACE_OS::set_errno_to_wsa_last_error ();
+ return -1;
+ }
+# else
+ for (int i = 0; i < n; ++i)
+ {
+ result = ::send ((SOCKET) handle,
+ buffers[i].iov_base,
+ buffers[i].iov_len,
+ 0);
+
+ if (result == SOCKET_ERROR)
+ {
+ // There is a subtle difference in behaviour depending on
+ // whether or not any data was sent. If no data was sent,
+ // then always return -1. Otherwise return bytes_sent.
+ // This gives the caller an opportunity to keep track of
+ // bytes that have already been sent.
+ if (bytes_sent > 0)
+ break;
+ else
+ {
+ ACE_OS::set_errno_to_wsa_last_error ();
+ return -1;
+ }
+ }
+ else
+ {
+ // Gets ignored on error anyway
+ bytes_sent += result;
+
+ // If the transfer isn't complete just drop out of the loop.
+ if (result < (int)buffers[i].iov_len)
+ break;
+ }
+ }
+# endif /* ACE_HAS_WINSOCK2 != 0 */
+
+ return (ssize_t) bytes_sent;
+
+#elif defined (ACE_HAS_SOCK_BUF_SIZE_MAX)
+
+ // Platform limits the maximum socket message size. Pare down the
+ // iovec, if necessary, to obey the limit.
+ iovec local_iov[ACE_IOV_MAX];
+ long total = 0;
+ long new_total = 0;
+ for (int i = 0; i < n; i++)
+ {
+ local_iov[i].iov_base = buffers[i].iov_base;
+ local_iov[i].iov_len = buffers[i].iov_len;
+
+ new_total = total + buffers[i].iov_len;
+ if (new_total >= ACE_HAS_SOCK_BUF_SIZE_MAX_VALUE)
+ {
+ local_iov[i].iov_len = ACE_HAS_SOCK_BUF_SIZE_MAX_VALUE - total;
+ n = i+1;
+ break;
+ }
+ total = new_total;
+ }
+ return ACE_OS::writev (handle, local_iov, n);
+
+#else
+ return ACE_OS::writev (handle, buffers, n);
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_INLINE int
+ACE_OS::setsockopt (ACE_HANDLE handle,
+ int level,
+ int optname,
+ const char *optval,
+ int optlen)
+{
+ ACE_OS_TRACE ("ACE_OS::setsockopt");
+#if defined (ACE_LACKS_SETSOCKOPT)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (level);
+ ACE_UNUSED_ARG (optname);
+ ACE_UNUSED_ARG (optval);
+ ACE_UNUSED_ARG (optlen);
+ ACE_NOTSUP_RETURN (-1);
+#else
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && defined(SO_REUSEPORT)
+ // To work around an inconsistency with Microsofts implementation of
+ // sockets, we will check for SO_REUSEADDR, and ignore it. Winsock
+ // always behaves as if SO_REUSEADDR=1. Some implementations have
+ // the same behaviour as Winsock, but use a new name for
+ // it. SO_REUSEPORT. If you want the normal behaviour for
+ // SO_REUSEADDR=0, then NT 4 sp4 and later supports
+ // SO_EXCLUSIVEADDRUSE. This also requires using an updated Platform
+ // SDK so it was decided to ignore the option for now. (Especially
+ // since Windows always sets SO_REUSEADDR=1, which we can mimic by doing
+ // nothing.)
+ if (level == SOL_SOCKET) {
+ if (optname == SO_REUSEADDR) {
+ return 0; // Not supported by Winsock
+ }
+ if (optname == SO_REUSEPORT) {
+ optname = SO_REUSEADDR;
+ }
+ }
+#endif /*ACE_HAS_WINSOCK2*/
+
+ int result;
+ ACE_SOCKCALL (::setsockopt ((ACE_SOCKET) handle,
+ level,
+ optname,
+ (ACE_SOCKOPT_TYPE1) optval,
+ optlen),
+ int,
+ -1,
+ result);
+#if defined (WSAEOPNOTSUPP)
+ if (result == -1 && errno == WSAEOPNOTSUPP)
+#else
+ if (result == -1)
+#endif /* WSAEOPNOTSUPP */
+ errno = ENOTSUP;
+ return result;
+#endif
+}
+
+ACE_INLINE int
+ACE_OS::shutdown (ACE_HANDLE handle, int how)
+{
+ ACE_OS_TRACE ("ACE_OS::shutdown");
+#if defined (ACE_LACKS_SHUTDOWN)
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (how);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_SOCKCALL_RETURN (::shutdown ((ACE_SOCKET) handle, how), int, -1);
+#endif /* ACE_LACKS_SHUTDOWN */
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_OS::socket (int domain,
+ int type,
+ int proto)
+{
+ ACE_OS_TRACE ("ACE_OS::socket");
+#if defined (ACE_LACKS_SOCKET)
+ ACE_UNUSED_ARG (domain);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (proto);
+ ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE);
+#else
+ ACE_SOCKCALL_RETURN (::socket (domain,
+ type,
+ proto),
+ ACE_HANDLE,
+ ACE_INVALID_HANDLE);
+#endif /* ACE_LACKS_SOCKET */
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_OS::socket (int domain,
+ int type,
+ int proto,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags)
+{
+ ACE_OS_TRACE ("ACE_OS::socket");
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ ACE_SOCKCALL_RETURN (::WSASocket (domain,
+ type,
+ proto,
+ protocolinfo,
+ g,
+ flags),
+ ACE_HANDLE,
+ ACE_INVALID_HANDLE);
+#else
+ ACE_UNUSED_ARG (protocolinfo);
+ ACE_UNUSED_ARG (g);
+ ACE_UNUSED_ARG (flags);
+
+ return ACE_OS::socket (domain,
+ type,
+ proto);
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_INLINE int
+ACE_OS::socketpair (int domain, int type,
+ int protocol, ACE_HANDLE sv[2])
+{
+ ACE_OS_TRACE ("ACE_OS::socketpair");
+#if defined (ACE_LACKS_SOCKETPAIR)
+ ACE_UNUSED_ARG (domain);
+ ACE_UNUSED_ARG (type);
+ ACE_UNUSED_ARG (protocol);
+ ACE_UNUSED_ARG (sv);
+
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::socketpair (domain, type, protocol, sv),
+ int, -1);
+#endif /* ACE_LACKS_SOCKETPAIR */
+}
+
+#if defined (__linux__) && defined (ACE_HAS_IPV6)
+ACE_INLINE unsigned int
+ACE_OS::if_nametoindex (const char *ifname)
+{
+ ACE_OS_TRACE ("ACE_OS::if_nametoindex");
+ ACE_OSCALL_RETURN (::if_nametoindex (ifname), int, 0);
+}
+
+ACE_INLINE char *
+ACE_OS::if_indextoname (unsigned int ifindex, char *ifname)
+{
+ ACE_OS_TRACE ("ACE_OS::if_indextoname");
+ ACE_OSCALL_RETURN (::if_indextoname (ifindex, ifname), char *, 0);
+}
+
+ACE_INLINE struct if_nameindex *
+ACE_OS::if_nameindex (void)
+{
+ ACE_OS_TRACE ("ACE_OS::if_nameindex");
+ ACE_OSCALL_RETURN (::if_nameindex (), struct if_nameindex *, 0);
+}
+
+ACE_INLINE void
+ACE_OS::if_freenameindex (struct if_nameindex *ptr)
+{
+ ACE_OS_TRACE ("ACE_OS::if_freenameindex");
+ if (ptr != 0)
+ ::if_freenameindex (ptr);
+}
+#endif /* __linux__ && ACE_HAS_IPV6 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_stat.cpp b/ACE/ace/OS_NS_sys_stat.cpp
new file mode 100644
index 00000000000..b5921cb86c8
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_stat.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_sys_stat.h"
+
+ACE_RCSID(ace, OS_NS_sys_stat, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_stat.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_sys_stat.h b/ACE/ace/OS_NS_sys_stat.h
new file mode 100644
index 00000000000..4afae8c1be7
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_stat.h
@@ -0,0 +1,149 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_stat.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_STAT_H
+# define ACE_OS_NS_SYS_STAT_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/os_include/sys/os_stat.h"
+#include "ace/Default_Constants.h" // for ACE_DEFAULT_DIR_PERMS
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 \
+ && defined (ACE_WIN32)
+# if defined (__BORLANDC__)
+typedef struct stati64 ACE_stat;
+# define ACE_STAT_FUNC_NAME ::_stati64
+# define ACE_WSTAT_FUNC_NAME ::_wstati64
+# elif !defined (ACE_HAS_WINCE) && defined (_MSC_VER)
+# if _MSC_VER >= 1400
+// For vc8 which has time_t as 64bit
+// 64-bit file offsets, 64-bit time_t
+# if defined (ACE_MSVC_USES_DOUBLE_UNDERSCORE_STAT64)
+typedef struct __stat64 ACE_stat;
+# else
+typedef struct _stat64 ACE_stat;
+# endif
+# define ACE_STAT_FUNC_NAME ::_stat64
+# define ACE_WSTAT_FUNC_NAME ::_wstat64
+# else
+// For vc71 which has time_t as 32bit
+typedef struct _stati64 ACE_stat;
+# define ACE_STAT_FUNC_NAME ::_stati64
+# define ACE_WSTAT_FUNC_NAME ::_wstati64
+# endif /* _MSC_VER >= 1400 */
+# else
+typedef struct stat ACE_stat;
+# define ACE_STAT_FUNC_NAME ::stat
+# define ACE_WSTAT_FUNC_NAME ACE_STAT_FUNC_NAME
+# endif /**/
+# else
+// Default file offset case.
+# if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+typedef struct _stat ACE_stat;
+# define ACE_STAT_FUNC_NAME ::_stat
+# define ACE_WSTAT_FUNC_NAME ::_wstat
+# else
+typedef struct stat ACE_stat;
+# define ACE_STAT_FUNC_NAME ::stat
+# define ACE_WSTAT_FUNC_NAME ACE_STAT_FUNC_NAME
+# endif /* ACE_WIN32 */
+# endif /* _FILE_OFFSET_BITS == 64 && ACE_WIN32 */
+
+namespace ACE_OS
+{
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE creat (const ACE_TCHAR *filename,
+ mode_t mode);
+
+ //@{ @name A set of wrappers for low-level file operations.
+
+ // non-standard
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_OFF_T filesize (ACE_HANDLE handle);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_OFF_T filesize (const ACE_TCHAR *handle);
+ //@}
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fstat (ACE_HANDLE,
+ ACE_stat *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int lstat (const char *,
+ ACE_stat *);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int lstat (const wchar_t *,
+ ACE_stat *);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int mkdir (const char *path,
+ mode_t mode = ACE_DEFAULT_DIR_PERMS);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int mkdir (const wchar_t *path,
+ mode_t mode = ACE_DEFAULT_DIR_PERMS);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int mkfifo (const ACE_TCHAR *file,
+ mode_t mode = ACE_DEFAULT_FILE_PERMS);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int stat (const char *file, ACE_stat *);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int stat (const wchar_t *file, ACE_stat *);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ mode_t umask (mode_t cmask);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_stat.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_STAT_H */
diff --git a/ACE/ace/OS_NS_sys_stat.inl b/ACE/ace/OS_NS_sys_stat.inl
new file mode 100644
index 00000000000..b8939275a5e
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_stat.inl
@@ -0,0 +1,292 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ ACE_INLINE ACE_HANDLE
+ creat (const ACE_TCHAR *filename, mode_t mode)
+ {
+ ACE_OS_TRACE ("ACE_OS::creat");
+#if defined (ACE_WIN32)
+ return ACE_OS::open (filename, O_CREAT|O_TRUNC|O_WRONLY, mode);
+#else
+ ACE_OSCALL_RETURN (::creat (ACE_TEXT_ALWAYS_CHAR (filename), mode),
+ ACE_HANDLE, ACE_INVALID_HANDLE);
+#endif /* ACE_WIN32 */
+ }
+
+ ACE_INLINE int
+ fstat (ACE_HANDLE handle, ACE_stat *stp)
+ {
+ ACE_OS_TRACE ("ACE_OS::fstat");
+#if defined (ACE_HAS_X86_STAT_MACROS)
+ // Solaris for intel uses an macro for fstat(), this is a wrapper
+ // for _fxstat() use of the macro.
+ // causes compile and runtime problems.
+ ACE_OSCALL_RETURN (::_fxstat (_STAT_VER, handle, stp), int, -1);
+#elif defined (ACE_WIN32)
+ BY_HANDLE_FILE_INFORMATION fdata;
+
+ if (::GetFileInformationByHandle (handle, &fdata) == FALSE)
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ else if (fdata.nFileSizeHigh != 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else
+ {
+ stp->st_size = fdata.nFileSizeLow;
+ stp->st_atime = ACE_Time_Value (fdata.ftLastAccessTime).sec ();
+ stp->st_mtime = ACE_Time_Value (fdata.ftLastWriteTime).sec ();
+ stp->st_ctime = ACE_Time_Value (fdata.ftCreationTime).sec ();
+ stp->st_nlink = static_cast<short> (fdata.nNumberOfLinks);
+ stp->st_dev = stp->st_rdev = 0; // No equivalent conversion.
+ stp->st_mode = S_IXOTH | S_IROTH |
+ (fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0 : S_IWOTH) |
+ (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? S_IFDIR : S_IFREG);
+ }
+ return 0;
+#else
+# if defined (ACE_OPENVMS)
+ //FUZZ: disable check_for_lack_ACE_OS
+ ::fsync(handle);
+ //FUZZ: enable check_for_lack_ACE_OS
+ #endif
+ ACE_OSCALL_RETURN (::fstat (handle, stp), int, -1);
+# endif /* !ACE_HAS_X86_STAT_MACROS */
+ }
+
+ // This function returns the number of bytes in the file referenced by
+ // FD.
+
+ ACE_INLINE ACE_OFF_T
+ filesize (ACE_HANDLE handle)
+ {
+ ACE_OS_TRACE ("ACE_OS::filesize");
+#if defined (ACE_WIN32)
+# if defined (_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
+ LARGE_INTEGER size;
+ return
+ (::GetFileSizeEx (handle, &size)
+ ? size.QuadPart
+ : (ACE_OS::set_errno_to_last_error (), -1));
+# else
+ DWORD const size = ::GetFileSize (handle, 0);
+ return
+ (size != INVALID_FILE_SIZE
+ ? static_cast<ACE_OFF_T> (size)
+ : (ACE_OS::set_errno_to_last_error (), -1));
+# endif /* _FILE_OFFSET_BITS == 64 */
+#else /* !ACE_WIN32 */
+ ACE_stat sb;
+ return ACE_OS::fstat (handle, &sb) == -1 ?
+ static_cast<ACE_OFF_T> (-1) : sb.st_size;
+#endif
+ }
+
+ ACE_INLINE ACE_OFF_T
+ filesize (const ACE_TCHAR *filename)
+ {
+ ACE_OS_TRACE ("ACE_OS::filesize");
+
+ ACE_HANDLE const h = ACE_OS::open (filename, O_RDONLY);
+ if (h != ACE_INVALID_HANDLE)
+ {
+ ACE_OFF_T size = ACE_OS::filesize (h);
+ ACE_OS::close (h);
+ return size;
+ }
+ else
+ return -1;
+ }
+
+ ACE_INLINE int
+ lstat (const char *file, ACE_stat *stp)
+ {
+ ACE_OS_TRACE ("ACE_OS::lstat");
+# if defined (ACE_LACKS_LSTAT)
+ return ACE_OS::stat (file, stp);
+# elif defined (ACE_HAS_X86_STAT_MACROS)
+ // Solaris for intel uses an macro for lstat(), this macro is a
+ // wrapper for _lxstat().
+ ACE_OSCALL_RETURN (::_lxstat (_STAT_VER, file, stp), int, -1);
+# else /* !ACE_HAS_X86_STAT_MACROS */
+ ACE_OSCALL_RETURN (::lstat (file, stp), int, -1);
+# endif /* ACE_LACKS_LSTAT */
+ }
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_INLINE int
+ lstat (const wchar_t *file, ACE_stat *stp)
+ {
+ ACE_OS_TRACE ("ACE_OS::lstat");
+# if defined (ACE_LACKS_LSTAT)
+ return ACE_OS::stat (file, stp);
+# else
+ return ACE_OS::lstat (ACE_Wide_To_Ascii (file).char_rep (), stp);
+# endif /* ACE_LACKS_LSTAT */
+ }
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_INLINE int
+ mkdir (const char *path, mode_t mode)
+ {
+#if defined (ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (mode);
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CreateDirectory (ACE_TEXT_CHAR_TO_TCHAR (path), 0),
+ ace_result_),
+ int, -1);
+#elif defined (ACE_MKDIR_LACKS_MODE)
+ ACE_UNUSED_ARG (mode);
+ ACE_OSCALL_RETURN (::mkdir (path), int, -1);
+#else
+ ACE_OSCALL_RETURN (::mkdir (path, mode), int, -1);
+#endif
+ }
+
+#if defined (ACE_HAS_WCHAR)
+
+ ACE_INLINE int
+ mkdir (const wchar_t *path, mode_t mode)
+ {
+#if defined (ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (mode);
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (CreateDirectoryW (path, 0),
+ ace_result_),
+ int, -1);
+#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_UNUSED_ARG (mode);
+ ACE_OSCALL_RETURN (::_wmkdir (path), int, -1);
+#else
+ return ACE_OS::mkdir (ACE_Wide_To_Ascii (path).char_rep (), mode);
+#endif /* ACE_HAS_WINCE */
+ }
+
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_INLINE int
+ mkfifo (const ACE_TCHAR *file, mode_t mode)
+ {
+ ACE_OS_TRACE ("ACE_OS::mkfifo");
+#if defined (ACE_LACKS_MKFIFO)
+ ACE_UNUSED_ARG (file);
+ ACE_UNUSED_ARG (mode);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::mkfifo (ACE_TEXT_ALWAYS_CHAR (file), mode), int, -1);
+#endif /* ACE_LACKS_MKFIFO */
+ }
+
+ ACE_INLINE int
+ stat (const char *file, ACE_stat *stp)
+ {
+ ACE_OS_TRACE ("ACE_OS::stat");
+#if defined (ACE_HAS_NONCONST_STAT)
+ ACE_OSCALL_RETURN (::stat (const_cast <char *> (file), stp), int, -1);
+#elif defined (ACE_HAS_WINCE)
+ ACE_TEXT_WIN32_FIND_DATA fdata;
+
+ HANDLE fhandle;
+
+ fhandle = ::FindFirstFile (ACE_TEXT_CHAR_TO_TCHAR (file), &fdata);
+ if (fhandle == INVALID_HANDLE_VALUE)
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ else if (fdata.nFileSizeHigh != 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else
+ {
+ stp->st_mode = static_cast<unsigned short>(fdata.dwFileAttributes);
+ stp->st_size = fdata.nFileSizeLow;
+ stp->st_atime = ACE_Time_Value (fdata.ftLastAccessTime);
+ stp->st_mtime = ACE_Time_Value (fdata.ftLastWriteTime);
+ }
+ return 0;
+#elif defined (ACE_HAS_X86_STAT_MACROS)
+ // Solaris for intel uses an macro for stat(), this macro is a
+ // wrapper for _xstat().
+ ACE_OSCALL_RETURN (::_xstat (_STAT_VER, file, stp), int, -1);
+#else
+ ACE_OSCALL_RETURN (ACE_STAT_FUNC_NAME (file, stp), int, -1);
+#endif /* ACE_HAS_NONCONST_STAT */
+ }
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_INLINE int
+ stat (const wchar_t *file, ACE_stat *stp)
+ {
+ ACE_OS_TRACE ("ACE_OS::stat");
+#if defined (ACE_HAS_WINCE)
+ WIN32_FIND_DATAW fdata;
+
+ HANDLE fhandle;
+
+ fhandle = ::FindFirstFileW (file, &fdata);
+ if (fhandle == INVALID_HANDLE_VALUE)
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ else if (fdata.nFileSizeHigh != 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else
+ {
+ stp->st_mode = static_cast<unsigned short>(fdata.dwFileAttributes);
+ stp->st_size = fdata.nFileSizeLow;
+ stp->st_atime = ACE_Time_Value (fdata.ftLastAccessTime);
+ stp->st_mtime = ACE_Time_Value (fdata.ftLastWriteTime);
+ }
+ return 0;
+#elif defined (__BORLANDC__) \
+ || (defined (_MSC_VER) && _MSC_VER >= 1300) \
+ || defined (__MINGW32__)
+ ACE_OSCALL_RETURN (ACE_WSTAT_FUNC_NAME (file, stp), int, -1);
+#else /* ACE_HAS_WINCE */
+ ACE_Wide_To_Ascii nfile (file);
+ return ACE_OS::stat (nfile.char_rep (), stp);
+#endif /* ACE_HAS_WINCE */
+ }
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_INLINE mode_t
+ umask (mode_t cmask)
+ {
+ ACE_OS_TRACE ("ACE_OS::umask");
+# if defined (ACE_LACKS_UMASK)
+ ACE_UNUSED_ARG (cmask);
+ ACE_NOTSUP_RETURN ((mode_t)-1);
+# elif defined (ACE_HAS_TR24731_2005_CRT)
+ mode_t old_mode;
+ ACE_SECURECRTCALL (_umask_s (cmask, &old_mode), mode_t, -1, old_mode);
+ return old_mode;
+# elif defined (ACE_WIN32) && !defined (__BORLANDC__)
+ ACE_OSCALL_RETURN (::_umask (cmask), mode_t, -1);
+# else
+ return ::umask (cmask); // This call shouldn't fail...
+# endif /* ACE_LACKS_UMASK */
+ }
+
+} // ACE_OS namespace
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_time.cpp b/ACE/ace/OS_NS_sys_time.cpp
new file mode 100644
index 00000000000..e04815edc36
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_time.cpp
@@ -0,0 +1,10 @@
+// $Id$
+
+#include "ace/OS_NS_sys_time.h"
+
+ACE_RCSID(ace, OS_NS_sys_time, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_time.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
diff --git a/ACE/ace/OS_NS_sys_time.h b/ACE/ace/OS_NS_sys_time.h
new file mode 100644
index 00000000000..898c57f8155
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_time.h
@@ -0,0 +1,69 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_time.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_TIME_H
+# define ACE_OS_NS_SYS_TIME_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/Time_Value.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+#if defined (ACE_WIN32) && defined (_WIN32_WCE)
+// Something is a bit brain-damaged here and I'm not sure what... this code
+// compiled before the OS reorg for ACE 5.4. Since then it hasn't - eVC
+// complains that the operators that return ACE_Time_Value are C-linkage
+// functions that can't return a C++ class. The only way I've found to
+// defeat this is to wrap the whole class in extern "C++".
+// - Steve Huston, 23-Aug-2004
+extern "C++" {
+#endif
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_Time_Value gettimeofday (void);
+
+#if defined (ACE_WIN32) && defined (_WIN32_WCE)
+}
+#endif
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_time.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_TIME_H */
diff --git a/ACE/ace/OS_NS_sys_time.inl b/ACE/ace/OS_NS_sys_time.inl
new file mode 100644
index 00000000000..9300e4ac011
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_time.inl
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/os_include/sys/os_time.h"
+#include "ace/os_include/os_errno.h"
+
+#if defined (ACE_VXWORKS)
+# include "ace/OS_NS_time.h"
+#endif /* ACE_VXWORKS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_WIN32) && defined (_WIN32_WCE)
+// Something is a bit brain-damaged here and I'm not sure what... this code
+// compiled before the OS reorg for ACE 5.4. Since then it hasn't - eVC
+// complains that the operators that return ACE_Time_Value are C-linkage
+// functions that can't return a C++ class. The only way I've found to
+// defeat this is to wrap the whole class in extern "C++".
+// - Steve Huston, 23-Aug-2004
+extern "C++" {
+#endif
+
+ACE_INLINE ACE_Time_Value
+ACE_OS::gettimeofday (void)
+{
+ // ACE_OS_TRACE ("ACE_OS::gettimeofday");
+
+#if !defined (ACE_HAS_WINCE)&& !defined (ACE_WIN32)
+ timeval tv;
+ int result = 0;
+#endif // !defined (ACE_HAS_WINCE)&& !defined (ACE_WIN32)
+
+#if (0)
+ struct timespec ts;
+
+ ACE_OSCALL (ACE_OS::clock_gettime (CLOCK_REALTIME, &ts), int, -1, result);
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000L; // timespec has nsec, but timeval has usec
+
+#elif defined (ACE_HAS_WINCE)
+ SYSTEMTIME tsys;
+ FILETIME tfile;
+ ::GetSystemTime (&tsys);
+ ::SystemTimeToFileTime (&tsys, &tfile);
+ return ACE_Time_Value (tfile);
+#elif defined (ACE_WIN32)
+ FILETIME tfile;
+ ::GetSystemTimeAsFileTime (&tfile);
+ return ACE_Time_Value (tfile);
+#if 0
+ // From Todd Montgomery...
+ struct _timeb tb;
+ ::_ftime (&tb);
+ tv.tv_sec = tb.time;
+ tv.tv_usec = 1000 * tb.millitm;
+#endif /* 0 */
+#elif defined (ACE_HAS_AIX_HI_RES_TIMER)
+ timebasestruct_t tb;
+
+ ::read_real_time (&tb, TIMEBASE_SZ);
+ ::time_base_to_time (&tb, TIMEBASE_SZ);
+
+ tv.tv_sec = tb.tb_high;
+ tv.tv_usec = tb.tb_low / 1000L;
+#else
+# if defined (ACE_HAS_TIMEZONE_GETTIMEOFDAY) || \
+ defined(ACE_HAS_VOIDPTR_GETTIMEOFDAY) || \
+ (defined (ACE_HAS_SVR4_GETTIMEOFDAY) && !defined (SCO))
+ ACE_OSCALL (::gettimeofday (&tv, 0), int, -1, result);
+# elif defined (ACE_VXWORKS)
+ // Assumes that struct timespec is same size as struct timeval,
+ // which assumes that time_t is a long: it currently (VxWorks
+ // 5.2/5.3) is.
+ struct timespec ts;
+
+ ACE_OSCALL (ACE_OS::clock_gettime (CLOCK_REALTIME, &ts), int, -1, result);
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000L; // timespec has nsec, but timeval has usec
+# else
+ ACE_OSCALL (::gettimeofday (&tv), int, -1, result);
+# endif /* ACE_HAS_SVR4_GETTIMEOFDAY */
+#endif /* 0 */
+#if !defined (ACE_HAS_WINCE)&& !defined (ACE_WIN32)
+ if (result == -1)
+ return ACE_Time_Value ((time_t)-1);
+ else
+ return ACE_Time_Value (tv);
+#endif // !defined (ACE_HAS_WINCE)&& !defined (ACE_WIN32)
+}
+
+#if defined (ACE_WIN32) && defined (_WIN32_WCE)
+}
+#endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_uio.cpp b/ACE/ace/OS_NS_sys_uio.cpp
new file mode 100644
index 00000000000..b87df5bc8b0
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_uio.cpp
@@ -0,0 +1,130 @@
+// $Id$
+
+#include "ace/OS_NS_sys_uio.h"
+
+ACE_RCSID(ace, OS_NS_sys_uio, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_uio.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_LACKS_READV)
+
+// "Fake" readv for operating systems without it. Note that this is
+// thread-safe.
+
+ssize_t
+ACE_OS::readv_emulation (ACE_HANDLE handle,
+ const iovec *iov,
+ int n)
+{
+ ACE_OS_TRACE ("ACE_OS::readv_emulation");
+
+ // In case there's a single element, skip the memcpy.
+ if (1 == n)
+ return ACE_OS::read (handle, iov[0].iov_base, iov[0].iov_len);
+
+ ssize_t length = 0;
+ int i;
+
+ for (i = 0; i < n; ++i)
+ if (static_cast<int> (iov[i].iov_len) < 0)
+ return -1;
+ else
+ length += iov[i].iov_len;
+
+ char *buf;
+# if defined (ACE_HAS_ALLOCA)
+ buf = (char *) alloca (length);
+# else
+ ACE_NEW_RETURN (buf,
+ char[length],
+ -1);
+# endif /* !defined (ACE_HAS_ALLOCA) */
+
+ length = ACE_OS::read (handle, buf, length);
+
+ if (length != -1)
+ {
+ char *ptr = buf;
+ ssize_t 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_LACKS_READV */
+
+# if defined (ACE_LACKS_WRITEV)
+
+// "Fake" writev for operating systems without it. Note that this is
+// thread-safe.
+
+ssize_t
+ACE_OS::writev_emulation (ACE_HANDLE handle, const iovec *iov, int n)
+{
+ ACE_OS_TRACE ("ACE_OS::writev_emulation");
+
+ // To avoid having to allocate a temporary buffer to which all of
+ // the data will be copied and then written, this implementation
+ // performs incremental writes.
+
+ ssize_t bytes_sent = 0;
+
+ for (int i = 0; i < n; ++i)
+ {
+ const ssize_t result =
+ ACE_OS::write (handle, iov[i].iov_base, iov[i].iov_len);
+
+ if (result == -1)
+ {
+ // There is a subtle difference in behaviour depending on
+ // whether or not any data was sent. If no data was sent,
+ // then always return -1. Otherwise return bytes_sent.
+ // This gives the caller an opportunity to keep track of
+ // bytes that have already been sent.
+ if (bytes_sent > 0)
+ break;
+ else
+ return -1;
+ }
+ else
+ {
+ bytes_sent += result;
+
+ // Do not continue on to the next loop iteration if the
+ // amount of data sent was less than the amount data given.
+ // This avoids a subtle problem where "holes" in the data
+ // stream would occur if partial sends of a given buffer in
+ // the iovec array occured.
+ if (static_cast<size_t> (result) < iov[i].iov_len)
+ break;
+ }
+ }
+
+ return bytes_sent;
+}
+# endif /* ACE_LACKS_WRITEV */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_uio.h b/ACE/ace/OS_NS_sys_uio.h
new file mode 100644
index 00000000000..ed746ad9b2e
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_uio.h
@@ -0,0 +1,80 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_uio.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_UIO_H
+# define ACE_OS_NS_SYS_UIO_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/os_include/sys/os_uio.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t readv (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovlen);
+
+#if defined (ACE_LACKS_READV)
+ extern ACE_Export
+ ssize_t readv_emulation (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt);
+#endif /* ACE_LACKS_READV */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t writev (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt);
+
+ // these don't need to be in the header, better to put them in the cpp
+ // or inl.
+#if defined (ACE_LACKS_WRITEV)
+ extern ACE_Export
+ ssize_t writev_emulation (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt);
+#endif /* ACE_LACKS_WRITEV */
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_uio.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_UIO_H */
diff --git a/ACE/ace/OS_NS_sys_uio.inl b/ACE/ace/OS_NS_sys_uio.inl
new file mode 100644
index 00000000000..b8d112bba84
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_uio.inl
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/os_include/os_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ssize_t
+ACE_OS::readv (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovlen)
+{
+ ACE_OS_TRACE ("ACE_OS::readv");
+#if defined (ACE_LACKS_READV)
+ ACE_OSCALL_RETURN (ACE_OS::readv_emulation (handle, iov, iovlen),
+ ssize_t,
+ -1);
+#else /* ACE_LACKS_READV */
+#if defined (ACE_HAS_NONCONST_READV)
+ ACE_OSCALL_RETURN (::readv (handle,
+ const_cast<iovec *>(iov),
+ iovlen), ssize_t, -1);
+#else
+ ACE_OSCALL_RETURN (::readv (handle,
+ iov,
+ iovlen), ssize_t, -1);
+#endif /* ACE_HAS_NONCONST_READV */
+#endif /* ACE_LACKS_READV */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::writev (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt)
+{
+ ACE_OS_TRACE ("ACE_OS::writev");
+#if defined (ACE_LACKS_WRITEV)
+ ACE_OSCALL_RETURN (ACE_OS::writev_emulation (handle,
+ iov,
+ iovcnt), ssize_t, -1);
+#else /* ACE_LACKS_WRITEV */
+#if defined (ACE_HAS_NONCONST_WRITEV)
+ ACE_OSCALL_RETURN (::writev (handle,
+ const_cast<iovec *>(iov),
+ iovcnt), ssize_t, -1);
+#else
+ ACE_OSCALL_RETURN (::writev (handle,
+ iov,
+ iovcnt), ssize_t, -1);
+#endif /* ACE_HAS_NONCONST_WRITEV */
+#endif /* ACE_LACKS_WRITEV */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_utsname.cpp b/ACE/ace/OS_NS_sys_utsname.cpp
new file mode 100644
index 00000000000..f8ec8043fc3
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_utsname.cpp
@@ -0,0 +1,237 @@
+// $Id$
+
+#include "ace/OS_NS_sys_utsname.h"
+
+ACE_RCSID(ace, OS_NS_sys_utsname, "$Id$")
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_UNAME)
+// for sysBspRev(), sysModel()
+# include /**/ <sysLib.h>
+// for kernelVersion()
+# include /**/ <kernelLib.h>
+#endif /* ACE_VXWORKS && ACE_LACKS_UNAME */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_OS::uname (ACE_utsname *name)
+{
+ ACE_OS_TRACE ("ACE_OS::uname");
+#if !defined (ACE_LACKS_UNAME)
+ ACE_OSCALL_RETURN (::uname (name), int, -1);
+#elif defined (ACE_WIN32)
+ size_t maxnamelen = sizeof name->nodename;
+ ACE_OS::strcpy (name->sysname, "Win32");
+
+ ACE_TEXT_OSVERSIONINFO vinfo;
+ vinfo.dwOSVersionInfoSize = sizeof(ACE_TEXT_OSVERSIONINFO);
+ ACE_TEXT_GetVersionEx (&vinfo);
+
+ SYSTEM_INFO sinfo;
+# if defined (ACE_HAS_PHARLAP)
+ // PharLap doesn't do GetSystemInfo. What's really wanted is the
+ // CPU architecture, so we can get that with EtsGetSystemInfo. Fill
+ // in what's wanted in the SYSTEM_INFO structure, and carry on. Note
+ // that the CPU type values in EK_KERNELINFO have the same values
+ // are the ones defined for SYSTEM_INFO.
+ EK_KERNELINFO ets_kern;
+ EK_SYSTEMINFO ets_sys;
+ EtsGetSystemInfo (&ets_kern, &ets_sys);
+ sinfo.wProcessorLevel = static_cast<WORD> (ets_kern.CpuType);
+ sinfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
+ sinfo.dwProcessorType = ets_kern.CpuType * 100 + 86;
+# else
+ ::GetSystemInfo(&sinfo);
+# endif /* ACE_HAS_PHARLAP */
+
+ const char* unknown = "???";
+
+ if (
+ vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT
+# if defined (VER_PLATFORM_WIN32_CE)
+ || vinfo.dwPlatformId == VER_PLATFORM_WIN32_CE
+# endif
+ )
+ {
+ // Get information from the two structures
+ const char *os;
+ if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ os = "Windows NT %d.%d";
+ else
+ os = "Windows CE %d.%d";
+ ACE_OS::sprintf (name->release,
+ os,
+ (int) vinfo.dwMajorVersion,
+ (int) vinfo.dwMinorVersion);
+ ACE_OS::sprintf (name->version,
+ "Build %d %s",
+ (int) vinfo.dwBuildNumber,
+ ACE_TEXT_ALWAYS_CHAR (vinfo.szCSDVersion));
+
+ // We have to make sure that the size of (processor + subtype)
+ // is not greater than the size of name->machine. So we give
+ // half the space to the processor and half the space to
+ // subtype. The -1 is necessary for because of the space
+ // between processor and subtype in the machine name.
+ const int bufsize = (sizeof (name->machine) / 2) - 1;
+ char processor[bufsize] = "Unknown";
+ char subtype[bufsize] = "Unknown";
+
+# if defined (ghs)
+ WORD arch = sinfo.u.s.wProcessorArchitecture;
+# else
+ WORD arch = sinfo.wProcessorArchitecture;
+# endif
+
+ switch (arch)
+ {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ ACE_OS::strcpy (processor, "Intel");
+ if (sinfo.wProcessorLevel == 3)
+ ACE_OS::strcpy (subtype, "80386");
+ else if (sinfo.wProcessorLevel == 4)
+ ACE_OS::strcpy (subtype, "80486");
+ else if (sinfo.wProcessorLevel == 5)
+ ACE_OS::strcpy (subtype, "Pentium");
+ else if (sinfo.wProcessorLevel == 6)
+ ACE_OS::strcpy (subtype, "Pentium Pro");
+ else if (sinfo.wProcessorLevel == 7) // I'm guessing here
+ ACE_OS::strcpy (subtype, "Pentium II");
+ break;
+ case PROCESSOR_ARCHITECTURE_MIPS:
+ ACE_OS::strcpy (processor, "MIPS");
+ ACE_OS::strcpy (subtype, "R4000");
+ break;
+ case PROCESSOR_ARCHITECTURE_ALPHA:
+ ACE_OS::strcpy (processor, "Alpha");
+ ACE_OS::sprintf (subtype, "%d", sinfo.wProcessorLevel);
+ break;
+ case PROCESSOR_ARCHITECTURE_PPC:
+ ACE_OS::strcpy (processor, "PPC");
+ if (sinfo.wProcessorLevel == 1)
+ ACE_OS::strcpy (subtype, "601");
+ else if (sinfo.wProcessorLevel == 3)
+ ACE_OS::strcpy (subtype, "603");
+ else if (sinfo.wProcessorLevel == 4)
+ ACE_OS::strcpy (subtype, "604");
+ else if (sinfo.wProcessorLevel == 6)
+ ACE_OS::strcpy (subtype, "603+");
+ else if (sinfo.wProcessorLevel == 9)
+ ACE_OS::strcpy (subtype, "804+");
+ else if (sinfo.wProcessorLevel == 20)
+ ACE_OS::strcpy (subtype, "620");
+ break;
+# if defined PROCESSOR_ARCHITECTURE_IA64
+ case PROCESSOR_ARCHITECTURE_IA64:
+ ACE_OS::strcpy (processor, "Itanium");
+ ACE_OS::sprintf (subtype, "%d",
+ sinfo.wProcessorLevel);
+ break;
+# endif
+# if defined PROCESSOR_ARCHITECTURE_AMD64
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ ACE_OS::strcpy (processor, "x64");
+ ACE_OS::sprintf (subtype, "%d",
+ sinfo.wProcessorLevel);
+ break;
+# endif
+# if defined PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
+ case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
+ ACE_OS::strcpy (processor, "WOW64");
+ ACE_OS::sprintf (subtype, "%d",
+ sinfo.wProcessorLevel);
+ break;
+# endif
+# if defined PROCESSOR_ARCHITECTURE_ARM
+ case PROCESSOR_ARCHITECTURE_ARM:
+ ACE_OS::strcpy (processor, "ARM");
+ ACE_OS::sprintf (subtype, "%d",
+ sinfo.wProcessorLevel);
+ break;
+# endif
+ case PROCESSOR_ARCHITECTURE_UNKNOWN:
+ default:
+ // @@ We could provide WinCE specific info here. But let's
+ // defer that to some later point.
+ ACE_OS::strcpy (processor, "Unknown");
+ break;
+ }
+ ACE_OS::sprintf (name->machine,
+ "%s %s",
+ processor, subtype);
+ }
+ else if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ {
+ if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 0)
+ {
+ ACE_OS::strcpy (name->release, "Windows 95");
+ if (vinfo.szCSDVersion[1] == ACE_TEXT('C'))
+ ACE_OS::strcat (name->release, " OSR2");
+ }
+ else if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 10)
+ {
+ ACE_OS::strcpy (name->release, "Windows 98");
+ if (vinfo.szCSDVersion[1] == ACE_TEXT('A'))
+ ACE_OS::strcat (name->release, " SE");
+ }
+ else if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 90)
+ {
+ ACE_OS::strcpy (name->release, "Windows Me");
+ }
+ else
+ {
+ ACE_OS::strcpy (name->release, unknown);
+ }
+
+ ACE_OS::sprintf (name->version, "%d", LOWORD (vinfo.dwBuildNumber));
+ if (sinfo.dwProcessorType == PROCESSOR_INTEL_386)
+ ACE_OS::strcpy (name->machine, "Intel 80386");
+ else if (sinfo.dwProcessorType == PROCESSOR_INTEL_486)
+ ACE_OS::strcpy (name->machine, "Intel 80486");
+ else if (sinfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
+ ACE_OS::strcpy (name->machine, "Intel Pentium");
+ else
+ ACE_OS::strcpy (name->machine, unknown);
+ }
+ else
+ {
+ // We don't know what this is!
+
+ ACE_OS::strcpy (name->release, unknown);
+ ACE_OS::strcpy (name->version, unknown);
+ ACE_OS::strcpy (name->machine, unknown);
+ }
+
+# if defined (ACE_LACKS_HOSTNAME)
+ return 0;
+# else /* ACE_LACKS_HOSTNAME */
+ return ACE_OS::hostname (name->nodename, maxnamelen);
+# endif /* ACE_LACKS_HOSTNAME */
+
+#elif defined (ACE_VXWORKS)
+ size_t maxnamelen = sizeof name->nodename;
+ ACE_OS::strcpy (name->sysname, "VxWorks");
+ ACE_OS::strcpy (name->release, kernelVersion());
+ ACE_OS::strcpy (name->version, sysBspRev ());
+ ACE_OS::strcpy (name->machine, sysModel ());
+
+ return ACE_OS::hostname (name->nodename, maxnamelen);
+#elif defined (INTEGRITY)
+ if(!name) {
+ errno = EFAULT;
+ return -1;
+ }
+ strcpy(name->sysname,"INTEGRITY");
+ int status = gethostname(name->nodename,_SYS_NMLN);
+ strcpy(name->release,"4.0");
+ strcpy(name->version,"4.0.9");
+ strcpy(name->machine,"a standard name");
+ return status;
+#endif /* ACE_WIN32 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_sys_utsname.h b/ACE/ace/OS_NS_sys_utsname.h
new file mode 100644
index 00000000000..5dde284c8cf
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_utsname.h
@@ -0,0 +1,71 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_utsname.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_UTSNAME_H
+# define ACE_OS_NS_SYS_UTSNAME_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/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+#if defined (ACE_LACKS_UTSNAME_T)
+# if !defined (SYS_NMLN)
+# define SYS_NMLN 257
+# endif /* SYS_NMLN */
+# if !defined (_SYS_NMLN)
+# define _SYS_NMLN SYS_NMLN
+# endif /* _SYS_NMLN */
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+struct ACE_utsname
+{
+ char sysname[_SYS_NMLN];
+ char nodename[_SYS_NMLN];
+ char release[_SYS_NMLN];
+ char version[_SYS_NMLN];
+ char machine[_SYS_NMLN];
+};
+ACE_END_VERSIONED_NAMESPACE_DECL
+# else
+# include "ace/os_include/sys/os_utsname.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+typedef struct utsname ACE_utsname;
+ACE_END_VERSIONED_NAMESPACE_DECL
+# endif /* ACE_LACKS_UTSNAME_T */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ extern ACE_Export
+ int uname (ACE_utsname *name);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_UTSNAME_H */
diff --git a/ACE/ace/OS_NS_sys_wait.cpp b/ACE/ace/OS_NS_sys_wait.cpp
new file mode 100644
index 00000000000..2eacfc313ca
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_wait.cpp
@@ -0,0 +1,9 @@
+// $Id$
+
+#include "ace/OS_NS_sys_wait.h"
+
+ACE_RCSID(ace, OS_NS_sys_wait, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_sys_wait.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
diff --git a/ACE/ace/OS_NS_sys_wait.h b/ACE/ace/OS_NS_sys_wait.h
new file mode 100644
index 00000000000..59628474ad6
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_wait.h
@@ -0,0 +1,87 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_sys_wait.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_SYS_WAIT_H
+# define ACE_OS_NS_SYS_WAIT_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/os_include/sys/os_wait.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ /// Calls OS @c ::wait function, so it's only portable to UNIX/POSIX
+ /// platforms.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ pid_t wait (int * = 0);
+
+ /**
+ * Calls @c ::WaitForSingleObject on Win32 and ACE::waitpid ()
+ * otherwise. Returns the passed in @a pid_t on success and -1 on
+ * failure.
+ * On Win32, @a pid is ignored if the @a handle is not equal to 0.
+ * Passing the process @a handle is prefer on Win32 because using
+ * @a pid to wait on the project doesn't always work correctly
+ * if the waited process has already terminated.
+ */
+ ACE_NAMESPACE_INLINE_FUNCTION
+ pid_t wait (pid_t pid,
+ ACE_exitcode *status,
+ int wait_options = 0,
+ ACE_HANDLE handle = 0);
+
+ /**
+ * Calls @c ::waitpid on UNIX/POSIX platforms Does not work on Vxworks 5.5.x.
+ * On Win32, @a pid is ignored if the @a handle is not equal to 0.
+ * Passing the process @a handle is prefer on Win32 because using
+ * @a pid to wait on the project doesn't always work correctly
+ * if the waited process has already terminated.
+ */
+ ACE_NAMESPACE_INLINE_FUNCTION
+ pid_t waitpid (pid_t pid,
+ ACE_exitcode *status = 0,
+ int wait_options = 0,
+ ACE_HANDLE handle = 0);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_sys_wait.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_SYS_WAIT_H */
diff --git a/ACE/ace/OS_NS_sys_wait.inl b/ACE/ace/OS_NS_sys_wait.inl
new file mode 100644
index 00000000000..2503d509828
--- /dev/null
+++ b/ACE/ace/OS_NS_sys_wait.inl
@@ -0,0 +1,105 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE pid_t
+ACE_OS::wait (int *status)
+{
+ ACE_OS_TRACE ("ACE_OS::wait");
+#if defined (ACE_LACKS_WAIT)
+ ACE_UNUSED_ARG (status);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN (::wait (status), pid_t, -1);
+#endif /* ACE_LACKS_WAIT */
+}
+
+ACE_INLINE pid_t
+ACE_OS::waitpid (pid_t pid,
+ ACE_exitcode *status,
+ int wait_options,
+ ACE_HANDLE handle)
+{
+ ACE_OS_TRACE ("ACE_OS::waitpid");
+#if defined (ACE_LACKS_WAITPID)
+ ACE_UNUSED_ARG (pid);
+ ACE_UNUSED_ARG (status);
+ ACE_UNUSED_ARG (wait_options);
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_WIN32)
+ int blocking_period = ACE_BIT_ENABLED (wait_options, WNOHANG)
+ ? 0 /* don't hang */
+ : INFINITE;
+
+ ACE_HANDLE phandle = handle;
+
+ if (phandle == 0)
+ {
+ phandle = ::OpenProcess (SYNCHRONIZE,
+ FALSE,
+ pid);
+
+ if (phandle == 0)
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+ }
+
+ pid_t result = pid;
+
+ // Don't try to get the process exit status if wait failed so we can
+ // keep the original error code intact.
+ switch (::WaitForSingleObject (phandle,
+ blocking_period))
+ {
+ case WAIT_OBJECT_0:
+ if (status != 0)
+ // The error status of <GetExitCodeProcess> is nonetheless
+ // not tested because we don't know how to return the value.
+ ::GetExitCodeProcess (phandle,
+ status);
+ break;
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ result = 0;
+ break;
+ default:
+ ACE_OS::set_errno_to_last_error ();
+ result = -1;
+ }
+ if (handle == 0)
+ ::CloseHandle (phandle);
+ return result;
+#elif defined(ACE_TANDEM_T1248_PTHREADS)
+ ACE_UNUSED_ARG (handle);
+ ACE_OSCALL_RETURN (::spt_waitpid (pid, status, wait_options),
+ pid_t, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_OSCALL_RETURN (::waitpid (pid, status, wait_options),
+ pid_t, -1);
+#endif /* ACE_LACKS_WAITPID */
+}
+
+ACE_INLINE pid_t
+ACE_OS::wait (pid_t pid,
+ ACE_exitcode *status,
+ int wait_options,
+ ACE_HANDLE handle)
+{
+ ACE_OS_TRACE ("ACE_OS::wait");
+ return ACE_OS::waitpid (pid,
+ status,
+ wait_options,
+ handle);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_time.cpp b/ACE/ace/OS_NS_time.cpp
new file mode 100644
index 00000000000..18f5b73c15c
--- /dev/null
+++ b/ACE/ace/OS_NS_time.cpp
@@ -0,0 +1,634 @@
+// $Id$
+
+#include "ace/OS_NS_time.h"
+
+ACE_RCSID(ace, OS_NS_time, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_time.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if defined (ACE_LACKS_STRPTIME)
+# include "ace/os_include/os_ctype.h"
+#endif /* ACE_LACKS_STRPTIME */
+
+#include "ace/OS_NS_Thread.h"
+#include "ace/Object_Manager_Base.h"
+
+#if defined (ACE_HAS_WINCE)
+# include "ace/OS_NS_stdio.h" /* Need ACE_OS::sprintf() */
+
+namespace
+{
+ ACE_TCHAR const * const ACE_OS_day_of_week_name[] =
+ {
+ ACE_TEXT ("Sun"),
+ ACE_TEXT ("Mon"),
+ ACE_TEXT ("Tue"),
+ ACE_TEXT ("Wed"),
+ ACE_TEXT ("Thu"),
+ ACE_TEXT ("Fri"),
+ ACE_TEXT ("Sat")
+ };
+
+ ACE_TCHAR const * const ACE_OS_month_name[] =
+ {
+ ACE_TEXT ("Jan"),
+ ACE_TEXT ("Feb"),
+ ACE_TEXT ("Mar"),
+ ACE_TEXT ("Apr"),
+ ACE_TEXT ("May"),
+ ACE_TEXT ("Jun"),
+ ACE_TEXT ("Jul"),
+ ACE_TEXT ("Aug"),
+ ACE_TEXT ("Sep"),
+ ACE_TEXT ("Oct"),
+ ACE_TEXT ("Nov"),
+ ACE_TEXT ("Dec")
+ };
+
+ static ACE_TCHAR const ACE_OS_CTIME_R_FMTSTR[] = ACE_TEXT ("%3s %3s %02d %02d:%02d:%02d %04d\n");
+} /* end blank namespace */
+#endif /* ACE_HAS_WINCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_WINCE)
+ACE_TCHAR *
+ACE_OS::ctime_r (const time_t *clock, ACE_TCHAR *buf, int buflen)
+{
+ // buflen must be at least 26 wchar_t long.
+ if (buflen < 26) // Again, 26 is a magic number.
+ {
+ errno = ERANGE;
+ return 0;
+ }
+ // This is really stupid, converting FILETIME to timeval back and
+ // forth. It assumes FILETIME and DWORDLONG are the same structure
+ // internally.
+ ULARGE_INTEGER _100ns;
+ _100ns.QuadPart = (DWORDLONG) *clock * 10000 * 1000
+ + ACE_Time_Value::FILETIME_to_timval_skew;
+ FILETIME file_time;
+ file_time.dwLowDateTime = _100ns.LowPart;
+ file_time.dwHighDateTime = _100ns.HighPart;
+
+ FILETIME localtime;
+ SYSTEMTIME systime;
+ FileTimeToLocalFileTime (&file_time, &localtime);
+ FileTimeToSystemTime (&localtime, &systime);
+ ACE_OS::sprintf (buf, ACE_OS_CTIME_R_FMTSTR,
+ ACE_OS_day_of_week_name[systime.wDayOfWeek],
+ ACE_OS_month_name[systime.wMonth - 1],
+ systime.wDay,
+ systime.wHour,
+ systime.wMinute,
+ systime.wSecond,
+ systime.wYear);
+ return buf;
+}
+# endif /* ACE_HAS_WINCE */
+
+# if defined (ACE_LACKS_DIFFTIME)
+double
+ACE_OS::difftime (time_t t1, time_t t0)
+{
+ /* return t1 - t0 in seconds */
+ struct tm tms[2], *ptms[2], temp;
+ double seconds;
+ int swap = 0;
+
+ /* extract the tm structure from time_t */
+ ptms[1] = ::gmtime_r (&t1, &tms[1]);
+ if (ptms[1] == 0) return 0.0;
+
+ ptms[0] = ::gmtime_r (&t0, &tms[0]);
+ if (ptms[0] == 0) return 0.0;
+
+ /* make sure t1 is > t0 */
+ if (tms[1].tm_year < tms[0].tm_year)
+ swap = 1;
+ else if (tms[1].tm_year == tms[0].tm_year)
+ {
+ if (tms[1].tm_yday < tms[0].tm_yday)
+ swap = 1;
+ else if (tms[1].tm_yday == tms[0].tm_yday)
+ {
+ if (tms[1].tm_hour < tms[0].tm_hour)
+ swap = 1;
+ else if (tms[1].tm_hour == tms[0].tm_hour)
+ {
+ if (tms[1].tm_min < tms[0].tm_min)
+ swap = 1;
+ else if (tms[1].tm_min == tms[0].tm_min)
+ {
+ if (tms[1].tm_sec < tms[0].tm_sec)
+ swap = 1;
+ }
+ }
+ }
+ }
+
+ if (swap)
+ temp = tms[0], tms[0] = tms[1], tms[1] = temp;
+
+ seconds = 0.0;
+ if (tms[1].tm_year > tms[0].tm_year)
+ {
+ // Accumulate the time until t[0] catches up to t[1]'s year.
+ seconds = 60 - tms[0].tm_sec;
+ tms[0].tm_sec = 0;
+ tms[0].tm_min += 1;
+ seconds += 60 * (60 - tms[0].tm_min);
+ tms[0].tm_min = 0;
+ tms[0].tm_hour += 1;
+ seconds += 60*60 * (24 - tms[0].tm_hour);
+ tms[0].tm_hour = 0;
+ tms[0].tm_yday += 1;
+
+# define ISLEAPYEAR(y) ((y)&3u?0:(y)%25u?1:(y)/25u&12?0:1)
+
+ if (ISLEAPYEAR(tms[0].tm_year))
+ seconds += 60*60*24 * (366 - tms[0].tm_yday);
+ else
+ seconds += 60*60*24 * (365 - tms[0].tm_yday);
+
+ tms[0].tm_yday = 0;
+ tms[0].tm_year += 1;
+
+ while (tms[1].tm_year > tms[0].tm_year)
+ {
+ if (ISLEAPYEAR(tms[0].tm_year))
+ seconds += 60*60*24 * 366;
+ else
+ seconds += 60*60*24 * 365;
+
+ tms[0].tm_year += 1;
+ }
+
+# undef ISLEAPYEAR
+
+ }
+ else
+ {
+ // Normalize
+ if (tms[1].tm_sec < tms[0].tm_sec)
+ {
+ if (tms[1].tm_min == 0)
+ {
+ if (tms[1].tm_hour == 0)
+ {
+ tms[1].tm_yday -= 1;
+ tms[1].tm_hour += 24;
+ }
+ tms[1].tm_hour -= 1;
+ tms[1].tm_min += 60;
+ }
+ tms[1].tm_min -= 1;
+ tms[1].tm_sec += 60;
+ }
+ tms[1].tm_sec -= tms[0].tm_sec;
+
+ if (tms[1].tm_min < tms[0].tm_min)
+ {
+ if (tms[1].tm_hour == 0)
+ {
+ tms[1].tm_yday -= 1;
+ tms[1].tm_hour += 24;
+ }
+ tms[1].tm_hour -= 1;
+ tms[1].tm_min += 60;
+ }
+ tms[1].tm_min -= tms[0].tm_min;
+
+ if (tms[1].tm_hour < tms[0].tm_hour)
+ {
+ tms[1].tm_yday -= 1;
+ tms[1].tm_hour += 24;
+ }
+ tms[1].tm_hour -= tms[0].tm_hour;
+
+ tms[1].tm_yday -= tms[0].tm_yday;
+ }
+
+ // accumulate the seconds
+ seconds += tms[1].tm_sec;
+ seconds += 60 * tms[1].tm_min;
+ seconds += 60*60 * tms[1].tm_hour;
+ seconds += 60*60*24 * tms[1].tm_yday;
+
+ return seconds;
+}
+# endif /* ACE_LACKS_DIFFTIME */
+
+struct tm *
+ACE_OS::localtime_r (const time_t *t, struct tm *res)
+{
+ ACE_OS_TRACE ("ACE_OS::localtime_r");
+#if defined (ACE_HAS_REENTRANT_FUNCTIONS)
+# if defined (DIGITAL_UNIX)
+ ACE_OSCALL_RETURN (::_Plocaltime_r (t, res), struct tm *, 0);
+# else
+ ACE_OSCALL_RETURN (::localtime_r (t, res), struct tm *, 0);
+# endif /* DIGITAL_UNIX */
+#elif defined (ACE_HAS_TR24731_2005_CRT)
+ ACE_SECURECRTCALL (localtime_s (res, t), struct tm *, 0, res);
+ return res;
+#elif !defined (ACE_HAS_WINCE)
+ ACE_OS_GUARD
+
+ ACE_UNUSED_ARG (res);
+ struct tm * res_ptr;
+ ACE_OSCALL (::localtime (t), struct tm *, 0, res_ptr);
+ if (res_ptr == 0)
+ return 0;
+ else
+ {
+ *res = *res_ptr;
+ return res;
+ }
+#elif defined (ACE_HAS_WINCE)
+ // This is really stupid, converting FILETIME to timeval back and
+ // forth. It assumes FILETIME and DWORDLONG are the same structure
+ // internally.
+
+ TIME_ZONE_INFORMATION pTz;
+
+ const unsigned short int __mon_yday[2][13] =
+ {
+ /* Normal years. */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* Leap years. */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+ };
+
+ ULARGE_INTEGER _100ns;
+ ::GetTimeZoneInformation (&pTz);
+
+ _100ns.QuadPart = (DWORDLONG) *t * 10000 * 1000 + ACE_Time_Value::FILETIME_to_timval_skew;
+ FILETIME file_time;
+ file_time.dwLowDateTime = _100ns.LowPart;
+ file_time.dwHighDateTime = _100ns.HighPart;
+
+ FILETIME localtime;
+ SYSTEMTIME systime;
+ FileTimeToLocalFileTime (&file_time, &localtime);
+ FileTimeToSystemTime (&localtime, &systime);
+
+ res->tm_hour = systime.wHour;
+
+ if(pTz.DaylightBias!=0)
+ res->tm_isdst = 1;
+ else
+ res->tm_isdst = 1;
+
+ int iLeap;
+ iLeap = (res->tm_year % 4 == 0 && (res->tm_year% 100 != 0 || res->tm_year % 400 == 0));
+ // based on leap select which group to use
+
+ res->tm_mday = systime.wDay;
+ res->tm_min = systime.wMinute;
+ res->tm_mon = systime.wMonth - 1;
+ res->tm_sec = systime.wSecond;
+ res->tm_wday = systime.wDayOfWeek;
+ res->tm_yday = __mon_yday[iLeap][systime.wMonth] + systime.wDay;
+ res->tm_year = systime.wYear;// this the correct year but bias the value to start at the 1900
+ res->tm_year = res->tm_year - 1900;
+
+ return res;
+#else
+ // @@ Same as ACE_OS::localtime (), you need to implement it
+ // yourself.
+ ACE_UNUSED_ARG (t);
+ ACE_UNUSED_ARG (res);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_REENTRANT_FUNCTIONS */
+}
+
+time_t
+ACE_OS::mktime (struct tm *t)
+{
+ ACE_OS_TRACE ("ACE_OS::mktime");
+# if defined (ACE_HAS_WINCE)
+ SYSTEMTIME t_sys;
+ FILETIME t_file;
+ t_sys.wSecond = t->tm_sec;
+ t_sys.wMinute = t->tm_min;
+ t_sys.wHour = t->tm_hour;
+ t_sys.wDay = t->tm_mday;
+ t_sys.wMonth = t->tm_mon + 1; // SYSTEMTIME is 1-indexed, tm is 0-indexed
+ t_sys.wYear = t->tm_year + 1900; // SYSTEMTIME is real; tm is since 1900
+ t_sys.wDayOfWeek = t->tm_wday; // Ignored in below function call.
+ if (SystemTimeToFileTime (&t_sys, &t_file) == 0)
+ return -1;
+ ACE_Time_Value tv (t_file);
+ return tv.sec ();
+# else
+# if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_MT_SAFE_MKTIME)
+ ACE_OS_GUARD
+# endif /* ACE_HAS_THREADS && ! ACE_HAS_MT_SAFE_MKTIME */
+
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::mktime (t), time_t, (time_t) -1);
+# endif /* ACE_HAS_WINCE */
+}
+
+#if defined (ACE_HAS_POWERPC_TIMER) && defined (ghs)
+void
+ACE_OS::readPPCTimeBase (u_long &most, u_long &least)
+{
+ ACE_OS_TRACE ("ACE_OS::readPPCTimeBase");
+
+ // This function can't be inline because it depends on the arguments
+ // being in particular registers (r3 and r4), in conformance with the
+ // EABI standard. It would be nice if we knew how to put the variable
+ // names directly into the assembler instructions . . .
+ asm("aclock:");
+ asm("mftb r5,TBU");
+ asm("mftb r6,TBL");
+ asm("mftb r7,TBU");
+ asm("cmpw r5,r7");
+ asm("bne aclock");
+
+ asm("stw r5, 0(r3)");
+ asm("stw r6, 0(r4)");
+}
+#endif /* ACE_HAS_POWERPC_TIMER && ghs */
+
+#if defined (ACE_LACKS_STRPTIME) && !defined (ACE_REFUSE_STRPTIME_EMULATION)
+char *
+ACE_OS::strptime_emulation (const char *buf, const char *format, struct tm *tm)
+{
+ int bi = 0;
+ int fi = 0;
+ int percent = 0;
+
+ if (!buf || !format)
+ return 0;
+
+ while (format[fi] != '\0')
+ {
+ if (percent)
+ {
+ percent = 0;
+ switch (format[fi])
+ {
+ case '%': // an escaped %
+ if (buf[bi] == '%')
+ {
+ fi++; bi++;
+ }
+ else
+ return const_cast<char*> (buf + bi);
+ break;
+
+ /* not supported yet: weekday via locale long/short names
+ case 'a': / * weekday via locale * /
+ / * FALL THROUGH * /
+ case 'A': / * long/short names * /
+ break;
+ */
+
+ /* not supported yet:
+ case 'b': / * month via locale * /
+ / * FALL THROUGH * /
+ case 'B': / * long/short names * /
+ / * FALL THROUGH * /
+ case 'h':
+ break;
+ */
+
+ /* not supported yet:
+ case 'c': / * %x %X * /
+ break;
+ */
+
+ /* not supported yet:
+ case 'C': / * date & time - * /
+ / * locale long format * /
+ break;
+ */
+
+ case 'd': /* day of month (1-31) */
+ /* FALL THROUGH */
+ case 'e':
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31))
+ return const_cast<char*> (buf + bi);
+
+ break;
+
+ case 'D': /* %m/%d/%y */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12))
+ return const_cast<char*> (buf + bi);
+
+ fi--;
+ tm->tm_mon--;
+
+ if (buf[bi] != '/')
+ return const_cast<char*> (buf + bi);
+
+ bi++;
+
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31))
+ return const_cast<char*> (buf + bi);
+
+ fi--;
+ if (buf[bi] != '/')
+ return const_cast<char*> (buf + bi);
+ bi++;
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_year, &bi, &fi, 0, 99))
+ return const_cast<char*> (buf + bi);
+ if (tm->tm_year < 69)
+ tm->tm_year += 100;
+ break;
+
+ case 'H': /* hour (0-23) */
+ /* FALL THROUGH */
+ case 'k':
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
+ return const_cast<char*> (buf + bi);
+ break;
+
+ /* not supported yet:
+ case 'I': / * hour (0-12) * /
+ / * FALL THROUGH * /
+ case 'l':
+ break;
+ */
+
+ case 'j': /* day of year (0-366) */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_yday, &bi, &fi, 1, 366))
+ return const_cast<char*> (buf + bi);
+
+ tm->tm_yday--;
+ break;
+
+ case 'm': /* an escaped % */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12))
+ return const_cast<char*> (buf + bi);
+
+ tm->tm_mon--;
+ break;
+
+ case 'M': /* minute (0-59) */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
+ return const_cast<char*> (buf + bi);
+
+ break;
+
+ /* not supported yet:
+ case 'p': / * am or pm for locale * /
+ break;
+ */
+
+ /* not supported yet:
+ case 'r': / * %I:%M:%S %p * /
+ break;
+ */
+
+ case 'R': /* %H:%M */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
+ return const_cast<char*> (buf + bi);
+
+ fi--;
+ if (buf[bi] != ':')
+ return const_cast<char*> (buf + bi);
+ bi++;
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
+ return const_cast<char*> (buf + bi);
+
+ break;
+
+ case 'S': /* seconds (0-61) */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61))
+ return const_cast<char*> (buf + bi);
+ break;
+
+ case 'T': /* %H:%M:%S */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
+ return const_cast<char*> (buf + bi);
+
+ fi--;
+ if (buf[bi] != ':')
+ return const_cast<char*> (buf + bi);
+ bi++;
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
+ return const_cast<char*> (buf + bi);
+
+ fi--;
+ if (buf[bi] != ':')
+ return const_cast<char*> (buf + bi);
+ bi++;
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61))
+ return const_cast<char*> (buf + bi);
+
+ break;
+
+ case 'w': /* day of week (0=Sun-6) */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_wday, &bi, &fi, 0, 6))
+ return const_cast<char*> (buf + bi);
+
+ break;
+
+ /* not supported yet: date, based on locale
+ case 'x': / * date, based on locale * /
+ break;
+ */
+
+ /* not supported yet:
+ case 'X': / * time, based on locale * /
+ break;
+ */
+
+ case 'y': /* the year - 1900 (0-99) */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_year, &bi, &fi, 0, 99))
+ return const_cast<char*> (buf + bi);
+
+ if (tm->tm_year < 69)
+ tm->tm_year += 100;
+ break;
+
+ case 'Y': /* the full year (1999) */
+ if (!ACE_OS::strptime_getnum
+ (buf + bi, &tm->tm_year, &bi, &fi, 0, 0))
+ return const_cast<char*> (buf + bi);
+
+ tm->tm_year -= 1900;
+ break;
+
+ default: /* unrecognised */
+ return const_cast<char*> (buf + bi);
+ } /* switch (format[fi]) */
+
+ }
+ else
+ { /* if (percent) */
+ if (format[fi] == '%')
+ {
+ percent = 1;
+ fi++;
+ }
+ else
+ {
+ if (format[fi] == buf[bi])
+ {
+ fi++;
+ bi++;
+ }
+ else
+ return const_cast<char*> (buf + bi);
+ }
+ } /* if (percent) */
+ } /* while (format[fi] */
+
+ return const_cast<char*> (buf + bi);
+}
+
+int
+ACE_OS::strptime_getnum (const char *buf,
+ int *num,
+ int *bi,
+ int *fi,
+ int min,
+ int max)
+{
+ int i = 0, tmp = 0;
+
+ while (isdigit (buf[i]))
+ {
+ tmp = (tmp * 10) + (buf[i] - '0');
+ if (max && (tmp > max))
+ return 0;
+ i++;
+ }
+
+ if (tmp < min)
+ return 0;
+ else if (i)
+ {
+ *num = tmp;
+ (*fi)++;
+ *bi += i;
+ return 1;
+ }
+ else
+ return 0;
+}
+#endif /* ACE_LACKS_STRPTIME && !ACE_REFUSE_STRPTIME_EMULATION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_time.h b/ACE/ace/OS_NS_time.h
new file mode 100644
index 00000000000..ad1bb484b98
--- /dev/null
+++ b/ACE/ace/OS_NS_time.h
@@ -0,0 +1,288 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_time.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_TIME_H
+# define ACE_OS_NS_TIME_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/OS_NS_errno.h"
+#include "ace/Basic_Types.h"
+#include "ace/os_include/os_time.h"
+#include /**/ "ace/ACE_export.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+# if defined (ACE_HAS_BROKEN_R_ROUTINES)
+# undef ctime_r
+# undef asctime_r
+# endif /* ACE_HAS_BROKEN_R_ROUTINES */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Type-safe, and unsigned.
+static const ACE_UINT32 ACE_U_ONE_SECOND_IN_MSECS = 1000U;
+static const ACE_UINT32 ACE_U_ONE_SECOND_IN_USECS = 1000000U;
+static const ACE_UINT32 ACE_U_ONE_SECOND_IN_NSECS = 1000000000U;
+
+#if defined (ACE_LACKS_STRUCT_TM)
+struct tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday; // Day of the month
+ int tm_mon;
+ int tm_year;
+ int tm_wday; // Day of the week
+ int tm_yday; // Day in the year
+ int tm_isdst; // >0 if dst in effet; 0 if not; <0 if unknown
+};
+#endif /* ACE_LACKS_STRUCT_TM */
+
+/// Helper for the ACE_OS::timezone() function
+/**
+ * We put all the timezone stuff that used to be in ACE_OS::timezone()
+ * here because on some platforms "timezone" is a macro. Because of this,
+ * the name ACE_OS::timezone will cause errors. So in order to use the
+ * macro as it is defined but also keep the name ACE_OS::timezone, we
+ * use timezone first here in this inline function, and then undefine
+ * timezone.
+ */
+inline long ace_timezone()
+{
+#if defined (ACE_WIN32)
+ TIME_ZONE_INFORMATION tz;
+ GetTimeZoneInformation (&tz);
+ return tz.Bias * 60;
+#elif defined (ACE_HAS_TIMEZONE)
+ // The XPG/POSIX specification requires that tzset() be called to
+ // set the global variable <timezone>.
+ ::tzset();
+ return timezone;
+#elif defined (ACE_HAS_TIMEZONE_GETTIMEOFDAY)
+ // The XPG/POSIX specification does not require gettimeofday to
+ // set the timezone struct (it leaves the behavior of passing a
+ // non-null struct undefined).
+ long result = 0;
+ struct timeval time;
+ struct timezone zone;
+ ACE_UNUSED_ARG (result);
+ ACE_OSCALL (::gettimeofday (&time, &zone), int, -1, result);
+ return zone.tz_minuteswest * 60;
+#else
+ ACE_NOTSUP_RETURN (0);
+#endif
+}
+
+
+#if !defined (ACE_LACKS_DIFFTIME)
+/// Helper for the ACE_OS::difftime() function
+/**
+ * We moved the difftime code that used to be in ACE_OS::difftime()
+ * here because on some platforms "difftime" is a macro. Because of this,
+ * the name ACE_OS::difftime will cause errors. So in order to use the
+ * macro as it is defined but also keep the name ACE_OS::difftime, we
+ * use difftime first here in this inline function, and then undefine
+ * it.
+ */
+inline double ace_difftime(time_t t1, time_t t0)
+{
+ return difftime (t1, t0);
+}
+#endif /* !ACE_LACKS_DIFFTIME */
+
+# if defined (ACE_WIN32)
+# if !defined (ACE_LACKS_LONGLONG_T)
+// 64-bit quad-word definitions.
+typedef unsigned __int64 ACE_QWORD;
+typedef unsigned __int64 ACE_hrtime_t;
+inline ACE_QWORD ACE_MAKE_QWORD (DWORD lo, DWORD hi) { return ACE_QWORD (lo) | (ACE_QWORD (hi) << 32); }
+inline DWORD ACE_LOW_DWORD (ACE_QWORD q) { return (DWORD) q; }
+inline DWORD ACE_HIGH_DWORD (ACE_QWORD q) { return (DWORD) (q >> 32); }
+# else
+// Can't find ANY place that ACE_QWORD is used, but hrtime_t is.
+typedef ACE_UINT64 ACE_hrtime_t;
+# endif // ACE_LACKS_LONGLONG_T
+# elif defined (_TNS_R_TARGET)
+typedef long long ACE_hrtime_t;
+# else /* !ACE_WIN32 */
+# if defined (ACE_HAS_HI_RES_TIMER) && !defined (ACE_LACKS_LONGLONG_T)
+ /* hrtime_t is defined on systems (Suns) with ACE_HAS_HI_RES_TIMER */
+ typedef hrtime_t ACE_hrtime_t;
+# else /* ! ACE_HAS_HI_RES_TIMER || ACE_LACKS_LONGLONG_T */
+ typedef ACE_UINT64 ACE_hrtime_t;
+# endif /* ! ACE_HAS_HI_RES_TIMER || ACE_LACKS_LONGLONG_T */
+# endif /* ACE_WIN32 */
+
+# if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+# define ACE_HRTIME_CONVERSION(VAL) ACE_U64_TO_U32(VAL)
+# define ACE_HRTIME_TO_U64(VAL) ACE_U_LongLong(VAL)
+# else
+# define ACE_HRTIME_CONVERSION(VAL) (VAL)
+# define ACE_HRTIME_TO_U64(VAL) (VAL)
+# endif
+
+namespace ACE_OS
+{
+ enum ACE_HRTimer_Op
+ {
+ ACE_HRTIMER_START = 0x0, // Only use these if you can stand
+ ACE_HRTIMER_INCR = 0x1, // for interrupts to be disabled during
+ ACE_HRTIMER_STOP = 0x2, // the timed interval!!!!
+ ACE_HRTIMER_GETTIME = 0xFFFF
+ };
+
+ //@{ @name A set of wrappers for operations on time.
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *asctime (const struct tm *tm);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *asctime_r (const struct tm *tm,
+ char *buf, int buflen);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int clock_gettime (clockid_t,
+ struct timespec *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int clock_settime (clockid_t,
+ const struct timespec *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_TCHAR *ctime (const time_t *t);
+
+#if defined (ACE_HAS_WINCE) && !defined (_DEBUG)
+ extern ACE_EXPORT_MACRO
+#else
+ ACE_NAMESPACE_INLINE_FUNCTION
+#endif
+ ACE_TCHAR *ctime_r (const time_t *clock, ACE_TCHAR *buf, int buflen);
+
+# if defined (difftime)
+# undef difftime
+# endif /* difftime */
+
+#if !defined (ACE_LACKS_DIFFTIME)
+ ACE_NAMESPACE_INLINE_FUNCTION
+#else
+ extern ACE_Export
+#endif /* ! ACE_LACKS_DIFFTIME */
+ double difftime (time_t t1,
+ time_t t0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_hrtime_t gethrtime (const ACE_HRTimer_Op = ACE_HRTIMER_GETTIME);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct tm *gmtime (const time_t *clock);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct tm *gmtime_r (const time_t *clock,
+ struct tm *res);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ struct tm *localtime (const time_t *clock);
+
+ extern ACE_Export
+ struct tm *localtime_r (const time_t *clock,
+ struct tm *res);
+
+ // Get the current time.
+ extern ACE_Export
+ time_t mktime (struct tm *timeptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int nanosleep (const struct timespec *requested,
+ struct timespec *remaining = 0);
+
+# if defined (ACE_HAS_POWERPC_TIMER) && defined (ghs)
+ extern ACE_Export
+ void readPPCTimeBase (u_long &most,
+ u_long &least);
+# endif /* ACE_HAS_POWERPC_TIMER && ghs */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ size_t strftime (char *s,
+ size_t maxsize,
+ const char *format,
+ const struct tm *timeptr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *strptime (const char *buf,
+ const char *format,
+ struct tm *tm);
+
+# if defined (ACE_LACKS_STRPTIME) && !defined (ACE_REFUSE_STRPTIME_EMULATION)
+ extern ACE_Export
+ char *strptime_emulation (const char *buf,
+ const char *format,
+ struct tm *tm);
+
+ extern ACE_Export
+ int strptime_getnum (const char *buf, int *num, int *bi,
+ int *fi, int min, int max);
+# endif /* ACE_LACKS_STRPTIME && !ACE_REFUSE_STRPTIME_EMULATION */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ time_t time (time_t *tloc = 0);
+
+# if defined (timezone)
+# undef timezone
+# endif /* timezone */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long timezone (void);
+
+ // wrapper for time zone information.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void tzset (void);
+
+ //@}
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if (defined (ACE_HAS_VERSIONED_NAMESPACE) \
+ && ACE_HAS_VERSIONED_NAMESPACE == 1) \
+ && defined (ghs) \
+ && defined (ACE_HAS_PENTIUM) \
+ && !defined (ACE_WIN32)
+#define ACE_GETHRTIME_NAME ACE_PREPROC_CONCATENATE(ACE_,ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _gethrtime))
+#else
+# define ACE_GETHRTIME_NAME ACE_gethrtime
+#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_time.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_TIME_H */
diff --git a/ACE/ace/OS_NS_time.inl b/ACE/ace/OS_NS_time.inl
new file mode 100644
index 00000000000..fe1804c04e7
--- /dev/null
+++ b/ACE/ace/OS_NS_time.inl
@@ -0,0 +1,505 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_time.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE char *
+ACE_OS::asctime (const struct tm *t)
+{
+ ACE_OS_TRACE ("ACE_OS::asctime");
+#if defined (ACE_LACKS_ASCTIME)
+ ACE_UNUSED_ARG (t);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::asctime (t), char *, 0);
+#endif /* ACE_LACKS_ASCTIME */
+}
+
+ACE_INLINE char *
+ACE_OS::asctime_r (const struct tm *t, char *buf, int buflen)
+{
+ ACE_OS_TRACE ("ACE_OS::asctime_r");
+#if defined (ACE_HAS_REENTRANT_FUNCTIONS)
+# if defined (ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R)
+ char *result;
+# if defined (DIGITAL_UNIX)
+ ACE_OSCALL (::_Pasctime_r (t, buf), char *, 0, result);
+# else
+ ACE_OSCALL (::asctime_r (t, buf), char *, 0, result);
+# endif /* DIGITAL_UNIX */
+ ACE_OS::strsncpy (buf, result, buflen);
+ return buf;
+# else
+# if defined (ACE_HAS_SIZET_PTR_ASCTIME_R_AND_CTIME_R)
+ ACE_OSCALL_RETURN (::asctime_r (t, buf, reinterpret_cast<size_t*>(&buflen)), char *, 0);
+# else
+ ACE_OSCALL_RETURN (::asctime_r (t, buf, buflen), char *, 0);
+# endif /* ACE_HAS_SIZET_PTR_ASCTIME_R_AND_CTIME_R */
+# endif /* ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R */
+#elif defined (ACE_LACKS_ASCTIME_R)
+ ACE_UNUSED_ARG (t);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (buflen);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_HAS_TR24731_2005_CRT)
+ char *result = buf;
+ ACE_SECURECRTCALL (asctime_s (buf, static_cast<size_t> (buflen), t), \
+ char*, 0, result);
+ return result;
+#else
+ char *result = 0;
+ ACE_OSCALL (ACE_STD_NAMESPACE::asctime (t), char *, 0, result);
+ ACE_OS::strsncpy (buf, result, buflen);
+ return buf;
+#endif /* ACE_HAS_REENTRANT_FUNCTIONS */
+}
+
+ACE_INLINE int
+ACE_OS::clock_gettime (clockid_t clockid, struct timespec *ts)
+{
+ ACE_OS_TRACE ("ACE_OS::clock_gettime");
+#if defined (ACE_HAS_CLOCK_GETTIME)
+ ACE_OSCALL_RETURN (::clock_gettime (clockid, ts), int, -1);
+#else
+ ACE_UNUSED_ARG (clockid);
+ ACE_UNUSED_ARG (ts);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_CLOCK_GETTIME */
+}
+
+ACE_INLINE int
+ACE_OS::clock_settime (clockid_t clockid, const struct timespec *ts)
+{
+#if defined (ACE_HAS_CLOCK_SETTIME)
+# if defined (ACE_HAS_NONCONST_CLOCK_SETTIME)
+ ACE_OSCALL_RETURN (::clock_settime (clockid, const_cast<struct timespec *>(ts)), int, -1);
+# else
+ ACE_OSCALL_RETURN (::clock_settime (clockid, ts), int, -1);
+# endif /* ACE_HAS_NONCONST_CLOCK_SETTIME */
+#else
+ ACE_UNUSED_ARG (clockid);
+ ACE_UNUSED_ARG (ts);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_CLOCK_SETTIME */
+}
+
+// Magic number declaration and definition for ctime and ctime_r ()
+static const int ctime_buf_size = 26;
+
+ACE_INLINE ACE_TCHAR *
+ACE_OS::ctime (const time_t *t)
+{
+ ACE_OS_TRACE ("ACE_OS::ctime");
+#if defined (ACE_HAS_BROKEN_CTIME)
+ ACE_OSCALL_RETURN (::asctime (::localtime (t)), char *, 0);
+#elif defined (ACE_HAS_WINCE)
+ static ACE_TCHAR buf [ctime_buf_size];
+ return ACE_OS::ctime_r (t,
+ buf,
+ ctime_buf_size);
+#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OSCALL_RETURN (::_wctime (t), wchar_t *, 0);
+#else
+# if defined (ACE_USES_WCHAR) /* Not Win32, else it would do the above */
+ char *narrow_time;
+ ACE_OSCALL (::ctime (t), char *, 0, narrow_time);
+ if (narrow_time == 0)
+ return 0;
+ // ACE_Ascii_To_Wide::convert allocates (via new []) a wchar_t[]. If
+ // we've done this before, free the previous one. Yes, this leaves a
+ // small memory leak (26 characters) but there's no way around this
+ // that I know of. (Steve Huston, 12-Feb-2003).
+ static wchar_t *wide_time = 0;
+ if (wide_time != 0)
+ delete [] wide_time;
+ wide_time = ACE_Ascii_To_Wide::convert (narrow_time);
+ return wide_time;
+# else
+ ACE_OSCALL_RETURN (::ctime (t), char *, 0);
+# endif /* ACE_USES_WCHAR */
+# endif /* ACE_HAS_BROKEN_CTIME */
+}
+
+#if !defined (ACE_HAS_WINCE) /* CE version in OS.cpp */
+ACE_INLINE ACE_TCHAR *
+ACE_OS::ctime_r (const time_t *t, ACE_TCHAR *buf, int buflen)
+{
+ ACE_OS_TRACE ("ACE_OS::ctime_r");
+
+#if defined (ACE_HAS_REENTRANT_FUNCTIONS)
+
+ char *bufp = 0;
+# if defined (ACE_USES_WCHAR)
+ char narrow_buf[ctime_buf_size];
+ bufp = narrow_buf;
+# else
+ bufp = buf;
+# endif /* ACE_USES_WCHAR */
+
+ if (buflen < ctime_buf_size)
+ {
+ errno = ERANGE;
+ return 0;
+ }
+# if defined (ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R)
+# if defined (DIGITAL_UNIX)
+ ACE_OSCALL (::_Pctime_r (t, bufp), ACE_TCHAR *, 0, bufp);
+# else /* DIGITAL_UNIX */
+ ACE_OSCALL (::ctime_r (t, bufp), char *, 0, bufp);
+# endif /* DIGITAL_UNIX */
+# else /* ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R */
+
+# if defined (ACE_HAS_SIZET_PTR_ASCTIME_R_AND_CTIME_R)
+ bufp = ::ctime_r (t, bufp, reinterpret_cast<size_t*>(&buflen));
+# else /* ACE_CTIME_R_RETURNS_INT */
+ bufp = ::ctime_r (t, bufp, buflen);
+# endif /* ACE_CTIME_R_RETURNS_INT */
+
+# endif /* ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R */
+
+ if (bufp == 0)
+ return 0;
+
+# if defined (ACE_USES_WCHAR)
+ ACE_Ascii_To_Wide wide_buf (bufp);
+ ACE_OS_String::strcpy (buf, wide_buf.wchar_rep ());
+ return buf;
+# else
+ return bufp;
+# endif /* ACE_USES_WCHAR */
+
+#elif defined (ACE_HAS_TR24731_2005_CRT)
+ if (buflen < ctime_buf_size)
+ {
+ errno = ERANGE;
+ return 0;
+ }
+ ACE_TCHAR *result = buf;
+# if defined (ACE_USES_WCHAR)
+ ACE_SECURECRTCALL (_wctime_s (buf, buflen, t), wchar_t *, 0, result);
+# else
+ ACE_SECURECRTCALL (ctime_s (buf, buflen, t), char *, 0, result);
+# endif
+ return result;
+
+#else /* ACE_HAS_REENTRANT_FUNCTIONS */
+ if (buflen < ctime_buf_size)
+ {
+ errno = ERANGE;
+ return 0;
+ }
+
+ ACE_TCHAR *result;
+# if defined (ACE_USES_WCHAR)
+ ACE_OSCALL (::_wctime (t), wchar_t *, 0, result);
+# else /* ACE_USES_WCHAR */
+ ACE_OSCALL (::ctime (t), char *, 0, result);
+# endif /* ACE_USES_WCHAR */
+ if (result != 0)
+ ACE_OS::strsncpy (buf, result, buflen);
+ return buf;
+#endif /* ACE_HAS_REENTRANT_FUNCTIONS */
+}
+#endif /* !ACE_HAS_WINCE */
+
+#if !defined (ACE_LACKS_DIFFTIME)
+ACE_INLINE double
+ACE_OS::difftime (time_t t1, time_t t0)
+{
+ return ::ace_difftime (t1, t0);
+}
+#endif /* ! ACE_LACKS_DIFFTIME */
+
+#if defined (ghs) && defined (ACE_HAS_PENTIUM) && !defined (ACE_WIN32)
+ extern "C" ACE_hrtime_t ACE_GETHRTIME_NAME ();
+#endif /* ghs && ACE_HAS_PENTIUM */
+
+ACE_INLINE ACE_hrtime_t
+ACE_OS::gethrtime (const ACE_HRTimer_Op op)
+{
+ ACE_OS_TRACE ("ACE_OS::gethrtime");
+#if defined (ACE_HAS_HI_RES_TIMER)
+ ACE_UNUSED_ARG (op);
+ return ::gethrtime ();
+#elif defined (ACE_HAS_AIX_HI_RES_TIMER)
+ ACE_UNUSED_ARG (op);
+ timebasestruct_t tb;
+
+ ::read_real_time(&tb, TIMEBASE_SZ);
+ ::time_base_to_time(&tb, TIMEBASE_SZ);
+
+ return ACE_hrtime_t(tb.tb_high) * ACE_ONE_SECOND_IN_NSECS + tb.tb_low;
+#elif defined (ACE_WIN32)
+ ACE_UNUSED_ARG(op);
+ LARGE_INTEGER freq;
+
+ ::QueryPerformanceCounter (&freq);
+
+# if defined (ACE_LACKS_LONGLONG_T)
+ ACE_UINT64 uint64_freq (freq.u.LowPart,
+ static_cast<unsigned int> (freq.u.HighPart));
+ return uint64_freq;
+# else
+ return freq.QuadPart;
+# endif //ACE_LACKS_LONGLONG_T
+#elif defined (ghs) && defined (ACE_HAS_PENTIUM)
+ ACE_UNUSED_ARG (op);
+ // Use .obj/gethrtime.o, which was compiled with g++.
+ return ACE_GETHRTIME_NAME ();
+#elif (defined (__GNUG__) || defined (__INTEL_COMPILER)) && !defined(ACE_VXWORKS) && defined (ACE_HAS_PENTIUM)
+ ACE_UNUSED_ARG (op);
+# if defined (ACE_LACKS_LONGLONG_T)
+ double now;
+# else /* ! ACE_LACKS_LONGLONG_T */
+ ACE_hrtime_t now;
+# endif /* ! ACE_LACKS_LONGLONG_T */
+
+#if defined (__amd64__) || defined (__x86_64__)
+ // Read the high res tick counter into 32 bit int variables "eax" and
+ // "edx", and then combine them into 64 bit int "now"
+ ACE_UINT32 eax, edx;
+ asm volatile ("rdtsc" : "=a" (eax), "=d" (edx) : : "memory");
+ now = (((ACE_UINT64) eax) | (((ACE_UINT64) edx) << 32));
+#else
+ // Read the high-res tick counter directly into memory variable "now".
+ // The A constraint signifies a 64-bit int.
+ asm volatile ("rdtsc" : "=A" (now) : : "memory");
+#endif
+
+# if defined (ACE_LACKS_LONGLONG_T)
+ ACE_UINT32 least, most;
+ ACE_OS::memcpy (&least, &now, sizeof (ACE_UINT32));
+ ACE_OS::memcpy (&most, (u_char *) &now + sizeof (ACE_UINT32),
+ sizeof (ACE_UINT32));
+
+ ACE_hrtime_t ret (least, most);
+ return ret;
+# else /* ! ACE_LACKS_LONGLONG_T */
+ return now;
+# endif /* ! ACE_LACKS_LONGLONG_T */
+#elif defined (linux) && defined (ACE_HAS_ALPHA_TIMER)
+ // NOTE: alphas only have a 32 bit tick (cycle) counter. The rpcc
+ // instruction actually reads 64 bits, but the high 32 bits are
+ // implementation-specific. Linux and Digital Unix, for example,
+ // use them for virtual tick counts, i.e., taking into account only
+ // the time that the process was running. This information is from
+ // David Mosberger's article, see comment below.
+ ACE_UINT32 now;
+
+ // The following statement is based on code published by:
+ // Mosberger, David, "How to Make Your Applications Fly, Part 1",
+ // Linux Journal Issue 42, October 1997, page 50. It reads the
+ // high-res tick counter directly into the memory variable.
+ asm volatile ("rpcc %0" : "=r" (now) : : "memory");
+
+ return now;
+#elif defined (ACE_HAS_POWERPC_TIMER) && (defined (ghs) || defined (__GNUG__))
+ // PowerPC w/ GreenHills or g++.
+
+ ACE_UNUSED_ARG (op);
+ u_long most;
+ u_long least;
+
+#if defined (ghs)
+ ACE_OS::readPPCTimeBase (most, least);
+#else
+ u_long scratch;
+
+ do {
+ asm volatile ("mftbu %0\n"
+ "mftb %1\n"
+ "mftbu %2"
+ : "=r" (most), "=r" (least), "=r" (scratch));
+ } while (most != scratch);
+#endif
+
+#if defined (ACE_LACKS_LONGLONG_T)
+ return ACE_U_LongLong (least, most);
+#else /* ! ACE_LACKS_LONGLONG_T */
+ return 0x100000000llu * most + least;
+#endif /* ! ACE_LACKS_LONGLONG_T */
+
+#elif defined (ACE_HAS_CLOCK_GETTIME)
+ // e.g., VxWorks (besides POWERPC && GreenHills) . . .
+ ACE_UNUSED_ARG (op);
+ struct timespec ts;
+
+ ACE_OS::clock_gettime (
+#if defined (ACE_HAS_CLOCK_GETTIME_MONOTONIC)
+ CLOCK_MONOTONIC,
+#endif /* !ACE_HAS_CLOCK_GETTIME_MONOTONIC */
+ CLOCK_REALTIME,
+ &ts);
+
+ // Carefully create the return value to avoid arithmetic overflow
+ // if ACE_hrtime_t is ACE_U_LongLong.
+ return static_cast<ACE_hrtime_t> (ts.tv_sec) *
+ ACE_U_ONE_SECOND_IN_NSECS + static_cast<ACE_hrtime_t> (ts.tv_nsec);
+#else
+ ACE_UNUSED_ARG (op);
+ ACE_Time_Value const now = ACE_OS::gettimeofday ();
+
+ // Carefully create the return value to avoid arithmetic overflow
+ // if ACE_hrtime_t is ACE_U_LongLong.
+ return (static_cast<ACE_hrtime_t> (now.sec ()) * (ACE_UINT32) 1000000 +
+ static_cast<ACE_hrtime_t> (now.usec ())) * (ACE_UINT32) 1000;
+#endif /* ACE_HAS_HI_RES_TIMER */
+}
+
+ACE_INLINE struct tm *
+ACE_OS::gmtime (const time_t *t)
+{
+ ACE_OS_TRACE ("ACE_OS::gmtime");
+#if defined (ACE_LACKS_GMTIME)
+ ACE_UNUSED_ARG (t);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN (::gmtime (t), struct tm *, 0);
+#endif /* ACE_LACKS_GMTIME */
+}
+
+ACE_INLINE struct tm *
+ACE_OS::gmtime_r (const time_t *t, struct tm *res)
+{
+ ACE_OS_TRACE ("ACE_OS::gmtime_r");
+#if defined (ACE_HAS_REENTRANT_FUNCTIONS)
+# if defined (DIGITAL_UNIX)
+ ACE_OSCALL_RETURN (::_Pgmtime_r (t, res), struct tm *, 0);
+# else
+ ACE_OSCALL_RETURN (::gmtime_r (t, res), struct tm *, 0);
+# endif /* DIGITAL_UNIX */
+#elif defined (ACE_HAS_TR24731_2005_CRT)
+ struct tm *tm_p = res;
+ ACE_SECURECRTCALL (gmtime_s (res, t), struct tm *, 0, tm_p);
+ return tm_p;
+#elif defined (ACE_LACKS_GMTIME_R)
+ ACE_UNUSED_ARG (t);
+ ACE_UNUSED_ARG (res);
+ ACE_NOTSUP_RETURN (0);
+#else
+ struct tm *result;
+ ACE_OSCALL (::gmtime (t), struct tm *, 0, result) ;
+ if (result != 0)
+ *res = *result;
+ return res;
+#endif /* ACE_HAS_REENTRANT_FUNCTIONS */
+}
+
+ACE_INLINE struct tm *
+ACE_OS::localtime (const time_t *t)
+{
+ ACE_OS_TRACE ("ACE_OS::localtime");
+#if defined (ACE_LACKS_LOCALTIME)
+ ACE_UNUSED_ARG (t);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN (::localtime (t), struct tm *, 0);
+#endif /* ACE_LACKS_LOCALTIME */
+}
+
+ACE_INLINE int
+ACE_OS::nanosleep (const struct timespec *requested,
+ struct timespec *remaining)
+{
+ ACE_OS_TRACE ("ACE_OS::nanosleep");
+#if defined (ACE_HAS_CLOCK_GETTIME)
+ // ::nanosleep () is POSIX 1003.1b. So is ::clock_gettime (). So,
+ // if ACE_HAS_CLOCK_GETTIME is defined, then ::nanosleep () should
+ // be available on the platform. On Solaris 2.x, both functions
+ // require linking with -lposix4.
+ return ::nanosleep ((ACE_TIMESPEC_PTR) requested, remaining);
+#else
+ ACE_UNUSED_ARG (remaining);
+
+ // Convert into seconds and microseconds.
+ ACE_Time_Value tv (requested->tv_sec,
+ requested->tv_nsec / 1000);
+ return ACE_OS::sleep (tv);
+#endif /* ACE_HAS_CLOCK_GETTIME */
+}
+
+ACE_INLINE size_t
+ACE_OS::strftime (char *s, size_t maxsize, const char *format,
+ const struct tm *timeptr)
+{
+#if defined (ACE_LACKS_STRFTIME)
+ ACE_UNUSED_ARG (s);
+ ACE_UNUSED_ARG (maxsize);
+ ACE_UNUSED_ARG (format);
+ ACE_UNUSED_ARG (timeptr);
+ ACE_NOTSUP_RETURN (0);
+#else
+ return ACE_STD_NAMESPACE::strftime (s, maxsize, format, timeptr);
+#endif /* ACE_LACKS_STRFTIME */
+}
+
+ACE_INLINE char *
+ACE_OS::strptime (const char *buf, const char *format, struct tm *tm)
+{
+#if defined (ACE_LACKS_STRPTIME)
+# if defined (ACE_REFUSE_STRPTIME_EMULATION)
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (format);
+ ACE_UNUSED_ARG (tm);
+ ACE_NOTSUP_RETURN (0);
+# else
+ return ACE_OS::strptime_emulation (buf, format, tm);
+# endif /* ACE_REFUSE_STRPTIME_EMULATION */
+#else
+ return ::strptime (buf, format, tm);
+#endif /* ACE_LACKS_STRPTIME */
+}
+
+ACE_INLINE time_t
+ACE_OS::time (time_t *tloc)
+{
+ ACE_OS_TRACE ("ACE_OS::time");
+#if !defined (ACE_HAS_WINCE)
+ ACE_OSCALL_RETURN (::time (tloc), time_t, (time_t) -1);
+#else
+ time_t retv = ACE_OS::gettimeofday ().sec ();
+ if (tloc)
+ *tloc = retv;
+ return retv;
+#endif /* ACE_HAS_WINCE */
+}
+
+// Linux won't compile unless we explicitly use a namespace here.
+#if defined (__GNUG__)
+namespace ACE_OS {
+ ACE_INLINE long
+ timezone (void)
+ {
+ return ::ace_timezone ();
+ }
+} /* namespace ACE_OS */
+#else
+ACE_INLINE long
+ACE_OS::timezone (void)
+{
+ return ::ace_timezone ();
+}
+#endif /* linux */
+
+ACE_INLINE void
+ACE_OS::tzset (void)
+{
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_VXWORKS) && !defined(ACE_HAS_RTEMS) && !defined (ACE_HAS_DINKUM_STL)
+# if defined (ACE_WIN32)
+ ::_tzset (); // For Win32.
+# else
+ ::tzset (); // For UNIX platforms.
+# endif /* ACE_WIN32 */
+# else
+ errno = ENOTSUP;
+# endif /* ACE_HAS_WINCE && !VXWORKS && !ACE_HAS_RTEMS && !ACE_HAS_DINKUM_STL */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_unistd.cpp b/ACE/ace/OS_NS_unistd.cpp
new file mode 100644
index 00000000000..112f49e6253
--- /dev/null
+++ b/ACE/ace/OS_NS_unistd.cpp
@@ -0,0 +1,859 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID (ace, OS_NS_unistd, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_unistd.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include "ace/Base_Thread_Adapter.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/Default_Constants.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_Thread.h"
+#include "ace/Object_Manager_Base.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/os_include/sys/os_pstat.h"
+#include "ace/os_include/sys/os_sysctl.h"
+
+#if defined (ACE_NEEDS_FTRUNCATE)
+extern "C" int
+ftruncate (ACE_HANDLE handle, long len)
+{
+ struct flock fl;
+ fl.l_whence = 0;
+ fl.l_len = 0;
+ fl.l_start = len;
+ fl.l_type = F_WRLCK;
+
+ return ACE_OS::fcntl (handle, F_FREESP, reinterpret_cast <long> (&fl));
+}
+#endif /* ACE_NEEDS_FTRUNCATE */
+
+/*****************************************************************************/
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_OS::argv_to_string (ACE_TCHAR **argv,
+ ACE_TCHAR *&buf,
+ bool substitute_env_args,
+ bool quote_args)
+{
+ if (argv == 0 || argv[0] == 0)
+ return 0;
+
+ size_t buf_len = 0;
+
+ // Determine the length of the buffer.
+
+ int argc;
+ for (argc = 0; argv[argc] != 0; ++argc)
+ continue;
+ ACE_TCHAR **argv_p = argv;
+
+ for (int i = 0; i < argc; ++i)
+ {
+#if !defined (ACE_LACKS_ENV)
+ // Account for environment variables.
+ if (substitute_env_args
+ && ACE_OS::strchr (argv[i], ACE_TEXT ('$')) != 0)
+ {
+ if (argv_p == argv)
+ {
+ argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
+ if (argv_p == 0)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+ ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
+ }
+ argv_p[i] = ACE_OS::strenvdup (argv[i]);
+ if (argv_p[i] == 0)
+ {
+ ACE_OS::free (argv_p);
+ errno = ENOMEM;
+ return 0;
+ }
+ }
+#endif /* ACE_LACKS_ENV */
+ if (quote_args
+ && ACE_OS::strchr (argv_p[i], ACE_TEXT (' ')) != 0)
+ {
+ if (argv_p == argv)
+ {
+ argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
+ if (argv_p == 0)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+ ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
+ }
+ int quotes = 0;
+ ACE_TCHAR *temp = argv_p[i];
+ if (ACE_OS::strchr (temp, ACE_TEXT ('"')) != 0)
+ {
+ for (int j = 0; temp[j] != 0; ++j)
+ if (temp[j] == ACE_TEXT ('"'))
+ ++quotes;
+ }
+ argv_p[i] =
+ (ACE_TCHAR *) ACE_OS::malloc (ACE_OS::strlen (temp) * sizeof (ACE_TCHAR) + quotes + 3);
+ if (argv_p[i] == 0)
+ {
+ ACE_OS::free (argv_p);
+ errno = ENOMEM;
+ return 0;
+ }
+ ACE_TCHAR *end = argv_p[i];
+
+ *end++ = ACE_TEXT ('"');
+
+ if (quotes > 0)
+ {
+ for (ACE_TCHAR *p = temp;
+ *p != 0;
+ *end++ = *p++)
+ if (*p == ACE_TEXT ('"'))
+ *end++ = ACE_TEXT ('\\');
+
+ *end++ = ACE_TEXT ('\0');
+ }
+ else
+ end = ACE_OS::strecpy (end, temp);
+
+ end[-1] = ACE_TEXT ('"');
+
+ *end = ACE_TEXT ('\0');
+ if (temp != argv[i])
+ ACE_OS::free (temp);
+ }
+ buf_len += ACE_OS::strlen (argv_p[i]);
+
+ // Add one for the extra space between each string.
+ buf_len++;
+ }
+
+ // Step through all argv params and copy each one into buf; separate
+ // each param with white space.
+
+ ACE_NEW_RETURN (buf,
+ ACE_TCHAR[buf_len + 1],
+ 0);
+
+ // Initial null charater to make it a null string.
+ buf[0] = ACE_TEXT ('\0');
+ ACE_TCHAR *end = buf;
+
+ for (int i = 0; i < argc; ++i)
+ {
+ end = ACE_OS::strecpy (end, argv_p[i]);
+ if (argv_p[i] != argv[i])
+ ACE_OS::free (argv_p[i]);
+
+ // Replace the null char that strecpy put there with white
+ // space.
+ end[-1] = ACE_TEXT (' ');
+ }
+ // Null terminate the string.
+ *end = ACE_TEXT ('\0');
+
+ if (argv_p != argv)
+ ACE_OS::free (argv_p);
+
+ // The number of arguments.
+ return argc;
+}
+
+int
+ACE_OS::execl (const char * /* path */, const char * /* arg0 */, ...)
+{
+ ACE_OS_TRACE ("ACE_OS::execl");
+ ACE_NOTSUP_RETURN (-1);
+ // Need to write this code.
+ // ACE_OSCALL_RETURN (::execv (path, argv), int, -1);
+}
+
+int
+ACE_OS::execle (const char * /* path */, const char * /* arg0 */, ...)
+{
+ ACE_OS_TRACE ("ACE_OS::execle");
+ ACE_NOTSUP_RETURN (-1);
+ // Need to write this code.
+ // ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1);
+}
+
+int
+ACE_OS::execlp (const char * /* file */, const char * /* arg0 */, ...)
+{
+ ACE_OS_TRACE ("ACE_OS::execlp");
+ ACE_NOTSUP_RETURN (-1);
+ // Need to write this code.
+ // ACE_OSCALL_RETURN (::execvp (file, argv), int, -1);
+}
+
+pid_t
+ACE_OS::fork (const ACE_TCHAR *program_name)
+{
+ ACE_OS_TRACE ("ACE_OS::fork");
+# if defined (ACE_LACKS_FORK)
+ ACE_UNUSED_ARG (program_name);
+ ACE_NOTSUP_RETURN (pid_t (-1));
+# else
+ pid_t const pid =
+# if defined (ACE_HAS_STHREADS)
+ ::fork1 ();
+#else
+ ::fork ();
+#endif /* ACE_HAS_STHREADS */
+
+#if !defined (ACE_HAS_MINIMAL_ACE_OS) && !defined (ACE_HAS_THREADS)
+
+ // ACE_Base_Thread_Adapter::sync_log_msg() is used to update the
+ // program name and process id in ACE's log framework. However, we
+ // can't invoke it from (the child process of) threaded programs
+ // because it calls async signal unsafe functions, which will result
+ // in undefined behavior (only async signal safe functions can be
+ // called after fork() until an exec()).
+ //
+ // This is no great loss. Using the ACE log framework in the child
+ // process will undoubtedly call async signal unsafe functions too.
+ // So it doesn't really matter that the program name and process id
+ // will not be updated.
+
+ if (pid == 0)
+ ACE_Base_Thread_Adapter::sync_log_msg (program_name);
+
+#else
+
+ ACE_UNUSED_ARG (program_name);
+
+#endif /* ! ACE_HAS_MINIMAL_ACE_OS && !ACE_HAS_THREADS */
+
+ return pid;
+# endif /* ACE_WIN32 */
+}
+
+// Create a contiguous command-line argument buffer with each arg
+// separated by spaces.
+
+pid_t
+ACE_OS::fork_exec (ACE_TCHAR *argv[])
+{
+# if defined (ACE_WIN32)
+
+ ACE_TCHAR *buf = 0;
+ ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_ptr (buf);
+ if (ACE_OS::argv_to_string (argv, buf) != -1)
+ {
+ PROCESS_INFORMATION process_info;
+# if !defined (ACE_HAS_WINCE)
+ ACE_TEXT_STARTUPINFO startup_info;
+ ACE_OS::memset ((void *) &startup_info,
+ 0,
+ sizeof startup_info);
+ startup_info.cb = sizeof startup_info;
+
+ if (ACE_TEXT_CreateProcess (0,
+ buf,
+ 0, // No process attributes.
+ 0, // No thread attributes.
+ TRUE, // Allow handle inheritance.
+ 0, // Don't create a new console window.
+ 0, // No environment.
+ 0, // No current directory.
+ &startup_info,
+ &process_info))
+# else
+ if (ACE_TEXT_CreateProcess (0,
+ buf,
+ 0, // No process attributes.
+ 0, // No thread attributes.
+ FALSE, // Can's inherit handles on CE
+ 0, // Don't create a new console window.
+ 0, // No environment.
+ 0, // No current directory.
+ 0, // Can't use startup info on CE
+ &process_info))
+# endif /* ! ACE_HAS_WINCE */
+ {
+ // Free resources allocated in kernel.
+ ACE_OS::close (process_info.hThread);
+ ACE_OS::close (process_info.hProcess);
+ // Return new process id.
+ return process_info.dwProcessId;
+ }
+ }
+
+ // CreateProcess failed.
+ return -1;
+# else
+ pid_t const result = ACE_OS::fork ();
+
+# if defined (ACE_USES_WCHAR)
+ // Wide-char builds need to convert the command-line args to
+ // narrow char strings for execv ().
+ char **cargv = 0;
+ int arg_count;
+# endif /* ACE_HAS_WCHAR */
+
+ switch (result)
+ {
+ case -1:
+ // Error.
+ return -1;
+ case 0:
+ // Child process.
+# if defined (ACE_USES_WCHAR)
+ for (arg_count = 0; argv[arg_count] != 0; ++arg_count)
+ ;
+ ++arg_count; // Need a 0-pointer end-of-array marker
+ ACE_NEW_NORETURN (cargv, char*[arg_count]);
+ if (cargv == 0)
+ ACE_OS::exit (errno);
+ --arg_count; // Back to 0-indexed
+ cargv[arg_count] = 0;
+ while (--arg_count >= 0)
+ cargv[arg_count] = ACE_Wide_To_Ascii::convert (argv[arg_count]);
+ // Don't worry about freeing the cargv or the strings it points to.
+ // Either the process will be replaced, or we'll exit.
+ if (ACE_OS::execv (cargv[0], cargv) == -1)
+ ACE_OS::exit (errno);
+# else
+ if (ACE_OS::execv (argv[0], argv) == -1)
+ {
+ // The OS layer should not print stuff out
+ // ACE_ERROR ((LM_ERROR,
+ // "%p Exec failed\n"));
+
+ // If the execv fails, this child needs to exit.
+ ACE_OS::exit (errno);
+ }
+# endif /* ACE_HAS_WCHAR */
+
+ default:
+ // Server process. The fork succeeded.
+ return result;
+ }
+# endif /* ACE_WIN32 */
+}
+
+long
+ACE_OS::num_processors (void)
+{
+ ACE_OS_TRACE ("ACE_OS::num_processors");
+
+#if defined (ACE_HAS_PHARLAP)
+ return 1;
+#elif defined (ACE_WIN32)
+ SYSTEM_INFO sys_info;
+ ::GetSystemInfo (&sys_info);
+ return sys_info.dwNumberOfProcessors;
+#elif defined (_SC_NPROCESSORS_CONF)
+ return ::sysconf (_SC_NPROCESSORS_CONF);
+#elif defined (ACE_HAS_SYSCTL)
+ int num_processors;
+ int mib[2] = { CTL_HW, HW_NCPU };
+ size_t len = sizeof (num_processors);
+ if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
+ return num_processors;
+ else
+ return -1;
+#elif defined (__hpux)
+ struct pst_dynamic psd;
+ if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
+ return psd.psd_max_proc_cnt;
+ else
+ return -1;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif
+}
+
+long
+ACE_OS::num_processors_online (void)
+{
+ ACE_OS_TRACE ("ACE_OS::num_processors_online");
+
+#if defined (ACE_HAS_PHARLAP)
+ return 1;
+#elif defined (ACE_WIN32)
+ SYSTEM_INFO sys_info;
+ ::GetSystemInfo (&sys_info);
+ return sys_info.dwNumberOfProcessors;
+#elif defined (_SC_NPROCESSORS_ONLN)
+ return ::sysconf (_SC_NPROCESSORS_ONLN);
+#elif defined (ACE_HAS_SYSCTL)
+ int num_processors;
+ int mib[2] = { CTL_HW, HW_NCPU };
+ size_t len = sizeof (num_processors);
+ if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
+ return num_processors;
+ else
+ return -1;
+#elif defined (__hpux)
+ struct pst_dynamic psd;
+ if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
+ return psd.psd_proc_cnt;
+ else
+ return -1;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif
+}
+
+ssize_t
+ACE_OS::read_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n = 0;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ n = ACE_OS::read (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred);
+
+ if (n == -1 || n == 0)
+ return n;
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE_OS::pread (ACE_HANDLE handle,
+ void *buf,
+ size_t nbytes,
+ ACE_OFF_T offset)
+{
+# if defined (ACE_HAS_P_READ_WRITE)
+# if defined (ACE_WIN32)
+
+ ACE_OS_GUARD
+
+ // Remember the original file pointer position
+ LONG original_high_position = 0;
+ DWORD original_low_position = ::SetFilePointer (handle,
+ 0,
+ &original_high_position,
+ FILE_CURRENT);
+
+ if (original_low_position == INVALID_SET_FILE_POINTER
+ && GetLastError () != NO_ERROR)
+ return -1;
+
+ // Go to the correct position
+ LONG low_offset = ACE_LOW_PART (offset);
+ LONG high_offset = ACE_HIGH_PART (offset);
+ DWORD altered_position = ::SetFilePointer (handle,
+ low_offset,
+ &high_offset,
+ FILE_BEGIN);
+ if (altered_position == INVALID_SET_FILE_POINTER
+ && GetLastError () != NO_ERROR)
+ return -1;
+
+ DWORD bytes_read;
+
+# if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+
+ OVERLAPPED overlapped;
+ overlapped.Internal = 0;
+ overlapped.InternalHigh = 0;
+ overlapped.Offset = low_offset;
+ overlapped.OffsetHigh = high_offset;
+ overlapped.hEvent = 0;
+
+ BOOL result = ::ReadFile (handle,
+ buf,
+ static_cast <DWORD> (nbytes),
+ &bytes_read,
+ &overlapped);
+
+ if (result == FALSE)
+ {
+ if (::GetLastError () != ERROR_IO_PENDING)
+ return -1;
+
+ else
+ {
+ result = ::GetOverlappedResult (handle,
+ &overlapped,
+ &bytes_read,
+ TRUE);
+ if (result == FALSE)
+ return -1;
+ }
+ }
+
+# else /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ BOOL result = ::ReadFile (handle,
+ buf,
+ nbytes,
+ &bytes_read,
+ 0);
+ if (result == FALSE)
+ return -1;
+
+# endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ // Reset the original file pointer position
+ if (::SetFilePointer (handle,
+ original_low_position,
+ &original_high_position,
+ FILE_BEGIN) == INVALID_SET_FILE_POINTER
+ && GetLastError () != NO_ERROR)
+ return -1;
+
+ return (ssize_t) bytes_read;
+
+# else /* ACE_WIN32 */
+
+ return ::pread (handle, buf, nbytes, offset);
+
+# endif /* ACE_WIN32 */
+
+# else /* ACE_HAS_P_READ_WRITE */
+
+ ACE_OS_GUARD
+
+ // Remember the original file pointer position
+ ACE_OFF_T original_position = ACE_OS::lseek (handle,
+ 0,
+ SEEK_CUR);
+
+ if (original_position == -1)
+ return -1;
+
+ // Go to the correct position
+ ACE_OFF_T altered_position = ACE_OS::lseek (handle, offset, SEEK_SET);
+
+ if (altered_position == -1)
+ return -1;
+
+ ssize_t const bytes_read = ACE_OS::read (handle, buf, nbytes);
+
+ if (bytes_read == -1)
+ return -1;
+
+ if (ACE_OS::lseek (handle,
+ original_position,
+ SEEK_SET) == -1)
+ return -1;
+
+ return bytes_read;
+
+# endif /* ACE_HAD_P_READ_WRITE */
+}
+
+ssize_t
+ACE_OS::pwrite (ACE_HANDLE handle,
+ const void *buf,
+ size_t nbytes,
+ ACE_OFF_T offset)
+{
+# if defined (ACE_HAS_P_READ_WRITE)
+# if defined (ACE_WIN32)
+
+ ACE_OS_GUARD
+
+ // Remember the original file pointer position
+ LARGE_INTEGER orig_position;
+ orig_position.QuadPart = 0;
+ orig_position.LowPart = ::SetFilePointer (handle,
+ 0,
+ &orig_position.HighPart,
+ FILE_CURRENT);
+ if (orig_position.LowPart == INVALID_SET_FILE_POINTER
+ && GetLastError () != NO_ERROR)
+ return -1;
+
+ DWORD bytes_written;
+ LARGE_INTEGER loffset;
+ loffset.QuadPart = offset;
+
+# if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+
+ OVERLAPPED overlapped;
+ overlapped.Internal = 0;
+ overlapped.InternalHigh = 0;
+ overlapped.Offset = loffset.LowPart;
+ overlapped.OffsetHigh = loffset.HighPart;
+ overlapped.hEvent = 0;
+
+ BOOL result = ::WriteFile (handle,
+ buf,
+ static_cast <DWORD> (nbytes),
+ &bytes_written,
+ &overlapped);
+
+ if (result == FALSE)
+ {
+ if (::GetLastError () != ERROR_IO_PENDING)
+ return -1;
+
+ result = ::GetOverlappedResult (handle,
+ &overlapped,
+ &bytes_written,
+ TRUE);
+ if (result == FALSE)
+ return -1;
+ }
+
+# else /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ // Go to the correct position; if this is a Windows variant without
+ // overlapped I/O, it probably doesn't have SetFilePointerEx either,
+ // so manage this with SetFilePointer, changing calls based on the use
+ // of 64 bit offsets.
+ DWORD newpos;
+# if defined (_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
+ newpos = ::SetFilePointer (handle,
+ loffset.LowPart,
+ &loffset.HighPart,
+ FILE_BEGIN);
+# else
+ newpos = ::SetFilePointer (handle,
+ loffset.LowPart,
+ 0,
+ FILE_BEGIN);
+# endif /* 64-bit file offsets */
+ if (newpos == 0xFFFFFFFF && ::GetLastError () != NO_ERROR)
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+
+ BOOL result = ::WriteFile (handle,
+ buf,
+ nbytes,
+ &bytes_written,
+ 0);
+ if (result == FALSE)
+ return -1;
+
+# endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+
+ // Reset the original file pointer position
+ if (::SetFilePointer (handle,
+ orig_position.LowPart,
+ &orig_position.HighPart,
+ FILE_BEGIN) == INVALID_SET_FILE_POINTER
+ && GetLastError () != NO_ERROR)
+ return -1;
+
+ return (ssize_t) bytes_written;
+
+# else /* ACE_WIN32 */
+
+ return ::pwrite (handle, buf, nbytes, offset);
+# endif /* ACE_WIN32 */
+# else /* ACE_HAS_P_READ_WRITE */
+
+ ACE_OS_GUARD
+
+ // Remember the original file pointer position
+ ACE_OFF_T original_position = ACE_OS::lseek (handle,
+ 0,
+ SEEK_CUR);
+ if (original_position == -1)
+ return -1;
+
+ // Go to the correct position
+ ACE_OFF_T altered_position = ACE_OS::lseek (handle,
+ offset,
+ SEEK_SET);
+ if (altered_position == -1)
+ return -1;
+
+ ssize_t const bytes_written = ACE_OS::write (handle,
+ buf,
+ nbytes);
+ if (bytes_written == -1)
+ return -1;
+
+ if (ACE_OS::lseek (handle,
+ original_position,
+ SEEK_SET) == -1)
+ return -1;
+
+ return bytes_written;
+# endif /* ACE_HAS_P_READ_WRITE */
+}
+
+int
+ACE_OS::string_to_argv (ACE_TCHAR *buf,
+ int &argc,
+ ACE_TCHAR **&argv,
+ bool substitute_env_args)
+{
+ // Reset the number of arguments
+ argc = 0;
+
+ if (buf == 0)
+ return -1;
+
+ ACE_TCHAR *cp = buf;
+
+ // First pass: count arguments.
+
+ // '#' is the start-comment token..
+ while (*cp != ACE_TEXT ('\0') && *cp != ACE_TEXT ('#'))
+ {
+ // Skip whitespace..
+ while (ACE_OS::ace_isspace (*cp))
+ ++cp;
+
+ // Increment count and move to next whitespace..
+ if (*cp != ACE_TEXT ('\0'))
+ ++argc;
+
+ while (*cp != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*cp))
+ {
+ // Grok quotes....
+ if (*cp == ACE_TEXT ('\'') || *cp == ACE_TEXT ('"'))
+ {
+ ACE_TCHAR quote = *cp;
+
+ // Scan past the string..
+ for (++cp; *cp != ACE_TEXT ('\0')
+ && (*cp != quote || cp[-1] == ACE_TEXT ('\\')); ++cp)
+ continue;
+
+ // '\0' implies unmatched quote..
+ if (*cp == ACE_TEXT ('\0'))
+ {
+ --argc;
+ break;
+ }
+ else
+ ++cp;
+ }
+ else
+ ++cp;
+ }
+ }
+
+ // Second pass: copy arguments.
+ ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ];
+ ACE_TCHAR *argp = arg;
+
+ // Make sure that the buffer we're copying into is always large
+ // enough.
+ if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ)
+ ACE_NEW_RETURN (argp,
+ ACE_TCHAR[cp - buf + 1],
+ -1);
+
+ // Make a new argv vector of argc + 1 elements.
+ ACE_NEW_RETURN (argv,
+ ACE_TCHAR *[argc + 1],
+ -1);
+
+ ACE_TCHAR *ptr = buf;
+
+ for (int i = 0; i < argc; ++i)
+ {
+ // Skip whitespace..
+ while (ACE_OS::ace_isspace (*ptr))
+ ++ptr;
+
+ // Copy next argument and move to next whitespace..
+ cp = argp;
+ while (*ptr != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*ptr))
+ if (*ptr == ACE_TEXT ('\'') || *ptr == ACE_TEXT ('"'))
+ {
+ ACE_TCHAR quote = *ptr++;
+
+ while (*ptr != ACE_TEXT ('\0')
+ && (*ptr != quote || ptr[-1] == ACE_TEXT ('\\')))
+ {
+ if (*ptr == quote && ptr[-1] == ACE_TEXT ('\\')) --cp;
+ *cp++ = *ptr++;
+ }
+
+ if (*ptr == quote)
+ ++ptr;
+ }
+ else
+ *cp++ = *ptr++;
+
+ *cp = ACE_TEXT ('\0');
+
+#if !defined (ACE_LACKS_ENV)
+ // Check for environment variable substitution here.
+ if (substitute_env_args) {
+ argv[i] = ACE_OS::strenvdup (argp);
+
+ if (argv[i] == 0)
+ {
+ if (argp != arg)
+ delete [] argp;
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ else
+#endif /* ACE_LACKS_ENV */
+ {
+ argv[i] = ACE_OS::strdup (argp);
+
+ if (argv[i] == 0)
+ {
+ if (argp != arg)
+ delete [] argp;
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ }
+
+ if (argp != arg)
+ delete [] argp;
+
+ argv[argc] = 0;
+ return 0;
+}
+
+// Write <len> bytes from <buf> to <handle> (uses the <write>
+// system call on UNIX and the <WriteFile> call on Win32).
+
+ssize_t
+ACE_OS::write_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ size_t *bt)
+{
+ size_t temp;
+ size_t &bytes_transferred = bt == 0 ? temp : *bt;
+ ssize_t n;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ n = ACE_OS::write (handle,
+ (char *) buf + bytes_transferred,
+ len - bytes_transferred);
+
+ if (n == -1 || n == 0)
+ return n;
+ }
+
+ return bytes_transferred;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_unistd.h b/ACE/ace/OS_NS_unistd.h
new file mode 100644
index 00000000000..aeb5b181964
--- /dev/null
+++ b/ACE/ace/OS_NS_unistd.h
@@ -0,0 +1,375 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_unistd.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_UNISTD_H
+# define ACE_OS_NS_UNISTD_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/ACE_export.h"
+#include "ace/Time_Value.h"
+#include "ace/Basic_Types.h"
+#include "ace/os_include/os_unistd.h"
+#include "ace/os_include/os_stdio.h"
+
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+// This should go in os_unistd.h, but since we don't yet implement any code
+// at that level, we put it here. It used to be in OS.i.
+#if defined (ACE_NEEDS_FTRUNCATE)
+extern "C" ACE_Export int ftruncate (ACE_HANDLE handle, long len);
+#endif /* ACE_NEEDS_FTRUNCATE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int access (const char *path, int amode);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int access (const wchar_t *path, int amode);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ unsigned int alarm (u_int secs);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long allocation_granularity (void);
+
+ // used by ARGV::argv_to_string() and ACE_OS::fork_exec()
+ extern ACE_Export
+ int argv_to_string (ACE_TCHAR **argv,
+ ACE_TCHAR *&buf,
+ bool substitute_env_args = true,
+ bool quote_args = false);
+
+#if !defined (ACE_LACKS_CHDIR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int chdir (const char *path);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int chdir (const wchar_t *path);
+#endif /* ACE_HAS_WCHAR */
+#endif /* ACE_LACKS_CHDIR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rmdir (const char *path);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int rmdir (const wchar_t *path);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int close (ACE_HANDLE handle);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE dup (ACE_HANDLE handle);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int dup2 (ACE_HANDLE oldfd,
+ ACE_HANDLE newfd);
+
+ extern ACE_Export
+ int execl (const char *path,
+ const char *arg0, ...);
+
+ extern ACE_Export
+ int execle (const char *path,
+ const char *arg0, ...);
+
+ extern ACE_Export
+ int execlp (const char *file,
+ const char *arg0, ...);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int execv (const char *path,
+ char *const argv[]);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int execve (const char *path,
+ char *const argv[],
+ char *const envp[]);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int execvp (const char *file,
+ char *const argv[]);
+
+ //@{
+ /// Forks and exec's a process in a manner that works on Solaris and
+ /// NT. argv[0] must be the full path name to the executable.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ pid_t fork (void);
+
+ // not in susv3
+ extern ACE_Export
+ pid_t fork (const ACE_TCHAR *program_name);
+
+ extern ACE_Export
+ pid_t fork_exec (ACE_TCHAR *argv[]);
+
+ //@}
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int fsync (ACE_HANDLE handle);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int ftruncate (ACE_HANDLE handle, ACE_OFF_T offset);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *getcwd (char *, size_t);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wchar_t *getcwd (wchar_t *, size_t);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ gid_t getgid (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ gid_t getegid (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int getopt (int argc,
+ char *const *argv,
+ const char *optstring);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long getpagesize (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ pid_t getpgid (pid_t pid);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ pid_t getpid (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ pid_t getppid (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ uid_t getuid (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ uid_t geteuid (void);
+
+ // should call gethostname()
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int hostname (char *name,
+ size_t maxnamelen);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int hostname (wchar_t *name,
+ size_t maxnamelen);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int isatty (int handle);
+
+#if defined (ACE_WIN32)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int isatty (ACE_HANDLE handle);
+#endif /* ACE_WIN32 */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_OFF_T lseek (ACE_HANDLE handle,
+ ACE_OFF_T offset,
+ int whence);
+
+#if defined (ACE_HAS_LLSEEK) || defined (ACE_HAS_LSEEK64)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_LOFF_T llseek (ACE_HANDLE handle,
+ ACE_LOFF_T offset,
+ int whence);
+#endif /* ACE_HAS_LLSEEK */
+
+ /// Get the number of CPUs configured in the machine.
+ extern ACE_Export
+ long num_processors (void);
+
+ /// Get the number of CPUs currently online.
+ extern ACE_Export
+ long num_processors_online (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int pipe (ACE_HANDLE handles[]);
+
+ extern ACE_Export
+ ssize_t pread (ACE_HANDLE handle,
+ void *buf,
+ size_t nbyte,
+ ACE_OFF_T offset);
+
+ extern ACE_Export
+ ssize_t pwrite (ACE_HANDLE handle,
+ const void *buf,
+ size_t nbyte,
+ ACE_OFF_T offset);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t read (ACE_HANDLE handle,
+ void *buf,
+ size_t len);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t read (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ ACE_OVERLAPPED *);
+
+ /**
+ * Receive @a len bytes into @a buf from <handle> (uses the
+ * <ACE_OS::read> call, which uses the <read> system call on UNIX
+ * and the <ReadFile> call on Win32). If errors occur, -1 is
+ * returned. If EOF occurs, 0 is returned. Whatever data has been
+ * read will be returned to the caller through<bytes_transferred>.
+ *
+ */
+ extern ACE_Export
+ ssize_t read_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len,
+ size_t *bytes_transferred = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t readlink (const char *path,
+ char *buf,
+ size_t bufsiz);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void *sbrk (intptr_t brk);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int setgid (gid_t);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int setegid (gid_t);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int setpgid (pid_t pid, pid_t pgid);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int setregid (gid_t rgid, gid_t egid);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int setreuid (uid_t ruid, uid_t euid);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ pid_t setsid (void);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int setuid (uid_t);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int seteuid (uid_t);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sleep (u_int seconds);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int sleep (const ACE_Time_Value &tv);
+
+ // used by ARGV::string_to_argv
+ extern ACE_Export
+ int string_to_argv (ACE_TCHAR *buf,
+ int &argc,
+ ACE_TCHAR **&argv,
+ bool substitute_env_args = true);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void swab (const void *src, void *dest, ssize_t n);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long sysconf (int);
+
+ // not in susv3
+ ACE_NAMESPACE_INLINE_FUNCTION
+ long sysinfo (int cmd,
+ char *buf,
+ long count);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int truncate (const ACE_TCHAR *filename, ACE_OFF_T length);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ useconds_t ualarm (useconds_t usecs,
+ useconds_t interval = 0);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ useconds_t ualarm (const ACE_Time_Value &tv,
+ const ACE_Time_Value &tv_interval = ACE_Time_Value::zero);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int unlink (const char *path);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int unlink (const wchar_t *path);
+#endif /* ACE_HAS_WCHAR */
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t write (ACE_HANDLE handle,
+ const void *buf,
+ size_t nbyte);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ssize_t write (ACE_HANDLE handle,
+ const void *buf,
+ size_t nbyte,
+ ACE_OVERLAPPED *);
+
+ /**
+ * Send @a len bytes from @a buf to @a handle (uses the <ACE_OS::write>
+ * calls, which is uses the <write> system call on UNIX and the
+ * <WriteFile> call on Win32). If errors occur, -1 is returned. If
+ * EOF occurs, 0 is returned. Whatever data has been transmitted
+ * will be returned to the caller through <bytes_transferred>.
+ */
+ extern ACE_Export
+ ssize_t write_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len,
+ size_t *bytes_transferred = 0);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_unistd.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_UNISTD_H */
diff --git a/ACE/ace/OS_NS_unistd.inl b/ACE/ace/OS_NS_unistd.inl
new file mode 100644
index 00000000000..62bb81d6be5
--- /dev/null
+++ b/ACE/ace/OS_NS_unistd.inl
@@ -0,0 +1,1193 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_sys_utsname.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_macros.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/Default_Constants.h"
+#include "ace/OS_Memory.h"
+#include "ace/Truncate.h"
+
+#if defined (ACE_HAS_CLOCK_GETTIME)
+# include "ace/os_include/os_time.h"
+#endif /* ACE_HAS_CLOCK_GETTIME */
+
+#if defined (ACE_LACKS_ACCESS)
+# include "ace/OS_NS_stdio.h"
+#endif /* ACE_LACKS_ACCESS */
+
+#if defined (ACE_VXWORKS) || defined (ACE_HAS_WINCE)
+# include "ace/os_include/os_unistd.h"
+# if defined (ACE_VXWORKS) && ((ACE_VXWORKS >= 0x620) && (ACE_VXWORKS <= 0x660))
+# if defined (__RTP__)
+# include "ace/os_include/os_strings.h"
+# else
+# include "ace/os_include/os_string.h"
+# endif
+# endif
+#endif /* VXWORKS || ACE_HAS_WINCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_OS::access (const char *path, int amode)
+{
+ ACE_OS_TRACE ("ACE_OS::access");
+#if defined (ACE_LACKS_ACCESS)
+# if defined (ACE_HAS_WINCE) || defined (ACE_VXWORKS)
+ // @@ WINCE: There should be a Win32 API that can do this.
+ // Hard coded read access here.
+ ACE_UNUSED_ARG (amode);
+ FILE* handle = ACE_OS::fopen (ACE_TEXT_CHAR_TO_TCHAR(path),
+ ACE_TEXT ("r"));
+ if (handle != 0)
+ {
+ ACE_OS::fclose (handle);
+ return 0;
+ }
+ return (-1);
+# else
+ ACE_UNUSED_ARG (path);
+ ACE_UNUSED_ARG (amode);
+ ACE_NOTSUP_RETURN (-1);
+# endif // ACE_HAS_WINCE
+#elif defined(ACE_WIN32)
+ // Windows doesn't support checking X_OK(6)
+ ACE_OSCALL_RETURN (::access (path, amode & 6), int, -1);
+#else
+ ACE_OSCALL_RETURN (::access (path, amode), int, -1);
+#endif /* ACE_LACKS_ACCESS */
+}
+
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::access (const wchar_t *path, int amode)
+{
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ ACE_OSCALL_RETURN (::_waccess (path, amode), int, -1);
+#else /* ACE_WIN32 && !ACE_HAS_WINCE */
+ return ACE_OS::access (ACE_Wide_To_Ascii (path).char_rep (), amode);
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE u_int
+ACE_OS::alarm (u_int secs)
+{
+ ACE_OS_TRACE ("ACE_OS::alarm");
+#if defined (ACE_LACKS_ALARM)
+ ACE_UNUSED_ARG (secs);
+ ACE_NOTSUP_RETURN (0);
+#else
+ return ::alarm (secs);
+#endif /* ACE_LACKS_ALARM */
+}
+
+ACE_INLINE long
+ACE_OS::getpagesize (void)
+{
+ ACE_OS_TRACE ("ACE_OS::getpagesize");
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+ SYSTEM_INFO sys_info;
+ ::GetSystemInfo (&sys_info);
+ return (long) sys_info.dwPageSize;
+#elif defined (_SC_PAGESIZE) && !defined (ACE_HAS_NOTSUP_SC_PAGESIZE)
+ return ::sysconf (_SC_PAGESIZE);
+#elif defined (ACE_HAS_GETPAGESIZE)
+ return ::getpagesize ();
+#else
+ // Use the default set in config.h
+ return ACE_PAGE_SIZE;
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE long
+ACE_OS::allocation_granularity (void)
+{
+#if defined (ACE_WIN32)
+ SYSTEM_INFO sys_info;
+ ::GetSystemInfo (&sys_info);
+ return sys_info.dwAllocationGranularity;
+#else
+ return ACE_OS::getpagesize ();
+#endif /* ACE_WIN32 */
+}
+
+#if !defined (ACE_LACKS_CHDIR)
+ACE_INLINE int
+ACE_OS::chdir (const char *path)
+{
+ ACE_OS_TRACE ("ACE_OS::chdir");
+#if defined (ACE_HAS_NONCONST_CHDIR)
+ ACE_OSCALL_RETURN (::chdir (const_cast<char *> (path)), int, -1);
+#elif defined (ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (path);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::chdir (path), int, -1);
+#endif /* ACE_HAS_NONCONST_CHDIR */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::chdir (const wchar_t *path)
+{
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ ACE_OSCALL_RETURN (::_wchdir (path), int, -1);
+#else /* ACE_WIN32 */
+ return ACE_OS::chdir (ACE_Wide_To_Ascii (path).char_rep ());
+#endif /* ACE_WIN32 */
+}
+#endif /* ACE_HAS_WCHAR */
+#endif /* ACE_LACKS_CHDIR */
+
+ACE_INLINE int
+ACE_OS::rmdir (const char *path)
+{
+#if defined (ACE_HAS_WINCE)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::RemoveDirectory (ACE_TEXT_CHAR_TO_TCHAR (path)),
+ ace_result_),
+ int, -1);
+#else
+ ACE_OSCALL_RETURN (::rmdir (path), int, -1);
+#endif /* ACE_WIN32 */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::rmdir (const wchar_t *path)
+{
+#if defined (ACE_HAS_WINCE)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::RemoveDirectoryW (path),
+ ace_result_),
+ int, -1);
+#elif defined (ACE_WIN32)
+ ACE_OSCALL_RETURN (::_wrmdir (path), int, -1);
+#else
+ ACE_Wide_To_Ascii n_path (path);
+ return ACE_OS::rmdir (n_path.char_rep ());
+#endif /* ACE_HAS_WINCE */
+}
+#endif /* ACE_HAS_WCHAR */
+
+// @todo: which 4 and why??? dhinton
+// NOTE: The following four function definitions must appear before
+// ACE_OS::sema_init ().
+
+ACE_INLINE int
+ACE_OS::close (ACE_HANDLE handle)
+{
+ ACE_OS_TRACE ("ACE_OS::close");
+#if defined (ACE_WIN32)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (handle), ace_result_), int, -1);
+#else
+ ACE_OSCALL_RETURN (::close (handle), int, -1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_OS::dup (ACE_HANDLE handle)
+{
+ ACE_OS_TRACE ("ACE_OS::dup");
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ ACE_HANDLE new_fd;
+ if (::DuplicateHandle(::GetCurrentProcess (),
+ handle,
+ ::GetCurrentProcess(),
+ &new_fd,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ return new_fd;
+ else
+ ACE_FAIL_RETURN (ACE_INVALID_HANDLE);
+ /* NOTREACHED */
+#elif defined (ACE_LACKS_DUP)
+ ACE_UNUSED_ARG (handle);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (handle);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN (::dup (handle), ACE_HANDLE, ACE_INVALID_HANDLE);
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+}
+
+ACE_INLINE int
+ACE_OS::dup2 (ACE_HANDLE oldhandle, ACE_HANDLE newhandle)
+{
+ ACE_OS_TRACE ("ACE_OS::dup2");
+#if defined (ACE_LACKS_DUP2)
+ // msvcrt has _dup2 ?!
+ ACE_UNUSED_ARG (oldhandle);
+ ACE_UNUSED_ARG (newhandle);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::dup2 (oldhandle, newhandle), int, -1);
+#endif /* ACE_LACKS_DUP2 */
+}
+
+ACE_INLINE int
+ACE_OS::execv (const char *path,
+ char *const argv[])
+{
+ ACE_OS_TRACE ("ACE_OS::execv");
+#if defined (ACE_LACKS_EXEC)
+ ACE_UNUSED_ARG (path);
+ ACE_UNUSED_ARG (argv);
+
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+# if defined (__BORLANDC__) /* VSB */
+ return ::execv (path, argv);
+# elif defined (__MINGW32__)
+ return ::_execv (path, (char *const *) argv);
+# else
+ // Why this odd-looking code? If execv() returns at all, it's an error.
+ // Windows defines this as returning an intptr_t rather than a simple int,
+ // and the conversion triggers compile warnings. So just return -1 if
+ // the call returns.
+ ::_execv (path, (const char *const *) argv);
+ return -1;
+# endif /* __BORLANDC__ */
+#else
+ ACE_OSCALL_RETURN (::execv (path, argv), int, -1);
+#endif /* ACE_LACKS_EXEC */
+}
+
+ACE_INLINE int
+ACE_OS::execve (const char *path,
+ char *const argv[],
+ char *const envp[])
+{
+ ACE_OS_TRACE ("ACE_OS::execve");
+#if defined (ACE_LACKS_EXEC)
+ ACE_UNUSED_ARG (path);
+ ACE_UNUSED_ARG (argv);
+ ACE_UNUSED_ARG (envp);
+
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+# if defined (__BORLANDC__) /* VSB */
+ return ::execve (path, argv, envp);
+# elif defined (__MINGW32__)
+ return ::_execve (path, (char *const *) argv, (char *const *) envp);
+# else
+ // Why this odd-looking code? If execv() returns at all, it's an error.
+ // Windows defines this as returning an intptr_t rather than a simple int,
+ // and the conversion triggers compile warnings. So just return -1 if
+ // the call returns.
+ ::_execve (path, (const char *const *) argv, (const char *const *) envp);
+ return -1;
+# endif /* __BORLANDC__ */
+#else
+ ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1);
+#endif /* ACE_LACKS_EXEC */
+}
+
+ACE_INLINE int
+ACE_OS::execvp (const char *file,
+ char *const argv[])
+{
+ ACE_OS_TRACE ("ACE_OS::execvp");
+#if defined (ACE_LACKS_EXEC)
+ ACE_UNUSED_ARG (file);
+ ACE_UNUSED_ARG (argv);
+
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+# if defined (__BORLANDC__) /* VSB */
+ return ::execvp (file, argv);
+# elif defined (__MINGW32__)
+ return ::_execvp (file, (char *const *) argv);
+# else
+ // Why this odd-looking code? If execv() returns at all, it's an error.
+ // Windows defines this as returning an intptr_t rather than a simple int,
+ // and the conversion triggers compile warnings. So just return -1 if
+ // the call returns.
+ ::_execvp (file, (const char *const *) argv);
+ return -1;
+# endif /* __BORLANDC__ */
+#else
+ ACE_OSCALL_RETURN (::execvp (file, argv), int, -1);
+#endif /* ACE_LACKS_EXEC */
+}
+
+ACE_INLINE pid_t
+ACE_OS::fork (void)
+{
+ ACE_OS_TRACE ("ACE_OS::fork");
+#if defined (ACE_LACKS_FORK)
+ ACE_NOTSUP_RETURN (pid_t (-1));
+#else
+ ACE_OSCALL_RETURN (::fork (), pid_t, -1);
+#endif /* ACE_LACKS_FORK */
+}
+
+ACE_INLINE int
+ACE_OS::fsync (ACE_HANDLE handle)
+{
+ ACE_OS_TRACE ("ACE_OS::fsync");
+# if defined (ACE_LACKS_FSYNC)
+ ACE_UNUSED_ARG (handle);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_WIN32)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::FlushFileBuffers (handle), ace_result_), int, -1);
+# else
+ ACE_OSCALL_RETURN (::fsync (handle), int, -1);
+# endif /* ACE_LACKS_FSYNC */
+}
+
+ACE_INLINE int
+ACE_OS::ftruncate (ACE_HANDLE handle, ACE_OFF_T offset)
+{
+ ACE_OS_TRACE ("ACE_OS::ftruncate");
+#if defined (ACE_WIN32)
+# if !defined (ACE_LACKS_WIN32_SETFILEPOINTEREX)
+ LARGE_INTEGER loff;
+ loff.QuadPart = offset;
+ if (::SetFilePointerEx (handle, loff, 0, FILE_BEGIN))
+# else
+ if (::SetFilePointer (handle,
+ offset,
+ 0,
+ FILE_BEGIN) != INVALID_SET_FILE_POINTER)
+# endif
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEndOfFile (handle), ace_result_), int, -1);
+ else
+ ACE_FAIL_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::ftruncate (handle, offset), int, -1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE char *
+ACE_OS::getcwd (char *buf, size_t size)
+{
+ ACE_OS_TRACE ("ACE_OS::getcwd");
+#if defined (ACE_LACKS_GETCWD)
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (size);
+ ACE_NOTSUP_RETURN (0);
+#elif defined (ACE_WIN32)
+ return ::getcwd (buf, static_cast<int> (size));
+#else
+ ACE_OSCALL_RETURN (::getcwd (buf, size), char *, 0);
+#endif /* ACE_LACKS_GETCWD */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wchar_t *
+ACE_OS::getcwd (wchar_t *buf, size_t size)
+{
+# if defined (ACE_HAS_WINCE)
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (size);
+ ACE_NOTSUP_RETURN (0);
+# elif defined (ACE_WIN32)
+ return ::_wgetcwd (buf, static_cast<int> (size));
+# else
+ char *narrow_buf = new char[size];
+ char *result = 0;
+ result = ACE_OS::getcwd (narrow_buf, size);
+ ACE_Ascii_To_Wide wide_buf (result);
+ delete [] narrow_buf;
+ if (result != 0)
+ ACE_OS::strsncpy (buf, wide_buf.wchar_rep (), size);
+ return result == 0 ? 0 : buf;
+# endif /* ACE_WIN32 */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE gid_t
+ACE_OS::getgid (void)
+{
+ ACE_OS_TRACE ("ACE_OS::getgid");
+#if defined (ACE_LACKS_GETGID)
+ ACE_NOTSUP_RETURN (static_cast<gid_t> (-1));
+# else
+ ACE_OSCALL_RETURN (::getgid (), gid_t, static_cast<gid_t> (-1));
+# endif /* ACE_LACKS_GETGID */
+}
+
+ACE_INLINE gid_t
+ACE_OS::getegid (void)
+{
+ ACE_OS_TRACE ("ACE_OS::getegid");
+#if defined (ACE_LACKS_GETEGID)
+ ACE_NOTSUP_RETURN (static_cast<gid_t> (-1));
+# else
+ ACE_OSCALL_RETURN (::getegid (), gid_t, static_cast<gid_t> (-1));
+# endif /* ACE_LACKS_GETEGID */
+}
+
+ACE_INLINE int
+ACE_OS::getopt (int argc, char *const *argv, const char *optstring)
+{
+ ACE_OS_TRACE ("ACE_OS::getopt");
+#if defined (ACE_LACKS_GETOPT)
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+ ACE_UNUSED_ARG (optstring);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ ACE_OSCALL_RETURN (::getopt (argc, argv, optstring), int, -1);
+# endif /* ACE_LACKS_GETOPT */
+}
+
+ACE_INLINE pid_t
+ACE_OS::getpgid (pid_t pid)
+{
+ ACE_OS_TRACE ("ACE_OS::getpgid");
+#if defined (ACE_LACKS_GETPGID)
+ ACE_UNUSED_ARG (pid);
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (linux) && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 0
+ // getpgid() is from SVR4, which appears to be the reason why GLIBC
+ // doesn't enable its prototype by default.
+ // Rather than create our own extern prototype, just use the one
+ // that is visible (ugh).
+ ACE_OSCALL_RETURN (::__getpgid (pid), pid_t, -1);
+#else
+ ACE_OSCALL_RETURN (::getpgid (pid), pid_t, -1);
+#endif /* ACE_LACKS_GETPGID */
+}
+
+ACE_INLINE pid_t
+ACE_OS::getpid (void)
+{
+ // ACE_OS_TRACE ("ACE_OS::getpid");
+#if defined (ACE_LACKS_GETPID)
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_WIN32)
+ return ::GetCurrentProcessId ();
+#else
+ ACE_OSCALL_RETURN (::getpid (), int, -1);
+#endif /* ACE_LACKS_GETPID */
+}
+
+ACE_INLINE pid_t
+ACE_OS::getppid (void)
+{
+ ACE_OS_TRACE ("ACE_OS::getppid");
+#if defined (ACE_LACKS_GETPPID)
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::getppid (), pid_t, -1);
+#endif /* ACE_LACKS_GETPPID */
+}
+
+ACE_INLINE uid_t
+ACE_OS::getuid (void)
+{
+ ACE_OS_TRACE ("ACE_OS::getuid");
+#if defined (ACE_LACKS_GETUID)
+ ACE_NOTSUP_RETURN (static_cast<uid_t> (-1));
+# else
+ ACE_OSCALL_RETURN (::getuid (), uid_t, static_cast<uid_t> (-1));
+# endif /* ACE_LACKS_GETUID*/
+}
+
+ACE_INLINE uid_t
+ACE_OS::geteuid (void)
+{
+ ACE_OS_TRACE ("ACE_OS::geteuid");
+#if defined (ACE_LACKS_GETEUID)
+ ACE_NOTSUP_RETURN (static_cast<uid_t> (-1));
+# else
+ ACE_OSCALL_RETURN (::geteuid (), uid_t, (uid_t) -1);
+# endif /* ACE_LACKS_GETEUID */
+}
+
+ACE_INLINE int
+ACE_OS::hostname (char name[], size_t maxnamelen)
+{
+ ACE_OS_TRACE ("ACE_OS::hostname");
+#if defined (ACE_HAS_PHARLAP)
+ // PharLap only can do net stuff with the RT version.
+# if defined (ACE_HAS_PHARLAP_RT)
+ // @@This is not at all reliable... requires ethernet and BOOTP to be used.
+ // A more reliable way is to go thru the devices w/ EtsTCPGetDeviceCfg until
+ // a legit IP address is found, then get its name w/ gethostbyaddr.
+ ACE_SOCKCALL_RETURN (gethostname (name, maxnamelen), int, SOCKET_ERROR);
+# else
+ ACE_UNUSED_ARG (name);
+ ACE_UNUSED_ARG (maxnamelen);
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PHARLAP_RT */
+#elif defined (ACE_VXWORKS) || defined (ACE_HAS_WINCE)
+ ACE_OSCALL_RETURN (::gethostname (name, maxnamelen), int, -1);
+#elif defined (ACE_WIN32)
+ if (::gethostname (name, ACE_Utils::truncate_cast<int> (maxnamelen)) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::GetComputerNameA (name,
+ LPDWORD (&maxnamelen)),
+ ace_result_), int, -1);
+ }
+#else /* ACE_HAS_PHARLAP */
+ ACE_utsname host_info;
+
+ if (ACE_OS::uname (&host_info) == -1)
+ return -1;
+ else
+ {
+ ACE_OS::strsncpy (name, host_info.nodename, maxnamelen);
+ return 0;
+ }
+#endif /* ACE_HAS_PHARLAP */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::hostname (wchar_t name[], size_t maxnamelen)
+{
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (GetComputerNameW (name,
+ LPDWORD (&maxnamelen)),
+ ace_result_), int, -1);
+#else /* ACE_WIN32 && !ACE_HAS_WINCE */
+ // Emulate using the char version
+ char *char_name = 0;
+ int result = 0;
+
+ ACE_NEW_RETURN (char_name, char[maxnamelen], -1);
+
+ result = ACE_OS::hostname(char_name, maxnamelen);
+ ACE_OS::strcpy (name, ACE_Ascii_To_Wide (char_name).wchar_rep ());
+
+ delete [] char_name;
+ return result;
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE int
+ACE_OS::isatty (int handle)
+{
+ ACE_OS_TRACE ("ACE_OS::isatty");
+#if defined (ACE_LACKS_ISATTY)
+ ACE_UNUSED_ARG (handle);
+ return 0;
+# elif defined (ACE_WIN32)
+ return ::_isatty (handle);
+# else
+ ACE_OSCALL_RETURN (::isatty (handle), int, -1);
+# endif /* ACE_LACKS_ISATTY */
+}
+
+#if defined (ACE_WIN32)
+ACE_INLINE int
+ACE_OS::isatty (ACE_HANDLE handle)
+{
+#if defined (ACE_LACKS_ISATTY)
+ ACE_UNUSED_ARG (handle);
+ return 0;
+#else
+ int fd = ::_open_osfhandle (intptr_t (handle), 0);
+ int status = ::_isatty (fd);
+ ::_close (fd);
+ return status;
+#endif /* ACE_LACKS_ISATTY */
+}
+
+#endif /* ACE_WIN32 */
+
+ACE_INLINE ACE_OFF_T
+ACE_OS::lseek (ACE_HANDLE handle, ACE_OFF_T offset, int whence)
+{
+ ACE_OS_TRACE ("ACE_OS::lseek");
+#if defined (ACE_WIN32)
+# if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END
+ //#error Windows NT is evil AND rude!
+ switch (whence)
+ {
+ case SEEK_SET:
+ whence = FILE_BEGIN;
+ break;
+ case SEEK_CUR:
+ whence = FILE_CURRENT;
+ break;
+ case SEEK_END:
+ whence = FILE_END;
+ break;
+ default:
+ errno = EINVAL;
+ return static_cast<ACE_OFF_T> (-1); // rather safe than sorry
+ }
+# endif /* SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END */
+ LONG low_offset = ACE_LOW_PART(offset);
+ LONG high_offset = ACE_HIGH_PART(offset);
+ DWORD const result =
+ ::SetFilePointer (handle, low_offset, &high_offset, whence);
+ if (result == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
+ ACE_FAIL_RETURN (static_cast<ACE_OFF_T> (-1));
+ else
+ return result;
+#else
+ ACE_OSCALL_RETURN (::lseek (handle, offset, whence), ACE_OFF_T, -1);
+#endif /* ACE_WIN32 */
+}
+
+#if defined (ACE_HAS_LLSEEK) || defined (ACE_HAS_LSEEK64)
+ACE_INLINE ACE_LOFF_T
+ACE_OS::llseek (ACE_HANDLE handle, ACE_LOFF_T offset, int whence)
+{
+ ACE_OS_TRACE ("ACE_OS::llseek");
+
+#if ACE_SIZEOF_LONG == 8
+ /* The native lseek is 64 bit. Use it. */
+ return ACE_OS::lseek (handle, offset, whence);
+#elif defined (ACE_HAS_LLSEEK) && defined (ACE_HAS_LSEEK64)
+# error Either ACE_HAS_LSEEK64 and ACE_HAS_LLSEEK should be defined, not both!
+#elif defined (ACE_HAS_LSEEK64)
+ ACE_OSCALL_RETURN (::lseek64 (handle, offset, whence), ACE_LOFF_T, -1);
+#elif defined (ACE_HAS_LLSEEK)
+# if defined (ACE_WIN32)
+# ifndef ACE_LACKS_WIN32_SETFILEPOINTEREX
+ LARGE_INTEGER distance, new_file_pointer;
+
+ distance.QuadPart = offset;
+
+ return
+ (::SetFilePointerEx (handle, distance, &new_file_pointer, whence)
+ ? new_file_pointer.QuadPart
+ : static_cast<ACE_LOFF_T> (-1));
+# else
+ LARGE_INTEGER l_offset;
+ l_offset.QuadPart = offset;
+ LONG low_offset = l_offset.LowPart;
+ LONG high_offset = l_offset.HighPart;
+
+ l_offset.LowPart = ::SetFilePointer (handle,
+ low_offset,
+ &high_offset,
+ whence);
+ if (l_offset.LowPart == INVALID_SET_FILE_POINTER &&
+ GetLastError () != NO_ERROR)
+ return static_cast<ACE_LOFF_T> (-1);
+ l_offset.HighPart = high_offset;
+ return l_offset.QuadPart;
+# endif /* ACE_LACKS_WIN32_SETFILEPOINTEREX */
+# else
+ ACE_OSCALL_RETURN (::llseek (handle, offset, whence), ACE_LOFF_T, -1);
+# endif /* WIN32 */
+#endif
+}
+#endif /* ACE_HAS_LLSEEK || ACE_HAS_LSEEK64 */
+
+ACE_INLINE ssize_t
+ACE_OS::read (ACE_HANDLE handle, void *buf, size_t len)
+{
+ ACE_OS_TRACE ("ACE_OS::read");
+#if defined (ACE_WIN32)
+ DWORD ok_len;
+ if (::ReadFile (handle, buf, static_cast<DWORD> (len), &ok_len, 0))
+ return (ssize_t) ok_len;
+ else
+ ACE_FAIL_RETURN (-1);
+#else
+
+ ssize_t result;
+
+# if defined (ACE_HAS_CHARPTR_SOCKOPT)
+ ACE_OSCALL (::read (handle, static_cast <char *> (buf), len), ssize_t, -1, result);
+# else
+ ACE_OSCALL (::read (handle, buf, len), ssize_t, -1, result);
+# endif /* ACE_HAS_CHARPTR_SOCKOPT */
+
+# if !(defined (EAGAIN) && defined (EWOULDBLOCK) && EAGAIN == EWOULDBLOCK)
+ // Optimize this code out if we can detect that EAGAIN ==
+ // EWOULDBLOCK at compile time. If we cannot detect equality at
+ // compile-time (e.g. if EAGAIN or EWOULDBLOCK are not preprocessor
+ // macros) perform the check at run-time. The goal is to avoid two
+ // TSS accesses in the _REENTRANT case when EAGAIN == EWOULDBLOCK.
+ if (result == -1
+# if !defined (EAGAIN) || !defined (EWOULDBLOCK)
+ && EAGAIN != EWOULDBLOCK
+# endif /* !EAGAIN || !EWOULDBLOCK */
+ && errno == EAGAIN)
+ {
+ errno = EWOULDBLOCK;
+ }
+# endif /* EAGAIN != EWOULDBLOCK*/
+
+ return result;
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::read (ACE_HANDLE handle, void *buf, size_t len,
+ ACE_OVERLAPPED *overlapped)
+{
+ ACE_OS_TRACE ("ACE_OS::read");
+ overlapped = overlapped;
+#if defined (ACE_WIN32)
+ DWORD ok_len;
+ DWORD short_len = static_cast<DWORD> (len);
+ if (::ReadFile (handle, buf, short_len, &ok_len, overlapped))
+ return (ssize_t) ok_len;
+ else
+ ACE_FAIL_RETURN (-1);
+#else
+ return ACE_OS::read (handle, buf, len);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::readlink (const char *path, char *buf, size_t bufsiz)
+{
+ ACE_OS_TRACE ("ACE_OS::readlink");
+# if defined (ACE_LACKS_READLINK)
+ ACE_UNUSED_ARG (path);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (bufsiz);
+ ACE_NOTSUP_RETURN (-1);
+# else
+# if !defined(ACE_HAS_NONCONST_READLINK)
+ ACE_OSCALL_RETURN (::readlink (path, buf, bufsiz), ssize_t, -1);
+# else
+ ACE_OSCALL_RETURN (
+ ::readlink (const_cast <char *>(path), buf, bufsiz), ssize_t, -1);
+# endif
+# endif /* ACE_LACKS_READLINK */
+}
+
+ACE_INLINE int
+ACE_OS::pipe (ACE_HANDLE fds[])
+{
+ ACE_OS_TRACE ("ACE_OS::pipe");
+# if defined (ACE_LACKS_PIPE)
+ ACE_UNUSED_ARG (fds);
+ ACE_NOTSUP_RETURN (-1);
+# elif defined (ACE_WIN32)
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL
+ (::CreatePipe (&fds[0], &fds[1], 0, 0),
+ ace_result_), int, -1);
+# else
+ ACE_OSCALL_RETURN (::pipe (fds), int, -1);
+# endif /* ACE_LACKS_PIPE */
+}
+
+ACE_INLINE void *
+ACE_OS::sbrk (intptr_t brk)
+{
+#if defined (ACE_LACKS_SBRK)
+ ACE_UNUSED_ARG (brk);
+ ACE_NOTSUP_RETURN (0);
+#else
+ ACE_OSCALL_RETURN (::sbrk (brk), void *, 0);
+#endif /* ACE_LACKS_SBRK */
+}
+
+ACE_INLINE int
+ACE_OS::setgid (gid_t gid)
+{
+ ACE_OS_TRACE ("ACE_OS::setgid");
+#if defined (ACE_LACKS_SETGID)
+ ACE_UNUSED_ARG (gid);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ ACE_OSCALL_RETURN (::setgid (gid), int, -1);
+# endif /* ACE_LACKS_SETGID */
+}
+
+ACE_INLINE int
+ACE_OS::setegid (gid_t gid)
+{
+ ACE_OS_TRACE ("ACE_OS::setegid");
+#if defined (ACE_LACKS_SETEGID)
+ ACE_UNUSED_ARG (gid);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ ACE_OSCALL_RETURN (::setegid (gid), int, -1);
+# endif /* ACE_LACKS_SETEGID */
+}
+
+ACE_INLINE int
+ACE_OS::setpgid (pid_t pid, pid_t pgid)
+{
+ ACE_OS_TRACE ("ACE_OS::setpgid");
+#if defined (ACE_LACKS_SETPGID)
+ ACE_UNUSED_ARG (pid);
+ ACE_UNUSED_ARG (pgid);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::setpgid (pid, pgid), int, -1);
+#endif /* ACE_LACKS_SETPGID */
+}
+
+ACE_INLINE int
+ACE_OS::setregid (gid_t rgid, gid_t egid)
+{
+ ACE_OS_TRACE ("ACE_OS::setregid");
+#if defined (ACE_LACKS_SETREGID)
+ ACE_UNUSED_ARG (rgid);
+ ACE_UNUSED_ARG (egid);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::setregid (rgid, egid), int, -1);
+#endif /* ACE_LACKS_SETREGID */
+}
+
+ACE_INLINE int
+ACE_OS::setreuid (uid_t ruid, uid_t euid)
+{
+ ACE_OS_TRACE ("ACE_OS::setreuid");
+#if defined (ACE_LACKS_SETREUID)
+ ACE_UNUSED_ARG (ruid);
+ ACE_UNUSED_ARG (euid);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::setreuid (ruid, euid), int, -1);
+#endif /* ACE_LACKS_SETREUID */
+}
+
+ACE_INLINE pid_t
+ACE_OS::setsid (void)
+{
+ ACE_OS_TRACE ("ACE_OS::setsid");
+#if defined (ACE_LACKS_SETSID)
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::setsid (), int, -1);
+# endif /* ACE_LACKS_SETSID */
+}
+
+ACE_INLINE int
+ACE_OS::setuid (uid_t uid)
+{
+ ACE_OS_TRACE ("ACE_OS::setuid");
+#if defined (ACE_LACKS_SETUID)
+ ACE_UNUSED_ARG (uid);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ ACE_OSCALL_RETURN (::setuid (uid), int, -1);
+# endif /* ACE_LACKS_SETUID */
+}
+
+ACE_INLINE int
+ACE_OS::seteuid (uid_t uid)
+{
+ ACE_OS_TRACE ("ACE_OS::seteuid");
+#if defined (ACE_LACKS_SETEUID)
+ ACE_UNUSED_ARG (uid);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ ACE_OSCALL_RETURN (::seteuid (uid), int, -1);
+# endif /* ACE_LACKS_SETEUID */
+}
+
+ACE_INLINE int
+ACE_OS::sleep (u_int seconds)
+{
+ ACE_OS_TRACE ("ACE_OS::sleep");
+#if defined (ACE_WIN32)
+ ::Sleep (seconds * ACE_ONE_SECOND_IN_MSECS);
+ return 0;
+#elif defined (ACE_HAS_CLOCK_GETTIME)
+ struct timespec rqtp;
+ // Initializer doesn't work with Green Hills 1.8.7
+ rqtp.tv_sec = seconds;
+ rqtp.tv_nsec = 0L;
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (::nanosleep (&rqtp, 0), int, -1);
+ //FUZZ: enable check_for_lack_ACE_OS
+#else
+ ACE_OSCALL_RETURN (::sleep (seconds), int, -1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_OS::sleep (const ACE_Time_Value &tv)
+{
+ ACE_OS_TRACE ("ACE_OS::sleep");
+#if defined (ACE_WIN32)
+ ::Sleep (tv.msec ());
+ return 0;
+#elif defined (ACE_HAS_CLOCK_GETTIME)
+ timespec_t rqtp = tv;
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (::nanosleep (&rqtp, 0), int, -1);
+ //FUZZ: enable check_for_lack_ACE_OS
+#else
+# if defined (ACE_HAS_NONCONST_SELECT_TIMEVAL)
+ // Copy the timeval, because this platform doesn't declare the timeval
+ // as a pointer to const.
+ timeval tv_copy = tv;
+# if defined(ACE_TANDEM_T1248_PTHREADS)
+ ACE_OSCALL_RETURN (::spt_select (0, 0, 0, 0, &tv_copy), int, -1);
+# else
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (::select (0, 0, 0, 0, &tv_copy), int, -1);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif
+# else /* ! ACE_HAS_NONCONST_SELECT_TIMEVAL */
+ const timeval *tvp = tv;
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_OSCALL_RETURN (::select (0, 0, 0, 0, tvp), int, -1);
+ //FUZZ: enable check_for_lack_ACE_OS
+# endif /* ACE_HAS_NONCONST_SELECT_TIMEVAL */
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE void
+ACE_OS::swab (const void *src,
+ void *dest,
+ ssize_t length)
+{
+#if defined (ACE_LACKS_SWAB)
+ // ------------------------------------------------------------
+ // The following copyright notice applies to the swab()
+ // implementation within this "ACE_LACKS_SWAB" block of code.
+ // ------------------------------------------------------------
+ /*
+ Copyright (c) 1994-2006 Red Hat, Inc. All rights reserved.
+
+ This copyrighted material is made available to anyone wishing to
+ use, modify, copy, or redistribute it subject to the terms and
+ conditions of the BSD License. This program is distributed in
+ the hope that it will be useful, but WITHOUT ANY WARRANTY
+ expressed or implied, including the implied warranties of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. A copy of
+ this license is available at
+ http://www.opensource.org/licenses. Any Red Hat trademarks that
+ are incorporated in the source code or documentation are not
+ subject to the BSD License and may only be used or replicated with
+ the express permission of Red Hat, Inc.
+ */
+
+ const char *from = static_cast<const char*> (src);
+ char *to = static_cast<char *> (dest);
+ ssize_t ptr = 0;
+ for (ptr = 1; ptr < length; ptr += 2)
+ {
+ char p = from[ptr];
+ char q = from[ptr-1];
+ to[ptr-1] = p;
+ to[ptr ] = q;
+ }
+ if (ptr == length) /* I.e., if length is odd, */
+ to[ptr-1] = 0; /* then pad with a NUL. */
+#elif defined (ACE_HAS_NONCONST_SWAB)
+ const char *tmp = static_cast<const char*> (src);
+ char *from = const_cast<char *> (tmp);
+ char *to = static_cast<char *> (dest);
+ ::swab (from, to, length);
+#elif defined (ACE_HAS_CONST_CHAR_SWAB)
+ const char *from = static_cast<const char*> (src);
+ char *to = static_cast<char *> (dest);
+ ::swab (from, to, length);
+#else
+ ::swab (src, dest, length);
+#endif /* ACE_LACKS_SWAB */
+
+}
+
+ACE_INLINE long
+ACE_OS::sysconf (int name)
+{
+ ACE_OS_TRACE ("ACE_OS::sysconf");
+#if defined (ACE_LACKS_SYSCONF)
+ ACE_UNUSED_ARG (name);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ ACE_OSCALL_RETURN (::sysconf (name), long, -1);
+#endif /* ACE_LACKS_SYSCONF */
+}
+
+ACE_INLINE long
+ACE_OS::sysinfo (int cmd, char *buf, long count)
+{
+ ACE_OS_TRACE ("ACE_OS::sysinfo");
+#if defined (ACE_HAS_SYSINFO)
+ ACE_OSCALL_RETURN (::sysinfo (cmd, buf, count), long, -1);
+#else
+ ACE_UNUSED_ARG (cmd);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (count);
+
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_SYSINFO */
+}
+
+ACE_INLINE int
+ACE_OS::truncate (const ACE_TCHAR *filename,
+ ACE_OFF_T offset)
+{
+ ACE_OS_TRACE ("ACE_OS::truncate");
+#if defined (ACE_WIN32)
+ ACE_HANDLE handle = ACE_OS::open (filename,
+ O_WRONLY,
+ ACE_DEFAULT_FILE_PERMS);
+
+# if !defined (ACE_LACKS_WIN32_SETFILEPOINTEREX)
+ LARGE_INTEGER loffset;
+ loffset.QuadPart = offset;
+#else
+ LONG low_offset = ACE_LOW_PART(offset);
+ LONG high_offset = ACE_HIGH_PART(offset);
+#endif
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_FAIL_RETURN (-1);
+
+# if !defined (ACE_LACKS_WIN32_SETFILEPOINTEREX)
+ else if (::SetFilePointerEx (handle,
+ loffset,
+ 0,
+ FILE_BEGIN))
+# else
+ else if (::SetFilePointer (handle,
+ low_offset,
+ &high_offset,
+ FILE_BEGIN) != INVALID_SET_FILE_POINTER
+ || GetLastError () == NO_ERROR)
+# endif /* ACE_LACKS_WIN32_SETFILEPOINTEREX */
+ {
+ BOOL result = ::SetEndOfFile (handle);
+ ::CloseHandle (handle);
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (result, ace_result_), int, -1);
+ }
+ else
+ {
+ ::CloseHandle (handle);
+ ACE_FAIL_RETURN (-1);
+ }
+ /* NOTREACHED */
+#elif !defined (ACE_LACKS_TRUNCATE)
+ ACE_OSCALL_RETURN
+ (::truncate (ACE_TEXT_ALWAYS_CHAR (filename), offset), int, -1);
+#else
+ ACE_UNUSED_ARG (filename);
+ ACE_UNUSED_ARG (offset);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE useconds_t
+ACE_OS::ualarm (useconds_t usecs, useconds_t interval)
+{
+ ACE_OS_TRACE ("ACE_OS::ualarm");
+
+#if defined (ACE_HAS_UALARM)
+ return ::ualarm (usecs, interval);
+#elif !defined (ACE_LACKS_UNIX_SIGNALS)
+ ACE_UNUSED_ARG (interval);
+ return ::alarm (usecs * ACE_ONE_SECOND_IN_USECS);
+#else
+ ACE_UNUSED_ARG (usecs);
+ ACE_UNUSED_ARG (interval);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_UALARM */
+}
+
+ACE_INLINE useconds_t
+ACE_OS::ualarm (const ACE_Time_Value &tv,
+ const ACE_Time_Value &tv_interval)
+{
+ ACE_OS_TRACE ("ACE_OS::ualarm");
+
+#if defined (ACE_HAS_UALARM)
+ useconds_t usecs = (tv.sec () * ACE_ONE_SECOND_IN_USECS) + tv.usec ();
+ useconds_t interval =
+ (tv_interval.sec () * ACE_ONE_SECOND_IN_USECS) + tv_interval.usec ();
+ return ::ualarm (usecs, interval);
+#elif !defined (ACE_LACKS_UNIX_SIGNALS)
+ ACE_UNUSED_ARG (tv_interval);
+ return ::alarm (tv.sec ());
+#else
+ ACE_UNUSED_ARG (tv_interval);
+ ACE_UNUSED_ARG (tv);
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_UALARM */
+}
+
+ACE_INLINE int
+ACE_OS::unlink (const char *path)
+{
+ ACE_OS_TRACE ("ACE_OS::unlink");
+# if defined (ACE_HAS_NONCONST_UNLINK)
+ ACE_OSCALL_RETURN (::unlink (const_cast<char *> (path)), int, -1);
+# elif defined (ACE_HAS_WINCE)
+ // @@ The problem is, DeleteFile is not actually equals to unlink. ;(
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::DeleteFile (ACE_TEXT_CHAR_TO_TCHAR (path)), ace_result_),
+ int, -1);
+# elif defined (ACE_LACKS_UNLINK)
+ ACE_UNUSED_ARG (path);
+ ACE_NOTSUP_RETURN (-1);
+# else
+ ACE_OSCALL_RETURN (::unlink (path), int, -1);
+# endif /* ACE_HAS_NONCONST_UNLINK */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_OS::unlink (const wchar_t *path)
+{
+ ACE_OS_TRACE ("ACE_OS::unlink");
+# if defined (ACE_HAS_WINCE)
+ // @@ The problem is, DeleteFile is not actually equals to unlink. ;(
+ ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::DeleteFileW (path), ace_result_),
+ int, -1);
+# elif defined (ACE_WIN32)
+ ACE_OSCALL_RETURN (::_wunlink (path), int, -1);
+# else
+ ACE_Wide_To_Ascii npath (path);
+ return ACE_OS::unlink (npath.char_rep ());
+# endif /* ACE_HAS_WINCE */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE ssize_t
+ACE_OS::write (ACE_HANDLE handle, const void *buf, size_t nbyte)
+{
+ ACE_OS_TRACE ("ACE_OS::write");
+#if defined (ACE_WIN32)
+ DWORD bytes_written; // This is set to 0 byte WriteFile.
+
+ // Strictly correctly, we should loop writing all the data if more
+ // than a DWORD length can hold.
+ DWORD short_nbyte = static_cast<DWORD> (nbyte);
+ if (::WriteFile (handle, buf, short_nbyte, &bytes_written, 0))
+ return (ssize_t) bytes_written;
+ else
+ ACE_FAIL_RETURN (-1);
+#else
+# if defined (ACE_HAS_CHARPTR_SOCKOPT)
+ ACE_OSCALL_RETURN (::write (handle, static_cast <char *> (const_cast <void *> (buf)), nbyte), ssize_t, -1);
+# else
+ ACE_OSCALL_RETURN (::write (handle, buf, nbyte), ssize_t, -1);
+# endif /* ACE_HAS_CHARPTR_SOCKOPT */
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_OS::write (ACE_HANDLE handle,
+ const void *buf,
+ size_t nbyte,
+ ACE_OVERLAPPED *overlapped)
+{
+ ACE_OS_TRACE ("ACE_OS::write");
+ overlapped = overlapped;
+#if defined (ACE_WIN32)
+ DWORD bytes_written; // This is set to 0 byte WriteFile.
+
+ DWORD short_nbyte = static_cast<DWORD> (nbyte);
+ if (::WriteFile (handle, buf, short_nbyte, &bytes_written, overlapped))
+ return (ssize_t) bytes_written;
+ else
+ ACE_FAIL_RETURN (-1);
+#else
+ return ACE_OS::write (handle, buf, nbyte);
+#endif /* ACE_WIN32 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_wchar.cpp b/ACE/ace/OS_NS_wchar.cpp
new file mode 100644
index 00000000000..194e4a9a1da
--- /dev/null
+++ b/ACE/ace/OS_NS_wchar.cpp
@@ -0,0 +1,377 @@
+// $Id$
+
+#include "ace/OS_NS_wchar.h"
+
+ACE_RCSID(ace, OS_NS_wchar, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_NS_wchar.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+#if defined (ACE_HAS_WCHAR)
+# include "ace/OS_NS_ctype.h"
+# include "ace/OS_NS_string.h"
+#endif /* ACE_HAS_WCHAR */
+
+// The following wcs*_emulation methods were created based on BSD code:
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCAT)
+wchar_t *
+ACE_OS::wcscat_emulation (wchar_t *destination,
+ const wchar_t *source)
+{
+ wchar_t *save = destination;
+
+ for (; *destination; ++destination);
+ while ((*destination++ = *source++));
+ return save;
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCAT */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCHR)
+wchar_t *
+ACE_OS::wcschr_emulation (const wchar_t *string, wchar_t c)
+{
+ for (;*string ; ++string)
+ if (*string == c)
+ return const_cast<wchar_t *> (string);
+
+ return 0;
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCHR */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSCMP)
+int
+ACE_OS::wcscmp_emulation (const ACE_WCHAR_T *string1,
+ const ACE_WCHAR_T *string2)
+{
+ while (*string1 == *string2++)
+ if (*string1++ == 0)
+ return (0);
+ return (*string1 - *--string2);
+}
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCMP */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCPY)
+wchar_t *
+ACE_OS::wcscpy_emulation (wchar_t *destination,
+ const wchar_t *source)
+{
+ wchar_t *save = destination;
+
+ for (; (*destination = *source); ++source, ++destination);
+ return save;
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCPY */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCSPN)
+size_t
+ACE_OS::wcscspn_emulation (const wchar_t *s, const wchar_t *reject)
+{
+ const wchar_t *scan = 0;
+ const wchar_t *rej_scan = 0;
+ int count = 0;
+
+ for (scan = s; *scan; scan++)
+ {
+
+ for (rej_scan = reject; *rej_scan; rej_scan++)
+ if (*scan == *rej_scan)
+ return count;
+
+ count++;
+ }
+
+ return count;
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCSPN */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSICMP)
+int
+ACE_OS::wcsicmp_emulation (const wchar_t *s, const wchar_t *t)
+{
+ const wchar_t *scan1 = s;
+ const wchar_t *scan2 = t;
+
+ while (*scan1 != 0
+ && ACE_OS::ace_towlower (*scan1)
+ == ACE_OS::ace_towlower (*scan2))
+ {
+ ++scan1;
+ ++scan2;
+ }
+
+ // The following case analysis is necessary so that characters which
+ // look negative collate low against normal characters but high
+ // against the end-of-string NUL.
+
+ if (*scan1 == '\0' && *scan2 == '\0')
+ return 0;
+ else if (*scan1 == '\0')
+ return -1;
+ else if (*scan2 == '\0')
+ return 1;
+ else
+ return ACE_OS::ace_tolower (*scan1) - ACE_OS::ace_towlower (*scan2);
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSICMP */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSLEN)
+size_t
+ACE_OS::wcslen_emulation (const ACE_WCHAR_T *string)
+{
+ const ACE_WCHAR_T *s;
+
+ for (s = string; *s; ++s)
+ continue;
+
+ return s - string;
+}
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSLEN */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCAT)
+ACE_WCHAR_T *
+ACE_OS::wcsncat_emulation (ACE_WCHAR_T *destination,
+ const ACE_WCHAR_T *source,
+ size_t count)
+{
+ if (count != 0)
+ {
+ ACE_WCHAR_T *d = destination;
+ const ACE_WCHAR_T *s = source;
+
+ while (*d != 0)
+ d++;
+
+ do
+ {
+ if ((*d = *s++) == 0)
+ break;
+
+ d++;
+ } while (--count != 0);
+
+ *d = 0;
+ }
+
+ return destination;
+}
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCAT */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCMP)
+int
+ACE_OS::wcsncmp_emulation (const ACE_WCHAR_T *s1,
+ const ACE_WCHAR_T *s2,
+ size_t len)
+{
+ if (len == 0)
+ return 0;
+
+ do
+ {
+ if (*s1 != *s2++)
+ return (*s1 - *--s2);
+ if (*s1++ == 0)
+ break;
+ } while (--len != 0);
+
+ return 0;
+}
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCMP */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCPY)
+ACE_WCHAR_T *
+ACE_OS::wcsncpy_emulation (ACE_WCHAR_T *destination,
+ const ACE_WCHAR_T *source,
+ size_t len)
+{
+ if (len != 0)
+ {
+ ACE_WCHAR_T *d = destination;
+ const ACE_WCHAR_T *s = source;
+
+ do
+ {
+ if ((*d++ = *s++) == 0)
+ {
+ // NUL pad the remaining n-1 bytes
+ while (--len != 0)
+ *d++ = 0;
+ break;
+ }
+ } while (--len != 0);
+ }
+
+ return destination;
+}
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCPY */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSNICMP)
+int
+ACE_OS::wcsnicmp_emulation (const wchar_t *s,
+ const wchar_t *t,
+ size_t len)
+{
+ const wchar_t *scan1 = s;
+ const wchar_t *scan2 = t;
+ size_t count = 0;
+
+ while (count++ < len
+ && *scan1 != 0
+ && ACE_OS::ace_towlower (*scan1)
+ == ACE_OS::ace_towlower (*scan2))
+ {
+ ++scan1;
+ ++scan2;
+ }
+
+ if (count > len)
+ return 0;
+
+ // The following case analysis is necessary so that characters which
+ // look negative collate low against normal characters but high
+ // against the end-of-string NUL.
+
+ if (*scan1 == '\0' && *scan2 == '\0')
+ return 0;
+ else if (*scan1 == '\0')
+ return -1;
+ else if (*scan2 == '\0')
+ return 1;
+ else
+ return ACE_OS::ace_towlower (*scan1) - ACE_OS::ace_towlower (*scan2);
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSNICMP */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSPBRK)
+wchar_t *
+ACE_OS::wcspbrk_emulation (const wchar_t *string,
+ const wchar_t *charset)
+{
+ const wchar_t *scanp;
+ int c, sc;
+
+ while ((c = *string++) != 0)
+ {
+ for (scanp = charset; (sc = *scanp++) != 0;)
+ if (sc == c)
+ return const_cast<wchar_t *> (string - 1);
+ }
+
+ return 0;
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSPBRK */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSRCHR)
+const wchar_t *
+ACE_OS::wcsrchr_emulation (const wchar_t *s, wint_t c)
+{
+ const wchar_t *p = s + ACE_OS::strlen (s);
+
+ while (*p != static_cast<wchar_t> (c))
+ if (p == s)
+ return 0;
+ else
+ p--;
+
+ return p;
+}
+
+wchar_t *
+ACE_OS::wcsrchr_emulation (wchar_t *s, wint_t c)
+{
+ wchar_t *p = s + ACE_OS::strlen (s);
+
+ while (*p != static_cast<wchar_t> (c))
+ if (p == s)
+ return 0;
+ else
+ p--;
+
+ return p;
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSRCHR */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSSPN)
+size_t
+ACE_OS::wcsspn_emulation (const wchar_t *string,
+ const wchar_t *charset)
+{
+ const wchar_t *p = string;
+ const wchar_t *spanp;
+ wchar_t c, sc;
+
+ // Skip any characters in charset, excluding the terminating \0.
+cont:
+ c = *p++;
+ for (spanp = charset; (sc = *spanp++) != 0;)
+ if (sc == c)
+ goto cont;
+ return (p - 1 - string);
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSSPN */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSSTR)
+wchar_t *
+ACE_OS::wcsstr_emulation (const wchar_t *string,
+ const wchar_t *charset)
+{
+ wchar_t c, sc;
+ size_t len;
+
+ if ((c = *charset++) != 0)
+ {
+ len = ACE_OS::strlen (charset);
+ do
+ {
+ do
+ {
+ if ((sc = *string++) == 0)
+ return 0;
+ } while (sc != c);
+ } while (ACE_OS::strncmp (string, charset, len) != 0);
+ string--;
+ }
+
+ return const_cast<wchar_t *> (string);
+}
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSSTR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_NS_wchar.h b/ACE/ace/OS_NS_wchar.h
new file mode 100644
index 00000000000..9cfa3b4bb65
--- /dev/null
+++ b/ACE/ace/OS_NS_wchar.h
@@ -0,0 +1,199 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_NS_wchar.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_WCHAR_H
+# define ACE_OS_NS_WCHAR_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/os_include/os_wchar.h"
+#include "ace/Basic_Types.h"
+#include /**/ "ace/ACE_export.h"
+#include "ace/ace_wchar.h" // include for the time being, but this code needs to be moved. dhinton
+
+#include "ace/os_include/os_errno.h"
+
+#if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+#endif
+#define ACE_EXPORT_MACRO ACE_Export
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS
+{
+
+ typedef ACE_WCHAR_T WChar;
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wint_t fgetwc (FILE* fp);
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCAT)
+ /// Emulated wcscat - Appends a string.
+ extern ACE_Export
+ wchar_t *wcscat_emulation (wchar_t *destination,
+ const wchar_t *source);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCAT */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCHR)
+ /// Emulated wcschr - Finds a character in a string.
+ extern ACE_Export
+ wchar_t *wcschr_emulation (const wchar_t *string, wchar_t c);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCHR */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSCMP)
+ /// Emulated wcscmp - Compares strings.
+ extern ACE_Export
+ int wcscmp_emulation (const ACE_WCHAR_T *string1, const ACE_WCHAR_T *string2);
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCMP */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCPY)
+ /// Emulated wcscpy - Copies a string.
+ extern ACE_Export
+ wchar_t *wcscpy_emulation (wchar_t *destination,
+ const wchar_t *source);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCPY */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCSPN)
+ /// Emulated wcscspn.
+ extern ACE_Export
+ size_t wcscspn_emulation (const wchar_t *string,
+ const wchar_t *reject);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCSPN */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSICMP)
+ /// Emulated wcsicmp - Performs a case insensitive comparison of strings.
+ extern ACE_Export
+ int wcsicmp_emulation (const wchar_t *string1,
+ const wchar_t *string2);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSICMP */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSLEN)
+ /// Emulated wcslen - Returns the length of a string.
+ extern ACE_Export
+ size_t wcslen_emulation (const ACE_WCHAR_T *string);
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSLEN */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCAT)
+ /// Emulated wcscat - Appends a string.
+ extern ACE_Export
+ ACE_WCHAR_T *wcsncat_emulation (ACE_WCHAR_T *destination,
+ const ACE_WCHAR_T *source,
+ size_t count);
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCAT */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCMP)
+ /// Emulated wcsncmp - Compares two arrays.
+ extern ACE_Export
+ int wcsncmp_emulation (const ACE_WCHAR_T *string1,
+ const ACE_WCHAR_T *string2,
+ size_t len);
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCMP */
+
+#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCPY)
+ /// Emulated wcsncpy - Copies an array.
+ extern ACE_Export
+ ACE_WCHAR_T *wcsncpy_emulation (ACE_WCHAR_T *destination,
+ const ACE_WCHAR_T *source,
+ size_t len);
+#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCPY */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSNICMP)
+ /// Emulated wcsnicmp - Performs a case insensitive comparison of two
+ /// arrays
+ extern ACE_Export
+ int wcsnicmp_emulation (const wchar_t *string1,
+ const wchar_t *string2,
+ size_t len);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSNICMP */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSPBRK)
+ /// Emulated wcspbrk - Searches for characters in a string.
+ extern ACE_Export
+ wchar_t *wcspbrk_emulation (const wchar_t *string,
+ const wchar_t *charset);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSPBRK */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSRCHR)
+ /// Emulated wcsrchr (wchar_t version) - Finds the last occurance of a
+ /// character in a string.
+ extern ACE_Export
+ wchar_t *wcsrchr_emulation (wchar_t *string, wint_t c);
+
+ /// Emulated wcsrchr (const wchar_t version) - Finds the last occurance of a
+ /// character in a string.
+ extern ACE_Export
+ const wchar_t *wcsrchr_emulation (const wchar_t *string, wint_t c);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSRCHR */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSSPN)
+ /// Emulated wcsspn.
+ extern ACE_Export
+ size_t wcsspn_emulation (const wchar_t *string,
+ const wchar_t *charset);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSSPN */
+
+#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSSTR)
+ /// Emulated wcsstr - Performs a case insensitive comparison of two strings.
+ extern ACE_Export
+ wchar_t *wcsstr_emulation (const wchar_t *string,
+ const wchar_t *charset);
+#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSSTR */
+
+ // these are named wrong. should be wcslen, etc... dhinton
+ ACE_NAMESPACE_INLINE_FUNCTION
+ u_int wslen (const WChar *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ WChar *wscpy (WChar *,
+ const WChar *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int wscmp (const WChar *,
+ const WChar *);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int wsncmp (const WChar *,
+ const WChar *,
+ size_t len);
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_NAMESPACE_INLINE_FUNCTION
+ wint_t ungetwc (wint_t c, FILE* fp);
+#endif /* ACE_HAS_WCHAR */
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_wchar.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_STDIO_H */
diff --git a/ACE/ace/OS_NS_wchar.inl b/ACE/ace/OS_NS_wchar.inl
new file mode 100644
index 00000000000..7f2abac8d8f
--- /dev/null
+++ b/ACE/ace/OS_NS_wchar.inl
@@ -0,0 +1,87 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wint_t
+ACE_OS::fgetwc (FILE* fp)
+{
+# if defined (ACE_LACKS_FGETWC)
+ ACE_UNUSED_ARG (fp);
+ ACE_NOTSUP_RETURN (0);
+# else
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::fgetwc (fp), wint_t, WEOF);
+# endif /* ACE_LACKS_FGETWC */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE u_int
+ACE_OS::wslen (const WChar *s)
+{
+ u_int len = 0;
+
+ while (*s++ != 0)
+ len++;
+
+ return len;
+}
+
+ACE_INLINE ACE_OS::WChar *
+ACE_OS::wscpy (WChar *dest, const WChar *src)
+{
+ WChar *original_dest = dest;
+
+ while ((*dest++ = *src++) != 0)
+ continue;
+
+ return original_dest;
+}
+
+ACE_INLINE int
+ACE_OS::wscmp (const WChar *s, const WChar *t)
+{
+ const WChar *scan1 = s;
+ const WChar *scan2 = t;
+
+ while (*scan1 != 0 && *scan1 == *scan2)
+ {
+ ++scan1;
+ ++scan2;
+ }
+
+ return *scan1 - *scan2;
+}
+
+ACE_INLINE int
+ACE_OS::wsncmp (const WChar *s, const WChar *t, size_t len)
+{
+ const WChar *scan1 = s;
+ const WChar *scan2 = t;
+
+ while (len != 0 && *scan1 != 0 && *scan1 == *scan2)
+ {
+ ++scan1;
+ ++scan2;
+ --len;
+ }
+
+ return len == 0 ? 0 : *scan1 - *scan2;
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE wint_t
+ACE_OS::ungetwc (wint_t c, FILE* fp)
+{
+# if defined (ACE_LACKS_FGETWC)
+ ACE_UNUSED_ARG (c);
+ ACE_UNUSED_ARG (fp);
+ ACE_NOTSUP_RETURN (0);
+# else
+ ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::ungetwc (c, fp), wint_t, WEOF);
+# endif /* ACE_LACKS_FGETWC */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_QoS.cpp b/ACE/ace/OS_QoS.cpp
new file mode 100644
index 00000000000..0b2c23f11c6
--- /dev/null
+++ b/ACE/ace/OS_QoS.cpp
@@ -0,0 +1,476 @@
+//=============================================================================
+///**
+// * @file OS_QoS.cpp
+// *
+// * $Id$
+// *
+// * @brief Contains OS specific data structures for QoS networking.
+// *
+// * @author Craig Rodrigues <crodrigu@bbn.com>
+// */
+//=============================================================================
+
+#include "ace/OS_QoS.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Flow_Spec::ACE_Flow_Spec (unsigned long token_rate,
+ unsigned long token_bucket_size,
+ unsigned long peak_bandwidth,
+ unsigned long latency,
+ unsigned long delay_variation,
+ ACE_SERVICE_TYPE service_type,
+ unsigned long max_sdu_size,
+ unsigned long minimum_policed_size,
+ int ttl,
+ int priority)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->TokenRate = token_rate;
+ this->TokenBucketSize = token_bucket_size;
+ this->PeakBandwidth = peak_bandwidth;
+ this->Latency = latency;
+ this->DelayVariation = delay_variation;
+#if defined(ACE_HAS_WINSOCK2_GQOS)
+ this->ServiceType = service_type;
+ this->MaxSduSize = max_sdu_size;
+ this->MinimumPolicedSize = minimum_policed_size;
+#else
+ ACE_UNUSED_ARG (service_type);
+ ACE_UNUSED_ARG (max_sdu_size);
+ ACE_UNUSED_ARG (minimum_policed_size);
+#endif /* ACE_HAS_WINSOCK2_GQOS */
+ ACE_UNUSED_ARG (ttl);
+ ACE_UNUSED_ARG (priority);
+#else
+
+ this->token_rate_ = token_rate;
+ this->token_bucket_size_ = token_bucket_size;
+ this->peak_bandwidth_ = peak_bandwidth;
+ this->latency_ = latency;
+ this->delay_variation_ = delay_variation;
+ this->service_type_ = service_type;
+ this->max_sdu_size_ = max_sdu_size;
+ this->minimum_policed_size_ = minimum_policed_size;
+ this->ttl_ = ttl;
+ this->priority_ = priority;
+
+#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
+}
+
+ACE_Flow_Spec::ACE_Flow_Spec (void)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ this->TokenRate = 0;
+ this->TokenBucketSize = 0;
+ this->PeakBandwidth = 0;
+ this->Latency = 0;
+ this->DelayVariation = 0;
+#if defined(ACE_HAS_WINSOCK2_GQOS)
+ this->ServiceType = 0;
+ this->MaxSduSize = 0;
+ this->MinimumPolicedSize = 0;
+#endif /* ACE_HAS_WINSOCK2_GQOS */
+#else
+
+ this->token_rate_ = 0;
+ this->token_bucket_size_ = 0;
+ this->peak_bandwidth_ = 0;
+ this->latency_ = 0;
+ this->delay_variation_ = 0;
+ this->service_type_ = 0;
+ this->max_sdu_size_ = 0;
+ this->minimum_policed_size_ = 0;
+ this->ttl_ = 0;
+ this->priority_ = 0;
+
+#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
+}
+
+unsigned long
+ACE_Flow_Spec::token_rate (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ return this->TokenRate;
+#else
+ return this->token_rate_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::token_rate (unsigned long tr)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->TokenRate = tr;
+#else
+ this->token_rate_ = tr;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+unsigned long
+ACE_Flow_Spec::token_bucket_size (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ return this->TokenBucketSize;
+#else
+ return this->token_bucket_size_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::token_bucket_size (unsigned long tbs)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->TokenBucketSize = tbs;
+#else
+ this->token_bucket_size_ = tbs;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+unsigned long
+ACE_Flow_Spec::peak_bandwidth (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ return this->PeakBandwidth;
+#else
+ return this->peak_bandwidth_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::peak_bandwidth (unsigned long pb)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->PeakBandwidth = pb;
+#else
+ this->peak_bandwidth_ = pb;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+unsigned long
+ACE_Flow_Spec::latency (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ return this->Latency;
+#else
+ return this->latency_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::latency (unsigned long l)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->Latency = l;
+#else
+ this->latency_ = l;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+unsigned long
+ACE_Flow_Spec::delay_variation (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ return this->DelayVariation;
+#else
+ return this->delay_variation_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+void
+ACE_Flow_Spec::delay_variation (unsigned long dv)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->DelayVariation = dv;
+#else
+ this->delay_variation_ = dv;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_SERVICE_TYPE
+ACE_Flow_Spec::service_type (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ return this->ServiceType;
+#else
+ return this->service_type_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::service_type (ACE_SERVICE_TYPE st)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ this->ServiceType = st;
+#else
+ this->service_type_ = st;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+unsigned long
+ACE_Flow_Spec::max_sdu_size (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ return this->MaxSduSize;
+#else
+ return this->max_sdu_size_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::max_sdu_size (unsigned long mss)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ this->MaxSduSize = mss;
+#else
+ this->max_sdu_size_ = mss;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+unsigned long
+ACE_Flow_Spec::minimum_policed_size (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ return this->MinimumPolicedSize;
+#else
+ return this->minimum_policed_size_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::minimum_policed_size (unsigned long mps)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ this->MinimumPolicedSize = mps;
+#else
+ this->minimum_policed_size_ = mps;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+int
+ACE_Flow_Spec::ttl (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ ACE_NOTSUP_RETURN (-1);
+#else
+ return this->ttl_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::ttl (int t)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ ACE_UNUSED_ARG (t);
+ // TBD...
+#else
+ this->ttl_ = t;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+int
+ACE_Flow_Spec::priority (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ ACE_NOTSUP_RETURN (-1);
+#else
+ return this->priority_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_Flow_Spec::priority (int p)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+ ACE_UNUSED_ARG (p);
+ // TBD...
+#else
+ this->priority_ = p;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_QoS::ACE_QoS (void)
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+#else
+ : sending_flowspec_ (0),
+ receiving_flowspec_ (0)
+#endif /* ACE_HAS_WINSOCK2 */
+{
+}
+
+ACE_Flow_Spec*
+ACE_QoS::sending_flowspec (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ return &((ACE_Flow_Spec &) this->SendingFlowspec);
+#else
+ return this->sending_flowspec_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_QoS::sending_flowspec (ACE_Flow_Spec *fs)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->SendingFlowspec = (FLOWSPEC) (*fs);
+#else
+ this->sending_flowspec_ = fs;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_Flow_Spec*
+ACE_QoS::receiving_flowspec (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ return &((ACE_Flow_Spec &) this->ReceivingFlowspec);
+#else
+ return receiving_flowspec_;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_QoS::receiving_flowspec (ACE_Flow_Spec *fs)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->ReceivingFlowspec = (FLOWSPEC) (*fs);
+#else
+ this->receiving_flowspec_ = fs;
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+iovec
+ACE_QoS::provider_specific (void) const
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ return (iovec&) this->ProviderSpecific;
+#else
+ ACE_NOTSUP_RETURN (iovec ());
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+void
+ACE_QoS::provider_specific (const iovec &ps)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ this->ProviderSpecific = (WSABUF) ((iovec &) ps);
+#else
+ ACE_UNUSED_ARG (ps);
+#endif /* ACE_HAS_WINSOCK2 */
+}
+
+ACE_QoS_Params::ACE_QoS_Params (iovec *caller_data,
+ iovec *callee_data,
+ ACE_QoS *socket_qos,
+ ACE_QoS *group_socket_qos,
+ unsigned long flags)
+ : caller_data_ (caller_data),
+ callee_data_ (callee_data),
+ socket_qos_ (socket_qos),
+ group_socket_qos_ (group_socket_qos),
+ flags_ (flags)
+{
+}
+
+iovec *
+ACE_QoS_Params::caller_data (void) const
+{
+ return this->caller_data_;
+}
+
+void
+ACE_QoS_Params::caller_data (iovec *cd)
+{
+ this->caller_data_ = cd;
+}
+
+iovec *
+ACE_QoS_Params::callee_data (void) const
+{
+ return this->callee_data_;
+}
+
+void
+ACE_QoS_Params::callee_data (iovec *cd)
+{
+ this->callee_data_ = cd;
+}
+
+ACE_QoS *
+ACE_QoS_Params::socket_qos (void) const
+{
+ return this->socket_qos_;
+}
+
+void
+ACE_QoS_Params::socket_qos (ACE_QoS *sq)
+{
+ this->socket_qos_ = sq;
+}
+
+ACE_QoS *
+ACE_QoS_Params::group_socket_qos (void) const
+{
+ return this->group_socket_qos_;
+}
+
+void
+ACE_QoS_Params::group_socket_qos (ACE_QoS *gsq)
+{
+ this->group_socket_qos_ = gsq;
+}
+
+unsigned long
+ACE_QoS_Params::flags (void) const
+{
+ return this->flags_;
+}
+
+void
+ACE_QoS_Params::flags (unsigned long f)
+{
+ this->flags_ = f;
+}
+
+ACE_Accept_QoS_Params::ACE_Accept_QoS_Params (ACE_QOS_CONDITION_FUNC qos_condition_callback,
+ unsigned long callback_data)
+ : qos_condition_callback_ (qos_condition_callback),
+ callback_data_ (callback_data)
+{
+}
+
+ACE_QOS_CONDITION_FUNC
+ACE_Accept_QoS_Params::qos_condition_callback (void) const
+{
+ return this->qos_condition_callback_;
+}
+
+void
+ACE_Accept_QoS_Params::qos_condition_callback (ACE_QOS_CONDITION_FUNC qcc)
+{
+ this->qos_condition_callback_ = qcc;
+}
+
+unsigned long
+ACE_Accept_QoS_Params::callback_data (void) const
+{
+ return this->callback_data_;
+}
+
+void
+ACE_Accept_QoS_Params::callback_data (unsigned long cd)
+{
+ this->callback_data_ = cd;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_QoS.h b/ACE/ace/OS_QoS.h
new file mode 100644
index 00000000000..bf5060c4419
--- /dev/null
+++ b/ACE/ace/OS_QoS.h
@@ -0,0 +1,449 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_QoS.h
+ *
+ * $Id$
+ *
+ * @brief Contains OS specific data structures for QoS networking.
+ *
+ * @author Craig Rodrigues <crodrigu@bbn.com>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_QOS_H
+#define ACE_OS_QOS_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_uio.h"
+#include "ace/OS_NS_stropts.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && defined (ACE_HAS_WINSOCK2_GQOS)
+typedef SERVICETYPE ACE_SERVICE_TYPE;
+#else
+typedef unsigned long ACE_SERVICE_TYPE;
+#endif /* ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */
+
+#if defined (WSA_FLAG_OVERLAPPED)
+# define ACE_OVERLAPPED_SOCKET_FLAG WSA_FLAG_OVERLAPPED
+#else
+# define ACE_OVERLAPPED_SOCKET_FLAG 0
+#endif
+
+#if defined (XP1_QOS_SUPPORTED)
+# define ACE_XP1_QOS_SUPPORTED XP1_QOS_SUPPORTED
+#else
+# define ACE_XP1_QOS_SUPPORTED 0x00002000
+#endif
+
+#if defined (XP1_SUPPORT_MULTIPOINT)
+# define ACE_XP1_SUPPORT_MULTIPOINT XP1_SUPPORT_MULTIPOINT
+#else
+# define ACE_XP1_SUPPORT_MULTIPOINT 0x00000400
+#endif
+
+#if defined (WSABASEERR)
+# define ACE_BASEERR WSABASEERR
+#else
+# define ACE_BASEERR 10000
+#endif
+
+#if defined (WSAENOBUFS)
+# define ACE_ENOBUFS WSAENOBUFS
+#else
+# define ACE_ENOBUFS (ACE_BASEERR+55)
+#endif
+
+#if defined (FROM_PROTOCOL_INFO)
+# define ACE_FROM_PROTOCOL_INFO FROM_PROTOCOL_INFO
+#else
+# define ACE_FROM_PROTOCOL_INFO (-1)
+#endif
+
+#if defined (WSA_FLAG_MULTIPOINT_C_ROOT)
+# define ACE_FLAG_MULTIPOINT_C_ROOT WSA_FLAG_MULTIPOINT_C_ROOT
+#else
+# define ACE_FLAG_MULTIPOINT_C_ROOT 0x02
+#endif
+
+#if defined (WSA_FLAG_MULTIPOINT_C_LEAF)
+# define ACE_FLAG_MULTIPOINT_C_LEAF WSA_FLAG_MULTIPOINT_C_LEAF
+#else
+# define ACE_FLAG_MULTIPOINT_C_LEAF 0x04
+#endif
+
+#if defined (WSA_FLAG_MULTIPOINT_D_ROOT)
+# define ACE_FLAG_MULTIPOINT_D_ROOT WSA_FLAG_MULTIPOINT_D_ROOT
+#else
+# define ACE_FLAG_MULTIPOINT_D_ROOT 0x08
+#endif
+
+#if defined (WSA_FLAG_MULTIPOINT_D_LEAF)
+# define ACE_FLAG_MULTIPOINT_D_LEAF WSA_FLAG_MULTIPOINT_D_LEAF
+#else
+# define ACE_FLAG_MULTIPOINT_D_LEAF 0x10
+#endif
+
+#if defined (QOS_NOT_SPECIFIED)
+# define ACE_QOS_NOT_SPECIFIED QOS_NOT_SPECIFIED
+#else
+# define ACE_QOS_NOT_SPECIFIED 0xFFFFFFFF
+#endif
+
+#if defined (SERVICETYPE_NOTRAFFIC)
+# define ACE_SERVICETYPE_NOTRAFFIC SERVICETYPE_NOTRAFFIC
+#else
+# define ACE_SERVICETYPE_NOTRAFFIC 0x00000000 /* No data in this */
+ /* direction. */
+#endif
+
+#if defined (SERVICETYPE_CONTROLLEDLOAD)
+# define ACE_SERVICETYPE_CONTROLLEDLOAD SERVICETYPE_CONTROLLEDLOAD
+#else
+# define ACE_SERVICETYPE_CONTROLLEDLOAD 0x00000001 /* Controlled Load. */
+#endif
+
+#if defined (SERVICETYPE_GUARANTEED)
+# define ACE_SERVICETYPE_GUARANTEED SERVICETYPE_GUARANTEED
+#else
+# define ACE_SERVICETYPE_GUARANTEED 0x00000003 /* Guaranteed. */
+#endif
+
+#if defined (JL_SENDER_ONLY)
+# define ACE_JL_SENDER_ONLY JL_SENDER_ONLY
+#else
+# define ACE_JL_SENDER_ONLY 0x01
+#endif
+
+#if defined (JL_BOTH)
+# define ACE_JL_BOTH JL_BOTH
+#else
+# define ACE_JL_BOTH 0x04
+#endif
+
+#if defined (SIO_GET_QOS)
+# define ACE_SIO_GET_QOS SIO_GET_QOS
+#else
+# define ACE_SIO_GET_QOS (0x40000000 | 0x08000000 | 7)
+#endif
+
+#if defined (SIO_MULTIPOINT_LOOPBACK)
+# define ACE_SIO_MULTIPOINT_LOOPBACK SIO_MULTIPOINT_LOOPBACK
+#else
+# define ACE_SIO_MULTIPOINT_LOOPBACK (0x08000000 | 9)
+#endif
+
+#if defined (SIO_MULTICAST_SCOPE)
+# define ACE_SIO_MULTICAST_SCOPE SIO_MULTICAST_SCOPE
+#else
+# define ACE_SIO_MULTICAST_SCOPE (0x08000000 | 10)
+#endif
+
+#if defined (SIO_SET_QOS)
+# define ACE_SIO_SET_QOS SIO_SET_QOS
+#else
+# define ACE_SIO_SET_QOS (0x08000000 | 11)
+#endif
+
+/**
+ * @class ACE_Flow_Spec
+ *
+ * @brief Wrapper class that defines the flow spec QoS information,
+ * which is used by IntServ (RSVP) and DiffServ.
+ */
+class ACE_Export ACE_Flow_Spec
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ : public FLOWSPEC
+#endif /* ACE_HAS_WINSOCK2 */
+{
+public:
+ /// Default constructor.
+ ACE_Flow_Spec (void);
+
+ /// Constructor that initializes all the fields.
+ ACE_Flow_Spec (unsigned long token_rate,
+ unsigned long token_bucket_size,
+ unsigned long peak_bandwidth,
+ unsigned long latency,
+ unsigned long delay_variation,
+ ACE_SERVICE_TYPE service_type,
+ unsigned long max_sdu_size,
+ unsigned long minimum_policed_size,
+ int ttl,
+ int priority);
+
+ /// Get the token rate in bytes/sec.
+ unsigned long token_rate (void) const;
+
+ /// Set the token rate in bytes/sec.
+ void token_rate (unsigned long tr);
+
+ /// Get the token bucket size in bytes.
+ unsigned long token_bucket_size (void) const;
+
+ /// Set the token bucket size in bytes.
+ void token_bucket_size (unsigned long tbs);
+
+ /// Get the PeakBandwidth in bytes/sec.
+ unsigned long peak_bandwidth (void) const;
+
+ /// Set the PeakBandwidth in bytes/sec.
+ void peak_bandwidth (unsigned long pb);
+
+ /// Get the latency in microseconds.
+ unsigned long latency (void) const;
+
+ /// Set the latency in microseconds.
+ void latency (unsigned long l);
+
+ /// Get the delay variation in microseconds.
+ unsigned long delay_variation (void) const;
+
+ /// Set the delay variation in microseconds.
+ void delay_variation (unsigned long dv);
+
+ /// Get the service type.
+ ACE_SERVICE_TYPE service_type (void) const;
+
+ /// Set the service type.
+ void service_type (ACE_SERVICE_TYPE st);
+
+ /// Get the maximum SDU size in bytes.
+ unsigned long max_sdu_size (void) const;
+
+ /// Set the maximum SDU size in bytes.
+ void max_sdu_size (unsigned long mss);
+
+ /// Get the minimum policed size in bytes.
+ unsigned long minimum_policed_size (void) const;
+
+ /// Set the minimum policed size in bytes.
+ void minimum_policed_size (unsigned long mps);
+
+ /// Get the time-to-live.
+ int ttl (void) const;
+
+ /// Set the time-to-live.
+ void ttl (int t);
+
+ /// Get the priority.
+ int priority (void) const;
+
+ /// Set the priority.
+ void priority (int p);
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS)
+#else
+private:
+ unsigned long token_rate_;
+ unsigned long token_bucket_size_;
+ unsigned long peak_bandwidth_;
+ unsigned long latency_;
+ unsigned long delay_variation_;
+ ACE_SERVICE_TYPE service_type_;
+ unsigned long max_sdu_size_;
+ unsigned long minimum_policed_size_;
+ int ttl_;
+ int priority_;
+#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \
+ defined (ACE_HAS_WINSOCK2_GQOS) */
+};
+
+/**
+ * @class ACE_QoS
+ *
+ * @brief Wrapper class that holds the sender and receiver flow spec
+ * information, which is used by IntServ (RSVP) and DiffServ.
+ */
+class ACE_Export ACE_QoS
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ : public QOS
+#endif /* ACE_HAS_WINSOCK2 */
+{
+public:
+ /// Constructor
+ ACE_QoS (void);
+
+ /// Get the flow spec for data sending.
+ ACE_Flow_Spec *sending_flowspec (void) const;
+
+ /// Set the flow spec for data sending.
+ void sending_flowspec (ACE_Flow_Spec *fs);
+
+ /// Get the flow spec for data receiving.
+ ACE_Flow_Spec *receiving_flowspec (void) const;
+
+ /// Set the flow spec for data receiving.
+ void receiving_flowspec (ACE_Flow_Spec *fs);
+
+ /// Get the provider specific information.
+ iovec provider_specific (void) const;
+
+ /// Set the provider specific information.
+ void provider_specific (const iovec &ps);
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+#else
+private:
+
+ ACE_Flow_Spec *sending_flowspec_;
+ ACE_Flow_Spec *receiving_flowspec_;
+#endif
+
+};
+
+/**
+ * @class ACE_QoS_Params
+ *
+ * @brief Wrapper class that simplifies the information passed to the QoS
+ * enabled <ACE_OS::connect> and <ACE_OS::join_leaf> methods.
+ */
+class ACE_Export ACE_QoS_Params
+{
+public:
+ /**
+ * Initialize the data members. The <caller_data> is a pointer to
+ * the user data that is to be transferred to the peer during
+ * connection establishment. The <callee_data> is a pointer to the
+ * user data that is to be transferred back from the peer during
+ * connection establishment. The_<socket_qos> is a pointer to the
+ * flow specifications for the socket, one for each direction. The
+ * <group_socket_qos> is a pointer to the flow speicfications for
+ * the socket group, if applicable. The_@a flags indicate if we're a
+ * sender, receiver, or both.
+ */
+ ACE_QoS_Params (iovec *caller_data = 0,
+ iovec *callee_data = 0,
+ ACE_QoS *socket_qos = 0,
+ ACE_QoS *group_socket_qos = 0,
+ unsigned long flags = 0);
+
+ /// Get caller data.
+ iovec *caller_data (void) const;
+
+ /// Set caller data.
+ void caller_data (iovec *);
+
+ /// Get callee data.
+ iovec *callee_data (void) const;
+
+ /// Set callee data.
+ void callee_data (iovec *);
+
+ /// Get socket qos.
+ ACE_QoS *socket_qos (void) const;
+
+ /// Set socket qos.
+ void socket_qos (ACE_QoS *);
+
+ /// Get group socket qos.
+ ACE_QoS *group_socket_qos (void) const;
+
+ /// Set group socket qos.
+ void group_socket_qos (ACE_QoS *);
+
+ /// Get flags.
+ unsigned long flags (void) const;
+
+ /// Set flags.
+ void flags (unsigned long);
+
+private:
+ /// A pointer to the user data that is to be transferred to the peer
+ /// during connection establishment.
+ iovec *caller_data_;
+
+ /// A pointer to the user data that is to be transferred back from
+ /// the peer during connection establishment.
+ iovec *callee_data_;
+
+ /// A pointer to the flow speicfications for the socket, one for each
+ /// direction.
+ ACE_QoS *socket_qos_;
+
+ /// A pointer to the flow speicfications for the socket group, if
+ /// applicable.
+ ACE_QoS *group_socket_qos_;
+
+ /// Flags that indicate if we're a sender, receiver, or both.
+ unsigned long flags_;
+};
+
+// Callback function that's used by the QoS-enabled <ACE_OS::accept>
+// method.
+typedef int (*ACE_QOS_CONDITION_FUNC) (iovec *caller_id,
+ iovec *caller_data,
+ ACE_QoS *socket_qos,
+ ACE_QoS *group_socket_qos,
+ iovec *callee_id,
+ iovec *callee_data,
+ ACE_SOCK_GROUP *g,
+ unsigned long callbackdata);
+
+
+/**
+ * @class ACE_Accept_QoS_Params
+ *
+ * @brief Wrapper class that simplifies the information passed to the QoS
+ * enabled <ACE_OS::accept> method.
+ */
+class ACE_Export ACE_Accept_QoS_Params
+{
+public:
+ /**
+ * Initialize the data members. The <qos_condition_callback> is the
+ * address of an optional, application-supplied condition function
+ * that will make an accept/reject decision based on the caller
+ * information pass in as parameters, and optionally create or join
+ * a socket group by assinging an appropriate value to the result
+ * parameter <g> of this function. The <callback_data> data is
+ * passed back to the application as a condition function parameter,
+ * i.e., it is an Asynchronous Completion Token (ACT).
+ */
+ ACE_Accept_QoS_Params (ACE_QOS_CONDITION_FUNC qos_condition_callback = 0,
+ unsigned long callback_data = 0);
+
+ /// Get QoS condition callback.
+ ACE_QOS_CONDITION_FUNC qos_condition_callback (void) const;
+
+ /// Set QoS condition callback.
+ void qos_condition_callback (ACE_QOS_CONDITION_FUNC qcc);
+
+ /// Get callback data.
+ unsigned long callback_data (void) const;
+
+ /// Set callback data.
+ void callback_data (unsigned long cd);
+
+private:
+ /**
+ * This is the address of an optional, application-supplied
+ * condition function that will make an accept/reject decision based
+ * on the caller information pass in as parameters, and optionally
+ * create or join a socket group by assinging an appropriate value
+ * to the result parameter <g> of this function.
+ */
+ ACE_QOS_CONDITION_FUNC qos_condition_callback_;
+
+ /**
+ * This data is passed back to the application as a condition
+ * function parameter, i.e., it is an Asynchronous Completion Token
+ * (ACT).
+ */
+ unsigned long callback_data_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_QOS_H */
diff --git a/ACE/ace/OS_String.h b/ACE/ace/OS_String.h
new file mode 100644
index 00000000000..01e2846f140
--- /dev/null
+++ b/ACE/ace/OS_String.h
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+//=============================================================================
+/**
+ * @file OS_String.h
+ *
+ * $Id$
+ *
+ * @brief Contains definition of class ACE_OS_String.
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller <stophph@diku.dk>
+ * @author and a cast of thousands...
+ */
+//=============================================================================
+
+#ifndef ACE_OS_STRING_H
+#define ACE_OS_STRING_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_strings.h"
+#include "ace/OS_NS_wchar.h"
+#include "ace/OS_NS_ctype.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_STRING_H */
diff --git a/ACE/ace/OS_TLI.cpp b/ACE/ace/OS_TLI.cpp
new file mode 100644
index 00000000000..45a0e239133
--- /dev/null
+++ b/ACE/ace/OS_TLI.cpp
@@ -0,0 +1,9 @@
+// $Id$
+
+#include "ace/OS_TLI.h"
+
+ACE_RCSID(ace, OS_TLI, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/OS_TLI.inl"
+#endif /* !ACE_HAS_INLINED_OSCALLS */
diff --git a/ACE/ace/OS_TLI.h b/ACE/ace/OS_TLI.h
new file mode 100644
index 00000000000..297fb31c551
--- /dev/null
+++ b/ACE/ace/OS_TLI.h
@@ -0,0 +1,285 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_TLI.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_OS_TLI_H
+# define ACE_OS_TLI_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/OS_Errno.h"
+# include "ace/ACE_export.h"
+
+# if defined (ACE_EXPORT_MACRO)
+# undef ACE_EXPORT_MACRO
+# endif
+# define ACE_EXPORT_MACRO ACE_Export
+
+# if !(defined(ACE_HAS_TLI) || defined(ACE_HAS_XTI))
+// Dummies to help compilation.
+struct t_call { };
+struct t_bind { };
+struct t_info { };
+struct t_optmgmt { };
+struct t_discon { };
+struct t_unitdata { };
+struct t_uderr { };
+struct netbuf { };
+
+# else /* !(ACE_HAS_TLI || ACE_HAS_XTI) */
+
+# if defined (ACE_HAS_CONFLICTING_XTI_MACROS)
+ // Make sure tcp.h gets included before sys/xti.h.
+# include "ace/os_include/netinet/os_tcp.h"
+# undef TCP_NODELAY
+# undef TCP_MAXSEG
+# endif /* ACE_HAS_CONFLICTING_XTI_MACROS */
+
+# if defined (ACE_HAS_XTI)
+# if defined (ACE_HAS_SYS_XTI_H) /* Nonstandard header placement */
+# define class ace_xti_class
+# include /**/ <sys/xti.h>
+# undef class
+# elif defined (ACE_HAS_FORE_ATM_XTI)
+# include /**/ <fore_xti/xti_user_types.h>
+# include /**/ <fore_xti/xti.h>
+# include /**/ <fore_xti/xti_atm.h>
+# include /**/ <fore_xti/netatm/atm.h>
+# include /**/ <fore_xti/ans.h>
+# else
+# include /**/ <xti.h>
+# endif /* ACE_HAS_SYS_XTI_H */
+
+ // The XTI API for obtaining local/peer addresses is t_getprotaddr().
+ // The ACE API was developed in TLI days and so uses t_getname().
+ // t_getname() has a type argument that specifies which address is
+ // desired, local or peer, while t_getprotaddr() gets both at once.
+ // t_getname() has values defined for the type, so these aren't defined
+ // for XTI systems. So, define them here for ACE API users to use.
+ // These values were taken from sys/tiuser.h on Solaris.
+# if !defined (LOCALNAME)
+# define LOCALNAME 0
+# endif
+# if !defined (REMOTENAME)
+# define REMOTENAME 1
+# endif
+
+# else /* !ACE_HAS_XTI, so this is a TLI system */
+# if !defined (ACE_HAS_TLI_PROTOTYPES)
+
+// Define ACE_TLI headers for systems that don't prototype them....
+extern "C"
+{
+ int t_accept(int fildes, int resfd, struct t_call *call);
+ char *t_alloc(int fildes, int struct_type, int fields);
+ int t_bind(int fildes, struct t_bind *req, struct t_bind *ret);
+ int t_close(int fildes);
+ int t_connect(int fildes, struct t_call *sndcall,
+ struct t_call *rcvcall);
+ void t_error(const char *errmsg);
+ int t_free(char *ptr, int struct_type);
+ int t_getinfo(int fildes, struct t_info *info);
+ int t_getname (int fildes, struct netbuf *namep, int type);
+ int t_getstate(int fildes);
+ int t_listen(int fildes, struct t_call *call);
+ int t_look(int fildes);
+ int t_open(char *path, int oflag, struct t_info *info);
+ int t_optmgmt(int fildes, struct t_optmgmt *req,
+ struct t_optmgmt *ret);
+ int t_rcv(int fildes, char *buf, unsigned int nbytes, int *flags);
+ int t_rcvconnect(int fildes, struct t_call *call);
+ int t_rcvdis(int fildes, struct t_discon *discon);
+ int t_rcvrel(int fildes);
+ int t_rcvudata(int fildes, struct t_unitdata *unitdata, int *flags);
+ int t_rcvuderr(int fildes, struct t_uderr *uderr);
+ int t_snd(int fildes, const char *buf, unsigned int nbytes, int flags);
+ int t_snddis(int fildes, struct t_call *call);
+ int t_sndrel(int fildes);
+ int t_sndudata(int fildes, struct t_unitdata *unitdata);
+ int t_sync(int fildes);
+ int t_unbind(int fildes);
+}
+# endif /* !ACE_HAS_TLI_PROTOTYPES */
+
+# if defined (ACE_HAS_TIUSER_H_BROKEN_EXTERN_C)
+extern "C" {
+# endif /* ACE_HAS_TIUSER_H_BROKEN_EXTERN_C */
+# if defined (ACE_HAS_TIUSER_H)
+# include /**/ <tiuser.h>
+# else
+ /* What to do here??? Is there a tli.h? */
+# endif /* ACE_HAS_TIUSER_H */
+# if defined (ACE_HAS_TIUSER_H_BROKEN_EXTERN_C)
+}
+# endif /* ACE_HAS_TIUSER_H_BROKEN_EXTERN_C */
+
+# if defined (ACE_HAS_SVR4_TLI)
+ // t_getname is a TLI extension added by some platforms before XTI
+ // was widely available. However, it's not often in the system's
+ // header files. Sun OS, for example, is like this.
+ extern "C" int t_getname (int, struct netbuf *, int);
+# endif /* ACE_HAS_SVR4_TLI */
+# endif /* !ACE_HAS_XTI */
+
+# endif /* ACE_HAS_XTI || ACE_HAS_TLI */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This hack is needed to get around an odd and hard-to-reproduce problem
+// with HP aC++. If struct sigaction is defined extern "C" and the sigaction
+// function in namespace ACE_OS, the compiler sometimes gets confused.
+// If we help it with this typedef, it's fine. User code should not use
+// the ACE typedef - it will be removed without warning as soon as we can
+// either drop support for the broken compilers or figure out how to reproduce
+// it so it can be reported to HP and fixed.
+// There's a similar hack in OS_TLI.h for struct t_optmgmt.
+// Also see ChangeLog entries:
+// Mon Jan 23 16:35:40 UTC 2006 Steve Huston <shuston@riverace.com>
+// Mon Jan 23 22:08:56 UTC 2006 Steve Huston <shuston@riverace.com>
+#if defined (__HP_aCC) && (__HP_aCC <= 37300)
+typedef extern "C" struct t_optmgmt ACE_TOPTMGMT;
+typedef extern "C" struct t_bind ACE_TBIND;
+#else
+typedef struct t_optmgmt ACE_TOPTMGMT;
+typedef struct t_bind ACE_TBIND;
+#endif
+
+/**
+ * @namespace ACE_OS
+ *
+ * @brief This class is a wrapper for the XTI/TLI operations
+ *
+ */
+namespace ACE_OS
+{
+ // = A set of wrappers for XTI/TLI.
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_accept (ACE_HANDLE fildes,
+ ACE_HANDLE resfd,
+ struct t_call
+ *call);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ char *t_alloc (ACE_HANDLE fildes,
+ int struct_type,
+ int
+ fields);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_bind (ACE_HANDLE fildes,
+ ACE_TBIND *req,
+ ACE_TBIND *ret);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_close (ACE_HANDLE fildes);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_connect (ACE_HANDLE fildes,
+ struct t_call *sndcall,
+ struct t_call *rcvcall);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ void t_error (const char *errmsg);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_free (char *ptr,
+ int struct_type);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_getinfo (ACE_HANDLE fildes,
+ struct t_info *info);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_getname (ACE_HANDLE fildes,
+ struct netbuf *namep,
+ int type);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_getstate (ACE_HANDLE fildes);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_listen (ACE_HANDLE fildes,
+ struct t_call *call);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_look (ACE_HANDLE fildes);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ ACE_HANDLE t_open (char *path,
+ int oflag,
+ struct t_info *info);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_optmgmt (ACE_HANDLE handle,
+ ACE_TOPTMGMT *req,
+ ACE_TOPTMGMT *ret);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_rcv (ACE_HANDLE fildes,
+ char *buf,
+ unsigned int nbytes,
+ int *flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_rcvdis (ACE_HANDLE fildes,
+ struct t_discon *discon);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_rcvrel (ACE_HANDLE fildes);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_rcvudata (ACE_HANDLE fildes,
+ struct t_unitdata *unitdata,
+ int *flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_rcvuderr (ACE_HANDLE fildes,
+ struct t_uderr *uderr);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_snd (ACE_HANDLE fildes,
+ const char *buf,
+ unsigned int nbytes,
+ int flags);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_snddis (ACE_HANDLE fildes,
+ struct t_call *call);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_sndrel (ACE_HANDLE fildes);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_sync (ACE_HANDLE fildes);
+
+ ACE_NAMESPACE_INLINE_FUNCTION
+ int t_unbind (ACE_HANDLE fildes);
+
+} /* namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_TLI.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_TLI_H */
diff --git a/ACE/ace/OS_TLI.inl b/ACE/ace/OS_TLI.inl
new file mode 100644
index 00000000000..4dffee0f96f
--- /dev/null
+++ b/ACE/ace/OS_TLI.inl
@@ -0,0 +1,390 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_OS {
+
+ACE_INLINE int
+t_accept (ACE_HANDLE handle, ACE_HANDLE reshandle, struct t_call *call)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_accept (handle, reshandle, call), int, -1);
+#else
+ ACE_UNUSED_ARG (call);
+ ACE_UNUSED_ARG (reshandle);
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE char *
+t_alloc (ACE_HANDLE handle, int struct_type, int fields)
+{
+#if defined (ACE_HAS_TLI)
+# if (defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 500)
+ // XPG5 changes t_alloc() return from char* to void*, so ACE_OSCALL_RETURN
+ // doesn't compile correctly.
+ char *result;
+ ACE_OSCALL (::t_alloc (handle, struct_type, fields), char *, 0, result);
+ return result;
+# else
+ ACE_OSCALL_RETURN (::t_alloc (handle, struct_type, fields),
+ char *, 0);
+# endif /* XPG4 vs XPG5 */
+#else
+ ACE_UNUSED_ARG (fields);
+ ACE_UNUSED_ARG (struct_type);
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (0);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_bind (ACE_HANDLE handle, ACE_TBIND *req, ACE_TBIND *ret)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_bind (handle, req, ret), int, -1);
+#else
+ ACE_UNUSED_ARG (ret);
+ ACE_UNUSED_ARG (req);
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_close (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_close (handle), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_connect(ACE_HANDLE fildes,
+ struct t_call *sndcall,
+ struct t_call *rcvcall)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_connect (fildes, sndcall, rcvcall), int, -1);
+#else
+ ACE_UNUSED_ARG (fildes);
+ ACE_UNUSED_ARG (sndcall);
+ ACE_UNUSED_ARG (rcvcall);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE void
+t_error (const char *errmsg)
+{
+#if defined (ACE_HAS_TLI)
+#if defined (ACE_HAS_BROKEN_T_ERROR)
+ ::t_error (const_cast<char *> (errmsg));
+#else
+ ::t_error (errmsg);
+#endif /* ACE_HAS_BROKEN_T_ERROR */
+#else
+ ACE_UNUSED_ARG (errmsg);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_free (char *ptr, int struct_type)
+{
+#if defined (ACE_HAS_TLI)
+ if (ptr == 0)
+ return 0;
+ ACE_OSCALL_RETURN (::t_free (ptr, struct_type), int, -1);
+#else
+ ACE_UNUSED_ARG (struct_type);
+ ACE_UNUSED_ARG (ptr);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_getinfo (ACE_HANDLE handle, struct t_info *info)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_getinfo (handle, info), int, -1);
+#else
+ ACE_UNUSED_ARG (info);
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_getname (ACE_HANDLE handle, struct netbuf *namep, int type)
+{
+#if defined (ACE_HAS_XTI)
+ ACE_TBIND bound, peer;
+ // Depending on which address the caller wants, fill caller's values
+ // into one of the t_bind netbufs. The other is set up to ignore that
+ // address.
+ switch (type)
+ {
+ case LOCALNAME:
+ bound.addr.buf = namep->buf;
+ bound.addr.maxlen = namep->maxlen;
+ bound.addr.len = 0;
+ peer.addr.buf = 0;
+ peer.addr.maxlen = 0;
+ peer.addr.len = 0;
+ break;
+ case REMOTENAME:
+ bound.addr.buf = 0;
+ bound.addr.maxlen = 0;
+ bound.addr.len = 0;
+ peer.addr.buf = namep->buf;
+ peer.addr.maxlen = namep->maxlen;
+ peer.addr.len = 0;
+ break;
+ default:
+ ACE_OS::last_error (EINVAL);
+ return -1;
+ }
+ if (t_getprotaddr (handle, &bound, &peer) == -1)
+ return -1;
+ // Call succeeded; put the caller's desired address length in his netbuf.
+ if (type == LOCALNAME)
+ namep->len = bound.addr.len;
+ else
+ namep->len = peer.addr.len;
+ return 0;
+
+#elif defined (ACE_HAS_SVR4_TLI)
+ ACE_OSCALL_RETURN (::t_getname (handle, namep, type), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (namep);
+ ACE_UNUSED_ARG (type);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SVR4_TLI */
+}
+
+ACE_INLINE int
+t_getstate (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_getstate (handle), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_listen (ACE_HANDLE handle, struct t_call *call)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_listen (handle, call), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (call);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_look (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_look (handle), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE ACE_HANDLE
+t_open (char *path, int oflag, struct t_info *info)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_open (path, oflag, info), ACE_HANDLE, ACE_INVALID_HANDLE);
+#else
+ ACE_UNUSED_ARG (path);
+ ACE_UNUSED_ARG (oflag);
+ ACE_UNUSED_ARG (info);
+
+ ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_optmgmt (ACE_HANDLE handle, ACE_TOPTMGMT *req, ACE_TOPTMGMT *ret)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_optmgmt (handle, req, ret), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (req);
+ ACE_UNUSED_ARG (ret);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_rcv (ACE_HANDLE handle,
+ char *buf,
+ unsigned int nbytes,
+ int *flags)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_rcv (handle, buf, nbytes, flags),
+ int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (nbytes);
+ ACE_UNUSED_ARG (flags);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_rcvdis (ACE_HANDLE handle, struct t_discon *discon)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_rcvdis (handle, discon), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (discon);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_rcvrel (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_rcvrel (handle), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_rcvudata (ACE_HANDLE handle,
+ struct t_unitdata *unitdata,
+ int *flags)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_rcvudata (handle, unitdata, flags),
+ int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (unitdata);
+ ACE_UNUSED_ARG (flags);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_rcvuderr (ACE_HANDLE handle, struct t_uderr *uderr)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_rcvuderr (handle, uderr), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (uderr);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_snd (ACE_HANDLE handle,
+ const char *buf,
+ unsigned int nbytes,
+ int flags)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_snd (handle, (char *) buf, nbytes, flags), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (buf);
+ ACE_UNUSED_ARG (nbytes);
+ ACE_UNUSED_ARG (flags);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_snddis (ACE_HANDLE handle, struct t_call *call)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_snddis (handle, call), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (call);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_sndrel (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_sndrel (handle), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_sync (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_sync (handle), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+ACE_INLINE int
+t_unbind (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_TLI)
+ ACE_OSCALL_RETURN (::t_unbind (handle), int, -1);
+#else
+ ACE_UNUSED_ARG (handle);
+
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TLI */
+}
+
+} /* end namespace ACE_OS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_Thread_Adapter.cpp b/ACE/ace/OS_Thread_Adapter.cpp
new file mode 100644
index 00000000000..904c87d2d1d
--- /dev/null
+++ b/ACE/ace/OS_Thread_Adapter.cpp
@@ -0,0 +1,153 @@
+// $Id$
+
+#include "ace/OS_Thread_Adapter.h"
+
+ACE_RCSID (ace,
+ OS_Thread_Adapter,
+ "$Id$")
+
+#include "ace/Thread_Hook.h"
+#include "ace/Object_Manager_Base.h"
+#include "ace/Global_Macros.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_OS_Thread_Adapter::ACE_OS_Thread_Adapter (
+ ACE_THR_FUNC user_func
+ , void *arg
+ , ACE_THR_C_FUNC entry_point
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , ACE_SEH_EXCEPT_HANDLER selector
+ , ACE_SEH_EXCEPT_HANDLER handler
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ )
+ : ACE_Base_Thread_Adapter (user_func, arg, entry_point
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , 0
+ , selector
+ , handler
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ )
+{
+}
+
+ACE_OS_Thread_Adapter::~ACE_OS_Thread_Adapter (void)
+{
+}
+
+ACE_THR_FUNC_RETURN
+ACE_OS_Thread_Adapter::invoke (void)
+{
+ // Inherit the logging features if the parent thread has an
+ // ACE_Log_Msg instance in thread-specific storage.
+ this->inherit_log_msg ();
+
+ // Extract the arguments.
+ ACE_THR_FUNC_INTERNAL func =
+ reinterpret_cast<ACE_THR_FUNC_INTERNAL> (this->user_func_);
+ void *arg = this->arg_;
+
+ // Delete ourselves since we don't need <this> anymore. Make sure
+ // not to access <this> anywhere below this point.
+ delete this;
+
+#if defined (ACE_NEEDS_LWP_PRIO_SET)
+ // On SunOS, the LWP priority needs to be set in order to get
+ // preemption when running in the RT class. This is the ACE way to
+ // do that . . .
+ ACE_hthread_t thr_handle;
+ ACE_OS::thr_self (thr_handle);
+ int prio;
+
+ // thr_getprio () on the current thread should never fail.
+ ACE_OS::thr_getprio (thr_handle, prio);
+
+ // ACE_OS::thr_setprio () has the special logic to set the LWP priority,
+ // if running in the RT class.
+ ACE_OS::thr_setprio (prio);
+
+#endif /* ACE_NEEDS_LWP_PRIO_SET */
+
+ ACE_THR_FUNC_RETURN status = 0;
+
+ ACE_SEH_TRY
+ {
+ ACE_SEH_TRY
+ {
+ ACE_Thread_Hook *hook =
+ ACE_OS_Object_Manager::thread_hook ();
+
+ if (hook)
+ // Invoke the start hook to give the user a chance to
+ // perform some initialization processing before the
+ // <func> is invoked.
+ status = hook->start (reinterpret_cast<ACE_THR_FUNC> (func),
+ arg);
+ else
+ {
+ // Call thread entry point.
+ status = (*func) (arg);
+ }
+ }
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_SEH_EXCEPT (ACE_OS_Object_Manager::seh_except_selector ()(
+ (void *) GetExceptionInformation ()))
+ {
+ ACE_OS_Object_Manager::seh_except_handler ()(0);
+ }
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ }
+
+ ACE_SEH_FINALLY
+ {
+ // If we changed this to 1, change the respective if in
+ // Task::svc_run to 0.
+#if 0
+ // Call the <Task->close> hook.
+ if (func == reinterpret_cast<ACE_THR_FUNC_INTERNAL> (ACE_Task_Base::svc_run))
+ {
+ ACE_Task_Base *task_ptr = (ACE_Task_Base *) arg;
+ ACE_Thread_Manager *thr_mgr_ptr = task_ptr->thr_mgr ();
+
+ // This calls the Task->close () hook.
+ task_ptr->cleanup (task_ptr, 0);
+
+ // This prevents a second invocation of the cleanup code
+ // (called later by <ACE_Thread_Manager::exit>.
+ thr_mgr_ptr->at_exit (task_ptr, 0, 0);
+ }
+#endif /* 0 */
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
+ // Call TSS destructors.
+ ACE_OS::cleanup_tss (0 /* not main thread */);
+
+# if defined (ACE_WIN32)
+ // Exit the thread. Allow CWinThread-destructor to be invoked
+ // from AfxEndThread. _endthreadex will be called from
+ // AfxEndThread so don't exit the thread now if we are running
+ // an MFC thread.
+# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+ // Not spawned by ACE_Thread_Manager, use the old buggy
+ // version. You should seriously consider using
+ // ACE_Thread_Manager to spawn threads. The following code
+ // is know to cause some problem.
+ CWinThread *pThread = ::AfxGetThread ();
+
+ if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
+ ACE_ENDTHREADEX (status);
+ else
+ ::AfxEndThread (status);
+# else
+ ACE_ENDTHREADEX (status);
+# endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
+# endif /* ACE_WIN32 */
+#endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
+ }
+
+ return status;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/OS_Thread_Adapter.h b/ACE/ace/OS_Thread_Adapter.h
new file mode 100644
index 00000000000..44576daff90
--- /dev/null
+++ b/ACE/ace/OS_Thread_Adapter.h
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_Thread_Adapter.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_THREAD_ADAPTER_H
+#define ACE_OS_THREAD_ADAPTER_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Base_Thread_Adapter.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include /**/ "ace/ACE_export.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_OS_Thread_Adapter
+ *
+ * @brief Converts a C++ function into a function that can be
+ * called from a thread creation routine
+ * (e.g., pthread_create() or _beginthreadex()) that expects an
+ * extern "C" entry point. This class also makes it possible to
+ * transparently provide hooks to register a thread with an
+ * ACE_Thread_Manager.
+ *
+ * This class is used in ACE_OS::thr_create(). In general, the
+ * thread that creates an object of this class is different from
+ * the thread that calls invoke() on this object. Therefore,
+ * the invoke() method is responsible for deleting itself.
+ */
+class ACE_Export ACE_OS_Thread_Adapter : public ACE_Base_Thread_Adapter
+{
+public:
+ /// Constructor.
+ ACE_OS_Thread_Adapter (ACE_THR_FUNC user_func,
+ void *arg,
+ ACE_THR_C_FUNC entry_point = (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME
+# 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 */
+ );
+
+ /**
+ * Execute the @a user_func_ with the @a arg. This function deletes
+ * @c this, thereby rendering the object useless after the call
+ * returns.
+ */
+ virtual ACE_THR_FUNC_RETURN invoke (void);
+
+protected:
+
+ /// Ensure that this object is allocated on the heap.
+ ~ACE_OS_Thread_Adapter (void);
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_THREAD_ADAPTER_H */
diff --git a/ACE/ace/OS_main.cpp b/ACE/ace/OS_main.cpp
new file mode 100644
index 00000000000..6d931fbd4b6
--- /dev/null
+++ b/ACE/ace/OS_main.cpp
@@ -0,0 +1,127 @@
+// $Id$
+
+#include "ace/OS_main.h"
+
+ACE_RCSID(ace, OS_main, "$Id$")
+
+#if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
+
+#include "ace/Init_ACE.h"
+
+# if !defined (ACE_HAS_MINIMAL_ACE_OS)
+# include "ace/Object_Manager.h"
+# endif /* ! ACE_HAS_MINIMAL_ACE_OS */
+
+// Rename "main ()" on platforms that don't allow it to be called "main ()".
+
+// Also, create ACE_Object_Manager static instance(s) in "main ()".
+// ACE_MAIN_OBJECT_MANAGER defines the ACE_Object_Manager(s) that will
+// be instantiated on the stack of main (). Note that it is only used
+// when compiling main (): its value does not affect the contents of
+// ace/OS.o.
+# if !defined (ACE_MAIN_OBJECT_MANAGER)
+# define ACE_MAIN_OBJECT_MANAGER \
+ ACE_OS_Object_Manager ace_os_object_manager; \
+ ACE_Object_Manager ace_object_manager;
+# endif /* ! ACE_MAIN_OBJECT_MANAGER */
+
+# if !defined (ACE_WIN32)
+
+# if !(defined (ACE_VXWORKS) && !defined (__RTP__))
+/* forward declaration */
+extern int ace_main_i (int, char *[]);
+# endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_VXWORKS) && !defined (__RTP__)
+ace_main_proc_ptr vx_ace_main_i_ptr = 0;
+
+int ace_os_main_i (int argc, char *argv[]) /* user's entry point, e.g., main */
+{
+ ACE_MAIN_OBJECT_MANAGER
+ return vx_ace_main_i_ptr ? (*vx_ace_main_i_ptr) (argc, argv) : (-1); /* what the user calls "main" */
+}
+# else /* !ACE_VXWORKS && !__RTP__ */
+int ace_os_main_i (int argc, char *argv[]) /* user's entry point, e.g., main */
+{
+ ACE_MAIN_OBJECT_MANAGER
+ return ace_main_i (argc, argv); /* what the user calls "main" */
+}
+# endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# elif !defined (ACE_HAS_WINCE)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+int ACE_Main_Base::run (int argc, ACE_TCHAR *argv[])
+{
+ return this->run_i (argc, argv);
+}
+
+ACE_Export int
+ace_os_wmain_i (ACE_Main_Base &mbase, int argc, ACE_TCHAR *argv[]) /* user's entry point, e.g., main */
+{
+ ACE_MAIN_OBJECT_MANAGER
+ return mbase.run (argc, argv); /* what the user calls "main" */
+}
+# else /* ! (ACE_WIN32 && ACE_USES_WCHAR) */
+
+ACE_Main_Base::ACE_Main_Base ()
+{
+ ACE::init ();
+}
+
+ACE_Main_Base::~ACE_Main_Base ()
+{
+ ACE::fini ();
+}
+
+int ACE_Main_Base::run (int argc, char *argv[])
+{
+ return this->run_i (argc, argv);
+}
+
+ACE_Export int
+ace_os_main_i (ACE_Main_Base &mbase, int argc, char *argv[]) /* user's entry point, e.g., main */
+{
+ ACE_MAIN_OBJECT_MANAGER
+ return mbase.run (argc, argv); /* what the user calls "main" */
+}
+# endif /* ACE_WIN32 && ACE_USES_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# else /* ACE_HAS_WINCE */
+
+// CE only gets a command line string; no argv. So we need to convert it
+// when the main entrypoint expects argc/argv. ACE_ARGV supports this.
+# include "ace/OS_NS_string.h"
+# include "ace/ACE.h"
+# include "ace/ARGV.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int ACE_Main_Base::run (HINSTANCE,
+ HINSTANCE,
+ LPWSTR lpCmdLine,
+ int)
+{
+ ACE_TCHAR cmdline[1024];
+ ACE_OS::strcpy (cmdline, ACE_TEXT ("program "));
+ ACE_OS::strcat (cmdline, ACE_TEXT_WCHAR_TO_TCHAR (lpCmdLine));
+ ACE_ARGV ce_argv (cmdline);
+ ACE::init ();
+ ACE_MAIN_OBJECT_MANAGER
+ int i = this->run_i (ce_argv.argc (), ce_argv.argv ());
+ ACE::fini ();
+ return i;
+}
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# endif /* !ACE_HAS_WINCE */
+
+# endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */
diff --git a/ACE/ace/OS_main.h b/ACE/ace/OS_main.h
new file mode 100644
index 00000000000..b6c0938c665
--- /dev/null
+++ b/ACE/ace/OS_main.h
@@ -0,0 +1,303 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file OS_main.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#include /**/ "ace/ACE_export.h"
+
+#ifndef ACE_OS_MAIN_H
+# define ACE_OS_MAIN_H
+
+# include /**/ "ace/pre.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+# if defined (ACE_HAS_RTEMS)
+extern char* rtems_progname;
+# endif /* ACE_HAS_RTEMS */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x640) && defined (__RTP__)
+# include <resolvLib.h>
+#endif
+
+# if !defined (ACE_MAIN)
+# define ACE_MAIN main
+# endif /* ! ACE_MAIN */
+
+# if !defined (ACE_WMAIN)
+# define ACE_WMAIN wmain
+# endif /* ! ACE_WMAIN */
+
+# if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+# define ACE_TMAIN wmain
+# else
+# if defined (ACE_USES_WCHAR) /* Not Win32, but uses wchar */
+ // Replace main() with a version that converts the char** argv to
+ // ACE_TCHAR and calls the ACE_TMAIN entrypoint.
+# include "ace/Argv_Type_Converter.h"
+# define ACE_TMAIN \
+ ace_main_i (int, ACE_TCHAR *[]); /* forward declaration */ \
+ int main (int argc, char *argv[]) { \
+ ACE_Argv_Type_Converter wide_argv (argc, argv); \
+ return ace_main_i (argc, wide_argv.get_TCHAR_argv ()); \
+ } \
+ int ace_main_i
+# else
+# define ACE_TMAIN main
+# endif /* ACE_USES_WCHAR */
+# endif
+
+# if defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
+# if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
+# define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+# endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */
+# endif /* ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */
+
+# if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) \
+ && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
+
+// Rename "main ()" on platforms that don't allow it to be called "main ()".
+
+# if defined (ACE_VXWORKS) && !defined (__RTP__)
+
+typedef int (*ace_main_proc_ptr)(int, char *[]);
+
+extern ace_main_proc_ptr vx_ace_main_i_ptr;
+
+// Declare ACE_MAIN as extern C so that it can be retrieved
+// using symFindByName
+extern "C"
+{
+ int ACE_MAIN (int, char* []);
+}
+
+# define main \
+ACE_MAIN (int, char *[]); /* forward decl to gobble up the 'int' if there is one */ \
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL \
+int ace_os_main_i (int, char *[]); \
+ACE_END_VERSIONED_NAMESPACE_DECL \
+int ace_main_i(int, char *[]); \
+int \
+ACE_MAIN (int argc, char *argv[]) /* user's entry point, e.g., main */ \
+{ \
+ vx_ace_main_i_ptr = ace_main_i; \
+ return ace_os_main_i (argc, argv); /* what the user calls "main" */ \
+} \
+int \
+ace_main_i
+
+# elif defined (ACE_HAS_RTEMS)
+
+# define main \
+ACE_MAIN (int, char *[]); /* forward decl to gobble up the 'int' if there is one */ \
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL \
+int ace_os_main_i (int, char *[]); \
+ACE_END_VERSIONED_NAMESPACE_DECL \
+int \
+ACE_MAIN (int argc, char *argv[]) /* user's entry point, e.g., main */ \
+{ \
+ if ((argc > 0) && argv && argv[0]) \
+ rtems_progname = argv[0]; \
+ else \
+ rtems_progname = "RTEMS"; \
+ return ace_os_main_i (argc, argv); /* what the user calls "main" */ \
+} \
+int \
+ace_main_i
+
+# elif defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x640) && defined (__RTP__)
+
+# define main \
+ACE_MAIN (int, char *[]); /* forward decl to gobble up the 'int' if there is one */ \
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL \
+int ace_os_main_i (int, char *[]); \
+ACE_END_VERSIONED_NAMESPACE_DECL \
+int \
+ACE_MAIN (int argc, char *argv[]) /* user's entry point, e.g., main */ \
+{ \
+ resolvInit(); \
+ return ace_os_main_i (argc, argv); /* what the user calls "main" */ \
+} \
+int \
+ace_main_i
+
+# elif !defined (ACE_WIN32)
+
+# define main \
+ACE_MAIN (int, char *[]); /* forward decl to gobble up the 'int' if there is one */ \
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL \
+int ace_os_main_i (int, char *[]); \
+ACE_END_VERSIONED_NAMESPACE_DECL \
+int \
+ACE_MAIN (int argc, char *argv[]) /* user's entry point, e.g., main */ \
+{ \
+ return ace_os_main_i (argc, argv); /* what the user calls "main" */ \
+} \
+int \
+ace_main_i
+
+# elif !defined (ACE_HAS_WINCE)
+
+# if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Export ACE_Main_Base
+{
+public:
+ int run (int, ACE_TCHAR *[]);
+ virtual int run_i (int, ACE_TCHAR *[]) = 0;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# define wmain \
+ace_wmain_i (int, ACE_TCHAR *[]); \
+ACE_Export int ace_os_wmain_i (ACE_Main_Base&, int, ACE_TCHAR *[]); \
+class ACE_Main : public ACE_Main_Base {int run_i (int, ACE_TCHAR *[]);}; \
+inline int ACE_Main::run_i (int argc, ACE_TCHAR *argv[]) \
+{ \
+ return ace_wmain_i (argc, argv); \
+} \
+int \
+ACE_WMAIN (int argc, ACE_TCHAR *argv[]) /* user's entry point, e.g., wmain */ \
+{ \
+ ACE_Main m; \
+ return ace_os_wmain_i (m, argc, argv); /* what the user calls "main" */ \
+} \
+int \
+ace_wmain_i
+
+# else /* ! (ACE_WIN32 && ACE_USES_WCHAR) */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Export ACE_Main_Base
+{
+public:
+ ACE_Main_Base ();
+ virtual ~ACE_Main_Base ();
+ int run (int, char *[]);
+ virtual int run_i (int, char *[]) = 0;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+/*
+** LabVIEW RT cannot directly use an executable. Need to build the program
+** as a DLL and call it from something else. The ACE test framework knows this
+** trick and uses a LabVIEW RT target-resident control program to load a
+** DLL, look up it's main() entrypoint, and call it.
+*/
+# if defined (ACE_BUILD_LABVIEW_EXE_AS_DLL)
+extern "C" __declspec (dllexport) int main (int, char *[]);
+# endif /* ACE_BUILD_LABVIEW_EXE_AS_DLL) */
+
+# define main \
+ace_main_i (int, char *[]); \
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL \
+ACE_Export int ace_os_main_i (ACE_Main_Base&, int, char *[]); \
+class ACE_Main : public ACE_Main_Base {int run_i (int, char *[]);}; \
+inline int ACE_Main::run_i (int argc, char *argv[]) \
+{ \
+ return ace_main_i (argc, argv); \
+} \
+ACE_END_VERSIONED_NAMESPACE_DECL \
+int \
+ACE_MAIN (int argc, char *argv[]) /* user's entry point, e.g., wmain */ \
+{ \
+ ACE_Main m; \
+ return m.run (argc, argv); /*ace_os_main_i (m, argc, argv); what the user calls "main" */ \
+} \
+int \
+ace_main_i
+
+# endif /* ACE_WIN32 && ACE_USES_WCHAR */
+
+# else /* ACE_HAS_WINCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Export ACE_Main_Base
+{
+public:
+ int run (HINSTANCE, HINSTANCE, LPWSTR, int);
+ virtual int run_i (int, ACE_TCHAR *[]) = 0;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_TMAIN) // Use WinMain on CE; others give warning/error.
+# undef ACE_TMAIN
+# endif // ACE_TMAIN
+
+// Support for ACE_TMAIN, which is a recommended way. It would be nice if
+// CE had CommandLineToArgvW()... but it's only on NT3.5 and up.
+
+# define ACE_TMAIN \
+ace_tmain_i (int, ACE_TCHAR *[]); \
+class ACE_Main : public ACE_Main_Base {int run_i (int argc, ACE_TCHAR *argv[]);}; \
+inline int ACE_Main::run_i (int argc, ACE_TCHAR *argv[]) \
+{ \
+ return ace_tmain_i (argc, argv); \
+} \
+int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) \
+{ \
+ ACE_Main m; \
+ return m.run (hInstance, hPrevInstance, lpCmdLine, nCmdShow); \
+} \
+int ace_tmain_i
+
+// Support for wchar_t but still can't fit to CE because of the command
+// line parameters.
+# define wmain \
+ace_wmain_i (int, ACE_TCHAR *[]); \
+ACE_Export int ace_os_winwmain_i (ACE_Main_Base&, hInstance, hPrevInstance, lpCmdLine, nCmdShow); /* forward declaration */ \
+class ACE_Main : public ACE_Main_Base {int run_i (int argc, ACE_TCHAR *argv[]);}; \
+inline int ACE_Main::run_i (int argc, ACE_TCHAR *argv[]) \
+{ \
+ return ace_wmain_i (argc, argv); \
+} \
+int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) \
+{ \
+ return ace_os_winwmain_i (hInstance, hPrevInstance, lpCmdLine, nCmdShow); \
+} \
+int ace_wmain_i
+
+// Supporting legacy 'main' is A LOT easier for users than changing existing
+// code on WinCE. Unfortunately, evc 3 can't grok a #include within the macro
+// expansion, so it needs to go out here.
+# include "ace/Argv_Type_Converter.h"
+# define main \
+ace_main_i (int, ACE_TCHAR *[]); \
+ACE_Export int ace_os_winmain_i (ACE_Main_Base&, hInstance, hPrevInstance, lpCmdLine, nCmdShow); /* forward declaration */ \
+class ACE_Main : public ACE_Main_Base {int run_i (int argc, ACE_TCHAR *argv[]);}; \
+inline int ACE_Main::run_i (int argc, ACE_TCHAR *argv[]) \
+{ \
+ return ace_main_i (argc, argv); \
+} \
+int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) \
+{ \
+ return ace_os_winmain_i (hInstance, hPrevInstance, lpCmdLine, nCmdShow); \
+} \
+int ace_main_i
+
+# endif /* ACE_PSOSIM */
+# endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */
+
+# include /**/ "ace/post.h"
+
+#endif /* ACE_OS_MAIN_H */
diff --git a/ACE/ace/Obchunk.cpp b/ACE/ace/Obchunk.cpp
new file mode 100644
index 00000000000..7cb00a4dfe6
--- /dev/null
+++ b/ACE/ace/Obchunk.cpp
@@ -0,0 +1,36 @@
+// $Id$
+
+#include "ace/Obchunk.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Obchunk.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Obchunk, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Obchunk)
+
+void
+ACE_Obchunk::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Obchunk::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("end_ = %x\n"), this->end_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("cur_ = %x\n"), this->cur_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Obchunk::ACE_Obchunk (size_t size)
+ : end_ (contents_ + size),
+ block_ (contents_),
+ cur_ (contents_),
+ next_ (0)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Obchunk.h b/ACE/ace/Obchunk.h
new file mode 100644
index 00000000000..9690c39f9d1
--- /dev/null
+++ b/ACE/ace/Obchunk.h
@@ -0,0 +1,77 @@
+// -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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];
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Obchunk.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OBCHUNK_H */
diff --git a/ACE/ace/Obchunk.inl b/ACE/ace/Obchunk.inl
new file mode 100644
index 00000000000..4853b0e12aa
--- /dev/null
+++ b/ACE/ace/Obchunk.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Obchunk::~ACE_Obchunk (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Object_Manager.cpp b/ACE/ace/Object_Manager.cpp
new file mode 100644
index 00000000000..313eb6a116a
--- /dev/null
+++ b/ACE/ace/Object_Manager.cpp
@@ -0,0 +1,888 @@
+// $Id$
+
+#include "ace/Object_Manager.h"
+#if !defined (ACE_LACKS_ACE_TOKEN)
+# include "ace/Token_Manager.h"
+#endif /* ! ACE_LACKS_ACE_TOKEN */
+#include "ace/Thread_Manager.h"
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+# include "ace/Service_Manager.h"
+# include "ace/Service_Config.h"
+#endif /* ! ACE_LACKS_ACE_SVCCONF */
+#include "ace/Signal.h"
+#include "ace/Log_Msg.h"
+#include "ace/Malloc.h"
+#include "ace/Sig_Adapter.h"
+#include "ace/Framework_Component.h"
+#include "ace/DLL_Manager.h"
+#include "ace/Atomic_Op.h"
+#include "ace/OS_NS_sys_time.h"
+
+#if defined (ACE_HAS_TRACE)
+#include "ace/Trace.h"
+#endif /* ACE_HAS_TRACE */
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Object_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Guard_T.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Mutex.h"
+#include "ace/RW_Thread_Mutex.h"
+
+ACE_RCSID(ace, Object_Manager, "$Id$")
+
+#if ! defined (ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS)
+# define ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS
+#endif /* ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS */
+
+#if ! defined (ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS)
+# define ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS
+#endif /* ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS */
+
+#if ! defined (ACE_APPLICATION_PREALLOCATED_OBJECT_DELETIONS)
+# define ACE_APPLICATION_PREALLOCATED_OBJECT_DELETIONS
+#endif /* ACE_APPLICATION_PREALLOCATED_OBJECT_DELETIONS */
+
+#if ! defined (ACE_APPLICATION_PREALLOCATED_ARRAY_DELETIONS)
+# define ACE_APPLICATION_PREALLOCATED_ARRAY_DELETIONS
+#endif /* ACE_APPLICATION_PREALLOCATED_ARRAY_DELETIONS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Singleton pointer.
+ACE_Object_Manager *ACE_Object_Manager::instance_ = 0;
+
+void *ACE_Object_Manager::preallocated_object[
+ ACE_Object_Manager::ACE_PREALLOCATED_OBJECTS] = { 0 };
+
+void *ACE_Object_Manager::preallocated_array[
+ ACE_Object_Manager::ACE_PREALLOCATED_ARRAYS] = { 0 };
+
+// Handy macros for use by ACE_Object_Manager constructor to
+// preallocate or delete an object or array, either statically (in
+// global data) or dynamically (on the heap).
+#if defined (ACE_HAS_STATIC_PREALLOCATION)
+# define ACE_PREALLOCATE_OBJECT(TYPE, ID)\
+ {\
+ static ACE_Cleanup_Adapter<TYPE> obj;\
+ preallocated_object[ID] = &obj;\
+ }
+# define ACE_PREALLOCATE_ARRAY(TYPE, ID, COUNT)\
+ {\
+ static ACE_Cleanup_Adapter<TYPE> obj[COUNT];\
+ preallocated_array[ID] = &obj;\
+ }
+#else
+# define ACE_PREALLOCATE_OBJECT(TYPE, ID)\
+ {\
+ ACE_Cleanup_Adapter<TYPE> *obj_p;\
+ ACE_NEW_RETURN (obj_p, ACE_Cleanup_Adapter<TYPE>, -1);\
+ preallocated_object[ID] = obj_p;\
+ }
+# define ACE_PREALLOCATE_ARRAY(TYPE, ID, COUNT)\
+ {\
+ ACE_Cleanup_Adapter<TYPE[COUNT]> *array_p;\
+ ACE_NEW_RETURN (array_p, ACE_Cleanup_Adapter<TYPE[COUNT]>, -1);\
+ preallocated_array[ID] = array_p;\
+ }
+# define ACE_DELETE_PREALLOCATED_OBJECT(TYPE, ID)\
+ ACE_CLEANUP_DESTROYER_NAME (\
+ (ACE_Cleanup_Adapter<TYPE> *) preallocated_object[ID], 0);\
+ preallocated_object[ID] = 0;
+# define ACE_DELETE_PREALLOCATED_ARRAY(TYPE, ID, COUNT)\
+ delete (ACE_Cleanup_Adapter<TYPE[COUNT]> *) preallocated_array[ID];\
+ preallocated_array[ID] = 0;
+#endif /* ACE_HAS_STATIC_PREALLOCATION */
+
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+
+/**
+ * @class ACE_Object_Manager_Preallocations
+ *
+ * @brief Performs preallocations of certain statically allocated services
+ * needed by ACE.
+ */
+class ACE_Object_Manager_Preallocations
+{
+public:
+ ACE_Object_Manager_Preallocations (void);
+ ~ACE_Object_Manager_Preallocations (void);
+
+private:
+ ACE_Static_Svc_Descriptor ace_svc_desc_ACE_Service_Manager;
+};
+
+ACE_Object_Manager_Preallocations::ACE_Object_Manager_Preallocations (void)
+{
+ ACE_STATIC_SVC_DEFINE (ACE_Service_Manager_initializer,
+ ACE_TEXT ("ACE_Service_Manager"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (ACE_Service_Manager),
+ ACE_Service_Type::DELETE_THIS |
+ ACE_Service_Type::DELETE_OBJ,
+ 0)
+
+ // Initialize the static service objects using the descriptors created
+ // above.
+ ace_svc_desc_ACE_Service_Manager =
+ ace_svc_desc_ACE_Service_Manager_initializer;
+
+ // Add to the list of static configured services.
+ ACE_Service_Config::static_svcs ()->
+ insert (&ace_svc_desc_ACE_Service_Manager);
+}
+
+ACE_Object_Manager_Preallocations::~ACE_Object_Manager_Preallocations (void)
+{
+}
+
+#endif /* ! ACE_LACKS_ACE_SVCCONF */
+
+int
+ACE_Object_Manager::starting_up (void)
+{
+ return ACE_Object_Manager::instance_ ? instance_->starting_up_i () : 1;
+}
+
+int
+ACE_Object_Manager::shutting_down (void)
+{
+ return ACE_Object_Manager::instance_ ? instance_->shutting_down_i () : 1;
+}
+
+#if defined (ACE_DISABLE_WIN32_ERROR_WINDOWS)
+// Instead of popping up a window for exceptions, just print something out
+LONG _stdcall ACE_UnhandledExceptionFilter (PEXCEPTION_POINTERS pExceptionInfo)
+{
+ DWORD dwExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode;
+
+ if (dwExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("\nERROR: ACCESS VIOLATION\n")));
+ else
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("\nERROR: UNHANDLED EXCEPTION\n")));
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif /* ACE_DISABLE_WIN32_ERROR_WINDOWS */
+
+// Initialize an ACE_Object_Manager. There can be instances of this object
+// other than The Instance. This can happen if a user creates one for some
+// reason. All objects set up their per-object information and managed
+// objects, but only The Instance sets up the static preallocated objects and
+// the (static) ACE_Service_Config signal handler.
+int
+ACE_Object_Manager::init (void)
+{
+ if (starting_up_i ())
+ {
+ // First, indicate that the ACE_Object_Manager instance is being
+ // initialized.
+ object_manager_state_ = OBJ_MAN_INITIALIZING;
+
+ // Only The Instance sets up with ACE_OS_Object_Manager and initializes
+ // the preallocated objects.
+ if (this == instance_)
+ {
+ // Make sure that the ACE_OS_Object_Manager has been created,
+ // and register with it for chained fini ().
+ ACE_OS_Object_Manager::instance ()->next_ = this;
+
+# if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
+ ACE_Atomic_Op<ACE_Thread_Mutex, long>::init_functions ();
+ ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::init_functions ();
+# endif /* ACE_HAS_BUILTIN_ATOMIC_OP */
+
+# if !defined (ACE_LACKS_ACE_SVCCONF)
+ // Construct the ACE_Service_Config's signal handler.
+ ACE_NEW_RETURN (ace_service_config_sig_handler_,
+ ACE_Sig_Adapter (&ACE_Service_Config::handle_signal), -1);
+ ACE_Service_Config::signal_handler (ace_service_config_sig_handler_);
+# endif /* ! ACE_LACKS_ACE_SVCCONF */
+
+ // Allocate the preallocated (hard-coded) object instances.
+ ACE_PREALLOCATE_OBJECT (ACE_SYNCH_RW_MUTEX, ACE_FILECACHE_LOCK)
+# if defined (ACE_HAS_THREADS)
+ ACE_PREALLOCATE_OBJECT (ACE_Recursive_Thread_Mutex,
+ ACE_STATIC_OBJECT_LOCK)
+# endif /* ACE_HAS_THREADS */
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_PREALLOCATE_OBJECT (ACE_Thread_Mutex,
+ ACE_MT_CORBA_HANDLER_LOCK)
+ ACE_PREALLOCATE_OBJECT (ACE_Thread_Mutex, ACE_DUMP_LOCK)
+ ACE_PREALLOCATE_OBJECT (ACE_Recursive_Thread_Mutex,
+ ACE_SIG_HANDLER_LOCK)
+ ACE_PREALLOCATE_OBJECT (ACE_Null_Mutex, ACE_SINGLETON_NULL_LOCK)
+ ACE_PREALLOCATE_OBJECT (ACE_Recursive_Thread_Mutex,
+ ACE_SINGLETON_RECURSIVE_THREAD_LOCK)
+ ACE_PREALLOCATE_OBJECT (ACE_Thread_Mutex, ACE_THREAD_EXIT_LOCK)
+#if !defined (ACE_LACKS_ACE_TOKEN) && defined (ACE_HAS_TOKENS_LIBRARY)
+ ACE_PREALLOCATE_OBJECT (ACE_TOKEN_CONST::MUTEX,
+ ACE_TOKEN_MANAGER_CREATION_LOCK)
+ ACE_PREALLOCATE_OBJECT (ACE_TOKEN_CONST::MUTEX,
+ ACE_TOKEN_INVARIANTS_CREATION_LOCK)
+#endif /* ! ACE_LACKS_ACE_TOKEN && ACE_HAS_TOKENS_LIBRARY */
+ ACE_PREALLOCATE_OBJECT (ACE_Thread_Mutex,
+ ACE_PROACTOR_EVENT_LOOP_LOCK)
+# endif /* ACE_MT_SAFE */
+ }
+
+ if (this == instance_)
+ {
+ // Hooks for preallocated objects and arrays provided by application.
+ ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS
+ ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS
+
+# if defined (ACE_HAS_TSS_EMULATION)
+ // Initialize the main thread's TS storage.
+ if (!ts_storage_initialized_)
+ {
+ ACE_TSS_Emulation::tss_open (ts_storage_);
+ ts_storage_initialized_ = true;
+ }
+# endif /* ACE_HAS_TSS_EMULATION */
+
+#if defined (ACE_DISABLE_WIN32_ERROR_WINDOWS) && \
+ defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+#if defined (_DEBUG) && (defined (_MSC_VER) || defined (__INTEL_COMPILER))
+ // This will keep the ACE_Assert window
+ _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
+ _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );
+#endif /* _DEBUG && _MSC_VER || __INTEL_COMPILER */
+
+ // The system does not display the critical-error-handler message box
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ // And this will catch all unhandled exceptions.
+ SetUnhandledExceptionFilter (&ACE_UnhandledExceptionFilter);
+#endif /* ACE_DISABLE_WIN32_ERROR_WINDOWS && ACE_WIN32 && !ACE_HAS_WINCE */
+
+
+# if !defined (ACE_LACKS_ACE_SVCCONF)
+ ACE_NEW_RETURN (preallocations_,
+ ACE_Object_Manager_Preallocations,
+ -1);
+# endif /* ! ACE_LACKS_ACE_SVCCONF */
+
+ // Open the main thread's ACE_Log_Msg.
+ if (0 == ACE_LOG_MSG)
+ return -1;
+ }
+
+ // Finally, indicate that the ACE_Object_Manager instance has
+ // been initialized.
+ object_manager_state_ = OBJ_MAN_INITIALIZED;
+
+#if defined (ACE_HAS_TRACE)
+ // Allow tracing again (useful if user does init/fini/init)
+ ACE_Trace::start_tracing ();
+#endif /* ACE_HAS_TRACE */
+
+ return 0;
+ } else {
+ // Had already initialized.
+ return 1;
+ }
+}
+
+#if defined (ACE_HAS_TSS_EMULATION)
+int
+ACE_Object_Manager::init_tss (void)
+{
+ return ACE_Object_Manager::instance ()->init_tss_i ();
+}
+
+int
+ACE_Object_Manager::init_tss_i (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *instance_->internal_lock_, -1));
+
+ if (!ts_storage_initialized_)
+ {
+ ACE_TSS_Emulation::tss_open (ts_storage_);
+ ts_storage_initialized_ = true;
+ }
+
+ return 0;
+}
+
+#endif
+
+ACE_Object_Manager::ACE_Object_Manager (void)
+ // With ACE_HAS_TSS_EMULATION, ts_storage_ is initialized by the call to
+ // ACE_OS::tss_open () in the function body.
+ : exit_info_ ()
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+ , preallocations_ (0)
+ , ace_service_config_sig_handler_ (0)
+#endif /* ! ACE_LACKS_ACE_SVCCONF */
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ , singleton_null_lock_ (0)
+ , singleton_recursive_lock_ (0)
+#endif /* ACE_MT_SAFE */
+#if defined (ACE_HAS_TSS_EMULATION)
+ , ts_storage_initialized_ (false)
+#endif
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_NEW (internal_lock_, ACE_Recursive_Thread_Mutex);
+# endif /* ACE_MT_SAFE */
+
+ // If instance_ was not 0, then another ACE_Object_Manager has
+ // already been instantiated (it is likely to be one initialized by way
+ // of library/DLL loading). Let this one go through construction in
+ // case there really is a good reason for it (like, ACE is a static/archive
+ // library, and this one is the non-static instance (with
+ // ACE_HAS_NONSTATIC_OBJECT_MANAGER, or the user has a good reason for
+ // creating a separate one) but the original one will be the one retrieved
+ // from calls to ACE_Object_Manager::instance().
+
+ // Be sure that no further instances are created via instance ().
+ if (instance_ == 0)
+ instance_ = this;
+
+ init ();
+}
+
+ACE_Object_Manager::~ACE_Object_Manager (void)
+{
+ dynamically_allocated_ = false; // Don't delete this again in fini()
+ fini ();
+}
+
+ACE_Object_Manager *
+ACE_Object_Manager::instance (void)
+{
+ // This function should be called during construction of static
+ // instances, or before any other threads have been created in
+ // the process. So, it's not thread safe.
+
+ if (instance_ == 0)
+ {
+ ACE_Object_Manager *instance_pointer = 0;
+
+ ACE_NEW_RETURN (instance_pointer,
+ ACE_Object_Manager,
+ 0);
+ ACE_ASSERT (instance_pointer == instance_);
+
+ instance_pointer->dynamically_allocated_ = true;
+
+ return instance_pointer;
+ }
+ else
+ return instance_;
+}
+
+int
+ACE_Object_Manager::at_exit_i (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *instance_->internal_lock_, -1));
+
+ if (shutting_down_i ())
+ {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ if (exit_info_.find (object))
+ {
+ // The object has already been registered.
+ errno = EEXIST;
+ return -1;
+ }
+
+ return exit_info_.at_exit_i (object, cleanup_hook, param);
+}
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+int
+ACE_Object_Manager::get_singleton_lock (ACE_Null_Mutex *&lock)
+{
+ if (starting_up () || shutting_down ())
+ {
+ // The preallocated lock has not been constructed yet.
+ // Therefore, the program is single-threaded at this point. Or,
+ // the ACE_Object_Manager instance has been destroyed, so the
+ // preallocated lock is not available. Allocate a lock to use,
+ // for interface compatibility, though there should be no
+ // contention on it.
+ if (ACE_Object_Manager::instance ()->singleton_null_lock_ == 0)
+ {
+ ACE_NEW_RETURN (ACE_Object_Manager::instance ()->
+ singleton_null_lock_,
+ ACE_Cleanup_Adapter<ACE_Null_Mutex>,
+ -1);
+
+ // Can't register with the ACE_Object_Manager here! The
+ // lock's declaration is visible to the ACE_Object_Manager
+ // destructor, so it will clean it up as a special case.
+ }
+
+ if (ACE_Object_Manager::instance ()->singleton_null_lock_ != 0)
+ lock = &ACE_Object_Manager::instance ()->singleton_null_lock_->
+ object ();
+ }
+ else
+ // Use the Object_Manager's preallocated lock.
+ lock = ACE_Managed_Object<ACE_Null_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SINGLETON_NULL_LOCK);
+
+ return 0;
+}
+
+int
+ACE_Object_Manager::get_singleton_lock (ACE_Thread_Mutex *&lock)
+{
+ if (lock == 0)
+ {
+ if (starting_up () || shutting_down ())
+ {
+ // The Object_Manager and its internal lock have not been
+ // constructed yet. Therefore, the program is single-
+ // threaded at this point. Or, the ACE_Object_Manager
+ // instance has been destroyed, so the internal lock is not
+ // available. Either way, we can not use double-checked
+ // locking. So, we'll leak the lock.
+ ACE_NEW_RETURN (lock,
+ ACE_Thread_Mutex,
+ -1);
+ }
+ else
+ {
+ // Allocate a new lock, but use double-checked locking to
+ // ensure that only one thread allocates it.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon,
+ *ACE_Object_Manager::instance ()->
+ internal_lock_,
+ -1));
+
+ if (lock == 0)
+ {
+ ACE_Cleanup_Adapter<ACE_Thread_Mutex> *lock_adapter;
+ ACE_NEW_RETURN (lock_adapter,
+ ACE_Cleanup_Adapter<ACE_Thread_Mutex>,
+ -1);
+ lock = &lock_adapter->object ();
+
+ // Register the lock for destruction at program
+ // termination. This call will cause us to grab the
+ // ACE_Object_Manager::instance ()->internal_lock_
+ // again; that's why it is a recursive lock.
+ ACE_Object_Manager::at_exit (lock_adapter);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_Object_Manager::get_singleton_lock (ACE_Mutex *&lock)
+{
+ if (lock == 0)
+ {
+ if (starting_up () || shutting_down ())
+ {
+ // The Object_Manager and its internal lock have not been
+ // constructed yet. Therefore, the program is single-
+ // threaded at this point. Or, the ACE_Object_Manager
+ // instance has been destroyed, so the internal lock is not
+ // available. Either way, we can not use double-checked
+ // locking. So, we'll leak the lock.
+
+ ACE_NEW_RETURN (lock,
+ ACE_Mutex,
+ -1);
+ }
+ else
+ {
+ // Allocate a new lock, but use double-checked locking to
+ // ensure that only one thread allocates it.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon,
+ *ACE_Object_Manager::instance ()->
+ internal_lock_,
+ -1));
+
+ if (lock == 0)
+ {
+ ACE_Cleanup_Adapter<ACE_Mutex> *lock_adapter;
+ ACE_NEW_RETURN (lock_adapter,
+ ACE_Cleanup_Adapter<ACE_Mutex>,
+ -1);
+ lock = &lock_adapter->object ();
+
+ // Register the lock for destruction at program
+ // termination. This call will cause us to grab the
+ // ACE_Object_Manager::instance ()->internal_lock_
+ // again; that's why it is a recursive lock.
+ ACE_Object_Manager::at_exit (lock_adapter);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_Object_Manager::get_singleton_lock (ACE_Recursive_Thread_Mutex *&lock)
+{
+ if (starting_up () || shutting_down ())
+ {
+ // The preallocated lock has not been constructed yet.
+ // Therefore, the program is single-threaded at this point. Or,
+ // the ACE_Object_Manager instance has been destroyed, so the
+ // preallocated lock is not available. Allocate a lock to use,
+ // for interface compatibility, though there should be no
+ // contention on it.
+ if (ACE_Object_Manager::instance ()->singleton_recursive_lock_ == 0)
+ ACE_NEW_RETURN (ACE_Object_Manager::instance ()->
+ singleton_recursive_lock_,
+ ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex>,
+ -1);
+
+ // Can't register with the ACE_Object_Manager here! The lock's
+ // declaration is visible to the ACE_Object_Manager destructor,
+ // so it will clean it up as a special case.
+
+ if (ACE_Object_Manager::instance ()->singleton_recursive_lock_ != 0)
+ lock = &ACE_Object_Manager::instance ()->singleton_recursive_lock_->
+ object ();
+ }
+ else
+ {
+ // Use the Object_Manager's preallocated lock.
+ lock = ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::
+ get_preallocated_object (ACE_Object_Manager::
+ ACE_SINGLETON_RECURSIVE_THREAD_LOCK);
+ }
+
+ return 0;
+}
+
+int
+ACE_Object_Manager::get_singleton_lock (ACE_RW_Thread_Mutex *&lock)
+{
+ if (lock == 0)
+ {
+ if (starting_up () || shutting_down ())
+ {
+ // The Object_Manager and its internal lock have not been
+ // constructed yet. Therefore, the program is single-
+ // threaded at this point. Or, the ACE_Object_Manager
+ // instance has been destroyed, so the internal lock is not
+ // available. Either way, we can not use double-checked
+ // locking. So, we'll leak the lock.
+
+ ACE_NEW_RETURN (lock,
+ ACE_RW_Thread_Mutex,
+ -1);
+ }
+ else
+ {
+ // Allocate a new lock, but use double-checked locking to
+ // ensure that only one thread allocates it.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon,
+ *ACE_Object_Manager::instance ()->
+ internal_lock_,
+ -1));
+
+ if (lock == 0)
+ {
+ ACE_Cleanup_Adapter<ACE_RW_Thread_Mutex> *lock_adapter;
+ ACE_NEW_RETURN (lock_adapter,
+ ACE_Cleanup_Adapter<ACE_RW_Thread_Mutex>,
+ -1);
+ lock = &lock_adapter->object ();
+
+
+ // Register the lock for destruction at program
+ // termination. This call will cause us to grab the
+ // ACE_Object_Manager::instance ()->internal_lock_
+ // again; that's why it is a recursive lock.
+ ACE_Object_Manager::at_exit (lock_adapter);
+ }
+ }
+ }
+
+ return 0;
+}
+#endif /* ACE_MT_SAFE */
+
+// Clean up an ACE_Object_Manager. There can be instances of this object
+// other than The Instance. This can happen if (on Win32) the ACE DLL
+// causes one to be created, or if a user creates one for some reason.
+// Only The Instance cleans up the static preallocated objects. All objects
+// clean up their per-object information and managed objects.
+int
+ACE_Object_Manager::fini (void)
+{
+ if (shutting_down_i ())
+ // Too late. Or, maybe too early. Either fini () has already
+ // been called, or init () was never called.
+ return object_manager_state_ == OBJ_MAN_SHUT_DOWN ? 1 : -1;
+
+ // No mutex here. Only the main thread should destroy the singleton
+ // ACE_Object_Manager instance.
+
+ // Indicate that this ACE_Object_Manager instance is being
+ // shut down.
+ object_manager_state_ = OBJ_MAN_SHUTTING_DOWN;
+
+ // Call all registered cleanup hooks, in reverse order of
+ // registration.
+ exit_info_.call_hooks ();
+
+ if (this == instance_)
+ {
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+ delete preallocations_;
+ preallocations_ = 0;
+#endif /* ! ACE_LACKS_ACE_SVCCONF */
+
+#if defined (ACE_HAS_TRACE)
+ ACE_Trace::stop_tracing ();
+#endif /* ACE_HAS_TRACE */
+
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+ // Close and possibly delete all service instances in the Service
+ // Repository.
+ ACE_Service_Config::fini_svcs ();
+
+ // Unlink all services in the Service Repository and close/delete
+ // all ACE library services and singletons.
+ ACE_Service_Config::close ();
+#endif /* ! ACE_LACKS_ACE_SVCCONF */
+
+ // This must come after closing ACE_Service_Config, since it will
+ // close down it's dlls--it manages ACE_DLL_Manager.
+ ACE_Framework_Repository::close_singleton ();
+ ACE_DLL_Manager::close_singleton ();
+
+# if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
+ ACE_Thread_Manager::close_singleton ();
+# endif /* ! ACE_THREAD_MANAGER_LACKS_STATICS */
+
+ // Close the main thread's TSS, including its Log_Msg instance.
+ ACE_OS::cleanup_tss (1 /* main thread */);
+
+ //
+ // Note: Do not access Log Msg after this since it is gone
+ //
+
+ // Close the ACE_Allocator.
+ ACE_Allocator::close_singleton ();
+
+#if ! defined (ACE_HAS_STATIC_PREALLOCATION)
+ // Hooks for deletion of preallocated objects and arrays provided by
+ // application.
+ ACE_APPLICATION_PREALLOCATED_ARRAY_DELETIONS
+ ACE_APPLICATION_PREALLOCATED_OBJECT_DELETIONS
+
+ // Cleanup the dynamically preallocated arrays.
+ // (none)
+
+ // Cleanup the dynamically preallocated objects.
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_SYNCH_RW_MUTEX, ACE_FILECACHE_LOCK)
+#if defined (ACE_HAS_THREADS)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_Recursive_Thread_Mutex,
+ ACE_STATIC_OBJECT_LOCK)
+#endif /* ACE_HAS_THREADS */
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_Thread_Mutex,
+ ACE_MT_CORBA_HANDLER_LOCK)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_Thread_Mutex, ACE_DUMP_LOCK)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_Recursive_Thread_Mutex,
+ ACE_SIG_HANDLER_LOCK)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_Null_Mutex,
+ ACE_SINGLETON_NULL_LOCK)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_Recursive_Thread_Mutex,
+ ACE_SINGLETON_RECURSIVE_THREAD_LOCK)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_Thread_Mutex, ACE_THREAD_EXIT_LOCK)
+#if !defined (ACE_LACKS_ACE_TOKEN) && defined (ACE_HAS_TOKENS_LIBRARY)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_TOKEN_CONST::MUTEX,
+ ACE_TOKEN_MANAGER_CREATION_LOCK)
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_TOKEN_CONST::MUTEX,
+ ACE_TOKEN_INVARIANTS_CREATION_LOCK)
+#endif /* ! ACE_LACKS_ACE_TOKEN && ACE_HAS_TOKENS_LIBRARY */
+ ACE_DELETE_PREALLOCATED_OBJECT (ACE_Thread_Mutex,
+ ACE_PROACTOR_EVENT_LOOP_LOCK)
+# endif /* ACE_MT_SAFE */
+#endif /* ! ACE_HAS_STATIC_PREALLOCATION */
+
+#if defined (ACE_HAS_THREADS)
+ ACE_Static_Object_Lock::cleanup_lock ();
+#endif /* ACE_HAS_THREADS */
+ }
+
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+ delete ace_service_config_sig_handler_;
+ ace_service_config_sig_handler_ = 0;
+#endif /* ! ACE_LACKS_ACE_SVCCONF */
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ delete internal_lock_;
+ internal_lock_ = 0;
+
+ delete singleton_null_lock_;
+ singleton_null_lock_ = 0;
+
+ delete singleton_recursive_lock_;
+ singleton_recursive_lock_ = 0;
+#endif /* ACE_MT_SAFE */
+
+ // Indicate that this ACE_Object_Manager instance has been shut down.
+ object_manager_state_ = OBJ_MAN_SHUT_DOWN;
+
+ // Then, ensure that the ACE_OS_Object_Manager gets shut down.
+ if (this == instance_ && ACE_OS_Object_Manager::instance_)
+ ACE_OS_Object_Manager::instance_->fini ();
+
+ if (dynamically_allocated_)
+ {
+ delete this;
+ }
+
+ if (this == instance_)
+ instance_ = 0;
+
+ return 0;
+}
+
+
+#if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
+/**
+ * @class ACE_Object_Manager_Manager
+ *
+ * @brief Ensure that the ACE_Object_Manager gets initialized at program
+ * startup, and destroyed at program termination.
+ *
+ * Without ACE_HAS_NONSTATIC_OBJECT_MANAGER, a static instance of this
+ * class is created. Therefore, it gets created before main ()
+ * is called. And it gets destroyed after main () returns.
+ */
+class ACE_Export ACE_Object_Manager_Manager
+{
+public:
+ ACE_Object_Manager_Manager (void);
+ ~ACE_Object_Manager_Manager (void);
+
+private:
+ /// Save the main thread ID, so that destruction can be suppressed.
+ ACE_thread_t saved_main_thread_id_;
+};
+
+ACE_Object_Manager_Manager::ACE_Object_Manager_Manager (void)
+ : saved_main_thread_id_ (ACE_OS::thr_self ())
+{
+ // Ensure that the Object_Manager gets initialized before any
+ // application threads have been spawned. Because this will be called
+ // during construction of static objects, that should always be the
+ // case.
+ (void) ACE_Object_Manager::instance ();
+}
+
+ACE_Object_Manager_Manager::~ACE_Object_Manager_Manager (void)
+{
+ if (ACE_OS::thr_equal (ACE_OS::thr_self (),
+ saved_main_thread_id_))
+ {
+ delete ACE_Object_Manager::instance_;
+ ACE_Object_Manager::instance_ = 0;
+ }
+ // else if this destructor is not called by the main thread, then do
+ // not delete the ACE_Object_Manager. That causes problems, on
+ // WIN32 at least.
+}
+
+static ACE_Object_Manager_Manager ACE_Object_Manager_Manager_instance;
+#endif /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER */
+
+#if defined (ACE_HAS_THREADS)
+
+// hack to get around errors while compiling using split-cpp
+#if !defined (ACE_IS_SPLITTING)
+// This is global so that it doesn't have to be declared in the header
+// file. That would cause nasty circular include problems.
+typedef ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex> ACE_Static_Object_Lock_Type;
+static ACE_Static_Object_Lock_Type *ACE_Static_Object_Lock_lock = 0;
+#endif /* ! ACE_IS_SPLITTING */
+
+// ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK isn't (currently) used by ACE.
+// But, applications may find it useful for avoiding recursive calls
+// if they have overridden operator new. Thanks to Jody Hagins
+// <jody@atdesk.com> for contributing it.
+
+ACE_Recursive_Thread_Mutex *
+ACE_Static_Object_Lock::instance (void)
+{
+ if (ACE_Object_Manager::starting_up () ||
+ ACE_Object_Manager::shutting_down ())
+ {
+ // The preallocated ACE_STATIC_OBJECT_LOCK has not been
+ // constructed yet. Therefore, the program is single-threaded
+ // at this point. Or, the ACE_Object_Manager instance has been
+ // destroyed, so the preallocated lock is not available.
+ // Allocate a lock to use, for interface compatibility, though
+ // there should be no contention on it.
+ if (ACE_Static_Object_Lock_lock == 0)
+ {
+# if defined (ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK)
+ // Allocate a buffer with malloc, and then use placement
+ // new for the object, on the malloc'd buffer.
+ void *buffer =
+ ACE_OS::malloc (sizeof (*ACE_Static_Object_Lock_lock));
+ if (buffer == 0)
+ {
+ return 0;
+ }
+ // do not use ACE_NEW macros for placement new
+ ACE_Static_Object_Lock_lock = new (buffer)
+ ACE_Static_Object_Lock_Type ();
+
+# else /* ! ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK */
+ ACE_NEW_RETURN (ACE_Static_Object_Lock_lock,
+ ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex>,
+ 0);
+# endif /* ! ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK */
+ }
+
+ // Can't register with the ACE_Object_Manager here! The lock's
+ // declaration is visible to the ACE_Object_Manager destructor,
+ // so it will clean it up as a special case.
+
+ return &ACE_Static_Object_Lock_lock->object ();
+ }
+ else
+ // Return the preallocated ACE_STATIC_OBJECT_LOCK.
+ return
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_STATIC_OBJECT_LOCK);
+}
+
+void
+ACE_Static_Object_Lock::cleanup_lock (void)
+{
+# if defined(ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK)
+ // It was malloc'd, so we need to explicitly call the dtor
+ // and then free the memory.
+ ACE_DES_FREE (ACE_Static_Object_Lock_lock,
+ ACE_OS::free,
+ ACE_Static_Object_Lock_Type);
+# else /* ! ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK */
+ delete ACE_Static_Object_Lock_lock;
+# endif /* ! ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK */
+ ACE_Static_Object_Lock_lock = 0;
+}
+#endif /* ACE_HAS_THREADS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Object_Manager.h b/ACE/ace/Object_Manager.h
new file mode 100644
index 00000000000..8481aa15e99
--- /dev/null
+++ b/ACE/ace/Object_Manager.h
@@ -0,0 +1,466 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Object_Manager.h
+ *
+ * $Id$
+ *
+ * @author David L. Levine <levine@cs.wustl.edu>
+ * @author Matthias Kerkhoff
+ * @author Per Andersson
+ */
+//=============================================================================
+
+#ifndef ACE_OBJECT_MANAGER_H
+#define ACE_OBJECT_MANAGER_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/Object_Manager_Base.h"
+#include "ace/Global_Macros.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+class ACE_Object_Manager_Preallocations;
+class ACE_Sig_Adapter;
+class ACE_Sig_Set;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ class ACE_Mutex;
+ class ACE_Null_Mutex;
+ class ACE_Thread_Mutex;
+ class ACE_Recursive_Thread_Mutex;
+ class ACE_RW_Thread_Mutex;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# include "ace/Recursive_Thread_Mutex.h"
+#endif /* ACE_MT_SAFE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// only used by ACE_OS_Object_Manager::ctor
+# if defined (ACE_WIN32)
+// Default WIN32 structured exception handler.
+int ACE_SEH_Default_Exception_Selector (void *);
+int ACE_SEH_Default_Exception_Handler (void *);
+# endif /* ACE_WIN32 */
+
+class ACE_Cleanup_Info_Node;
+template <class T> class ACE_Cleanup_Adapter;
+
+// Configuration parameters.
+#if !defined (ACE_MAX_MANAGED_OBJECTS)
+# define ACE_MAX_MANAGED_OBJECTS 128
+#endif /* ! ACE_MAX_MANAGED_OBJECTS */
+
+#if !defined (ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS)
+# define ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS
+#endif /* ! ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS */
+
+#if !defined (ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS)
+# define ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS
+#endif /* ! ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS */
+
+/**
+ * @class ACE_Object_Manager
+ *
+ * @brief Manager for ACE library services and singleton cleanup.
+ *
+ * The ACE_Object_Manager manages cleanup of objects, typically
+ * singletons, at program termination. In addition to managing
+ * the cleanup of the ACE library, it provides an interface for
+ * application to register objects to be cleaned up.
+ * This class also shuts down ACE library services, so that they
+ * can reclaim their storage, at program termination. It works
+ * by creating a static instance whose destructor gets called
+ * along with those of all other static objects. Hooks are
+ * provided for application code to register objects and arrays
+ * for cleanup, e.g., destruction. The order of such cleanup
+ * calls is in the reverse order of registration, i.e., that
+ * last object/array to register gets cleaned up first.
+ * The ACE_Object_Manager API includes ACE_Managed_Object. That
+ * class is contained in a separate file because it is a
+ * template class, and some compilers require that template and
+ * non-template class definitions appear in separate files.
+ * Please see ace/Managed_Object.h for a description of that
+ * part of the API. In summary, ACE_Managed_Object provides two
+ * adapters, the ACE_Cleanup_Adapter and ACE_Managed_Object
+ * template classes for adapting objects of any type to be
+ * easily managed by the ACE_Object_Manager. There are several
+ * mechanisms for adapting objects and arrays for cleanup at
+ * program termination, in roughly increasing order of ease-of-use:
+ * 1) Derive the object's class from ACE_Cleanup.
+ * 2) Allow the ACE_Object_Manager to both dynamically allocate
+ * and deallocate the object.
+ * 3) Provide an <ACE_CLEANUP_FUNC> cleanup hook for the object or
+ * array.
+ * 4) Allow the ACE_Object_Manager to both preallocate the object
+ * or array, either statically in global data or dynamically on
+ * the heap, when its singleton instance is construction.
+ *
+ * There are also several mechanisms for registering objects and
+ * arrays for cleanup. In decreasing order of flexibility and
+ * complexity (with the exception of the last mechanism):
+ *
+ * 1) ACE_Object_Manager::at_exit (void *object,
+ * ACE_CLEANUP_FUNC cleanup_hook,
+ * void *param);
+ * can be used to register any object or array for any
+ * cleanup activity at program termination.
+ * 2) ACE_Object_Manager::at_exit (ACE_Cleanup *object,
+ * void *param = 0);
+ * can be used to register an ACE_Cleanup object
+ * for any cleanup activity at program termination.
+ * The final mechanism is not general purpose, but can only
+ * be used to allocate objects and arrays at program startup:
+ * 3) ACE_Managed_Object::get_preallocated_object
+ * (ACE_Object_Manager::Preallocated_Object id);
+ * and
+ * ACE_Managed_Object::get_preallocated_array
+ * (ACE_Object_Manager::Preallocated_Array id);
+ * can only be used to allocate objects at program startup,
+ * either in global data or on the heap (selected at compile
+ * time). These are intended to replace static locks, etc.
+ * Instead of creating a static ACE_Object_Manager instance, one
+ * can alternatively be created on the stack of the main program
+ * thread. It is created just after entry to ::main (int, char
+ * *[]), and before any existing code in that function is
+ * executed. To enable this alternative, add #define
+ * ACE_HAS_NONSTATIC_OBJECT_MANAGER before including the platform
+ * specific config-* file in ace/config.h prior to
+ * building the ACE library and your applications. This #define
+ * is enabled in some config files that are supplied with ACE.
+ *
+ * To ensure a static object manager is used, #undef
+ * ACE_HAS_NONSTATIC_OBJECT_MANAGER *after* including the platform
+ * specific config-* file.
+ * Note that the ACE_Object_Manager _must_ be created before
+ * any threads are spawned by the program.
+ * If ACE_HAS_NONSTATIC_OBJECT_MANAGER is not #defined, the ACE
+ * library creates a static, singleton ACE_Object_Manager instance.
+ * The instance is placed in global program data, and constructed
+ * via a static object constructor. If ACE_HAS_NONSTATIC_OBJECT_MANAGER
+ * is #defined, the ACE_Object_Manager instance is created on the stack
+ * of the main program thread, as noted above.
+ *
+ * With ACE_HAS_NONSTATIC_OBJECT_MANAGER enabled, the ACE
+ * library has no static objects that require destruction.
+ * However, there are two drawbacks to using it:
+ * 1) main (int, char *[]) must be declared with arguments, even
+ * if they're not used. All of ACE is converted to this, so
+ * just applications have to be concerned with it.
+ * 2) If there any static objects that depend on those that are
+ * cleaned up by the Object_Manager, they'll get cleaned up too
+ * late. The ACE tests do not violate this requirement.
+ * However, applications may have trouble with it.
+ * NOTE on the use of <::exit> -- <::exit> does not destroy
+ * automatic objects. Therefore, if
+ * ACE_HAS_NONSTATIC_OBJECT_MANAGER is enabled, the
+ * ACE_Object_Manager instance will *not* be destroyed if
+ * <::exit> is called! However, <ACE_OS::exit> will properly
+ * destroy the ACE_Object_Manager. It is highly recommended
+ * that <ACE_OS::exit> be used instead of <::exit>.
+ *
+ * However, <::exit> and <ACE_OS::exit> are tricky to use
+ * properly, especially in multithread programs. It is much
+ * safer to throw an exception (or simulate that effect) that
+ * will be caught by <main> instead of calling exit. Then,
+ * <main> can perform any necessary application-specific cleanup
+ * and return the status value. In addition, it's usually best
+ * to avoid calling <::exit> and <ACE_OS::exit> from threads
+ * other than the main thread. Thanks to Jeff Greif
+ * <jmg@trivida.com> for pointing out that <::exit> doesn't
+ * destroy automatic objects, and for developing the
+ * recommendations in this paragraph.
+ *
+ * Instead of creating a static ACE_Object_Manager, or letting
+ * ACE create it on the stack of <main> for you, another
+ * alternative is to #define
+ * ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER. With that
+ * #define, the application must create the ACE_Object_Manager.
+ * The recommended way is to call <ACE::init> at the start of
+ * the program, and call <ACE::fini> at the end. Alternatively,
+ * the application could explicity construct an
+ * ACE_Object_Manager.
+ */
+class ACE_Export ACE_Object_Manager : public ACE_Object_Manager_Base
+{
+
+public:
+ /**
+ * Explicitly initialize (construct the singleton instance of) the
+ * ACE_Object_Manager. Returns 0 on success, -1 on failure, and 1
+ * if it had already been called.
+ */
+ virtual int init (void);
+
+ /**
+ * Explicitly destroy the singleton instance of the
+ * ACE_Object_Manager. Returns 0 on success, -1 on failure, and 1
+ * if it had already been called.
+ */
+ virtual int fini (void);
+
+ /**
+ * Returns 1 before the ACE_Object_Manager has been constructed.
+ * This flag can be used to determine if the program is constructing
+ * static objects. If no static object spawns any threads, the
+ * program will be single-threaded when this flag returns 1. (Note
+ * that the program still might construct some static objects when
+ * this flag returns 0, if ACE_HAS_NONSTATIC_OBJECT_MANAGER is not
+ * defined.)
+ */
+ static int starting_up (void);
+
+ /**
+ * Returns 1 after the ACE_Object_Manager has been destroyed. This
+ * flag can be used to determine if the program is in the midst of
+ * destroying static objects. (Note that the program might destroy
+ * some static objects before this flag can return 1, if
+ * ACE_HAS_NONSTATIC_OBJECT_MANAGER is not defined.)
+ */
+ static int shutting_down (void);
+
+ /**
+ * Register an ACE_Cleanup object for cleanup at process
+ * termination. The object is deleted via the
+ * <ace_cleanup_destroyer>. If you need more flexiblity, see the
+ * <other at_exit> method below. For OS's that do not have
+ * processes, cleanup takes place at the end of <main>. Returns 0
+ * on success. On failure, returns -1 and sets errno to: EAGAIN if
+ * shutting down, ENOMEM if insufficient virtual memory, or EEXIST
+ * if the object (or array) had already been registered.
+ */
+ static int at_exit (ACE_Cleanup *object, void *param = 0);
+
+#if defined (ACE_HAS_TSS_EMULATION)
+ static int init_tss (void);
+ int init_tss_i (void);
+#endif
+
+ /**
+ * Register an object (or array) for cleanup at process termination.
+ * "cleanup_hook" points to a (global, or static member) function
+ * that is called for the object or array when it to be destroyed.
+ * It may perform any necessary cleanup specific for that object or
+ * its class. "param" is passed as the second parameter to the
+ * "cleanup_hook" function; the first parameter is the object (or
+ * array) to be destroyed. "cleanup_hook", for example, may delete
+ * the object (or array). For OS's that do not have processes, this
+ * function is the same as <at_thread_exit>. Returns 0 on success.
+ * On failure, returns -1 and sets errno to: EAGAIN if shutting
+ * down, ENOMEM if insufficient virtual memory, or EEXIST if the
+ * object (or array) had already been registered.
+ */
+ static int at_exit (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param);
+
+#if 0 /* not implemented yet */
+ /// Similar to <at_exit>, except that the cleanup_hook is called
+ /// when the current thread exits instead of when the program terminates.
+ static int at_thread_exit (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param);
+#endif /* 0 */
+
+ /// Unique identifiers for preallocated objects. Please see
+ /// ace/Managed_Object.h for information on accessing preallocated
+ /// objects.
+ enum Preallocated_Object
+ {
+ ACE_FILECACHE_LOCK,
+#if defined (ACE_HAS_THREADS)
+ ACE_STATIC_OBJECT_LOCK,
+#endif /* ACE_HAS_THREADS */
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_MT_CORBA_HANDLER_LOCK,
+ ACE_DUMP_LOCK,
+ ACE_SIG_HANDLER_LOCK,
+ ACE_SINGLETON_NULL_LOCK,
+ ACE_SINGLETON_RECURSIVE_THREAD_LOCK,
+ ACE_THREAD_EXIT_LOCK,
+#if !defined (ACE_LACKS_ACE_TOKEN)
+ ACE_TOKEN_MANAGER_CREATION_LOCK,
+ ACE_TOKEN_INVARIANTS_CREATION_LOCK,
+#endif /* ! ACE_LACKS_ACE_TOKEN */
+ ACE_PROACTOR_EVENT_LOOP_LOCK,
+#endif /* ACE_MT_SAFE */
+
+ // Hook for preallocated objects provided by application.
+ ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS
+
+ ACE_PREALLOCATED_OBJECTS // This enum value must be last!
+ };
+
+ /// Unique identifiers for preallocated arrays. Please see
+ /// ace/Managed_Object.h for information on accessing preallocated
+ /// arrays.
+ enum Preallocated_Array
+ {
+ /// There currently are no preallocated arrays in the ACE
+ /// library. If the application doesn't have any, make sure
+ /// the the preallocated_array size is at least one by declaring
+ /// this dummy . . .
+ ACE_EMPTY_PREALLOCATED_ARRAY,
+
+ /// Hook for preallocated arrays provided by application.
+ ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS
+
+ ACE_PREALLOCATED_ARRAYS // This enum value must be last!
+ };
+
+ /**
+ * @deprecated Accesses a default signal set used, for example,
+ * in ACE_Sig_Guard methods.
+ * Deprecated: use ACE_Object_Manager::default_mask () instead.
+ */
+ static ACE_Sig_Set &default_mask (void);
+
+private:
+ /// For at_exit support.
+ ACE_OS_Exit_Info exit_info_;
+
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+ /// Preallocated objects collection.
+ ACE_Object_Manager_Preallocations *preallocations_;
+
+ /// ACE_Service_Config signal handler.
+ ACE_Sig_Adapter *ace_service_config_sig_handler_;
+#endif /* ! ACE_LACKS_ACE_SVCCONF */
+
+ /// Register an object or array for deletion at program termination.
+ /// See description of static version above for return values.
+ int at_exit_i (void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param);
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+public:
+ // = The <get_singleton_lock> accessors are for internal
+ // use by ACE_Singleton _only_.
+
+ /**
+ * Accesses an ACE_Null_Mutex to be used for construction of
+ * ACE_Singletons. Returns 0, and the lock in the argument, on
+ * success; returns -1 on failure.
+ */
+ static int get_singleton_lock (ACE_Null_Mutex *&);
+
+ /**
+ * Accesses a non-recursive ACE_Thread_Mutex to be used for
+ * construction of ACE_Singletons. Returns 0, and the lock in the
+ * argument, on success; returns -1 on failure.
+ */
+ static int get_singleton_lock (ACE_Thread_Mutex *&);
+
+ /**
+ * Accesses a non-recursive ACE_Mutex to be used for construction
+ * of ACE_Singletons. Returns 0, and the lock in the argument, on
+ * success; returns -1 on failure.
+ */
+ static int get_singleton_lock (ACE_Mutex *&);
+
+ /**
+ * Accesses a recursive ACE_Recursive_Thread_Mutex to be used for
+ * construction of ACE_Singletons. Returns 0, and the lock in the
+ * argument, on success; returns -1 on failure.
+ */
+ static int get_singleton_lock (ACE_Recursive_Thread_Mutex *&);
+
+ /**
+ * Accesses a readers/writer ACE_RW_Thread_Mutex to be used for
+ * construction of ACE_Singletons. Returns 0, and the lock in the
+ * argument, on success; returns -1 on failure.
+ */
+ static int get_singleton_lock (ACE_RW_Thread_Mutex *&);
+#endif /* ACE_MT_SAFE */
+
+public:
+ // For internal use only by ACE_Managed_Objects.
+
+ /**
+ * Accessor to singleton instance. Because static member functions
+ * are provided in the interface, this should not be public. However,
+ * it is public so that ACE_Managed_Object<TYPE> can access it.
+ */
+ static ACE_Object_Manager *instance (void);
+
+ /// Table of preallocated objects.
+ static void *preallocated_object[ACE_PREALLOCATED_OBJECTS];
+
+ /// Table of preallocated arrays.
+ static void *preallocated_array[ACE_PREALLOCATED_ARRAYS];
+
+public:
+ // Application code should not use these explicitly, so they're
+ // hidden here. They're public so that the ACE_Object_Manager can
+ // be constructed/destructed in <main> with
+ // ACE_HAS_NONSTATIC_OBJECT_MANAGER.
+ ACE_Object_Manager (void);
+ ~ACE_Object_Manager (void);
+
+private:
+ /// Singleton pointer.
+ static ACE_Object_Manager *instance_;
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ /// Lock that is used to guard internal structures.
+ ACE_Recursive_Thread_Mutex *internal_lock_;
+
+ /// Null lock for guarding singleton creation.
+ ACE_Cleanup_Adapter<ACE_Null_Mutex> *singleton_null_lock_;
+
+ /// Lock for guarding singleton creation, when Object_Manager
+ /// hasn't been started up, or has already been shut down.
+ ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex> *singleton_recursive_lock_;
+#endif /* ACE_MT_SAFE */
+
+#if defined (ACE_HAS_TSS_EMULATION)
+ // Main thread's thread-specific storage array.
+ void *ts_storage_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX];
+ bool ts_storage_initialized_;
+#endif /* ACE_HAS_TSS_EMULATION */
+
+#if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
+ friend class ACE_Object_Manager_Manager;
+#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */
+
+ // Disallow copying by not implementing the following . . .
+ ACE_Object_Manager (const ACE_Object_Manager &);
+ ACE_Object_Manager &operator= (const ACE_Object_Manager &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include "ace/Static_Object_Lock.h"
+
+#if defined (__ACE_INLINE__)
+#include "ace/Object_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Managed_Object.h"
+
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+// We can't use the ACE_SVC_FACTORY_DECLARE macro here because this
+// needs to be in the ACE_Export context rather than the
+// ACE_Svc_Export context.
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_Service_Object;
+ACE_END_VERSIONED_NAMESPACE_DECL
+ACE_FACTORY_DECLARE (ACE, ACE_Service_Manager)
+#endif /* ! ACE_LACKS_ACE_SVCCONF */
+
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OBJECT_MANAGER_H */
diff --git a/ACE/ace/Object_Manager.inl b/ACE/ace/Object_Manager.inl
new file mode 100644
index 00000000000..bb95a485fdc
--- /dev/null
+++ b/ACE/ace/Object_Manager.inl
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+int
+ACE_Object_Manager::at_exit (ACE_Cleanup *object,
+ void *param)
+{
+ return ACE_Object_Manager::instance ()->at_exit_i (
+ object,
+ (ACE_CLEANUP_FUNC) ACE_CLEANUP_DESTROYER_NAME,
+ param);
+}
+
+ACE_INLINE
+int
+ACE_Object_Manager::at_exit (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param)
+{
+ return ACE_Object_Manager::instance ()->at_exit_i (
+ object,
+ cleanup_hook,
+ param);
+}
+
+ACE_INLINE
+ACE_Sig_Set &
+ACE_Object_Manager::default_mask (void)
+{
+ // A safe cast, but this static method shouldn't be used anyways.
+ // Use ACE_Object_Manager::default_mask () instead.
+ return
+ *reinterpret_cast<ACE_Sig_Set *> (ACE_OS_Object_Manager::default_mask ());
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Object_Manager_Base.cpp b/ACE/ace/Object_Manager_Base.cpp
new file mode 100644
index 00000000000..866f999871b
--- /dev/null
+++ b/ACE/ace/Object_Manager_Base.cpp
@@ -0,0 +1,506 @@
+// $Id$
+
+#include "ace/Object_Manager_Base.h"
+
+ACE_RCSID(ace, Object_Manager_Base, "$Id$")
+
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_Thread.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/OS_NS_stdio.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+int ACE_SEH_Default_Exception_Selector (void *)
+{
+#if 0
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Win32 structured exception exiting thread\n")));
+#endif /* 0 */
+ // this is only windows and only used here,
+ // defined in ace/config-win32-common.h.
+ return (DWORD) ACE_SEH_DEFAULT_EXCEPTION_HANDLING_ACTION;
+}
+
+int ACE_SEH_Default_Exception_Handler (void *)
+{
+ return 0;
+}
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+# define ACE_OS_PREALLOCATE_OBJECT(TYPE, ID)\
+ {\
+ TYPE *obj_p = 0;\
+ ACE_NEW_RETURN (obj_p, TYPE, -1);\
+ preallocated_object[ID] = (void *) obj_p;\
+ }
+# define ACE_OS_DELETE_PREALLOCATED_OBJECT(TYPE, ID)\
+ delete (TYPE *) preallocated_object[ID];\
+ preallocated_object[ID] = 0;
+
+ACE_Object_Manager_Base::ACE_Object_Manager_Base (void)
+ : object_manager_state_ (OBJ_MAN_UNINITIALIZED)
+ , dynamically_allocated_ (false)
+ , next_ (0)
+{
+}
+
+ACE_Object_Manager_Base::~ACE_Object_Manager_Base (void)
+{
+#if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
+ // Clear the flag so that fini () doesn't delete again.
+ dynamically_allocated_ = false;
+#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */
+}
+
+int
+ACE_Object_Manager_Base::starting_up_i ()
+{
+ return object_manager_state_ < OBJ_MAN_INITIALIZED;
+}
+
+int
+ACE_Object_Manager_Base::shutting_down_i ()
+{
+ return object_manager_state_ > OBJ_MAN_INITIALIZED;
+}
+
+/*****************************************************************************/
+
+extern "C"
+void
+ACE_OS_Object_Manager_Internal_Exit_Hook (void)
+{
+ if (ACE_OS_Object_Manager::instance_)
+ ACE_OS_Object_Manager::instance ()->fini ();
+}
+
+ACE_OS_Object_Manager *ACE_OS_Object_Manager::instance_ = 0;
+
+void *ACE_OS_Object_Manager::preallocated_object[
+ ACE_OS_Object_Manager::ACE_OS_PREALLOCATED_OBJECTS] = { 0 };
+
+ACE_OS_Object_Manager::ACE_OS_Object_Manager (void)
+ // default_mask_ isn't initialized, because it's defined by <init>.
+ : thread_hook_ (0)
+ , exit_info_ ()
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , seh_except_selector_ (ACE_SEH_Default_Exception_Selector)
+ , seh_except_handler_ (ACE_SEH_Default_Exception_Handler)
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+{
+ // If instance_ was not 0, then another ACE_OS_Object_Manager has
+ // already been instantiated (it is likely to be one initialized by
+ // way of library/DLL loading). Let this one go through
+ // construction in case there really is a good reason for it (like,
+ // ACE is a static/archive library, and this one is the non-static
+ // instance (with ACE_HAS_NONSTATIC_OBJECT_MANAGER, or the user has
+ // a good reason for creating a separate one) but the original one
+ // will be the one retrieved from calls to
+ // ACE_Object_Manager::instance().
+
+ // Be sure that no further instances are created via instance ().
+ if (instance_ == 0)
+ instance_ = this;
+
+ init ();
+}
+
+ACE_OS_Object_Manager::~ACE_OS_Object_Manager (void)
+{
+ dynamically_allocated_ = false; // Don't delete this again in fini()
+ fini ();
+}
+
+sigset_t *
+ACE_OS_Object_Manager::default_mask (void)
+{
+ return ACE_OS_Object_Manager::instance ()->default_mask_;
+}
+
+ACE_Thread_Hook *
+ACE_OS_Object_Manager::thread_hook (void)
+{
+ return ACE_OS_Object_Manager::instance ()->thread_hook_;
+}
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ACE_SEH_EXCEPT_HANDLER
+ACE_OS_Object_Manager::seh_except_selector (void)
+{
+ return ACE_OS_Object_Manager::instance ()->seh_except_selector_;
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_OS_Object_Manager::seh_except_selector (ACE_SEH_EXCEPT_HANDLER n)
+{
+ ACE_OS_Object_Manager *instance =
+ ACE_OS_Object_Manager::instance ();
+
+ ACE_SEH_EXCEPT_HANDLER retv = instance->seh_except_selector_;
+ instance->seh_except_selector_ = n;
+ return retv;
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_OS_Object_Manager::seh_except_handler (void)
+{
+ return ACE_OS_Object_Manager::instance ()->seh_except_handler_;
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_OS_Object_Manager::seh_except_handler (ACE_SEH_EXCEPT_HANDLER n)
+{
+ ACE_OS_Object_Manager *instance =
+ ACE_OS_Object_Manager::instance ();
+
+ ACE_SEH_EXCEPT_HANDLER retv = instance->seh_except_handler_;
+ instance->seh_except_handler_ = n;
+ return retv;
+}
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ACE_Thread_Hook *
+ACE_OS_Object_Manager::thread_hook (ACE_Thread_Hook *new_thread_hook)
+{
+ ACE_OS_Object_Manager *os_om = ACE_OS_Object_Manager::instance ();
+ ACE_Thread_Hook *old_hook = os_om->thread_hook_;
+ os_om->thread_hook_ = new_thread_hook;
+ return old_hook;
+}
+
+ACE_OS_Object_Manager *
+ACE_OS_Object_Manager::instance (void)
+{
+ // This function should be called during construction of static
+ // instances, or before any other threads have been created in the
+ // process. So, it's not thread safe.
+
+ if (instance_ == 0)
+ {
+ ACE_OS_Object_Manager *instance_pointer = 0;
+
+ ACE_NEW_RETURN (instance_pointer,
+ ACE_OS_Object_Manager,
+ 0);
+ // I (coryan) removed it, using asserts in the OS layer
+ // brings down the Log msg stuff
+ // ACE_ASSERT (instance_pointer == instance_);
+
+ instance_pointer->dynamically_allocated_ = true;
+
+ }
+
+ return instance_;
+}
+
+int
+ACE_OS_Object_Manager::init (void)
+{
+ if (starting_up_i ())
+ {
+ // First, indicate that this ACE_OS_Object_Manager instance is being
+ // initialized.
+ object_manager_state_ = OBJ_MAN_INITIALIZING;
+
+ if (this == instance_)
+ {
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
+ ACE_CE_Errno::init ();
+# endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
+ ACE_OS_PREALLOCATE_OBJECT (ACE_thread_mutex_t, ACE_OS_MONITOR_LOCK)
+ if (ACE_OS::thread_mutex_init
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_OS_MONITOR_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_OS_MONITOR_LOCK"));
+ ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t,
+ ACE_TSS_CLEANUP_LOCK)
+ if (ACE_OS::recursive_mutex_init
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_recursive_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_TSS_CLEANUP_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_TSS_CLEANUP_LOCK"));
+ ACE_OS_PREALLOCATE_OBJECT (ACE_thread_mutex_t,
+ ACE_LOG_MSG_INSTANCE_LOCK)
+ if (ACE_OS::thread_mutex_init
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_LOG_MSG_INSTANCE_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_LOG_MSG_INSTANCE_LOCK"));
+# if defined (ACE_HAS_TSS_EMULATION)
+ ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t,
+ ACE_TSS_KEY_LOCK)
+ if (ACE_OS::recursive_mutex_init
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_recursive_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_TSS_KEY_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_TSS_KEY_LOCK"));
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t,
+ ACE_TSS_BASE_LOCK)
+ if (ACE_OS::recursive_mutex_init
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_recursive_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_TSS_BASE_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_TSS_BASE_LOCK"));
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+# endif /* ACE_HAS_TSS_EMULATION */
+# endif /* ACE_MT_SAFE */
+
+ // Open Winsock (no-op on other platforms).
+ ACE_OS::socket_init (ACE_WSOCK_VERSION);
+
+ // Register the exit hook, for use by ACE_OS::exit ().
+ ACE_OS::set_exit_hook (&ACE_OS_Object_Manager_Internal_Exit_Hook);
+ }
+
+ ACE_NEW_RETURN (default_mask_, sigset_t, -1);
+ ACE_OS::sigfillset (default_mask_);
+
+ // Finally, indicate that the ACE_OS_Object_Manager instance has
+ // been initialized.
+ object_manager_state_ = OBJ_MAN_INITIALIZED;
+
+# if defined (ACE_WIN32)
+ ACE_OS::win32_versioninfo_.dwOSVersionInfoSize =
+ sizeof (ACE_TEXT_OSVERSIONINFO);
+ ACE_TEXT_GetVersionEx (&ACE_OS::win32_versioninfo_);
+# endif /* ACE_WIN32 */
+ return 0;
+ } else {
+ // Had already initialized.
+ return 1;
+ }
+}
+
+// Clean up an ACE_OS_Object_Manager. There can be instances of this object
+// other than The Instance. This can happen if a user creates one for some
+// reason. All objects clean up their per-object information and managed
+// objects, but only The Instance cleans up the static preallocated objects.
+int
+ACE_OS_Object_Manager::fini (void)
+{
+ if (instance_ == 0 || shutting_down_i ())
+ // Too late. Or, maybe too early. Either fini () has already
+ // been called, or init () was never called.
+ return object_manager_state_ == OBJ_MAN_SHUT_DOWN ? 1 : -1;
+
+ // No mutex here. Only the main thread should destroy the singleton
+ // ACE_OS_Object_Manager instance.
+
+ // Indicate that the ACE_OS_Object_Manager instance is being shut
+ // down. This object manager should be the last one to be shut
+ // down.
+ object_manager_state_ = OBJ_MAN_SHUTTING_DOWN;
+
+ // If another Object_Manager has registered for termination, do it.
+ if (next_)
+ {
+ next_->fini ();
+ next_ = 0; // Protect against recursive calls.
+ }
+
+ // Call all registered cleanup hooks, in reverse order of
+ // registration.
+ exit_info_.call_hooks ();
+
+ // Only clean up preallocated objects when the singleton Instance is being
+ // destroyed.
+ if (this == instance_)
+ {
+ // Close down Winsock (no-op on other platforms).
+ ACE_OS::socket_fini ();
+
+#if ! defined (ACE_HAS_STATIC_PREALLOCATION)
+ // Cleanup the dynamically preallocated objects.
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
+ if (ACE_OS::thread_mutex_destroy
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_OS_MONITOR_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_OS_MONITOR_LOCK"));
+# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
+ ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_thread_mutex_t,
+ ACE_OS_MONITOR_LOCK)
+# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
+ if (ACE_OS::recursive_mutex_destroy
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_recursive_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_TSS_CLEANUP_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_TSS_CLEANUP_LOCK"));
+# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
+ ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t,
+ ACE_TSS_CLEANUP_LOCK)
+# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
+ if (ACE_OS::thread_mutex_destroy
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object [ACE_LOG_MSG_INSTANCE_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_LOG_MSG_INSTANCE_LOCK "));
+# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
+ ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_thread_mutex_t,
+ ACE_LOG_MSG_INSTANCE_LOCK)
+# if defined (ACE_HAS_TSS_EMULATION)
+# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
+ if (ACE_OS::recursive_mutex_destroy
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_recursive_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_TSS_KEY_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_TSS_KEY_LOCK"));
+# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
+ ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t,
+ ACE_TSS_KEY_LOCK)
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
+ if (ACE_OS::recursive_mutex_destroy
+ // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
+ (reinterpret_cast <ACE_recursive_thread_mutex_t *> (ACE_OS_Object_Manager::preallocated_object[ACE_TSS_BASE_LOCK])) != 0)
+ ACE_OS_Object_Manager::print_error_message (
+ __LINE__, ACE_TEXT ("ACE_TSS_BASE_LOCK"));
+# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
+ ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t,
+ ACE_TSS_BASE_LOCK)
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+# endif /* ACE_HAS_TSS_EMULATION */
+# if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
+ ACE_CE_Errno::fini ();
+# endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
+# endif /* ACE_MT_SAFE */
+#endif /* ! ACE_HAS_STATIC_PREALLOCATION */
+ }
+
+ delete default_mask_;
+ default_mask_ = 0;
+
+ // Indicate that this ACE_OS_Object_Manager instance has been shut down.
+ object_manager_state_ = OBJ_MAN_SHUT_DOWN;
+
+ if (dynamically_allocated_)
+ {
+ delete this;
+ }
+
+ if (this == instance_)
+ instance_ = 0;
+
+ return 0;
+}
+
+int ace_exit_hook_marker = 0;
+
+int
+ACE_OS_Object_Manager::at_exit (ACE_EXIT_HOOK func)
+{
+ return exit_info_.at_exit_i (&ace_exit_hook_marker,
+ reinterpret_cast <ACE_CLEANUP_FUNC> (func),
+ 0);
+}
+
+void
+ACE_OS_Object_Manager::print_error_message (unsigned int line_number,
+ const ACE_TCHAR *message)
+{
+ // To avoid duplication of these const strings in OS.o.
+#if !defined (ACE_HAS_WINCE)
+ fprintf (stderr, "ace/Object_Manager_Base.cpp, line %u: %s ",
+ line_number,
+ ACE_TEXT_ALWAYS_CHAR (message));
+ perror ("failed");
+#else
+ // @@ Need to use the following information.
+ ACE_UNUSED_ARG (line_number);
+ ACE_UNUSED_ARG (message);
+
+ ACE_TCHAR *lpMsgBuf = 0;
+ ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ ::GetLastError (),
+ MAKELANGID (LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ // Default language
+ (ACE_TCHAR *) &lpMsgBuf,
+ 0,
+ 0);
+ ::MessageBox (0,
+ lpMsgBuf,
+ ACE_TEXT ("ACE_OS error"),
+ MB_OK);
+#endif
+}
+
+int
+ACE_OS_Object_Manager::starting_up (void)
+{
+ return ACE_OS_Object_Manager::instance_
+ ? instance_->starting_up_i ()
+ : 1;
+}
+
+int
+ACE_OS_Object_Manager::shutting_down (void)
+{
+ return ACE_OS_Object_Manager::instance_
+ ? instance_->shutting_down_i ()
+ : 1;
+}
+
+/*****************************************************************************/
+
+#if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
+/**
+ * @class ACE_OS_Object_Manager_Manager
+ *
+ * @brief Ensure that the ACE_OS_Object_Manager gets initialized at
+ * program startup, and destroyed at program termination.
+ *
+ * Without ACE_HAS_NONSTATIC_OBJECT_MANAGER, a static instance of this
+ * class is created. Therefore, it gets created before main ()
+ * is called. And it gets destroyed after main () returns.
+ */
+class ACE_OS_Object_Manager_Manager
+{
+public:
+ /// Constructor.
+ ACE_OS_Object_Manager_Manager (void);
+
+ /// Destructor.
+ ~ACE_OS_Object_Manager_Manager (void);
+
+private:
+ /// Save the main thread ID, so that destruction can be suppressed.
+ ACE_thread_t saved_main_thread_id_;
+};
+
+ACE_OS_Object_Manager_Manager::ACE_OS_Object_Manager_Manager (void)
+ : saved_main_thread_id_ (ACE_OS::thr_self ())
+{
+ // Ensure that the Object_Manager gets initialized before any
+ // application threads have been spawned. Because this will be called
+ // during construction of static objects, that should always be the
+ // case.
+ (void) ACE_OS_Object_Manager::instance ();
+}
+
+ACE_OS_Object_Manager_Manager::~ACE_OS_Object_Manager_Manager (void)
+{
+ if (ACE_OS::thr_equal (ACE_OS::thr_self (),
+ saved_main_thread_id_))
+ {
+ delete ACE_OS_Object_Manager::instance_;
+ ACE_OS_Object_Manager::instance_ = 0;
+ }
+ // else if this destructor is not called by the main thread, then do
+ // not delete the ACE_OS_Object_Manager. That causes problems, on
+ // WIN32 at least.
+}
+
+static ACE_OS_Object_Manager_Manager ACE_OS_Object_Manager_Manager_instance;
+#endif /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Object_Manager_Base.h b/ACE/ace/Object_Manager_Base.h
new file mode 100644
index 00000000000..a67c5ceeec8
--- /dev/null
+++ b/ACE/ace/Object_Manager_Base.h
@@ -0,0 +1,248 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Object_Manager_Base.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OBJECT_MANAGER_BASE_H
+#define ACE_OBJECT_MANAGER_BASE_H
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/Cleanup.h"
+#include "ace/os_include/sys/os_types.h"
+#include "ace/os_include/os_signal.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Object_Manager;
+class ACE_OS_Object_Manager_Manager;
+class ACE_TSS_Cleanup;
+class ACE_TSS_Emulation;
+class ACE_Log_Msg;
+class ACE_Thread_Hook;
+
+/**
+ * @class ACE_Object_Manager_Base
+ *
+ * @brief Base class for ACE_Object_Manager(s).
+ *
+ * Encapsulates the most useful ACE_Object_Manager data structures.
+ */
+class ACE_Export ACE_Object_Manager_Base
+{
+protected:
+ /// Default constructor.
+ ACE_Object_Manager_Base (void);
+
+ /// Destructor.
+ virtual ~ACE_Object_Manager_Base (void);
+
+public:
+ /**
+ * Explicitly initialize. Returns 0 on success, -1 on failure due
+ * to dynamic allocation failure (in which case errno is set to
+ * ENOMEM), or 1 if it had already been called.
+ */
+ virtual int init (void) = 0;
+
+ /**
+ * Explicitly destroy. Returns 0 on success, -1 on failure because
+ * the number of fini () calls hasn't reached the number of init ()
+ * calls, or 1 if it had already been called.
+ */
+ virtual int fini (void) = 0;
+
+ enum Object_Manager_State
+ {
+ OBJ_MAN_UNINITIALIZED = 0,
+ OBJ_MAN_INITIALIZING,
+ OBJ_MAN_INITIALIZED,
+ OBJ_MAN_SHUTTING_DOWN,
+ OBJ_MAN_SHUT_DOWN
+ };
+
+protected:
+ /**
+ * Returns 1 before ACE_Object_Manager_Base has been constructed.
+ * This flag can be used to determine if the program is constructing
+ * static objects. If no static object spawns any threads, the
+ * program will be single-threaded when this flag returns 1. (Note
+ * that the program still might construct some static objects when
+ * this flag returns 0, if ACE_HAS_NONSTATIC_OBJECT_MANAGER is not
+ * defined.)
+ */
+ int starting_up_i (void);
+
+ /**
+ * Returns 1 after ACE_Object_Manager_Base has been destroyed. This
+ * flag can be used to determine if the program is in the midst of
+ * destroying static objects. (Note that the program might destroy
+ * some static objects before this flag can return 1, if
+ * ACE_HAS_NONSTATIC_OBJECT_MANAGER is not defined.)
+ */
+ int shutting_down_i (void);
+
+ /// State of the Object_Manager;
+ Object_Manager_State object_manager_state_;
+
+ /**
+ * Flag indicating whether the ACE_Object_Manager was dynamically
+ * allocated by ACE. (If is was dynamically allocated by the
+ * application, then the application is responsible for destroying
+ * it.)
+ */
+ bool dynamically_allocated_;
+
+ /// Link to next Object_Manager, for chaining.
+ ACE_Object_Manager_Base *next_;
+private:
+ // Disallow copying by not implementing the following . . .
+ ACE_Object_Manager_Base (const ACE_Object_Manager_Base &);
+ ACE_Object_Manager_Base &operator= (const ACE_Object_Manager_Base &);
+};
+
+extern "C"
+void
+ACE_OS_Object_Manager_Internal_Exit_Hook (void);
+
+
+// @@ This forward declaration should go away.
+class ACE_Log_Msg;
+
+class ACE_Export ACE_OS_Object_Manager : public ACE_Object_Manager_Base
+{
+public:
+ /// Explicitly initialize.
+ virtual int init (void);
+
+ /// Explicitly destroy.
+ virtual int fini (void);
+
+ /**
+ * Returns 1 before the ACE_OS_Object_Manager has been
+ * constructed. See <ACE_Object_Manager::starting_up> for more
+ * information.
+ */
+ static int starting_up (void);
+
+ /// Returns 1 after the ACE_OS_Object_Manager has been destroyed.
+ /// See <ACE_Object_Manager::shutting_down> for more information.
+ static int shutting_down (void);
+
+ /// Unique identifiers for preallocated objects.
+ enum Preallocated_Object
+ {
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_OS_MONITOR_LOCK,
+ ACE_TSS_CLEANUP_LOCK,
+ ACE_LOG_MSG_INSTANCE_LOCK,
+# if defined (ACE_HAS_TSS_EMULATION)
+ ACE_TSS_KEY_LOCK,
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ ACE_TSS_BASE_LOCK,
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+# endif /* ACE_HAS_TSS_EMULATION */
+# else
+ // Without ACE_MT_SAFE, There are no preallocated objects. Make
+ // sure that the preallocated_array size is at least one by
+ // declaring this dummy . . .
+ ACE_OS_EMPTY_PREALLOCATED_OBJECT,
+# endif /* ACE_MT_SAFE */
+
+ /// This enum value must be last!
+ ACE_OS_PREALLOCATED_OBJECTS
+ };
+
+ /// Accesses a default signal set used, for example, in
+ /// ACE_Sig_Guard methods.
+ static sigset_t *default_mask (void);
+
+ /// Returns the current thread hook for the process.
+ static ACE_Thread_Hook *thread_hook (void);
+
+ /// Returns the existing thread hook and assign a <new_thread_hook>.
+ static ACE_Thread_Hook *thread_hook (ACE_Thread_Hook *new_thread_hook);
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ /// Get/Set TSS exception action.
+ static ACE_SEH_EXCEPT_HANDLER seh_except_selector (void);
+ static ACE_SEH_EXCEPT_HANDLER seh_except_selector (ACE_SEH_EXCEPT_HANDLER);
+
+ static ACE_SEH_EXCEPT_HANDLER seh_except_handler (void);
+ static ACE_SEH_EXCEPT_HANDLER seh_except_handler (ACE_SEH_EXCEPT_HANDLER);
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+public:
+ // = Applications shouldn't use these so they're hidden here.
+
+ // They're public so that the ACE_Object_Manager can be
+ // constructed/destructed in <main> with
+ // <ACE_HAS_NONSTATIC_OBJECT_MANAGER>.
+ /// Constructor.
+ ACE_OS_Object_Manager (void);
+
+ /// Destructor.
+ ~ACE_OS_Object_Manager (void);
+
+ /// Accessor to singleton instance.
+ static ACE_OS_Object_Manager *instance (void);
+
+ /// For <ACE_OS::atexit> support.
+ int at_exit (ACE_EXIT_HOOK func);
+
+//private:
+ /// Singleton instance pointer.
+ static ACE_OS_Object_Manager *instance_;
+
+ /// Table of preallocated objects.
+ static void *preallocated_object[ACE_OS_PREALLOCATED_OBJECTS];
+
+ /// Default signal set used, for example, in ACE_Sig_Guard.
+ sigset_t *default_mask_;
+
+ /// Thread hook that's used by this process.
+ ACE_Thread_Hook *thread_hook_;
+
+ /// For at_exit support.
+ ACE_OS_Exit_Info exit_info_;
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ /// These handlers determine how a thread handles win32 structured
+ /// exception.
+ ACE_SEH_EXCEPT_HANDLER seh_except_selector_;
+ ACE_SEH_EXCEPT_HANDLER seh_except_handler_;
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ /// For use by init () and fini (), to consolidate error reporting.
+ static void print_error_message (unsigned int line_number, const ACE_TCHAR *message);
+
+ /// This class is for internal use by ACE_OS, etc., only.
+ friend class ACE_Object_Manager;
+ friend class ACE_OS_Object_Manager_Manager;
+ friend class ACE_TSS_Cleanup;
+ friend class ACE_TSS_Emulation;
+ friend class ACE_Log_Msg;
+ friend void ACE_OS_Object_Manager_Internal_Exit_Hook ();
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OBJECT_MANAGER_BASE_H */
diff --git a/ACE/ace/Obstack.h b/ACE/ace/Obstack.h
new file mode 100644
index 00000000000..511f7715f69
--- /dev/null
+++ b/ACE/ace/Obstack.h
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+//=============================================================================
+/**
+ * @file Obstack.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_SINGLETON_DECLARATION (ACE_Obstack_T <char>;)
+
+typedef ACE_Obstack_T<char> ACE_Obstack;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OBSTACK_H */
diff --git a/ACE/ace/Obstack_T.cpp b/ACE/ace/Obstack_T.cpp
new file mode 100644
index 00000000000..ecce0636b2d
--- /dev/null
+++ b/ACE/ace/Obstack_T.cpp
@@ -0,0 +1,226 @@
+// $Id$
+
+#ifndef ACE_OBSTACK_T_CPP
+#define ACE_OBSTACK_T_CPP
+
+#include "ace/Obstack_T.h"
+#include "ace/Malloc_Base.h"
+#include "ace/OS_NS_string.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Obstack_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Obstack_T)
+
+template <class CHAR> void
+ACE_Obstack_T<CHAR>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("size_ = %d\n"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("head_ = %x\n"), this->head_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("curr_ = %x\n"), this->curr_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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);
+
+ // Check to see if there's room for the requested length, including
+ // any part of an existing string, if any.
+ size_t resulting_len = (this->curr_->cur_ - this->curr_->block_) + len;
+
+ // Increase the length of the underlying chunks if the request made is
+ // for bigger sized chunks.
+ if (this->size_ < resulting_len)
+ this->size_ = this->size_ << 1;
+
+ // We now know the request will fit; see if it can fit in the current
+ // chunk or will need a new one.
+ if (this->curr_->cur_ + len >= this->curr_->end_)
+ {
+ // Need a new chunk. Save the current one so the current string can be
+ // copied to the new chunk.
+ ACE_Obchunk *temp = this->curr_;
+ if (this->curr_->next_ == 0)
+ {
+ // We must allocate new memory.
+ ACE_Obchunk* tmp = this->new_chunk();
+ if (!tmp)
+ return -1;
+ this->curr_->next_ = tmp;
+ 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_;
+ }
+
+ // Copy any initial characters to the new chunk.
+ if (temp->cur_ != temp->block_)
+ {
+ size_t datasize = temp->cur_ - temp->block_;
+ ACE_OS::memcpy (this->curr_->block_,
+ temp->block_,
+ datasize);
+ this->curr_->cur_ = this->curr_->block_ + datasize;
+ // Reset the old chunk.
+ temp->cur_ = temp->block_;
+ }
+ }
+
+ 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 = 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 = 0;
+
+ ACE_NEW_MALLOC_RETURN (temp,
+ 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),
+ head_ (0),
+ curr_ (0)
+{
+ 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 (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>::unwind (void* obj)
+{
+ if (obj >= this->curr_->contents_ && obj < this->curr_->end_)
+ this->curr_->block_ = this->curr_->cur_ = reinterpret_cast<char*> (obj);
+ else
+ this->unwind_i (obj);
+}
+
+template <class CHAR> void
+ACE_Obstack_T<CHAR>::unwind_i (void* obj)
+{
+ ACE_Obchunk* curr = this->head_;
+ while (curr != 0 && (curr->contents_ > obj || curr->end_ < obj))
+ curr = curr->next_;
+ if (curr)
+ {
+ this->curr_ = curr;
+ this->curr_->block_ = this->curr_->cur_ = reinterpret_cast<char*> (obj);
+ }
+ else if (obj != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Deletion of non-existent object.\n%a")));
+}
+
+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_;
+}
+
+template <class CHAR> void
+ACE_Obstack_T<CHAR>::grow_fast (CHAR c)
+{
+ * (reinterpret_cast<CHAR *> (this->curr_->cur_)) = c;
+ this->curr_->cur_ += sizeof (CHAR);
+}
+
+template <class CHAR> CHAR *
+ACE_Obstack_T<CHAR>::freeze (void)
+{
+ CHAR *retv = reinterpret_cast<CHAR *> (this->curr_->block_);
+ * (reinterpret_cast<CHAR *> (this->curr_->cur_)) = 0;
+
+ this->curr_->cur_ += sizeof (CHAR);
+ this->curr_->block_ = this->curr_->cur_;
+ return retv;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_OBSTACK_T_CPP */
diff --git a/ACE/ace/Obstack_T.h b/ACE/ace/Obstack_T.h
new file mode 100644
index 00000000000..3e24ab31925
--- /dev/null
+++ b/ACE/ace/Obstack_T.h
@@ -0,0 +1,134 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Obstack_T.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+#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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Allocator;
+
+/**
+ * @class ACE_Obstack_T
+ *
+ * @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).
+ ///
+ /// @deprecated No need to use this function as you can put objects of
+ /// arbitrary lengths into the obstack now.
+ size_t length (void) const;
+ size_t size (void) const;
+
+ /// "Unwind" the stack. If @a obj is a null pointer, everything allocated
+ /// in the stack is released. Otherwise, @a obj must be an address of an
+ /// object allocated in the stack. In this case, @a obj is released along
+ /// with everthing allocated in the Obstack since @a obj.
+ void unwind (void* obj);
+
+ /// "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);
+
+ /// Search through the list of Obchunks and release them. Helper funtion
+ /// used by unwind.
+ void unwind_i (void* obj);
+
+ /// 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Obstack_T.inl"
+#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/ace/Obstack_T.inl b/ACE/ace/Obstack_T.inl
new file mode 100644
index 00000000000..1eddbdcf4e6
--- /dev/null
+++ b/ACE/ace/Obstack_T.inl
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/PI_Malloc.cpp b/ACE/ace/PI_Malloc.cpp
new file mode 100644
index 00000000000..5b2897d2dcf
--- /dev/null
+++ b/ACE/ace/PI_Malloc.cpp
@@ -0,0 +1,165 @@
+#ifndef ACE_PI_MALLOC_CPP
+#define ACE_PI_MALLOC_CPP
+
+#include "ace/PI_Malloc.h"
+
+ACE_RCSID (ace,
+ PI_Malloc,
+ "$Id$")
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/PI_Malloc.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Object_Manager.h"
+#include "ace/Process_Mutex.h"
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_PI_Control_Block::ACE_Malloc_Header::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Malloc_Header::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnext_block = %x"), (ACE_Malloc_Header *) this->next_block_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nsize = %d\n"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_PI_Control_Block::print_alignment_info (void)
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Control_Block::print_alignment_info");
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Start ---> ACE_PI_Control_Block::print_alignment_info:\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Sizeof ptr: %d\n")
+ ACE_TEXT ("Sizeof size_t: %d\n")
+ ACE_TEXT ("Sizeof long: %d\n")
+ ACE_TEXT ("Sizeof double: %d\n")
+ ACE_TEXT ("Sizeof ACE_MALLOC_ALIGN: %d\n")
+ ACE_TEXT ("sizeof ACE_MALLOC_PADDING: %d\n")
+ ACE_TEXT ("Sizeof ACE_MALLOC_HEADER_SIZE: %d\n")
+ ACE_TEXT ("Sizeof ACE_PI_MALLOC_PADDING_SIZE: %d\n")
+ ACE_TEXT ("Sizeof ACE_PI_CONTROL_BLOCK_SIZE: %d\n")
+ ACE_TEXT ("Sizeof ACE_PI_CONTROL_BLOCK_ALIGN_BYTES: %d\n")
+ ACE_TEXT ("Sizeof (MALLOC_HEADER): %d\n")
+ ACE_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_BYTES,
+ sizeof (ACE_Malloc_Header),
+ sizeof (ACE_PI_Control_Block)
+ ));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("End <--- ACE_PI_Control_Block::print_alignment_info:\n")));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_PI_Control_Block::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_PI_Control_Block::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Name Node:\n")));
+ for (ACE_Name_Node *nextn = this->name_head_;
+ nextn != 0;
+ nextn = nextn->next_)
+ nextn->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("freep_ = %x"), (ACE_Malloc_Header *) this->freep_));
+ this->base_.dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_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_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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
+{
+ return this->name_;
+}
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Name_Node::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("pointer = %x"), (const char *) this->pointer_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("\nnext_ = %x"), (ACE_Name_Node *) this->next_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("\nname_ = (%x, %s)"),
+ (const char *) this->name_,
+ (const char *) this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1*/
+
+#endif /* ACE_PI_MALLOC_CPP */
diff --git a/ACE/ace/PI_Malloc.h b/ACE/ace/PI_Malloc.h
new file mode 100644
index 00000000000..650a34254f1
--- /dev/null
+++ b/ACE/ace/PI_Malloc.h
@@ -0,0 +1,213 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file PI_Malloc.h
+ *
+ * $Id$
+ *
+ * @author Priyanka Gontla <pgontla@ece.uci.edu>
+ * @author Based on code that existed in other ACE files.
+ */
+//==========================================================================
+
+#ifndef ACE_PI_MALLOC_H
+#define ACE_PI_MALLOC_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/Malloc.h"
+#include "ace/Based_Pointer_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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)
+# define ACE_PI_MALLOC_PADDING_SIZE ACE_MALLOC_ROUNDUP (ACE_MALLOC_HEADER_SIZE + sizeof (MALLOC_HEADER_PTR) + sizeof (size_t), ACE_MALLOC_ALIGN) - (sizeof (MALLOC_HEADER_PTR) + sizeof (size_t))
+# endif /* !ACE_PI_MALLOC_PADDING_SIZE */
+ char padding_[(ACE_PI_MALLOC_PADDING_SIZE) ? ACE_PI_MALLOC_PADDING_SIZE : ACE_MALLOC_ALIGN];
+
+ /// Dump the state of the object.
+ void dump (void) const;
+
+ private:
+
+ // Disallow copy construction and assignment.
+ ACE_Malloc_Header (ACE_Malloc_Header const &);
+ void operator= (ACE_Malloc_Header 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 (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:
+
+ // Disallow assignment.
+ 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_BYTES)
+# define ACE_PI_CONTROL_BLOCK_ALIGN_BYTES \
+ ACE_MALLOC_ROUNDUP (ACE_PI_CONTROL_BLOCK_SIZE, ACE_MALLOC_ALIGN) - ACE_PI_CONTROL_BLOCK_SIZE
+# endif /* !ACE_PI_CONTROL_BLOCK_ALIGN_LONGS */
+ /// Force alignment.
+ char align_[(ACE_PI_CONTROL_BLOCK_ALIGN_BYTES) ? ACE_PI_CONTROL_BLOCK_ALIGN_BYTES : ACE_MALLOC_ALIGN];
+
+ /// 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:
+
+ // Disallow assignment.
+ void operator= (const ACE_Control_Block &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/PI_Malloc.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_PI_MALLOC_H */
diff --git a/ACE/ace/PI_Malloc.inl b/ACE/ace/PI_Malloc.inl
new file mode 100644
index 00000000000..1cb78d466e1
--- /dev/null
+++ b/ACE/ace/PI_Malloc.inl
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
diff --git a/ACE/ace/POSIX_Asynch_IO.cpp b/ACE/ace/POSIX_Asynch_IO.cpp
new file mode 100644
index 00000000000..551293f6215
--- /dev/null
+++ b/ACE/ace/POSIX_Asynch_IO.cpp
@@ -0,0 +1,2416 @@
+// $Id$
+
+#include "ace/POSIX_Asynch_IO.h"
+
+#if defined (ACE_HAS_AIO_CALLS)
+
+#include "ace/Flag_Manip.h"
+#include "ace/Proactor.h"
+#include "ace/Message_Block.h"
+#include "ace/INET_Addr.h"
+#include "ace/Asynch_Pseudo_Task.h"
+#include "ace/POSIX_Proactor.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_sys_stat.h"
+
+ACE_RCSID (ace,
+ POSIX_Asynch_IO,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+size_t
+ACE_POSIX_Asynch_Result::bytes_transferred (void) const
+{
+ return this->bytes_transferred_;
+}
+
+void
+ACE_POSIX_Asynch_Result::set_bytes_transferred (size_t 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 = 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void* act,
+ ACE_HANDLE /* event */, // Event is not used on POSIX.
+ u_long offset,
+ u_long offset_high,
+ int priority,
+ int signal_number)
+ : handler_proxy_ (handler_proxy),
+ act_ (act),
+ bytes_transferred_ (0),
+ success_ (0),
+ completion_key_ (0),
+ error_ (0)
+{
+ aio_offset = offset;
+ aio_reqprio = priority;
+ aio_sigevent.sigev_signo = signal_number;
+
+ //
+ // @@ 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void * /* completion_key */,
+ ACE_Proactor *proactor)
+{
+ this->proactor_ = proactor;
+ this->handler_proxy_ = handler_proxy;
+ this->handle_ = handle;
+
+ // Grab the handle from the <handler> if <handle> is invalid
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ {
+ ACE_Handler *handler = handler_proxy.get ()->handler ();
+ if (handler != 0)
+ this->handle_ = 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 */
+
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Operation::cancel (void)
+{
+ if (!posix_proactor_)
+ return -1;
+ return posix_proactor_->cancel_aio (this->handle_);
+}
+
+ACE_Proactor *
+ACE_POSIX_Asynch_Operation::proactor (void) const
+{
+ return this->proactor_;
+}
+
+ACE_POSIX_Proactor *
+ACE_POSIX_Asynch_Operation::posix_proactor (void) const
+{
+ return this->posix_proactor_;
+}
+
+ACE_POSIX_Asynch_Operation::~ACE_POSIX_Asynch_Operation (void)
+{
+}
+
+ACE_POSIX_Asynch_Operation::ACE_POSIX_Asynch_Operation (ACE_POSIX_Proactor *posix_proactor)
+ : posix_proactor_ (posix_proactor),
+ handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+// *********************************************************************
+
+size_t
+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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_POSIX_Asynch_Result
+ (handler_proxy, 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;
+}
+
+void
+ACE_POSIX_Asynch_Read_Stream_Result::complete (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_read_stream (result);
+}
+
+ACE_POSIX_Asynch_Read_Stream_Result::~ACE_POSIX_Asynch_Read_Stream_Result (void)
+{
+}
+
+// ************************************************************
+
+ACE_POSIX_Asynch_Read_Stream::ACE_POSIX_Asynch_Read_Stream (ACE_POSIX_Proactor *posix_proactor)
+ : ACE_POSIX_Asynch_Operation (posix_proactor)
+{
+}
+
+int
+ACE_POSIX_Asynch_Read_Stream::read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ size_t space = message_block.space ();
+ if (bytes_to_read > space)
+ bytes_to_read=space;
+
+ if (bytes_to_read == 0)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ // Create the Asynch_Result.
+ ACE_POSIX_Asynch_Read_Stream_Result *result = 0;
+ ACE_POSIX_Proactor *proactor = this->posix_proactor ();
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Read_Stream_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ proactor->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ int return_val = proactor->start_aio (result, ACE_POSIX_Proactor::ACE_OPCODE_READ);
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_Asynch_Read_Stream::~ACE_POSIX_Asynch_Read_Stream (void)
+{
+}
+
+// *********************************************************************
+
+size_t
+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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_POSIX_Asynch_Result
+ (handler_proxy, 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;
+}
+
+void
+ACE_POSIX_Asynch_Write_Stream_Result::complete (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_write_stream (result);
+}
+
+ACE_POSIX_Asynch_Write_Stream_Result::~ACE_POSIX_Asynch_Write_Stream_Result (void)
+{
+}
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Write_Stream::ACE_POSIX_Asynch_Write_Stream (ACE_POSIX_Proactor *posix_proactor)
+ : ACE_POSIX_Asynch_Operation (posix_proactor)
+{
+}
+
+int
+ACE_POSIX_Asynch_Write_Stream::write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ size_t len = message_block.length ();
+ if (bytes_to_write > len)
+ bytes_to_write = len;
+
+ if (bytes_to_write == 0)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_POSIX_Asynch_Write_Stream::write:")
+ ACE_TEXT ("Attempt to write 0 bytes\n")),
+ -1);
+
+ ACE_POSIX_Asynch_Write_Stream_Result *result = 0;
+ ACE_POSIX_Proactor *proactor = this->posix_proactor ();
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Write_Stream_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ proactor->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ int return_val = proactor->start_aio (result, ACE_POSIX_Proactor::ACE_OPCODE_WRITE);
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_Asynch_Write_Stream::~ACE_POSIX_Asynch_Write_Stream (void)
+{
+}
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Read_File_Result::ACE_POSIX_Asynch_Read_File_Result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_POSIX_Asynch_Read_Stream_Result (handler_proxy,
+ 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 (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_read_file (result);
+}
+
+ACE_POSIX_Asynch_Read_File_Result::~ACE_POSIX_Asynch_Read_File_Result (void)
+{
+}
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Read_File::ACE_POSIX_Asynch_Read_File (ACE_POSIX_Proactor *posix_proactor)
+ : ACE_POSIX_Asynch_Read_Stream (posix_proactor)
+{
+}
+
+int
+ACE_POSIX_Asynch_Read_File::read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ size_t space = message_block.space ();
+ if ( bytes_to_read > space )
+ bytes_to_read=space;
+
+ if ( bytes_to_read == 0 )
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_POSIX_Asynch_Read_File::read:")
+ ACE_TEXT ("Attempt to read 0 bytes or no space in the message block\n")),
+ -1);
+
+ ACE_POSIX_Asynch_Read_File_Result *result = 0;
+ ACE_POSIX_Proactor *proactor = this->posix_proactor ();
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Read_File_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ posix_proactor ()->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ int return_val = proactor->start_aio (result, ACE_POSIX_Proactor::ACE_OPCODE_READ);
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_Asynch_Read_File::~ACE_POSIX_Asynch_Read_File (void)
+{
+}
+
+int
+ACE_POSIX_Asynch_Read_File::read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return ACE_POSIX_Asynch_Read_Stream::read (message_block,
+ bytes_to_read,
+ act,
+ priority,
+ signal_number);
+}
+
+// ************************************************************
+
+ACE_POSIX_Asynch_Write_File_Result::ACE_POSIX_Asynch_Write_File_Result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_POSIX_Asynch_Write_Stream_Result (handler_proxy,
+ 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 (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_write_file (result);
+}
+
+ACE_POSIX_Asynch_Write_File_Result::~ACE_POSIX_Asynch_Write_File_Result (void)
+{
+}
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Write_File::ACE_POSIX_Asynch_Write_File (ACE_POSIX_Proactor *posix_proactor)
+ : ACE_POSIX_Asynch_Write_Stream (posix_proactor)
+{
+}
+
+int
+ACE_POSIX_Asynch_Write_File::write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ size_t len = message_block.length ();
+ if (bytes_to_write > len)
+ bytes_to_write = len;
+
+ if (bytes_to_write == 0)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_POSIX_Asynch_Write_File::write:")
+ ACE_TEXT ("Attempt to write 0 bytes\n")),
+ -1);
+
+ ACE_POSIX_Asynch_Write_File_Result *result = 0;
+ ACE_POSIX_Proactor *proactor = this->posix_proactor ();
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Write_File_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ proactor->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ int return_val = proactor->start_aio (result, ACE_POSIX_Proactor::ACE_OPCODE_WRITE);
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_Asynch_Write_File::~ACE_POSIX_Asynch_Write_File (void)
+{
+}
+
+int
+ACE_POSIX_Asynch_Write_File::write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return ACE_POSIX_Asynch_Write_Stream::write (message_block,
+ bytes_to_write,
+ act,
+ priority,
+ signal_number);
+}
+
+// *********************************************************************
+
+
+size_t
+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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+
+ : ACE_POSIX_Asynch_Result
+ (handler_proxy, 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 (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_accept (result);
+}
+
+ACE_POSIX_Asynch_Accept_Result::~ACE_POSIX_Asynch_Accept_Result (void)
+{
+}
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Accept::ACE_POSIX_Asynch_Accept (ACE_POSIX_Proactor * posix_proactor)
+ : ACE_POSIX_Asynch_Operation (posix_proactor),
+ flg_open_ (false)
+{
+}
+
+ACE_POSIX_Asynch_Accept::~ACE_POSIX_Asynch_Accept (void)
+{
+ this->close ();
+ this->reactor (0); // to avoid purge_pending_notifications
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Accept::get_handle (void) const
+{
+ return this->handle_;
+}
+
+void
+ACE_POSIX_Asynch_Accept::set_handle (ACE_HANDLE handle)
+{
+ ACE_ASSERT (handle_ == ACE_INVALID_HANDLE);
+ this->handle_ = handle;
+}
+
+int
+ACE_POSIX_Asynch_Accept::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept::open");
+
+ // if we are already opened,
+ // we could not create a new handler without closing the previous
+ if (this->flg_open_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("%N:%l:ACE_POSIX_Asynch_Accept::open:")
+ ACE_TEXT("acceptor already open \n")),
+ -1);
+
+ if (-1 == ACE_POSIX_Asynch_Operation::open (handler_proxy,
+ handle,
+ completion_key,
+ proactor))
+ return -1;
+
+ flg_open_ = true;
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ if (-1 == task.register_io_handler (this->get_handle(),
+ this,
+ ACE_Event_Handler::ACCEPT_MASK,
+ 1)) // suspend after register
+ {
+ this->flg_open_= false;
+ this->handle_ = ACE_INVALID_HANDLE;
+ return -1 ;
+ }
+
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Accept::accept (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number,
+ int addr_family)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept::accept");
+
+ if (!this->flg_open_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("%N:%l:ACE_POSIX_Asynch_Accept::accept")
+ ACE_TEXT("acceptor was not opened before\n")),
+ -1);
+
+ // Sanity check: make sure that enough space has been allocated by
+ // the caller.
+ size_t address_size = sizeof (sockaddr_in);
+#if defined (ACE_HAS_IPV6)
+ if (addr_family == AF_INET6)
+ address_size = sizeof (sockaddr_in6);
+#else
+ ACE_UNUSED_ARG (addr_family);
+#endif
+ size_t available_space = message_block.space ();
+ size_t space_needed = bytes_to_read + 2 * address_size;
+
+ if (available_space < space_needed)
+ {
+ ACE_OS::last_error (ENOBUFS);
+ return -1;
+ }
+
+ // Common code for both WIN and POSIX.
+ // Create future Asynch_Accept_Result
+ ACE_POSIX_Asynch_Accept_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Accept_Result (this->handler_proxy_,
+ this->handle_,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ this->posix_proactor()->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Enqueue result
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+ if (this->result_queue_.enqueue_tail (result) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_POSIX_Asynch_Accept::accept: %p\n")
+ ACE_TEXT ("enqueue_tail")));
+ delete result; // to avoid memory leak
+ return -1;
+ }
+
+ if (this->result_queue_.size () > 1)
+ return 0;
+ }
+
+ // If this is the only item, then it means there the set was empty
+ // before. So enable the accept handle in the reactor.
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ return task.resume_io_handler (this->get_handle ());
+}
+
+//@@ 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::cancel_uncompleted (int flg_notify)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept::cancel_uncompleted");
+
+ int retval = 0;
+
+ for (; ; retval++)
+ {
+ ACE_POSIX_Asynch_Accept_Result* result = 0;
+
+ this->result_queue_.dequeue_head (result);
+
+ if (result == 0)
+ break;
+
+ if (this->flg_open_ == 0 || flg_notify == 0) //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,
+ ACE_TEXT("(%P | %t):%p\n"),
+ ACE_TEXT("ACE_POSIX_Asynch_Accept::")
+ ACE_TEXT("cancel_uncompleted")
+ ));
+ }
+ }
+ return retval;
+}
+
+int
+ACE_POSIX_Asynch_Accept::cancel (void)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept::cancel");
+
+ // Since this is not a real POSIX asynch I/O operation, we can't
+ // call ::aiocancel () or ACE_POSIX_Asynch_Operation::cancel ().
+ // We delegate real cancelation to cancel_uncompleted (1)
+
+ int rc = -1 ; // ERRORS
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ int num_cancelled = cancel_uncompleted (flg_open_);
+
+ if (num_cancelled == 0)
+ rc = 1 ; // AIO_ALLDONE
+ else if (num_cancelled > 0)
+ rc = 0 ; // AIO_CANCELED
+
+ if (!this->flg_open_)
+ return rc ;
+ }
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ task.suspend_io_handler (this->get_handle());
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Accept::close ()
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept::close");
+
+ // 1. It performs cancellation of all pending requests
+ // 2. Removes itself from Reactor ( ACE_Asynch_Pseudo_Task)
+ // 3. 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
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+ this->cancel_uncompleted (flg_open_);
+ }
+
+ if (!this->flg_open_)
+ {
+ if (this->handle_ != ACE_INVALID_HANDLE)
+ {
+ ACE_OS::closesocket (this->handle_);
+ this->handle_ = ACE_INVALID_HANDLE;
+ }
+ return 0;
+ }
+
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ return 0;
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ task.remove_io_handler (this->get_handle ());
+ if (this->handle_ != ACE_INVALID_HANDLE)
+ {
+ ACE_OS::closesocket (this->handle_);
+ this->handle_ = ACE_INVALID_HANDLE;
+ }
+
+ this->flg_open_ = false;
+
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Accept::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept::handle_close");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
+
+ // handle_close is called in two cases:
+ // 1. Pseudo task is closing (i.e. proactor destructor)
+ // 2. The listen handle is closed (we don't have exclusive access to this)
+
+ this->cancel_uncompleted (0);
+
+ this->flg_open_ = false;
+ this->handle_ = ACE_INVALID_HANDLE;
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Accept::handle_input (ACE_HANDLE /* fd */)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept::handle_input");
+
+ // 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>.
+
+ ACE_POSIX_Asynch_Accept_Result* result = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
+
+ // Deregister this info pertaining to this accept call.
+ if (this->result_queue_.dequeue_head (result) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("%N:%l:(%P | %t):%p\n"),
+ ACE_TEXT("ACE_POSIX_Asynch_Accept::handle_input:")
+ ACE_TEXT( " dequeueing failed")));
+
+ // Disable the handle in the reactor if no more accepts are pending.
+ if (this->result_queue_.size () == 0)
+ {
+ ACE_Asynch_Pseudo_Task & task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ task.suspend_io_handler (this->get_handle());
+ }
+ }
+
+ // 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 (this->handle_, 0, 0);
+
+ if (result == 0) // there is nobody to notify
+ {
+ ACE_OS::closesocket (new_handle);
+ return 0;
+ }
+
+ if (new_handle == ACE_INVALID_HANDLE)
+ {
+ result->set_error (errno);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("%N:%l:(%P | %t):%p\n"),
+ ACE_TEXT("ACE_POSIX_Asynch_Accept::handle_input: ")
+ ACE_TEXT("accept")));
+
+ // 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 ((LM_ERROR,
+ ACE_TEXT("Error:(%P | %t):%p\n"),
+ ACE_TEXT("ACE_POSIX_Asynch_Accept::handle_input: ")
+ ACE_TEXT(" <post_completion> failed")));
+
+ return 0;
+}
+
+// *********************************************************************
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Connect_Result::connect_handle (void) const
+{
+ return this->aio_fildes;
+}
+
+void ACE_POSIX_Asynch_Connect_Result::connect_handle (ACE_HANDLE handle)
+{
+ this->aio_fildes = handle;
+}
+
+
+ACE_POSIX_Asynch_Connect_Result::ACE_POSIX_Asynch_Connect_Result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_POSIX_Asynch_Result
+ (handler_proxy, act, event, 0, 0, priority, signal_number)
+{
+ this->aio_fildes = connect_handle;
+ this->aio_nbytes = 0;
+}
+
+void
+ACE_POSIX_Asynch_Connect_Result::complete (size_t 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;
+
+ // Create the interface result class.
+ ACE_Asynch_Connect::Result result (this);
+
+ // Call the application handler.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_connect (result);
+}
+
+ACE_POSIX_Asynch_Connect_Result::~ACE_POSIX_Asynch_Connect_Result (void)
+{
+}
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Connect::ACE_POSIX_Asynch_Connect (ACE_POSIX_Proactor * posix_proactor)
+ : ACE_POSIX_Asynch_Operation (posix_proactor),
+ flg_open_ (false)
+{
+}
+
+ACE_POSIX_Asynch_Connect::~ACE_POSIX_Asynch_Connect (void)
+{
+ this->close ();
+ this->reactor(0); // to avoid purge_pending_notifications
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Connect::get_handle (void) const
+{
+ ACE_ASSERT (0);
+ return ACE_INVALID_HANDLE;
+}
+
+void
+ACE_POSIX_Asynch_Connect::set_handle (ACE_HANDLE)
+{
+ ACE_ASSERT (0) ;
+}
+
+int
+ACE_POSIX_Asynch_Connect::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Connect::open");
+
+ if (this->flg_open_)
+ return -1;
+
+ //int result =
+ ACE_POSIX_Asynch_Operation::open (handler_proxy,
+ handle,
+ completion_key,
+ proactor);
+
+ // Ignore result as we pass ACE_INVALID_HANDLE
+ //if (result == -1)
+ // return result;
+
+ this->flg_open_ = true;
+
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Connect::connect (ACE_HANDLE connect_handle,
+ const ACE_Addr & remote_sap,
+ const ACE_Addr & local_sap,
+ int reuse_addr,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Connect::connect");
+
+ if (this->flg_open_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("%N:%l:ACE_POSIX_Asynch_Connect::connect")
+ ACE_TEXT("connector was not opened before\n")),
+ -1);
+
+ // Common code for both WIN and POSIX.
+ // Create future Asynch_Connect_Result
+ ACE_POSIX_Asynch_Connect_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Connect_Result (this->handler_proxy_,
+ connect_handle,
+ act,
+ this->posix_proactor ()->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ int rc = connect_i (result,
+ remote_sap,
+ local_sap,
+ reuse_addr);
+
+ // update handle
+ connect_handle = result->connect_handle ();
+
+ if (rc != 0)
+ return post_result (result, true);
+
+ // Enqueue result we will wait for completion
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ if (this->result_map_.bind (connect_handle, result) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%N:%l:%p\n"),
+ ACE_TEXT ("ACE_POSIX_Asynch_Connect::connect:")
+ ACE_TEXT ("bind")));
+
+ result->set_error (EFAULT);
+ return post_result (result, true);
+ }
+ }
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ rc = task.register_io_handler (connect_handle,
+ this,
+ ACE_Event_Handler::CONNECT_MASK,
+ 0); // don't suspend after register
+ if (rc < 0)
+ {
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ this->result_map_.unbind (connect_handle, result);
+ }
+ if (result != 0)
+ {
+ result->set_error (EFAULT);
+ this->post_result (result, true);
+ }
+ return -1;
+ }
+ else
+ result = 0;
+
+
+ return 0;
+}
+
+int ACE_POSIX_Asynch_Connect::post_result (ACE_POSIX_Asynch_Connect_Result * result,
+ bool post_enable)
+{
+ if (this->flg_open_ && post_enable != 0)
+ {
+ if (this->posix_proactor ()->post_completion (result) == 0)
+ return 0;
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("Error:(%P | %t):%p\n"),
+ ACE_TEXT("ACE_POSIX_Asynch_Connect::post_result: ")
+ ACE_TEXT(" <post_completion> failed")));
+ }
+
+ ACE_HANDLE handle = result->connect_handle ();
+
+ if (handle != ACE_INVALID_HANDLE)
+ ACE_OS::closesocket (handle);
+
+ delete result;
+
+ return -1;
+}
+
+//connect_i
+// return code :
+// -1 errors before attempt to connect
+// 0 connect started
+// 1 connect finished ( may be unsuccessfully)
+
+int
+ACE_POSIX_Asynch_Connect::connect_i (ACE_POSIX_Asynch_Connect_Result *result,
+ const ACE_Addr & remote_sap,
+ const ACE_Addr & local_sap,
+ int reuse_addr)
+{
+ result->set_bytes_transferred (0);
+
+ ACE_HANDLE handle = result->connect_handle ();
+
+ if (handle == ACE_INVALID_HANDLE)
+ {
+ int protocol_family = remote_sap.get_type ();
+
+ handle = ACE_OS::socket (protocol_family,
+ SOCK_STREAM,
+ 0);
+ // save it
+ result->connect_handle (handle);
+ if (handle == ACE_INVALID_HANDLE)
+ {
+ result->set_error (errno);
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT("ACE_POSIX_Asynch_Connect::connect_i: %p\n"),
+ ACE_TEXT("socket")),
+ -1);
+ }
+
+ // Reuse the address
+ int one = 1;
+ if (protocol_family != PF_UNIX &&
+ reuse_addr != 0 &&
+ ACE_OS::setsockopt (handle,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (const char*) &one,
+ sizeof one) == -1 )
+ {
+ result->set_error (errno);
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT("ACE_POSIX_Asynch_Connect::connect_i: %p\n"),
+ ACE_TEXT("setsockopt")),
+ -1);
+ }
+ }
+
+ if (local_sap != ACE_Addr::sap_any)
+ {
+ sockaddr * laddr = reinterpret_cast<sockaddr *> (local_sap.get_addr ());
+ size_t size = local_sap.get_size ();
+
+ if (ACE_OS::bind (handle, laddr, size) == -1)
+ {
+ result->set_error (errno);
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT("ACE_POSIX_Asynch_Connect::connect_i: %p\n"),
+ ACE_TEXT("bind")),
+ -1);
+ }
+ }
+
+ // set non blocking mode
+ if (ACE::set_flags (handle, ACE_NONBLOCK) != 0)
+ {
+ result->set_error (errno);
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT("ACE_POSIX_Asynch_Connect::connect_i: %p\n")
+ ACE_TEXT("set_flags")),
+ -1);
+ }
+
+ for (;;)
+ {
+ int rc = ACE_OS::connect
+ (handle,
+ reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
+ remote_sap.get_size ());
+ if (rc < 0) // failure
+ {
+ if (errno == EWOULDBLOCK || errno == EINPROGRESS)
+ return 0; // connect started
+
+ if (errno == EINTR)
+ continue;
+
+ result->set_error (errno);
+ }
+
+ return 1 ; // connect finished
+ }
+
+ ACE_NOTREACHED (return 0);
+}
+
+
+//@@ 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_Connect::cancel_uncompleted (bool flg_notify,
+ ACE_Handle_Set & set)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Connect::cancel_uncompleted");
+
+ int retval = 0;
+
+ MAP_MANAGER::ITERATOR iter (result_map_);
+ MAP_MANAGER::ENTRY * me = 0;
+
+ set.reset ();
+
+ for (; iter.next (me) != 0; retval++ , iter.advance ())
+ {
+ ACE_HANDLE handle = me->ext_id_;
+ ACE_POSIX_Asynch_Connect_Result* result = me->int_id_ ;
+
+ set.set_bit (handle);
+
+ result->set_bytes_transferred (0);
+ result->set_error (ECANCELED);
+ this->post_result (result, flg_notify);
+ }
+
+ result_map_.unbind_all ();
+
+ return retval;
+}
+
+int
+ACE_POSIX_Asynch_Connect::cancel (void)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Connect::cancel");
+
+ // Since this is not a real asynch I/O operation, we can't just call
+ // ::aiocancel () or ACE_POSIX_Asynch_Operation::cancel ().
+ // Delegate real cancelation to cancel_uncompleted (1)
+
+ int rc = -1 ; // ERRORS
+
+ ACE_Handle_Set set;
+ int num_cancelled = 0;
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+ num_cancelled = cancel_uncompleted (flg_open_, set);
+ }
+ if (num_cancelled == 0)
+ rc = 1 ; // AIO_ALLDONE
+ else if (num_cancelled > 0)
+ rc = 0 ; // AIO_CANCELED
+
+ if (!this->flg_open_)
+ return rc ;
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ task.remove_io_handler (set);
+ return rc;
+}
+
+int
+ACE_POSIX_Asynch_Connect::close (void)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Connect::close");
+
+ ACE_Handle_Set set ;
+ int num_cancelled = 0;
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+ num_cancelled = cancel_uncompleted (flg_open_, set);
+ }
+
+ if (num_cancelled == 0 || !this->flg_open_)
+ {
+ this->flg_open_ = false;
+ return 0;
+ }
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ task.remove_io_handler (set);
+ this->flg_open_ = false;
+
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Connect::handle_output (ACE_HANDLE fd)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Connect::handle_output");
+
+ ACE_POSIX_Asynch_Connect_Result* result = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
+ if (this->result_map_.unbind (fd, result) != 0) // not found
+ return -1;
+ }
+
+ int sockerror = 0 ;
+ int lsockerror = sizeof sockerror;
+
+ ACE_OS::getsockopt (fd,
+ SOL_SOCKET,
+ SO_ERROR,
+ (char*) &sockerror,
+ &lsockerror);
+
+ result->set_bytes_transferred (0);
+ result->set_error (sockerror);
+
+ // This previously just did a "return -1" and let handle_close() clean
+ // things up. However, this entire object may be gone as a result of
+ // the application's completion handler, so don't count on 'this' being
+ // legitimate on return from post_result().
+ // remove_io_handler() contains flag DONT_CALL
+ this->posix_proactor ()->get_asynch_pseudo_task ().remove_io_handler (fd);
+ this->post_result (result, this->flg_open_);
+ return 0;
+}
+
+
+int
+ACE_POSIX_Asynch_Connect::handle_close (ACE_HANDLE fd, ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Connect::handle_close");
+
+ ACE_Asynch_Pseudo_Task &task =
+ this->posix_proactor ()->get_asynch_pseudo_task ();
+
+ task.remove_io_handler (fd);
+
+ ACE_POSIX_Asynch_Connect_Result* result = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
+ if (this->result_map_.unbind (fd, result) != 0) // not found
+ return -1;
+ }
+
+ result->set_bytes_transferred (0);
+ result->set_error (ECANCELED);
+ this->post_result (result, this->flg_open_);
+
+ return 0;
+}
+
+// *********************************************************************
+
+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_;
+}
+
+size_t
+ACE_POSIX_Asynch_Transmit_File_Result::bytes_to_write (void) const
+{
+ return this->aio_nbytes;
+}
+
+size_t
+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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_POSIX_Asynch_Result
+ (handler_proxy, 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 (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_transmit_file (result);
+}
+
+ACE_POSIX_Asynch_Transmit_File_Result::~ACE_POSIX_Asynch_Transmit_File_Result (void)
+{
+}
+
+
+// *********************************************************************
+
+/**
+ * @class ACE_POSIX_Asynch_Transmit_Handler
+ *
+ * @brief Auxillary handler for doing <Asynch_Transmit_File> in
+ * Unix. <ACE_POSIX_Asynch_Transmit_File> internally uses this.
+ *
+ * This is a helper class for implementing
+ * <ACE_POSIX_Asynch_Transmit_File> in Unix systems.
+ */
+class ACE_Export ACE_POSIX_Asynch_Transmit_Handler : public ACE_Handler
+{
+public:
+ /// Constructor. Result pointer will have all the information to do
+ /// the file transmission (socket, file, application handler, bytes
+ /// to write).
+ ACE_POSIX_Asynch_Transmit_Handler (ACE_POSIX_Proactor *posix_proactor,
+ ACE_POSIX_Asynch_Transmit_File_Result *result);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Transmit_Handler (void);
+
+ /// Do the transmission. All the info to do the transmission is in
+ /// the <result> member.
+ int transmit (void);
+
+protected:
+
+ /// The asynch result pointer made from the initial transmit file
+ /// request.
+ ACE_POSIX_Asynch_Transmit_File_Result *result_;
+
+ /// Message bloack used to do the transmission.
+ ACE_Message_Block *mb_;
+
+ enum ACT
+ {
+ HEADER_ACT = 1,
+ DATA_ACT = 2,
+ TRAILER_ACT = 3
+ };
+
+ /// ACT to transmit header.
+ ACT header_act_;
+
+ /// ACT to transmit data.
+ ACT data_act_;
+
+ /// ACT to transmit trailer.
+ ACT trailer_act_;
+
+ /// Current offset of the file being transmitted.
+ size_t file_offset_;
+
+ /// Total size of the file.
+ size_t file_size_;
+
+ /// Number of bytes transferred on the stream.
+ size_t bytes_transferred_;
+
+ /// This is called when asynchronous writes from the socket complete.
+ virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
+
+ /// This is called when asynchronous reads from the file complete.
+ virtual void handle_read_file (const ACE_Asynch_Read_File::Result &result);
+
+ /// Issue asynch read from the file.
+ int initiate_read_file (void);
+
+ /// To read from the file to be transmitted.
+ ACE_POSIX_Asynch_Read_File rf_;
+
+ /// Write stream to write the header, trailer and the data.
+ ACE_POSIX_Asynch_Write_Stream ws_;
+};
+
+// ************************************************************
+
+// Constructor.
+ACE_POSIX_Asynch_Transmit_Handler::ACE_POSIX_Asynch_Transmit_Handler
+ (ACE_POSIX_Proactor *posix_proactor,
+ 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),
+ rf_ (posix_proactor),
+ ws_ (posix_proactor)
+{
+ // 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 ();
+}
+
+
+// Do the transmission.
+// Initiate transmitting the header. When that completes
+// handle_write_stream will be called, there start transmitting the file.
+int
+ACE_POSIX_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->proxy (),
+ 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->proxy (),
+ 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 (),
+ 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_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.
+ size_t 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_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_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_Asynch_Transmit_File::ACE_POSIX_Asynch_Transmit_File (ACE_POSIX_Proactor *posix_proactor)
+ : ACE_POSIX_Asynch_Operation (posix_proactor)
+{
+}
+
+int
+ACE_POSIX_Asynch_Transmit_File::transmit_file (ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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_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_proxy_,
+ 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_Asynch_Transmit_Handler *transmit_handler = 0;
+
+ ACE_NEW_RETURN (transmit_handler,
+ ACE_POSIX_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_Asynch_Transmit_File::~ACE_POSIX_Asynch_Transmit_File (void)
+{
+}
+
+// *********************************************************************
+size_t
+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_;
+}
+
+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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_POSIX_Asynch_Result
+ (handler_proxy, 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 (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_read_dgram (result);
+}
+
+ACE_POSIX_Asynch_Read_Dgram_Result::~ACE_POSIX_Asynch_Read_Dgram_Result (void)
+{
+ delete this->remote_address_;
+}
+
+//***************************************************************************
+size_t
+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_;
+}
+
+
+ACE_Message_Block*
+ACE_POSIX_Asynch_Write_Dgram_Result::message_block () const
+{
+ return this->message_block_;
+}
+
+ACE_POSIX_Asynch_Write_Dgram_Result::ACE_POSIX_Asynch_Write_Dgram_Result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_POSIX_Asynch_Result
+ (handler_proxy, 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 (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_write_dgram (result);
+}
+
+ACE_POSIX_Asynch_Write_Dgram_Result::~ACE_POSIX_Asynch_Write_Dgram_Result (void)
+{
+}
+
+/***************************************************************************/
+ACE_POSIX_Asynch_Read_Dgram::~ACE_POSIX_Asynch_Read_Dgram (void)
+{
+}
+
+ssize_t
+ACE_POSIX_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)
+{
+ size_t space = message_block->space ();
+ // Create the Asynch_Result.
+ ACE_POSIX_Asynch_Read_Dgram_Result *result = 0;
+ ACE_POSIX_Proactor *proactor = this->posix_proactor ();
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Read_Dgram_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ space,
+ flags,
+ protocol_family,
+ act,
+ proactor->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ int return_val = proactor->start_aio (result, ACE_POSIX_Proactor::ACE_OPCODE_READ);
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_Asynch_Read_Dgram::ACE_POSIX_Asynch_Read_Dgram (ACE_POSIX_Proactor *posix_proactor)
+ : ACE_POSIX_Asynch_Operation (posix_proactor)
+{
+}
+
+//***************************************************************************
+
+ACE_POSIX_Asynch_Write_Dgram::~ACE_POSIX_Asynch_Write_Dgram (void)
+{
+}
+
+ssize_t
+ACE_POSIX_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)
+{
+ size_t len = message_block->length ();
+ if (len == 0)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_POSIX_Asynch_Write_Stream::write:")
+ ACE_TEXT ("Attempt to write 0 bytes\n")),
+ -1);
+
+ ACE_POSIX_Asynch_Write_Dgram_Result *result = 0;
+ ACE_POSIX_Proactor *proactor = this->posix_proactor ();
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Write_Dgram_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ len,
+ flags,
+ act,
+ proactor->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ int return_val = proactor->start_aio (result, ACE_POSIX_Proactor::ACE_OPCODE_WRITE);
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_Asynch_Write_Dgram::ACE_POSIX_Asynch_Write_Dgram
+ (ACE_POSIX_Proactor *posix_proactor)
+ : ACE_POSIX_Asynch_Operation (posix_proactor)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_AIO_CALLS */
diff --git a/ACE/ace/POSIX_Asynch_IO.h b/ACE/ace/POSIX_Asynch_IO.h
new file mode 100644
index 00000000000..25a360313bb
--- /dev/null
+++ b/ACE/ace/POSIX_Asynch_IO.h
@@ -0,0 +1,1302 @@
+// -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_AIO_CALLS)
+
+#include "ace/os_include/os_aio.h"
+
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Unbounded_Queue.h"
+#include "ace/Map_Manager.h"
+#include "ace/Event_Handler.h"
+#if defined(INTEGRITY)
+#include "ace/ACE.h"
+#endif
+
+#include "ace/Null_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations
+class ACE_POSIX_Proactor;
+class ACE_Proactor_Impl;
+class ACE_Handle_Set;
+
+/**
+ * @class ACE_POSIX_Asynch_Result
+ *
+ * This class provides concrete implementation for ACE_Asynch_Result
+ * for POSIX4 platforms. This class extends @c 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.
+ size_t 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.
+ *
+ * @note This is not implemented for POSIX4 platforms.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fails.
+ 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 @c 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 (size_t nbytes);
+
+protected:
+ /// Constructor. <Event> is not used on POSIX.
+ ACE_POSIX_Asynch_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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::Proxy_Ptr handler_proxy_;
+
+ /**
+ * 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.
+ size_t 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 implements ACE_Asynch_Operation for all
+ * implementations of Proactor (AIOCB, SIG, SUN)
+ * Specific future implementations 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 (@a handle == ACE_INVALID_HANDLE),
+ * @c 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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;
+
+ /// Return the underlying Proactor implementation.
+ ACE_POSIX_Proactor * posix_proactor (void) const;
+
+protected:
+ /// Contructor.
+ ACE_POSIX_Asynch_Operation (ACE_POSIX_Proactor *posix_proactor);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Operation (void);
+
+ // 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_Proactor *posix_proactor_;
+
+ /// Proactor that this Asynch IO will be registered with.
+ ACE_Proactor *proactor_;
+
+ /// Handler that will receive the callback.
+ ACE_Handler::Proxy_Ptr handler_proxy_;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @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 will have special permissions.
+ friend class ACE_POSIX_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.
+ size_t 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;
+
+protected:
+ ACE_POSIX_Asynch_Read_Stream_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (size_t bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ 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_Asynch_Read_Stream
+ *
+ * This class implements <ACE_Asynch_Read_Stream> for all POSIX
+ * based implementation of Proactor.
+ *
+ */
+class ACE_Export ACE_POSIX_Asynch_Read_Stream : public virtual ACE_Asynch_Read_Stream_Impl,
+ public ACE_POSIX_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_Asynch_Read_Stream (ACE_POSIX_Proactor *posix_proactor);
+
+ /// This starts off an asynchronous read. Upto @a bytes_to_read will
+ /// be read and stored in the @a message_block.
+ int read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Read_Stream (void);
+};
+
+
+/**
+ * @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
+ * @c 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_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.
+ size_t 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;
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Write_Stream factory.
+ ACE_POSIX_Asynch_Write_Stream_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (size_t 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_Asynch_Write_Stream
+ *
+ * @brief This class implements <ACE_Asynch_Write_Stream> for
+ * all POSIX implementations of ACE_Proactor.
+ */
+class ACE_Export ACE_POSIX_Asynch_Write_Stream : public virtual ACE_Asynch_Write_Stream_Impl,
+ public ACE_POSIX_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_Asynch_Write_Stream (ACE_POSIX_Proactor *posix_proactor);
+
+ /// This starts off an asynchronous write. Upto @a bytes_to_write
+ /// will be written from the @a message_block.
+ int write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Write_Stream (void);
+};
+
+/**
+ * @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 will have special permissions.
+ friend class ACE_POSIX_Asynch_Read_File;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+public:
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Read_File factory.
+ ACE_POSIX_Asynch_Read_File_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+
+ /// ACE_Proactor will call this method when the read completes.
+ virtual void complete (size_t bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Read_File_Result (void);
+};
+
+/**
+ * @class ACE_POSIX_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
+ * all POSIX implementations 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 @c 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_Asynch_Read_File : public virtual ACE_Asynch_Read_File_Impl,
+ public ACE_POSIX_Asynch_Read_Stream
+{
+
+public:
+ /// Constructor.
+ ACE_POSIX_Asynch_Read_File (ACE_POSIX_Proactor *posix_proactor);
+
+ /**
+ * This starts off an asynchronous read. Upto @a bytes_to_read will
+ * be read and stored in the @a message_block. The read will start
+ * at @a offset from the beginning of the file.
+ */
+ int read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Read_File (void);
+
+private:
+ /**
+ * This belongs to ACE_POSIX_Asynch_Read_Stream. We have
+ * defined this here to avoid compiler warnings and forward the
+ * method to <ACE_POSIX_Asynch_Read_Stream::read>.
+ */
+ int read (ACE_Message_Block &message_block,
+ size_t 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
+ * @c 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 @c handler instead of
+ * <ACE_Handler::handle_write_stream>. No additional state is
+ * required by this class as <ACE_Asynch_Result> can store the
+ * @a 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_Asynch_Write_File;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Write_File factory.
+ ACE_POSIX_Asynch_Write_File_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (size_t bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Write_File_Result (void);
+};
+
+/**
+ * @class ACE_POSIX_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_Asynch_Write_File : public virtual ACE_Asynch_Write_File_Impl,
+ public ACE_POSIX_Asynch_Write_Stream
+{
+public:
+ /// Constructor.
+ ACE_POSIX_Asynch_Write_File (ACE_POSIX_Proactor *posix_proactor);
+
+ /**
+ * This starts off an asynchronous write. Upto @a bytes_to_write
+ * will be written and stored in the @a message_block. The write will
+ * start at @a offset from the beginning of the file.
+ */
+ int write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Write_File (void);
+
+private:
+ /**
+ * This <write> belongs to ACE_POSIX_Asynch_Write_Stream. We
+ * have put this here to avoid compiler warnings. We forward this
+ * method call to the <ACE_POSIX_Asynch_Write_Stream::write>
+ * one.
+ */
+ int write (ACE_Message_Block &message_block,
+ size_t 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 will have special permissions.
+ friend class ACE_POSIX_Asynch_Accept;
+
+ /// 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.
+ size_t 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;
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Accept factory.
+ ACE_POSIX_Asynch_Accept_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+
+ /// ACE_Proactor will call this method when the accept completes.
+ virtual void complete (size_t 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
+ *
+ * @brief For the POSIX implementation this class is common for all Proactors
+ * (AIOCB/SIG/SUN)
+ */
+class ACE_Export ACE_POSIX_Asynch_Accept :
+ public virtual ACE_Asynch_Accept_Impl,
+ public ACE_POSIX_Asynch_Operation,
+ public ACE_Event_Handler
+{
+public:
+
+ /// Constructor.
+ ACE_POSIX_Asynch_Accept (ACE_POSIX_Proactor * posix_proactor);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Accept (void);
+
+ /**
+ * This <open> belongs to ACE_POSIX_Asynch_Operation. We forward
+ * this call to that method. We have put this here to avoid the
+ * compiler warnings.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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
+ * @c handler. Upto @a bytes_to_read will be read and stored in the
+ * @a message_block. The <accept_handle> will be used for the
+ * <accept> call. If (<accept_handle> == INVALID_HANDLE), a new
+ * handle will be created.
+ *
+ * @a 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,
+ size_t bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number = 0,
+ int addr_family = AF_INET);
+
+ /**
+ * Cancel all pending pseudo-asynchronus requests
+ * Behavior as usual AIO request
+ */
+ int cancel (void);
+
+ /**
+ * Close performs cancellation of all pending requests
+ * and closure the listen handle
+ */
+ int close ();
+
+ /// virtual from ACE_Event_Handler
+ ACE_HANDLE get_handle (void) const;
+
+ /// virtual from ACE_Event_Handler
+ void set_handle (ACE_HANDLE handle);
+
+ /// virtual from ACE_Event_Handler
+ /// Called when accept event comes up on <listen_handle>
+ int handle_input (ACE_HANDLE handle);
+
+ /// virtual from ACE_Event_Handler
+ int handle_close (ACE_HANDLE handle, ACE_Reactor_Mask close_mask);
+
+private:
+ /// flg_notify points whether or not we should send notification about
+ /// canceled accepts
+ /// 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 cancel_uncompleted (int flg_notify);
+
+ /// true - Accept is registered in ACE_Asynch_Pseudo_Task
+ /// false - Accept is deregisted in ACE_Asynch_Pseudo_Task
+ bool flg_open_ ;
+
+ /// Queue of Result pointers that correspond to all the pending
+ /// accept operations.
+ ACE_Unbounded_Queue<ACE_POSIX_Asynch_Accept_Result*> result_queue_;
+
+ /// 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_SYNCH_MUTEX lock_;
+};
+
+/**
+ * @class ACE_POSIX_Asynch_Connect_Result
+ *
+ * @brief This is that class which will be passed back to the
+ * completion handler when the asynchronous connect completes.
+ *
+ * This class has all the information necessary for a
+ * completion handler to uniquely identify the completion of the
+ * asynchronous connect.
+ */
+class ACE_Export ACE_POSIX_Asynch_Connect_Result : public virtual ACE_Asynch_Connect_Result_Impl,
+ public ACE_POSIX_Asynch_Result
+{
+ /// Factory classes will have special permissions.
+ friend class ACE_POSIX_Asynch_Connect;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+public:
+
+ /// I/O handle for the connection.
+ ACE_HANDLE connect_handle (void) const;
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Connect factory.
+ ACE_POSIX_Asynch_Connect_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+
+ /// ACE_Proactor will call this method when the accept completes.
+ virtual void complete (size_t bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Connect_Result (void);
+
+ // aiocb::aio_filedes
+ // I/O handle for the new connection.
+ void connect_handle (ACE_HANDLE handle);
+};
+
+
+/**
+ * @class ACE_POSIX_Asynch_Connect
+ *
+ */
+class ACE_Export ACE_POSIX_Asynch_Connect :
+ public virtual ACE_Asynch_Connect_Impl,
+ public ACE_POSIX_Asynch_Operation,
+ public ACE_Event_Handler
+{
+public:
+
+ /// Constructor.
+ ACE_POSIX_Asynch_Connect (ACE_POSIX_Proactor * posix_proactor);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Connect (void);
+
+ /**
+ * This belongs to ACE_POSIX_Asynch_Operation. We forward
+ * this call to that method. We have put this here to avoid the
+ * compiler warnings.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * This starts off an asynchronous connect.
+ *
+ * @arg connect_handle will be used for the connect call. If
+ * ACE_INVALID_HANDLE is specified, a new
+ * handle will be created.
+ */
+ int connect (ACE_HANDLE connect_handle,
+ const ACE_Addr &remote_sap,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /**
+ * Cancel all pending pseudo-asynchronus requests
+ * Behavior as usual AIO request
+ */
+ int cancel (void);
+
+ /**
+ * Close performs cancellation of all pending requests.
+ */
+ int close (void);
+
+ /// virtual from ACE_Event_Handler
+ ACE_HANDLE get_handle (void) const;
+
+ /// virtual from ACE_Event_Handler
+ void set_handle (ACE_HANDLE handle);
+
+ /// virtual from ACE_Event_Handler
+ /// The default action on handle_input() and handle_exception is to
+ /// return -1. Since that's what we want to do, just reuse them.
+ /// handle_output(), however, is where successful connects are reported.
+ int handle_output (ACE_HANDLE handle);
+
+ /// virtual from ACE_Event_Handler
+ int handle_close (ACE_HANDLE handle, ACE_Reactor_Mask close_mask) ;
+
+private:
+ int connect_i (ACE_POSIX_Asynch_Connect_Result *result,
+ const ACE_Addr & remote_sap,
+ const ACE_Addr & local_sap,
+ int reuse_addr);
+
+ int post_result (ACE_POSIX_Asynch_Connect_Result *result, bool flg_post);
+
+ /// Cancel uncompleted connect operations.
+ /**
+ * @arg flg_notify Indicates whether or not we should send notification
+ * about canceled accepts. If this is false, don't send
+ * notifications about canceled connects. If true, notify
+ * user about canceled connects according POSIX
+ * standards we should receive notifications on canceled
+ * AIO requests.
+ */
+ int cancel_uncompleted (bool flg_notify, ACE_Handle_Set &set);
+
+ bool flg_open_ ;
+ /// true - Connect is registered in ACE_Asynch_Pseudo_Task
+ /// false - Aceept is deregisted in ACE_Asynch_Pseudo_Task
+
+ typedef ACE_Map_Manager<ACE_HANDLE, ACE_POSIX_Asynch_Connect_Result *, ACE_SYNCH_NULL_MUTEX>
+ MAP_MANAGER;
+
+ /// @deprecated (Two) Deprecated typedefs. Use the map traits instead.
+ typedef MAP_MANAGER::ITERATOR MAP_ITERATOR;
+ typedef MAP_MANAGER::ENTRY MAP_ENTRY;
+
+ /// Map of Result pointers that correspond to all the pending connects.
+ MAP_MANAGER result_map_;
+
+ /// The lock to protect the result map which is shared. The queue
+ /// is updated by main thread in the register function call and
+ /// through the auxillary thread in the asynch pseudo task.
+ ACE_SYNCH_MUTEX lock_;
+};
+
+
+/**
+ * @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 will have special permissions.
+ friend class ACE_POSIX_Asynch_Transmit_File;
+
+ /// Handlers do all the job.
+ friend class ACE_POSIX_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.
+ size_t bytes_to_write (void) const;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ size_t bytes_per_send (void) const;
+
+ /// Flags which were passed into transmit file.
+ u_long flags (void) const;
+
+protected:
+ ACE_POSIX_Asynch_Transmit_File_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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 (size_t 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.
+ size_t bytes_per_send_;
+
+ /// Flags which were passed into transmit file.
+ u_long flags_;
+};
+
+/**
+ * @class ACE_POSIX_Asynch_Transmit_File
+ *
+ * @brief Implementation for transmit_file will make use of
+ * POSIX_Asynch_Transmit_Handler.
+ */
+class ACE_Export ACE_POSIX_Asynch_Transmit_File : public virtual ACE_Asynch_Transmit_File_Impl,
+ public ACE_POSIX_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_Asynch_Transmit_File (ACE_POSIX_Proactor *posix_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 @a bytes_to_write will be
+ * written to the <socket>. If you want to send the entire file,
+ * let @a bytes_to_write = 0. @a 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,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t bytes_per_send,
+ u_long flags,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Transmit_File (void);
+};
+
+
+/**
+ * @class ACE_POSIX_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_Asynch_Read_Dgram : public virtual ACE_Asynch_Read_Dgram_Impl,
+ public ACE_POSIX_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_Asynch_Read_Dgram (ACE_POSIX_Proactor *posix_proactor);
+ virtual ~ACE_POSIX_Asynch_Read_Dgram (void);
+
+ /** This method queues an asynchronous read. Up to
+ * @a message_block->total_size() bytes will be read and stored in the
+ * @a message_block beginning at its write pointer. The @a message_block
+ * write pointer will be updated to reflect any added bytes if the read
+ * operation is successful completed.
+ * Priority of the operation is specified by @a 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. @a signal_number argument is a no-op on non-POSIX4 systems.
+ *
+ * @note Unlike the Windows version of this facility, no indication of
+ * immediate success can be returned, and @a number_of_bytes_read is
+ * never used.
+ *
+ * @arg flags Not used.
+ * @arg protocol_family Not used.
+ * @retval 0 The IO will complete asynchronously.
+ * @retval -1 There was an error; see @c errno to get the error code.
+ *
+ */
+ 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);
+
+protected:
+ /// Do-nothing constructor.
+ ACE_POSIX_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 will have special permissions.
+ friend class ACE_POSIX_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.
+ size_t 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;
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Write_Stream factory.
+ ACE_POSIX_Asynch_Write_Dgram_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_Proactor will call this method when the write completes.
+ virtual void complete (size_t 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.
+ size_t 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_Asynch_Write_Dgram
+ *
+ * @brief This class is a factory for starting off asynchronous writes
+ * on a UDP socket. The UDP socket must be "connected", as there is
+ * no facility for specifying the destination address on each send
+ * operation.
+ *
+ * Once @c open() is called, multiple asynchronous writes can
+ * started using this class. A ACE_Asynch_Write_Stream::Result
+ * will be passed back to the associated completion handler when the
+ * asynchronous write completes through the
+ * ACE_Handler::handle_write_stream() callback.
+ */
+class ACE_Export ACE_POSIX_Asynch_Write_Dgram : public virtual ACE_Asynch_Write_Dgram_Impl,
+ public ACE_POSIX_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_Asynch_Write_Dgram (ACE_POSIX_Proactor *posix_proactor);
+
+ /// Destructor
+ virtual ~ACE_POSIX_Asynch_Write_Dgram (void);
+
+ /** This method queues an asynchronous send. Up to
+ * @a message_block->total_length bytes will be sent, beginning at the
+ * read pointer. The @a message_block read pointer will be updated to
+ * reflect the sent bytes if the send operation is successful completed.
+ *
+ * Priority of the operation is specified by @a priority. On POSIX,
+ * this is supported. Works like @c 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, etc.
+ * @a signal_number is a no-op on non-POSIX4 systems.
+ *
+ * @note Unlike the Windows version of this facility, no indication of
+ * immediate success can be returned, and @a number_of_bytes_sent is
+ * never used.
+ *
+ * @arg flags Not used.
+ * @arg addr Not used.
+ * @retval 0 The IO will complete asynchronously.
+ * @retval -1 There was an error; see @c errno to get the error code.
+ */
+ 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);
+
+protected:
+ /// Do-nothing constructor.
+ ACE_POSIX_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_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.
+ size_t 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 (void) const;
+
+ /// The flags used in the read
+ int flags (void) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Read_Dgram factory.
+ ACE_POSIX_Asynch_Read_Dgram_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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);
+
+ /// Proactor will call this method when the read completes.
+ virtual void complete (size_t 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.
+ size_t 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_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_AIO_CALLS */
+#endif /* ACE_POSIX_ASYNCH_IO_H */
diff --git a/ACE/ace/POSIX_CB_Proactor.cpp b/ACE/ace/POSIX_CB_Proactor.cpp
new file mode 100644
index 00000000000..3ce4218090a
--- /dev/null
+++ b/ACE/ace/POSIX_CB_Proactor.cpp
@@ -0,0 +1,185 @@
+// $Id$
+
+#include "ace/POSIX_CB_Proactor.h"
+
+#if defined (ACE_HAS_AIO_CALLS) && !defined (ACE_HAS_BROKEN_SIGEVENT_STRUCT)
+
+#include "ace/Task_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Object_Manager.h"
+#include "ace/OS_NS_sys_time.h"
+
+ACE_RCSID (ace,
+ POSIX_CB_Proactor,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_POSIX_CB_Proactor::ACE_POSIX_CB_Proactor (size_t max_aio_operations)
+ : ACE_POSIX_AIOCB_Proactor (max_aio_operations,
+ ACE_POSIX_Proactor::PROACTOR_CB),
+ sema_ ((unsigned int) 0)
+{
+ // we should start pseudo-asynchronous accept task
+ // one per all future acceptors
+
+ this->get_asynch_pseudo_task ().start ();
+}
+
+// Destructor.
+ACE_POSIX_CB_Proactor::~ACE_POSIX_CB_Proactor (void)
+{
+ this->close ();
+}
+
+ACE_POSIX_Proactor::Proactor_Type
+ACE_POSIX_CB_Proactor::get_impl_type (void)
+{
+ return PROACTOR_CB;
+}
+
+void ACE_POSIX_CB_Proactor::aio_completion_func (sigval cb_data)
+{
+ ACE_POSIX_CB_Proactor * impl = static_cast<ACE_POSIX_CB_Proactor *> (cb_data.sival_ptr);
+ if ( impl != 0 )
+ impl->notify_completion (0);
+}
+
+#if defined (ACE_HAS_SIG_C_FUNC)
+extern "C" void
+ACE_POSIX_CB_Proactor_aio_completion (sigval cb_data)
+{
+ ACE_POSIX_CB_Proactor::aio_completion_func (cb_data);
+}
+#endif /* ACE_HAS_SIG_C_FUNC */
+
+int
+ACE_POSIX_CB_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_i (wait_time.msec ());
+}
+
+int
+ACE_POSIX_CB_Proactor::handle_events (void)
+{
+ return this->handle_events_i (ACE_INFINITE);
+}
+
+int
+ACE_POSIX_CB_Proactor::notify_completion (int sig_num)
+{
+ ACE_UNUSED_ARG (sig_num);
+
+ return this->sema_.release();
+}
+
+
+ssize_t
+ACE_POSIX_CB_Proactor::allocate_aio_slot (ACE_POSIX_Asynch_Result *result)
+{
+ ssize_t slot = ACE_POSIX_AIOCB_Proactor::allocate_aio_slot (result);
+ if (slot == -1)
+ return -1;
+
+ // setup OS notification methods for this aio
+ // @@ TODO: This gets the completion method back to this proactor to
+ // find the completed aiocb. It would be so much better to not only get
+ // the proactor, but the aiocb as well.
+#if defined(__sgi)
+ result->aio_sigevent.sigev_notify = SIGEV_CALLBACK;
+ result->aio_sigevent.sigev_func = aio_completion_func ;
+#else
+ result->aio_sigevent.sigev_notify = SIGEV_THREAD;
+# if defined (ACE_HAS_SIG_C_FUNC)
+ result->aio_sigevent.sigev_notify_function =
+ ACE_POSIX_CB_Proactor_aio_completion;
+# else
+ result->aio_sigevent.sigev_notify_function = aio_completion_func;
+# endif /* ACE_HAS_SIG_C_FUNC */
+ result->aio_sigevent.sigev_notify_attributes = 0;
+#endif /* __sgi */
+
+ result->aio_sigevent.sigev_value.sival_ptr = this ;
+
+ return slot;
+}
+
+int
+ACE_POSIX_CB_Proactor::handle_events_i (u_long milli_seconds)
+{
+
+ int result_wait=0;
+
+ // Wait for the signals.
+ if (milli_seconds == ACE_INFINITE)
+ {
+ result_wait = this->sema_.acquire();
+ }
+ else
+ {
+ // Wait for <milli_seconds> amount of time.
+ ACE_Time_Value abs_time = ACE_OS::gettimeofday ()
+ + ACE_Time_Value (0, milli_seconds * 1000);
+
+ result_wait = this->sema_.acquire(abs_time);
+ }
+
+ // Check for errors
+ // but let continue work in case of errors
+ // we should check "post_completed" queue
+ if (result_wait == -1)
+ {
+ int const lerror = errno;
+ if (lerror != ETIME && // timeout
+ lerror != EINTR ) // interrupted system call
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_POSIX_CB_Proactor::handle_events:"
+ "semaphore acquire failed"
+ ));
+ }
+
+ size_t index = 0; // start index to scan aiocb list
+ size_t count = this->aiocb_list_max_size_; // max number to iterate
+
+ int error_status = 0;
+ size_t return_status = 0;
+
+ int ret_aio = 0;
+ int ret_que = 0;
+
+ for (;; ret_aio++)
+ {
+ ACE_POSIX_Asynch_Result * asynch_result =
+ this->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.
+ 0, // No completion key.
+ error_status); // Error
+ }
+
+ // process post_completed results
+ 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_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_AIO_CALLS && !ACE_HAS_BROKEN_SIGEVENT_STRUCT */
diff --git a/ACE/ace/POSIX_CB_Proactor.h b/ACE/ace/POSIX_CB_Proactor.h
new file mode 100644
index 00000000000..a37e72e139e
--- /dev/null
+++ b/ACE/ace/POSIX_CB_Proactor.h
@@ -0,0 +1,97 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file POSIX_CB_Proactor.h
+ *
+ * $Id$
+ *
+ * @author Alexander Libman <alibman@ihug.com.au>
+ */
+//=============================================================================
+
+#ifndef ACE_POSIX_CB_PROACTOR_H
+#define ACE_POSIX_CB_PROACTOR_H
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_AIO_CALLS)
+
+#include "ace/Synch_Traits.h"
+#include "ace/Thread_Semaphore.h"
+#include "ace/Null_Semaphore.h"
+
+#include "ace/POSIX_Proactor.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_POSIX_CB_Proactor
+ *
+ * @brief Implementation of Callback-based Proactor
+ * };
+ */
+class ACE_Export ACE_POSIX_CB_Proactor : public ACE_POSIX_AIOCB_Proactor
+{
+
+public:
+ virtual Proactor_Type get_impl_type (void);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_CB_Proactor (void);
+
+ /// Constructor defines max number asynchronous operations that can
+ /// be started at the same time.
+ ACE_POSIX_CB_Proactor (size_t max_aio_operations = ACE_AIO_DEFAULT_SIZE);
+
+ // This only public so the "extern C" completion function can see it
+ // when needed.
+ static void aio_completion_func (sigval cb_data);
+
+protected:
+
+ /**
+ * Dispatch a single set of events. If @a 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 @a 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);
+
+ /// Find free slot to store result and aiocb pointer
+ virtual ssize_t 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);
+
+ /**
+ * Dispatch a single set of events. If @a milli_seconds elapses
+ * before any events occur, return 0. Return 1 if a completion is
+ * dispatched. Return -1 on errors.
+ */
+ int handle_events_i (u_long milli_seconds);
+
+ /// Semaphore variable to notify
+ /// used to wait the first AIO start
+ ACE_SYNCH_SEMAPHORE sema_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_AIO_CALLS */
+#endif /* ACE_POSIX_CB_PROACTOR_H*/
diff --git a/ACE/ace/POSIX_Proactor.cpp b/ACE/ace/POSIX_Proactor.cpp
new file mode 100644
index 00000000000..1c2c271efb9
--- /dev/null
+++ b/ACE/ace/POSIX_Proactor.cpp
@@ -0,0 +1,2064 @@
+// $Id$
+
+#include "ace/POSIX_Proactor.h"
+
+#if defined (ACE_HAS_AIO_CALLS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/POSIX_Proactor.inl"
+#endif /* __ACE_INLINE__ */
+
+# if defined (ACE_HAS_SYSINFO)
+# include /**/ <sys/systeminfo.h>
+# endif /* ACE_HAS_SYS_INFO */
+
+#include "ace/ACE.h"
+#include "ace/Flag_Manip.h"
+#include "ace/Task_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Object_Manager.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/OS_NS_unistd.h"
+
+#if defined (sun)
+# include "ace/OS_NS_strings.h"
+#endif /* sun */
+
+// *********************************************************************
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_POSIX_Wakeup_Completion
+ *
+ * This result object is used by the <end_event_loop> of the
+ * ACE_Proactor interface to wake up all the threads blocking
+ * for completions.
+ */
+class ACE_POSIX_Wakeup_Completion : public ACE_POSIX_Asynch_Result
+{
+public:
+ /// Constructor.
+ ACE_POSIX_Wakeup_Completion (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void *act = 0,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Wakeup_Completion (void);
+
+
+ /// This method calls the <handler>'s <handle_wakeup> method.
+ virtual void complete (size_t bytes_transferred = 0,
+ int success = 1,
+ const void *completion_key = 0,
+ u_long error = 0);
+};
+
+// *********************************************************************
+ACE_POSIX_Proactor::ACE_POSIX_Proactor (void)
+ : os_id_ (ACE_OS_UNDEFINED)
+{
+#if defined(sun)
+
+ os_id_ = ACE_OS_SUN; // set family
+
+ char Buf [32];
+
+ ::memset(Buf,0,sizeof(Buf));
+
+ ACE_OS::sysinfo (SI_RELEASE , Buf, sizeof(Buf)-1);
+
+ if (ACE_OS::strcasecmp (Buf , "5.6") == 0)
+ os_id_ = ACE_OS_SUN_56;
+ else if (ACE_OS::strcasecmp (Buf , "5.7") == 0)
+ os_id_ = ACE_OS_SUN_57;
+ else if (ACE_OS::strcasecmp (Buf , "5.8") == 0)
+ os_id_ = ACE_OS_SUN_58;
+
+#elif defined(HPUX)
+
+ os_id_ = ACE_OS_HPUX; // set family
+
+#elif defined(__sgi)
+
+ os_id_ = ACE_OS_IRIX; // set family
+
+#elif defined(__OpenBSD)
+
+ os_id_ = ACE_OS_OPENBSD; // 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_Impl *
+ACE_POSIX_Proactor::create_asynch_read_stream (void)
+{
+ ACE_Asynch_Read_Stream_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Read_Stream (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_Stream_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_read_stream_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+
+ACE_Asynch_Write_Stream_Impl *
+ACE_POSIX_Proactor::create_asynch_write_stream (void)
+{
+ ACE_Asynch_Write_Stream_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Write_Stream (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_Stream_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_write_stream_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+
+ACE_Asynch_Read_File_Impl *
+ACE_POSIX_Proactor::create_asynch_read_file (void)
+{
+ ACE_Asynch_Read_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Read_File (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_File_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_read_file_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+
+ACE_Asynch_Write_File_Impl *
+ACE_POSIX_Proactor::create_asynch_write_file (void)
+{
+ ACE_Asynch_Write_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Write_File (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_File_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_write_file_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+
+ACE_Asynch_Read_Dgram_Impl *
+ACE_POSIX_Proactor::create_asynch_read_dgram (void)
+{
+ ACE_Asynch_Read_Dgram_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Read_Dgram (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_Dgram_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_read_dgram_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ handle,
+ message_block,
+ bytes_to_read,
+ flags,
+ protocol_family,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+
+ return implementation;
+}
+
+
+ACE_Asynch_Write_Dgram_Impl *
+ACE_POSIX_Proactor::create_asynch_write_dgram (void)
+{
+ ACE_Asynch_Write_Dgram_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Write_Dgram (this),
+ 0);
+
+ return implementation;
+}
+
+ACE_Asynch_Write_Dgram_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_write_dgram_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ handle,
+ message_block,
+ bytes_to_write,
+ flags,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+
+ return implementation;
+}
+
+
+ACE_Asynch_Accept_Impl *
+ACE_POSIX_Proactor::create_asynch_accept (void)
+{
+ ACE_Asynch_Accept_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Accept (this),
+ 0);
+
+ return implementation;
+}
+
+ACE_Asynch_Accept_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_accept_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ listen_handle,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+
+ACE_Asynch_Connect_Impl *
+ACE_POSIX_Proactor::create_asynch_connect (void)
+{
+ ACE_Asynch_Connect_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Connect (this),
+ 0);
+
+ return implementation;
+}
+
+ACE_Asynch_Connect_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_connect_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Connect_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Connect_Result (handler_proxy,
+ connect_handle,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+
+ACE_Asynch_Transmit_File_Impl *
+ACE_POSIX_Proactor::create_asynch_transmit_file (void)
+{
+ ACE_Asynch_Transmit_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Transmit_File (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Transmit_File_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_transmit_file_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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_proxy,
+ 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_POSIX_Asynch_Timer *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Timer (handler_proxy,
+ 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,
+ size_t bytes_transferred,
+ const void */* completion_key*/,
+ u_long error)
+{
+ ACE_SEH_TRY
+ {
+ // Call completion hook
+ asynch_result->complete (bytes_transferred,
+ error ? 0 : 1,
+ 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 (int ci = 0; ci < how_many; ci++)
+ {
+ ACE_NEW_RETURN
+ (wakeup_completion,
+ ACE_POSIX_Wakeup_Completion (this->wakeup_handler_.proxy ()),
+ -1);
+ if (this->post_completion (wakeup_completion) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+ACE_POSIX_Proactor::Proactor_Type
+ACE_POSIX_Proactor::get_impl_type (void)
+{
+ return PROACTOR_POSIX;
+}
+
+
+/**
+ * @class ACE_AIOCB_Notify_Pipe_Manager
+ *
+ * @brief 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>.
+
+ * <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.
+ */
+class ACE_AIOCB_Notify_Pipe_Manager : public ACE_Handler
+{
+public:
+ /// Constructor. You need the posix proactor because you need to call
+ /// <application_specific_code>
+ ACE_AIOCB_Notify_Pipe_Manager (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+
+ /// Destructor.
+ virtual ~ACE_AIOCB_Notify_Pipe_Manager (void);
+
+ /// Send the result pointer through the notification pipe.
+ int notify ();
+
+ /// This is the call back method when <Asynch_Read> from the pipe is
+ /// complete.
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+
+private:
+ /// The implementation proactor class.
+ ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor_;
+
+ /// Message block to get ACE_POSIX_Asynch_Result pointer from the pipe.
+ ACE_Message_Block message_block_;
+
+ /// Pipe for the communication between Proactor and the
+ /// Asynch_Accept/Asynch_Connect and other post_completions
+ ACE_Pipe pipe_;
+
+ /// To do asynch_read on the pipe.
+ ACE_POSIX_Asynch_Read_Stream read_stream_;
+
+ /// Default constructor. Shouldnt be called.
+ ACE_AIOCB_Notify_Pipe_Manager (void);
+};
+
+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 (2)),
+ 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);
+
+ // Set read side in BLOCK mode
+ ACE::clr_flags (this->pipe_.read_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->proxy (),
+ 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)
+{
+ // 1. try to cancel pending aio
+ this->read_stream_.cancel ();
+
+ // 2. close both handles
+ // Destuctor of ACE_Pipe does not close handles.
+ // We can not use ACE_Pipe::close() as it
+ // closes read_handle and than write_handle.
+ // In some systems close() may wait for
+ // completion for all asynch. pending requests.
+ // So we should close write_handle firstly
+ // to force read completion ( if 1. does not help )
+ // and then read_handle and not vice versa
+
+ ACE_HANDLE h = this->pipe_.write_handle ();
+ if (h != ACE_INVALID_HANDLE)
+ ACE_OS::closesocket (h);
+
+ h = this->pipe_.read_handle ();
+ if ( h != ACE_INVALID_HANDLE)
+ ACE_OS::closesocket (h);
+
+}
+
+
+int
+ACE_AIOCB_Notify_Pipe_Manager::notify ()
+{
+ // Send the result pointer through the pipe.
+ char char_send = 0;
+ ssize_t ret_val = ACE::send (this->pipe_.write_handle (),
+ &char_send,
+ sizeof (char_send));
+
+ if (ret_val < 0)
+ {
+ if (errno != EWOULDBLOCK)
+#if 0
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P %t):%p\n"),
+ ACE_TEXT ("ACE_AIOCB_Notify_Pipe_Manager::notify")
+ ACE_TEXT ("Error:Writing on to notify pipe failed")));
+#endif /* 0 */
+ return -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 (-1 == this->read_stream_.read (this->message_block_,
+ 1, // enough to read 1 byte
+ 0, // ACT
+ 0)) // Priority
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_TEXT ("ACE_AIOCB_Notify_Pipe_Manager::handle_read_stream:")
+ ACE_TEXT ("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 ();
+
+ this->create_result_aiocb_list ();
+
+ this->create_notify_manager ();
+
+ // start pseudo-asynchronous accept task
+ // one per all future acceptors
+ this->get_asynch_pseudo_task().start ();
+
+}
+
+// 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)
+ : 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
+ this->check_max_aio_num ();
+
+ this->create_result_aiocb_list ();
+
+ // @@ 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)
+{
+ this->close();
+}
+
+ACE_POSIX_Proactor::Proactor_Type
+ACE_POSIX_AIOCB_Proactor::get_impl_type (void)
+{
+ return PROACTOR_AIOCB;
+}
+
+
+int
+ACE_POSIX_AIOCB_Proactor::close (void)
+{
+ // stop asynch accept task
+ this->get_asynch_pseudo_task().stop ();
+
+ this->delete_notify_manager ();
+
+ this->clear_result_queue ();
+
+ return this->delete_result_aiocb_list ();
+}
+
+void ACE_POSIX_AIOCB_Proactor::set_notify_handle (ACE_HANDLE h)
+{
+ notify_pipe_read_handle_ = h;
+}
+
+int ACE_POSIX_AIOCB_Proactor::create_result_aiocb_list (void)
+{
+ if (aiocb_list_ != 0)
+ return 0;
+
+ ACE_NEW_RETURN (aiocb_list_, aiocb *[aiocb_list_max_size_], -1);
+
+ ACE_NEW_RETURN (result_list_,
+ ACE_POSIX_Asynch_Result *[aiocb_list_max_size_],
+ -1);
+
+ // Initialize the array.
+ for (size_t ai = 0; ai < this->aiocb_list_max_size_; ai++)
+ {
+ aiocb_list_[ai] = 0;
+ result_list_[ai] = 0;
+ }
+
+ return 0;
+}
+
+int ACE_POSIX_AIOCB_Proactor::delete_result_aiocb_list (void)
+{
+ if (aiocb_list_ == 0) // already deleted
+ return 0;
+
+ size_t ai;
+
+ // Try to cancel all uncompleted operations; POSIX systems may have
+ // hidden system threads that still can work with our aiocbs!
+ for (ai = 0; ai < aiocb_list_max_size_; ai++)
+ if (this->aiocb_list_[ai] != 0) // active operation
+ this->cancel_aiocb (result_list_[ai]);
+
+ int num_pending = 0;
+
+ for (ai = 0; ai < aiocb_list_max_size_; ai++)
+ {
+ if (this->aiocb_list_[ai] == 0 ) // not active operation
+ continue;
+
+ // Get the error and return status of the aio_ operation.
+ int error_status = 0;
+ size_t transfer_count = 0;
+ int flg_completed = this->get_result_status (result_list_[ai],
+ error_status,
+ transfer_count);
+
+ //don't delete uncompleted AIOCB's
+ if (flg_completed == 0) // not completed !!!
+ {
+ num_pending++;
+#if 0
+ char * errtxt = ACE_OS::strerror (error_status);
+ if (errtxt == 0)
+ errtxt ="?????????";
+
+ char * op = (aiocb_list_[ai]->aio_lio_opcode == LIO_WRITE )?
+ "WRITE":"READ" ;
+
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("slot=%d op=%s status=%d xfercnt=%d %s\n"),
+ ai,
+ op,
+ error_status,
+ transfer_count,
+ errtxt));
+#endif /* 0 */
+ }
+ else // completed , OK
+ {
+ delete this->result_list_[ai];
+ this->result_list_[ai] = 0;
+ this->aiocb_list_[ai] = 0;
+ }
+ }
+
+ // If it is not possible cancel some operation (num_pending > 0 ),
+ // we can do only one thing -report about this
+ // and complain about POSIX implementation.
+ // We know that we have memory leaks, but it is better than
+ // segmentation fault!
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT("ACE_POSIX_AIOCB_Proactor::delete_result_aiocb_list\n")
+ ACE_TEXT(" number pending AIO=%d\n"),
+ num_pending));
+
+ delete [] this->aiocb_list_;
+ this->aiocb_list_ = 0;
+
+ delete [] this->result_list_;
+ this->result_list_ = 0;
+
+ return (num_pending == 0 ? 0 : -1);
+ // ?? or just always return 0;
+}
+
+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) || defined (__FreeBSD__)
+ // 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 || __FreeBSD__ */
+
+ // 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_));
+
+#if defined(__sgi)
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT( "SGI IRIX specific: aio_init!\n")));
+
+//typedef struct aioinit {
+// int aio_threads; /* The number of aio threads to start (5) */
+// int aio_locks; /* Initial number of preallocated locks (3) */
+// int aio_num; /* estimated total simultanious aiobc structs (1000) */
+// int aio_usedba; /* Try to use DBA for raw I/O in lio_listio (0) */
+// int aio_debug; /* turn on debugging (0) */
+// int aio_numusers; /* max number of user sprocs making aio_* calls (5) */
+// int aio_reserved[3];
+//} aioinit_t;
+
+ aioinit_t aioinit;
+
+ aioinit.aio_threads = 10; /* The number of aio threads to start (5) */
+ aioinit.aio_locks = 20; /* Initial number of preallocated locks (3) */
+ /* estimated total simultaneous aiobc structs (1000) */
+ aioinit.aio_num = aiocb_list_max_size_;
+ aioinit.aio_usedba = 0; /* Try to use DBA for raw IO in lio_listio (0) */
+ aioinit.aio_debug = 0; /* turn on debugging (0) */
+ aioinit.aio_numusers = 100; /* max number of user sprocs making aio_* calls (5) */
+ aioinit.aio_reserved[0] = 0;
+ aioinit.aio_reserved[1] = 0;
+ aioinit.aio_reserved[2] = 0;
+
+ aio_sgi_init (&aioinit);
+
+#endif
+
+ return;
+}
+
+void
+ACE_POSIX_AIOCB_Proactor::create_notify_manager (void)
+{
+ // Remember! this issues a Asynch_Read
+ // on the notify pipe for doing the Asynch_Accept/Connect.
+
+ 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_i (wait_time.msec ());
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::handle_events (void)
+{
+ return this->handle_events_i (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.
+ 0, // No completion key.
+ result->error()); //0, No error.
+
+ ret_val++;
+ }
+
+ return ret_val;
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::handle_events_i (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)) * 1000000;
+ 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,
+ ACE_TEXT ("%N:%l:(%P|%t)::%p\n"),
+ ACE_TEXT ("handle_events: aio_suspend failed")));
+ // 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;
+ size_t transfer_count = 0;
+
+ for (;; retval++)
+ {
+ ACE_POSIX_Asynch_Result *asynch_result =
+ find_completed_aio (error_status,
+ transfer_count,
+ index,
+ count);
+
+ if (asynch_result == 0)
+ break;
+
+ // Call the application code.
+ this->application_specific_code (asynch_result,
+ transfer_count,
+ 0, // No completion key.
+ error_status);
+ }
+ }
+
+ // process post_completed results
+ retval += this->process_result_queue ();
+
+ return retval > 0 ? 1 : 0;
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::get_result_status (ACE_POSIX_Asynch_Result *asynch_result,
+ int &error_status,
+ size_t &transfer_count)
+{
+ transfer_count = 0;
+
+ // Get the error status of the aio_ operation.
+ error_status = aio_error (asynch_result);
+ if (error_status == EINPROGRESS)
+ return 0; // not completed
+
+ ssize_t op_return = aio_return (asynch_result);
+ if (op_return > 0)
+ transfer_count = static_cast<size_t> (op_return);
+ // else transfer_count is already 0, error_status reports the error.
+ return 1; // completed
+}
+
+ACE_POSIX_Asynch_Result *
+ACE_POSIX_AIOCB_Proactor::find_completed_aio (int &error_status,
+ size_t &transfer_count,
+ 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;
+
+ if (num_started_aio_ == 0) // save time
+ return 0;
+
+ 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;
+
+ if (0 != this->get_result_status (result_list_[index],
+ error_status,
+ transfer_count)) // completed
+ break;
+
+ } // end for
+
+ if (count == 0) // all processed , nothing found
+ return 0;
+ 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;
+}
+
+
+int
+ACE_POSIX_AIOCB_Proactor::start_aio (ACE_POSIX_Asynch_Result *result,
+ ACE_POSIX_Proactor::Opcode op)
+{
+ ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::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 ACE_POSIX_Proactor::ACE_OPCODE_READ:
+ result->aio_lio_opcode = LIO_READ;
+ break;
+
+ case ACE_POSIX_Proactor::ACE_OPCODE_WRITE:
+ result->aio_lio_opcode = LIO_WRITE;
+ break;
+
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%N:%l:(%P|%t)::")
+ ACE_TEXT ("start_aio: Invalid op code %d\n"),
+ op),
+ -1);
+ }
+
+ if (ret_val != 0) // No free slot
+ {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ // Find a free slot and store.
+
+ ssize_t slot = allocate_aio_slot (result);
+
+ if (slot < 0)
+ return -1;
+
+ size_t index = static_cast<size_t> (slot);
+
+ result_list_[index] = result; //Store result ptr anyway
+ aiocb_list_cur_size_++;
+
+ ret_val = start_aio_i (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_--;
+ return -1;
+}
+
+ssize_t
+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 static_cast<ssize_t> (i);
+}
+
+// start_aio_i 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_i (ACE_POSIX_Asynch_Result *result)
+{
+ ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_aio_i");
+
+ int ret_val;
+ const ACE_TCHAR *ptype = 0;
+
+ // Start IO
+
+ switch (result->aio_lio_opcode )
+ {
+ case LIO_READ :
+ ptype = ACE_TEXT ("read ");
+ ret_val = aio_read (result);
+ break;
+ case LIO_WRITE :
+ ptype = ACE_TEXT ("write");
+ ret_val = aio_write (result);
+ break;
+ default:
+ ptype = ACE_TEXT ("?????");
+ ret_val = -1;
+ break;
+ }
+
+ if (ret_val == 0)
+ {
+ ++this->num_started_aio_;
+ }
+ else // if (ret_val == -1)
+ {
+ if (errno == EAGAIN || errno == ENOMEM) //Ok, it will be deferred AIO
+ ret_val = 1;
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%N:%l:(%P | %t)::start_aio_i: aio_%s %p\n"),
+ ptype,
+ ACE_TEXT ("queueing failed")));
+ }
+
+ 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_i (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 < this->aiocb_list_max_size_; ai++)
+ {
+ if (this->result_list_[ai] == 0) // Skip empty slot
+ continue;
+
+ if (this->result_list_[ai]->aio_fildes != handle) // Not ours
+ continue;
+
+ ++num_total;
+
+ ACE_POSIX_Asynch_Result *asynch_result = this->result_list_[ai];
+
+ if (this->aiocb_list_[ai] == 0) // Canceling a deferred operation
+ {
+ num_cancelled++;
+ this->num_deferred_aiocb_--;
+
+ this->aiocb_list_[ai] = 0;
+ this->result_list_[ai] = 0;
+ this->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 method is called from cancel_aio
+ // to cancel a previously submitted 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 // (rc == AIO_NOTCANCELED)
+ return 2;
+}
+
+
+// *********************************************************************
+
+#if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
+
+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.
+ ACE_OS::sigemptyset (&this->RT_completion_signals_);
+
+ // Add the signal number to the signal set.
+ if (ACE_OS::sigaddset (&this->RT_completion_signals_, ACE_SIGRTMIN) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("ACE_POSIX_SIG_Proactor: %p\n"),
+ ACE_TEXT ("sigaddset")));
+ this->block_signals ();
+ // Set up the signal action for SIGRTMIN.
+ this->setup_signal_handler (ACE_SIGRTMIN);
+
+ // we do not have to create notify manager
+ // but we should start pseudo-asynchronous accept task
+ // one per all future acceptors
+
+ this->get_asynch_pseudo_task().start ();
+ 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->block_signals ();
+
+ // we do not have to create notify manager
+ // but we should start pseudo-asynchronous accept task
+ // one per all future acceptors
+
+ this->get_asynch_pseudo_task().start ();
+ return;
+}
+
+ACE_POSIX_SIG_Proactor::~ACE_POSIX_SIG_Proactor (void)
+{
+ this->close ();
+
+ // @@ Enable the masked signals again.
+}
+
+ACE_POSIX_Proactor::Proactor_Type
+ACE_POSIX_SIG_Proactor::get_impl_type (void)
+{
+ return PROACTOR_SIG;
+}
+
+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_i (&wait_time);
+}
+
+int
+ACE_POSIX_SIG_Proactor::handle_events (void)
+{
+ return this->handle_events_i (0);
+}
+
+int
+ACE_POSIX_SIG_Proactor::notify_completion (int sig_num)
+{
+ // Get this process id.
+ pid_t const 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 (ACE_HAS_SIGVAL_SIGVAL_INT)
+ value.sigval_int = -1;
+#else
+ value.sival_int = -1;
+#endif /* ACE_HAS_SIGVAL_SIGVAL_INT */
+
+ // 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ act,
+ tv,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+#if 0
+static 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));
+}
+#endif /*if 0*/
+
+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
+#if 0
+ 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);
+#else
+ ACE_UNUSED_ARG(signal_number);
+#endif
+ return 0;
+}
+
+
+int
+ACE_POSIX_SIG_Proactor::block_signals (void) const
+{
+ return ACE_OS::pthread_sigmask (SIG_BLOCK, &this->RT_completion_signals_, 0);
+}
+
+ssize_t
+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);
+
+ // 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 (ACE_HAS_SIGVAL_SIGVAL_INT)
+ result->aio_sigevent.sigev_value.sigval_int = static_cast<int> (i);
+#else
+ result->aio_sigevent.sigev_value.sival_int = static_cast<int> (i);
+#endif /* ACE_HAS_SIGVAL_SIGVAL_INT */
+
+ return static_cast<ssize_t> (i);
+}
+
+int
+ACE_POSIX_SIG_Proactor::handle_events_i (const ACE_Time_Value *timeout)
+{
+ int result_sigwait = 0;
+ siginfo_t sig_info;
+
+ do
+ {
+ // Wait for the signals.
+ if (timeout == 0)
+ {
+ result_sigwait = ACE_OS::sigwaitinfo (&this->RT_completion_signals_,
+ &sig_info);
+ }
+ else
+ {
+ result_sigwait = ACE_OS::sigtimedwait (&this->RT_completion_signals_,
+ &sig_info,
+ timeout);
+ if (result_sigwait == -1 && errno == EAGAIN)
+ return 0;
+ }
+ }
+ while (result_sigwait == -1 && errno == EINTR);
+
+ if (result_sigwait == -1) // Not a timeout, not EINTR: tell caller of error
+ return -1;
+
+ // Decide what to do. We always check the completion queue since it's an
+ // easy, quick check. What is decided here is whether to check for
+ // I/O completions and, if so, how completely to scan.
+ int flg_aio = 0; // 1 if AIO Completion possible
+
+ size_t index = 0; // start index to scan aiocb list
+ size_t count = 1; // max number of aiocbs to scan
+ int error_status = 0;
+ size_t transfer_count = 0;
+
+ if (sig_info.si_code == SI_ASYNCIO || this->os_id_ == ACE_OS_SUN_56)
+ {
+ flg_aio = 1; // AIO signal received
+ // define index to start
+ // nothing will happen if it contains garbage
+#if defined (ACE_HAS_SIGVAL_SIGVAL_INT)
+ index = static_cast<size_t> (sig_info.si_value.sigval_int);
+#else
+ index = static_cast<size_t> (sig_info.si_value.sival_int);
+#endif /* ACE_HAS_SIGVAL_SIGVAL_INT */
+ // Assume we have a correctly-functioning implementation, and that
+ // there is one I/O to process, and it's correctly specified in the
+ // siginfo received. There are, however, some special situations
+ // where this isn't true...
+ if (os_id_ == ACE_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, hence the
+ // OS_SUN_56 addition to the si_code check, above.
+ count = aiocb_list_max_size_;
+ }
+ }
+ else if (sig_info.si_code != SI_QUEUE)
+ {
+ // 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,
+ ACE_TEXT ("%N:%l:(%P | %t): ")
+ ACE_TEXT ("ACE_POSIX_SIG_Proactor::handle_events: ")
+ ACE_TEXT ("Unexpected signal code (%d) returned ")
+ ACE_TEXT ("from sigwait; expecting %d\n"),
+ result_sigwait, sig_info.si_code));
+ flg_aio = 1;
+ }
+
+ 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,
+ transfer_count,
+ index,
+ count);
+
+ if (asynch_result == 0)
+ break;
+
+ // Call the application code.
+ this->application_specific_code (asynch_result,
+ transfer_count,
+ 0, // No completion key.
+ error_status); // Error
+ }
+
+ // process post_completed results
+ ret_que = this->process_result_queue ();
+
+ // Uncomment this if you want to test
+ // and research the behavior of you system
+#if 0
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) NumAIO=%d NumQueue=%d\n",
+ ret_aio, ret_que));
+#endif
+
+ return ret_aio + ret_que > 0 ? 1 : 0;
+}
+
+#endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Timer::ACE_POSIX_Asynch_Timer
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_POSIX_Asynch_Result
+ (handler_proxy, act, event, 0, 0, priority, signal_number),
+ time_ (tv)
+{
+}
+
+void
+ACE_POSIX_Asynch_Timer::complete (size_t /* bytes_transferred */,
+ int /* success */,
+ const void * /* completion_key */,
+ u_long /* error */)
+{
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_time_out (this->time_, this->act ());
+}
+
+
+// *********************************************************************
+
+ACE_POSIX_Wakeup_Completion::ACE_POSIX_Wakeup_Completion
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_POSIX_Asynch_Result (handler_proxy,
+ act,
+ event,
+ 0,
+ 0,
+ priority,
+ signal_number)
+{
+}
+
+ACE_POSIX_Wakeup_Completion::~ACE_POSIX_Wakeup_Completion (void)
+{
+}
+
+void
+ACE_POSIX_Wakeup_Completion::complete (size_t /* bytes_transferred */,
+ int /* success */,
+ const void * /* completion_key */,
+ u_long /* error */)
+{
+
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_wakeup ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_AIO_CALLS */
diff --git a/ACE/ace/POSIX_Proactor.h b/ACE/ace/POSIX_Proactor.h
new file mode 100644
index 00000000000..5833ce47454
--- /dev/null
+++ b/ACE/ace/POSIX_Proactor.h
@@ -0,0 +1,659 @@
+// -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_AIO_CALLS)
+// POSIX implementation of Proactor depends on the <aio_> family of
+// system calls.
+
+#include "ace/Proactor_Impl.h"
+#include "ace/Free_List.h"
+#include "ace/Pipe.h"
+#include "ace/POSIX_Asynch_IO.h"
+#include "ace/Asynch_Pseudo_Task.h"
+
+#define ACE_AIO_MAX_SIZE 2048
+#define ACE_AIO_DEFAULT_SIZE 1024
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_POSIX_AIOCB_Proactor and
+ * ACE_POSIX_SIG_Proactor specialize this class for each strategy.
+ */
+class ACE_Export ACE_POSIX_Proactor : public ACE_Proactor_Impl
+{
+public:
+ enum Proactor_Type
+ {
+ /// Base class type
+ PROACTOR_POSIX = 0,
+
+ /// Aio_suspend() based
+ PROACTOR_AIOCB = 1,
+
+ /// Signals notifications
+ PROACTOR_SIG = 2,
+
+ /// SUN specific aiowait()
+ PROACTOR_SUN = 3,
+
+ /// Callback notifications
+ PROACTOR_CB = 4
+ };
+
+
+ enum SystemType // open for future extention
+ {
+ ACE_OS_UNDEFINED= 0x0000,
+ ACE_OS_WIN = 0x0100, // for future
+ ACE_OS_WIN_NT = ACE_OS_WIN | 0x0001,
+ ACE_OS_WIN_2000 = ACE_OS_WIN | 0x0002,
+ ACE_OS_SUN = 0x0200, // Sun Solaris family
+ ACE_OS_SUN_55 = ACE_OS_SUN | 0x0001,
+ ACE_OS_SUN_56 = ACE_OS_SUN | 0x0002,
+ ACE_OS_SUN_57 = ACE_OS_SUN | 0x0004,
+ ACE_OS_SUN_58 = ACE_OS_SUN | 0x0008,
+ ACE_OS_HPUX = 0x0400, // HPUX family
+ ACE_OS_HPUX_11 = ACE_OS_HPUX | 0x0001,
+ ACE_OS_LINUX = 0x0800, // Linux family
+ ACE_OS_FREEBSD = 0x1000, // FreeBSD family
+ ACE_OS_IRIX = 0x2000, // SGI IRIX family
+ ACE_OS_OPENBSD = 0x4000 // OpenBSD familty
+ };
+
+ enum Opcode {
+ ACE_OPCODE_READ = 1,
+ ACE_OPCODE_WRITE = 2
+ };
+
+ virtual Proactor_Type get_impl_type (void);
+
+ /// Virtual destructor.
+ virtual ~ACE_POSIX_Proactor (void);
+
+ /// Close down the Proactor.
+ virtual int close (void);
+
+ /**
+ * Dispatch a single set of events. If @a 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.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;
+
+ /**
+ * 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;
+
+ virtual int start_aio (ACE_POSIX_Asynch_Result *result, Opcode op) = 0;
+
+ virtual int cancel_aio (ACE_HANDLE h) = 0;
+
+ /// Task to process pseudo-asynchronous operations
+ ACE_Asynch_Pseudo_Task &get_asynch_pseudo_task ();
+
+ /// This function is a no-op function for Unix systems. Returns 0.
+ virtual int register_handle (ACE_HANDLE handle,
+ const void *completion_key);
+
+ /// @@ 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 factory and result objects. We
+ // create the right objects here in these methods.
+
+ virtual ACE_Asynch_Read_Stream_Impl *create_asynch_read_stream (void);
+ virtual ACE_Asynch_Read_Stream_Result_Impl *
+ create_asynch_read_stream_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_Impl *create_asynch_write_stream (void);
+ virtual ACE_Asynch_Write_Stream_Result_Impl *
+ create_asynch_write_stream_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_Impl *create_asynch_read_file (void);
+ virtual ACE_Asynch_Read_File_Result_Impl *
+ create_asynch_read_file_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_Impl *create_asynch_write_file (void);
+ virtual ACE_Asynch_Write_File_Result_Impl *
+ create_asynch_write_file_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_Impl *create_asynch_read_dgram (void);
+ virtual ACE_Asynch_Read_Dgram_Result_Impl *
+ create_asynch_read_dgram_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_Impl *create_asynch_write_dgram (void);
+ virtual ACE_Asynch_Write_Dgram_Result_Impl *
+ create_asynch_write_dgram_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_Impl *create_asynch_accept (void);
+ virtual ACE_Asynch_Accept_Result_Impl *
+ create_asynch_accept_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Connect_Impl *create_asynch_connect (void);
+ virtual ACE_Asynch_Connect_Result_Impl *
+ create_asynch_connect_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void *act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Transmit_File_Impl *create_asynch_transmit_file (void);
+ virtual ACE_Asynch_Transmit_File_Result_Impl *
+ create_asynch_transmit_file_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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,
+ size_t bytes_transferred,
+ 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_;
+
+private:
+ /// Task to process pseudo-asynchronous accept/connect
+ ACE_Asynch_Pseudo_Task pseudo_task_;
+
+};
+
+// 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_Asynch_Operation;
+ friend class ACE_POSIX_Asynch_Accept;
+ friend class ACE_POSIX_Asynch_Connect;
+
+
+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);
+
+ /// Close down the Proactor.
+ virtual int close (void);
+
+ /**
+ * Dispatch a single set of events. If @a 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 @a 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);
+
+ virtual int start_aio (ACE_POSIX_Asynch_Result *result,
+ ACE_POSIX_Proactor::Opcode op);
+
+ /**
+ * 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);
+
+ /// Check AIO for completion, error and result status
+ /// Return: 1 - AIO completed , 0 - not completed yet
+ virtual int get_result_status (ACE_POSIX_Asynch_Result *asynch_result,
+ int &error_status,
+ size_t &transfer_count);
+
+ /// Create aiocb list
+ int create_result_aiocb_list (void);
+
+ /// Call this method from derived class when virtual table is
+ /// built.
+ int delete_result_aiocb_list (void);
+
+ /// 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.
+ */
+ int handle_events_i (u_long milli_seconds);
+
+ /// Start deferred AIO if necessary
+ int start_deferred_aio (void);
+
+ /// 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,
+ size_t &transfer_count,
+ size_t &index,
+ size_t &count);
+
+ /// Find free slot to store result and aiocb pointer
+ virtual ssize_t allocate_aio_slot (ACE_POSIX_Asynch_Result *result);
+
+ /// Initiate an aio operation.
+ virtual int start_aio_i (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_;
+};
+
+#if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
+/**
+ * @class ACE_POSIX_SIG_Proactor
+ *
+ * @brief This Proactor implementation does completion event detection using
+ * POSIX Real Time signals. @c sigtimedwait() or @c sigwaitinfo() is
+ * used to wait for 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 asynchronous 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 @a 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 @a 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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;
+
+ /// Insures that RT_completion_signals_ are blocked in the calling thread.
+ int block_signals (void) const;
+
+ /**
+ * Dispatch a single set of events. @a timeout is a pointer to a
+ * relative time representing the maximum amount of time to wait for
+ * an event to occur. If 0, wait indefinitely.
+ *
+ * @retval 0 A timeout occurred before any event was detected.
+ * @retval 1 A completion was dispatched.
+ * @retval -1 An error occurred; errno contains an error code.
+ */
+ virtual int handle_events_i (const ACE_Time_Value *timeout);
+
+ /// Find free slot to store result and aiocb pointer
+ virtual ssize_t 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);
+
+ /**
+ * These signals are used for completion notification by the
+ * Proactor. The signals specified while issuing asynchronous
+ * operations are stored here in this set. These signals are masked
+ * for a thread when it calls handle_events().
+ */
+ sigset_t RT_completion_signals_;
+};
+
+
+#endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
+
+/**
+ * @class ACE_POSIX_Asynch_Timer
+ *
+ * @brief This class is posted to the completion port when a timer
+ * expires. When the @c complete() method of this object is
+ * called, the handler's @c 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;
+#if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
+ friend class ACE_POSIX_SIG_Proactor;
+#endif
+
+protected:
+ /// Constructor.
+ ACE_POSIX_Asynch_Timer (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 (size_t bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error = 0);
+
+ /// Time value requested by caller
+ ACE_Time_Value time_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/POSIX_Proactor.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_AIO_CALLS && ACE_HAS_POSIX_REALTIME_SIGNALS */
+#endif /* ACE_POSIX_PROACTOR_H */
diff --git a/ACE/ace/POSIX_Proactor.inl b/ACE/ace/POSIX_Proactor.inl
new file mode 100644
index 00000000000..ae5f727c2a8
--- /dev/null
+++ b/ACE/ace/POSIX_Proactor.inl
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Asynch_Pseudo_Task& ACE_POSIX_Proactor::get_asynch_pseudo_task (void)
+{
+ return this->pseudo_task_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Pagefile_Memory_Pool.cpp b/ACE/ace/Pagefile_Memory_Pool.cpp
new file mode 100644
index 00000000000..81b84dfddb7
--- /dev/null
+++ b/ACE/ace/Pagefile_Memory_Pool.cpp
@@ -0,0 +1,384 @@
+// $Id$
+
+// Pagefile_Memory_Pool.cpp
+#include "ace/Pagefile_Memory_Pool.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Pagefile_Memory_Pool.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/RW_Thread_Mutex.h"
+#include "ace/OS_NS_sys_mman.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_unistd.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, Pagefile_Memory_Pool, "$Id$")
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+#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 /* !ACE_HAS_WINCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 (int)
+{
+ 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;
+ }
+ else
+ {
+ this->local_cb_.req_base_ = 0;
+ this->local_cb_.mapped_base_ = 0;
+ this->local_cb_.sh_.max_size_ =
+ this->round_to_chunk_size (page_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;
+ }
+
+ int update_backing_store_name = backing_store_name == 0 ? 0 : 1;
+
+ 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)));
+
+ if (update_backing_store_name
+ && ACE_OS::strlen (this->backing_store_name_) < sizeof this->backing_store_name_)
+ ACE_OS::strcat (this->backing_store_name_,
+ ACE_TEXT ("_"));
+}
+
+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_ < rounded_bytes)
+ {
+ size_t append = 0;
+ if (rounded_bytes > this->shared_cb_->sh_.free_size_)
+ append = rounded_bytes - this->shared_cb_->sh_.free_size_;
+
+ 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_ < 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,
+ size_t append_bytes)
+{
+ size_t map_size;
+ void *map_addr;
+
+ // Create file mapping, if not yet done
+ if (object_handle_ == 0)
+ {
+#if !defined (ACE_LACKS_WIN32_SECURITY_DESCRIPTORS)
+ // Allow access by all users.
+ SECURITY_ATTRIBUTES sa;
+ SECURITY_DESCRIPTOR sd;
+ ::InitializeSecurityDescriptor (&sd,
+ SECURITY_DESCRIPTOR_REVISION);
+ ::SetSecurityDescriptorDacl (&sd,
+ TRUE,
+ 0,
+ FALSE);
+ sa.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = &sd;
+ sa.bInheritHandle = FALSE;
+#endif /* ACE_LACKS_WIN32_SECURITY_DESCRIPTORS */
+
+ // Get an object handle to the named reserved memory object.
+ DWORD size_high;
+ DWORD size_low;
+#if defined (ACE_WIN64)
+ size_high = static_cast<DWORD> (this->local_cb_.sh_.max_size_ >> 32);
+ size_low = static_cast<DWORD> (this->local_cb_.sh_.max_size_ & 0xFFFFFFFF);
+#else
+ size_high = 0;
+ size_low = this->local_cb_.sh_.max_size_;
+#endif
+
+ object_handle_ =
+ ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE,
+#if !defined (ACE_LACKS_WIN32_SECURITY_DESCRIPTORS)
+ &sa,
+#else
+ 0,
+#endif /* !ACE_LACKS_WIN32_SECURITY_DESCRIPTORS */
+ PAGE_READWRITE | SEC_RESERVE,
+ size_high,
+ size_low,
+ 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */
diff --git a/ACE/ace/Pagefile_Memory_Pool.h b/ACE/ace/Pagefile_Memory_Pool.h
new file mode 100644
index 00000000000..a82e5706c3f
--- /dev/null
+++ b/ACE/ace/Pagefile_Memory_Pool.h
@@ -0,0 +1,201 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Pagefile_Memory_Pool.h
+ *
+ * $Id$
+ *
+ * @author Dougls C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_PAGEFILE_MEMORY_POOL_H
+#define ACE_PAGEFILE_MEMORY_POOL_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+
+#include "ace/ACE.h"
+#include "ace/os_include/sys/os_mman.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a 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 (int destroy = 1);
+
+ /**
+ * 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 @a 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);
+
+ /// Return the base address of this memory pool, 0 if base_addr
+ /// never changes.
+ virtual void *base_addr (void) const;
+
+ void dump (void) const {}
+
+protected:
+
+ /**
+ * Map portions or the entire pool into the local virtual address
+ * space. To do this, we compute the new @c file_offset of the
+ * backing store and commit the memory.
+ */
+ int map (int &firstTime, size_t 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
+ size_t mapped_size_;
+
+ /// Offset to mapped but not yet acquired address space
+ ptrdiff_t free_offset_;
+
+ /// Size of mapped but not yet acquired address space
+ size_t 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];
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Pagefile_Memory_Pool.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MEMORY_POOL_H */
diff --git a/ACE/ace/Pagefile_Memory_Pool.inl b/ACE/ace/Pagefile_Memory_Pool.inl
new file mode 100644
index 00000000000..6fd4cf0e8b1
--- /dev/null
+++ b/ACE/ace/Pagefile_Memory_Pool.inl
@@ -0,0 +1,54 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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;
+}
+
+ACE_INLINE void *
+ACE_Pagefile_Memory_Pool::base_addr (void) const
+{
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 &7 !ACE_HAS_PHARLAP */
diff --git a/ACE/ace/Pair.h b/ACE/ace/Pair.h
new file mode 100644
index 00000000000..7a12dab6c0e
--- /dev/null
+++ b/ACE/ace/Pair.h
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Pair.h
+ *
+ * $Id$
+ *
+ * ACE_Pair<> convenience header.
+ *
+ * @author Irfan Pyarali
+ */
+//=============================================================================
+
+
+#ifndef ACE_PAIR_H
+#define ACE_PAIR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Include the templates here.
+#include "ace/Pair_T.h"
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_PAIR_H */
diff --git a/ACE/ace/Pair_T.cpp b/ACE/ace/Pair_T.cpp
new file mode 100644
index 00000000000..fd38f8236ef
--- /dev/null
+++ b/ACE/ace/Pair_T.cpp
@@ -0,0 +1,16 @@
+// $Id$
+
+#ifndef ACE_PAIR_T_CPP
+#define ACE_PAIR_T_CPP
+
+#include "ace/Pair_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Pair_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_PAIR_T_CPP */
diff --git a/ACE/ace/Pair_T.h b/ACE/ace/Pair_T.h
new file mode 100644
index 00000000000..58b1ec2a71c
--- /dev/null
+++ b/ACE/ace/Pair_T.h
@@ -0,0 +1,129 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Pair_T.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_PAIR_T_H
+#define ACE_PAIR_T_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Pair
+ *
+ * @brief Defines a pair.
+ *
+ * Similar to the STL pair.
+ */
+template <class T1, class T2>
+class ACE_Pair
+{
+public:
+
+ // = Traits.
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Pair (const T1 &t1,
+ const T2 &t2);
+
+ /// Default constructor.
+ ACE_Pair (void);
+
+ /// Get first.
+ T1 &first (void);
+ const T1 &first (void) const;
+
+ /// Set first.
+ void first (const T1 &t1);
+
+ /// Get second.
+ T2 &second (void);
+ const T2 &second (void) const;
+
+ /// Set second.
+ void second (const T2 &t2);
+
+ // Compare pairs.
+ bool operator== (const ACE_Pair<T1, T2> &rhs) const;
+
+protected:
+ /// First.
+ T1 first_;
+
+ /// Second.
+ T2 second_;
+};
+
+/**
+ * @class ACE_Reference_Pair
+ *
+ * @brief Defines a pair that only hold references.
+ *
+ * Similar to the STL pair (but restricted to holding references
+ * and not copies).
+ */
+template <class T1, class T2>
+class ACE_Reference_Pair
+{
+public:
+
+ // = Traits.
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Reference_Pair (T1 &t1,
+ T2 &t2);
+
+ /// Access first.
+ T1 &first (void) const;
+
+ /// Access second.
+ T2 &second (void) const;
+
+ // Compare pairs.
+ bool operator== (const ACE_Reference_Pair<T1, T2> &rhs) const;
+
+protected:
+ /// First.
+ T1 &first_;
+
+ /// Second.
+ T2 &second_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Pair_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Pair_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Pair_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_PAIR_T_H */
diff --git a/ACE/ace/Pair_T.inl b/ACE/ace/Pair_T.inl
new file mode 100644
index 00000000000..4ce4a4acae4
--- /dev/null
+++ b/ACE/ace/Pair_T.inl
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T1, class T2> ACE_INLINE
+ACE_Pair<T1, T2>::ACE_Pair (const T1 &t1,
+ const T2 &t2)
+ : first_ (t1),
+ second_ (t2)
+{
+}
+
+template <class T1, class T2> ACE_INLINE
+ACE_Pair<T1, T2>::ACE_Pair (void)
+{
+}
+
+template <class T1, class T2> ACE_INLINE T1 &
+ACE_Pair<T1, T2>::first (void)
+{
+ return this->first_;
+}
+
+template <class T1, class T2> ACE_INLINE const T1 &
+ACE_Pair<T1, T2>::first (void) const
+{
+ return this->first_;
+}
+
+template <class T1, class T2> ACE_INLINE void
+ACE_Pair<T1, T2>::first (const T1 &t1)
+{
+ this->first_ = t1;
+}
+
+template <class T1, class T2> ACE_INLINE T2 &
+ACE_Pair<T1, T2>::second (void)
+{
+ return this->second_;
+}
+
+template <class T1, class T2> ACE_INLINE const T2 &
+ACE_Pair<T1, T2>::second (void) const
+{
+ return this->second_;
+}
+
+template <class T1, class T2> ACE_INLINE void
+ACE_Pair<T1, T2>::second (const T2 &t2)
+{
+ this->second_ = t2;
+}
+
+template <class T1, class T2> ACE_INLINE bool
+ACE_Pair<T1, T2>::operator== (const ACE_Pair<T1, T2> &rhs) const
+{
+ return (this->first_ == rhs.first_ &&
+ this->second_ == rhs.second_);
+}
+
+template <class T1, class T2> ACE_INLINE
+ACE_Reference_Pair<T1, T2>::ACE_Reference_Pair (T1 &t1,
+ T2 &t2)
+ : first_ (t1),
+ second_ (t2)
+{
+}
+
+template <class T1, class T2> ACE_INLINE T1 &
+ACE_Reference_Pair<T1, T2>::first (void) const
+{
+ return this->first_;
+}
+
+template <class T1, class T2> ACE_INLINE T2 &
+ACE_Reference_Pair<T1, T2>::second (void) const
+{
+ return this->second_;
+}
+
+template <class T1, class T2> ACE_INLINE bool
+ACE_Reference_Pair<T1, T2>::operator== (const ACE_Reference_Pair<T1, T2> &rhs) const
+{
+ return (this->first_ == rhs.first_ &&
+ this->second_ == rhs.second_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Parse_Node.cpp b/ACE/ace/Parse_Node.cpp
new file mode 100644
index 00000000000..376866af7fb
--- /dev/null
+++ b/ACE/ace/Parse_Node.cpp
@@ -0,0 +1,838 @@
+#include "ace/Parse_Node.h"
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+
+#include "ace/Service_Config.h"
+#include "ace/Service_Repository.h"
+#include "ace/Service_Types.h"
+#include "ace/Task.h"
+#include "ace/DLL.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ Parse_Node,
+ "$Id$")
+
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Stream_Node)
+
+// Provide the class hierarchy that defines the parse tree of Service
+// Nodes.
+
+ void
+ACE_Stream_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Stream_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Stream_Node::apply (ACE_Service_Gestalt *config, int &yyerrno)
+{
+ ACE_TRACE ("ACE_Stream_Node::apply");
+
+ if (config->initialize (this->node_->record (config),
+ this->node_->parameters ()) == -1)
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Did stream on %s, error = %d\n"),
+ this->node_->name (),
+ yyerrno));
+#endif /* ACE_NLOGGING */
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Parse_Node)
+
+ void
+ACE_Parse_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Parse_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+const ACE_TCHAR *
+ACE_Parse_Node::name (void) const
+{
+ ACE_TRACE ("ACE_Parse_Node::name");
+ return this->name_;
+}
+
+ACE_Parse_Node *
+ACE_Parse_Node::link (void) const
+{
+ ACE_TRACE ("ACE_Parse_Node::link");
+ return this->next_;
+}
+
+void
+ACE_Parse_Node::link (ACE_Parse_Node *n)
+{
+ ACE_TRACE ("ACE_Parse_Node::link");
+ this->next_ = n;
+}
+
+ACE_Stream_Node::ACE_Stream_Node (const ACE_Static_Node *str_ops,
+ const ACE_Parse_Node *str_mods)
+ : ACE_Parse_Node ((str_ops == 0 ? ACE_TEXT ("<unknown>") : str_ops->name ())),
+ node_ (str_ops),
+ mods_ (str_mods)
+{
+ ACE_TRACE ("ACE_Stream_Node::ACE_Stream_Node");
+}
+
+
+ACE_Stream_Node::~ACE_Stream_Node (void)
+{
+ ACE_TRACE ("ACE_Stream_Node::~ACE_Stream_Node");
+ ACE_Static_Node *n = const_cast<ACE_Static_Node *> (this->node_);
+ delete n;
+ ACE_Parse_Node *m = const_cast<ACE_Parse_Node *> (this->mods_);
+ delete m;
+}
+
+ACE_Parse_Node::ACE_Parse_Node (void)
+ : name_ (0),
+ next_ (0)
+{
+ ACE_TRACE ("ACE_Parse_Node::ACE_Parse_Node");
+}
+
+
+ACE_Parse_Node::ACE_Parse_Node (const ACE_TCHAR *nm)
+ : name_ (ACE::strnew (nm)),
+ next_ (0)
+{
+ ACE_TRACE ("ACE_Parse_Node::ACE_Parse_Node");
+}
+
+void
+ACE_Parse_Node::print (void) const
+{
+ ACE_TRACE ("ACE_Parse_Node::print");
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("svc = %s\n"),
+ this->name ()));
+
+ if (this->next_)
+ this->next_->print ();
+}
+
+
+ACE_Parse_Node::~ACE_Parse_Node (void)
+{
+ ACE_TRACE ("ACE_Parse_Node::~ACE_Parse_Node");
+ delete[] const_cast<ACE_TCHAR*> (this->name_);
+ delete this->next_;
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Suspend_Node)
+
+ void
+ACE_Suspend_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Suspend_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Suspend_Node::ACE_Suspend_Node (const ACE_TCHAR *name)
+ : ACE_Parse_Node (name)
+{
+ ACE_TRACE ("ACE_Suspend_Node::ACE_Suspend_Node");
+}
+
+ACE_Suspend_Node::~ACE_Suspend_Node (void)
+{
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Resume_Node)
+
+ void
+ACE_Resume_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Resume_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Resume_Node::ACE_Resume_Node (const ACE_TCHAR *name)
+ : ACE_Parse_Node (name)
+{
+ ACE_TRACE ("ACE_Resume_Node::ACE_Resume_Node");
+}
+
+ACE_Resume_Node::~ACE_Resume_Node (void)
+{
+}
+
+void
+ACE_Suspend_Node::apply (ACE_Service_Gestalt *config, int &yyerrno)
+{
+ ACE_TRACE ("ACE_Suspend_Node::apply");
+
+ if (config->suspend (this->name ()) == -1)
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("did suspend on %s, error = %d\n"),
+ this->name (),
+ yyerrno));
+#endif /* ACE_NLOGGING */
+}
+
+void
+ACE_Resume_Node::apply (ACE_Service_Gestalt *config, int &yyerrno)
+{
+ ACE_TRACE ("ACE_Resume_Node::apply");
+
+ if (config->resume (this->name ()) == -1)
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("did resume on %s, error = %d\n"),
+ this->name (),
+ yyerrno));
+#endif /* ACE_NLOGGING */
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Remove_Node)
+
+ void
+ACE_Remove_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Remove_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Remove_Node::ACE_Remove_Node (const ACE_TCHAR *name)
+ : ACE_Parse_Node (name)
+{
+ ACE_TRACE ("ACE_Remove_Node::ACE_Remove_Node");
+}
+
+ACE_Remove_Node::~ACE_Remove_Node (void)
+{
+}
+
+void
+ACE_Remove_Node::apply (ACE_Service_Gestalt *config, int &yyerrno)
+{
+ ACE_TRACE ("ACE_Remove_Node::apply");
+
+ if (config->remove (this->name ()) == -1)
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) Remove_Node::apply")
+ ACE_TEXT (" - did remove on %s, error = %d\n"),
+ this->name (),
+ yyerrno));
+#endif /* ACE_NLOGGING */
+}
+
+
+ACE_Dynamic_Node::ACE_Dynamic_Node (ACE_Service_Type_Factory const *stf,
+ ACE_TCHAR *parms)
+ : ACE_Static_Node (stf->name (), parms)
+ , factory_ (stf)
+{
+ ACE_TRACE ("ACE_Dynamic_Node::ACE_Dynamic_Node");
+}
+
+void
+ACE_Dynamic_Node::apply (ACE_Service_Gestalt *config, int &yyerrno)
+{
+ ACE_TRACE ("ACE_Dynamic_Node::apply");
+
+ if (config->initialize (this->factory_.get (),
+ this->parameters ()) == -1)
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) Dynamic_Node::apply")
+ ACE_TEXT (" - Did dynamic on %s (yyerrno=%d)\n"),
+ this->name (),
+ yyerrno));
+#endif /* ACE_NLOGGING */
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Dynamic_Node)
+
+ void
+ACE_Dynamic_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Dynamic_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Dynamic_Node::~ACE_Dynamic_Node (void)
+{
+ ACE_TRACE ("ACE_Dynamic_Node::~ACE_Dynamic_Node");
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Static_Node)
+
+ void
+ACE_Static_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Static_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Static_Node::ACE_Static_Node (const ACE_TCHAR *nm,
+ ACE_TCHAR *params)
+ : ACE_Parse_Node (nm),
+ parameters_ (ACE::strnew (params))
+{
+ ACE_TRACE ("ACE_Static_Node::ACE_Static_Node");
+}
+
+const ACE_Service_Type *
+ACE_Static_Node::record (const ACE_Service_Gestalt *config) const
+{
+ ACE_TRACE ("ACE_Static_Node::record");
+ ACE_Service_Type *sr = 0;
+
+ if (config->find (this->name (), (const ACE_Service_Type **) &sr) == -1)
+ return 0;
+
+ return sr;
+}
+
+ACE_TCHAR *
+ACE_Static_Node::parameters (void) const
+{
+ ACE_TRACE ("ACE_Static_Node::parameters");
+ return this->parameters_;
+}
+
+void
+ACE_Static_Node::apply (ACE_Service_Gestalt *config, int &yyerrno)
+{
+ ACE_TRACE ("ACE_Static_Node::apply");
+ if (config->initialize (this->name (),
+ this->parameters ()) == -1)
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) Static_Node::apply -")
+ ACE_TEXT (" Did static on %s (yyerrno=%d)\n"),
+ this->name (),
+ yyerrno));
+#endif /* ACE_NLOGGING */
+}
+
+ACE_Static_Node::~ACE_Static_Node (void)
+{
+ ACE_TRACE ("ACE_Static_Node::~ACE_Static_Node");
+ delete[] this->parameters_;
+}
+
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Location_Node)
+
+ void
+ACE_Location_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Location_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Location_Node::ACE_Location_Node (void)
+ : pathname_ (0),
+ dll_ (),
+ symbol_ (0)
+{
+ ACE_TRACE ("ACE_Location_Node::ACE_Location_Node");
+}
+
+ACE_Location_Node::~ACE_Location_Node (void)
+{
+ ACE_TRACE ("ACE_Location_Node::~ACE_Location_Node");
+}
+
+const ACE_DLL &
+ACE_Location_Node::dll (void)
+{
+ return this->dll_;
+}
+
+const ACE_TCHAR *
+ACE_Location_Node::pathname (void) const
+{
+ ACE_TRACE ("ACE_Location_Node::pathname");
+ return this->pathname_;
+}
+
+void
+ACE_Location_Node::pathname (const ACE_TCHAR *p)
+{
+ ACE_TRACE ("ACE_Location_Node::pathname");
+ this->pathname_ = p;
+}
+
+int
+ACE_Location_Node::dispose (void) const
+{
+ ACE_TRACE ("ACE_Location_Node::dispose");
+ return this->must_delete_;
+}
+
+int
+ACE_Location_Node::open_dll (int & yyerrno)
+{
+ ACE_TRACE ("ACE_Location_Node::open_dll");
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) LN::open_dll - path=%s\n"),
+ this->pathname ()));
+#endif /* ACE_NLOGGING */
+
+ if (-1 == this->dll_.open (this->pathname ()))
+ {
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ ACE_TCHAR *errmsg = this->dll_.error ();
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) LN::open_dll - Failed to open %s: %s\n"),
+ this->pathname (),
+ errmsg ? errmsg : ACE_TEXT ("no error reported")));
+#endif /* ACE_NLOGGING */
+
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void
+ACE_Location_Node::set_symbol (void *s)
+{
+ ACE_TRACE ("ACE_Location_Node::set_symbol");
+ this->symbol_ = s;
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Object_Node)
+
+ void
+ACE_Object_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Object_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Object_Node::ACE_Object_Node (const ACE_TCHAR *path,
+ const ACE_TCHAR *obj_name)
+ : object_name_ (ACE::strnew (obj_name))
+{
+ ACE_TRACE ("ACE_Object_Node::ACE_Object_Node");
+ this->pathname (ACE::strnew (path));
+ this->must_delete_ = 0;
+}
+
+void *
+ACE_Object_Node::symbol (ACE_Service_Gestalt *,
+ int &yyerrno,
+ ACE_Service_Object_Exterminator *)
+{
+ ACE_TRACE ("ACE_Object_Node::symbol");
+ if (this->open_dll (yyerrno) == 0)
+ {
+ ACE_TCHAR *object_name = const_cast<ACE_TCHAR *> (this->object_name_);
+
+ this->symbol_ = this->dll_.symbol (object_name);
+ if (this->symbol_ == 0)
+ {
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ ACE_TCHAR *errmsg = this->dll_.error ();
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) DLL::symbol -")
+ ACE_TEXT (" Failed for object %s: %s\n"),
+ object_name,
+ errmsg ? errmsg : ACE_TEXT ("no error reported")));
+#endif /* ACE_NLOGGING */
+
+ return 0;
+ }
+
+ return this->symbol_;
+ }
+
+ return 0;
+}
+
+ACE_Object_Node::~ACE_Object_Node (void)
+{
+ ACE_TRACE ("ACE_Object_Node::~ACE_Object_Node");
+ delete[] const_cast<ACE_TCHAR *> (this->object_name_);
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Function_Node)
+
+ void
+ACE_Function_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Function_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Function_Node::ACE_Function_Node (const ACE_TCHAR *path,
+ const ACE_TCHAR *func_name)
+ : function_name_ (make_func_name (func_name))
+{
+ ACE_TRACE ("ACE_Function_Node::ACE_Function_Node");
+ this->pathname (ACE::strnew (path));
+ this->must_delete_ = 1;
+}
+
+ACE_TCHAR *
+ACE_Function_Node::make_func_name (ACE_TCHAR const * func_name)
+{
+ // Preprocessor symbols will not be expanded if they are
+ // stringified. Force the preprocessor to expand them during the
+ // argument prescan by calling a macro that itself calls another
+ // that performs the actual stringification.
+#if defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1
+# define ACE_MAKE_VERSIONED_NAMESPACE_NAME_STRING_IMPL(NAME) #NAME
+# define ACE_MAKE_VERSIONED_NAMESPACE_NAME_STRING(NAME) ACE_MAKE_VERSIONED_NAMESPACE_NAME_STRING_IMPL(NAME)
+# define ACE_VERSIONED_NAMESPACE_NAME_STRING ACE_MAKE_VERSIONED_NAMESPACE_NAME_STRING(ACE_VERSIONED_NAMESPACE_NAME)
+
+ // Check if function is using the ACE naming convention. If so,
+ // it is likely that the ACE factory function macros
+ // (e.g. ACE_FACTORY_DECLARE) were used to declare and define it, so
+ // mangle the function name to include the ACE versioned namespace
+ // name as is done in the ACE macros. Otherwise, leave the function
+ // name as is.
+
+ static ACE_TCHAR const make_prefix[] = ACE_TEXT ("_make_");
+ static size_t const make_prefix_len =
+ sizeof (make_prefix) / sizeof (make_prefix[0]) - 1;
+
+ if (ACE_OS::strncmp (make_prefix, func_name, make_prefix_len) == 0)
+ {
+ static ACE_TCHAR const versioned_namespace_name[] =
+ ACE_TEXT (ACE_VERSIONED_NAMESPACE_NAME_STRING) ACE_TEXT("_") ;
+
+ // Null terminator included in versioned_namespace_name_len since
+ // it is static constant.
+ static size_t const versioned_namespace_name_len =
+ sizeof (versioned_namespace_name)
+ / sizeof (versioned_namespace_name[0]); // - 1;
+
+ size_t const len =
+ ACE_OS::strlen (func_name)
+ + versioned_namespace_name_len;
+ // + 1; // Null terminator.
+
+ ACE_TCHAR * mangled_func_name;
+ ACE_NEW_RETURN (mangled_func_name,
+ ACE_TCHAR[len],
+ 0);
+
+ ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe (mangled_func_name);
+
+ ACE_OS::snprintf (mangled_func_name,
+ len,
+ ACE_TEXT ("%s%s%s"),
+ make_prefix,
+ versioned_namespace_name,
+ func_name + make_prefix_len);
+
+ return safe.release ();
+ }
+#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+ return ACE::strnew (func_name);
+}
+
+void *
+ACE_Function_Node::symbol (ACE_Service_Gestalt *,
+ int &yyerrno,
+ ACE_Service_Object_Exterminator *gobbler)
+{
+ typedef ACE_Service_Object *(*ACE_Service_Factory_Ptr)
+ (ACE_Service_Object_Exterminator *);
+
+ ACE_TRACE ("ACE_Function_Node::symbol");
+ if (this->open_dll (yyerrno) == 0)
+ {
+ this->symbol_ = 0;
+
+ // Locate the factory function <function_name> in the shared
+ // object.
+ ACE_TCHAR * const function_name =
+ const_cast<ACE_TCHAR *> (this->function_name_);
+
+ void * const func_p = this->dll_.symbol (function_name);
+ if (func_p == 0)
+ {
+ ++yyerrno;
+
+#ifndef ACE_NLOGGING
+ ACE_TCHAR * const errmsg = this->dll_.error ();
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("DLL::symbol failed for function %s: ")
+ ACE_TEXT ("%s\n"),
+ function_name,
+ errmsg ? errmsg : ACE_TEXT ("no error reported")));
+#endif /* ACE_NLOGGING */
+
+ return 0;
+ }
+
+#if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
+ int const temp_p = reinterpret_cast<int> (func_p);
+#else
+ intptr_t const temp_p = reinterpret_cast<intptr_t> (func_p);
+#endif
+
+ ACE_Service_Factory_Ptr func =
+ reinterpret_cast<ACE_Service_Factory_Ptr> (temp_p);
+
+ // Invoke the factory function and record it's return value.
+ this->symbol_ = (*func) (gobbler);
+
+ if (this->symbol_ == 0)
+ {
+ ++yyerrno;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ this->function_name_),
+ 0);
+ }
+ }
+ return this->symbol_;
+}
+
+ACE_Function_Node::~ACE_Function_Node (void)
+{
+ ACE_TRACE ("ACE_Function_Node::~ACE_Function_Node");
+ delete[] const_cast<ACE_TCHAR *> (function_name_);
+ delete[] const_cast<ACE_TCHAR *> (pathname_);
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Dummy_Node)
+
+ void
+ACE_Dummy_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Dummy_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Dummy_Node::ACE_Dummy_Node (const ACE_Static_Node *static_node,
+ const ACE_Parse_Node *str_mods)
+ : ACE_Parse_Node (static_node->name ()),
+ node_ (static_node),
+ mods_ (str_mods)
+{
+ ACE_TRACE ("ACE_Dummy_Node::ACE_Dummy_Node");
+}
+
+void
+ACE_Dummy_Node::apply (ACE_Service_Gestalt *, int &yyerrno)
+{
+ ACE_TRACE ("ACE_Dummy_Node::apply");
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("did operations on stream %s, error = %d\n"),
+ this->name (),
+ yyerrno));
+#else
+ ACE_UNUSED_ARG (yyerrno);
+#endif /* ACE_NLOGGING */
+}
+
+ACE_Dummy_Node::~ACE_Dummy_Node (void)
+{
+ ACE_TRACE ("ACE_Dummy_Node::~ACE_Dummy_Node");
+ ACE_Static_Node *n = const_cast<ACE_Static_Node *> (this->node_);
+ delete n;
+ ACE_Parse_Node *m = const_cast<ACE_Parse_Node *> (this->mods_);
+ delete m;
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Static_Function_Node)
+
+ void
+ACE_Static_Function_Node::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Static_Function_Node::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Static_Function_Node::ACE_Static_Function_Node (const ACE_TCHAR *func_name)
+ : function_name_ (ACE::strnew (func_name))
+{
+ ACE_TRACE ("ACE_Static_Function_Node::ACE_Static_Function_Node");
+ this->must_delete_ = 1;
+}
+
+void *
+ACE_Static_Function_Node::symbol (ACE_Service_Gestalt *config,
+ int &yyerrno,
+ ACE_Service_Object_Exterminator *gobbler)
+{
+ ACE_TRACE ("ACE_Static_Function_Node::symbol");
+
+ this->symbol_ = 0;
+
+ // Locate the factory function <function_name> in the statically
+ // linked svcs.
+
+ ACE_Static_Svc_Descriptor *ssd = 0;
+ if (config->find_static_svc_descriptor (this->function_name_, &ssd) == -1)
+ {
+ yyerrno++;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) No static service ")
+ ACE_TEXT ("registered for function %s\n"),
+ this->function_name_),
+ 0);
+ }
+
+ if (ssd->alloc_ == 0)
+ {
+ yyerrno++;
+
+ if (this->symbol_ == 0)
+ {
+ ++yyerrno;
+
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) No static service factory ")
+ ACE_TEXT ("function registered for function %s\n"),
+ this->function_name_),
+ 0);
+ }
+ }
+
+ // Invoke the factory function and record it's return value.
+ this->symbol_ = (*ssd->alloc_) (gobbler);
+
+ if (this->symbol_ == 0)
+ {
+ ++yyerrno;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ this->function_name_),
+ 0);
+ }
+
+ return this->symbol_;
+}
+
+ACE_Static_Function_Node::~ACE_Static_Function_Node (void)
+{
+ ACE_TRACE ("ACE_Static_Function_Node::~ACE_Static_Function_Node");
+ delete[] const_cast<ACE_TCHAR *> (this->function_name_);
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Service_Type_Factory)
+
+ACE_Service_Type_Factory::ACE_Service_Type_Factory (ACE_TCHAR const *name,
+ int type,
+ ACE_Location_Node *location,
+ int active)
+ : name_ (name)
+ , type_ (type)
+ , location_ (location)
+ , is_active_ (active)
+{
+}
+
+
+ACE_Service_Type_Factory::~ACE_Service_Type_Factory (void)
+{
+}
+
+
+ACE_Service_Type *
+ACE_Service_Type_Factory::make_service_type (ACE_Service_Gestalt *cfg) const
+{
+ ACE_TRACE ("ACE_Service_Type_Factory::make_service_type");
+
+ u_int flags = ACE_Service_Type::DELETE_THIS
+ | (this->location_->dispose () == 0 ? 0 : ACE_Service_Type::DELETE_OBJ);
+
+ int yyerrno = 0;
+ ACE_Service_Object_Exterminator gobbler = 0;
+
+ void *sym = this->location_->symbol (cfg, yyerrno, &gobbler);
+
+ if (sym != 0)
+ {
+ ACE_Service_Type_Impl *stp =
+ ACE_Service_Config::create_service_type_impl (this->name (),
+ this->type_,
+ sym,
+ flags,
+ gobbler);
+ if (stp == 0)
+ ++yyerrno;
+
+ ACE_Service_Type *tmp = 0;
+ ACE_NEW_RETURN (tmp,
+ ACE_Service_Type (this->name (),
+ stp,
+ this->location_->dll (),
+ this->is_active_),
+ 0);
+ return tmp;
+ }
+
+#ifndef ACE_NLOGGING
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) Unable to create ")
+ ACE_TEXT ("service object for %s\n"),
+ this->name ()));
+#endif
+ ++yyerrno;
+ return 0;
+}
+
+ACE_TCHAR const*
+ACE_Service_Type_Factory::name (void) const
+{
+ return name_.c_str ();
+}
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
diff --git a/ACE/ace/Parse_Node.h b/ACE/ace/Parse_Node.h
new file mode 100644
index 00000000000..ff3647ad875
--- /dev/null
+++ b/ACE/ace/Parse_Node.h
@@ -0,0 +1,522 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Parse_Node.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_PARSE_NODE_H
+#define ACE_PARSE_NODE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+
+#include "ace/DLL.h"
+#include "ace/Svc_Conf.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Forward declarations.
+class ACE_Service_Config;
+class ACE_Service_Type;
+
+/**
+ * @class ACE_Parse_Node
+ *
+ * @brief Provide the base of the object hierarchy that defines the parse
+ * tree of Service Nodes.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Parse_Node
+{
+public:
+ ACE_Parse_Node (void);
+ explicit ACE_Parse_Node (const ACE_TCHAR *name);
+ virtual ~ACE_Parse_Node (void);
+
+ ACE_Parse_Node *link (void) const;
+ void link (ACE_Parse_Node *);
+
+ /// Will update the yyereno member and/or the corresponding configuration
+ virtual void apply (ACE_Service_Gestalt *cfg, int &yyerrno) = 0;
+
+ const ACE_TCHAR *name (void) const;
+ void print (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ const ACE_TCHAR *name_;
+ ACE_Parse_Node *next_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Parse_Node (const ACE_Parse_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Parse_Node& operator= (const ACE_Parse_Node&))
+};
+
+/**
+ * @class ACE_Suspend_Node
+ *
+ * @brief Suspend a Service Node.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Suspend_Node : public ACE_Parse_Node
+{
+public:
+ ACE_Suspend_Node (const ACE_TCHAR *name);
+ ~ACE_Suspend_Node (void);
+
+ virtual void apply (ACE_Service_Gestalt *cfg, int &yyerrno);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Suspend_Node (const ACE_Suspend_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Suspend_Node& operator= (const ACE_Suspend_Node&))
+};
+
+/**
+ * @class ACE_Resume_Node
+ *
+ * @brief Resume a Service Node.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Resume_Node : public ACE_Parse_Node
+{
+public:
+ ACE_Resume_Node (const ACE_TCHAR *name);
+ ~ACE_Resume_Node (void);
+
+ virtual void apply (ACE_Service_Gestalt *cfg, int &yyerrno);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Resume_Node (const ACE_Resume_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Resume_Node& operator= (const ACE_Resume_Node&))
+};
+
+/**
+ * @class ACE_Remove_Node
+ *
+ * @brief Remove a Service Node.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Remove_Node : public ACE_Parse_Node
+{
+public:
+ ACE_Remove_Node (const ACE_TCHAR *name);
+ ~ACE_Remove_Node (void);
+
+ virtual void apply (ACE_Service_Gestalt *cfg, int &yyerrno);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Remove_Node (const ACE_Remove_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Remove_Node& operator= (const ACE_Remove_Node&))
+};
+
+/**
+ * @class ACE_Static_Node
+ *
+ * @brief Handle a statically linked node.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Static_Node : public ACE_Parse_Node
+{
+public:
+ ACE_Static_Node (const ACE_TCHAR *name, ACE_TCHAR *params = 0);
+ virtual ~ACE_Static_Node (void);
+
+ virtual void apply (ACE_Service_Gestalt *cfg, int &yyerrno);
+ virtual const ACE_Service_Type *record (const ACE_Service_Gestalt *g) const;
+
+ ACE_TCHAR *parameters (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// "Command-line" parameters.
+ ACE_TCHAR *parameters_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Static_Node (const ACE_Static_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Static_Node& operator= (const ACE_Static_Node&))
+};
+
+
+class ACE_Service_Type_Factory;
+
+/**
+ * @class ACE_Dynamic_Node
+ *
+ * @brief Handle a dynamically linked node.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Dynamic_Node : public ACE_Static_Node
+{
+public:
+ ACE_Dynamic_Node (ACE_Service_Type_Factory const *, ACE_TCHAR *params);
+
+ virtual ~ACE_Dynamic_Node (void);
+
+ // virtual const ACE_Service_Type *record (void) const;
+ virtual void apply (ACE_Service_Gestalt *cfg, int &yyerrno);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to a descriptor that describes this node.
+ ACE_Auto_Ptr<const ACE_Service_Type_Factory> factory_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dynamic_Node (const ACE_Dynamic_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dynamic_Node& operator= (const ACE_Dynamic_Node&))
+};
+
+/**
+ * @class ACE_Stream_Node
+ *
+ * @brief Handle a Stream.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Stream_Node : public ACE_Parse_Node
+{
+public:
+ ACE_Stream_Node (const ACE_Static_Node *, const ACE_Parse_Node *);
+ virtual ~ACE_Stream_Node (void);
+
+ virtual void apply (ACE_Service_Gestalt *cfg, int &yyerrno);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Linked list of modules that are part of the stream.
+ const ACE_Static_Node *node_;
+ const ACE_Parse_Node *mods_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Stream_Node (const ACE_Stream_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Stream_Node& operator= (const ACE_Stream_Node&))
+};
+
+/**
+ * @class ACE_Dummy_Node
+ *
+ * @brief I forget why this is here... ;-)
+ * @brief Used in a special case of static STREAM definintion
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ */
+class ACE_Dummy_Node : public ACE_Parse_Node
+{
+public:
+ ACE_Dummy_Node (const ACE_Static_Node *, const ACE_Parse_Node *);
+ ~ACE_Dummy_Node (void);
+
+ virtual void apply (ACE_Service_Gestalt *cfg, int &yyerrno);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Linked list of modules that we're dealing with.
+ const ACE_Static_Node *node_;
+ const ACE_Parse_Node *mods_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dummy_Node (const ACE_Dummy_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dummy_Node& operator= (const ACE_Dummy_Node&))
+};
+
+/**
+ * @class ACE_Location_Node
+ *
+ * @brief Keep track of where a shared library is located.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Location_Node
+{
+public:
+ ACE_Location_Node (void);
+ const ACE_DLL &dll (void);
+ const ACE_TCHAR *pathname (void) const;
+ void pathname (const ACE_TCHAR *h);
+ int dispose (void) const;
+
+ virtual ~ACE_Location_Node (void);
+ virtual void set_symbol (void *h);
+
+ /// Will update the yyerrno member and/or corresponding configuration
+ /// repository
+ virtual void *symbol (ACE_Service_Gestalt *cfgptr,
+ int &yyerrno,
+ ACE_Service_Object_Exterminator * = 0) = 0;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ int open_dll (int & yyerrno);
+
+ /// Pathname to the shared library we are working on.
+ const ACE_TCHAR *pathname_;
+
+ /**
+ * Flag indicating whether the Service_Object generated by this
+ * Location Node should be deleted or not
+ * (ACE_Service_Type::DELETE_OBJ.)
+ */
+ int must_delete_;
+
+ /// The open shared library.
+ ACE_DLL dll_;
+
+ /// Symbol that we've obtained from the shared library.
+ void *symbol_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Location_Node (const ACE_Location_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Location_Node& operator= (const ACE_Location_Node&))
+};
+
+/**
+ * @class ACE_Object_Node
+ *
+ * @brief Keeps track of the symbol name for a shared object.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Object_Node : public ACE_Location_Node
+{
+public:
+ ACE_Object_Node (const ACE_TCHAR *pathname, const ACE_TCHAR *obj_name);
+ virtual void *symbol (ACE_Service_Gestalt *config,
+ int &yyerrno,
+ ACE_Service_Object_Exterminator * = 0);
+ virtual ~ACE_Object_Node (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Name of the object that we're parsing.
+ const ACE_TCHAR *object_name_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Object_Node (const ACE_Object_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Object_Node& operator= (const ACE_Object_Node&))
+};
+
+/**
+ * @class ACE_Function_Node
+ *
+ * @brief Keeps track of the symbol name of for a shared function.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Function_Node : public ACE_Location_Node
+{
+public:
+ ACE_Function_Node (const ACE_TCHAR *pathname, const ACE_TCHAR *func_name);
+ virtual void *symbol (ACE_Service_Gestalt *config,
+ int &yyerrno,
+ ACE_Service_Object_Exterminator *gobbler = 0);
+ virtual ~ACE_Function_Node (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /// Return mangled function name that takes into account ACE
+ /// versioned namespace.
+ /**
+ * This function embeds the ACE versioned namespace name into the
+ * original function name if versioned namespace support has been
+ * enabled and the original function name conforms to the ACE
+ * Service Object factory function naming conventions. For example
+ * "@c _make_Foo" becomes "@c make_ACE_5_4_7_Foo".
+ * @par
+ * If versioned namespace support is disabled or the factory
+ * function name does conform to ACE conventions, no mangling will
+ * occur and the verbatim function name is returned.
+ *
+ * @return Function name that takes into account versioned namespace
+ * name. Caller is responsible for calling operator
+ * delete[] or ACE::strdelete() on the returned string.
+ */
+ ACE_TCHAR * make_func_name (ACE_TCHAR const * func_name);
+
+private:
+
+ /// Name of the function that we're parsing.
+ const ACE_TCHAR *function_name_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Function_Node (const ACE_Function_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Function_Node& operator= (const ACE_Function_Node&))
+};
+
+/**
+ * @class ACE_Static_Function_Node
+ *
+ * @brief Keeps track of the symbol name for a function that is not
+ * linked in from a DLL, but is statically linked with the
+ * application.
+ *
+ * @note This class is only meant for INTERNAL use by ACE.
+ *
+ * @internal
+ */
+class ACE_Static_Function_Node : public ACE_Location_Node
+{
+public:
+ explicit ACE_Static_Function_Node (const ACE_TCHAR *func_name);
+ virtual void *symbol (ACE_Service_Gestalt *config,
+ int &yyerrno,
+ ACE_Service_Object_Exterminator * = 0);
+ virtual ~ACE_Static_Function_Node (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Name of the function that we're parsing.
+ const ACE_TCHAR *function_name_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_Static_Function_Node (const ACE_Static_Function_Node&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Static_Function_Node& operator= (const ACE_Static_Function_Node&))
+};
+
+/// A helper class used to safely register dynamic services, which may contains
+/// subordinate static services. It is used to capture the necessary data during
+/// the parsing, but perform the actuall instantiation later.
+class ACE_Service_Type_Factory
+{
+public:
+ ACE_Service_Type_Factory (ACE_TCHAR const *name,
+ int type,
+ ACE_Location_Node *location,
+ int active);
+
+ ~ACE_Service_Type_Factory (void);
+
+ ACE_Service_Type *make_service_type (ACE_Service_Gestalt *pcfg) const;
+
+ ACE_TCHAR const* name (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /**
+ * Not implemented to enforce no copying
+ */
+ ACE_UNIMPLEMENTED_FUNC
+ (ACE_Service_Type_Factory(const ACE_Service_Type_Factory&))
+
+ ACE_UNIMPLEMENTED_FUNC
+ (ACE_Service_Type_Factory& operator=(const ACE_Service_Type_Factory&))
+
+private:
+ ACE_TString name_;
+ int type_;
+ ACE_Auto_Ptr<ACE_Location_Node> location_;
+ int is_active_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_PARSE_NODE_H */
diff --git a/ACE/ace/Ping_Socket.cpp b/ACE/ace/Ping_Socket.cpp
new file mode 100644
index 00000000000..8fc6ffcc69f
--- /dev/null
+++ b/ACE/ace/Ping_Socket.cpp
@@ -0,0 +1,377 @@
+// $Id$
+
+#include "ace/Ping_Socket.h"
+
+#if defined (ACE_HAS_ICMP_SUPPORT) && (ACE_HAS_ICMP_SUPPORT == 1)
+
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_sys_socket.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Ping_Socket.inl"
+#endif /* !__ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Ping_Socket,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Ping_Socket)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+//---------------------------------------------------------------------------
+// Better to arrange some os_include/netinet/ip.h and
+// os_include/netinet/icmp.h files ?
+//---------------------------------------------------------------------------
+
+#if !defined (ACE_WIN32)
+
+/*
+ * This is where ICMP-related stuff is defined on any sane system...
+ */
+#include /**/ <netinet/in_systm.h>
+#include /**/ <netinet/ip.h>
+#include /**/ <netinet/ip_icmp.h>
+
+#else /* #if ! defined (ACE_WIN32) */
+
+/*
+ * This was a surpise to me... This stuff is not defined anywhere under MSVC.
+ * These values have only been checked for NT4 and Win2K. They were taken from
+ * the MSDN ping.c program and modified.
+ */
+
+#define ICMP_ECHO 8
+#define ICMP_ECHOREPLY 0
+
+#pragma pack(1)
+
+struct ip
+{
+ ACE_UINT8 ip_hl:4; // length of the header
+ ACE_UINT8 version:4; // Version of IP
+ ACE_UINT8 tos; // Type of service
+ ACE_UINT16 total_len; // total length of the packet
+ ACE_UINT16 ident; // unique identifier
+ ACE_UINT16 frag_and_flags; // flags
+ ACE_UINT8 ip_ttl; // Time to live
+ ACE_UINT8 proto; // protocol (TCP, UDP etc)
+ ACE_UINT16 checksum; // IP checksum
+ ACE_UINT32 sourceIP;
+ ACE_UINT32 destIP;
+};
+
+struct icmp
+{
+ ACE_UINT8 icmp_type;
+ ACE_UINT8 icmp_code; // type sub code
+ ACE_UINT16 icmp_cksum;
+ ACE_UINT16 icmp_id;
+ ACE_UINT16 icmp_seq;
+ ACE_UINT32 icmp_data; // time data
+};
+
+#pragma pack()
+
+#endif /* #if ! defined (ACE_WIN32) */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int const ICMP_MIN = 8; // Minimal size of ICMP packet, header only
+int const ICMP_DATA_LENGTH = 56; // For ICMP data with Echo request
+ACE_Time_Value const ACE_Ping_Socket::time_default_ (0, 500000);
+
+
+void
+ACE_Ping_Socket::dump (void) const
+{
+ ACE_TRACE ("ACE_Ping_Socket::dump");
+}
+
+ACE_Ping_Socket::ACE_Ping_Socket (void)
+{
+ ACE_TRACE ("ACE_Ping_Socket::ACE_Ping_Socket");
+}
+
+ACE_Ping_Socket::ACE_Ping_Socket (ACE_Addr const & local,
+ int protocol,
+ int reuse_addr)
+ : sequence_number_ (0),
+ connected_socket_ (0)
+{
+ ACE_TRACE ("ACE_Ping_Socket::ACE_Ping_Socket");
+
+ ACE_OS::memset (icmp_send_buff_, 0, sizeof (icmp_send_buff_));
+ ACE_OS::memset (icmp_recv_buff_, 0, sizeof (icmp_recv_buff_));
+
+ if (this->open (local, protocol, reuse_addr) == -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE_Ping_Socket::ACE_Ping_Socket: %p\n"),
+ ACE_TEXT ("open")));
+ return;
+ }
+
+ // trying to increase the size of socket receive buffer - some
+ // protection from multiple responces e.g., when falling to the
+ // multi-cast address
+ int size = 64 * 1024;
+ ACE_SOCK::set_option (SOL_SOCKET,
+ SO_RCVBUF,
+ (void *) &size,
+ sizeof (size));
+}
+
+ACE_Ping_Socket::~ACE_Ping_Socket (void)
+{
+ ACE_TRACE ("ACE_Ping_Socket::~ACE_Ping_Socket");
+}
+
+int
+ACE_Ping_Socket::open (ACE_Addr const & local,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_Ping_Socket::open");
+ return inherited::open (local, protocol, reuse_addr);
+}
+
+int
+ACE_Ping_Socket::receive_echo_reply (ACE_Time_Value const * timeout)
+{
+ ACE_TRACE ("ACE_Ping_Socket::receive_echo_reply");
+
+ ACE_Time_Value before = ACE_OS::gettimeofday ();
+ ACE_Time_Value after;
+ ACE_Time_Value time_left;
+ ACE_Time_Value *wait_time = const_cast<ACE_Time_Value *> (timeout);
+ const ACE_Time_Value half_millisec (0, 500);
+
+ ACE_OS::memset (icmp_recv_buff_, 0, sizeof icmp_recv_buff_);
+
+ do
+ {
+ int rval_recv = inherited::recv (icmp_recv_buff_,
+ sizeof icmp_recv_buff_,
+ 0,
+ wait_time);
+ if (rval_recv < 0)
+ {
+ if (errno == EINTR)
+ {
+ after = ACE_OS::gettimeofday ();
+ time_left = *timeout - after + before;
+
+ // If more than .5 ms left, wait on select()
+ if (time_left > half_millisec)
+ {
+ wait_time = &time_left; // coming back to wait on select()
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return -1;
+ }
+ else if (!this->process_incoming_dgram (icmp_recv_buff_, rval_recv))
+ {
+ return 0; //= success
+ }
+ else
+ {
+ after = ACE_OS::gettimeofday ();
+ if ((after - before) >= *timeout)
+ {
+ errno = ETIMEDOUT;
+ break;
+ }
+ // new timeout, we are coming back to sit on select
+ *wait_time = *timeout - after + before;
+ }
+ } while (*wait_time >= half_millisec);
+
+ errno = ETIMEDOUT;
+ return -1;
+}
+
+int
+ACE_Ping_Socket::process_incoming_dgram (char * ptr, ssize_t len)
+{
+ unsigned char hlen1;
+ int icmplen;
+ struct ip * ip;
+ struct icmp * icmp;
+
+ ip = (struct ip *) ptr; // start of IP header
+
+ // Warning... using knowledge of IP header layout. This avoids a maze of
+ // #if blocks for various systems. The first byte of the header has the
+ // IP version in the left-most 4 bits and the length in the other 4 bits.
+#if 0
+ hlen1 = ip->ip_hl; // length of IP header
+#else
+ hlen1 = static_cast<unsigned char>(*ptr);
+ hlen1 <<= 4; // Bump the version off
+ hlen1 >>= 4; // Zero-extended length remains
+#endif
+ hlen1 <<= 2; // Now it counts bytes, not words
+
+ icmp = (struct icmp *) (ptr + hlen1); // start of ICMP header
+
+ if ((icmplen = len - hlen1) < ICMP_MIN)
+ {
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) ACE_Ping_Socket::process_incoming_dgram")
+ ACE_TEXT (" - ICMP length is %d < 8.\n"),
+ icmplen));
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_Ping_Socket::process_incoming_dgram - ")
+ ACE_TEXT ("The ICMP header either not received or is corrupted.")),
+ -1);
+ }
+
+ if (icmp->icmp_type == ICMP_ECHOREPLY)
+ {
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) ACE_Ping_Socket::process_incoming_dgram")
+ ACE_TEXT (" - ICMP_ECHOREPLY received.\n")));
+
+ if (icmp->icmp_id != getpid ())
+ {
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_Ping_Socket::")
+ ACE_TEXT ("process_incoming_dgram ")
+ ACE_TEXT ("- The ICMP header received is a reply")
+ ACE_TEXT (" to request of another process.")),
+ -1);
+ }
+ if (icmplen < 16)
+ {
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_Ping_Socket::")
+ ACE_TEXT ("process_incoming_dgram - ICMP length ")
+ ACE_TEXT ("is %d < 16."),
+ icmplen),
+ -1);
+ }
+
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) ACE::Ping_Socket::process_incoming_dgram - ")
+ ACE_TEXT ("received ")
+ ACE_TEXT ("ICMP datagram with length of %d bytes (not counting ")
+ ACE_TEXT ("IP-header): seq=%u, ttl=%d.\n"),
+ icmplen, icmp->icmp_seq, ip->ip_ttl));
+
+ return 0; //= success
+ }
+
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) ACE::Ping_Socket::process_incoming_dgram - ")
+ ACE_TEXT ("received datagram that is not ICMP_ECHOREPLY.\n")));
+
+ return -1;
+}
+
+int
+ACE_Ping_Socket::send_echo_check (ACE_INET_Addr &remote_addr,
+ int to_connect)
+{
+ if (this->get_handle () == ACE_INVALID_HANDLE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ sockaddr_in *addr_connect = 0;
+ addr_connect = (sockaddr_in *) remote_addr.get_addr ();
+
+ /*
+ * Nulling port field to prevent strange behavior, when a raw
+ * socket is "connected" to a sockaddr_in with a non-nulled port.
+ */
+ ACE_OS::memset ((void*) &addr_connect->sin_port,
+ 0,
+ sizeof (addr_connect->sin_port));
+
+ // to connect the socket
+ if (to_connect && !this->connected_socket_)
+ {
+ if (ACE_OS::connect (this->get_handle (),
+ (sockaddr*) addr_connect,
+ remote_addr.get_size ()) == -1)
+ {
+ if (errno != EINTR)
+ return -1;
+ }
+ this->connected_socket_ = 1;
+ }
+
+ ACE_OS::memset (this->icmp_send_buff_, 0, sizeof this->icmp_send_buff_);
+ int datalen = ICMP_DATA_LENGTH;
+ struct icmp *_icmp;
+
+ _icmp = (struct icmp *) this->icmp_send_buff_;
+ _icmp->icmp_type = ICMP_ECHO;
+ _icmp->icmp_code = 0;
+ _icmp->icmp_id = getpid ();
+ _icmp->icmp_seq = sequence_number_++;
+
+#if defined (ACE_WIN32)
+ _icmp->icmp_data = GetTickCount ();
+#else /* #if defined (ACE_WIN32) */
+ gettimeofday ((struct timeval *) &_icmp->icmp_data, 0);
+#endif /* #if defined (ACE_WIN32) */
+
+ int length_icmp = ICMP_MIN + datalen; // checksum ICMP header and data.
+ _icmp->icmp_cksum = 0;
+ _icmp->icmp_cksum = inherited::calculate_checksum ((u_short *) _icmp,
+ length_icmp);
+ int rval_send = -1;
+
+ if ((rval_send = send ((void const *) icmp_send_buff_,
+ length_icmp,
+ remote_addr)) != length_icmp)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int
+ACE_Ping_Socket::make_echo_check (ACE_INET_Addr & remote_addr,
+ int to_connect,
+ ACE_Time_Value const * timeout)
+{
+ int rval_send = -1;
+
+ if ((rval_send = this->send_echo_check (remote_addr,
+ to_connect)) == -1)
+ return -1;
+
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) ACE_Ping_Socket::make_echo_check - sent %d.\n"),
+ rval_send));
+
+ return this->receive_echo_reply (timeout);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_ICMP_SUPPORT == 1 */
diff --git a/ACE/ace/Ping_Socket.h b/ACE/ace/Ping_Socket.h
new file mode 100644
index 00000000000..c5a28e3d4dc
--- /dev/null
+++ b/ACE/ace/Ping_Socket.h
@@ -0,0 +1,119 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Ping_Socket.h
+ *
+ * $Id$
+ *
+ * @author Robert S. Iakobashvili <coroberti@gmail.com> <coroberti@walla.co.il>
+ * @author Gonzalo A. Diethelm <gonzalo.diethelm@aditiva.com>
+ */
+//=============================================================================
+
+#ifndef ACE_PING_SOCKET_H
+#define ACE_PING_SOCKET_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_ICMP_SUPPORT) && (ACE_HAS_ICMP_SUPPORT == 1)
+
+#include "ace/ICMP_Socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_INET_Addr;
+
+/**
+ * @class ACE_Ping_Socket
+ *
+ * @brief This class is useful to perform ICMP echo checks (pinging)
+ * on the party of your interest. It may be used as well to check
+ * LAN-adapters against 3rd parties.
+ */
+class ACE_Export ACE_Ping_Socket : public ACE_ICMP_Socket
+{
+ typedef ACE_ICMP_Socket inherited;
+
+public:
+
+ // = Initialization and termination methods.
+
+ /// Default constructor.
+ ACE_Ping_Socket (void);
+
+ ACE_Ping_Socket (ACE_Addr const & local,
+ int protocol = IPPROTO_ICMP,
+ int reuse_addr = 0);
+
+ /// Destructor.
+ ~ACE_Ping_Socket (void);
+
+ /// Wrapper around the BSD-style @c socket system call (no QoS).
+ int open (ACE_Addr const & local = ACE_Addr::sap_any,
+ int protocol = IPPROTO_ICMP,
+ int reuse_addr = 0);
+
+ /// @a toConnect = 1 - makes connect to remote address
+ int send_echo_check (ACE_INET_Addr & remote_addr,
+ int to_connect = 0);
+
+ /// To receive @c ICMP_ECHOREPLY. To be called after successfully
+ /// sending @c ICMP_ECHO.
+ int process_incoming_dgram (char * ptr, ssize_t len);
+
+ /// @a toConnect = 1 - makes connect to remote address
+ int make_echo_check (ACE_INET_Addr & remote_addr,
+ int to_connect = 0,
+ ACE_Time_Value const * timeout = &time_default_);
+
+ char * icmp_recv_buff (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+public:
+
+ enum
+ {
+ PING_BUFFER_SIZE = (1024 * 2)
+ };
+
+ static ACE_Time_Value const time_default_;
+
+private:
+
+ int receive_echo_reply (ACE_Time_Value const * timeout);
+
+ /// Do not allow this function to percolate up to this interface.
+ int get_remote_addr (ACE_INET_Addr &addr) const;
+
+ char icmp_send_buff_[PING_BUFFER_SIZE];
+ char icmp_recv_buff_[PING_BUFFER_SIZE];
+
+ ACE_UINT16 sequence_number_;
+
+ int connected_socket_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Ping_Socket.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_ICMP_SUPPORT == 1 */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_PING_SOCKET_H */
diff --git a/ACE/ace/Ping_Socket.inl b/ACE/ace/Ping_Socket.inl
new file mode 100644
index 00000000000..c331b21cea7
--- /dev/null
+++ b/ACE/ace/Ping_Socket.inl
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE char *
+ACE_Ping_Socket::icmp_recv_buff (void)
+{
+ return this->icmp_recv_buff_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Pipe.cpp b/ACE/ace/Pipe.cpp
new file mode 100644
index 00000000000..aa87ab740eb
--- /dev/null
+++ b/ACE/ace/Pipe.cpp
@@ -0,0 +1,360 @@
+// $Id$
+
+#include "ace/Pipe.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_Memory.h"
+#include "ace/Truncate.h"
+
+#if defined (ACE_HAS_STREAM_PIPES) || defined (__QNX__)
+# include "ace/OS_NS_unistd.h"
+#endif // ACE_HAS_STREAM_PIPES || __QNX__
+
+#include "ace/os_include/netinet/os_tcp.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Pipe.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Pipe, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Pipe::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Pipe::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("handles_[0] = %d"), this->handles_[0]));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhandles_[1] = %d"), this->handles_[1]));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Pipe::open (int buffer_size)
+{
+ ACE_TRACE ("ACE_Pipe::open");
+
+#if 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;
+# if defined (ACE_WIN32)
+ ACE_INET_Addr local_any (static_cast<u_short> (0), ACE_LOCALHOST);
+# else
+ ACE_Addr local_any = ACE_Addr::sap_any;
+# endif /* ACE_WIN32 */
+
+ // Bind listener to any port and then find out what the port was.
+ if (acceptor.open (local_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_RCVBUF,
+ reinterpret_cast <void *> (&buffer_size),
+ sizeof (buffer_size)) == -1
+ && errno != ENOTSUP)
+ {
+ this->close ();
+ return -1;
+ }
+ else if (writer.set_option (SOL_SOCKET,
+ SO_SNDBUF,
+ 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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ioctl")), -1);
+ }
+#endif /* __QNX__ */
+
+#else /* ! 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_TEXT ("%p\n"),
+ ACE_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,
+ 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,
+ reinterpret_cast <const char *> (&buffer_size),
+ sizeof (buffer_size)) == -1
+ && errno != ENOTSUP)
+ {
+ this->close ();
+ return -1;
+ }
+# endif /* ! ACE_LACKS_SOCKET_BUFSIZ */
+# if defined (ACE_OPENVMS) && !defined (ACE_LACKS_TCP_NODELAY)
+ int one = 1;
+ // OpenVMS implements socketpair(AF_UNIX...) by returning AF_INET sockets.
+ // Since these are plagued by Nagle as any other INET socket we need to set
+ // TCP_NODELAY on the write handle.
+ if (ACE_OS::setsockopt (this->handles_[1],
+ ACE_IPPROTO_TCP,
+ TCP_NODELAY,
+ reinterpret_cast <const char *> (&one),
+ sizeof (one)) == -1)
+ {
+ this->close ();
+ return -1;
+ }
+# endif /* ACE_OPENVMS && !ACE_LACKS_TCP_NODELAY */
+#endif /* ! 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_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;
+}
+
+// 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_Pipe::send (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_Pipe::send");
+ va_list argp;
+ int total_tuples = ACE_Utils::truncate_cast<int> (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 (int i = 0; i < total_tuples; ++i)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+#if defined (ACE_WIN32)
+ ssize_t result = ACE::sendv (this->write_handle (),
+ iovp,
+ total_tuples);
+#else
+ ssize_t result = ACE_OS::writev (this->write_handle (),
+ iovp,
+ total_tuples);
+#endif /* ACE_WIN32 */
+
+#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_Pipe::recv (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_Pipe::recv");
+ va_list argp;
+ int total_tuples = ACE_Utils::truncate_cast<int> (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 (int i = 0; i < total_tuples; ++i)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+#if defined (ACE_WIN32)
+ ssize_t const result = ACE::recvv (this->read_handle (),
+ iovp,
+ total_tuples);
+#else
+ ssize_t const result = ACE_OS::readv (this->read_handle (),
+ iovp,
+ total_tuples);
+#endif /* ACE_WIN32 */
+
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Pipe.h b/ACE/ace/Pipe.h
new file mode 100644
index 00000000000..4d2f2b13cd0
--- /dev/null
+++ b/ACE/ace/Pipe.h
@@ -0,0 +1,165 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Pipe.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_PIPE_H
+#define ACE_PIPE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Default_Constants.h"
+
+#include "ace/OS_NS_sys_uio.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl.
+class ACE_Message_Block;
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Pipe
+ *
+ * @brief Provides a portable bidirectional "pipe" abstraction.
+ *
+ * This class is designed to work with select()-based demuxers, such
+ * as the ACE_Select_Reactor, which is why it uses sockets on Windows
+ * rather than Win32 pipes (which aren't select()'able).
+ */
+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 @a read and @a 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;
+
+ /// send upto @a n bytes in @a buf.
+ ssize_t send (const void *buf, size_t n) const;
+
+ /// Recv upto @a n bytes in @a 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 @a message_blocks 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;
+
+ /// Send iovecs via <::writev>.
+ ssize_t send (const iovec iov[], int n) const;
+
+ /// Recv iovecs via <::readv>.
+ ssize_t recv (iovec iov[], int 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 @a n bytes via Win32 WriteFile using overlapped I/O.
+ ssize_t send (const void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Recv @a 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 @a n to the file.
+ ssize_t sendv (const iovec iov[],
+ int n) const;
+
+ /// Send an @c iovec of size @a n to the file. Will block until all
+ /// bytes are sent or an error occurs.
+ ssize_t sendv_n (const iovec iov[],
+ int n) const;
+
+ /// Receive an @c iovec of size @a n to the file.
+ ssize_t recvv_n (iovec iov[],
+ int n) const;
+
+private:
+ ACE_HANDLE handles_[2];
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Pipe.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_PIPE_H */
diff --git a/ACE/ace/Pipe.inl b/ACE/ace/Pipe.inl
new file mode 100644
index 00000000000..17b532ed632
--- /dev/null
+++ b/ACE/ace/Pipe.inl
@@ -0,0 +1,188 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+#include "ace/ACE.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Pipe::~ACE_Pipe (void)
+{
+ ACE_TRACE ("ACE_Pipe::~ACE_Pipe");
+ // Notice that the destructor doesn't close the handles for you.
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_Pipe::read_handle (void) const
+{
+ ACE_TRACE ("ACE_Pipe::read_handle");
+ return this->handles_[0];
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_Pipe::write_handle (void) const
+{
+ ACE_TRACE ("ACE_Pipe::write_handle");
+ return this->handles_[1];
+}
+
+ACE_INLINE ssize_t
+ACE_Pipe::sendv_n (const iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_Pipe::sendv_n");
+#if defined (ACE_WIN32)
+ return ACE::sendv_n (this->write_handle (),
+ iov,
+ n);
+#else
+ return ACE::writev_n (this->write_handle (),
+ iov,
+ n);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_Pipe::send_n (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ ACE_TRACE ("ACE_Pipe::send_n");
+#if defined (ACE_WIN32)
+ return ACE::send_n (this->write_handle (),
+ message_block,
+ timeout,
+ bytes_transferred);
+#else
+ ACE_UNUSED_ARG (timeout);
+ return ACE::write_n (this->write_handle (),
+ message_block,
+ bytes_transferred);
+#endif /* ACE_WIN32 */
+}
+
+// Recv an n byte message from the file.
+
+ACE_INLINE ssize_t
+ACE_Pipe::recvv_n (iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_Pipe::recvv_n");
+ // @@ Carlos, can you please update this to call the
+ // new ACE::recvv_n() method that you write?
+#if defined (ACE_WIN32)
+ return ACE_OS::sendv (this->read_handle (),
+ iov,
+ n);
+#else
+ return ACE_OS::readv (this->read_handle (),
+ iov,
+ n);
+#endif /* ACE_WIN32 */
+}
+
+// Send an <iovec> of size <n> to the file.
+
+ACE_INLINE ssize_t
+ACE_Pipe::sendv (const iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_Pipe::sendv");
+#if defined (ACE_WIN32)
+ return ACE_OS::sendv (this->write_handle (), iov, n);
+#else
+ return ACE_OS::writev (this->write_handle (), iov, n);
+#endif /* ACE_WIN32 */
+}
+
+// Send exactly N bytes from BUF to this file. Keeping trying until
+// this many bytes are sent.
+
+ACE_INLINE ssize_t
+ACE_Pipe::send_n (const void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_Pipe::send_n");
+#if defined (ACE_WIN32)
+ return ACE::send_n (this->write_handle (), buf, n);
+#else
+ return ACE::write_n (this->write_handle (), buf, n);
+#endif /* ACE_WIN32 */
+}
+
+// Receive exactly N bytes from this file into BUF. Keep trying until
+// this many bytes are received.
+
+ACE_INLINE ssize_t
+ACE_Pipe::recv_n (void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_Pipe::recv_n");
+#if defined (ACE_WIN32)
+ return ACE::recv_n (this->read_handle (), buf, n);
+#else
+ return ACE::read_n (this->read_handle (), buf, n);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_Pipe::send (const void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_Pipe::send");
+#if defined (ACE_WIN32)
+ return ACE_OS::send (this->write_handle (), static_cast <const char *> (buf), n);
+#else
+ return ACE_OS::write (this->write_handle (), static_cast <const char *> (buf), n);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_Pipe::recv (void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_Pipe::recv");
+#if defined (ACE_WIN32)
+ return ACE_OS::recv (this->read_handle (), static_cast <char *> (buf), n);
+#else
+ return ACE_OS::read (this->read_handle (), static_cast <char *> (buf), n);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_Pipe::send (const iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_Pipe::send");
+#if defined (ACE_WIN32)
+ return ACE_OS::sendv (this->write_handle (), iov, n);
+#else
+ return ACE_OS::writev (this->write_handle (), iov, n);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_Pipe::recv (iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_Pipe::recv");
+#if defined (ACE_WIN32)
+ return ACE_OS::recvv (this->read_handle (), iov, n);
+#else
+ return ACE_OS::readv (this->read_handle (), iov, n);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ssize_t
+ACE_Pipe::send (const void *buf, size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_Pipe::send");
+ return ACE_OS::write (this->write_handle (),
+ static_cast <const char *> (buf), n,
+ overlapped);
+}
+
+ACE_INLINE ssize_t
+ACE_Pipe::recv (void *buf, size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_Pipe::recv");
+ return ACE_OS::read (this->read_handle (), static_cast <char *> (buf), n,
+ overlapped);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Priority_Reactor.cpp b/ACE/ace/Priority_Reactor.cpp
new file mode 100644
index 00000000000..cba55b0174c
--- /dev/null
+++ b/ACE/ace/Priority_Reactor.cpp
@@ -0,0 +1,188 @@
+// $Id$
+
+#include "ace/Priority_Reactor.h"
+#include "ace/Malloc_T.h"
+
+ACE_RCSID(ace, Priority_Reactor, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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::build_bucket (ACE_Handle_Set &dispatch_mask,
+ int &min_priority,
+ int &max_priority)
+{
+ ACE_Handle_Set_Iterator handle_iter (dispatch_mask);
+
+ for (ACE_HANDLE handle;
+ (handle = handle_iter ()) != ACE_INVALID_HANDLE;
+ )
+ {
+ ACE_Event_Handler *event_handler =
+ this->handler_rep_.find (handle);
+ if (event_handler == 0)
+ return -1;
+
+ ACE_Event_Tuple et (event_handler,
+ 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;
+
+ if (bucket_[prio]->enqueue_tail (et) == -1)
+ return -1;
+
+ // Update the priority ranges....
+ if (min_priority > prio)
+ min_priority = prio;
+ if (max_priority < prio)
+ max_priority = prio;
+ }
+
+ return 0;
+}
+
+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;
+
+ if (this->build_bucket (dispatch_mask,
+ min_priority,
+ max_priority) == -1)
+ return -1;
+
+ for (int i = max_priority; i >= min_priority; --i)
+ {
+ while (!bucket_[i]->is_empty ()
+ && number_dispatched < number_of_active_handles)
+ {
+
+ ACE_Event_Tuple et;
+
+ bucket_[i]->dequeue_head (et);
+
+ this->notify_handle (et.handle_,
+ mask,
+ ready_mask,
+ et.event_handler_,
+ callback);
+ number_dispatched++;
+
+ // clear the bit from that dispatch mask,
+ // so when we need to restart the iteration (rebuilding the iterator...)
+ // we will not dispatch the already dipatched handlers
+ this->clear_dispatch_mask (et.handle_,
+ mask);
+
+ if (this->state_changed_)
+ this->state_changed_ = false; // so it will not rebuild it ...
+ }
+
+ // 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 ();
+ }
+
+ return 0;
+}
+
+void
+ACE_Priority_Reactor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Priority_Reactor.h b/ACE/ace/Priority_Reactor.h
new file mode 100644
index 00000000000..5624fa4c9a7
--- /dev/null
+++ b/ACE/ace/Priority_Reactor.h
@@ -0,0 +1,100 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Select_Reactor.h"
+#include "ace/Unbounded_Queue.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a 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);
+
+ /// Build the bucket from the given dispatch_mask. Return -1 on
+ /// failure, 0 otherwise.
+ int build_bucket (ACE_Handle_Set& dispatch_mask,
+ int &min_priority,
+ int &max_priority);
+
+ /// 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_Priority_Reactor &);
+ ACE_Priority_Reactor &operator = (const ACE_Priority_Reactor &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_PRIORITY_REACTOR_H */
diff --git a/ACE/ace/Proactor.cpp b/ACE/ace/Proactor.cpp
new file mode 100644
index 00000000000..a907ce61cae
--- /dev/null
+++ b/ACE/ace/Proactor.cpp
@@ -0,0 +1,1177 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#include "ace/Proactor.h"
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
+
+// This only works on Win32 platforms and on Unix platforms with aio
+// calls.
+
+#include "ace/Auto_Ptr.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$")
+
+
+#include "ace/Task_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Framework_Component.h"
+
+#if defined (ACE_HAS_AIO_CALLS)
+# include "ace/POSIX_Proactor.h"
+# include "ace/POSIX_CB_Proactor.h"
+#else /* !ACE_HAS_AIO_CALLS */
+# include "ace/WIN32_Proactor.h"
+#endif /* ACE_HAS_AIO_CALLS */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Proactor.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Auto_Event.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// 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!)
+bool ACE_Proactor::delete_proactor_ = false;
+
+/**
+ * @class ACE_Proactor_Timer_Handler
+ *
+ * @brief A Handler for timer. It helps in the management of timers
+ * registered with the Proactor.
+ *
+ * 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).
+ */
+class ACE_Proactor_Timer_Handler : public ACE_Task<ACE_NULL_SYNCH>
+{
+
+ /// Proactor has special privileges
+ /// Access needed to: timer_event_
+ friend class ACE_Proactor;
+
+public:
+ /// Constructor.
+ ACE_Proactor_Timer_Handler (ACE_Proactor &proactor);
+
+ /// Destructor.
+ virtual ~ACE_Proactor_Timer_Handler (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.
+ int destroy (void);
+
+protected:
+ /// Run by a daemon thread to handle deferred processing. In other
+ /// words, this method will do the waiting on the earliest timer and
+ /// event.
+ virtual int svc (void);
+
+ /// Event to wait on.
+ ACE_Auto_Event timer_event_;
+
+ /// Proactor.
+ ACE_Proactor &proactor_;
+
+ /// Flag used to indicate when we are shutting down.
+ int 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 = ACE_Time_Value::zero;
+
+ // 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_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_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::registration (TIMER_QUEUE &,
+ ACE_Handler *,
+ const void *)
+{
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::preinvoke (TIMER_QUEUE &,
+ ACE_Handler *,
+ const void *,
+ int,
+ const ACE_Time_Value &,
+ const void *&)
+{
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::postinvoke (TIMER_QUEUE &,
+ ACE_Handler *,
+ const void *,
+ int,
+ const ACE_Time_Value &,
+ const void *)
+{
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::timeout (TIMER_QUEUE &,
+ ACE_Handler *handler,
+ const void *act,
+ int,
+ const ACE_Time_Value &time)
+{
+ if (this->proactor_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%t) No Proactor set in ACE_Proactor_Handle_Timeout_Upcall,")
+ ACE_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->proxy (),
+ act,
+ time,
+ ACE_INVALID_HANDLE,
+ 0,
+ -1);
+
+ if (asynch_timer == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_TEXT ("ACE_Proactor_Handle_Timeout_Upcall::timeout:")
+ ACE_TEXT ("create_asynch_timer failed")),
+ -1);
+
+ auto_ptr<ACE_Asynch_Result_Impl> safe_asynch_timer (asynch_timer);
+
+ // Post a completion.
+ if (-1 == safe_asynch_timer->post_completion
+ (this->proactor_->implementation ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failure in dealing with timers: ")
+ ACE_TEXT ("PostQueuedCompletionStatus failed\n")),
+ -1);
+
+ // The completion has been posted. The proactor is now responsible
+ // for managing the asynch_timer memory.
+ (void) safe_asynch_timer.release ();
+
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::cancel_type (TIMER_QUEUE &,
+ ACE_Handler *,
+ int,
+ int &)
+{
+ // Do nothing
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::cancel_timer (TIMER_QUEUE &,
+ ACE_Handler *,
+ int,
+ int)
+{
+ // Do nothing
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::deletion (TIMER_QUEUE &,
+ ACE_Handler *,
+ const void *)
+{
+ // 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_TEXT ("ACE_Proactor_Handle_Timeout_Upcall is only suppose")
+ ACE_TEXT (" to be used with ONE (and only one) Proactor\n")),
+ -1);
+}
+
+// *********************************************************************
+
+ACE_Proactor::ACE_Proactor (ACE_Proactor_Impl *implementation,
+ bool 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 order: CB, SIG, AIOCB */
+# if !defined(ACE_HAS_BROKEN_SIGEVENT_STRUCT)
+ ACE_NEW (implementation, ACE_POSIX_CB_Proactor);
+# else
+# if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
+ ACE_NEW (implementation, ACE_POSIX_SIG_Proactor);
+# else
+ ACE_NEW (implementation, ACE_POSIX_AIOCB_Proactor);
+# endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
+# endif /* !ACE_HAS_BROKEN_SIGEVENT_STRUCT */
+# endif /* ACE_POSIX_AIOCB_PROACTOR */
+#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_ = true;
+ }
+
+ // 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_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_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_ = true;
+ ACE_REGISTER_FRAMEWORK_COMPONENT(ACE_Proactor, ACE_Proactor::proactor_);
+ }
+ }
+ return ACE_Proactor::proactor_;
+}
+
+ACE_Proactor *
+ACE_Proactor::instance (ACE_Proactor * r, bool 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;
+ ACE_REGISTER_FRAMEWORK_COMPONENT(ACE_Proactor, ACE_Proactor::proactor_);
+
+ 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_ = false;
+ }
+}
+
+const ACE_TCHAR *
+ACE_Proactor::dll_name (void)
+{
+ return ACE_TEXT ("ACE");
+}
+
+const ACE_TCHAR *
+ACE_Proactor::name (void)
+{
+ return ACE_TEXT ("ACE_Proactor");
+}
+
+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 || result == 0)
+ 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.
+ this->end_event_loop_ = 1;
+
+ // Number of completions to post.
+ how_many = this->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_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_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));
+
+ // Remember the old proactor.
+ ACE_Proactor *old_proactor = handler.proactor ();
+
+ // Assign *this* Proactor to the handler.
+ handler.proactor (this);
+
+ // 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;
+ }
+ }
+
+ if (result == -1)
+ {
+ // Reset the old proactor in case of failures.
+ handler.proactor (old_proactor);
+ }
+
+ 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_Connect_Impl *
+ACE_Proactor::create_asynch_connect (void)
+{
+ return this->implementation ()->create_asynch_connect ();
+}
+
+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::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ listen_handle,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Connect_Result_Impl *
+ACE_Proactor::create_asynch_connect_result
+ (ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->create_asynch_connect_result
+ (handler_proxy,
+ connect_handle,
+ act,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Transmit_File_Result_Impl *
+ACE_Proactor::create_asynch_transmit_file_result
+ (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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::Proxy_Ptr &handler_proxy,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->create_asynch_timer
+ (handler_proxy,
+ 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#else /* !ACE_WIN32 || !ACE_HAS_AIO_CALLS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Proactor *
+ACE_Proactor::instance (size_t /* 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 &)
+{
+ // not implemented
+ 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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
diff --git a/ACE/ace/Proactor.h b/ACE/ace/Proactor.h
new file mode 100644
index 00000000000..704eef416ff
--- /dev/null
+++ b/ACE/ace/Proactor.h
@@ -0,0 +1,691 @@
+// -*- 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/config-all.h"
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || 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"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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_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 a timer is registered.
+ int registration (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg);
+
+ /// This method is called before the timer expires.
+ int preinvoke (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time,
+ const void *&upcall_act);
+
+ /// This method is called when the timer expires.
+ int timeout (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time);
+
+ /// This method is called after the timer expires.
+ int postinvoke (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time,
+ const void *upcall_act);
+
+ /// This method is called when a handler is canceled.
+ int cancel_type (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ int dont_call_handle_close,
+ int &requires_reference_counting);
+
+ /// This method is called when a timer is canceled.
+ int cancel_timer (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ int dont_call_handle_close,
+ int requires_reference_counting);
+
+ /// 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 @a implementation is 0, the correct implementation
+ * object will be created. @a delete_implementation flag determines
+ * whether the implementation object should be deleted by the
+ * Proactor or not. If @a tq is 0, a new TIMER_QUEUE is created.
+ */
+ ACE_Proactor (ACE_Proactor_Impl *implementation = 0,
+ bool delete_implementation = false,
+ TIMER_QUEUE *tq = 0);
+
+ /// Destruction.
+ ~ACE_Proactor (void);
+
+ /// Get pointer to a process-wide ACE_Proactor. @a 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,
+ bool delete_proactor = false);
+
+ /// 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);
+
+ /// Name of dll in which the singleton instance lives.
+ static const ACE_TCHAR *dll_name (void);
+
+ /// Name of component--ACE_Proactor in this case.
+ static const ACE_TCHAR *name (void);
+
+ // = 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, in which case 0 is returned.
+ */
+ 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 associated @c ACE_Proactor_Impl implementation object.
+ /**
+ * If @arg delete_implementation was specified to the @c open() method,
+ * the implementation object is also deleted.
+ */
+ 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.
+ */
+ 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, in which case a 0 is returned.
+ */
+ 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.
+ */
+ int proactor_end_event_loop (void);
+
+ /// Report if the ACE_Proactor event loop is finished.
+ int proactor_event_loop_done (void);
+
+ /// Resets the <ACE_Proactor::end_event_loop_> static so that the
+ /// <run_event_loop> method can be restarted.
+ int proactor_reset_event_loop (void);
+
+
+ /// This method adds the @a handle to the I/O completion port. This
+ /// function is a no-op function for Unix systems and returns 0;
+ int register_handle (ACE_HANDLE handle,
+ const void *completion_key);
+
+ // = Timer management.
+ /**
+ * Schedule a @a handler that will expire after <time>. If it
+ * expires then @a act is passed in as the value to the @a 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>).
+ */
+ long schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time);
+
+ long schedule_repeating_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &interval);
+
+ // Same as above except @a interval it is used to reschedule the
+ // @a handler automatically.
+
+ /// This combines the above two methods into one. Mostly for backward
+ /// compatibility.
+ 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 @a handler. Returns number
+ /// of timers cancelled.
+ int cancel_timer (ACE_Handler &handler,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel the single <ACE_Handler> that matches the @a timer_id value
+ * (which was returned from the <schedule> method). If @a 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 @a timer_id
+ * wasn't found.
+ */
+ 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.
+ */
+ 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.
+ */
+ 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);
+
+ /// Get number of thread used as a parameter to CreatIoCompletionPort.
+ size_t number_of_threads (void) const;
+
+ /// Set number of thread used as a parameter to CreatIoCompletionPort.
+ void number_of_threads (size_t threads);
+
+ /// Get timer queue.
+ TIMER_QUEUE *timer_queue (void) const;
+
+ /// Set timer queue.
+ 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.
+ */
+ ACE_HANDLE get_handle (void) const;
+
+ /// Get the implementation class.
+ 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.
+ ACE_Asynch_Read_Stream_Impl *create_asynch_read_stream (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Write_Stream.
+ ACE_Asynch_Write_Stream_Impl *create_asynch_write_stream (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Read_File.
+ ACE_Asynch_Read_File_Impl *create_asynch_read_file (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Write_File.
+ ACE_Asynch_Write_File_Impl *create_asynch_write_file (void);
+
+ /// Create the correct implementation class for doing Asynch_Accept.
+ ACE_Asynch_Accept_Impl *create_asynch_accept (void);
+
+ /// Create the correct implementation class for doing Asynch_Connect.
+ ACE_Asynch_Connect_Impl *create_asynch_connect (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Transmit_File.
+ ACE_Asynch_Transmit_File_Impl *create_asynch_transmit_file (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Read_Dgram.
+ ACE_Asynch_Read_Dgram_Impl *create_asynch_read_dgram (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Write_Dgram.
+ 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.
+ ACE_Asynch_Read_Stream_Result_Impl *
+ create_asynch_read_stream_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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.
+ ACE_Asynch_Write_Stream_Result_Impl *
+ create_asynch_write_stream_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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.
+ ACE_Asynch_Read_File_Result_Impl *
+ create_asynch_read_file_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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.
+ ACE_Asynch_Write_File_Result_Impl *
+ create_asynch_write_file_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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.
+ ACE_Asynch_Read_Dgram_Result_Impl *
+ create_asynch_read_dgram_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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.
+ ACE_Asynch_Write_Dgram_Result_Impl *
+ create_asynch_write_dgram_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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.
+ ACE_Asynch_Accept_Result_Impl *
+ create_asynch_accept_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_Connect::Result
+ ACE_Asynch_Connect_Result_Impl *
+ create_asynch_connect_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ 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.
+ ACE_Asynch_Transmit_File_Result_Impl *
+ create_asynch_transmit_file_result (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 @a 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.
+ */
+ ACE_Asynch_Result_Impl *
+ create_asynch_timer (ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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>.
+ */
+ int proactor_post_wakeup_completions (int how_many);
+
+ /// Set the implementation class.
+ 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.
+ bool delete_implementation_;
+
+ /// Pointer to a process-wide ACE_Proactor.
+ static ACE_Proactor *proactor_;
+
+ /// Must delete the <proactor_> if true.
+ static bool 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 &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (__ACE_INLINE__)
+# include "ace/Proactor.inl"
+# endif /* __ACE_INLINE__ */
+
+#else /* NOT WIN32 or POSIX with AIO features. */
+
+# include "ace/os_include/os_stddef.h"
+# include "ace/os_include/os_signal.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+class ACE_Export ACE_Proactor
+{
+public:
+ class Timer_Queue {};
+ ACE_Proactor (size_t /* number_of_threads */ = 0,
+ Timer_Queue * /* tq */ = 0) {}
+ ~ACE_Proactor (void) {}
+ int handle_events (void) { return -1; }
+ 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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_PROACTOR_H */
diff --git a/ACE/ace/Proactor.inl b/ACE/ace/Proactor.inl
new file mode 100644
index 00000000000..37b887c14d6
--- /dev/null
+++ b/ACE/ace/Proactor.inl
@@ -0,0 +1,80 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Proactor::run_event_loop (void)
+{
+ ACE_TRACE ("ACE_Proactor::run_event_loop");
+ ACE_Proactor * const 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 * const 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 * const 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 * const 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 * const 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 * const p = ACE_Proactor::instance ();
+
+ if (p == 0)
+ return -1;
+
+ return p->proactor_post_wakeup_completions (how_many);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Proactor_Impl.cpp b/ACE/ace/Proactor_Impl.cpp
new file mode 100644
index 00000000000..fe08453778e
--- /dev/null
+++ b/ACE/ace/Proactor_Impl.cpp
@@ -0,0 +1,21 @@
+// $Id$
+
+#include "ace/Proactor_Impl.h"
+
+ACE_RCSID (ace,
+ Proactor_Impl,
+ "$Id$")
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
+// This only works on standard Win32 platforms and on Unix platforms supporting
+// aio calls.
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Proactor_Impl::~ACE_Proactor_Impl (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif
diff --git a/ACE/ace/Proactor_Impl.h b/ACE/ace/Proactor_Impl.h
new file mode 100644
index 00000000000..607fbd0af09
--- /dev/null
+++ b/ACE/ace/Proactor_Impl.h
@@ -0,0 +1,265 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Proactor_Impl.h
+ *
+ * $Id$
+ *
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ * @author Alexander Libman <alibman@ihug.com.au>
+ */
+//=============================================================================
+
+
+#ifndef ACE_PROACTOR_IMPL_H
+#define ACE_PROACTOR_IMPL_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
+// This only works on standard Win32 platforms and on Unix platforms supporting
+// aio calls.
+
+#include "ace/Asynch_IO.h"
+#include "ace/Reactor.h"
+#include "ace/Countdown_Time.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a 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 @a 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;
+
+ /// Get number of thread used as a parameter to CreatIoCompletionPort.
+ virtual size_t number_of_threads (void) const = 0;
+
+ /// Set number of thread used as a parameter to CreatIoCompletionPort.
+ 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_Connect.
+ virtual ACE_Asynch_Connect_Impl *create_asynch_connect (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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t 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_Connect::Result.
+ virtual ACE_Asynch_Connect_Result_Impl *
+ create_asynch_connect_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = 0) = 0;
+
+ /**
+ * Post @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
+#include /**/ "ace/post.h"
+#endif /* ACE_PROACTOR_IMPL_H */
diff --git a/ACE/ace/Process.cpp b/ACE/ace/Process.cpp
new file mode 100644
index 00000000000..11ac859ebf2
--- /dev/null
+++ b/ACE/ace/Process.cpp
@@ -0,0 +1,1275 @@
+// $Id$
+
+#include "ace/Process.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Process.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/ARGV.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Signal.h"
+#include "ace/SString.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_Memory.h"
+#include "ace/Countdown_Time.h"
+#include "ace/Truncate.h"
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600) && defined (__RTP__)
+# include <rtpLib.h>
+# include <taskLib.h>
+#endif
+
+ACE_RCSID (ace, Process, "$Id$")
+
+// This function acts as a signal handler for SIGCHLD. We don't really want
+// to do anything with the signal - it's just needed to interrupt a sleep.
+// See wait() for more info.
+#if !defined (ACE_WIN32) && !defined(ACE_LACKS_UNIX_SIGNALS)
+static void
+sigchld_nop (int, siginfo_t *, ucontext_t *)
+{
+ return;
+}
+#endif /* ACE_WIN32 */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Process::ACE_Process (void)
+ :
+#if !defined (ACE_WIN32)
+ child_id_ (ACE_INVALID_PID),
+#endif /* !defined (ACE_WIN32) */
+ exit_code_ (0)
+{
+#if defined (ACE_WIN32)
+ ACE_OS::memset ((void *) &this->process_info_,
+ 0,
+ sizeof this->process_info_);
+#endif /* ACE_WIN32 */
+}
+
+ACE_Process::~ACE_Process (void)
+{
+#if defined (ACE_WIN32)
+ // Free resources allocated in kernel.
+ ACE_OS::close (this->process_info_.hThread);
+ ACE_OS::close (this->process_info_.hProcess);
+#endif /* ACE_WIN32 */
+ // If any handles were duplicated for the child process and
+ // still not closed, get them now.
+ this->close_dup_handles ();
+}
+
+int
+ACE_Process::prepare (ACE_Process_Options &)
+{
+ return 0;
+}
+
+pid_t
+ACE_Process::spawn (ACE_Process_Options &options)
+{
+ if (this->prepare (options) < 0)
+ return ACE_INVALID_PID;
+
+ // Stash the passed/duped handle sets away in this object for later
+ // closing if needed or requested. At the same time, figure out which
+ // ones to include in command line options if that's needed below.
+ ACE_Handle_Set *set_p = 0;
+ if (options.dup_handles (this->dup_handles_))
+ set_p = &this->dup_handles_;
+ else if (options.passed_handles (this->handles_passed_))
+ set_p = &this->handles_passed_;
+
+ // If we are going to end up running a new program (i.e. Win32, or
+ // NO_EXEC option is set) then get any handles passed in the options,
+ // and tack them onto the command line with +H <handle> options,
+ // unless the command line runs out of space.
+ // Note that we're using the knowledge that all the options, argvs, etc.
+ // passed to the options are all sitting in the command_line_buf. Any
+ // call to get the argv then splits them out. So, regardless of the
+ // platform, tack them all onto the command line buf and take it
+ // from there.
+ if (set_p && !ACE_BIT_ENABLED (options.creation_flags (),
+ ACE_Process_Options::NO_EXEC))
+ {
+ int maxlen = 0;
+ ACE_TCHAR *cmd_line_buf = options.command_line_buf (&maxlen);
+ size_t max_len = static_cast<size_t> (maxlen);
+ size_t curr_len = ACE_OS::strlen (cmd_line_buf);
+ ACE_Handle_Set_Iterator h_iter (*set_p);
+ // Because the length of the to-be-formatted +H option is not
+ // known, and we don't have a snprintf, guess at the space
+ // needed (20 chars), and use that as a limit.
+ for (ACE_HANDLE h = h_iter ();
+ h != ACE_INVALID_HANDLE && curr_len + 20 < max_len;
+ h = h_iter ())
+ {
+#if defined (ACE_WIN32)
+# if defined (ACE_WIN64)
+ curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
+ ACE_TEXT (" +H %I64p"),
+ h);
+# else
+ curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
+ ACE_TEXT (" +H %p"),
+ h);
+# endif /* ACE_WIN64 */
+#else
+ curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
+ ACE_TEXT (" +H %d"),
+ h);
+#endif /* ACE_WIN32 */
+ }
+ }
+
+#if defined (ACE_HAS_WINCE)
+ // Note that WinCE does not have process name included in the command line as argv[0]
+ // like other OS environment. Therefore, it is user's whole responsibility to call
+ // 'ACE_Process_Options::process_name(const ACE_TCHAR *name)' to set the proper
+ // process name (the execution file name with path if needed).
+
+ BOOL fork_result =
+ ACE_TEXT_CreateProcess (options.process_name(),
+ options.command_line_buf(),
+ options.get_process_attributes(), // must be NULL in CE
+ options.get_thread_attributes(), // must be NULL in CE
+ options.handle_inheritence(), // must be false in CE
+ options.creation_flags(), // must be NULL in CE
+ options.env_buf(), // environment variables, must be NULL in CE
+ options.working_directory(), // must be NULL in CE
+ options.startup_info(), // must be NULL in CE
+ &this->process_info_);
+
+ if (fork_result)
+ {
+ parent (this->getpid ());
+ return this->getpid ();
+ }
+ return ACE_INVALID_PID;
+
+#elif defined (ACE_WIN32)
+ BOOL fork_result =
+ ACE_TEXT_CreateProcess (0,
+ options.command_line_buf (),
+ options.get_process_attributes (),
+ options.get_thread_attributes (),
+ options.handle_inheritence (),
+ options.creation_flags (),
+ options.env_buf (), // environment variables
+ options.working_directory (),
+ options.startup_info (),
+ &this->process_info_);
+
+ if (fork_result)
+ {
+ parent (this->getpid ());
+ return this->getpid ();
+ }
+ return ACE_INVALID_PID;
+
+#elif defined(ACE_OPENVMS)
+ if (ACE_BIT_ENABLED (options.creation_flags (),
+ ACE_Process_Options::NO_EXEC))
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
+
+ int saved_stdin = ACE_STDIN;
+ int saved_stdout = ACE_STDOUT;
+ int saved_stderr = ACE_STDERR;
+ // Save STD file descriptors and redirect
+ if (options.get_stdin () != ACE_INVALID_HANDLE) {
+ if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
+ ACE_OS::exit (errno);
+ if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
+ ACE_OS::exit (errno);
+ }
+ if (options.get_stdout () != ACE_INVALID_HANDLE) {
+ if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
+ ACE_OS::exit (errno);
+ if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
+ ACE_OS::exit (errno);
+ }
+ if (options.get_stderr () != ACE_INVALID_HANDLE) {
+ if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
+ ACE_OS::exit (errno);
+ if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
+ ACE_OS::exit (errno);
+ }
+
+ if (options.working_directory () != 0)
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
+
+ this->child_id_ = vfork();
+ if (this->child_id_ == 0) {
+ ACE_OS::execvp (options.process_name (),
+ options.command_line_argv ());
+ // something went wrong
+ this->child_id_ = ACE_INVALID_PID;
+ }
+
+ // restore STD file descriptors (if necessary)
+ if (options.get_stdin () != ACE_INVALID_HANDLE) {
+ if (saved_stdin == -1)
+ ACE_OS::close (ACE_STDIN);
+ else
+ ACE_OS::dup2 (saved_stdin, ACE_STDIN);
+ }
+ if (options.get_stdout () != ACE_INVALID_HANDLE) {
+ if (saved_stdout == -1)
+ ACE_OS::close (ACE_STDOUT);
+ else
+ ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
+ }
+ if (options.get_stderr () != ACE_INVALID_HANDLE) {
+ if (saved_stderr == -1)
+ ACE_OS::close (ACE_STDERR);
+ else
+ ACE_OS::dup2 (saved_stderr, ACE_STDERR);
+ }
+
+ return this->child_id_;
+#elif (defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600)) && defined (__RTP__)
+ if (ACE_BIT_ENABLED (options.creation_flags (),
+ ACE_Process_Options::NO_EXEC))
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
+
+ if (options.working_directory () != 0)
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
+
+ int saved_stdin = ACE_STDIN;
+ int saved_stdout = ACE_STDOUT;
+ int saved_stderr = ACE_STDERR;
+ // Save STD file descriptors and redirect
+ if (options.get_stdin () != ACE_INVALID_HANDLE) {
+ if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
+ ACE_OS::exit (errno);
+ if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
+ ACE_OS::exit (errno);
+ }
+ if (options.get_stdout () != ACE_INVALID_HANDLE) {
+ if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
+ ACE_OS::exit (errno);
+ if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
+ ACE_OS::exit (errno);
+ }
+ if (options.get_stderr () != ACE_INVALID_HANDLE) {
+ if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
+ ACE_OS::exit (errno);
+ if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
+ ACE_OS::exit (errno);
+ }
+
+ // Wide-char builds need narrow-char strings for commandline and
+ // environment variables.
+# if defined (ACE_USES_WCHAR)
+ wchar_t * const *wargv = options.command_line_argv ();
+ size_t vcount, i;
+ for (vcount = 0; wargv[vcount] != 0; ++vcount)
+ ;
+ char **procargv = new char *[vcount + 1]; // Need 0 at the end
+ procargv[vcount] = 0;
+ for (i = 0; i < vcount; ++i)
+ procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
+
+ char **procenv = 0;
+ if (options.inherit_environment ())
+ {
+ wargv = options.env_argv ();
+ for (vcount = 0; wargv[vcount] != 0; ++vcount)
+ ;
+ procenv = new char *[vcount + 1]; // Need 0 at the end
+ procenv[vcount] = 0;
+ for (i = 0; i < vcount; ++i)
+ procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
+ }
+# else
+ const char **procargv = const_cast<const char**> (options.command_line_argv ());
+ const char **procenv = const_cast<const char**> (options.env_argv ());
+# endif /* ACE_USES_WCHAR */
+
+ this->child_id_ = ::rtpSpawn (procargv[0],
+ procargv,
+ procenv,
+ 200, // priority
+ 0x10000, // uStackSize
+ 0, // options
+ VX_FP_TASK); // taskOptions
+ int my_errno_ = errno;
+ if (this->child_id_ == ERROR) {
+ // something went wrong
+ this->child_id_ = ACE_INVALID_PID;
+ }
+
+# if defined (ACE_USES_WCHAR)
+ if (procenv)
+ delete procenv;
+# endif /* ACE_USES_WCHAR */
+
+ // restore STD file descriptors (if necessary)
+ if (options.get_stdin () != ACE_INVALID_HANDLE) {
+ if (saved_stdin == -1)
+ ACE_OS::close (ACE_STDIN);
+ else
+ ACE_OS::dup2 (saved_stdin, ACE_STDIN);
+ }
+ if (options.get_stdout () != ACE_INVALID_HANDLE) {
+ if (saved_stdout == -1)
+ ACE_OS::close (ACE_STDOUT);
+ else
+ ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
+ }
+ if (options.get_stderr () != ACE_INVALID_HANDLE) {
+ if (saved_stderr == -1)
+ ACE_OS::close (ACE_STDERR);
+ else
+ ACE_OS::dup2 (saved_stderr, ACE_STDERR);
+ }
+
+ if (this->child_id_ == ACE_INVALID_PID) {
+ errno = my_errno_;
+ }
+
+ return this->child_id_;
+#else /* ACE_WIN32 */
+ // Fork the new process.
+ this->child_id_ = ACE::fork (options.process_name (),
+ options.avoid_zombies ());
+
+ if (this->child_id_ == 0)
+ {
+# if !defined (ACE_LACKS_SETPGID)
+ // If we're the child and the options specified a non-default
+ // process group, try to set our pgid to it. This allows the
+ // <ACE_Process_Manager> to wait for processes by their
+ // process-group.
+ if (options.getgroup () != ACE_INVALID_PID
+ && ACE_OS::setpgid (0,
+ options.getgroup ()) < 0)
+ {
+#if !defined (ACE_HAS_THREADS)
+ // We can't emit this log message because ACE_ERROR(), etc.
+ // will invoke async signal unsafe functions, which results
+ // in undefined behavior in threaded programs.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
+#endif
+ }
+# endif /* ACE_LACKS_SETPGID */
+
+# if !defined (ACE_LACKS_SETREGID)
+ if (options.getrgid () != (uid_t) -1
+ || options.getegid () != (uid_t) -1)
+ if (ACE_OS::setregid (options.getrgid (),
+ options.getegid ()) == -1)
+ {
+#if !defined (ACE_HAS_THREADS)
+ // We can't emit this log message because ACE_ERROR(), etc.
+ // will invoke async signal unsafe functions, which results
+ // in undefined behavior in threaded programs.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
+#endif
+ }
+# endif /* ACE_LACKS_SETREGID */
+
+# if !defined (ACE_LACKS_SETREUID)
+ // Set user and group id's.
+ if (options.getruid () != (uid_t) -1
+ || options.geteuid () != (uid_t) -1)
+ if (ACE_OS::setreuid (options.getruid (),
+ options.geteuid ()) == -1)
+ {
+#if !defined (ACE_HAS_THREADS)
+ // We can't emit this log message because ACE_ERROR(), etc.
+ // will invoke async signal unsafe functions, which results
+ // in undefined behavior in threaded programs.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
+#endif
+ }
+# endif /* ACE_LACKS_SETREUID */
+
+ this->child (ACE_OS::getppid ());
+ }
+ else if (this->child_id_ != -1)
+ this->parent (this->child_id_);
+
+ // If we're not supposed to exec, return the process id.
+ if (ACE_BIT_ENABLED (options.creation_flags (),
+ ACE_Process_Options::NO_EXEC))
+ return this->child_id_;
+
+ switch (this->child_id_)
+ {
+ case -1:
+ // Error.
+ return ACE_INVALID_PID;
+ case 0:
+ // Child process...exec the
+ {
+ if (options.get_stdin () != ACE_INVALID_HANDLE
+ && ACE_OS::dup2 (options.get_stdin (),
+ ACE_STDIN) == -1)
+ ACE_OS::exit (errno);
+ else if (options.get_stdout () != ACE_INVALID_HANDLE
+ && ACE_OS::dup2 (options.get_stdout (),
+ ACE_STDOUT) == -1)
+ ACE_OS::exit (errno);
+ else if (options.get_stderr () != ACE_INVALID_HANDLE
+ && ACE_OS::dup2 (options.get_stderr (),
+ ACE_STDERR) == -1)
+ ACE_OS::exit (errno);
+
+ // close down unneeded descriptors
+ ACE_OS::close (options.get_stdin ());
+ ACE_OS::close (options.get_stdout ());
+ ACE_OS::close (options.get_stderr ());
+
+ // If we must, set the working directory for the child
+ // process.
+ if (options.working_directory () != 0)
+ ACE_OS::chdir (options.working_directory ());
+ // Should check for error here!
+
+ // Child process executes the command.
+ int result = 0;
+
+ // Wide-char builds not on Windows need narrow-char strings for
+ // exec() and environment variables. Don't need to worry about
+ // releasing any of the converted string memory since this
+ // process will either exec() or exit() shortly.
+# if defined (ACE_USES_WCHAR)
+ ACE_Wide_To_Ascii n_procname (options.process_name ());
+ const char *procname = n_procname.char_rep ();
+
+ wchar_t * const *wargv = options.command_line_argv ();
+ size_t vcount, i;
+ for (vcount = 0; wargv[vcount] != 0; ++vcount)
+ ;
+ char **procargv = new char *[vcount + 1]; // Need 0 at the end
+ procargv[vcount] = 0;
+ for (i = 0; i < vcount; ++i)
+ procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
+
+ wargv = options.env_argv ();
+ for (vcount = 0; wargv[vcount] != 0; ++vcount)
+ ;
+ char **procenv = new char *[vcount + 1]; // Need 0 at the end
+ procenv[vcount] = 0;
+ for (i = 0; i < vcount; ++i)
+ procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
+# else
+ const char *procname = options.process_name ();
+ char *const *procargv = options.command_line_argv ();
+ char *const *procenv = options.env_argv ();
+# endif /* ACE_USES_WCHAR */
+
+ if (options.inherit_environment ())
+ {
+ // Add the new environment variables to the environment
+ // context of the context before doing an <execvp>.
+ for (size_t i = 0; procenv[i] != 0; i++)
+ if (ACE_OS::putenv (procenv[i]) != 0)
+ return ACE_INVALID_PID;
+
+ // Now the forked process has both inherited variables and
+ // the user's supplied variables.
+ result = ACE_OS::execvp (procname, procargv);
+ }
+ else
+ {
+# if defined (ghs)
+ // GreenHills 1.8.8 (for VxWorks 5.3.x) can't compile this
+ // code. Processes aren't supported on VxWorks anyways.
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
+# else
+ result = ACE_OS::execve (procname, procargv, procenv);
+# endif /* ghs */
+ }
+ if (result == -1)
+ {
+ // If the execv fails, this child needs to exit.
+
+ // Exit with the errno so that the calling process can
+ // catch this and figure out what went wrong.
+ ACE_OS::_exit (errno);
+ }
+ // ... otherwise, this is never reached.
+ return 0;
+ }
+ default:
+ // Server process. The fork succeeded.
+ return this->child_id_;
+ }
+#endif /* ACE_WIN32 */
+}
+
+void
+ACE_Process::parent (pid_t)
+{
+ // nothing to do
+}
+
+void
+ACE_Process::child (pid_t)
+{
+ // nothing to do
+}
+
+void
+ACE_Process::unmanage (void)
+{
+ // nothing to do
+}
+
+int
+ACE_Process::running (void) const
+{
+#if defined (ACE_WIN32)
+ DWORD code;
+
+ BOOL result = ::GetExitCodeProcess (this->gethandle (),
+ &code);
+ return result && code == STILL_ACTIVE;
+#else
+ if (ACE_INVALID_PID == this->getpid ())
+ return 0;
+ else
+ return ACE_OS::kill (this->getpid (),
+ 0) == 0
+ || errno != ESRCH;
+#endif /* ACE_WIN32 */
+}
+
+pid_t
+ACE_Process::wait (const ACE_Time_Value &tv,
+ ACE_exitcode *status)
+{
+#if defined (ACE_WIN32)
+ // Don't try to get the process exit status if wait failed so we can
+ // keep the original error code intact.
+ switch (::WaitForSingleObject (process_info_.hProcess,
+ tv.msec ()))
+ {
+ case WAIT_OBJECT_0:
+ // The error status of <GetExitCodeProcess> is nonetheless not
+ // tested because we don't know how to return the value.
+ ::GetExitCodeProcess (process_info_.hProcess,
+ &this->exit_code_);
+ if (status != 0)
+ *status = this->exit_code_;
+ return this->getpid ();
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ return 0;
+ default:
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+#elif defined(ACE_LACKS_UNIX_SIGNALS)
+ if (tv == ACE_Time_Value::zero)
+ {
+ pid_t retv =
+ ACE_OS::waitpid (this->child_id_,
+ &this->exit_code_,
+ WNOHANG);
+ if (status != 0)
+ *status = this->exit_code_;
+
+ return retv;
+ }
+
+ if (tv == ACE_Time_Value::max_time)
+# if defined (ACE_VXWORKS)
+ {
+ pid_t retv;
+ while ( (retv = this->wait (status)) == ACE_INVALID_PID && errno == EINTR ) ;
+ return retv;
+ }
+# else
+ return this->wait (status);
+# endif
+
+ pid_t pid = 0;
+ ACE_Time_Value sleeptm (1); // 1 msec
+ if (sleeptm > tv) // if sleeptime > waittime
+ sleeptm = tv;
+ ACE_Time_Value tmo (tv); // Need one we can change
+ for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
+ {
+ pid = ACE_OS::waitpid (this->getpid (),
+ &this->exit_code_,
+ WNOHANG);
+ if (status != 0)
+ *status = this->exit_code_;
+
+ if (pid > 0 || pid == ACE_INVALID_PID)
+ break; // Got a child or an error - all done
+
+ // pid 0, nothing is ready yet, so wait.
+ // Do a (very) short sleep (only this thread sleeps).
+ ACE_OS::sleep (sleeptm);
+ }
+
+ return pid;
+#else /* !ACE_WIN32 && !ACE_LACKS_UNIX_SIGNALS */
+ if (tv == ACE_Time_Value::zero)
+ {
+ pid_t retv =
+ ACE_OS::waitpid (this->child_id_,
+ &this->exit_code_,
+ WNOHANG);
+ if (status != 0)
+ *status = this->exit_code_;
+
+ return retv;
+ }
+
+ if (tv == ACE_Time_Value::max_time)
+ return this->wait (status);
+
+ // Need to wait but limited to specified time.
+ // Force generation of SIGCHLD, even though we don't want to
+ // catch it - just need it to interrupt the sleep below.
+ // If this object has a reactor set, assume it was given at
+ // open(), and there's already a SIGCHLD action set, so no
+ // action is needed here.
+ ACE_Sig_Action old_action;
+ ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
+ do_sigchld.register_action (SIGCHLD, &old_action);
+
+ pid_t pid;
+ ACE_Time_Value tmo (tv); // Need one we can change
+ for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
+ {
+ pid = ACE_OS::waitpid (this->getpid (),
+ &this->exit_code_,
+ WNOHANG);
+ if (status != 0)
+ *status = this->exit_code_;
+
+ if (pid > 0 || pid == ACE_INVALID_PID)
+ break; // Got a child or an error - all done
+
+ // pid 0, nothing is ready yet, so wait.
+ // Do a sleep (only this thread sleeps) til something
+ // happens. This relies on SIGCHLD interrupting the sleep.
+ // If SIGCHLD isn't delivered, we'll need to do something
+ // with sigaction to force it.
+ if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
+ continue;
+ // Timed out
+ pid = 0;
+ break;
+ }
+
+ // Restore the previous SIGCHLD action if it was changed.
+ old_action.register_action (SIGCHLD);
+
+ return pid;
+#endif /* ACE_WIN32 */
+}
+
+void
+ACE_Process::close_dup_handles (void)
+{
+ if (this->dup_handles_.num_set () > 0)
+ {
+ ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
+ for (ACE_HANDLE h = h_iter ();
+ h != ACE_INVALID_HANDLE;
+ h = h_iter ())
+ ACE_OS::closesocket (h);
+ this->dup_handles_.reset ();
+ }
+ return;
+}
+
+void
+ACE_Process::close_passed_handles (void)
+{
+ if (this->handles_passed_.num_set () > 0)
+ {
+ ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
+ for (ACE_HANDLE h = h_iter ();
+ h != ACE_INVALID_HANDLE;
+ h = h_iter ())
+ ACE_OS::closesocket (h);
+ this->handles_passed_.reset ();
+ }
+ return;
+}
+
+ACE_Process_Options::ACE_Process_Options (bool inherit_environment,
+ int command_line_buf_len,
+ int env_buf_len,
+ int max_env_args)
+ :
+#if !defined (ACE_HAS_WINCE)
+ inherit_environment_ (inherit_environment),
+#endif /* ACE_HAS_WINCE */
+ creation_flags_ (0),
+ avoid_zombies_ (0),
+#if !defined (ACE_HAS_WINCE)
+#if defined (ACE_WIN32)
+ environment_inherited_ (0),
+ handle_inheritence_ (TRUE),
+ process_attributes_ (0),
+ thread_attributes_ (0),
+#else /* ACE_WIN32 */
+ stdin_ (ACE_INVALID_HANDLE),
+ stdout_ (ACE_INVALID_HANDLE),
+ stderr_ (ACE_INVALID_HANDLE),
+ ruid_ ((uid_t) -1),
+ euid_ ((uid_t) -1),
+ rgid_ ((uid_t) -1),
+ egid_ ((uid_t) -1),
+#endif /* ACE_WIN32 */
+ set_handles_called_ (0),
+ environment_buf_index_ (0),
+ environment_argv_index_ (0),
+ environment_buf_ (0),
+ environment_buf_len_ (env_buf_len),
+ max_environment_args_ (max_env_args),
+ max_environ_argv_index_ (max_env_args - 1),
+#endif /* !ACE_HAS_WINCE */
+ command_line_argv_calculated_ (0),
+ command_line_buf_ (0),
+ command_line_copy_ (0),
+ command_line_buf_len_ (command_line_buf_len),
+ process_group_ (ACE_INVALID_PID)
+{
+ ACE_NEW (command_line_buf_,
+ ACE_TCHAR[command_line_buf_len]);
+ command_line_buf_[0] = '\0';
+
+#if !defined (ACE_HAS_WINCE)
+ working_directory_[0] = '\0';
+ ACE_NEW (environment_buf_,
+ ACE_TCHAR[env_buf_len]);
+ ACE_NEW (environment_argv_,
+ ACE_TCHAR *[max_env_args]);
+ environment_buf_[0] = '\0';
+ environment_argv_[0] = 0;
+ process_name_[0] = '\0';
+#if defined (ACE_WIN32)
+ ACE_OS::memset ((void *) &this->startup_info_,
+ 0,
+ sizeof this->startup_info_);
+ this->startup_info_.cb = sizeof this->startup_info_;
+#endif /* ACE_WIN32 */
+#endif /* !ACE_HAS_WINCE */
+}
+
+#if !defined (ACE_HAS_WINCE)
+#if defined (ACE_WIN32)
+void
+ACE_Process_Options::inherit_environment (void)
+{
+ // Ensure only once execution.
+ if (environment_inherited_)
+ return;
+ environment_inherited_ = 1;
+
+ // Get the existing environment.
+ ACE_TCHAR *existing_environment = ACE_OS::getenvstrings ();
+
+ size_t slot = 0;
+
+ while (existing_environment[slot] != '\0')
+ {
+ size_t len = ACE_OS::strlen (existing_environment + slot);
+
+ // Add the string to our env buffer.
+ if (this->setenv_i (existing_environment + slot, len) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("ACE_Process_Options::ACE_Process_Options")));
+ break;
+ }
+
+ // Skip to the next word.
+ slot += len + 1;
+ }
+
+ ACE_TEXT_FreeEnvironmentStrings (existing_environment);
+}
+
+#else /* defined ACE_WIN32 */
+
+ACE_TCHAR * const *
+ACE_Process_Options::env_argv (void)
+{
+ return environment_argv_;
+}
+
+#endif /* ACE_WIN32 */
+
+int
+ACE_Process_Options::setenv (ACE_TCHAR *envp[])
+{
+ int i = 0;
+ while (envp[i])
+ {
+ if (this->setenv_i (envp[i],
+ ACE_OS::strlen (envp[i])) == -1)
+ return -1;
+ i++;
+ }
+
+#if defined (ACE_WIN32)
+ if (inherit_environment_)
+ this->inherit_environment ();
+#endif /* ACE_WIN32 */
+
+ return 0;
+}
+
+int
+ACE_Process_Options::setenv (const ACE_TCHAR *format, ...)
+{
+ ACE_TCHAR stack_buf[DEFAULT_COMMAND_LINE_BUF_LEN];
+
+ // Start varargs.
+ va_list argp;
+ va_start (argp, format);
+
+ // Add the rest of the varargs.
+ ACE_OS::vsprintf (stack_buf,
+ format,
+ argp);
+ // End varargs.
+ va_end (argp);
+
+ // Append the string to are environment buffer.
+ if (this->setenv_i (stack_buf,
+ ACE_OS::strlen (stack_buf)) == -1)
+ return -1;
+
+#if defined (ACE_WIN32)
+ if (inherit_environment_)
+ this->inherit_environment ();
+#endif /* ACE_WIN32 */
+
+ return 0;
+}
+
+int
+ACE_Process_Options::setenv (const ACE_TCHAR *variable_name,
+ const ACE_TCHAR *format, ...)
+{
+ // To address the potential buffer overflow,
+ // we now allocate the buffer on heap with a variable size.
+ size_t const buflen = ACE_OS::strlen (variable_name) + ACE_OS::strlen (format) + 2;
+ ACE_TCHAR *newformat = 0;
+ ACE_NEW_RETURN (newformat, ACE_TCHAR[buflen], -1);
+ ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_newformat (newformat);
+
+ // Add in the variable name.
+ ACE_OS::sprintf (safe_newformat.get (),
+ ACE_TEXT ("%s=%s"),
+ variable_name,
+ format);
+
+ // Start varargs.
+ va_list argp;
+ va_start (argp, format);
+
+ // Add the rest of the varargs.
+ size_t tmp_buflen = DEFAULT_COMMAND_LINE_BUF_LEN > buflen
+ ? static_cast<size_t> (DEFAULT_COMMAND_LINE_BUF_LEN) : buflen;
+ int retval = 0;
+
+ ACE_TCHAR *stack_buf = 0;
+ ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
+ ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_stack_buf (stack_buf);
+
+ do
+ {
+ retval = ACE_OS::vsnprintf (safe_stack_buf.get (), tmp_buflen, safe_newformat.get (), argp);
+ if (retval > ACE_Utils::truncate_cast<int> (tmp_buflen))
+ {
+ tmp_buflen *= 2;
+ ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
+ safe_stack_buf.reset (stack_buf);
+ }
+ else
+ break;
+ }
+ while (1);
+
+ if (retval == -1)
+ {
+ // In case that vsnprintf is not supported,
+ // e.g., LynxOS and VxWorks 5, we have to
+ // fall back to vsprintf.
+ if (errno == ENOTSUP)
+ {
+ // ALERT: Since we have to use vsprintf here, there is still a chance that
+ // the stack_buf overflows, i.e., the length of the resulting string
+ // can still possibly go beyond the allocated stack_buf.
+ retval = ACE_OS::vsprintf (safe_stack_buf.get (), safe_newformat.get (), argp);
+ if (retval == -1)
+ // vsprintf is failed.
+ return -1;
+ }
+ else
+ // vsnprintf is failed.
+ return -1;
+ }
+
+ // End varargs.
+ va_end (argp);
+
+ // Append the string to our environment buffer.
+ if (this->setenv_i (safe_stack_buf.get (),
+ ACE_OS::strlen (safe_stack_buf.get ())) == -1)
+ return -1;
+
+#if defined (ACE_WIN32)
+ if (inherit_environment_)
+ this->inherit_environment ();
+#endif /* ACE_WIN32 */
+
+ return 0;
+}
+
+int
+ACE_Process_Options::setenv_i (ACE_TCHAR *assignment,
+ size_t len)
+{
+ // Add one for the null char.
+ ++len;
+
+ // If environment larger than allocated buffer return. Also check to
+ // make sure we have enough room.
+ if (environment_argv_index_ == max_environ_argv_index_
+ || (len + environment_buf_index_) >= environment_buf_len_)
+ return -1;
+
+ // Copy the new environment string.
+ ACE_OS::memcpy (environment_buf_ + environment_buf_index_,
+ assignment,
+ len * sizeof (ACE_TCHAR));
+
+ // Update the argv array.
+ environment_argv_[environment_argv_index_++] =
+ environment_buf_ + environment_buf_index_;
+ environment_argv_[environment_argv_index_] = 0;
+
+ // Update our index.
+ environment_buf_index_ += len;
+
+ // Make sure the buffer is null-terminated.
+ environment_buf_[environment_buf_index_] = '\0';
+ return 0;
+}
+
+int
+ACE_Process_Options::set_handles (ACE_HANDLE std_in,
+ ACE_HANDLE std_out,
+ ACE_HANDLE std_err)
+{
+ this->set_handles_called_ = 1;
+#if defined (ACE_WIN32)
+
+ // Tell the new process to use our std handles.
+ this->startup_info_.dwFlags = STARTF_USESTDHANDLES;
+
+ if (std_in == ACE_INVALID_HANDLE)
+ std_in = ACE_STDIN;
+ if (std_out == ACE_INVALID_HANDLE)
+ std_out = ACE_STDOUT;
+ if (std_err == ACE_INVALID_HANDLE)
+ std_err = ACE_STDERR;
+
+ if (!::DuplicateHandle (::GetCurrentProcess (),
+ std_in,
+ ::GetCurrentProcess (),
+ &this->startup_info_.hStdInput,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ return -1;
+
+ if (!::DuplicateHandle (::GetCurrentProcess (),
+ std_out,
+ ::GetCurrentProcess (),
+ &this->startup_info_.hStdOutput,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ return -1;
+
+ if (!::DuplicateHandle (::GetCurrentProcess (),
+ std_err,
+ ::GetCurrentProcess (),
+ &this->startup_info_.hStdError,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ return -1;
+#else /* ACE_WIN32 */
+ this->stdin_ = ACE_OS::dup (std_in);
+ this->stdout_ = ACE_OS::dup (std_out);
+ this->stderr_ = ACE_OS::dup (std_err);
+#endif /* ACE_WIN32 */
+
+ return 0; // Success.
+}
+
+
+void
+ACE_Process_Options::release_handles ()
+{
+ if (set_handles_called_)
+ {
+#if defined (ACE_WIN32)
+ ACE_OS::close (startup_info_.hStdInput);
+ ACE_OS::close (startup_info_.hStdOutput);
+ ACE_OS::close (startup_info_.hStdError);
+#else /* ACE_WIN32 */
+ ACE_OS::close (stdin_);
+ ACE_OS::close (stdout_);
+ ACE_OS::close (stderr_);
+#endif /* ACE_WIN32 */
+ set_handles_called_ = 0;
+ }
+}
+#endif /* !ACE_HAS_WINCE */
+
+
+ACE_Process_Options::~ACE_Process_Options (void)
+{
+#if !defined (ACE_HAS_WINCE)
+ release_handles();
+ delete [] environment_buf_;
+ delete [] environment_argv_;
+#endif /* !ACE_HAS_WINCE */
+ delete [] command_line_buf_;
+ ACE::strdelete (command_line_copy_);
+}
+
+int
+ACE_Process_Options::command_line (const ACE_TCHAR *const argv[])
+{
+ // @@ Factor out the code between this
+ int i = 0;
+
+ if (argv[i])
+ {
+ ACE_OS::strcat (command_line_buf_, argv[i]);
+ while (argv[++i])
+ {
+ ACE_OS::strcat (command_line_buf_,
+ ACE_TEXT (" "));
+ ACE_OS::strcat (command_line_buf_,
+ argv[i]);
+ }
+ }
+
+ command_line_argv_calculated_ = 0;
+ return 0; // Success.
+}
+
+int
+ACE_Process_Options::command_line (const ACE_TCHAR *format, ...)
+{
+ // Store all ... args in argp.
+ va_list argp;
+ va_start (argp, format);
+
+ if (command_line_buf_len_ < 1)
+ return -1;
+
+#if !defined (ACE_LACKS_VSNPRINTF) || defined (ACE_HAS_TRIO)
+ // vsnprintf the format and args into command_line_buf__.
+ ACE_OS::vsnprintf (command_line_buf_,
+ command_line_buf_len_,
+ format,
+ argp);
+#else
+ // sprintf the format and args into command_line_buf__.
+ ACE_OS::vsprintf (command_line_buf_,
+ format,
+ argp);
+#endif
+
+ // Useless macro.
+ va_end (argp);
+
+ command_line_argv_calculated_ = 0;
+ return 0;
+}
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_HAS_WINCE)
+/**
+ * @note Not available on Windows CE because it doesn't have a char version of
+ * vsprintf.
+ */
+int
+ACE_Process_Options::command_line (const ACE_ANTI_TCHAR *format, ...)
+{
+ ACE_ANTI_TCHAR *anti_clb;
+ ACE_NEW_RETURN (anti_clb,
+ ACE_ANTI_TCHAR[this->command_line_buf_len_],
+ -1);
+
+ // Store all ... args in argp.
+ va_list argp;
+ va_start (argp, format);
+
+ // sprintf the format and args into command_line_buf_.
+ ACE_OS::vsprintf (anti_clb,
+ format,
+ argp);
+
+ // Useless macro.
+ va_end (argp);
+
+ ACE_OS::strcpy (this->command_line_buf_,
+ ACE_TEXT_ANTI_TO_TCHAR (anti_clb));
+
+ delete [] anti_clb;
+
+ command_line_argv_calculated_ = 0;
+ return 0;
+}
+#endif /* ACE_HAS_WCHAR && !ACE_HAS_WINCE */
+
+ACE_TCHAR *
+ACE_Process_Options::env_buf (void)
+{
+#if !defined (ACE_HAS_WINCE)
+ if (environment_buf_[0] == '\0')
+ return 0;
+ else
+ return environment_buf_;
+#else
+ return 0;
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_TCHAR * const *
+ACE_Process_Options::command_line_argv (void)
+{
+ if (command_line_argv_calculated_ == 0)
+ {
+ command_line_argv_calculated_ = 1;
+
+ // We need to free up any previous allocated memory first.
+ ACE::strdelete (command_line_copy_);
+
+ // We need to make a dynamically allocated copy here since
+ // ACE_Tokenizer modifies its arguments.
+ command_line_copy_ = ACE::strnew (command_line_buf_);
+ // This tokenizer will replace all spaces with end-of-string
+ // characters and will preserve text between "" and '' pairs.
+ ACE_Tokenizer parser (command_line_copy_);
+ parser.delimiter_replace (' ', '\0');
+ parser.preserve_designators ('\"', '\"'); // "
+ parser.preserve_designators ('\'', '\'');
+
+ int x = 0;
+ do
+ command_line_argv_[x] = parser.next ();
+ while (command_line_argv_[x] != 0
+ // substract one for the ending zero.
+ && ++x < MAX_COMMAND_LINE_OPTIONS - 1);
+
+ command_line_argv_[x] = 0;
+ }
+
+ return command_line_argv_;
+}
+
+// Cause the specified handle to be passed to a child process
+// when it's spawned.
+int
+ACE_Process_Options::pass_handle (ACE_HANDLE h)
+{
+# if defined (ACE_WIN32)
+# if defined (ACE_HAS_WINCE)
+ ACE_NOTSUP_RETURN (-1);
+# else
+
+ // This is oriented towards socket handles... may need some adjustment
+ // for non-sockets.
+ // This is all based on an MSDN article:
+ // http://support.microsoft.com/support/kb/articles/Q150/5/23.asp
+ // If on Win95/98, the handle needs to be duplicated for the to-be-spawned
+ // process. On WinNT, they get inherited by the child process automatically.
+ // If the handle is duplicated, remember the duplicate so it can be
+ // closed later. Can't be closed now, or the child won't get it.
+ ACE_TEXT_OSVERSIONINFO osvi;
+ ZeroMemory (&osvi, sizeof (osvi));
+ osvi.dwOSVersionInfoSize = sizeof (ACE_TEXT_OSVERSIONINFO);
+ // If this is Win95/98 or we can't tell, duplicate the handle.
+ if (!ACE_TEXT_GetVersionEx (&osvi) || osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
+ {
+ HANDLE dup_handle;
+ if (!DuplicateHandle (GetCurrentProcess (),
+ static_cast<HANDLE> (h),
+ GetCurrentProcess (),
+ &dup_handle,
+ 0,
+ TRUE, // Inheritable
+ DUPLICATE_SAME_ACCESS))
+ return -1;
+ dup_handles_.set_bit (static_cast<ACE_HANDLE> (dup_handle));
+ }
+# endif /* ACE_HAS_WINCE */
+#endif /* ACE_WIN32 */
+
+ this->handles_passed_.set_bit (h);
+
+ return 0;
+}
+
+// Get a copy of the handles the ACE_Process_Options duplicated
+// for the spawned process.
+int
+ACE_Process_Options::dup_handles (ACE_Handle_Set &set) const
+{
+ if (this->dup_handles_.num_set () == 0)
+ return 0;
+ set.reset ();
+ set = this->dup_handles_;
+ return 1;
+}
+
+// Get a copy of the handles passed to the spawned process. This
+// will be the set of handles previously passed to @arg pass_handle().
+int
+ACE_Process_Options::passed_handles (ACE_Handle_Set &set) const
+{
+ if (this->handles_passed_.num_set () == 0)
+ return 0;
+ set.reset ();
+ set = this->handles_passed_;
+ return 1;
+}
+
+ACE_Managed_Process::~ACE_Managed_Process (void)
+{
+}
+
+void
+ACE_Managed_Process::unmanage (void)
+{
+ delete this;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Process.h b/ACE/ace/Process.h
new file mode 100644
index 00000000000..140c6bb6e5f
--- /dev/null
+++ b/ACE/ace/Process.h
@@ -0,0 +1,617 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Process.h
+ *
+ * $Id$
+ *
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_PROCESS_H
+#define ACE_PROCESS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Handle_Set.h"
+#include "ace/Global_Macros.h"
+#include "ace/os_include/sys/os_types.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Process_Options
+ *
+ * @brief Process Options
+ *
+ * This class controls the options passed to <CreateProcess> (or <fork>
+ * and <exec>).
+ * Notice that on Windows CE, creating a process merely means
+ * instantiating a new process. You can't set the handles (since
+ * there's no stdin, stdout and stderr,) specify process/thread
+ * options, set environment,... So, basically, this class only
+ * set the command line and nothing else.
+ * Notice that on UNIX platforms, if the <setenv> is used, the
+ * <spawn> is using the <execve> system call. It means that the
+ * <command_line> should include a full path to the program file
+ * (<execve> does not search the PATH). If <setenv> is not used
+ * then, the <spawn> is using the <execvp> which searches for the
+ * program file in the PATH variable.
+ */
+class ACE_Export ACE_Process_Options
+{
+public:
+ enum
+ {
+ DEFAULT_COMMAND_LINE_BUF_LEN = 1024,
+ // UNIX process creation flags.
+#if defined (ACE_WIN32)
+ NO_EXEC = 0
+#else
+ NO_EXEC = 1
+#endif /* ACE_WIN32 */
+ };
+
+protected:
+ // = Default settings not part of public Interface.
+ //
+ /// @todo These sizes should be taken from the appropriate
+ /// POSIX/system header files and/or defined dynamically.
+ enum
+ {
+ MAX_COMMAND_LINE_OPTIONS = 128,
+ ENVIRONMENT_BUFFER = 16 * 1024, // 16K
+ MAX_ENVIRONMENT_ARGS = 512 //
+ };
+
+public:
+ /**
+ * If @a inherit_environment == true, the new process will inherit the
+ * environment of the current process. @a command_line_buf_len is the
+ * max strlen for command-line arguments.
+ */
+ ACE_Process_Options (bool inherit_environment = true,
+ int command_line_buf_len = DEFAULT_COMMAND_LINE_BUF_LEN,
+ int env_buf_len = ENVIRONMENT_BUFFER,
+ int max_env_args = MAX_ENVIRONMENT_ARGS);
+
+ /// Destructor.
+ ~ACE_Process_Options (void);
+
+ // = Methods to set process creation options portably.
+
+ /**
+ * Set the standard handles of the new process to the respective
+ * handles. If you want to affect a subset of the handles, make
+ * sure to set the others to ACE_INVALID_HANDLE. Returns 0 on
+ * success, -1 on failure.
+ */
+ int set_handles (ACE_HANDLE std_in,
+ ACE_HANDLE std_out = ACE_INVALID_HANDLE,
+ ACE_HANDLE std_err = ACE_INVALID_HANDLE);
+
+ /// Release the standard handles previously set with set_handles;
+ void release_handles (void);
+
+ /// @param format must be of the form "VARIABLE=VALUE". There can not be
+ /// any spaces between VARIABLE and the equal sign.
+ int setenv (const ACE_TCHAR *format,
+ ...);
+
+ /**
+ * Set a single environment variable, @a variable_name. Since
+ * different platforms separate each environment variable
+ * differently, you must call this method once for each variable.
+ * <format> can be any printf format string. So options->setenv
+ * ("FOO","one + two = %s", "three") will result in "FOO=one + two =
+ * three".
+ */
+ int setenv (const ACE_TCHAR *variable_name,
+ const ACE_TCHAR *format,
+ ...);
+
+ /// Same as above with argv format. @a envp must be null terminated.
+ int setenv (ACE_TCHAR *envp[]);
+
+ /// Set the working directory for the process. strlen of @a wd must
+ /// be <= MAXPATHLEN.
+ void working_directory (const char *wd);
+
+#if defined (ACE_HAS_WCHAR)
+ /// wchar_t version of working_directory
+ void working_directory (const wchar_t *wd);
+#endif /* ACE_HAS_WCHAR */
+
+ /**
+ * Set the command-line arguments. @a format can use any printf
+ * formats. The first token in @a format should be the path to the
+ * application. This can either be a full path, relative path, or
+ * just an executable name. If an executable name is used, we rely
+ * on the platform's support for searching paths. Since we need a
+ * path to run a process, this method *must* be called! Returns 0
+ * on success, -1 on failure.
+ */
+ int command_line (const ACE_TCHAR *format, ...);
+
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_HAS_WINCE)
+ /// Anti-TChar version of command_line ()
+ int command_line (const ACE_ANTI_TCHAR *format, ...);
+#endif /* ACE_HAS_WCHAR && !ACE_HAS_WINCE */
+
+ /// Same as above in argv format. @a argv must be null terminated.
+ int command_line (const ACE_TCHAR * const argv[]);
+
+ /**
+ * Specify the full path or relative path, or just the executable
+ * name for the process. If this is set, then @a name will be used to
+ * create the process instead of argv[0] set in the command
+ * line. This is here so that you can supply something other than
+ * executable name as argv[0].
+ */
+ void process_name (const ACE_TCHAR *name);
+
+ /// Return the process_name. If the <process_name(name)> set
+ /// method is not called, this method will return argv[0].
+ const ACE_TCHAR *process_name (void);
+
+ /// Get the creation flags.
+ u_long creation_flags (void) const;
+
+ /**
+ * Set the creation flags to affect how a new process is spawned.
+ * The only ACE-defined flag is @c NO_EXEC which prevents the new process
+ * from executing a new program image; this is a simple POSIX fork().
+ * The @c NO_EXEC option has no affect on Windows; on other platforms where
+ * a POSIX fork is not possible, specifying @c NO_EXEC will cause
+ * ACE_Process::spawn() to fail.
+ *
+ * On Windows, the value of creation_flags is passed to the @c CreateProcess
+ * system call as the value of the @c dwCreationFlags parameter.
+ */
+ void creation_flags (u_long);
+
+ /// Current working directory. Returns "" if nothing has been set.
+ ACE_TCHAR *working_directory (void);
+
+ /// Buffer of command-line options. Returns a pointer to a buffer that
+ /// contains the list of command line options. Prior to a call to
+ /// command_line_argv(), this is a single string of space separated
+ /// arguments independent of which form of command_line() was used to
+ /// create it. After a call to command_line_argv(), this is a list of
+ /// strings each terminated by '\0'. [Note: spawn() will call
+ /// command_line_argv().] The total length of all these strings is the
+ /// same as the single string in the prior case and can be obtained by
+ /// providing max_len. @arg max_len, if non-zero, provides a location
+ /// into which the total length of the command line buffer is returned.
+ ACE_TCHAR *command_line_buf (int *max_len = 0);
+
+ /**
+ * argv-style command-line options. Parses and modifies the string
+ * created from <command_line_>. All spaces not in quotes ("" or
+ * '') are replaced with null (\0) bytes. An argv array is built
+ * and returned with each entry pointing to the start of
+ * null-terminated string. Returns { 0 } if nothing has been set.
+ */
+ ACE_TCHAR * const *command_line_argv (void);
+
+ /**
+ * Null-terminated buffer of null terminated strings. Each string
+ * is an environment assignment "VARIABLE=value". This buffer
+ * should end with two null characters.
+ */
+ ACE_TCHAR *env_buf (void);
+
+ /// Get the process group. On UNIX, these methods are used by the
+ /// ACE_Process_Manager to manage groups of processes.
+ pid_t getgroup (void) const;
+
+ /// Set the process group. On UNIX, these methods are used by the
+ /// ACE_Process_Manager to manage groups of processes.
+ pid_t setgroup (pid_t pgrp);
+
+ /// Allows disabling of handle inheritence, default is TRUE.
+ int handle_inheritence (void);
+ void handle_inheritence (int);
+
+ /// Cause the specified handle to be passed to a child process
+ /// when it runs a new program image.
+ /**
+ * The specified handle value will be included in the spawned
+ * process's command line as @arg +H @arg handle, if a new
+ * program is spawned (always on Win32; else if NO_EXEC is not
+ * set in creation flags). The passed handle value will be
+ * duplicated if on Win32 less capable than NT.
+ * @return 0 if success, -1 if failure.
+ */
+ int pass_handle (ACE_HANDLE);
+
+ /// Get a copy of the handles the ACE_Process_Options duplicated
+ /// for the spawned process.
+ /**
+ * Any handles created through duplication of those passed into
+ * @arg pass_handle are returned in @arg set.
+ * @return 0 if there were no handles to return; 1 if there were.
+ */
+ int dup_handles (ACE_Handle_Set &set) const;
+
+ /// Get a copy of the handles passed to the spawned process. This
+ /// will be the set of handles previously passed to @arg pass_handle().
+ /**
+ * Any handles previously passed to @arg pass_handle are returned
+ * in @arg set.
+ * @return 0 if there were no handles to return; 1 if there were.
+ */
+ int passed_handles (ACE_Handle_Set &set) const;
+
+ /// Set value for avoid_zombies (has no real effect except on *nix).
+ void avoid_zombies (int);
+
+ /// Get current value for avoid_zombies.
+ int avoid_zombies (void);
+
+#if defined (ACE_WIN32)
+ // = Non-portable accessors for when you "just have to use them."
+
+ /// Used for setting and getting.
+ ACE_TEXT_STARTUPINFO *startup_info (void);
+
+ /// Get the process_attributes. Returns NULL if
+ /// set_process_attributes has not been set.
+ LPSECURITY_ATTRIBUTES get_process_attributes (void) const;
+
+ /// If this is called, a non-null process attributes is sent to
+ /// CreateProcess.
+ LPSECURITY_ATTRIBUTES set_process_attributes (void);
+
+ /// Get the thread_attributes. Returns NULL if set_thread_attributes
+ /// has not been set.
+ LPSECURITY_ATTRIBUTES get_thread_attributes (void) const;
+
+ /// If this is called, a non-null thread attributes is sent to
+ /// CreateProcess.
+ LPSECURITY_ATTRIBUTES set_thread_attributes (void);
+
+#else /* All things not WIN32 */
+
+ /// argv-style array of environment settings.
+ ACE_TCHAR *const *env_argv (void);
+
+ // = Accessors for the standard handles.
+ ACE_HANDLE get_stdin (void) const;
+ ACE_HANDLE get_stdout (void) const;
+ ACE_HANDLE get_stderr (void) const;
+
+ // = Set/get real & effective user & group id associated with user.
+ int setreugid (const ACE_TCHAR* user);
+ void setruid (uid_t id);
+ void seteuid (uid_t id);
+ void setrgid (uid_t id);
+ void setegid (uid_t id);
+ uid_t getruid (void) const;
+ uid_t geteuid (void) const;
+ uid_t getrgid (void) const;
+ uid_t getegid (void) const;
+
+ /**
+ * Get the inherit_environment flag.
+ */
+ bool inherit_environment (void) const;
+
+ /**
+ * Set the inherit_environment flag.
+ */
+ void inherit_environment (bool nv);
+#endif /* ACE_WIN32 */
+protected:
+
+#if !defined (ACE_HAS_WINCE)
+ /// Add @a assignment to environment_buf_ and adjust
+ /// environment_argv_. @a len is the strlen of @a assignment.
+ int setenv_i (ACE_TCHAR *assignment, size_t len);
+
+ /// Whether the child process inherits the current process
+ /// environment.
+ bool inherit_environment_;
+#endif /* !ACE_HAS_WINCE */
+
+ /// Default 0.
+ u_long creation_flags_;
+
+ /// Avoid zombies for spawned processes.
+ int avoid_zombies_;
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ /// Helper function to grab win32 environment and stick it in
+ /// environment_buf_ using this->setenv_i.
+ void inherit_environment (void);
+
+ /// Ensures once only call to inherit environment.
+ int environment_inherited_;
+
+ ACE_TEXT_STARTUPINFO startup_info_;
+
+ /// Default TRUE.
+ BOOL handle_inheritence_;
+
+ /// Pointer to security_buf1_.
+ LPSECURITY_ATTRIBUTES process_attributes_;
+
+ /// Pointer to security_buf2_.
+ LPSECURITY_ATTRIBUTES thread_attributes_;
+
+ /// Data for process_attributes_.
+ SECURITY_ATTRIBUTES security_buf1_;
+
+ /// Data for thread_attributes_.
+ SECURITY_ATTRIBUTES security_buf2_;
+
+#else /* !ACE_WIN32 */
+ ACE_HANDLE stdin_;
+ ACE_HANDLE stdout_;
+ ACE_HANDLE stderr_;
+
+ // = Real & effective user & group id's.
+ // These should be set to -1 to leave unchanged (default).
+ uid_t ruid_;
+ uid_t euid_;
+ uid_t rgid_;
+ uid_t egid_;
+#endif /* ACE_WIN32 */
+
+#if !defined (ACE_HAS_WINCE)
+ /// Is 1 if stdhandles was called.
+ int set_handles_called_;
+
+ /// Pointer into environment_buf_. This should point to the next
+ /// free spot.
+ size_t environment_buf_index_;
+
+ /// Pointer to environment_argv_.
+ int environment_argv_index_;
+
+ /// Pointer to buffer of the environment settings.
+ ACE_TCHAR *environment_buf_;
+
+ /// Size of the environment buffer. Configurable
+ size_t environment_buf_len_;
+
+ /// Pointers into environment_buf_.
+ ACE_TCHAR **environment_argv_;
+
+ /// Maximum number of environment variables. Configurable
+ int max_environment_args_;
+
+ /// Maximum index of environment_argv_ buffer
+ int max_environ_argv_index_;
+
+ /// The current working directory.
+ ACE_TCHAR working_directory_[MAXPATHLEN + 1];
+#endif /* !ACE_HAS_WINCE */
+
+ /// Ensures command_line_argv is only calculated once.
+ int command_line_argv_calculated_;
+
+ /// Pointer to buffer of command-line arguments. E.g., "-f foo -b bar".
+ ACE_TCHAR *command_line_buf_;
+
+ /// Pointer to copy of command-line arguments, which is needed when
+ /// converting a command-line string into a command-line argv.
+ ACE_TCHAR *command_line_copy_;
+
+ /// Max length of command_line_buf_
+ int command_line_buf_len_;
+
+ /// Argv-style command-line arguments.
+ ACE_TCHAR *command_line_argv_[MAX_COMMAND_LINE_OPTIONS];
+
+ /// Process-group on Unix; unused on Win32.
+ pid_t process_group_;
+
+ /// Set of handles that were passed in pass_handle ().
+ ACE_Handle_Set handles_passed_;
+
+ /// Results of duplicating handles passed in pass_handle ().
+ ACE_Handle_Set dup_handles_;
+
+ /// Pathname for the process. Relative path or absolute path or just
+ /// the program name.
+ ACE_TCHAR process_name_[MAXPATHLEN + 1];
+};
+
+//class ACE_Process_Manager;
+
+/**
+ * @class ACE_Process
+ *
+ * @brief Process
+ *
+ * A Portable encapsulation for creating new processes.
+ * Notice that on UNIX platforms, if the <setenv> is used, the
+ * <spawn> is using the <execve> system call. It means that the
+ * <command_line> should include a full path to the program file
+ * (<execve> does not search the PATH). If <setenv> is not used
+ * then, the <spawn> is using the <execvp> which searches for the
+ * program file in the PATH variable.
+ */
+class ACE_Export ACE_Process
+{
+public:
+ friend class ACE_Process_Manager;
+
+ /// Default construction. Must use <ACE_Process::spawn> to start.
+ ACE_Process (void);
+
+ /// Destructor.
+ virtual ~ACE_Process (void);
+
+ /**
+ * Called just before <ACE_OS::fork> in the <spawn>. If this
+ * returns non-zero, the <spawn> is aborted (and returns
+ * ACE_INVALID_PID). The default simply returns zero.
+ */
+ virtual int prepare (ACE_Process_Options &options);
+
+ /**
+ * Launch a new process as described by @a options. On success,
+ * returns 1 if the option avoid_zombies is set, else returns the
+ * process id of the newly spawned child. Returns -1 on
+ * failure. This will be fixed in the future versions of ACE when
+ * the process id of the child will be returned regardless of the option.
+ */
+ virtual pid_t spawn (ACE_Process_Options &options);
+
+ /// Called just after <ACE_OS::fork> in the parent's context, if the
+ /// <fork> succeeds. The default is to do nothing.
+ virtual void parent (pid_t child);
+
+ /**
+ * Called just after <ACE_OS::fork> in the child's context. The
+ * default does nothing. This function is *not* called on Win32
+ * because the process-creation scheme does not allow it.
+ */
+ virtual void child (pid_t parent);
+
+ /// Called by a <Process_Manager> that is removing this Process from
+ /// its table of managed Processes. Default is to do nothing.
+ virtual void unmanage (void);
+
+ /**
+ * Wait for the process we've created to exit. If <status> != 0, it
+ * points to an integer where the function store the exit status of
+ * child process to. If <wait_options> == <WNOHANG> then return 0
+ * and don't block if the child process hasn't exited yet. A return
+ * value of -1 represents the <wait> operation failed, otherwise,
+ * the child process id is returned.
+ */
+ pid_t wait (ACE_exitcode *status = 0,
+ int wait_options = 0);
+
+ /**
+ * Timed wait for the process we've created to exit. A return value
+ * of -1 indicates that the something failed; 0 indicates that a
+ * timeout occurred. Otherwise, the child's process id is returned.
+ * If <status> != 0, it points to an integer where the function
+ * stores the child's exit status.
+ *
+ * @note On UNIX platforms this function uses <ualarm>, i.e., it
+ * overwrites any existing alarm. In addition, it steals all
+ * <SIGCHLD>s during the timeout period, which will break another
+ * <ACE_Process_Manager> in the same process that's expecting
+ * <SIGCHLD> to kick off process reaping.
+ */
+ pid_t wait (const ACE_Time_Value &tv,
+ ACE_exitcode *status = 0);
+
+ /// Send the process a signal. This is only portable to operating
+ /// systems that support signals, such as UNIX/POSIX.
+ int kill (int signum = SIGINT);
+
+ /**
+ * Terminate the process abruptly using <ACE::terminate_process>.
+ * This call doesn't give the process a chance to cleanup, so use it
+ * with caution...
+ */
+ int terminate (void);
+
+ /// Return the process id of the new child process.
+ pid_t getpid (void) const;
+
+ /// Return the handle of the process, if it has one.
+ ACE_HANDLE gethandle (void) const;
+
+ /// Return 1 if running; 0 otherwise.
+ int running (void) const;
+
+ /// Return the Process' exit code. This method returns the raw
+ /// exit status returned from system APIs (such as <wait> or
+ /// <waitpid>). This value is system dependent.
+ ACE_exitcode exit_code (void) const;
+
+ /// Return the Process' return value. This method returns the
+ /// actual return value that a child process returns or <exit>s.
+ int return_value (void) const;
+
+ /// Close all the handles in the set obtained from the
+ /// @arg ACE_Process_Options::dup_handles object used to spawn
+ /// the process.
+ void close_dup_handles (void);
+
+ /// Close all the handles in the set obtained from the
+ /// @arg ACE_Process_Options::passed_handles object used to spawn
+ /// the process.
+ void close_passed_handles (void);
+
+#if defined (ACE_WIN32)
+ PROCESS_INFORMATION process_info (void);
+#endif /* ACE_WIN32 */
+
+private:
+
+ // Disallow copying and assignment since we don't support this (yet).
+ ACE_Process (const ACE_Process &);
+ void operator= (const ACE_Process &);
+
+protected:
+ /// Set this process' <exit_code_>. ACE_Process_Manager uses this
+ /// method to set the <exit_code_> after successfully waiting for
+ /// this process to exit.
+ void exit_code (ACE_exitcode code);
+
+#if defined (ACE_WIN32)
+ PROCESS_INFORMATION process_info_;
+#else /* ACE_WIN32 */
+ /// Process id of the child.
+ pid_t child_id_;
+#endif /* ACE_WIN32 */
+ ACE_exitcode exit_code_;
+
+ /// Set of handles that were passed to the child process.
+ ACE_Handle_Set handles_passed_;
+ /// Handle duplicates made for the child process.
+ ACE_Handle_Set dup_handles_;
+
+};
+
+
+/**
+ * @class ACE_Managed_Process
+ *
+ * @brief A process easily managed by ACE_Process_Manager.
+ *
+ * @arg ACE_Managed_Process is just an @arg ACE_Process with an
+ * @arg unmanage() method that deletes the instance.
+ * This class is only valid for use as a dynamically-allocated object!
+ */
+class ACE_Export ACE_Managed_Process : public ACE_Process
+{
+public:
+
+ /// Cleanup by deleting @c this.
+ virtual void unmanage (void);
+
+protected:
+
+ /// Make sure that we're allocated dynamically!
+ virtual ~ACE_Managed_Process (void);
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Process.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_PROCESS_H */
diff --git a/ACE/ace/Process.inl b/ACE/ace/Process.inl
new file mode 100644
index 00000000000..228874778ce
--- /dev/null
+++ b/ACE/ace/Process.inl
@@ -0,0 +1,412 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/ACE.h"
+#include "ace/OS_NS_sys_wait.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/OS_NS_pwd.h"
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_WIN32)
+
+ACE_INLINE PROCESS_INFORMATION
+ACE_Process::process_info (void)
+{
+ return process_info_;
+}
+#endif /* ACE_WIN32 */
+
+ACE_INLINE ACE_HANDLE
+ACE_Process::gethandle (void) const
+{
+#if defined (ACE_WIN32)
+ return process_info_.hProcess;
+#else
+ return ACE_HANDLE (child_id_);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE pid_t
+ACE_Process::getpid (void)
+ const
+{
+#if defined (ACE_WIN32)
+ return process_info_.dwProcessId;
+#else /* ACE_WIN32 */
+ return child_id_;
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE pid_t
+ACE_Process::wait (ACE_exitcode *status,
+ int wait_options)
+{
+ pid_t retv =
+ ACE_OS::wait (this->getpid (),
+ &this->exit_code_,
+ wait_options
+#if defined (ACE_WIN32)
+ , process_info_.hProcess
+#endif /* ACE_WIN32 */
+ );
+ if (status != 0)
+ *status = this->exit_code_;
+
+ return retv;
+}
+
+ACE_INLINE int
+ACE_Process::kill (int signum)
+{
+ if (this->getpid () != -1)
+ return ACE_OS::kill (this->getpid (), signum);
+ else
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Process::terminate (void)
+{
+ if (this->getpid () != -1)
+ return ACE::terminate_process (this->getpid ());
+ else
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Process::return_value (void) const
+{
+#if defined (ACE_WIN32)
+ return this->exit_code_;
+#else
+ return WEXITSTATUS (this->exit_code_);
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ACE_exitcode
+ACE_Process::exit_code (void) const
+{
+ return this->exit_code_;
+}
+
+ACE_INLINE void
+ACE_Process::exit_code (ACE_exitcode code)
+{
+ this->exit_code_ = code;
+}
+
+ACE_INLINE u_long
+ACE_Process_Options::creation_flags (void) const
+{
+#if defined (ACE_USES_WCHAR) && defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ return creation_flags_ | CREATE_UNICODE_ENVIRONMENT;
+#else
+ return creation_flags_;
+#endif /* ACE_USES_WCHAR */
+}
+
+ACE_INLINE void
+ACE_Process_Options::creation_flags (u_long cf)
+{
+ creation_flags_ = cf;
+}
+
+ACE_INLINE pid_t
+ACE_Process_Options::getgroup (void) const
+{
+ return process_group_;
+}
+
+ACE_INLINE pid_t
+ACE_Process_Options::setgroup (pid_t pgrp)
+{
+ pid_t old = process_group_;
+ process_group_ = pgrp;
+ return old;
+}
+
+ACE_INLINE int
+ACE_Process_Options::handle_inheritence (void)
+{
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ return handle_inheritence_;
+#else
+ ACE_NOTSUP_RETURN (0); // This is a benign error.
+#endif /* ACE_WIN32 && ! ACE_HAS_WINCE */
+}
+
+ACE_INLINE void
+ACE_Process_Options::handle_inheritence (int hi)
+{
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ handle_inheritence_ = hi;
+#else
+ ACE_UNUSED_ARG (hi);
+ ACE_NOTSUP;
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_INLINE int
+ACE_Process_Options::avoid_zombies (void)
+{
+ return avoid_zombies_;
+}
+ACE_INLINE void
+ACE_Process_Options::avoid_zombies (int avoid_zombies)
+{
+ avoid_zombies_ = avoid_zombies;
+}
+
+#if defined (ACE_WIN32)
+
+ACE_INLINE ACE_TEXT_STARTUPINFO *
+ACE_Process_Options::startup_info (void)
+{
+#if !defined (ACE_HAS_WINCE)
+ return &startup_info_;
+#else
+ return 0;
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_INLINE LPSECURITY_ATTRIBUTES
+ACE_Process_Options::get_process_attributes (void) const
+{
+#if !defined (ACE_HAS_WINCE)
+ return process_attributes_;
+#else
+ return 0;
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_INLINE LPSECURITY_ATTRIBUTES
+ACE_Process_Options::set_process_attributes (void)
+{
+#if !defined (ACE_HAS_WINCE)
+ process_attributes_ = &security_buf1_;
+ return process_attributes_;
+#else
+ return 0;
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_INLINE LPSECURITY_ATTRIBUTES
+ACE_Process_Options::get_thread_attributes (void) const
+{
+#if !defined (ACE_HAS_WINCE)
+ return thread_attributes_;
+#else
+ return 0;
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_INLINE LPSECURITY_ATTRIBUTES
+ACE_Process_Options::set_thread_attributes (void)
+{
+#if !defined (ACE_HAS_WINCE)
+ thread_attributes_ = &security_buf2_;
+ return thread_attributes_;
+#else
+ return 0;
+#endif /* !ACE_HAS_WINCE */
+}
+
+#else /* !defined (ACE_WIN32) */
+
+ACE_INLINE ACE_HANDLE
+ACE_Process_Options::get_stdin (void) const
+{
+ return stdin_;
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_Process_Options::get_stdout (void) const
+{
+ return stdout_;
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_Process_Options::get_stderr (void) const
+{
+ return stderr_;
+}
+
+ACE_INLINE bool
+ACE_Process_Options::inherit_environment (void) const
+{
+ return inherit_environment_;
+}
+
+ACE_INLINE void
+ACE_Process_Options::inherit_environment (bool nv)
+{
+ inherit_environment_ = nv;
+}
+
+ACE_INLINE int
+ACE_Process_Options::setreugid (const ACE_TCHAR* user)
+{
+#if !defined (ACE_LACKS_PWD_FUNCTIONS)
+ struct passwd *ent = ACE_OS::getpwnam (ACE_TEXT_ALWAYS_CHAR (user));
+
+ if (ent != 0)
+ {
+ this->euid_ = ent->pw_uid;
+ this->ruid_ = ent->pw_uid;
+ this->egid_ = ent->pw_gid;
+ this->rgid_ = ent->pw_gid;
+ return 0;
+ }
+ else
+ return -1;
+#else
+ ACE_UNUSED_ARG (user);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_LACKS_PWD_FUNCTIONS */
+}
+
+ACE_INLINE void
+ACE_Process_Options::setruid (uid_t id)
+{
+ this->ruid_ = id;
+}
+
+ACE_INLINE void
+ACE_Process_Options::seteuid (uid_t id)
+{
+ this->euid_ = id;
+}
+
+ACE_INLINE void
+ACE_Process_Options::setrgid (uid_t id)
+{
+ this->rgid_ = id;
+}
+
+ACE_INLINE void
+ACE_Process_Options::setegid (uid_t id)
+{
+ this->egid_ = id;
+}
+
+ACE_INLINE uid_t
+ACE_Process_Options::getruid (void) const
+{
+ return this->ruid_;
+}
+
+ACE_INLINE uid_t
+ACE_Process_Options::geteuid (void) const
+{
+ return this->euid_;
+}
+
+ACE_INLINE uid_t
+ACE_Process_Options::getrgid (void) const
+{
+ return this->rgid_;
+}
+
+ACE_INLINE uid_t
+ACE_Process_Options::getegid (void) const
+{
+ return this->egid_;
+}
+#endif /* ACE_WIN32 */
+
+ACE_INLINE ACE_TCHAR *
+ACE_Process_Options::command_line_buf (int *max_lenp)
+{
+ if (max_lenp != 0)
+ *max_lenp = this->command_line_buf_len_;
+ return this->command_line_buf_;
+}
+
+ACE_INLINE ACE_TCHAR *
+ACE_Process_Options::working_directory (void)
+{
+#if !defined (ACE_HAS_WINCE)
+ if (working_directory_[0] == '\0')
+ return 0;
+ else
+ return working_directory_;
+#else
+ return 0;
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_INLINE void
+ACE_Process_Options::working_directory (const char *wd)
+{
+#if !defined(ACE_HAS_WINCE)
+ ACE_OS::strcpy (working_directory_, ACE_TEXT_CHAR_TO_TCHAR (wd));
+#else
+ ACE_UNUSED_ARG (wd);
+#endif /* !ACE_HAS_WINCE */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE void
+ACE_Process_Options::working_directory (const wchar_t *wd)
+{
+#if !defined(ACE_HAS_WINCE)
+ ACE_OS::strcpy (working_directory_, ACE_TEXT_WCHAR_TO_TCHAR (wd));
+#else
+ ACE_UNUSED_ARG (wd);
+#endif /* !ACE_HAS_WINCE */
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_INLINE void
+ACE_Process_Options::process_name (const ACE_TCHAR *p)
+{
+ ACE_OS::strcpy (this->process_name_, p);
+}
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Process_Options::process_name (void)
+{
+ if (process_name_[0] == '\0')
+ this->process_name (this->command_line_argv ()[0]);
+
+ return this->process_name_;
+}
+
+#if defined (ACE_HAS_WINCE)
+// Here is a collection of inline functions which are defined only
+// under CE. They are not empty on most other platforms.
+
+ACE_INLINE int
+ACE_Process_Options::setenv (ACE_TCHAR * /* envp */[])
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Process_Options::setenv (const ACE_TCHAR * /* format */, ...)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Process_Options::setenv (const ACE_TCHAR * /* variable_name */,
+ const ACE_TCHAR * /* format */,
+ ...)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Process_Options::set_handles (ACE_HANDLE /* std_in */,
+ ACE_HANDLE /* std_out */,
+ ACE_HANDLE /* std_err */)
+{
+ return -1;
+}
+
+#endif /* ACE_HAS_WINCE */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Process_Manager.cpp b/ACE/ace/Process_Manager.cpp
new file mode 100644
index 00000000000..0caacba7234
--- /dev/null
+++ b/ACE/ace/Process_Manager.cpp
@@ -0,0 +1,1015 @@
+// $Id$
+
+// Process_Manager.cpp
+#include "ace/Process_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Process_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/ACE.h"
+#include "ace/Guard_T.h"
+#include "ace/Process.h"
+#include "ace/Signal.h"
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/Countdown_Time.h"
+#include "ace/OS_NS_sys_wait.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_time.h"
+
+ACE_RCSID (ace,
+ Process_Manager,
+ "$Id$")
+
+#if defined (ACE_HAS_SIG_C_FUNC)
+extern "C" void
+ACE_Process_Manager_cleanup (void *instance, void *arg)
+{
+ ACE_Process_Manager::cleanup (instance, arg);
+}
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Process_Manager::cleanup (void *, void *)
+{
+ ACE_Process_Manager::close_singleton ();
+}
+
+// This function acts as a signal handler for SIGCHLD. We don't really
+// want to do anything with the signal - it's just needed to interrupt
+// a sleep. See wait() for more info.
+#if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
+static void
+sigchld_nop (int, siginfo_t *, ucontext_t *)
+{
+ return;
+}
+#endif /* ACE_WIN32 */
+
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Process_Manager)
+
+// Singleton instance.
+ACE_Process_Manager *ACE_Process_Manager::instance_ = 0;
+
+// Controls whether the <Process_Manager> is deleted when we shut down
+// (we can only delete it safely if we created it!)
+bool ACE_Process_Manager::delete_instance_ = false;
+
+ACE_Process_Manager::Process_Descriptor::~Process_Descriptor (void)
+{
+}
+
+void
+ACE_Process_Manager::Process_Descriptor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Process_Manager::Process_Descriptor::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nproc_id_ = %d"),
+ this->process_->getpid( )));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Process_Manager::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Process_Manager::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmax_process_table_size_ = %d"), this->max_process_table_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncurrent_count_ = %d"), this->current_count_));
+
+ for (size_t i = 0; i < this->current_count_; i++)
+ this->process_table_[i].dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Process_Manager::Process_Descriptor::Process_Descriptor (void)
+ : process_ (0),
+ exit_notify_ (0)
+{
+ ACE_TRACE ("ACE_Process_Manager::Process_Descriptor::Process_Descriptor");
+}
+
+ACE_Process_Manager *
+ACE_Process_Manager::instance (void)
+{
+ ACE_TRACE ("ACE_Process_Manager::instance");
+
+ if (ACE_Process_Manager::instance_ == 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_Process_Manager::instance_ == 0)
+ {
+ ACE_NEW_RETURN (ACE_Process_Manager::instance_,
+ ACE_Process_Manager,
+ 0);
+ ACE_Process_Manager::delete_instance_ = true;
+
+ // Register with the Object_Manager so that the wrapper to
+ // delete the proactor will be called when Object_Manager is
+ // being terminated.
+
+#if defined ACE_HAS_SIG_C_FUNC
+ ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_,
+ ACE_Process_Manager_cleanup,
+ 0);
+#else
+ ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_,
+ ACE_Process_Manager::cleanup,
+ 0);
+#endif /* ACE_HAS_SIG_C_FUNC */
+
+ }
+ }
+
+ return ACE_Process_Manager::instance_;
+}
+
+ACE_Process_Manager *
+ACE_Process_Manager::instance (ACE_Process_Manager *tm)
+{
+ ACE_TRACE ("ACE_Process_Manager::instance");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ ACE_Process_Manager *t = ACE_Process_Manager::instance_;
+ // We can't safely delete it since we don't know who created it!
+ ACE_Process_Manager::delete_instance_ = false;
+
+ // Register with the Object_Manager so that the wrapper to
+ // delete the proactor will be called when Object_Manager is
+ // being terminated.
+
+#if defined ACE_HAS_SIG_C_FUNC
+ ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_,
+ ACE_Process_Manager_cleanup,
+ 0);
+#else
+ ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_,
+ ACE_Process_Manager::cleanup,
+ 0);
+#endif /* ACE_HAS_SIG_C_FUNC */
+
+ ACE_Process_Manager::instance_ = tm;
+ return t;
+}
+
+void
+ACE_Process_Manager::close_singleton( void )
+{
+ ACE_TRACE ("ACE_Process_Manager::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ if (ACE_Process_Manager::delete_instance_)
+ {
+ delete ACE_Process_Manager::instance_;
+ ACE_Process_Manager::instance_ = 0;
+ ACE_Process_Manager::delete_instance_ = false;
+ }
+}
+
+int
+ACE_Process_Manager::resize (size_t size)
+{
+ ACE_TRACE ("ACE_Process_Manager::resize");
+
+ if (size <= this->max_process_table_size_)
+ return 0;
+
+ Process_Descriptor *temp = 0;
+
+ ACE_NEW_RETURN (temp,
+ Process_Descriptor[size],
+ -1);
+
+ for (size_t i = 0;
+ i < this->current_count_;
+ i++)
+ // Structure assignment.
+ temp[i] = this->process_table_[i];
+
+ this->max_process_table_size_ = size;
+
+ delete [] this->process_table_;
+
+ this->process_table_ = temp;
+ return 0;
+}
+
+// Create and initialize the table to keep track of the process pool.
+
+int
+ACE_Process_Manager::open (size_t size, ACE_Reactor *r)
+{
+ ACE_TRACE ("ACE_Process_Manager::open");
+
+ if (r)
+ {
+ this->reactor (r);
+#if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
+ // Register signal handler object.
+ if (r->register_handler (SIGCHLD, this) == -1)
+ return -1;
+#endif /* !defined(ACE_WIN32) */
+ }
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (this->max_process_table_size_ < size)
+ this->resize (size);
+ return 0;
+}
+
+// Initialize the synchronization variables.
+
+ACE_Process_Manager::ACE_Process_Manager (size_t size,
+ ACE_Reactor *r)
+ : ACE_Event_Handler (),
+ process_table_ (0),
+ max_process_table_size_ (0),
+ current_count_ (0),
+ default_exit_handler_ (0)
+#if defined (ACE_HAS_THREADS)
+ , lock_ ()
+#endif /* ACE_HAS_THREADS */
+{
+ ACE_TRACE ("ACE_Process_Manager::ACE_Process_Manager");
+
+ if (this->open (size,
+ r) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Process_Manager")));
+}
+
+// Close up and release all resources.
+
+int
+ACE_Process_Manager::close (void)
+{
+ ACE_TRACE ("ACE_Process_Manager::close");
+
+ if (this->reactor () != 0)
+ {
+#if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
+ this->reactor ()->remove_handler (SIGCHLD, (ACE_Sig_Action *) 0);
+#endif /* !ACE_WIN32 */
+ this->reactor (0);
+ }
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (this->process_table_ != 0)
+ {
+ while (this->current_count_ > 0)
+ this->remove_proc (0);
+
+ delete [] this->process_table_;
+ this->process_table_ = 0;
+ this->max_process_table_size_ = 0;
+ this->current_count_ = 0;
+ }
+
+ if (this->default_exit_handler_ != 0)
+ this->default_exit_handler_->handle_close (ACE_INVALID_HANDLE,0);
+ this->default_exit_handler_ = 0;
+
+ return 0;
+}
+
+ACE_Process_Manager::~ACE_Process_Manager (void)
+{
+ ACE_TRACE ("ACE_Process_Manager::~ACE_Process_Manager");
+ this->close ();
+}
+
+#if !defined (ACE_WIN32)
+
+// This is called when the Reactor notices that a Process has exited.
+// What has actually happened is a SIGCHLD invoked the <handle_signal>
+// routine, which fooled the Reactor into thinking that this routine
+// needed to be called. Since we don't know which Process exited, we
+// must reap as many exit statuses as are immediately available.
+
+int
+ACE_Process_Manager::handle_input (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Process_Manager::handle_input");
+
+ pid_t pid;
+
+ do
+ pid = this->wait (0,
+ ACE_Time_Value::zero);
+ while (pid != 0 && pid != ACE_INVALID_PID);
+
+ return 0;
+}
+
+#endif /* !ACE_WIN32 */
+
+// On Unix, this routine is called asynchronously when a SIGCHLD is
+// received. We just tweak the reactor so that it'll call back our
+// <handle_input> function, which allows us to handle Process exits
+// synchronously.
+//
+// On Win32, this routine is called synchronously, and is passed the
+// HANDLE of the Process that exited, so we can do all our work here.
+
+int
+ACE_Process_Manager::handle_signal (int,
+ siginfo_t *si,
+ ucontext_t *)
+{
+#if defined (ACE_WIN32)
+ ACE_HANDLE proc = si->si_handle_;
+ ACE_exitcode status = 0;
+ BOOL result = ::GetExitCodeProcess (proc,
+ &status);
+ if (result)
+ {
+ if (status != STILL_ACTIVE)
+ {
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, lock_, -1));
+
+ ssize_t const i = this->find_proc (proc);
+ if (i == -1)
+ return -1;
+#if 0
+ pid_t pid = i != -1
+ ? process_table_[i].process_->getpid ()
+ : ACE_INVALID_PID;
+#endif
+ this->notify_proc_handler (i, status);
+ this->remove_proc (i);
+ }
+ return -1; // remove this HANDLE/Event_Handler combination
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Process still active")
+ ACE_TEXT (" -- shouldn't have been called yet!\n")),
+ 0); // return 0 : stay registered
+ }
+ else
+ {
+ // <GetExitCodeProcess> failed.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("GetExitCodeProcess failed")),
+ -1); // return -1: unregister
+ }
+#else /* !ACE_WIN32 */
+ ACE_UNUSED_ARG (si);
+ return reactor ()->notify (this, ACE_Event_Handler::READ_MASK);
+#endif /* !ACE_WIN32 */
+}
+
+int
+ACE_Process_Manager::register_handler (ACE_Event_Handler *eh,
+ pid_t pid)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (pid == ACE_INVALID_PID)
+ {
+ if (this->default_exit_handler_ != 0)
+ this->default_exit_handler_->handle_close (ACE_INVALID_HANDLE, 0);
+ this->default_exit_handler_ = eh;
+ return 0;
+ }
+
+ ssize_t const i = this->find_proc (pid);
+
+ if (i == -1)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ Process_Descriptor &proc_desc = this->process_table_[i];
+
+ if (proc_desc.exit_notify_ != 0)
+ proc_desc.exit_notify_->handle_close (ACE_INVALID_HANDLE, 0);
+ proc_desc.exit_notify_ = eh;
+ return 0;
+}
+
+// Create a new process.
+
+pid_t
+ACE_Process_Manager::spawn (ACE_Process_Options &options,
+ ACE_Event_Handler *event_handler)
+{
+ ACE_Process *process = 0;
+ ACE_NEW_RETURN (process,
+ ACE_Managed_Process,
+ ACE_INVALID_PID);
+
+ pid_t const pid = spawn (process, options, event_handler);
+ if (pid == ACE_INVALID_PID || pid == 0)
+ delete process;
+
+ return pid;
+}
+
+// Create a new process.
+
+pid_t
+ACE_Process_Manager::spawn (ACE_Process *process,
+ ACE_Process_Options &options,
+ ACE_Event_Handler *event_handler)
+{
+ ACE_TRACE ("ACE_Process_Manager::spawn");
+
+ pid_t const pid = process->spawn (options);
+
+ // Only include the pid in the parent's table.
+ if (pid == ACE_INVALID_PID || pid == 0)
+ return pid;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon, this->lock_, -1));
+
+ if (this->append_proc (process, event_handler) == -1)
+ // bad news: spawned, but not registered in table.
+ return ACE_INVALID_PID;
+
+ return pid;
+}
+
+// Create N new processs.
+
+int
+ACE_Process_Manager::spawn_n (size_t n,
+ ACE_Process_Options &options,
+ pid_t *child_pids,
+ ACE_Event_Handler *event_handler)
+{
+ ACE_TRACE ("ACE_Process_Manager::spawn_n");
+
+ if (child_pids != 0)
+ for (size_t i = 0;
+ i < n;
+ ++i)
+ child_pids[i] = ACE_INVALID_PID;
+
+ for (size_t i = 0;
+ i < n;
+ i++)
+ {
+ pid_t const pid = this->spawn (options, event_handler);
+ if (pid == ACE_INVALID_PID || pid == 0)
+ // We're in the child or something's gone wrong.
+ return pid;
+ else if (child_pids != 0)
+ child_pids[i] = pid;
+ }
+
+ return 0;
+}
+
+// Append a process into the pool (does not check for duplicates).
+// Must be called with locks held.
+
+int
+ACE_Process_Manager::append_proc (ACE_Process *proc,
+ ACE_Event_Handler *event_handler)
+{
+ ACE_TRACE ("ACE_Process_Manager::append_proc");
+
+ // Try to resize the array to twice its existing size (or the DEFAULT_SIZE,
+ // if there are no array entries) if we run out of space...
+ if (this->current_count_ >= this->max_process_table_size_)
+ {
+ size_t new_size = this->max_process_table_size_ * 2;
+ if (new_size == 0)
+ new_size = ACE_Process_Manager::DEFAULT_SIZE;
+ if (this->resize (new_size) == -1)
+ return -1;
+ }
+
+ Process_Descriptor &proc_desc =
+ this->process_table_[this->current_count_];
+
+ proc_desc.process_ = proc;
+ proc_desc.exit_notify_ = event_handler;
+
+#if defined (ACE_WIN32)
+ // If we have a Reactor, then we're supposed to reap Processes
+ // automagically. Get a handle to this new Process and tell the
+ // Reactor we're interested in <handling_input> on it.
+
+ ACE_Reactor * const r = this->reactor ();
+ if (r != 0)
+ r->register_handler (this, proc->gethandle ());
+#endif /* ACE_WIN32 */
+
+ ++this->current_count_;
+ return 0;
+}
+
+// Insert a process into the pool (checks for duplicates and doesn't
+// allow them to be inserted twice).
+
+int
+ACE_Process_Manager::insert_proc (ACE_Process *proc,
+ ACE_Event_Handler *event_handler)
+{
+ ACE_TRACE ("ACE_Process_Manager::insert_proc");
+
+ // Check for duplicates and bail out if they're already
+ // registered...
+ if (this->find_proc (proc->getpid ()) != -1)
+ return -1;
+
+ return this->append_proc (proc, event_handler);
+}
+
+// Remove a process from the pool.
+
+int
+ACE_Process_Manager::remove (pid_t pid)
+{
+ ACE_TRACE ("ACE_Process_Manager::remove");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ ssize_t const i = this->find_proc (pid);
+
+ if (i != -1)
+ return this->remove_proc (i);
+
+ // set "process not found" error
+ return -1;
+}
+
+// Remove a process from the pool. Must be called with locks held.
+
+int
+ACE_Process_Manager::remove_proc (size_t i)
+{
+ ACE_TRACE ("ACE_Process_Manager::remove_proc");
+
+ // If there's an exit_notify_ <Event_Handler> for this pid, call its
+ // <handle_close> method.
+
+ if (this->process_table_[i].exit_notify_ != 0)
+ {
+ this->process_table_[i].exit_notify_->handle_close
+ (this->process_table_[i].process_->gethandle(),
+ 0);
+ this->process_table_[i].exit_notify_ = 0;
+ }
+
+#if defined (ACE_WIN32)
+ ACE_Reactor * const r = this->reactor ();
+ if (r != 0)
+ r->remove_handler (this->process_table_[i].process_->gethandle (),
+ ACE_Event_Handler::DONT_CALL);
+#endif /* ACE_WIN32 */
+
+ this->process_table_[i].process_->unmanage ();
+
+ this->process_table_[i].process_ = 0;
+
+ this->current_count_--;
+
+ if (this->current_count_ > 0)
+ // Compact the table by moving the last item into the slot vacated
+ // by the index being removed (this is a structure assignment).
+ this->process_table_[i] =
+ this->process_table_[this->current_count_];
+
+ return 0;
+}
+
+int
+ACE_Process_Manager::terminate (pid_t pid)
+{
+ ACE_TRACE ("ACE_Process_Manager::terminate");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ // Check for duplicates and bail out if they're already
+ // registered...
+ ssize_t const i = this->find_proc (pid);
+
+ if (i == -1)
+ // set "no such process" error
+ return -1;
+
+ return ACE::terminate_process (pid);
+}
+
+int
+ACE_Process_Manager::terminate (pid_t pid, int sig)
+{
+ ACE_TRACE ("ACE_Process_Manager::terminate");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ // Check for duplicates and bail out if they're already
+ // registered...
+ ssize_t const i = this->find_proc (pid);
+
+ if (i == -1)
+ // set "no such process" error
+ return -1;
+
+ return ACE_OS::kill (pid, sig);
+}
+
+
+int
+ACE_Process_Manager::set_scheduler (const ACE_Sched_Params & params,
+ pid_t pid)
+{
+ ACE_TRACE ("ACE_Process_Manager::set_scheduler");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon, this->lock_, -1));
+
+ // Check to see if the process identified by the given pid is managed by
+ // this instance of ACE_Process_Manager.
+ ssize_t const i = this->find_proc (pid);
+
+ if (i == -1)
+ // set "no such process" error
+ return ACE_INVALID_PID;
+
+ return ACE_OS::sched_params (params, pid);
+}
+
+int
+ACE_Process_Manager::set_scheduler_all (const ACE_Sched_Params & params)
+{
+ ACE_TRACE ("ACE_Process_Manager::set_scheduler_all");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon, this->lock_, -1));
+
+ for (size_t i = 0; i < this->current_count_; ++i)
+ {
+ pid_t const pid = this->process_table_[i].process_->getpid ();
+ if (ACE_OS::sched_params (params, pid) != 0)
+ return -1;
+ }
+ return 0;
+}
+
+// Locate the index in the table associated with <pid>. Must be
+// called with the lock held.
+
+ssize_t
+ACE_Process_Manager::find_proc (pid_t pid)
+{
+ ACE_TRACE ("ACE_Process_Manager::find_proc");
+
+ for (size_t i = 0; i < this->current_count_; ++i)
+ if (pid == this->process_table_[i].process_->getpid ())
+ return i;
+
+ return -1;
+}
+
+#if defined (ACE_WIN32)
+// Locate the index in the table associated with <h>. Must be
+// called with the lock held.
+
+ssize_t
+ACE_Process_Manager::find_proc (ACE_HANDLE h)
+{
+ ACE_TRACE ("ACE_Process_Manager::find_proc");
+
+ for (size_t i = 0; i < this->current_count_; ++i)
+ if (h == this->process_table_[i].process_->gethandle ())
+ return i;
+
+ return -1;
+}
+#endif /* ACE_WIN32 */
+
+// Wait for all the Processs to exit, or until <timeout> elapses.
+// Returns the number of Processes remaining, or -1 on an error.
+
+int
+ACE_Process_Manager::wait (const ACE_Time_Value &timeout)
+{
+ ACE_TRACE ("ACE_Process_Manager::wait");
+
+ ACE_Time_Value until = timeout;
+ ACE_Time_Value remaining = timeout;
+
+ if (until < ACE_Time_Value::max_time)
+ until += ACE_OS::gettimeofday ();
+
+ while (this->current_count_ > 0)
+ {
+ pid_t const pid = this->wait (0, remaining);
+
+ if (pid == ACE_INVALID_PID) // wait() failed
+ return -1;
+ else if (pid == 0) // timeout
+ break;
+
+ remaining = until < ACE_Time_Value::max_time
+ ? until - ACE_OS::gettimeofday ()
+ : ACE_Time_Value::max_time;
+
+ if (remaining <= ACE_Time_Value::zero)
+ break;
+
+ // else Process terminated...wait for more...
+ }
+ return static_cast<int> (this->current_count_);
+}
+
+// Collect a single child process' exit status. Store the exit code
+// in *<stat_loc> if non-zero. Call the appropriate exit_notify. If
+// <pid> == 0, wait for any of the Process_Manager's children (or as
+// near as possible -- on Unix, we might accidentally get some other
+// Process_Manager's Process, or an unmanaged Process, or a child
+// process started by some other means.
+
+pid_t
+ACE_Process_Manager::wait (pid_t pid,
+ ACE_exitcode *status)
+{
+ ACE_TRACE ("ACE_Process_Manager::wait");
+
+ return this->wait (pid,
+ ACE_Time_Value::max_time,
+ status);
+}
+
+// Collect a single child processes' exit status, unless <timeout>
+// elapses before the process exits. Same caveats about accidental
+// Process reaping on Unix as above.
+
+pid_t
+ACE_Process_Manager::wait (pid_t pid,
+ const ACE_Time_Value &timeout,
+ ACE_exitcode *status)
+{
+ ACE_TRACE ("ACE_Process_Manager::wait");
+
+ ACE_exitcode local_stat = 0;
+ if (status == 0)
+ status = &local_stat;
+
+ *status = 0;
+
+ ssize_t idx = -1;
+ ACE_Process *proc = 0;
+
+ {
+ // fake context after which the lock is released
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (pid != 0)
+ {
+ idx = this->find_proc (pid);
+ if (idx == -1)
+ return ACE_INVALID_PID;
+ else
+ proc = process_table_[idx].process_;
+ }
+ // release the lock.
+ }
+ if (proc != 0)
+ pid = proc->wait (timeout, status);
+ else
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+ // Wait for any Process spawned by this Process_Manager.
+#if defined (ACE_WIN32)
+ HANDLE *handles = 0;
+
+ ACE_NEW_RETURN (handles,
+ HANDLE[this->current_count_],
+ ACE_INVALID_PID);
+
+ for (size_t i = 0;
+ i < this->current_count_;
+ ++i)
+ handles[i] =
+ process_table_[i].process_->gethandle ();
+
+ DWORD handle_count = static_cast<DWORD> (this->current_count_);
+ DWORD result = ::WaitForMultipleObjects (handle_count,
+ handles,
+ FALSE,
+ timeout == ACE_Time_Value::max_time
+ ? INFINITE
+ : timeout.msec ());
+ if (result == WAIT_FAILED)
+ pid = ACE_INVALID_PID;
+ else if (result == WAIT_TIMEOUT)
+ pid = 0;
+ else
+ {
+ // Green Hills produces a warning that result >=
+ // WAIT_OBJECT_0 is a pointless comparison because
+ // WAIT_OBJECT_0 is zero and DWORD is unsigned long, so this
+ // test is skipped for Green Hills. Same for mingw.
+# if defined (ghs) || defined (__MINGW32__) || (defined (_MSC_VER) && _MSC_VER >= 1300)
+ ACE_ASSERT (result < WAIT_OBJECT_0 + this->current_count_);
+# else
+ ACE_ASSERT (result >= WAIT_OBJECT_0
+ && result < WAIT_OBJECT_0 + this->current_count_);
+# endif
+
+ idx = this->find_proc (handles[result - WAIT_OBJECT_0]);
+
+ if (idx != -1)
+ {
+ pid = process_table_[idx].process_->getpid ();
+ result = ::GetExitCodeProcess (handles[result - WAIT_OBJECT_0],
+ status);
+ if (result == 0)
+ {
+ // <GetExitCodeProcess> failed!
+ this->remove_proc (idx);
+ pid = ACE_INVALID_PID;
+ }
+ }
+ else
+ {
+ // uh oh...handle removed from process_table_, even though
+ // we're holding a lock!
+ delete [] handles;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Process removed")
+ ACE_TEXT (" -- somebody's ignoring the lock!\n")),
+ -1);
+ }
+ }
+
+ delete [] handles;
+#else /* !defined(ACE_WIN32) */
+ if (timeout == ACE_Time_Value::max_time)
+ pid = ACE_OS::waitpid (-1, status, 0);
+ else if (timeout == ACE_Time_Value::zero)
+ pid = ACE_OS::waitpid (-1, status, WNOHANG);
+ else
+ {
+# if defined (ACE_LACKS_UNIX_SIGNALS)
+ pid = 0;
+ ACE_Time_Value sleeptm (1); // 1 msec
+ if (sleeptm > timeout) // if sleeptime > waittime
+ sleeptm = timeout;
+ ACE_Time_Value tmo (timeout); // Need one we can change
+ for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
+ {
+ pid = ACE_OS::waitpid (-1, status, WNOHANG);
+ if (pid > 0 || pid == ACE_INVALID_PID)
+ break; // Got a child or an error - all done
+
+ // pid 0, nothing is ready yet, so wait.
+ // Do a (very) short sleep (only this thread sleeps).
+ ACE_OS::sleep (sleeptm);
+ }
+# else
+ // Force generation of SIGCHLD, even though we don't want to
+ // catch it - just need it to interrupt the sleep below.
+ // If this object has a reactor set, assume it was given at
+ // open(), and there's already a SIGCHLD action set, so no
+ // action is needed here.
+ ACE_Sig_Action old_action;
+ if (this->reactor () == 0)
+ {
+ ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
+ do_sigchld.register_action (SIGCHLD, &old_action);
+ }
+
+ ACE_Time_Value tmo (timeout); // Need one we can change
+ for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
+ {
+ pid = ACE_OS::waitpid (-1, status, WNOHANG);
+# if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)
+ if (pid > 0 || (pid == ACE_INVALID_PID && errno != EINTR))
+# else
+ if (pid > 0 || pid == ACE_INVALID_PID)
+# endif
+ break; // Got a child or an error - all done
+
+ // pid 0, nothing is ready yet, so wait.
+ // Do a sleep (only this thread sleeps) til something
+ // happens. This relies on SIGCHLD interrupting the sleep.
+ // If SIGCHLD isn't delivered, we'll need to do something
+ // with sigaction to force it.
+ if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
+ continue;
+ // Timed out
+ pid = 0;
+ break;
+ }
+
+ // Restore the previous SIGCHLD action if it was changed.
+ if (this->reactor () == 0)
+ old_action.register_action (SIGCHLD);
+# endif /* !ACE_LACKS_UNIX_SIGNALS */
+ }
+#endif /* !defined (ACE_WIN32) */
+ }
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+ if (pid != ACE_INVALID_PID && pid != 0)
+ {
+ //we always need to get our id, because we could have been moved in the table meanwhile
+ idx = this->find_proc (pid);
+ if (idx == -1)
+ {
+ // oops, reaped an unmanaged process!
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) oops, reaped unmanaged %d\n"),
+ pid));
+ return pid;
+ }
+ else
+ proc = process_table_[idx].process_;
+ if (proc != 0)
+ ACE_ASSERT (pid == proc->getpid ());
+
+ this->notify_proc_handler (idx,
+ *status);
+ this->remove (pid);
+ }
+
+ return pid;
+}
+
+// Legacy method:
+
+int
+ACE_Process_Manager::reap (pid_t pid,
+ ACE_exitcode *stat_loc,
+ int options)
+{
+ ACE_TRACE ("ACE_Process_Manager::reap");
+
+ return this->wait (pid,
+ (ACE_BIT_ENABLED (options, WNOHANG)
+ ? ACE_Time_Value::zero
+ : ACE_Time_Value::max_time),
+ stat_loc);
+}
+
+// Notify either the process-specific handler or the generic handler.
+// If process-specific, call handle_close on the handler. Returns 1
+// if process found, 0 if not. Must be called with locks held.
+
+int
+ACE_Process_Manager::notify_proc_handler (size_t i,
+ ACE_exitcode exit_code)
+{
+ if (i < this->current_count_)
+ {
+ Process_Descriptor &proc_desc =
+ this->process_table_[i];
+
+ proc_desc.process_->exit_code (exit_code);
+
+ if (proc_desc.exit_notify_ != 0)
+ proc_desc.exit_notify_->handle_exit (proc_desc.process_);
+ else if (this->default_exit_handler_ != 0
+ && this->default_exit_handler_->handle_exit (proc_desc.process_) < 0)
+ {
+ this->default_exit_handler_->handle_close
+ (ACE_INVALID_HANDLE,
+ 0);
+ this->default_exit_handler_ = 0;
+ }
+ return 1;
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P:%t|%T) ACE_Process_Manager::notify_proc_handler:")
+ ACE_TEXT (" unknown/unmanaged process reaped\n")));
+ return 0;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Process_Manager.h b/ACE/ace/Process_Manager.h
new file mode 100644
index 00000000000..cd9e2009eca
--- /dev/null
+++ b/ACE/ace/Process_Manager.h
@@ -0,0 +1,478 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Process_Manager.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_PROCESS_MANAGER_H
+#define ACE_PROCESS_MANAGER_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Process.h"
+#include "ace/Event_Handler.h"
+#include "ace/Time_Value.h"
+
+#if defined (ACE_HAS_THREADS)
+# include "ace/Recursive_Thread_Mutex.h"
+#endif /* ACE_HAS_THREADS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Reactor;
+
+/**
+ * @class ACE_Process_Manager
+ *
+ * @brief Manages a group of processes.
+ *
+ * This class allows applications to control groups of processes,
+ * similar to how the ACE_Thread_Manager controls groups of
+ * threads. Naturally, it doesn't work at all on platforms, such
+ * as VxWorks or pSoS, that don't support process.
+ * There are two main ways of using ACE_Process_Manager,
+ * depending on how involved you wish to be with the termination
+ * of managed processes. If you want processes to simply
+ * go away when they're finished, register the ACE_Process_Manager with
+ * an ACE_Reactor that can handle notifications of child process exit:
+ * @code
+ * ACE_Process_Manager mgr;
+ * // ...
+ * mgr.open (100, ACE_Reactor::instance ());
+ * @endcode
+ * In this usage scenario, the ACE_Process_Manager will clean up after any
+ * processes that it spawns. (On Unix, this means executing a
+ * wait(2) to collect the exit status and avoid zombie
+ * processes; on Win32, it means closing the process and thread
+ * HANDLEs that are created when CreateProcess is called.)
+ *
+ * @note When you register a ACE_Process_Manager with a
+ * ACE_Reactor, the reactor's notification pipe is used to help reap the
+ * available process exit statuses. Therefore, you must not use a
+ * reactor whose notify pipe has been disabled. Here's the
+ * sequence of steps used to reap the exit statuses in this case:
+ * -# The ACE_Process_Manager registers a signal handler for
+ * SIGCHLD.
+ * -# The SIGCHLD handler, when invoked, uses the ACE_Reactor's
+ * notify() method to inform the ACE_Reactor to wake up.
+ * -# The ACE_Reactor calls the ACE_Process_Manager's
+ * handle_input() method; this happens synchronously, not in
+ * signal context.
+ * -# The handle_input() method collects all available exit
+ * statuses.
+ *
+ * If, on the other hand you want to wait "in line" to handle the
+ * terminated process cleanup code, call one of the wait functions
+ * whenever there might be managed processes that have exited.
+ *
+ * Note that in either case, ACE_Process_Manager allows you to
+ * register an ACE_Event_Handler to be called when a specific
+ * spawned process exits, or when any process without a specific
+ * ACE_Event_Handler exits. When a process exits, the
+ * appropriate ACE_Event_Handler's handle_input() method is called; the
+ * ACE_HANDLE passed is either the process's HANDLE (on Win32),
+ * or its pid cast to an ACE_HANDLE (on POSIX).
+ * It is also possible to call the wait() functions even when the
+ * ACE_Process_Manager is registered with a reactor.
+ *
+ * @note Be aware that the wait functions are "sloppy" on Unix,
+ * because there's no good way to wait for a subset of the
+ * children of a process. The wait functions may end up
+ * collecting the exit status of a process that's not managed by
+ * the ACE_Process_Manager whose wait() you invoked. It's best to
+ * only use a single ACE_Process_Manager, and to create all
+ * subprocesses by calling that manager's spawn() method.
+ */
+class ACE_Export ACE_Process_Manager : protected ACE_Event_Handler
+{
+public:
+ friend class ACE_Process_Control;
+
+ enum
+ {
+ DEFAULT_SIZE = 100
+ };
+
+ /**
+ * @name Initialization and termination methods
+ */
+ //@{
+ /**
+ * Initialize an ACE_Process_Manager with a table containing up to
+ * @a size processes. This table resizes itself automatically as
+ * needed. If a @a reactor is provided, this
+ * ACE_Process_Manager uses it to notify an application when a
+ * process it controls exits. By default, however, we don't use an
+ * ACE_Reactor.
+ */
+ ACE_Process_Manager (size_t size = ACE_Process_Manager::DEFAULT_SIZE,
+ ACE_Reactor *reactor = 0);
+
+ /**
+ * Initialize an ACE_Process_Manager with a table containing up to
+ * @a size processes. This table resizes itself automatically as
+ * needed. If a @a reactor is provided, this
+ * ACE_Process_Manager uses it to notify an application when a
+ * process it controls exits. By default, however, we don't use an
+ * ACE_Reactor.
+ */
+ int open (size_t size = ACE_Process_Manager::DEFAULT_SIZE,
+ ACE_Reactor *r = 0);
+
+ /// Release all resources. Do not wait for processes to exit.
+ int close (void);
+
+ /// Destructor releases all resources and does not wait for processes
+ /// to exit.
+ virtual ~ACE_Process_Manager (void);
+
+ //@}
+
+ /**
+ * @name Singleton access and control
+ */
+ //@{
+ /// Get pointer to a process-wide ACE_Process_Manager.
+ static ACE_Process_Manager *instance (void);
+
+ /// Set pointer to a process-wide ACE_Process_Manager and return
+ /// existing pointer.
+ static ACE_Process_Manager *instance (ACE_Process_Manager *);
+
+ /// 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);
+
+ //@}
+
+ /**
+ * @name Process creation methods
+ */
+ //@{
+ /**
+ * Create a new process with specified @a options.
+ * Register @a event_handler to be called back when the process exits.
+ *
+ * On success, returns the process id of the child that was created.
+ * On failure, returns ACE_INVALID_PID.
+ */
+ pid_t spawn (ACE_Process *proc,
+ ACE_Process_Options &options,
+ ACE_Event_Handler *event_handler = 0);
+
+ /**
+ * Create a new process with the specified @a options.
+ * Register @a event_handler to be called back when the process exits.
+ *
+ * On success, returns the process id of the child that was created.
+ * On failure, returns ACE_INVALID_PID.
+ */
+ pid_t spawn (ACE_Process_Options &options,
+ ACE_Event_Handler *event_handler = 0);
+
+ /**
+ * Create @a n new processes with the same @a options.
+ * If @a child_pids is non-0 it is expected to be an array of at least
+ * @a n pid_t, which are filled in with the process IDs of the spawned
+ * processes.
+ * Register @a event_handler to be called back when each process exits.
+ * Returns 0 on success and -1 on failure.
+ */
+ int spawn_n (size_t n,
+ ACE_Process_Options &options,
+ pid_t *child_pids = 0,
+ ACE_Event_Handler *event_Handler = 0);
+ //@}
+
+ /**
+ * @name Process synchronization operations
+ */
+ //@{
+ /**
+ * Abruptly terminate a single process with id @a pid using the
+ * ACE::terminate_process() method which works on both signal-capable
+ * systems and on Windows.
+ *
+ * @note This call is potentially dangerous to use since the process
+ * being terminated may not have a chance to cleanup before it shuts down.
+ *
+ * @retval 0 on success and -1 on failure.
+ */
+ int terminate (pid_t pid);
+
+ /**
+ * Sends the specified signal to the specified process.
+ *
+ * @note This only works on platforms that have signal capability. In
+ * particular, it doesn't work on Windows.
+ *
+ * @retval 0 on success and -1 on failure.
+ */
+ int terminate (pid_t pid, int sig);
+
+ /**
+ * Block until there are no more child processes running that were
+ * spawned by this ACE_Process_Manager. Unlike the wait() method
+ * below, this method does not require a signal handler or use of
+ * ACE_OS::sigwait() because it simply blocks synchronously waiting
+ * for all the children managed by this ACE_Process_Manager to
+ * exit. Note that this does not return any status information
+ * about the success or failure of exiting child processes, although
+ * any registered exit handlers are called.
+ *
+ * @param timeout Relative time to wait for processes to terminate.
+ *
+ * @retval 0 on success; -1 on failure.
+ */
+ int wait (const ACE_Time_Value &timeout = ACE_Time_Value::max_time);
+
+ /**
+ * Wait up to @a timeout for a single specified process to terminate.
+ * If @a pid is 0, this method waits for any of the managed processes
+ * (but see the note concerning "sloppy process cleanup on unix").
+ * If @a pid != 0, waits for that process only.
+ *
+ * @param pid Process ID
+ * @param timeout Relative time to wait for process to terminate
+ * @param status Exit status of terminated process
+ *
+ * @retval The pid of the process which exited, 0
+ * if a timeout occurred, or ACE_INVALID_PID on error.
+ */
+ pid_t wait (pid_t pid,
+ const ACE_Time_Value &timeout,
+ ACE_exitcode *status = 0);
+
+ /**
+ * Wait indefinitely for a single, specified process to terminate.
+ * If @a pid is 0, waits for any of the managed processes (but see the
+ * note concerning "sloppy process cleanup on unix").
+ * If @a pid != 0, this method waits for that process only.
+ *
+ * @retval The pid of the process which exited, or
+ * ACE_INVALID_PID on error.
+ */
+ pid_t wait (pid_t pid,
+ ACE_exitcode *status = 0);
+
+ /**
+ * @deprecated
+ * Reap the result of a single process by calling ACE_OS::waitpid(),
+ * therefore, this method is not portable to Windows. If the child is
+ * successfully reaped, remove() is called automatically.
+ * Use one of the wait() methods instead of this method.
+ */
+ int reap (pid_t pid = -1,
+ ACE_exitcode *stat_loc = 0,
+ int options = WNOHANG);
+ //@}
+
+ /**
+ * @name Utility methods
+ */
+ //@{
+ /**
+ * Register an event handler to be called back when the specified
+ * process exits. If @a pid == ACE_INVALID_PID this handler is called
+ * when any process with no specific handler exits.
+ *
+ * @warning In multithreaded applications, there is a race condition
+ * if a process exits between the time it is spawned and when its
+ * handler is registered. To avoid this, register the handler at
+ * the time the process is spawned.
+ */
+ int register_handler (ACE_Event_Handler *event_handler,
+ pid_t pid = ACE_INVALID_PID);
+
+ /**
+ * Remove process @a pid from the ACE_Process_Manager's internal records.
+ * This is called automatically by the reap() method after it successfully
+ * reaps a process. It's also possible to call this method
+ * directly from a signal handler, but don't call both reap() and
+ * remove()!
+ */
+ int remove (pid_t pid);
+
+ /// Return the number of managed processes.
+ size_t managed (void) const;
+
+ /**
+ * Sets the scheduling parameters for process identified by @a pid by
+ * passing @a params, @a pid to ACE_OS::sched_params().
+ *
+ * @retval 0 on success, -1 on failure, and ACE_INVALID_PID when the
+ * specified @a pid is not managed by this ACE_Process_Manager.
+ */
+ int set_scheduler (const ACE_Sched_Params &params,
+ pid_t pid);
+
+ /**
+ * Sets the scheduling parameters for all the processes managed by
+ * this ACE_Process_Manager by passing @a params to
+ * ACE_OS::sched_params().
+ *
+ * @retval 0 on success, -1 on failure.
+ */
+ int set_scheduler_all (const ACE_Sched_Params &);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+ //@}
+
+protected:
+ // = These methods allow a <Process_Manager> to be an <Event_Handler>.
+
+ // As an <Event_Handler>, the <Process_Manager> automagically
+ // detects child Processes exiting and calls notify_proc_handler()
+ // and remove(). This means that you don't have to (shouldn't!)
+ // call the wait(...) methods yourself.
+
+ // On Unix, we can't detect individual process termination very
+ // well; the best method is to catch SIGCHLD and then call the
+ // polling wait() function to collect any available exit statuses.
+ // However, we don't want to do this from within a signal handler
+ // because of the restrictions associated. Therefore (following the
+ // lead in examples/mumble) we open a bogus handle (to ACE_DEV_NULL)
+ // and register that handle with our Reactor. Then, when our
+ // SIGCHLD handler gets invoked, we tell the Reactor that the bogus
+ // handle is readable. That will cause the handle_input() function
+ // to be called once we're out of the interrupt context, and
+ // handle_input() collects exit statuses.
+
+ // On Win32, we simply register ourself with the Reactor to deal
+ // with the Process handle becoming signaled. No muss, no fuss, no
+ // signal handler, and no dummy handle.
+
+#if !defined(ACE_WIN32)
+ /// Collect one (or more, on unix) process exit status.
+ virtual int handle_input (ACE_HANDLE proc);
+#endif // !defined(ACE_WIN32)
+
+ /**
+ * On Unix, this routine is called asynchronously when a SIGCHLD is
+ * received. We just tweak the reactor so that it'll call back our
+ * <handle_input> function, which allows us to handle Process exits
+ * synchronously.
+ *
+ * On Win32, this routine is called synchronously, and is passed the
+ * HANDLE of the Process that exited, so we can do all our work here
+ */
+ virtual int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0);
+
+private:
+
+ /**
+ * @struct Process_Descriptor
+ *
+ * @internal This struct is for internal use only by ACE_Process_Manager.
+ *
+ * @brief Information describing each process that's controlled by an
+ * ACE_Process_Manager.
+ */
+ struct Process_Descriptor
+ {
+ /// Default ctor/dtor.
+ Process_Descriptor (void);
+ ~Process_Descriptor (void);
+
+ /// Describes the process itself.
+ ACE_Process *process_;
+
+ /// function to call when process exits
+ ACE_Event_Handler *exit_notify_;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+ };
+
+ /// Resize the pool of Process_Descriptors.
+ int resize (size_t);
+
+ /// Locate the index of the table slot occupied by @a process_id.
+ /// Returns -1 if @a process_id is not in the <process_table_>
+ ssize_t find_proc (pid_t process_id);
+
+#if defined (ACE_WIN32)
+ /// Locate the index of the table slot occupied by @a process_handle.
+ /// Returns ~0 if @a process_handle is not in the <process_table_>
+ ssize_t find_proc (ACE_HANDLE process_handle);
+#endif /* ACE_WIN32 */
+
+ /// Insert a process in the table (checks for duplicates). Omitting
+ /// the process handle won't work on Win32...
+ /// Register @a event_handler to be called back when the process exits.
+ int insert_proc (ACE_Process *process,
+ ACE_Event_Handler *event_handler = 0);
+
+ /**
+ * Append information about a process, i.e., its <process_id> in the
+ * <process_table_>. Each entry is added at the end, growing the
+ * table if necessary.
+ * Register @a event_handler to be called back when the process exits.
+ */
+ int append_proc (ACE_Process *process,
+ ACE_Event_Handler *event_handler = 0);
+
+ /// Actually removes the process at index @a n from the table. This method
+ /// must be called with locks held.
+ int remove_proc (size_t n);
+
+ /// If there's a specific handler for the Process at index @a n in the
+ /// table, or there's a default handler, call it.
+ int notify_proc_handler (size_t n, ACE_exitcode status);
+
+ /// Vector that describes process state within the Process_Manager.
+ Process_Descriptor *process_table_;
+
+ /// Maximum number of processes we can manage (should be dynamically
+ /// allocated).
+ size_t max_process_table_size_;
+
+ /// Current number of processes we are managing.
+ size_t current_count_;
+
+ /// This event handler is used to notify when a process we control
+ /// exits.
+ ACE_Event_Handler *default_exit_handler_;
+
+ /// Singleton pointer.
+ static ACE_Process_Manager *instance_;
+
+ /// Controls whether the <Process_Manager> is deleted when we shut
+ /// down (we can only delete it safely if we created it!)
+ static bool delete_instance_;
+
+#if defined (ACE_HAS_THREADS)
+ /// This lock protects access/ops on <process_table_>.
+ ACE_Recursive_Thread_Mutex lock_;
+#endif /* ACE_HAS_THREADS */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Process_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_PROCESS_MANAGER_H */
diff --git a/ACE/ace/Process_Manager.inl b/ACE/ace/Process_Manager.inl
new file mode 100644
index 00000000000..248acd4c8e0
--- /dev/null
+++ b/ACE/ace/Process_Manager.inl
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE size_t
+ACE_Process_Manager::managed (void) const
+{
+ return current_count_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Process_Mutex.cpp b/ACE/ace/Process_Mutex.cpp
new file mode 100644
index 00000000000..9aba33a7894
--- /dev/null
+++ b/ACE/ace/Process_Mutex.cpp
@@ -0,0 +1,90 @@
+// $Id$
+
+#include "ace/Process_Mutex.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/Guard_T.h"
+#include "ace/Process_Mutex.h"
+#include "ace/Malloc_T.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Process_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Process_Mutex, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Process_Mutex)
+
+void
+ACE_Process_Mutex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Process_Mutex::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+const ACE_TCHAR *
+ACE_Process_Mutex::unique_name (void)
+{
+ // For all platforms other than Win32, we are going to create a
+ // machine-wide unique name if one is not provided by the user. On
+ // Win32, unnamed synchronization objects are acceptable.
+ ACE::unique_name (this, this->name_, ACE_UNIQUE_NAME_LEN);
+ return this->name_;
+}
+
+ACE_Process_Mutex::ACE_Process_Mutex (const char *name, void *arg, mode_t mode)
+#if defined (_ACE_USE_SV_SEM)
+ : lock_ (name ? name : ACE_TEXT_ALWAYS_CHAR (this->unique_name ()),
+ ACE_SV_Semaphore_Complex::ACE_CREATE,
+ 1,
+ 1,
+ mode)
+#else
+ : lock_ (USYNC_PROCESS,
+ name ?
+ ACE_TEXT_CHAR_TO_TCHAR (name) : this->unique_name (),
+ (ACE_mutexattr_t *) arg,
+ mode)
+#endif /* _ACE_USE_SV_SEM */
+{
+#if defined (_ACE_USE_SV_SEM)
+ ACE_UNUSED_ARG (arg);
+#endif /* !_ACE_USE_SV_SEM */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_Process_Mutex::ACE_Process_Mutex (const wchar_t *name,
+ void *arg,
+ mode_t mode)
+#if defined (_ACE_USE_SV_SEM)
+ : lock_ (name ?
+ ACE_Wide_To_Ascii (name).char_rep () :
+ ACE_TEXT_ALWAYS_CHAR (this->unique_name ()),
+ ACE_SV_Semaphore_Complex::ACE_CREATE,
+ 1,
+ 1,
+ mode)
+#else
+ : lock_ (USYNC_PROCESS,
+ name ?
+ ACE_TEXT_WCHAR_TO_TCHAR (name) : this->unique_name (),
+ (ACE_mutexattr_t *) arg,
+ mode)
+#endif /* _ACE_USE_SV_SEM */
+{
+#if defined (_ACE_USE_SV_SEM)
+ ACE_UNUSED_ARG (arg);
+#endif /* _ACE_USE_SV_SEM */
+}
+#endif /* ACE_HAS_WCHAR */
+ACE_Process_Mutex::~ACE_Process_Mutex (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Process_Mutex.h b/ACE/ace/Process_Mutex.h
new file mode 100644
index 00000000000..c2fb3c702da
--- /dev/null
+++ b/ACE/ace/Process_Mutex.h
@@ -0,0 +1,216 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Process_Mutex.h
+ *
+ * $Id$
+ *
+ * A wrapper for mutexes that can be used across processes on the
+ * same host machine, as well as within a process, of course.
+ *
+ * @author Douglas C. Schmidt <schmidt@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_PROCESS_MUTEX_H
+#define ACE_PROCESS_MUTEX_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// To make it easier to carry the setting though this file as well as
+// Process_Mutex.{cpp inl}, set a private macro here.
+#ifdef _ACE_USE_SV_SEM
+# undef _ACE_USE_SV_SEM
+#endif /* _ACE_USE_SV_SEM */
+
+#if defined (ACE_HAS_SYSV_IPC) && !defined (ACE_USES_MUTEX_FOR_PROCESS_MUTEX)
+# include "ace/SV_Semaphore_Complex.h"
+# define _ACE_USE_SV_SEM
+#else
+# include "ace/Mutex.h"
+#endif /* ACE_HAS_SYSV_IPC && !ACE_USES_MUTEX_FOR_PROCESS_MUTEX */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Process_Mutex
+ *
+ * @brief A wrapper for mutexes that can be used across processes on
+ * the same host machine, as well as within a process, of
+ * course.
+ *
+ * @attention The mechanism upon which @c ACE_Process_Mutex is based
+ * can be configured at build time to be either @c ACE_SV_Semaphore_Complex
+ * (on platforms that support it) or @c ACE_Mutex. On platforms that
+ * require interprocess mutexes be allocated from shared memory (Pthreads
+ * and UI Threads are examples), @c ACE_SV_Semaphore_Complex provides a
+ * more reliable mechanism for implementing inter-process mutex than
+ * @c ACE_Mutex. However, at least on some platforms,
+ * @c ACE_SV_Semaphore_Complex is limited to a small number of
+ * objects by the underlying System V IPC kernel parameters. If you
+ * want to force use of @c ACE_Mutex as the underlying mechanism, set
+ * @c ACE_USES_MUTEX_FOR_PROCESS_MUTEX in your @c config.h file.
+ * Also, if you require the ability to do a timed @c acquire(), you must
+ * set @c ACE_USES_MUTEX_FOR_PROCESS_MUTEX, as timed acquire does not
+ * work with System V semaphores.
+ * @attention Currently there is also the operational difference between
+ * pthreads and semaphores based @c. For semaphore base @c the semaphore
+ * is destroyed after the last instance of @c in OS. In contrary, pthread based
+ * @c is destroyed when the owner, namely the process which created the
+ * first instance of @c destroys the mutex. For protable applications it is better
+ * to always ensure that the owner of the mutex destroys it after the
+ * other processes.
+ */
+class ACE_Export ACE_Process_Mutex
+{
+public:
+ /**
+ * Create a Process_Mutex, passing in the optional @c name.
+ *
+ * @param name optional, null-terminated string containing the name of
+ * the object. Multiple users of the same @c ACE_Process_Mutex must use
+ * the same name to access the same object. If not specified, a name
+ * is generated.
+ * @param arg optional, attributes to be used to initialize the mutex.
+ * If using @c ACE_SV_Semaphore_Complex as the underlying mechanism,
+ * this argument is ignored.
+ * @param mode optional, the protection mode for either the backing store
+ * file (for ACE_Mutex use) or the ACE_SV_Semaphore_Complex that's created.
+ */
+ ACE_Process_Mutex (const char *name = 0,
+ void *arg = 0,
+ mode_t mode = ACE_DEFAULT_FILE_PERMS);
+
+#if defined (ACE_HAS_WCHAR)
+ /**
+ * Create a Process_Mutex, passing in the optional @c name. (@c wchar_t
+ * version)
+ *
+ * @param name optional, null-terminated string containing the name of
+ * the object. Multiple users of the same @c ACE_Process_Mutex must use
+ * the same name to access the same object. If not specified, a name
+ * is generated.
+ * @param arg optional, attributes to be used to initialize the mutex.
+ * If using @c ACE_SV_Semaphore_Complex as the underlying mechanism,
+ * this argument is ignored.
+ * @param mode optional, the protection mode for either the backing store
+ * file (for ACE_Mutex use) or the ACE_SV_Semaphore_Complex that's created.
+ */
+ ACE_Process_Mutex (const wchar_t *name,
+ void *arg = 0,
+ mode_t mode = ACE_DEFAULT_FILE_PERMS);
+#endif /* ACE_HAS_WCHAR */
+
+ ~ACE_Process_Mutex (void);
+
+ /**
+ * Explicitly destroy the mutex. Note that only one thread should
+ * call this method since it doesn't protect against race
+ * conditions.
+ *
+ * @return 0 on success; -1 on failure.
+ */
+ int remove (void);
+
+ /**
+ * Acquire lock ownership (wait on queue if necessary).
+ *
+ * @return 0 on success; -1 on failure.
+ */
+ int acquire (void);
+
+ /**
+ * Acquire lock ownership, but timeout if lock if hasn't been
+ * acquired by given time.
+ *
+ * @param tv the absolute time until which the caller is willing to
+ * wait to acquire the lock.
+ *
+ * @return 0 on success; -1 on failure.
+ */
+ int acquire (ACE_Time_Value &tv);
+
+ /**
+ * Conditionally acquire lock (i.e., don't wait on queue).
+ *
+ * @return 0 on success; -1 on failure. If the lock could not be acquired
+ * because someone else already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire (void);
+
+ /// Release lock and unblock a thread at head of queue.
+ int release (void);
+
+ /// Acquire lock ownership (wait on queue if necessary).
+ int acquire_read (void);
+
+ /// Acquire lock ownership (wait on queue if necessary).
+ int acquire_write (void);
+
+ /**
+ * Conditionally acquire a lock (i.e., won't block). Returns -1 on
+ * failure. If we "failed" because someone else already had the
+ * lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_read (void);
+
+ /**
+ * Conditionally acquire a lock (i.e., won't block). Returns -1 on
+ * failure. If we "failed" because someone else already had the
+ * lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_write (void);
+
+ /**
+ * This is only here for consistency with the other synchronization
+ * APIs and usability with Lock adapters. Assumes the caller already has
+ * acquired the mutex and returns 0 in all cases.
+ */
+ int tryacquire_write_upgrade (void);
+
+#if !defined (_ACE_USE_SV_SEM)
+ /// Return the underlying mutex.
+ const ACE_mutex_t &lock (void) const;
+#endif /* !_ACE_USE_SV_SEM */
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// If the user does not provide a name we generate a unique name in
+ /// this buffer.
+ ACE_TCHAR name_[ACE_UNIQUE_NAME_LEN];
+
+ /// Create and return the unique name.
+ const ACE_TCHAR *unique_name (void);
+
+#if defined (_ACE_USE_SV_SEM)
+ /// We need this to get the right semantics...
+ ACE_SV_Semaphore_Complex lock_;
+#else
+ ACE_Mutex lock_;
+#endif /* _ACE_USE_SV_SEM */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Process_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_PROCESS_MUTEX_H */
diff --git a/ACE/ace/Process_Mutex.inl b/ACE/ace/Process_Mutex.inl
new file mode 100644
index 00000000000..6c19e8d6757
--- /dev/null
+++ b/ACE/ace/Process_Mutex.inl
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if !defined (_ACE_USE_SV_SEM)
+ACE_INLINE const ACE_mutex_t &
+ACE_Process_Mutex::lock (void) const
+{
+// ACE_TRACE ("ACE_Process_Mutex::lock");
+ return this->lock_.lock ();
+}
+#endif /* !_ACE_USE_SV_SEM */
+
+// Explicitly destroy the mutex.
+ACE_INLINE int
+ACE_Process_Mutex::remove (void)
+{
+ return this->lock_.remove ();
+}
+
+// Acquire lock ownership (wait on priority queue if necessary).
+ACE_INLINE int
+ACE_Process_Mutex::acquire (void)
+{
+#if defined (_ACE_USE_SV_SEM)
+ return this->lock_.acquire (0, SEM_UNDO);
+#else
+ return this->lock_.acquire ();
+#endif // _ACE_USE_SV_SEM
+}
+
+// Acquire lock ownership (wait on priority queue if necessary).
+ACE_INLINE int
+ACE_Process_Mutex::acquire (ACE_Time_Value &tv)
+{
+#if !defined (_ACE_USE_SV_SEM)
+ return this->lock_.acquire (tv);
+#else
+ ACE_UNUSED_ARG (tv);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* !_ACE_USE_SV_SEM */
+}
+
+// Conditionally acquire lock (i.e., don't wait on queue).
+ACE_INLINE int
+ACE_Process_Mutex::tryacquire (void)
+{
+#if defined (_ACE_USE_SV_SEM)
+ return this->lock_.tryacquire (0, SEM_UNDO);
+#else
+ return this->lock_.tryacquire ();
+#endif // _ACE_USE_SV_SEM
+}
+
+// Release lock and unblock a thread at head of priority queue.
+ACE_INLINE int
+ACE_Process_Mutex::release (void)
+{
+#if defined (_ACE_USE_SV_SEM)
+ return this->lock_.release (0, SEM_UNDO);
+#else
+ return this->lock_.release ();
+#endif // _ACE_USE_SV_SEM
+}
+
+// Acquire lock ownership (wait on priority queue if necessary).
+ACE_INLINE int
+ACE_Process_Mutex::acquire_read (void)
+{
+#if defined (_ACE_USE_SV_SEM)
+ return this->lock_.acquire_read (0, SEM_UNDO);
+#else
+ return this->lock_.acquire_read ();
+#endif // _ACE_USE_SV_SEM
+}
+
+// Acquire lock ownership (wait on priority queue if necessary).
+ACE_INLINE int
+ACE_Process_Mutex::acquire_write (void)
+{
+#if defined (_ACE_USE_SV_SEM)
+ return this->lock_.acquire_write (0, SEM_UNDO);
+#else
+ return this->lock_.acquire_write ();
+#endif // _ACE_USE_SV_SEM
+}
+
+// Conditionally acquire a lock (i.e., won't block).
+ACE_INLINE int
+ACE_Process_Mutex::tryacquire_read (void)
+{
+#if defined (_ACE_USE_SV_SEM)
+ return this->lock_.tryacquire_read (0, SEM_UNDO);
+#else
+ return this->lock_.tryacquire_read ();
+#endif // _ACE_USE_SV_SEM
+}
+
+// Conditionally acquire a lock (i.e., won't block).
+ACE_INLINE int
+ACE_Process_Mutex::tryacquire_write (void)
+{
+#if defined (_ACE_USE_SV_SEM)
+ return this->lock_.tryacquire_write (0, SEM_UNDO);
+#else
+ return this->lock_.tryacquire_write ();
+#endif // _ACE_USE_SV_SEM
+}
+
+ACE_INLINE int
+ACE_Process_Mutex::tryacquire_write_upgrade (void)
+{
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Process_Semaphore.cpp b/ACE/ace/Process_Semaphore.cpp
new file mode 100644
index 00000000000..860eda3b016
--- /dev/null
+++ b/ACE/ace/Process_Semaphore.cpp
@@ -0,0 +1,111 @@
+// $Id$
+
+#include "ace/Process_Semaphore.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_Memory.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Process_Semaphore.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/ACE.h"
+
+ACE_RCSID(ace, Process_Semaphore, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Process_Semaphore::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Process_Semaphore::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Process_Semaphore::ACE_Process_Semaphore (u_int count,
+ const ACE_TCHAR *name,
+ void *arg,
+ int max)
+#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM)
+ : lock_ (count, USYNC_PROCESS, name, arg, max)
+#else
+ : lock_ (ACE_TEXT_ALWAYS_CHAR (name),
+ ACE_SV_Semaphore_Complex::ACE_CREATE,
+ count)
+#endif /* ACE_WIN32 || ACE_HAS_POSIX_SEM */
+{
+ ACE_UNUSED_ARG (arg);
+ ACE_UNUSED_ARG (max);
+// ACE_TRACE ("ACE_Process_Semaphore::ACE_Process_Semaphore");
+}
+
+// Explicitly destroy the semaphore.
+
+int
+ACE_Process_Semaphore::remove (void)
+{
+// ACE_TRACE ("ACE_Process_Semaphore::remove");
+ return this->lock_.remove ();
+}
+
+// Block the thread until the semaphore count becomes
+// greater than 0, then decrement it.
+
+int
+ACE_Process_Semaphore::acquire (void)
+{
+// ACE_TRACE ("ACE_Process_Semaphore::acquire");
+#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM)
+ return this->lock_.acquire ();
+#else
+ return this->lock_.acquire (0, SEM_UNDO);
+#endif /* defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM) */
+}
+
+// Conditionally decrement the semaphore if count is greater
+// than 0 (i.e., won't block).
+
+int
+ACE_Process_Semaphore::tryacquire (void)
+{
+// ACE_TRACE ("ACE_Process_Semaphore::tryacquire");
+#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM)
+ return this->lock_.tryacquire ();
+#else
+ return this->lock_.tryacquire (0, SEM_UNDO);
+#endif /* defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM) */
+}
+
+// Increment the semaphore, potentially unblocking
+// a waiting thread.
+
+int
+ACE_Process_Semaphore::release (void)
+{
+// ACE_TRACE ("ACE_Process_Semaphore::release");
+#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM)
+ return this->lock_.release ();
+#else
+ return this->lock_.release (0, SEM_UNDO);
+#endif /* defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM) */
+}
+
+/*****************************************************************************/
+
+ACE_Process_Semaphore *
+ACE_Malloc_Lock_Adapter_T<ACE_Process_Semaphore>::operator () (const ACE_TCHAR *name)
+{
+ ACE_Process_Semaphore *p = 0;
+ if (name == 0)
+ ACE_NEW_RETURN (p, ACE_Process_Semaphore (1, name), 0);
+ else
+ ACE_NEW_RETURN (p, ACE_Process_Semaphore (1, ACE::basename (name,
+ ACE_DIRECTORY_SEPARATOR_CHAR)),
+ 0);
+ return p;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Process_Semaphore.h b/ACE/ace/Process_Semaphore.h
new file mode 100644
index 00000000000..61665207d82
--- /dev/null
+++ b/ACE/ace/Process_Semaphore.h
@@ -0,0 +1,161 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Process_Semaphore.h
+ *
+ * $Id$
+ *
+ * Wrapper for Dijkstra style general semaphores that work
+ * across processes.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_PROCESS_SEMAPHORE_H
+#define ACE_PROCESS_SEMAPHORE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !(defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM))
+# include "ace/SV_Semaphore_Complex.h"
+#else
+# include "ace/Semaphore.h"
+#endif /* !(ACE_WIN32 || ACE_HAS_POSIX_SEM) */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Process_Semaphore
+ *
+ * @brief Wrapper for Dijkstra style general semaphores that work
+ * across processes.
+ */
+class ACE_Export ACE_Process_Semaphore
+{
+public:
+ /// Initialize the semaphore, with an initial value of @a count and a
+ /// maximum value of @a max.
+ ACE_Process_Semaphore (u_int count = 1, // By default make this unlocked.
+ const ACE_TCHAR *name = 0,
+ void * = 0,
+ int max = 0x7FFFFFFF);
+
+ /**
+ * Explicitly destroy the semaphore. Note that only one thread
+ * should call this method since it doesn't protect against race
+ * conditions.
+ */
+ int remove (void);
+
+ /// Block the thread until the semaphore count becomes greater than
+ /// 0, then decrement it.
+ int acquire (void);
+
+ /**
+ * Conditionally decrement the semaphore if count is greater than 0
+ * (i.e., won't block). Returns -1 on failure. If we "failed"
+ * because someone else already had the lock, @c errno is set to
+ * @c EBUSY.
+ */
+ int tryacquire (void);
+
+ /// Increment the semaphore, potentially unblocking a waiting thread.
+ int release (void);
+
+ /**
+ * Acquire semaphore ownership. This calls <acquire> and is only
+ * here to make the ACE_Process_Semaphore interface consistent
+ * with the other synchronization APIs.
+ */
+ int acquire_read (void);
+
+ /**
+ * Acquire semaphore ownership. This calls <acquire> and is only
+ * here to make the ACE_Process_Semaphore interface consistent
+ * with the other synchronization APIs.
+ */
+ int acquire_write (void);
+
+ /**
+ * Conditionally acquire semaphore (i.e., won't block). This calls
+ * <tryacquire> and is only here to make the ACE_Process_Semaphore
+ * interface consistent with the other synchronization APIs.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_read (void);
+
+ /**
+ * Conditionally acquire semaphore (i.e., won't block). This calls
+ * <tryacquire> and is only here to make the ACE_Process_Semaphore
+ * interface consistent with the other synchronization APIs.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_write (void);
+
+ /**
+ * This is only here to make the ACE_Process_Semaphore
+ * interface consistent with the other synchronization APIs.
+ * Assumes the caller has already acquired the semaphore using one of
+ * the above calls, and returns 0 (success) always.
+ */
+ int tryacquire_write_upgrade (void);
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM)
+ /// Return the underlying lock.
+ const ACE_sema_t &lock (void) const;
+#endif /* ACE_WIN32 || ACE_HAS_POSIX_SEM */
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM)
+ ACE_Semaphore lock_;
+#else
+ /// We need this to get the right semantics...
+ ACE_SV_Semaphore_Complex lock_;
+#endif /* ACE_WIN32 || ACE_HAS_POSIX_SEM */
+};
+
+/*****************************************************************************/
+
+template <class T> class ACE_Malloc_Lock_Adapter_T;
+
+/**
+ * @class ACE_Malloc_Lock_Adapter_T<ACE_Process_Semaphore>
+ *
+ * @brief Template specialization of ACE_Malloc_Lock_Adapter_T for
+ * ACE_Process_Semaphore.
+ *
+ * This is needed since the ctor for ACE_Process_Semaphore doesn't match
+ * the standard form used by other lock strategy classes.
+ */
+template<>
+class ACE_Export ACE_Malloc_Lock_Adapter_T<ACE_Process_Semaphore>
+{
+public:
+ ACE_Process_Semaphore * operator () (const ACE_TCHAR *name);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#if defined (__ACE_INLINE__)
+#include "ace/Process_Semaphore.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_PROCESS_SEMAPHORE_H */
diff --git a/ACE/ace/Process_Semaphore.inl b/ACE/ace/Process_Semaphore.inl
new file mode 100644
index 00000000000..e51d0890665
--- /dev/null
+++ b/ACE/ace/Process_Semaphore.inl
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM)
+ACE_INLINE const ACE_sema_t &
+ACE_Process_Semaphore::lock (void) const
+{
+// ACE_TRACE ("ACE_Process_Semaphore::lock");
+ return this->lock_.lock ();
+}
+#endif /* ACE_WIN32 || ACE_HAS_POSIX_SEM */
+
+// Acquire semaphore ownership. This calls <acquire> and is only here
+// to make the ACE_Process_Semaphore interface consistent with the
+// other synchronization APIs.
+
+ACE_INLINE int
+ACE_Process_Semaphore::acquire_read (void)
+{
+ return this->acquire ();
+}
+
+// Acquire semaphore ownership. This calls <acquire> and is only here
+// to make the ACE_Process_Semaphore interface consistent with the
+// other synchronization APIs.
+
+ACE_INLINE int
+ACE_Process_Semaphore::acquire_write (void)
+{
+ return this->acquire ();
+}
+
+// Conditionally acquire semaphore (i.e., won't block). This calls
+// <tryacquire> and is only here to make the ACE_Process_Semaphore
+// interface consistent with the other synchronization APIs.
+
+ACE_INLINE int
+ACE_Process_Semaphore::tryacquire_read (void)
+{
+ return this->tryacquire ();
+}
+
+// Conditionally acquire semaphore (i.e., won't block). This calls
+// <tryacquire> and is only here to make the ACE_Process_Semaphore
+// interface consistent with the other synchronization APIs.
+
+ACE_INLINE int
+ACE_Process_Semaphore::tryacquire_write (void)
+{
+ return this->tryacquire ();
+}
+
+// This is only here to make the ACE_Process_Semaphore
+// interface consistent with the other synchronization APIs.
+// Assumes the caller has already acquired the semaphore using one of
+// the above calls, and returns 0 (success) always.
+ACE_INLINE int
+ACE_Process_Semaphore::tryacquire_write_upgrade (void)
+{
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Profile_Timer.cpp b/ACE/ace/Profile_Timer.cpp
new file mode 100644
index 00000000000..03d1d1c46ce
--- /dev/null
+++ b/ACE/ace/Profile_Timer.cpp
@@ -0,0 +1,438 @@
+// $Id$
+
+#include "ace/Profile_Timer.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Profile_Timer.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(ace, Profile_Timer, "$Id$")
+
+#if (defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)) && !defined (ACE_WIN32)
+
+#include "ace/OS_NS_stdio.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Profile_Timer)
+
+
+void
+ACE_Profile_Timer::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Profile_Timer::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+// Initialize interval timer.
+
+ACE_Profile_Timer::ACE_Profile_Timer (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::ACE_Profile_Timer");
+ ACE_OS::memset (&this->end_usage_, 0, sizeof this->end_usage_);
+ ACE_OS::memset (&this->begin_usage_, 0, sizeof this->begin_usage_);
+ ACE_OS::memset (&this->last_usage_, 0, sizeof this->last_usage_);
+
+# if defined (ACE_HAS_PRUSAGE_T)
+ ACE_OS::memset (&this->last_usage_, 0, sizeof this->last_usage_);
+ char buf[20];
+ ACE_OS::sprintf (buf, "/proc/%d", static_cast<int> (ACE_OS::getpid ()));
+
+ this->proc_handle_ = ACE_OS::open (buf, O_RDONLY, 0);
+ if (this->proc_handle_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ buf));
+# elif defined (ACE_HAS_GETRUSAGE)
+ ACE_OS::memset (&this->begin_time_, 0, sizeof this->begin_time_);
+ ACE_OS::memset (&this->end_time_, 0, sizeof this->end_time_);
+ ACE_OS::memset (&this->last_time_, 0, sizeof this->last_time_);
+# endif /* ACE_HAS_PRUSAGE_T */
+}
+
+// Terminate the interval timer.
+ACE_Profile_Timer::~ACE_Profile_Timer (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::~ACE_Profile_Timer");
+# if defined (ACE_HAS_PRUSAGE_T)
+ if (ACE_OS::close (this->proc_handle_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Profile_Timer::~ACE_Profile_Timer")));
+# endif /* ACE_HAS_PRUSAGE_T */
+}
+
+// Return the resource utilization.
+
+void
+ACE_Profile_Timer::get_rusage (ACE_Profile_Timer::Rusage &usage)
+{
+ ACE_TRACE ("ACE_Profile_Timer::get_rusage");
+ usage = this->end_usage_;
+}
+
+# if defined (ACE_HAS_PRUSAGE_T)
+
+// Compute the amount of resource utilization since the start time.
+
+void
+ACE_Profile_Timer::elapsed_rusage (ACE_Profile_Timer::Rusage &rusage)
+{
+ ACE_TRACE ("ACE_Profile_Timer::elapsed_rusage");
+ rusage.pr_lwpid =
+ this->end_usage_.pr_lwpid - this->last_usage_.pr_lwpid;
+ rusage.pr_count =
+ this->end_usage_.pr_count - this->last_usage_.pr_count;
+ rusage.pr_minf =
+ this->end_usage_.pr_minf - this->last_usage_.pr_minf;
+ rusage.pr_majf =
+ this->end_usage_.pr_majf - this->last_usage_.pr_majf;
+ rusage.pr_inblk =
+ this->end_usage_.pr_inblk - this->last_usage_.pr_inblk;
+ rusage.pr_oublk =
+ this->end_usage_.pr_oublk - this->last_usage_.pr_oublk;
+ rusage.pr_msnd =
+ this->end_usage_.pr_msnd - this->last_usage_.pr_msnd;
+ rusage.pr_mrcv =
+ this->end_usage_.pr_mrcv - this->last_usage_.pr_mrcv;
+ rusage.pr_sigs =
+ this->end_usage_.pr_sigs - this->last_usage_.pr_sigs;
+ this->subtract (rusage.pr_wtime,
+ this->end_usage_.pr_wtime,
+ this->last_usage_.pr_wtime);
+ this->subtract (rusage.pr_ltime,
+ this->end_usage_.pr_ltime,
+ this->last_usage_.pr_ltime);
+ this->subtract (rusage.pr_slptime,
+ this->end_usage_.pr_slptime,
+ this->last_usage_.pr_slptime);
+ rusage.pr_vctx =
+ this->end_usage_.pr_vctx - this->last_usage_.pr_vctx;
+ rusage.pr_ictx =
+ this->end_usage_.pr_ictx - this->last_usage_.pr_ictx;
+ rusage.pr_sysc =
+ this->end_usage_.pr_sysc - this->last_usage_.pr_sysc;
+ rusage.pr_ioch =
+ this->end_usage_.pr_ioch - this->last_usage_.pr_ioch;
+}
+
+// Compute the elapsed time.
+
+void
+ACE_Profile_Timer::compute_times (ACE_Elapsed_Time &et)
+{
+ ACE_TRACE ("ACE_Profile_Timer::compute_times");
+ timespec_t td;
+
+ ACE_Profile_Timer::Rusage &end = this->end_usage_;
+ ACE_Profile_Timer::Rusage &begin = this->begin_usage_;
+
+ this->subtract (td, end.pr_tstamp, begin.pr_tstamp);
+ // Convert nanoseconds into seconds.
+ et.real_time = td.tv_sec + ((double) td.tv_nsec) / ACE_ONE_SECOND_IN_NSECS;
+ this->subtract (td, end.pr_utime, begin.pr_utime);
+ // Convert nanoseconds into seconds.
+ et.user_time = td.tv_sec + ((double) td.tv_nsec) / ACE_ONE_SECOND_IN_NSECS;
+ this->subtract (td, end.pr_stime, begin.pr_stime);
+ // Convert nanoseconds into seconds.
+ et.system_time = td.tv_sec + ((double) td.tv_nsec) / ACE_ONE_SECOND_IN_NSECS;
+}
+
+// Determine the difference between T1 and T2.
+
+void
+ACE_Profile_Timer::subtract (timespec_t &tdiff, timespec_t &t1, timespec_t &t0)
+{
+ ACE_TRACE ("ACE_Profile_Timer::subtract");
+ tdiff.tv_sec = t1.tv_sec - t0.tv_sec;
+ tdiff.tv_nsec = t1.tv_nsec - t0.tv_nsec;
+
+ // Normalize the time.
+
+ while (tdiff.tv_nsec < 0)
+ {
+ tdiff.tv_sec--;
+ tdiff.tv_nsec += ACE_ONE_SECOND_IN_NSECS;
+ }
+}
+
+# elif defined (ACE_HAS_GETRUSAGE)
+// Compute the amount of resource utilization since the start time.
+
+void
+ACE_Profile_Timer::elapsed_rusage (ACE_Profile_Timer::Rusage &usage)
+{
+ ACE_TRACE ("ACE_Profile_Timer::elapsed_rusage");
+# if !defined (ACE_HAS_LIMITED_RUSAGE_T)
+ // integral shared memory size
+ usage.ru_ixrss =
+ this->end_usage_.ru_ixrss - this->last_usage_.ru_ixrss;
+ // integral unshared data "
+ usage.ru_idrss =
+ this->end_usage_.ru_idrss - this->last_usage_.ru_idrss;
+ // integral unshared stack "
+ usage.ru_isrss =
+ this->end_usage_.ru_isrss - this->last_usage_.ru_isrss;
+ // page reclaims - total vmfaults
+ usage.ru_minflt =
+ this->end_usage_.ru_minflt - this->last_usage_.ru_minflt;
+ // page faults
+ usage.ru_majflt =
+ this->end_usage_.ru_majflt - this->last_usage_.ru_majflt;
+ // swaps
+ usage.ru_nswap =
+ this->end_usage_.ru_nswap - this->last_usage_.ru_nswap;
+ // block input operations
+ usage.ru_inblock =
+ this->end_usage_.ru_inblock - this->last_usage_.ru_inblock;
+ // block output operations
+ usage.ru_oublock =
+ this->end_usage_.ru_oublock - this->last_usage_.ru_oublock;
+ // messages sent
+ usage.ru_msgsnd =
+ this->end_usage_.ru_msgsnd - this->last_usage_.ru_msgsnd;
+ // messages received
+ usage.ru_msgrcv =
+ this->end_usage_.ru_msgrcv - this->last_usage_.ru_msgrcv;
+ // signals received
+ usage.ru_nsignals =
+ this->end_usage_.ru_nsignals - this->last_usage_.ru_nsignals;
+ // voluntary context switches
+ usage.ru_nvcsw =
+ this->end_usage_.ru_nvcsw - this->last_usage_.ru_nvcsw;
+ // involuntary context switches
+ usage.ru_nivcsw =
+ this->end_usage_.ru_nivcsw - this->last_usage_.ru_nivcsw;
+ this->subtract (usage.ru_utime,
+ this->end_usage_.ru_utime,
+ this->last_usage_.ru_utime);
+ this->subtract (usage.ru_stime,
+ this->end_usage_.ru_stime,
+ this->last_usage_.ru_stime);
+# else
+ ACE_UNUSED_ARG(usage);
+# endif /* ACE_HAS_LIMITED_RUSAGE_T */
+}
+
+void
+ACE_Profile_Timer::compute_times (ACE_Elapsed_Time &et)
+{
+ ACE_TRACE ("ACE_Profile_Timer::compute_times");
+
+ timeval td;
+
+ this->subtract (td, this->end_time_, this->begin_time_);
+ et.real_time = td.tv_sec + ((double) td.tv_usec) / ACE_ONE_SECOND_IN_USECS;
+
+ this->subtract (td, this->end_usage_.ru_utime, this->begin_usage_.ru_utime);
+ et.user_time = td.tv_sec + ((double) td.tv_usec) / ACE_ONE_SECOND_IN_USECS;
+
+ this->subtract (td, this->end_usage_.ru_stime, this->begin_usage_.ru_stime);
+ et.system_time = td.tv_sec + ((double) td.tv_usec) / ACE_ONE_SECOND_IN_USECS;
+}
+
+// Determine the difference between T1 and T2.
+
+void
+ACE_Profile_Timer::subtract (timeval &tdiff, timeval &t1, timeval &t0)
+{
+ ACE_TRACE ("ACE_Profile_Timer::subtract");
+ tdiff.tv_sec = t1.tv_sec - t0.tv_sec;
+ tdiff.tv_usec = t1.tv_usec - t0.tv_usec;
+
+ // Normalize the time.
+
+ while (tdiff.tv_usec < 0)
+ {
+ tdiff.tv_sec--;
+ tdiff.tv_usec += ACE_ONE_SECOND_IN_USECS;
+ }
+}
+
+# endif /* ACE_HAS_PRUSAGE_T */
+
+// Compute the amount of time that has elapsed between start and stop.
+
+int
+ACE_Profile_Timer::elapsed_time (ACE_Elapsed_Time &et)
+{
+ ACE_TRACE ("ACE_Profile_Timer::elapsed_time");
+ this->compute_times (et);
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#elif defined (ACE_WIN32) /* defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE) */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Profile_Timer::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Profile_Timer::dump");
+ timer_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+// Initialize interval timer.
+ACE_Profile_Timer::ACE_Profile_Timer (void)
+ : timer_ ()
+{
+ ACE_TRACE ("ACE_Profile_Timer::ACE_Profile_Timer");
+# if defined (ACE_HAS_GETRUSAGE)
+
+ ACE_OS::memset (&this->end_usage_, 0, sizeof this->end_usage_);
+ ACE_OS::memset (&this->begin_usage_, 0, sizeof this->begin_usage_);
+ ACE_OS::memset (&this->last_usage_, 0, sizeof this->last_usage_);
+
+ ACE_OS::memset (&this->begin_time_, 0, sizeof this->begin_time_);
+ ACE_OS::memset (&this->end_time_, 0, sizeof this->end_time_);
+ ACE_OS::memset (&this->last_time_, 0, sizeof this->last_time_);
+# endif /* ACE_HAS_GETRUSAGE */
+}
+
+int
+ACE_Profile_Timer::elapsed_time (ACE_Elapsed_Time &et)
+{
+ ACE_TRACE ("ACE_Profile_Timer::elapsed_time");
+
+ ACE_hrtime_t delta_t; // nanoseconds
+ timer_.elapsed_time (delta_t);
+# if defined (ACE_LACKS_LONGLONG_T)
+ et.real_time = delta_t / (double) ACE_ONE_SECOND_IN_NSECS;
+# else
+ et.real_time = (__int64) delta_t / (double) ACE_ONE_SECOND_IN_NSECS;
+# endif /* ACE_LACKS_LONGLONG_T */
+# if defined (ACE_HAS_GETRUSAGE)
+ ACE_Time_Value atv = ACE_Time_Value (this->end_usage_.ru_utime)
+ - ACE_Time_Value (this->begin_usage_.ru_utime);
+ et.user_time = atv.sec () + ((double) atv.usec ()) / ACE_ONE_SECOND_IN_USECS;
+
+ atv = ACE_Time_Value (this->end_usage_.ru_stime)
+ - ACE_Time_Value (this->begin_usage_.ru_stime);
+ et.system_time = atv.sec () + ((double) atv.usec ()) / ACE_ONE_SECOND_IN_USECS;
+# else /* ACE_HAS_GETRUSAGE */
+ et.user_time = 0;
+ et.system_time = 0;
+# endif /* ACE_HAS_GETRUSAGE */
+
+ return 0;
+}
+
+// Return the resource utilization.
+
+void
+ACE_Profile_Timer::get_rusage (ACE_Profile_Timer::Rusage &usage)
+{
+ ACE_TRACE ("ACE_Profile_Timer::get_rusage");
+# if defined (ACE_HAS_GETRUSAGE)
+ usage = this->end_usage_;
+# else /* ACE_HAS_GETRUSAGE */
+ usage = 0;
+# endif /* ACE_HAS_GETRUSAGE */
+}
+
+// Compute the amount of resource utilization since the start time.
+
+void
+ACE_Profile_Timer::elapsed_rusage (ACE_Profile_Timer::Rusage &usage)
+{
+ ACE_TRACE ("ACE_Profile_Timer::elapsed_rusage");
+
+# if defined (ACE_HAS_GETRUSAGE)
+ // Use ACE_Time_Value's as intermediate because the type of ru_utime can
+ // be multiple types and using the - operator is not safe when this are
+ // 64bit FILETIMEs on Windows
+ ACE_Time_Value end_ru_utime (this->end_usage_.ru_utime);
+ ACE_Time_Value begin_ru_utime (this->begin_usage_.ru_utime);
+ usage.ru_utime = end_ru_utime - begin_ru_utime;
+
+ ACE_Time_Value end_ru_stime (this->end_usage_.ru_stime);
+ ACE_Time_Value begin_ru_stime (this->begin_usage_.ru_stime);
+ usage.ru_stime = end_ru_stime - begin_ru_stime;
+# else /* ACE_HAS_GETRUSAGE */
+ usage = 0;
+# endif /* ACE_HAS_GETRUSAGE */
+}
+
+# if defined (ACE_HAS_GETRUSAGE)
+// Determine the difference between T1 and T2.
+
+void
+ACE_Profile_Timer::subtract (timeval &tdiff, timeval &t1, timeval &t0)
+{
+ ACE_TRACE ("ACE_Profile_Timer::subtract");
+ tdiff.tv_sec = t1.tv_sec - t0.tv_sec;
+ tdiff.tv_usec = t1.tv_usec - t0.tv_usec;
+
+ // Normalize the time.
+
+ while (tdiff.tv_usec < 0)
+ {
+ tdiff.tv_sec--;
+ tdiff.tv_usec += ACE_ONE_SECOND_IN_USECS;
+ }
+}
+# endif /* ACE_HAS_GETRUSAGE */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#else
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Profile_Timer::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Profile_Timer::dump");
+ timer_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Profile_Timer::ACE_Profile_Timer (void)
+ : timer_ ()
+{
+ ACE_TRACE ("ACE_Profile_Timer::ACE_Profile_Timer");
+}
+
+int
+ACE_Profile_Timer::elapsed_time (ACE_Elapsed_Time &et)
+{
+ ACE_TRACE ("ACE_Profile_Timer::elapsed_time");
+
+ ACE_hrtime_t delta_t; /* nanoseconds */
+ timer_.elapsed_time (delta_t);
+
+ et.real_time = delta_t / (double) ACE_ONE_SECOND_IN_NSECS;
+
+ et.user_time = 0;
+ et.system_time = 0;
+
+ return 0;
+}
+
+void
+ACE_Profile_Timer::get_rusage (ACE_Profile_Timer::Rusage &usage)
+{
+ ACE_TRACE ("ACE_Profile_Timer::get_rusage");
+ usage = 0;
+}
+
+
+void
+ACE_Profile_Timer::elapsed_rusage (ACE_Profile_Timer::Rusage &usage)
+{
+ ACE_TRACE ("ACE_Profile_Timer::elapsed_rusage");
+ usage = 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* defined (ACE_HAS_PRUSAGE_T) ||
+ defined (ACE_HAS_GETRUSAGE) && !defined (ACE_WIN32) */
diff --git a/ACE/ace/Profile_Timer.h b/ACE/ace/Profile_Timer.h
new file mode 100644
index 00000000000..1dd699a1b6a
--- /dev/null
+++ b/ACE/ace/Profile_Timer.h
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Profile_Timer.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+
+#ifndef ACE_PROFILE_TIMER_H
+#define ACE_PROFILE_TIMER_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/High_Res_Timer.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Profile_Timer
+ *
+ * @brief This class provides both a timing mechanism and a mechanism
+ * for reporting the resource usage of a process.
+ */
+class ACE_Export ACE_Profile_Timer
+{
+public:
+
+ /**
+ * @class ACE_Elapsed_Time
+ *
+ * @brief Keeps track of the various user, system, and elapsed (real)
+ * times.
+ */
+ class ACE_Elapsed_Time
+ {
+ public:
+ /// Elapsed wall clock time.
+ ACE_timer_t real_time;
+
+ /// CPU time spent in user space.
+ ACE_timer_t user_time;
+
+ /// CPU time spent in system space.
+ ACE_timer_t system_time;
+ };
+
+ typedef ACE_Rusage Rusage;
+
+ // = Initialization and termination methods.
+ /// Default constructor. Clears all time values to 0.
+ ACE_Profile_Timer (void);
+
+ /// Shutdown the timer.
+ ~ACE_Profile_Timer (void);
+
+ // = Timer methods.
+ /// Activate the timer.
+ int start (void);
+
+ /// Stop the timer.
+ int stop (void);
+
+ // = Resource utilization methods.
+ /// Compute the time elapsed between calls to @c start() and @c stop().
+ int elapsed_time (ACE_Elapsed_Time &et);
+
+ /// Compute the amount of resource utilization between calls to @c start()
+ /// and @c stop().
+ void elapsed_rusage (ACE_Profile_Timer::Rusage &rusage);
+
+ /// Return the resource utilization (don't recompute it).
+ void get_rusage (ACE_Profile_Timer::Rusage &rusage);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Compute how much time has elapsed.
+ void compute_times (ACE_Elapsed_Time &et);
+
+ /// Keep track of the starting resource utilization.
+ ACE_Profile_Timer::Rusage begin_usage_;
+
+ /// Keep track of the ending resource utilization.
+ ACE_Profile_Timer::Rusage end_usage_;
+
+ /// Keep track of the last rusage for incremental timing.
+ ACE_Profile_Timer::Rusage last_usage_;
+
+#if defined (ACE_HAS_PRUSAGE_T)
+ /// Substract two timestructs and store their difference.
+ void subtract (timespec_t &tdiff, timespec_t &t0, timespec_t &t1);
+
+ /// I/O handle for /proc file system.
+ ACE_HANDLE proc_handle_;
+
+#elif defined (ACE_HAS_GETRUSAGE)
+ /// Substract two timestructs and store their difference.
+ void subtract (timeval &tdiff,
+ timeval &t0,
+ timeval &t1);
+
+ /// Keep track of the beginning time.
+ timeval begin_time_;
+
+ /// Keep track of the ending time.
+ timeval end_time_;
+
+ /// Keep track of the last time for incremental timing.
+ timeval last_time_;
+#endif /* ACE_HAS_PRUSAGE_T */
+
+#if defined (ACE_WIN32) || (!defined (ACE_HAS_PRUSAGE_T) && !defined (ACE_HAS_GETRUSAGE))
+ /// The high resolution timer
+ ACE_High_Res_Timer timer_;
+#endif /* ACE_WIN32 || !ACE_HAS_PRUSAGE_T && !ACE_HAS_GETRUSAGE */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Profile_Timer.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_PROFILE_TIMER_H */
diff --git a/ACE/ace/Profile_Timer.inl b/ACE/ace/Profile_Timer.inl
new file mode 100644
index 00000000000..6ef5aa45af3
--- /dev/null
+++ b/ACE/ace/Profile_Timer.inl
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_sys_resource.h"
+#include "ace/Global_Macros.h"
+
+#if (defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)) && !defined (ACE_WIN32)
+
+# if defined (ACE_HAS_PRUSAGE_T)
+# include "ace/OS_NS_stropts.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Profile_Timer::start (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::start");
+ return ACE_OS::ioctl (this->proc_handle_,
+ PIOCUSAGE,
+ &this->begin_usage_);
+}
+
+ACE_INLINE int
+ACE_Profile_Timer::stop (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::stop");
+ this->last_usage_ = this->end_usage_;
+ return ACE_OS::ioctl (this->proc_handle_,
+ PIOCUSAGE,
+ &this->end_usage_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# elif defined (ACE_HAS_GETRUSAGE)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Profile_Timer::start (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::start");
+ this->begin_time_ = ACE_OS::gettimeofday ();
+ ACE_OS::getrusage (RUSAGE_SELF,
+ &this->begin_usage_);
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Profile_Timer::stop (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::stop");
+ this->last_time_ = this->end_time_;
+ this->end_time_ = ACE_OS::gettimeofday ();
+ this->last_usage_ = this->end_usage_;
+ ACE_OS::getrusage (RUSAGE_SELF,
+ &this->end_usage_);
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# endif /* ACE_HAS_PRUSAGE_T */
+
+#elif defined (ACE_WIN32)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Profile_Timer::~ACE_Profile_Timer (void)
+{
+}
+
+ACE_INLINE int
+ACE_Profile_Timer::start (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::start");
+# if defined (ACE_HAS_GETRUSAGE)
+ ACE_OS::getrusage (RUSAGE_SELF,
+ &this->begin_usage_);
+# endif /* ACE_HAS_GETRUSAGE */
+ this->timer_.start ();
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Profile_Timer::stop (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::stop");
+ this->timer_.stop ();
+# if defined (ACE_HAS_GETRUSAGE)
+ this->last_usage_ = this->end_usage_;
+ ACE_OS::getrusage (RUSAGE_SELF, &this->end_usage_);
+# endif /* ACE_HAS_GETRUSAGE */
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#else
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Profile_Timer::start (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::start");
+ this->timer_.start ();
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Profile_Timer::stop (void)
+{
+ ACE_TRACE ("ACE_Profile_Timer::stop");
+ this->timer_.stop ();
+ return 0;
+}
+
+ACE_INLINE
+ACE_Profile_Timer::~ACE_Profile_Timer (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE) */
diff --git a/ACE/ace/QoS/ACE_QoS.pc.in b/ACE/ace/QoS/ACE_QoS.pc.in
new file mode 100644
index 00000000000..ba6fda765b9
--- /dev/null
+++ b/ACE/ace/QoS/ACE_QoS.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE_QOS
+Description: ACE Quality of Service Library
+Requires: ACE
+Version: @VERSION@
+Libs: -L${libdir} -lACE_QoS
+Cflags: -I${includedir}
diff --git a/ACE/ace/QoS/ACE_QoS_Export.h b/ACE/ace/QoS/ACE_QoS_Export.h
new file mode 100644
index 00000000000..ec47ab46c9c
--- /dev/null
+++ b/ACE/ace/QoS/ACE_QoS_Export.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by
+// generate_export_file.pl
+// ------------------------------
+#if !defined (ACE_QOS_EXPORT_H)
+#define ACE_QOS_EXPORT_H
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS)
+# if !defined (ACE_QoS_HAS_DLL)
+# define ACE_QoS_HAS_DLL 0
+# endif /* ! ACE_QoS_HAS_DLL */
+#else
+# if !defined (ACE_QoS_HAS_DLL)
+# define ACE_QoS_HAS_DLL 1
+# endif /* ! ACE_QoS_HAS_DLL */
+#endif /* ACE_AS_STATIC_LIB */
+
+#if defined (ACE_QoS_HAS_DLL)
+# if (ACE_QoS_HAS_DLL == 1)
+# if defined (ACE_QoS_BUILD_DLL)
+# define ACE_QoS_Export ACE_Proper_Export_Flag
+# define ACE_QoS_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define ACE_QoS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else
+# define ACE_QoS_Export ACE_Proper_Import_Flag
+# define ACE_QoS_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define ACE_QoS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ACE_QoS_BUILD_DLL */
+# else
+# define ACE_QoS_Export
+# define ACE_QoS_SINGLETON_DECLARATION(T)
+# define ACE_QoS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ! ACE_QoS_HAS_DLL == 1 */
+#else
+# define ACE_QoS_Export
+# define ACE_QoS_SINGLETON_DECLARATION(T)
+# define ACE_QoS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* ACE_QoS_HAS_DLL */
+
+#endif /* ACE_QOS_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/QoS/Makefile.am b/ACE/ace/QoS/Makefile.am
new file mode 100644
index 00000000000..c48750d77a7
--- /dev/null
+++ b/ACE/ace/QoS/Makefile.am
@@ -0,0 +1,74 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+includedir = @includedir@/ace/QoS
+pkgconfigdir = @libdir@/pkgconfig
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.QoS.am
+
+if BUILD_QOS
+
+lib_LTLIBRARIES = libACE_QoS.la
+
+libACE_QoS_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_QoS_BUILD_DLL
+
+libACE_QoS_la_SOURCES = \
+ QoS_Decorator.cpp \
+ QoS_Manager.cpp \
+ QoS_Session_Factory.cpp \
+ QoS_Session_Impl.cpp \
+ SOCK_Dgram_Mcast_QoS.cpp
+
+libACE_QoS_la_LDFLAGS = \
+ -release @ACE_VERSION_NAME@
+
+libACE_QoS_la_LIBADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+nobase_include_HEADERS = \
+ ACE_QoS_Export.h \
+ QoS_Decorator.h \
+ QoS_Manager.h \
+ QoS_Session.h \
+ QoS_Session_Factory.h \
+ QoS_Session_Impl.h \
+ QoS_Session_Impl.inl \
+ SOCK_Dgram_Mcast_QoS.h \
+ SOCK_Dgram_Mcast_QoS.inl
+
+pkgconfig_DATA = \
+ ACE_QoS.pc
+
+CLEANFILES = \
+ ACE_QoS.pc
+
+ACE_QoS.pc: ${top_builddir}/config.status ${srcdir}/ACE_QoS.pc.in
+ ${top_builddir}/config.status --file $@:${srcdir}/ACE_QoS.pc.in
+
+endif BUILD_QOS
+
+EXTRA_DIST = \
+ ACE_QoS.pc.in
+
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/ace/QoS/QoS_Decorator.cpp b/ACE/ace/QoS/QoS_Decorator.cpp
new file mode 100644
index 00000000000..90cc748e856
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Decorator.cpp
@@ -0,0 +1,165 @@
+// QoS_Decorator.cpp
+// $Id$
+
+#include "QoS_Decorator.h"
+
+ACE_RCSID(ace, QoS_Decorator, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_QOS_DECORATOR)
+
+// Constructor.
+ACE_QoS_Decorator_Base::ACE_QoS_Decorator_Base (void)
+{}
+
+// Constructor.
+ACE_QoS_Decorator_Base::ACE_QoS_Decorator_Base (ACE_Event_Handler
+ *event_handler)
+ : event_handler_ (event_handler)
+{
+}
+
+// Destructor.
+ACE_QoS_Decorator_Base::~ACE_QoS_Decorator_Base (void)
+{
+}
+
+// Forward the call to ACE_Event_Handler component.
+ACE_HANDLE
+ACE_QoS_Decorator_Base::get_handle (void) const
+{
+ return this->event_handler_->get_handle ();
+}
+
+// Forward the call to ACE_Event_Handler component.
+int
+ACE_QoS_Decorator_Base::handle_input (ACE_HANDLE fd)
+{
+ return this->event_handler_->handle_input (fd);
+}
+
+// Forward the call to ACE_Event_Handler component.
+int
+ACE_QoS_Decorator_Base::handle_qos (ACE_HANDLE fd)
+{
+ return this->event_handler_->handle_qos (fd);
+}
+
+// Constructor.
+ACE_QoS_Decorator::ACE_QoS_Decorator (void)
+{}
+
+// Constructor.
+ACE_QoS_Decorator::ACE_QoS_Decorator (ACE_Event_Handler *event_handler,
+ ACE_QoS_Session *qos_session,
+ ACE_Reactor *reactor)
+ : qos_session_ (qos_session),
+ reactor_ (reactor)
+{
+ ACE_NEW (this->decorator_base_,
+ ACE_QoS_Decorator_Base (event_handler));
+
+ ACE_NEW (this->qos_event_handler_,
+ ACE_QoS_Event_Handler (this->decorator_base_));
+}
+
+// Destructor.
+ACE_QoS_Decorator::~ACE_QoS_Decorator (void)
+{
+ delete this->decorator_base_;
+ delete this->qos_event_handler_;
+}
+
+// Implements the undecorated functionality. This is sufficient for
+// GQoS. RAPI needs additional QoS decoration. This is done by the
+// ACE_QoS_Event_Handler class.
+ACE_HANDLE
+ACE_QoS_Decorator::get_handle (void) const
+{
+ return this->decorator_base_->get_handle ();
+}
+
+// Implements the undecorated functionality. This is sufficient for
+// GQoS. RAPI needs additional QoS decoration. This is done by the
+// ACE_QoS_Event_Handler class.
+int
+ACE_QoS_Decorator::handle_input (ACE_HANDLE fd)
+{
+ return this->decorator_base_->handle_input (fd);
+}
+
+// Implements the undecorated functionality. This is sufficient for
+// GQoS. RAPI needs additional QoS decoration. This is done by the
+// ACE_QoS_Event_Handler class.
+int
+ACE_QoS_Decorator::handle_qos (ACE_HANDLE fd)
+{
+ return this->decorator_base_->handle_qos (fd);
+}
+
+// This method registers the RAPI QoS event handler with the reactor
+// if the application is using RAPI. Note that it is a no-op for GQoS
+// because an extra socket for handling QoS events is not required.
+int
+ACE_QoS_Decorator::init (void)
+{
+#if defined (ACE_HAS_RAPI)
+
+ // Pass the QoS session to QoS Event Handler.
+ this->qos_event_handler_->qos_session (this->qos_session_);
+
+ // Register the QoS Event Handler with the Reactor.
+ return this->reactor_->register_handler (this->qos_event_handler_,
+ ACE_Event_Handler::READ_MASK);
+#endif
+ return 0;
+
+}
+
+// Constructor.
+ACE_QoS_Event_Handler::ACE_QoS_Event_Handler (void)
+{
+}
+
+// Constructor.
+ACE_QoS_Event_Handler::ACE_QoS_Event_Handler (ACE_QoS_Decorator_Base
+ *decorator_base)
+ : decorator_base_ (decorator_base)
+{
+}
+
+// Destructor.
+ACE_QoS_Event_Handler::~ACE_QoS_Event_Handler (void)
+{
+}
+
+// Set the QoS session.
+void
+ACE_QoS_Event_Handler::qos_session (ACE_QoS_Session *qos_session)
+{
+ this->qos_session_ = qos_session;
+}
+
+// Returns the RAPI file descriptor for listening to RAPI evnets.
+ACE_HANDLE
+ACE_QoS_Event_Handler::get_handle (void) const
+{
+ return this->qos_session_->rsvp_events_handle ();
+}
+
+// Note, here the handle_input () calls the handle_qos () of the
+// Decorator Base which then calls handle_qos () of the
+// ACE_Event_Handler component within it. This helps to translate the
+// normal read events into qos events in case of RAPI so the
+// application using the API is oblivious to the fact that in RAPI,
+// QoS events are received on a different socket. This helps to
+// maintain a uniform design for the application irrespective of
+// whether it is using RAPI or GQoS.
+int
+ACE_QoS_Event_Handler::handle_input (ACE_HANDLE fd)
+{
+ return this->decorator_base_->handle_qos (fd);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/QoS/QoS_Decorator.h b/ACE/ace/QoS/QoS_Decorator.h
new file mode 100644
index 00000000000..512912e7c3b
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Decorator.h
@@ -0,0 +1,179 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file QoS_Decorator.h
+ *
+ * $Id$
+ *
+ * @author Vishal Kachroo <vishal@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef QOS_DECORATOR_H
+#define QOS_DECORATOR_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+#include "ace/Event_Handler.h"
+#include "SOCK_Dgram_Mcast_QoS.h"
+#include "ACE_QoS_Export.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_QoS_Decorator_Base
+ *
+ * @brief This class is the Decorator Pattern Base class for decorating
+ * ACE_Event_Handler.
+ *
+ * It simply forwards the requests for get_handle (),
+ * handle_input () and handle_qos () to its event_handler_
+ * component. Concrete decorators for ACE_Event_Handler will use
+ * this class to access the basic event handler functionality and
+ * decorate that by their own implementation.
+ */
+class ACE_QoS_Export ACE_QoS_Decorator_Base : public ACE_Event_Handler
+{
+
+public:
+
+ // Initialization and termination methods.
+ /// Constructor.
+ ACE_QoS_Decorator_Base (void);
+
+ /// Constructor.
+ ACE_QoS_Decorator_Base (ACE_Event_Handler *event_handler);
+
+ /// Destructor.
+ ~ACE_QoS_Decorator_Base (void);
+
+ /// Forwards the request to its event_handler_ component.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Forwards the request to its event_handler_ component.
+ virtual int handle_input (ACE_HANDLE fd);
+
+ /// Forwards the request to its event_handler_ component.
+ virtual int handle_qos (ACE_HANDLE fd);
+
+private:
+
+ /// The event handler that is decorated by this class.
+ ACE_Event_Handler *event_handler_;
+
+};
+
+/**
+ * @class ACE_QoS_Event_Handler
+ *
+ * @brief This Handler is registered with the Reactor for QoS events.
+ *
+ * Concrete QoS decorator uses this class to receive QoS events
+ * for RAPI. It hides the application from knowing that it is
+ * receiving QoS events on a different socket so the application
+ * doesnt have to be designed differently for RAPI and GQoS.
+ */
+class ACE_QoS_Export ACE_QoS_Event_Handler : public ACE_Event_Handler
+{
+
+ /// Destructor.
+ ~ACE_QoS_Event_Handler (void);
+
+ /// Returns the RAPI file descriptor for receiving QoS events.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Calls the base class handle_input ().
+ virtual int handle_input (ACE_HANDLE fd);
+
+ /// Sets the QoS session.
+ void qos_session (ACE_QoS_Session *qos_session);
+
+ friend class ACE_QoS_Decorator;
+
+private:
+
+ /// Constructor is private because only ACE_QoS_Decorator should
+ /// create this object.
+ ACE_QoS_Event_Handler (void);
+
+ /// The QoS Decorator passes in its base for this handler to use.
+ ACE_QoS_Event_Handler (ACE_QoS_Decorator_Base *decorator_base);
+
+ /// Used to get to the RAPI file descriptor for QoS Events.
+ ACE_QoS_Session *qos_session_;
+
+ /// Requests on the class are forwarded to this base class;
+ ACE_QoS_Decorator_Base *decorator_base_;
+
+};
+
+/**
+ * @class ACE_QoS_Decorator
+ *
+ * @brief Concrete QoS Decorator.
+ *
+ * Decorates the ACE_Event_Handler to additionally handle QoS
+ * events uniformly for different QoS mechanisms like RAPI and
+ * GQoS.
+ */
+class ACE_QoS_Export ACE_QoS_Decorator : public ACE_QoS_Decorator_Base
+{
+
+public:
+
+ // Initialization and termination methods.
+ /// Constructor.
+ ACE_QoS_Decorator (void);
+
+ /// Constructor.
+ ACE_QoS_Decorator (ACE_Event_Handler *event_handler,
+ ACE_QoS_Session *qos_session,
+ ACE_Reactor *reactor = ACE_Reactor::instance ());
+
+ /// Destructor.
+ ~ACE_QoS_Decorator (void);
+
+ /// Calls the base class get_handle ().
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Calls the base class handle_input ().
+ virtual int handle_input (ACE_HANDLE fd);
+
+ /// Calls the base class handle_qos ().
+ virtual int handle_qos (ACE_HANDLE fd);
+
+ /// This method registers the QoS Event Handler with the Reactor
+ /// to receive RAPI events.
+ int init (void);
+
+private:
+
+ /// Requests on the class are forwarded to this base class;
+ ACE_QoS_Decorator_Base *decorator_base_;
+
+ /// Handles the QoS events and in that sense decorates the usual
+ /// ACE_Event_Handler.
+ ACE_QoS_Event_Handler *qos_event_handler_;
+
+ /// Passed to the ACE_QoS_Event_Handler for retrieving the RAPI
+ /// session specific information like rapi_fd.
+ ACE_QoS_Session *qos_session_;
+
+ /// If the application wants to use an instance of Reactor other
+ /// than the Singleton one.
+ ACE_Reactor *reactor_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* QOS_DECORATOR_H */
diff --git a/ACE/ace/QoS/QoS_Manager.cpp b/ACE/ace/QoS/QoS_Manager.cpp
new file mode 100644
index 00000000000..5dcd5d7a473
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Manager.cpp
@@ -0,0 +1,41 @@
+// QoS_Manager.cpp
+// $Id$
+
+#include "QoS_Manager.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, QoS_Manager, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_QOS_MANAGER)
+
+ACE_QoS_Manager::ACE_QoS_Manager (void)
+{}
+
+ACE_QoS_Manager::~ACE_QoS_Manager (void)
+{}
+
+// Adds the given session to the list of session objects joined by
+// this socket.
+
+int
+ACE_QoS_Manager::join_qos_session (ACE_QoS_Session *qos_session)
+{
+ if (this->qos_session_set ().insert (qos_session) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Error in adding a new session to the ")
+ ACE_TEXT ("socket session set\n")),
+ -1);
+ return 0;
+}
+
+// Returns the QoS session set for this socket.
+
+ACE_Unbounded_Set <ACE_QoS_Session *>
+ACE_QoS_Manager::qos_session_set (void)
+{
+ return this->qos_session_set_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/QoS/QoS_Manager.h b/ACE/ace/QoS/QoS_Manager.h
new file mode 100644
index 00000000000..8a0b52c9943
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Manager.h
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file QoS_Manager.h
+ *
+ * $Id$
+ *
+ * @author Vishal Kachroo
+ */
+//=============================================================================
+
+
+#ifndef ACE_QOS_MANAGER_H
+#define ACE_QOS_MANAGER_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/IPC_SAP.h"
+#include "ace/Containers_T.h"
+#include "ACE_QoS_Export.h"
+#include "QoS_Session.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_QoS_Manager
+ *
+ * @brief This class manages the QoS sessions associated with ACE_SOCK.
+ *
+ * This class provides functions to manage the QoS
+ * associated with a socket. The idea is to keep the management of
+ * QoS for a socket separate from the socket itself. Currently, the
+ * manager is used to manage the QoS session set. It will handle more
+ * responsibilities in the future.
+ */
+class ACE_QoS_Export ACE_QoS_Manager
+{
+
+public:
+ /// Default constructor.
+ ACE_QoS_Manager (void);
+
+ /// Default destructor.
+ ~ACE_QoS_Manager (void);
+
+ /**
+ * Join the given QoS session. A socket can join multiple QoS
+ * sessions. This call adds the given QoS session to the list of
+ * QoS sessions that the socket has already joined.
+ */
+ int join_qos_session (ACE_QoS_Session *qos_session);
+
+ typedef ACE_Unbounded_Set <ACE_QoS_Session *> ACE_QOS_SESSION_SET;
+
+ /// Get the QoS session set.
+ ACE_QOS_SESSION_SET qos_session_set (void);
+
+private:
+
+ /// Set of QoS sessions that this socket has joined.
+ ACE_QOS_SESSION_SET qos_session_set_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_QOS_MANAGER_H */
diff --git a/ACE/ace/QoS/QoS_Session.h b/ACE/ace/QoS/QoS_Session.h
new file mode 100644
index 00000000000..3e08bbc69ce
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Session.h
@@ -0,0 +1,183 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file QoS_Session.h
+ *
+ * $Id$
+ *
+ * @author Vishal Kachroo <vishal@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_QOS_SESSION_H
+#define ACE_QOS_SESSION_H
+#include /**/ "ace/pre.h"
+
+#include "ACE_QoS_Export.h"
+#include "ace/INET_Addr.h"
+#include "ace/OS_QoS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_SOCK;
+class ACE_QoS_Manager;
+
+typedef int ACE_Protocol_ID;
+// IPPROTO_UDP or IPPROTO_TCP.
+
+/**
+ * @class ACE_QoS_Session
+ *
+ * @brief A QoS Session object.
+ *
+ * This class defines the interface for a QoS Session. It abstracts the
+ * notion of QoS on different platforms and presents a simple, easy-to-use
+ * API. Current [RAPI,GQoS] and future implementations will conform to this
+ * interface.
+ */
+class ACE_QoS_Export ACE_QoS_Session
+{
+
+public:
+
+ enum RSVP_Event_Type
+ {
+ RSVP_PATH_EVENT,
+ RSVP_RESV_EVENT,
+ RSVP_RESV_CONFIRM,
+ RSVP_RESV_ERROR,
+ RSVP_PATH_ERROR
+ };
+
+ /// A flag to indicate if this endpoint is a sender or a receiver or
+ /// both.
+ enum ACE_End_Point_Type
+ {
+ ACE_QOS_SENDER,
+ ACE_QOS_RECEIVER,
+ ACE_QOS_BOTH
+ };
+
+
+ /// to shutup g++.
+ virtual ~ACE_QoS_Session (void) {};
+
+ /// Open a QoS session [dest IP, dest port, Protocol ID].
+ virtual int open (ACE_INET_Addr dest_addr,
+ ACE_Protocol_ID protocol_id) = 0;
+
+ /// Close the QoS Session.
+ virtual int close (void) = 0;
+
+ /// Returns the QoS in the current session.
+ virtual ACE_QoS qos (void) const = 0;
+
+ /// Set QoS for the current session. The qos manager is used to
+ /// confirm if this QoS session was subscribed to by the socket.
+ virtual int qos (ACE_SOCK *socket,
+ ACE_QoS_Manager *qos_manager,
+ const ACE_QoS &ace_qos) = 0;
+
+ /**
+ * Sets the QoS for this session object to ace_qos. Does not
+ * interfere with the QoS in the underlying socket. This call is
+ * useful to update the QoS object when the underlying socket QoS is
+ * being set through a mechanism other than the previous qos ()
+ * method e.g. inside the dgram_mcast.subscribe () where the QoS for
+ * the socket is set through ACE_OS::join_leaf ().
+ */
+ virtual void qos (const ACE_QoS &ace_qos) = 0;
+
+ /**
+ * This is called from handle_qos () method of the the QoS Event
+ * Handler. Invoking this method is an indication of a QoS event
+ * occurring, that may have resulted in a change of QoS for the
+ * underlying session. This method updates the QoS object associated
+ * with this session.
+ */
+ virtual int update_qos (void) = 0;
+
+ /// Get/Set methods for the flags_.
+ virtual ACE_End_Point_Type flags (void) const = 0;
+ virtual void flags (const ACE_End_Point_Type flags) = 0;
+
+ /// Get the session id.
+ virtual int session_id (void) const = 0;
+
+ /// Set the session id.
+ virtual void session_id (const int session_id) = 0;
+
+ /// Get the file descriptor on which RSVP events will occur.
+ virtual ACE_HANDLE rsvp_events_handle (void) = 0;
+
+ virtual void rsvp_event_type (RSVP_Event_Type event_type) = 0;
+ ///Set the RAPI event that last occured
+
+ virtual RSVP_Event_Type rsvp_event_type (void) = 0;
+ ///Get the RAPI event that last occured
+
+
+ /// Get the destination address for this session.
+ virtual ACE_INET_Addr dest_addr (void) const = 0;
+
+ /// Set the destination address for this session.
+ virtual void dest_addr (const ACE_INET_Addr &dest_addr) = 0;
+
+ /// Get the source port for this session.
+ virtual u_short source_port (void) const = 0;
+
+ /// Set the source port for this session.
+ virtual void source_port (const u_short &source_port) = 0;
+
+ //Set the source host
+ virtual ACE_INET_Addr* source_addr (void) const = 0;
+
+ /// Set the source port for this session.
+ virtual void source_addr (ACE_INET_Addr* source_addr) = 0;
+
+
+ /**
+ * Returns the version of the underlying RSVP implementation. Is
+ * meaningful only when the underlying implementation has
+ * versioning.
+ */
+ virtual int version (void) = 0;
+
+protected:
+
+ /// Source port if this is a Sender session. Used for rapi_sender ().
+ u_short source_port_;
+
+ /// session id for the session.
+ int session_id_;
+
+ /// Destination address for this session.
+ ACE_INET_Addr dest_addr_;
+
+ /// Source address for this session.
+ ACE_INET_Addr* src_addr_;
+
+ /// Is this a TCP or a UDP session.
+ ACE_Protocol_ID protocol_id_;
+
+ /// QoS for this session.
+ ACE_QoS qos_;
+
+ /// Specifies if this is a sending/receiving/both session.
+ ACE_End_Point_Type flags_;
+
+ RSVP_Event_Type rsvp_event_type_;
+ //Has the last rsvp event that occured
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_QOS_SESSION_H */
diff --git a/ACE/ace/QoS/QoS_Session_Factory.cpp b/ACE/ace/QoS/QoS_Session_Factory.cpp
new file mode 100644
index 00000000000..18f0957696a
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Session_Factory.cpp
@@ -0,0 +1,105 @@
+// QoS_Session_Factory.cpp
+// $Id$
+
+#include "QoS_Session_Factory.h"
+#include "QoS_Session_Impl.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, QoS_Session_Factory, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_QoS_Session_Factory)
+
+#if defined(ACE_HAS_RAPI)
+const enum ACE_QoS_Session_Factory::ACE_QoS_Session_Type
+ ACE_QoS_Session_Factory::ACE_DEFAULT_QOS_SESSION = ACE_QoS_Session_Factory::ACE_RAPI_SESSION;
+#elif defined(ACE_HAS_WINSOCK2_GQOS)
+ const enum ACE_QoS_Session_Factory::ACE_QoS_Session_Type
+ ACE_QoS_Session_Factory::ACE_DEFAULT_QOS_SESSION = ACE_QoS_Session_Factory::ACE_GQOS_SESSION;
+#else
+# error "QoS type not supported. Cannot build."
+#endif /* ACE_HAS_RAPI */
+
+ACE_QoS_Session_Factory::ACE_QoS_Session_Factory (void)
+{
+ ACE_TRACE ("ACE_QoS_Session_Factory::ACE_QoS_Session_Factory");
+}
+
+ACE_QoS_Session_Factory::~ACE_QoS_Session_Factory (void)
+{
+ ACE_TRACE ("ACE_QoS_Session_Factory::~ACE_QoS_Session_Factory");
+}
+
+// Create a QoS session of the given type (RAPI or GQoS).
+ACE_QoS_Session *
+ACE_QoS_Session_Factory::create_session (ACE_QoS_Session_Type qos_session_type)
+{
+
+ ACE_QoS_Session * qos_session = 0;
+
+#if defined (ACE_HAS_RAPI)
+ if (qos_session_type == ACE_RAPI_SESSION)
+ ACE_NEW_RETURN (qos_session,
+ ACE_RAPI_Session,
+ 0);
+#endif /* ACE_HAS_RAPI */
+
+ if (qos_session_type == ACE_GQOS_SESSION)
+ ACE_NEW_RETURN (qos_session,
+ ACE_GQoS_Session,
+ 0);
+
+ if (this->add_session (qos_session) == -1)
+ {
+ delete qos_session;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Error in adding session\n")),
+ 0);
+ }
+
+ return qos_session;
+}
+
+// Destroy the QoS Session.
+int
+ACE_QoS_Session_Factory::destroy_session (ACE_QoS_Session *qos_session)
+{
+
+ if ((qos_session != 0) && (this->remove_session (qos_session) == -1))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Error in destroying session\n")),
+ -1);
+
+ return 0;
+}
+
+// Add a session to the set of sessions created by this factory. This is a
+// private method called by the create_session ().
+int
+ACE_QoS_Session_Factory::add_session (ACE_QoS_Session *qos_session)
+{
+ if (this->qos_session_set_.insert (qos_session) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Error in adding a new session")
+ ACE_TEXT ("to the session set\n")),
+ -1);
+
+ return 0;
+}
+
+// Remove a session from the set of sessions created by this factory. This is
+// a private method called by the destroy_session ().
+int
+ACE_QoS_Session_Factory::remove_session (ACE_QoS_Session *qos_session)
+{
+ if (this->qos_session_set_.remove (qos_session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Error in removing a session")
+ ACE_TEXT ("from the session set\n")),
+ -1);
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/QoS/QoS_Session_Factory.h b/ACE/ace/QoS/QoS_Session_Factory.h
new file mode 100644
index 00000000000..0559dce4220
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Session_Factory.h
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file QoS_Session_Factory.h
+ *
+ * $Id$
+ *
+ * @author Vishal Kachroo <vishal@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_QOS_SESSION_FACTORY_H
+#define ACE_QOS_SESSION_FACTORY_H
+#include /**/ "ace/pre.h"
+
+#include "ace/QoS/QoS_Session.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Containers_T.h"
+#include "ACE_QoS_Export.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declare this, so the factory uses only references to this.
+class ACE_QoS_Session;
+
+/**
+ * @class ACE_QoS_Session_Factory
+ *
+ * @brief Concrete factory for the QoS Session objects.
+ *
+ * This class manages the life cycle of QoS Session objects. These
+ * objects are currently either RAPI session objects or GQoS session
+ * objects. It stores the sessions in an unbounded set.
+ */
+class ACE_QoS_Export ACE_QoS_Session_Factory
+{
+
+public :
+
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_QoS_Session_Factory (void);
+
+ /// Default destructor.
+ ~ACE_QoS_Session_Factory (void);
+
+
+ /// Types of sessions for this factory to manage.
+ enum ACE_QoS_Session_Type
+ {
+ /// ACE_RAPI_SESSION on Unix platforms with RAPI support
+ ACE_RAPI_SESSION,
+
+ /// ACE_GQOS_SESSION on Windows platforms with GQOS support
+ ACE_GQOS_SESSION
+ };
+
+ /** The default QoS type supported on this platform.
+ *
+ * ACE_DEFAULT_QOS_SESSION = ACE_RAPI_SESSION on Unix platforms with RAPI support
+ * = ACE_GQOS_SESSION on Windows platforms with GQOS support
+ */
+ static const enum ACE_QoS_Session_Type ACE_DEFAULT_QOS_SESSION;
+
+ /// Create a QoS session of the given type (RAPI or GQoS).
+ ACE_QoS_Session * create_session (ACE_QoS_Session_Type qos_session_type = ACE_DEFAULT_QOS_SESSION );
+
+ /// Destroy the QoS Session.
+ int destroy_session (ACE_QoS_Session *qos_session);
+
+private:
+
+ /// Used by the create_session () to add new sessions to the
+ /// set of sessions created by this factory.
+ int add_session (ACE_QoS_Session *qos_session);
+
+ /// Used by the destroy_session () to remove a session from the set
+ /// of sessions created by this factory.
+ int remove_session (ACE_QoS_Session *qos_session);
+
+ /// Unordered set of QoS Sessions.
+ typedef ACE_Unbounded_Set <ACE_QoS_Session *> QOS_SESSION_SET;
+ QOS_SESSION_SET qos_session_set_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_QOS_SESSION_FACTORY_H */
diff --git a/ACE/ace/QoS/QoS_Session_Impl.cpp b/ACE/ace/QoS/QoS_Session_Impl.cpp
new file mode 100644
index 00000000000..e46b6e4422b
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Session_Impl.cpp
@@ -0,0 +1,718 @@
+// QoS_Session_Impl.cpp
+// $Id$
+
+#include "ace/OS_NS_arpa_inet.h"
+#include "ace/SOCK.h"
+#include "QoS_Manager.h"
+#include "QoS_Session_Impl.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "QoS_Session_Impl.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, QoS_Session_Impl, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_QoS_Session_Impl)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_RAPI)
+#include "rapi_err.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int ACE_RAPI_Session::rsvp_error = 0;
+
+// Call back function used by RAPI to report RSVP events. This
+// function translates the RAPI QoS parameters into the more generic
+// ACE_QoS parameters for the underlying RAPI session.
+int
+rsvp_callback (rapi_sid_t /* sid */,
+ rapi_eventinfo_t eventype,
+ int /* style_id */,
+ int errcode,
+ int errvalue,
+ sockaddr * errnode,
+ u_char /* errflags */,
+ int /* filter_spec_no */,
+ rapi_filter_t * /* filter_spec_list */,
+ int flow_spec_no,
+ rapi_flowspec_t *flow_spec_list,
+ int /* ad_spec_no */,
+ rapi_adspec_t * /* ad_spec_list */,
+ void *args
+ )
+{
+ if (args == 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "Argument in the call back function is null\n\n"));
+
+ ACE_QoS_Session *qos_session = (ACE_QoS_Session *) args;
+
+ qos_flowspecx_t *csxp = 0;
+
+ if (!flow_spec_list)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%N|%l) Null flow_spec_list\n"));
+ }
+ else
+ {
+ // Extended Legacy format.
+ csxp = &flow_spec_list->specbody_qosx;
+ if(!csxp)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N|%l) Null csxp\n"),
+ -1);
+ }
+ }
+
+ ACE_QoS ace_qos = qos_session->qos ();
+
+ switch(eventype)
+ {
+ case RAPI_PATH_EVENT:
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "RSVP PATH Event received\n"
+ "No. of TSpecs received : %d %d\n",
+ flow_spec_no, &flow_spec_list->len));
+
+ ACE_Flow_Spec *receiving_fs = 0;
+
+ if (flow_spec_no != 0)
+ {
+ ACE_NEW_RETURN (receiving_fs,
+ ACE_Flow_Spec,
+ -1);
+
+ ACE_NEW_RETURN (receiving_fs,
+ ACE_Flow_Spec ((u_long)csxp->xspec_r,
+ (u_long)csxp->xspec_b,
+ (u_long)csxp->xspec_p,
+ 0,
+ csxp->xspec_S,
+ 1,
+ csxp->xspec_M,
+ csxp->xspec_m,
+ 25,
+ 0),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nTSpec :\n"
+ "\t Spec Type = %d\n"
+ "\t Rate = %f\n"
+ "\t Bucket = %f\n"
+ "\t Peak = %f\n"
+ "\t MPU = %d\n"
+ "\t MDU = %d\n"
+ "\t TTL = %d\n",
+ csxp->spec_type,
+ csxp->xspec_r,
+ csxp->xspec_b,
+ csxp->xspec_p,
+ csxp->xspec_m,
+ csxp->xspec_M,
+ 25));
+ }
+
+ // Set the sending flowspec QoS of the given session.
+ ace_qos.receiving_flowspec (receiving_fs);
+
+ qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_PATH_EVENT);
+ }
+ break;
+
+ case RAPI_RESV_EVENT:
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "RSVP RESV Event received\n"
+ "No. of FlowSpecs received : %d\n",
+ flow_spec_no));
+
+ ACE_Flow_Spec *sending_flow = 0;
+
+ if (flow_spec_no != 0)
+ {
+ ACE_NEW_RETURN (sending_flow,
+ ACE_Flow_Spec,
+ -1);
+
+ // Choose based on the service type : [QOS_GUARANTEEDX/QOS_CNTR_LOAD].
+ switch (csxp->spec_type)
+ {
+ case QOS_GUARANTEEDX:
+ // Slack term in MICROSECONDS
+ sending_flow->delay_variation (csxp->xspec_S);
+
+ // @@How does the guaranteed rate parameter map to the ACE_Flow_Spec.
+ // Note there is no break !!
+
+ case QOS_CNTR_LOAD:
+ // qos_service_type.
+ sending_flow->service_type (csxp->spec_type);
+ // Token Bucket Average Rate (B/s)
+ sending_flow->token_rate ((u_long)csxp->xspec_r);
+ // Token Bucket Rate (B)
+ sending_flow->token_bucket_size ((u_long)csxp->xspec_b);
+ // Peak Data Rate (B/s)
+ sending_flow->peak_bandwidth ((u_long)csxp->xspec_p);
+ // Minimum Policed Unit (B)
+ sending_flow->minimum_policed_size (csxp->xspec_m);
+ // Max Packet Size (B)
+ sending_flow->max_sdu_size (csxp->xspec_M);
+ break;
+
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N|%l) Unknown flowspec type: %u.\n", csxp->spec_type),
+ -1);
+ }
+ }
+
+ ace_qos.sending_flowspec (sending_flow);
+ qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_EVENT);
+ }
+ break;
+
+ case RAPI_PATH_ERROR:
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "PATH ERROR Event received\n"
+ "Code=%d Val=%d Node= %s\n",
+ errcode,
+ errvalue,
+ ACE_OS::inet_ntoa(((sockaddr_in *)errnode)->sin_addr)));
+ qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_PATH_ERROR);
+ }
+ break;
+
+ case RAPI_RESV_ERROR:
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "RESV ERROR Event received\n"
+ "Code=%d Val=%d Node= %s\n",
+ errcode,
+ errvalue,
+ ACE_OS::inet_ntoa(((sockaddr_in *)errnode)->sin_addr)));
+ qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_ERROR);
+ }
+ break;
+
+ case RAPI_RESV_CONFIRM:
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "RESV CONFIRM Event received\n"));
+ qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_CONFIRM);
+ }
+ break;
+
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ "Unknown RSVP Event Received\n"));
+ break;
+
+ }
+
+ // Set the updated ACE_QoS for the RSVP callback argument(QoS session).
+ qos_session->qos (ace_qos);
+
+ // @@ what is the meaning of the return value. RAPI docs don't say anything!
+ return 0;
+}
+
+// Constructor.
+ACE_RAPI_Session::ACE_RAPI_Session (void)
+{
+ ACE_TRACE ("ACE_RAPI_Session::ACE_RAPI_Session");
+ //this->source_port (DEFAULT_SOURCE_SENDER_PORT);
+ ACE_NEW (this->src_addr_,
+ ACE_INET_Addr ("0"));
+}
+
+// Open a RAPI QoS session [dest IP, dest port, Protocol ID].
+int
+ACE_RAPI_Session::open (ACE_INET_Addr dest_addr,
+ ACE_Protocol_ID protocol_id)
+{
+ char buf [BUFSIZ];
+ dest_addr.addr_to_string (buf,
+ BUFSIZ);
+ ACE_DEBUG ((LM_DEBUG,
+ "In RAPI SESSION OPEN %s\n",
+ buf));
+
+ this->dest_addr_ = dest_addr;
+ this->protocol_id_ = protocol_id;
+
+ // Open a RAPI session. Note "this" is being passed as an argument to
+ // the callback function. The callback function uses this argument to
+ // update the QoS of this session based on the RSVP event it receives.
+
+ if ((this->session_id_ = rapi_session((struct sockaddr *) dest_addr.get_addr (),
+ protocol_id,
+ 0,
+ rsvp_callback,
+ (void *) this,
+ &rsvp_error)) == NULL_SID)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "rapi_session () call fails. Error\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "rapi_session () call succeeds. "
+ "Session ID = %d\n",
+ this->session_id_));
+
+ return 0;
+}
+
+// Close the RAPI QoS Session.
+int
+ACE_RAPI_Session::close (void)
+{
+ this->rsvp_error = rapi_release(this->session_id_);
+
+ if (rsvp_error == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Can't release RSVP session:\n\t%s\n",
+ rapi_errlist[rsvp_error]),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "rapi session with id %d released successfully.\n",
+ this->session_id_));
+ return 0;
+}
+
+//Get the most recent RSVP event that occured
+ACE_QoS_Session::RSVP_Event_Type
+ACE_RAPI_Session::rsvp_event_type (void)
+{
+ return this->rsvp_event_type_;
+}
+
+//Set the most recent RSVP event that occured
+void
+ACE_RAPI_Session::rsvp_event_type (ACE_QoS_Session::RSVP_Event_Type event_type)
+{
+ this->rsvp_event_type_ = event_type;
+}
+
+int
+ACE_RAPI_Session::qos (ACE_SOCK * /* socket */,
+ ACE_QoS_Manager * /* qos_manager */,
+ const ACE_QoS &ace_qos)
+{
+
+ // If sender : call sending_qos ()
+ // If receiver : call receiving_qos ()
+ // If both : call sending_qos () and receiving_qos ()
+
+ if (this->flags_ != ACE_QOS_RECEIVER)
+ return this->sending_qos (ace_qos);
+
+ if (this->flags_ != ACE_QOS_SENDER)
+ return this->receiving_qos (ace_qos);
+
+ return 0;
+}
+
+// Set sending QoS for this RAPI session.
+int
+ACE_RAPI_Session::sending_qos (const ACE_QoS &ace_qos)
+{
+ ACE_Flow_Spec *sending_flowspec = ace_qos.sending_flowspec ();
+
+ if (sending_flowspec == 0)
+ {
+ int result = rapi_sender (this->session_id_,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 25);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
+ result),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "rapi_sender () call succeeds with PATH Tear! \n"));
+
+ return 0;
+ }
+
+ rapi_tspec_t *t_spec = this->init_tspec_simplified (*sending_flowspec);
+ if (t_spec == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N|%l) Error in translating from ACE Flow Spec to"
+ " RAPI TSpec\n"),
+ -1);
+
+ char buffer[BUFSIZ];
+
+ // This formats the t_spec in a visually intuitive char * that can
+ // be printed.
+
+ (void) rapi_fmt_tspec(t_spec, buffer, sizeof(buffer));
+ ACE_DEBUG ((LM_DEBUG,
+ "\nSender TSpec : %s\n",
+ buffer));
+
+ // Print out all the fields separately.
+ ACE_DEBUG ((LM_DEBUG,
+ "\nTSpec :\n"
+ "\t Spec Type = %d\n"
+ "\t Rate = %f\n"
+ "\t Bucket = %f\n"
+ "\t Peak = %f\n"
+ "\t MPU = %d\n"
+ "\t MDU = %d\n"
+ "\t TTL = %d\n",
+ t_spec->tspecbody_qosx.spec_type,
+ t_spec->tspecbody_qosx.xtspec_r,
+ t_spec->tspecbody_qosx.xtspec_b,
+ t_spec->tspecbody_qosx.xtspec_p,
+ t_spec->tspecbody_qosx.xtspec_m,
+ t_spec->tspecbody_qosx.xtspec_M,
+ sending_flowspec->ttl ()));
+
+ // This the source sender port.
+ // ACE_INET_Addr sender_addr (this->source_port ());
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Making the rapi_sender () call\n"));
+
+ // Set the Sender TSpec for this QoS session.
+
+
+ int result = rapi_sender(this->session_id_,
+ 0,
+ (sockaddr *) this->src_addr_->get_addr (),
+ 0,
+ t_spec,
+ 0,
+ 0,
+ sending_flowspec->ttl ()) ;
+
+ /*
+ int result = rapi_sender(this->session_id_,
+ 0,
+ (sockaddr *) sender_addr.get_addr (),
+ 0,
+ t_spec,
+ 0,
+ 0,
+ sending_flowspec->ttl ()) ;
+ */
+ if(result!= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
+ result),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "rapi_sender () call succeeds ! \n"));
+ return 0;
+}
+
+// Set receiving QoS for this RAPI session.
+int
+ACE_RAPI_Session::receiving_qos (const ACE_QoS &ace_qos)
+{
+
+ ACE_Flow_Spec *receiving_flowspec = ace_qos.receiving_flowspec ();
+ if (receiving_flowspec == 0)
+ {
+ if (rapi_reserve(this->session_id_,
+ 0,
+ // Setting the RAPI_REQ_CONFIRM flag requests confirmation
+ // of the resevation, by means of a confirmation upcall of
+ // type RAPI_RESV_CONFIRM.
+ // (sockaddr *)receiver_addr.get_addr (),
+ 0,
+ RAPI_RSTYLE_WILDCARD,
+ // This applies the flowspec to all the senders. Given this,
+ // @@I am passing the filter_spec to be null, hoping this will work.
+ 0,
+ 0,
+ 0,
+ 0,
+ // The filter spec is NULL. This should work since the RSTYLE is
+ // WILDCARD.
+ 0,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N|%l)rapi_reserve () error:\n\tRESV Generation can't be started\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "rapi_reserve () for RESV Tear call succeeds \n"));
+
+ return 0;
+ }
+
+
+ rapi_flowspec_t *flow_spec = init_flowspec_simplified (*receiving_flowspec);
+
+ if (flow_spec == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N|%l) Error in translating from ACE Flow Spec to"
+ " RAPI FlowSpec\n"),
+ -1);
+
+ char buffer[BUFSIZ];
+
+ // This formats the flow_spec in a visually intuitive char * that can
+ // be printed.
+ (void)rapi_fmt_flowspec(flow_spec, buffer, sizeof(buffer));
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceiver FlowSpec : %s\n",
+ buffer));
+
+ // Print out all the fields separately.
+ ACE_DEBUG ((LM_DEBUG,
+ "\nFlowSpec :\n"
+ "\t Spec Type = %d\n"
+ "\t Rate = %f\n"
+ "\t Bucket = %f\n"
+ "\t Peak = %f\n"
+ "\t MPU = %d\n"
+ "\t MDU = %d\n",
+ flow_spec->specbody_qosx.spec_type,
+ flow_spec->specbody_qosx.xspec_r,
+ flow_spec->specbody_qosx.xspec_b,
+ flow_spec->specbody_qosx.xspec_p,
+ flow_spec->specbody_qosx.xspec_m,
+ flow_spec->specbody_qosx.xspec_M));
+
+ sockaddr_in Receiver_host;
+
+ Receiver_host.sin_addr.s_addr = INADDR_ANY;
+
+ // Set the Receiver FlowSpec for this QoS session.
+ // @@The filter style is hardcoded to WildCard. This can be changed later.
+ if (rapi_reserve(this->session_id_,
+ RAPI_REQ_CONFIRM,
+ // Setting the RAPI_REQ_CONFIRM flag requests confirmation
+ // of the resevation, by means of a confirmation upcall of
+ // type RAPI_RESV_CONFIRM.
+ // (sockaddr *)receiver_addr.get_addr (),
+ (sockaddr *)&Receiver_host,
+ RAPI_RSTYLE_WILDCARD,
+ // This applies the flowspec to all the senders. Given this,
+ // @@I am passing the filter_spec to be null, hoping this will work.
+ 0,
+ 0,
+ 0,
+ 0,
+ // The filter spec is NULL. This should work since the RSTYLE is
+ // WILDCARD.
+ 1,
+ flow_spec) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "rapi_reserve () error:\n\tRESV Generation can't be started\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "rapi_reserve () call succeeds \n"));
+
+ return 0;
+}
+
+int
+ACE_RAPI_Session::update_qos (void)
+{
+ // Update the session QoS Parameters based on the RSVP Event Received.
+ if ((rsvp_error = rapi_dispatch ()) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in rapi_dispatch () : %s\n",
+ rapi_errlist[rsvp_error]),
+ -1);
+ return 0;
+}
+
+// Construct a simplified RAPI Sender TSpec object
+// from an ACE_Flow_Spec. Note the form of the TSpec is
+// simplified as against the full bodied IntServ version.
+
+rapi_tspec_t *
+ACE_RAPI_Session::init_tspec_simplified (const ACE_Flow_Spec &flow_spec)
+{
+ rapi_tspec_t *t_spec;
+
+ ACE_NEW_RETURN (t_spec,
+ rapi_tspec_t,
+ 0);
+
+ qos_tspecx_t *ctxp = &(t_spec->tspecbody_qosx);
+
+ // There may be some type incompatibility here.
+ // Note the types of the LHS are float32_t, uint32_t etc.
+
+ ctxp->spec_type = flow_spec.service_type ();//QOS_TSPEC;
+ ctxp->xtspec_r = flow_spec.token_rate (); // Token Rate (B/s)
+ ctxp->xtspec_b = flow_spec.token_bucket_size (); // Token Bucket Depth (B)
+ ctxp->xtspec_p = flow_spec.peak_bandwidth (); // Peak Data Rate (B/s)
+ ctxp->xtspec_m = flow_spec.minimum_policed_size (); // Minimum policed unit.
+ ctxp->xtspec_M = flow_spec.max_sdu_size(); // Maximum SDU size.
+ t_spec->len = sizeof(rapi_hdr_t) + sizeof(qos_tspecx_t);
+ t_spec->form = RAPI_TSPECTYPE_Simplified;
+
+ return (t_spec);
+}
+
+
+// Construct a simplified RAPI flowspec object from ACE_Flow_Spec.
+// Note the form of the FlowSpec is simplified as against the
+// full bodied IntServ version.
+
+rapi_flowspec_t *
+ACE_RAPI_Session::init_flowspec_simplified(const ACE_Flow_Spec &flow_spec)
+{
+ rapi_flowspec_t *flowsp;
+ ACE_NEW_RETURN (flowsp,
+ rapi_flowspec_t,
+ 0);
+
+ // Extended Legacy format.
+ qos_flowspecx_t *csxp = &flowsp->specbody_qosx;
+
+ // Choose based on the service type : [QOS_GUARANTEEDX/QOS_CNTR_LOAD].
+
+ switch (flow_spec.service_type ())
+ {
+ case QOS_GUARANTEEDX:
+ csxp->xspec_R = 0 ; // Guaranteed Rate B/s. @@How does this map to the
+ // ACE Flow Spec Parameters.
+
+ csxp->xspec_S = flow_spec.delay_variation () ; // Slack term in MICROSECONDS
+
+ // Note there is no break !!
+
+ case QOS_CNTR_LOAD:
+ csxp->spec_type = flow_spec.service_type (); // qos_service_type
+ csxp->xspec_r = flow_spec.token_rate (); // Token Bucket Average Rate (B/s)
+ csxp->xspec_b = flow_spec.token_bucket_size (); // Token Bucket Rate (B)
+ csxp->xspec_p = flow_spec.peak_bandwidth (); // Peak Data Rate (B/s)
+ csxp->xspec_m = flow_spec.minimum_policed_size (); // Minimum Policed Unit (B)
+
+ csxp->xspec_M = flow_spec.max_sdu_size(); // Max Packet Size (B)
+
+ flowsp->form = RAPI_FLOWSTYPE_Simplified;
+ break;
+
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N|%l) Unknown flowspec type: %u\n",flow_spec.service_type () ),
+ 0);
+ }
+
+ flowsp->len = sizeof(rapi_flowspec_t);
+ return flowsp;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_RAPI */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This is a GQoS session ID generator.
+int ACE_GQoS_Session::GQoS_session_id = 0;
+
+// Constructor.
+ACE_GQoS_Session::ACE_GQoS_Session (void)
+{
+ ACE_TRACE ("ACE_GQoS_Session::ACE_GQoS_Session");
+}
+
+// Open a GQoS session [dest IP, dest port, Protocol ID].
+int
+ACE_GQoS_Session::open (ACE_INET_Addr dest_addr,
+ ACE_Protocol_ID protocol_id)
+{
+ this->dest_addr_ = dest_addr;
+ this->protocol_id_ = protocol_id;
+
+ this->session_id_ = GQoS_session_id++;
+
+ return 0;
+}
+
+// Close the GQoS Session.
+int
+ACE_GQoS_Session::close (void)
+{
+ // TBD.
+ return 0;
+}
+
+// Set the QoS for this GQoS session.
+int
+ACE_GQoS_Session::qos (ACE_SOCK *socket,
+ ACE_QoS_Manager *qos_manager,
+ const ACE_QoS &ace_qos)
+{
+
+ // Confirm if the current session is one of the QoS sessions
+ // subscribed to by the given socket.
+
+ if (qos_manager->qos_session_set ().find (this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("This QoS session was not subscribed to")
+ ACE_TEXT (" by the socket\n")),
+ -1);
+
+ // Set the QOS according to the supplied ACE_QoS. The I/O control
+ // code used under the hood is SIO_SET_QOS.
+
+ u_long ret_bytes = 0;
+
+ ACE_QoS qos = ace_qos;
+ if (ACE_OS::ioctl (socket->get_handle (),
+ ACE_SIO_SET_QOS,
+ qos,
+ &ret_bytes) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Error in Qos set ACE_OS::ioctl() %d\n"),
+ ret_bytes),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Setting QoS with ACE_OS::ioctl () succeeds \n")));
+
+ return 0;
+}
+
+int
+ACE_GQoS_Session::update_qos (void)
+{
+ // WSAIoctl (GET_QOS) call goes here...
+ return 0;
+}
+
+//Get the most recent RSVP event that occured
+ACE_QoS_Session::RSVP_Event_Type
+ACE_GQoS_Session::rsvp_event_type (void)
+{
+ return this->rsvp_event_type_;
+}
+
+//Set the most recent RSVP event that occured
+void
+ACE_GQoS_Session::rsvp_event_type (ACE_QoS_Session::RSVP_Event_Type event_type)
+{
+ this->rsvp_event_type_ = event_type;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/QoS/QoS_Session_Impl.h b/ACE/ace/QoS/QoS_Session_Impl.h
new file mode 100644
index 00000000000..a9ea0287540
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Session_Impl.h
@@ -0,0 +1,265 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file QoS_Session_Impl.h
+ *
+ * $Id$
+ *
+ * @author Vishal Kachroo <vishal@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_QOS_SESSION_IMPL_H
+#define ACE_QOS_SESSION_IMPL_H
+#include /**/ "ace/pre.h"
+
+#include "ace/QoS/QoS_Session.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+#if defined (ACE_HAS_RAPI)
+#include "rapi_lib.h"
+
+#define DEFAULT_SOURCE_SENDER_PORT 10001
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_RAPI_Session
+ *
+ * @brief A RAPI QoS session object.
+ *
+ * This class is a RAPI (RSVP API, an implementation of RSVP on UNIX)
+ * implementation of the ACE_QoS_Session interface.
+ */
+class ACE_QoS_Export ACE_RAPI_Session : public ACE_QoS_Session
+{
+
+public:
+
+ /// Default destructor.
+ ~ACE_RAPI_Session (void);
+
+ /// Error handling for RSVP callback
+ static int rsvp_error;
+
+ /// Open a RAPI QoS session [dest IP, dest port, Protocol ID].
+ virtual int open (ACE_INET_Addr dest_addr,
+ ACE_Protocol_ID protocol_id);
+
+ /// Close the RAPI QoS Session.
+ virtual int close (void);
+
+ /// Returns the QoS for this RAPI session.
+ virtual ACE_QoS qos (void) const;
+
+ /// Set QoS for this RAPI session. The socket parameter is used to confirm if
+ /// this QoS session was subscribed to by the socket.
+ virtual int qos (ACE_SOCK *socket,
+ ACE_QoS_Manager *qos_manager,
+ const ACE_QoS &ace_qos);
+
+ /**
+ * Sets the QoS for this session object to ace_qos. Does not interfere with the
+ * QoS in the underlying socket. This call is useful to update the QoS object
+ * when the underlying socket QoS is being set through a mechanism other than
+ * the previous qos () method e.g. inside the dgram_mcast.subscribe () where the
+ * QoS for the socket is set through ACE_OS::join_leaf ().
+ */
+ virtual void qos (const ACE_QoS &ace_qos);
+
+ /**
+ * Calls rapi_dispatch () that further triggers the call back function.
+ * It is a mechanism of updating the QoS for this session asynchronously, as
+ * RSVP events occur.
+ */
+ virtual int update_qos (void);
+
+ /// Get methods for the flags_.
+ virtual ACE_End_Point_Type flags (void) const;
+
+ /// Set methods for the flags_.
+ virtual void flags (const ACE_End_Point_Type flags);
+
+ /// Get the RAPI session id.
+ virtual int session_id (void) const;
+
+ /// Set the RAPI session id.
+ virtual void session_id (const int session_id);
+
+ /// Get the RAPI file descriptor for RSVP events.
+ virtual ACE_HANDLE rsvp_events_handle (void);
+
+ ///Set the RAPI event that last occured
+ virtual void rsvp_event_type (RSVP_Event_Type event_type);
+
+ ///Get the RAPI event that last occured
+ virtual RSVP_Event_Type rsvp_event_type (void);
+
+ /// Get the destination address for this RAPI session.
+ virtual ACE_INET_Addr dest_addr (void) const;
+
+ /// Set the destination address for this RAPI session.
+ virtual void dest_addr (const ACE_INET_Addr &dest_addr);
+
+ /// Get the source port for this session.
+ virtual u_short source_port (void) const;
+
+ /// Set the source port for this session.
+ virtual void source_port (const u_short &source_port);
+
+ //Set the source host
+ virtual ACE_INET_Addr* source_addr (void) const;
+
+ /// Set the source port for this session.
+ virtual void source_addr (ACE_INET_Addr* source_addr);
+
+ /// RAPI version. Returned value = 100 * major-version + minor-version.
+ virtual int version ();
+
+ /// The factory is a friend so it can create this object through
+ /// the only private constructor.
+ friend class ACE_QoS_Session_Factory;
+
+private:
+
+ /// Default constuctor. Constructor is defined private so that only
+ /// the friend factory can instantiate this class.
+ ACE_RAPI_Session (void);
+
+ /// Construct a simplified RAPI Sender TSpec object
+ /// from an ACE_Flow_Spec object. Used internally by this class.
+ rapi_tspec_t *init_tspec_simplified (const ACE_Flow_Spec &flow_spec);
+
+ /// Construct a simplified RAPI Receiver FlowSpec object
+ /// from an ACE_Flow_Spec object. Used internally by the class.
+ rapi_flowspec_t *init_flowspec_simplified(const ACE_Flow_Spec &flow_spec);
+
+ /// Set sending QoS for this RAPI session.
+ int sending_qos (const ACE_QoS &ace_qos);
+
+ /// Set receiving QoS for this RAPI session.
+ int receiving_qos (const ACE_QoS &ace_qos);
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_RAPI */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_GQoS_Session
+ *
+ * @brief A GQoS session object.
+ *
+ * This class is a GQoS (Generic QoS, an implementation of RSVP on
+ * Win2K) implementation of the ACE_QoS_Session interface.
+ */
+class ACE_QoS_Export ACE_GQoS_Session : public ACE_QoS_Session
+{
+
+public:
+
+ /// Default destructor.
+ ~ACE_GQoS_Session (void);
+
+ /// This is a session ID generator. It does a lot more than expected
+ /// from an int!.
+ static int GQoS_session_id;
+
+ /// Open a GQoS session [dest IP, dest port, Protocol ID].
+ virtual int open (ACE_INET_Addr dest_addr,
+ ACE_Protocol_ID protocol_id);
+
+ /// Close the GQoS Session.
+ virtual int close (void);
+
+ /// Returns the QoS for this GQoS session.
+ virtual ACE_QoS qos (void) const;
+
+ /// Set QoS for this GQoS session. The socket parameter is used to confirm if
+ /// this QoS session was subscribed to by the socket.
+ virtual int qos (ACE_SOCK *socket,
+ ACE_QoS_Manager *qos_manager,
+ const ACE_QoS &ace_qos);
+
+ /**
+ * Sets the QoS for this session object to ace_qos. Does not interfere with the
+ * QoS in the underlying socket. This call is useful to update the QoS object
+ * when the underlying socket QoS is being set through a mechanism other than
+ * the previous qos () method e.g. inside the dgram_mcast.subscribe () where the
+ * QoS for the socket is set through ACE_OS::join_leaf ().
+ */
+ virtual void qos (const ACE_QoS &ace_qos);
+
+ /// Calls the ioctl (ACE_SIO_GET_QOS). It is a mechanism of updating the
+ /// QoS for this session asynchronously, as RSVP events occur.
+ virtual int update_qos (void);
+
+ /// Get/Set methods for the flags_.
+ virtual ACE_End_Point_Type flags (void) const;
+ virtual void flags (const ACE_End_Point_Type flags);
+
+ /// Get the destination address for this GQoS session.
+ virtual ACE_INET_Addr dest_addr (void) const;
+
+ /// Set the destination address for this GQoS session.
+ virtual void dest_addr (const ACE_INET_Addr &dest_addr);
+
+ /// Get the source port for this session.
+ virtual u_short source_port (void) const;
+
+ /// Set the source port for this session.
+ virtual void source_port (const u_short &source_port);
+
+ //Set the source host
+ virtual ACE_INET_Addr* source_addr (void) const;
+
+ /// Set the source port for this session.
+ virtual void source_addr (ACE_INET_Addr* source_addr);
+
+ /// Get the GQoS session id.
+ virtual int session_id (void) const;
+
+ /// Set the GQoS session id.
+ virtual void session_id (const int session_id);
+
+ /// Get the file descriptor of the underlying socket.
+ virtual ACE_HANDLE rsvp_events_handle (void);
+
+ virtual void rsvp_event_type (RSVP_Event_Type event_type);
+ ///Set the RAPI event that last occured
+
+ virtual RSVP_Event_Type rsvp_event_type (void);
+ ///Get the RAPI event that last occured
+
+ /// GQoS version.
+ virtual int version ();
+
+ /// The factory is a friend so it can create this object through
+ /// the only private constructor.
+ friend class ACE_QoS_Session_Factory;
+
+private:
+
+ /// Default constructor. Constructor is defined private so that only
+ /// the friend factory can instantiate this class.
+ ACE_GQoS_Session (void);
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "QoS_Session_Impl.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_QOS_SESSION_IMPL_H */
diff --git a/ACE/ace/QoS/QoS_Session_Impl.inl b/ACE/ace/QoS/QoS_Session_Impl.inl
new file mode 100644
index 00000000000..b3971b46d52
--- /dev/null
+++ b/ACE/ace/QoS/QoS_Session_Impl.inl
@@ -0,0 +1,229 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_RAPI)
+
+ACE_INLINE
+ACE_RAPI_Session::~ACE_RAPI_Session (void)
+{
+ ACE_TRACE ("ACE_RAPI_Session::~ACE_RAPI_Session");
+}
+
+// Returns the QoS for this RAPI session.
+ACE_INLINE ACE_QoS
+ACE_RAPI_Session::qos (void) const
+{
+ return this->qos_;
+}
+
+// Overloaded method to set the QoS for this session object. Does not
+// interfere with the underlying socket QoS.
+ACE_INLINE void
+ACE_RAPI_Session::qos (const ACE_QoS &ace_qos)
+{
+ this->qos_ = ace_qos;
+}
+
+// Get the RAPI session id.
+ACE_INLINE int
+ACE_RAPI_Session::session_id (void) const
+{
+ return this->session_id_;
+}
+
+// Set the RAPI session id.
+ACE_INLINE void
+ACE_RAPI_Session::session_id (const int session_id)
+{
+ this->session_id_ = session_id;
+}
+
+// Get the RAPI file desciptor for RSVP events.
+ACE_INLINE ACE_HANDLE
+ACE_RAPI_Session::rsvp_events_handle (void)
+{
+ int rapi_fd = rapi_getfd (this->session_id ());
+ if (rapi_fd == -1)
+ {
+ this->close ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in rapi_getfd ()\n"),
+ -1);
+ }
+
+ return rapi_fd;
+}
+
+// Get the End Point Type (Sender/Receiver/Both).
+ACE_INLINE ACE_QoS_Session::ACE_End_Point_Type
+ACE_RAPI_Session::flags (void) const
+{
+ return this->flags_;
+}
+
+// Set the End Point Type (Sender/Receiver/Both).
+ACE_INLINE void
+ACE_RAPI_Session::flags (const ACE_End_Point_Type flags)
+{
+ this->flags_ = flags;
+}
+
+
+// Get the destination address for this RAPI session.
+ACE_INLINE ACE_INET_Addr
+ACE_RAPI_Session::dest_addr (void) const
+{
+ return this->dest_addr_;
+}
+
+// Set the destination address for this RAPI session.
+ACE_INLINE void
+ACE_RAPI_Session::dest_addr (const ACE_INET_Addr &dest_addr)
+{
+ this->dest_addr_ = dest_addr;
+}
+
+// Get the source port for this RAPI session.
+ACE_INLINE u_short
+ACE_RAPI_Session::source_port (void) const
+{
+ return this->source_port_;
+}
+
+// Set the source port for this RAPI session.
+ACE_INLINE void
+ACE_RAPI_Session::source_port (const u_short &source_port)
+{
+ this->source_port_ = source_port;
+}
+
+ACE_INLINE ACE_INET_Addr*
+ACE_RAPI_Session::source_addr (void) const
+{
+ return this->src_addr_;
+}
+
+ACE_INLINE void
+ACE_RAPI_Session::source_addr (ACE_INET_Addr* source_addr)
+{
+ this->src_addr_ = source_addr;
+}
+
+// RAPI version. Returned value = 100 * major-version + minor-version.
+ACE_INLINE int
+ACE_RAPI_Session::version (void)
+{
+ return 0;
+}
+
+#endif /* ACE_HAS_RAPI */
+
+ACE_INLINE
+ACE_GQoS_Session::~ACE_GQoS_Session (void)
+{
+ ACE_TRACE ("ACE_GQoS_Session::~ACE_GQoS_Session");
+}
+
+// Returns the QoS for this GQoS session.
+ACE_INLINE ACE_QoS
+ACE_GQoS_Session::qos (void) const
+{
+ return this->qos_;
+}
+
+// Overloaded method to set the QoS for this session object. Does not
+// interfere with the underlying socket QoS.
+ACE_INLINE void
+ACE_GQoS_Session::qos (const ACE_QoS &ace_qos)
+{
+ this->qos_ = ace_qos;
+}
+
+// Get the GQoS session id.
+ACE_INLINE int
+ACE_GQoS_Session::session_id (void) const
+{
+ return this->session_id_;
+}
+
+// Set the GQoS session id.
+ACE_INLINE void
+ACE_GQoS_Session::session_id (const int session_id)
+{
+ this->session_id_ = session_id;
+}
+
+// Get the underlying file desciptor for RSVP events.
+// Currently returns 0 because GQoS does not have a special
+// descriptor for QoS events.
+ACE_INLINE ACE_HANDLE
+ACE_GQoS_Session::rsvp_events_handle (void)
+{
+ return 0;
+}
+
+// Get the End Point Type (Sender/Receiver/Both).
+ACE_INLINE ACE_QoS_Session::ACE_End_Point_Type
+ACE_GQoS_Session::flags (void) const
+{
+ return this->flags_;
+}
+
+// Set the End Point Type (Sender/Receiver/Both).
+ACE_INLINE void
+ACE_GQoS_Session::flags (const ACE_End_Point_Type flags)
+{
+ this->flags_ = flags;
+}
+
+// Get the destination address for this GQoS session.
+ACE_INLINE ACE_INET_Addr
+ACE_GQoS_Session::dest_addr (void) const
+{
+ return this->dest_addr_;
+}
+
+// Set the destination address for this GQoS session.
+ACE_INLINE void
+ACE_GQoS_Session::dest_addr (const ACE_INET_Addr &dest_addr)
+{
+ this->dest_addr_ = dest_addr;
+}
+
+// Get the source port for this RAPI session.
+ACE_INLINE u_short
+ACE_GQoS_Session::source_port (void) const
+{
+ return this->source_port_;
+}
+
+// Set the source port for this RAPI session.
+ACE_INLINE void
+ACE_GQoS_Session::source_port (const u_short &source_port)
+{
+ this->source_port_ = source_port;
+}
+
+ACE_INLINE ACE_INET_Addr*
+ACE_GQoS_Session::source_addr (void) const
+{
+ return this->src_addr_;
+}
+
+ACE_INLINE void
+ACE_GQoS_Session::source_addr (ACE_INET_Addr* source_addr)
+{
+ this->src_addr_ = source_addr;
+}
+
+// GQoS version.
+ACE_INLINE int
+ACE_GQoS_Session::version (void)
+{
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/QoS/README b/ACE/ace/QoS/README
new file mode 100644
index 00000000000..4415bf1862b
--- /dev/null
+++ b/ACE/ace/QoS/README
@@ -0,0 +1,55 @@
+$Id$
+
+ACE QoS API (AQoSA)
+===================
+
+This directory contains the implementation for the ACE QoS API (AQoSA).
+
+BUILD REQUIREMENTS
+==================
+WIN2K :
+
+AQoSA makes use of the GQOS API under Windows 2000. The minimum
+requirements are:
+
+1. June98 Platform SDK or later.
+2. Link with ws2_32.lib
+
+More information about GQOS is available from the MSDN website:
+http://msdn.microsoft.com/msdn-files/026/002/258/Search.asp
+
+-------------------------------------------------------------------------------
+
+UNIX :
+
+AQoSA makes use of the RSVP API (RAPI) under UNIX.
+RAPI can be obtained from: ftp://ftp.isi.edu/rsvp/release/.
+rsvpd.rel4.2a4-1 may require patches in order to compile
+under current versions of Linux. Contact Craig Rodrigues <crodrigu@bbn.com>
+to obtain these patches.
+
+The following lines should be added to your platform_macros.GNU file
+before building AQoSA:
+
+PLATFORM_RAPI_CPPFLAGS += -I[path to RAPI header files]
+PLATFORM_RAPI_LIBS += -lrsvp
+PLATFORM_RAPI_LDFLAGS += -L[path to RAPI library files]
+
+1. Compile AQoSA with
+
+ make rapi=1
+
+More information about RAPI can be found at:
+
+http://www.opengroup.org/onlinepubs/9619099/toc.htm
+http://www.cs.wustl.edu/~vishal/qos.html
+http://www.sun.com/software/bandwidth/rsvp/docs/
+http://www.tru64unix.compaq.com/faqs/publications/base_doc/DOCUMENTATION/V51_HTML/ARH9UCTE/TOC.HTM#RSVPCHXX
+
+-------------------------------------------------------------------------------
+
+TEST
+====
+
+The test for AQoSA is located in $ACE_ROOT/examples/QOS
+
diff --git a/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.cpp b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.cpp
new file mode 100644
index 00000000000..1788a98ea82
--- /dev/null
+++ b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.cpp
@@ -0,0 +1,258 @@
+// $Id$
+
+#include "SOCK_Dgram_Mcast_QoS.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_socket.h"
+
+#if defined (ACE_WIN32)
+#include "ace/Sock_Connect.h" // needed for subscribe_ifs()
+#endif /* ACE_WIN32 */
+
+#if !defined (__ACE_INLINE__)
+#include "SOCK_Dgram_Mcast_QoS.inl"
+#endif /* __ACE_INLINE__ */
+
+// 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 (QoS,
+ SOCK_Dgram_Mcast_QoS,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Mcast_QoS)
+
+// Dummy default constructor...
+
+ACE_SOCK_Dgram_Mcast_QoS::ACE_SOCK_Dgram_Mcast_QoS (options opts)
+ : ACE_SOCK_Dgram_Mcast (opts)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::ACE_SOCK_Dgram_Mcast_QoS");
+}
+
+int
+ACE_SOCK_Dgram_Mcast_QoS::open (const ACE_INET_Addr &addr,
+ const ACE_QoS_Params &qos_params,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::open");
+
+ ACE_UNUSED_ARG (qos_params);
+
+ // Only perform the <open> initialization if we haven't been opened
+ // earlier.
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ return 0;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Get Handle Returns Invalid Handle\n"));
+
+ if (ACE_SOCK::open (SOCK_DGRAM,
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ return -1;
+
+ return this->open_i (addr, 0, reuse_addr);
+}
+
+
+int
+ACE_SOCK_Dgram_Mcast_QoS::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_QoS_Params &qos_params,
+ const ACE_TCHAR *net_if,
+ int protocol_family,
+ int protocol,
+ int reuse_addr,
+ ACE_Protocol_Info *protocolinfo)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::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_Sock_Connect::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_Sock_Connect::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,
+ qos_params,
+ reuse_addr,
+ ACE_TEXT ("0.0.0.0"),
+ protocol_family,
+ protocol,
+ protocolinfo) == 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].is_loopback())
+ continue;
+ if (this->subscribe (mcast_addr,
+ qos_params,
+ reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR
+ (if_addrs[if_cnt].get_host_addr()),
+ protocol_family,
+ protocol,
+ protocolinfo) == 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 (qos_params);
+ ACE_UNUSED_ARG (protocol_family);
+ ACE_UNUSED_ARG (protocol);
+ ACE_UNUSED_ARG (reuse_addr);
+ ACE_UNUSED_ARG (protocolinfo);
+#endif /* ACE_WIN32 */
+ // Otherwise, do it like everyone else...
+
+ // Create multicast request.
+ if (this->make_multicast_ifaddr (0,
+ mcast_addr,
+ net_if) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast_QoS::subscribe (const ACE_INET_Addr &mcast_addr,
+ const ACE_QoS_Params &qos_params,
+ int reuse_addr,
+ const ACE_TCHAR *net_if,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ ACE_QoS_Session *qos_session)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::subscribe");
+
+ if (this->open (mcast_addr,
+ qos_params,
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ return -1;
+
+ // The following method call only applies to Win32 currently.
+ int result = this->subscribe_ifs (mcast_addr,
+ qos_params,
+ net_if,
+ protocol_family,
+ protocol,
+ reuse_addr,
+ protocolinfo);
+ // Check for the "short-circuit" return value of 1 (for NT).
+ if (result != 0)
+ return result;
+
+ // Tell network device driver to read datagrams with a
+ // <mcast_request_if_> IP interface.
+ else
+ {
+ // Check if the mcast_addr passed into this method is the
+ // same as the QoS session address.
+ if (qos_session != 0 && mcast_addr == qos_session->dest_addr ())
+ {
+ // Subscribe to the QoS session.
+ if (this->qos_manager_.join_qos_session (qos_session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Unable to join QoS Session\n")),
+ -1);
+ }
+ else
+ {
+ if (this->close () != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Unable to close socket\n")));
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Dest Addr in the QoS Session does")
+ ACE_TEXT (" not match the address passed into")
+ ACE_TEXT (" subscribe\n")),
+ -1);
+ }
+
+ ip_mreq ret_mreq;
+ this->make_multicast_ifaddr (&ret_mreq, mcast_addr, net_if);
+
+ // XX This is windows stuff only. fredk
+ if (ACE_OS::join_leaf (this->get_handle (),
+ reinterpret_cast<const sockaddr *> (&ret_mreq.IMR_MULTIADDR.s_addr),
+ sizeof ret_mreq.IMR_MULTIADDR.s_addr,
+ qos_params) == ACE_INVALID_HANDLE
+ && errno != ENOTSUP)
+ return -1;
+
+ else
+ if (qos_params.socket_qos () != 0 && qos_session != 0)
+ qos_session->qos (*(qos_params.socket_qos ()));
+
+ return 0;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.h b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.h
new file mode 100644
index 00000000000..d397bb68e70
--- /dev/null
+++ b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.h
@@ -0,0 +1,142 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SOCK_Dgram_Mcast_QoS.h
+ *
+ * $Id$
+ *
+ * @author Vishal Kachroo <vishal@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SOCK_DGRAM_MCAST_QOS_H
+#define ACE_SOCK_DGRAM_MCAST_QOS_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "QoS_Manager.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SOCK_Dgram_Mcast_QoS
+ *
+ * @brief Defines the member functions for the ACE QoS enabled socket
+ * wrapper for UDP/IP multicast.
+ */
+class ACE_QoS_Export ACE_SOCK_Dgram_Mcast_QoS : public ACE_SOCK_Dgram_Mcast
+{
+
+public:
+ // = Initialization routines.
+ /// Ctor, has same defaults as ACE_SOCK_Dgram_Mcast
+ ACE_SOCK_Dgram_Mcast_QoS (options opts = DEFOPTS);
+
+ // 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.
+
+ /// Default dtor.
+ ~ACE_SOCK_Dgram_Mcast_QoS (void);
+
+ // = Multicast group management routines.
+ /**
+ * This is a QoS-enabled method for joining a multicast group, which
+ * passes <qos_params> via <ACE_OS::join_leaf>. 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 session object specifies the QoS
+ * session that the socket wants to subscribe to. A socket may
+ * subscribe to multiple QoS sessions by calling this method multiple
+ * times with different session objects.
+ *
+ * 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,
+ const ACE_QoS_Params &qos_params,
+ int reuse_addr = 1,
+ const ACE_TCHAR *net_if = 0,
+ int protocol_family = PF_INET,
+ int protocol = 0,
+ ACE_Protocol_Info *protocolinfo = 0,
+ ACE_SOCK_GROUP g = 0,
+ u_long flags = 0,
+ ACE_QoS_Session *qos_session = 0);
+
+ // = Data transfer routines.
+
+ /// Send <buffer_count> worth of @a buffers to @a 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;
+
+ /// Send an @a n byte @a 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;
+
+ /// Returns the QoS manager for this socket.
+ ACE_QoS_Manager qos_manager (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ int open (const ACE_INET_Addr &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);
+
+private:
+ // = Disable public <open> method to ensure class used properly.
+
+
+ /// Subscribe to the multicast interface using QoS-enabled semantics.
+ int subscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_QoS_Params &qos_params,
+ const ACE_TCHAR *net_if,
+ int protocol_family,
+ int protocol,
+ int reuse_addr,
+ ACE_Protocol_Info *protocolinfo);
+
+ /// Manages the QoS sessions that this socket subscribes to.
+ ACE_QoS_Manager qos_manager_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "SOCK_Dgram_Mcast_QoS.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_DGRAM_MCAST_QOS_H */
diff --git a/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.inl b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.inl
new file mode 100644
index 00000000000..9e2347669c5
--- /dev/null
+++ b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.inl
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SOCK_Dgram_Mcast_QoS::~ACE_SOCK_Dgram_Mcast_QoS (void)
+{
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_Dgram_Mcast_QoS::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_Mcast_QoS::send");
+
+ return ACE_SOCK_Dgram::send (buffers,
+ buffer_count,
+ number_of_bytes_sent,
+ flags,
+ addr,
+ overlapped,
+ func);
+
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_Dgram_Mcast_QoS::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_Mcast_QoS::send");
+
+ return ACE_SOCK_Dgram::send (buf,
+ n,
+ addr,
+ flags,
+ overlapped,
+ func);
+}
+
+ACE_INLINE ACE_QoS_Manager
+ACE_SOCK_Dgram_Mcast_QoS::qos_manager (void)
+{
+ return this->qos_manager_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/QoS/qos.mpc b/ACE/ace/QoS/qos.mpc
new file mode 100644
index 00000000000..9702c646049
--- /dev/null
+++ b/ACE/ace/QoS/qos.mpc
@@ -0,0 +1,17 @@
+// -*- MPC -*-
+// $Id$
+
+project(QoS) : acelib, ace_output, install {
+ requires += qos
+ sharedname = ACE_QoS
+ dynamicflags = ACE_QoS_BUILD_DLL
+ macros += ACE_HAS_QOS
+
+ specific(borland, bmake, nmake, em3, vc6, vc7, vc71, vc8, vc9) {
+ macros += ACE_HAS_WINSOCK2_GQOS
+ }
+
+ pkgconfig_files {
+ ACE_QoS.pc.in
+ }
+}
diff --git a/ACE/ace/QtReactor/ACE_QtReactor.pc.in b/ACE/ace/QtReactor/ACE_QtReactor.pc.in
new file mode 100644
index 00000000000..4e7aa83e6be
--- /dev/null
+++ b/ACE/ace/QtReactor/ACE_QtReactor.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE_QtReactor
+Description: ACE QtReactor Library
+Requires: ACE
+Version: @VERSION@
+Libs: -L${libdir} -lACE_QtReactor
+Cflags: -I${includedir}
diff --git a/ACE/ace/QtReactor/ACE_QtReactor_export.h b/ACE/ace/QtReactor/ACE_QtReactor_export.h
new file mode 100644
index 00000000000..f7192051a29
--- /dev/null
+++ b/ACE/ace/QtReactor/ACE_QtReactor_export.h
@@ -0,0 +1,58 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl -s ACE_QtReactor
+// ------------------------------
+#ifndef ACE_QTREACTOR_EXPORT_H
+#define ACE_QTREACTOR_EXPORT_H
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_QTREACTOR_HAS_DLL)
+# define ACE_QTREACTOR_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ACE_QTREACTOR_HAS_DLL */
+
+#if !defined (ACE_QTREACTOR_HAS_DLL)
+# define ACE_QTREACTOR_HAS_DLL 1
+#endif /* ! ACE_QTREACTOR_HAS_DLL */
+
+#if defined (ACE_QTREACTOR_HAS_DLL) && (ACE_QTREACTOR_HAS_DLL == 1)
+# if defined (ACE_QTREACTOR_BUILD_DLL)
+# define ACE_QtReactor_Export ACE_Proper_Export_Flag
+# define ACE_QTREACTOR_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define ACE_QTREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* ACE_QTREACTOR_BUILD_DLL */
+# define ACE_QtReactor_Export ACE_Proper_Import_Flag
+# define ACE_QTREACTOR_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define ACE_QTREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ACE_QTREACTOR_BUILD_DLL */
+#else /* ACE_QTREACTOR_HAS_DLL == 1 */
+# define ACE_QtReactor_Export
+# define ACE_QTREACTOR_SINGLETON_DECLARATION(T)
+# define ACE_QTREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* ACE_QTREACTOR_HAS_DLL == 1 */
+
+// Set ACE_QTREACTOR_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (ACE_QTREACTOR_NTRACE)
+# if (ACE_NTRACE == 1)
+# define ACE_QTREACTOR_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define ACE_QTREACTOR_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !ACE_QTREACTOR_NTRACE */
+
+#if (ACE_QTREACTOR_NTRACE == 1)
+# define ACE_QTREACTOR_TRACE(X)
+#else /* (ACE_QTREACTOR_NTRACE == 1) */
+# if !defined (ACE_HAS_TRACE)
+# define ACE_HAS_TRACE
+# endif /* ACE_HAS_TRACE */
+# define ACE_QTREACTOR_TRACE(X) ACE_TRACE_IMPL(X)
+# include "ace/Trace.h"
+#endif /* (ACE_QTREACTOR_NTRACE == 1) */
+
+#endif /* ACE_QTREACTOR_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/QtReactor/QtReactor.cpp b/ACE/ace/QtReactor/QtReactor.cpp
new file mode 100644
index 00000000000..5a80886174b
--- /dev/null
+++ b/ACE/ace/QtReactor/QtReactor.cpp
@@ -0,0 +1,644 @@
+//$Id$
+
+#include "ace/QtReactor/QtReactor.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_QtReactor)
+
+// Must be called with lock held
+
+ACE_QtReactor::ACE_QtReactor (QApplication *qapp ,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int disable_notify_pipe,
+ ACE_Reactor_Notify *notify,
+ int mask_signals,
+ int s_queue ):
+ ACE_Select_Reactor( sh, tq, disable_notify_pipe,
+ notify, mask_signals, s_queue),
+ qapp_(qapp),
+ qtime_ (0)
+{
+ reopen_notification_pipe();
+}
+
+// Must be called with lock held
+ACE_QtReactor::ACE_QtReactor (size_t size,
+ QApplication *qapp,
+ int restart,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int disable_notify_pipe,
+ ACE_Reactor_Notify *notify,
+ int mask_signals,
+ int s_queue):
+ ACE_Select_Reactor( size, restart, sh, tq,
+ disable_notify_pipe, notify, mask_signals,
+ s_queue ),
+ qapp_(qapp),
+ qtime_ (0)
+
+{
+ reopen_notification_pipe();
+}
+
+void ACE_QtReactor::reopen_notification_pipe( void)
+{
+ // 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)
+ if ( initialized_ )
+ {
+ 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)
+{
+ // iterate over QSocketNotifiers for read and release them
+ MAP::ITERATOR iter = this->read_notifier_.begin ();
+ MAP::ITERATOR iterEnd = this->read_notifier_.end ();
+ while( iter != iterEnd )
+ {
+ MAP::ENTRY &entry = *iter;
+ // QOBject destructor notifies qapplication (hopefully) on delete
+ delete entry.int_id_;
+ ++iter;
+ }
+
+ // iterate over QSocketNotifiers for write and release them
+ this->write_notifier_.begin ();
+ this->write_notifier_.end ();
+ while( iter != iterEnd )
+ {
+ MAP::ENTRY &entry = *iter;
+ // QOBject destructor notifies qapplication (hopefully) on delete
+ delete entry.int_id_;
+ ++iter;
+ }
+
+ // iterate over QSocketNotifiers for exceptions and release them
+ this->exception_notifier_.begin ();
+ this->exception_notifier_.end ();
+ while( iter != iterEnd )
+ {
+ MAP::ENTRY &entry = *iter;
+ // QOBject destructor notifies qapplication (hopefully) on delete
+ delete entry.int_id_;
+ ++iter;
+ }
+
+ // QOBject destructor notifies qapplication (hopefully) on delete
+ delete qtime_;
+}
+
+void
+ACE_QtReactor::qapplication (QApplication *qapp)
+{
+ // reparent QSocketNotifiers and QTimer
+ qapp_ = qapp ;
+}
+
+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 p_handle)
+{
+ ACE_TRACE ("ACE_QtReactor::read_event");
+
+ ACE_HANDLE handle = ACE_HANDLE( p_handle );
+
+#ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
+ // disable socket notifier to clear pending events
+ QSocketNotifier *qsock_notifier = 0;
+ if ( ( this->read_notifier_.find( handle,
+ qsock_notifier) != -1) )
+ qsock_notifier->setEnabled( false );
+#endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
+
+ // The core of read event handling
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ dispatch_set.rd_mask_.set_bit ( handle );
+ this->dispatch (1, dispatch_set);
+
+#ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
+ // enable socket notifier according to current mask
+ ACE_Reactor_Mask mask = 0;
+ mask = mask_ops( handle, mask, ACE_Reactor::GET_MASK );
+ if ( -1 != mask )
+ set_enable_flag_by_mask ( 1, handle, mask);
+#endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
+}
+
+void
+ACE_QtReactor::write_event (int p_handle)
+{
+ ACE_TRACE ("ACE_QtReactor::write_event");
+
+ ACE_HANDLE handle = ACE_HANDLE( p_handle );
+
+#ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
+ // disable socket notifier to clear pending events
+ QSocketNotifier *qsock_notifier = 0;
+ if ( ( this->write_notifier_.find( handle, qsock_notifier) != -1) )
+ qsock_notifier->setEnabled( false );
+#endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
+
+ // The core of write event handling
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ dispatch_set.wr_mask_.set_bit( handle );
+ this->dispatch (1, dispatch_set);
+
+#ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
+ // enable socket notifier according to current mask
+ ACE_Reactor_Mask mask = 0;
+ mask = mask_ops( handle, mask, ACE_Reactor::GET_MASK );
+ if ( -1 != mask )
+ set_enable_flag_by_mask ( 1, handle, mask);
+#endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
+}
+
+void
+ACE_QtReactor::exception_event (int p_handle)
+{
+ ACE_TRACE ("ACE_QtReactor::exception_event");
+
+ ACE_HANDLE handle = ACE_HANDLE( p_handle );
+
+
+#ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
+ // disable socket notifier to clear pending events
+ QSocketNotifier *qsock_notifier = 0;
+ if ( ( this->exception_notifier_.find( handle, qsock_notifier) != -1) )
+ qsock_notifier->setEnabled( false );
+#endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
+
+ // The core of exception event handling
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ dispatch_set.ex_mask_.set_bit( handle );
+ dispatch (1, dispatch_set);
+
+#ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
+ // enable socket notifier according to current mask
+ ACE_Reactor_Mask mask = 0;
+ mask = mask_ops( handle, mask, ACE_Reactor::GET_MASK );
+ if ( -1 != mask )
+ set_enable_flag_by_mask ( 1, handle, mask);
+#endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
+}
+
+int
+ACE_QtReactor::set_enable_flag_by_mask (int flag_value,
+ ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ QSocketNotifier *qs_not;
+
+ if (ACE_BIT_ENABLED(mask, ACE_Event_Handler::READ_MASK) ||
+ ACE_BIT_ENABLED( mask, ACE_Event_Handler::ACCEPT_MASK))
+ {
+ // Find the current notifier
+ qs_not = 0;
+ if ((this->read_notifier_.find (handle, qs_not) == -1))
+ return -1;
+
+ qs_not->setEnabled (flag_value);
+ }
+
+ 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))
+ {
+ qs_not = 0;
+ if ((this->write_notifier_.find (handle, qs_not) == -1))
+ return -1;
+
+ qs_not->setEnabled (flag_value);
+ }
+
+ if (ACE_BIT_ENABLED( mask,
+ ACE_Event_Handler::EXCEPT_MASK))
+ {
+ qs_not = 0;
+ if ((this->exception_notifier_.find (handle, qs_not) == -1))
+ return -1;
+
+ qs_not->setEnabled (flag_value);
+ }
+
+ return 0;
+}
+
+int
+ACE_QtReactor::bit_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Select_Reactor_Handle_Set &handle_set,
+ int ops)
+{
+ int result;
+ ACE_Select_Reactor_Handle_Set preserved_handle_set = handle_set;
+
+ // Call regular bit_ops
+ if ((result = ACE_Select_Reactor::bit_ops (handle, mask, handle_set, ops)) == -1)
+ return -1;
+
+ // disable or enable the notifiers based on handle_set and mask
+ int enableFlag = -1;
+ if (&handle_set == &this->suspend_set_)
+ enableFlag = 0;
+ else if (&handle_set == &this->wait_set_)
+ enableFlag = 1;
+ else
+ // We have no work to do here, so just return
+ return result;
+
+ switch (ops)
+ {
+ case ACE_Reactor::SET_MASK:
+ case ACE_Reactor::ADD_MASK:
+ // Enable or disable notifiers based on the specified masks
+ if (this->set_enable_flag_by_mask (enableFlag, handle, mask) == -1)
+ {
+ // We can't just return -1 here because we'll have half-changed things.
+ // So, we need to restore the old handle_set, then return -1.
+ handle_set = preserved_handle_set;
+ return -1;
+ }
+ break;
+
+ case ACE_Reactor::CLR_MASK:
+ if (this->set_enable_flag_by_mask (!enableFlag, handle, mask) == -1)
+ {
+ handle_set = preserved_handle_set;
+ return -1;
+ }
+ break;
+
+ default:
+ // we take no action for any other operations
+ break;
+ }
+
+ return result;
+}
+
+void
+ACE_QtReactor::create_notifiers_for_handle (ACE_HANDLE handle)
+{
+ QSocketNotifier *qsock_notifier = 0;
+
+ // if there is already a read socket notifier for this handle, do nothing
+ // otherwise create read notifier
+ if ( ( this->read_notifier_.find (handle,
+ qsock_notifier) == -1) )
+ {
+ ACE_NEW (qsock_notifier,
+ QSocketNotifier (int(handle), QSocketNotifier::Read, this));
+ this->read_notifier_.bind (handle,
+ qsock_notifier);
+ QObject::connect (qsock_notifier,
+ SIGNAL (activated (int)),
+ this,
+ SLOT (read_event (int))) ;
+ // disable; it will be enabled by the regular register_handler_i if
+ // necessary
+ qsock_notifier->setEnabled (0);
+ }
+
+ qsock_notifier = 0;
+
+
+ // if there is already a write socket notifier for this handle, do nothing
+ // otherwise create read notifier
+ if ((this->write_notifier_.find (handle,
+ qsock_notifier) == -1))
+ {
+ ACE_NEW (qsock_notifier,
+ QSocketNotifier (int(handle), QSocketNotifier::Write, this));
+
+ this->write_notifier_.bind (handle,
+ qsock_notifier);
+
+ QObject::connect (qsock_notifier,
+ SIGNAL (activated (int)),
+ this,
+ SLOT (write_event (int)));
+ // disable; it will be enabled by the regular register_handler_i if
+ // necessary
+ qsock_notifier->setEnabled (0);
+ }
+
+
+ qsock_notifier = 0;
+
+ // if there is already a write socket notifier for this handle, do nothing
+ // otherwise create read notifier
+ if ((this->exception_notifier_.find (handle,
+ qsock_notifier) == -1))
+ {
+
+ ACE_NEW (qsock_notifier,
+ QSocketNotifier (int(handle), QSocketNotifier::Exception, this));
+
+ this->exception_notifier_.bind (handle,
+ qsock_notifier);
+
+ QObject::connect (qsock_notifier,
+ SIGNAL (activated (int)),
+ this,
+ SLOT (exception_event (int))) ;
+ // disable; it will be enabled by the regular register_handler_i if
+ // necessary
+ qsock_notifier->setEnabled (0);
+ }
+}
+
+void
+ACE_QtReactor::destroy_notifiers_for_handle (ACE_HANDLE handle)
+{
+ QSocketNotifier *qsock_notifier = 0;
+
+ // Looks for the handle in the maps and removes them.
+
+ if ((this->read_notifier_.find (handle,
+ qsock_notifier) != -1))
+ {
+ this->read_notifier_.unbind (handle,
+ qsock_notifier);
+ delete qsock_notifier;
+ }
+
+ if ((this->write_notifier_.find (handle,
+ qsock_notifier) != -1))
+ {
+ this->write_notifier_.unbind (handle,
+ qsock_notifier);
+ delete qsock_notifier;
+ }
+
+
+ if ((this->exception_notifier_.find (handle,
+ qsock_notifier) != -1))
+ {
+ this->exception_notifier_.unbind (handle,
+ qsock_notifier);
+ delete qsock_notifier;
+ }
+}
+
+int
+ACE_QtReactor::register_handler_i (ACE_HANDLE handle ,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_QtReactor::register_handler_i");
+
+ this->create_notifiers_for_handle (handle);
+
+ int result;
+ if ((result = ACE_Select_Reactor::register_handler_i(handle,
+ handler,
+ mask ))
+ == -1)
+ {
+ // destroy notifiers only when there is no handler for handle
+ if ( !ACE_Select_Reactor::find_handler( handle ) )
+ this->destroy_notifiers_for_handle (handle);
+ return -1;
+ }
+
+ 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");
+
+ int result = ACE_Select_Reactor::remove_handler_i (handle, mask);
+ // destroy notifiers only when there is no handler for handle
+ if ( !ACE_Select_Reactor::find_handler( handle ) )
+ this->destroy_notifiers_for_handle (handle);
+ return result;
+}
+
+
+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 ()));
+
+#if QT_VERSION >= 0x040000
+ qtime_->setSingleShot (1);
+ qtime_->start(max_wait_time->msec());
+#else
+ qtime_->start(max_wait_time->msec(), 1);
+#endif
+ }
+
+}
+
+
+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 ;
+ }
+}
+
+// mbrudka: who needs QtWaitForMultipleEvents? It seems it's cargo load now!
+int
+ACE_QtReactor::QtWaitForMultipleEvents (int width,
+ ACE_Select_Reactor_Handle_Set &wait_set,
+ ACE_Time_Value * /*max_wait_time*/)
+{
+ // Keep a copy of the wait set in case the wait_set be changed
+ // between the two select calls in this function. It could happen
+ // while waiting for an event, another event is handled and dispatched
+ // which changes the dispatch_set_/wait_set.
+ ACE_Select_Reactor_Handle_Set orig_wait_set = wait_set;
+
+ // 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.
+#if QT_VERSION >= 0x040000
+ this->qapp_->processEvents();
+#else
+ this->qapp_->processOneEvent ();
+#endif
+
+ // 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,
+ orig_wait_set.rd_mask_,
+ orig_wait_set.wr_mask_,
+ orig_wait_set.ex_mask_,
+ (ACE_Time_Value *) &ACE_Time_Value::zero);
+}
+
+// mbrudka: who needs wait_for_multiple_events? It seems it's cargo load now!
+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
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/QtReactor/QtReactor.h b/ACE/ace/QtReactor/QtReactor.h
new file mode 100644
index 00000000000..279516e38e6
--- /dev/null
+++ b/ACE/ace/QtReactor/QtReactor.h
@@ -0,0 +1,231 @@
+// -*- 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/QtReactor/ACE_QtReactor_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Select_Reactor.h"
+#include "ace/Map_Manager.h"
+
+#include "qglobal.h"
+
+// QT toolkit specific includes.
+#if QT_VERSION >= 0x040000
+#include /**/ <QtGui/QApplication>
+#include /**/ <QtCore/QObject>
+#include /**/ <QtCore/QSocketNotifier.h>
+#include /**/ <QtCore/QTimer.h>
+#else
+#include /**/ <qapplication.h>
+#include /**/ <qobject.h>
+#include /**/ <qsocketnotifier.h>
+#include /**/ <qtimer.h>
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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.
+ *
+ * \note Marek Brudka <mbrudka@elka.pw.edu.pl>: ACE_QtReactor was
+ * quickly bugfixed to meet ACE 5.4.2 (6.0.0?) deadline.
+ * While it passes QtReactor_Test now, there is a great
+ * room for improvements as the implementation is rather inefficient
+ * and obfuscated
+ * To be more specific:
+ * - reset_timeout always creates and removes qtimer after each
+ * timeout event! Obviously, for fast triggering timers this may
+ * lead to excessive memory management.
+ * - create/destroy_notifiers_for_handle may also be reworked to
+ * establish more clean relations between handles and QSocketNotifiers.
+ * - read/write_exception_event disable now SocketNotifier for a while
+ * to clear pending events. The cost of this operation is high: two hash
+ * acces in ACE and at least two next ones in Qt. This makes QtReator slow,
+ * but how clear pending events another way ?
+ * - there is qapplication() mutator, which sets new qapplication for
+ * QtReactor. This mutator violates implicit assumption about the
+ * relations between QTimer and QSocketNotifiers and QApplication for
+ * this reactor, namely one may expect that after qapplication(), none
+ * of QtReactor artifacts is bound to old qapplication. That's not true
+ * now, as QTimer and QSocketNotifiers are not reparent to new
+ * QApplication. As a result, the sequence:
+ * QApplication *old_qapp = new QApplication(..);
+ * QtReactor qreactor( old_qapp);
+ * // .. register handlers, schedule_timers etc
+ * QApplication *new_qapp = new QApplication(..);
+ * qreactor.qpplication( new_qapp );
+ * delete old_qapp;
+ * almost always leads to problems and memory violation, because
+ * QSocketNotifiers are released by old_qapp. Therefore QtReactor
+ * should not be reparent now by setting new qapplication.
+ * - the lifecycle of Qt objects in ACE contects is rather mysterious
+ * and should be made more explicit.
+ * - valgrind reports a small memory leak in QtReactor_Test, though as for now
+ * it is not clear if the leak is introduced by QtReactor, or rather incorrect
+ * memory management in QtReactor_Test.
+ */
+class ACE_QtReactor_Export ACE_QtReactor
+ : public QObject,
+ public ACE_Select_Reactor
+{
+
+ Q_OBJECT
+
+public:
+ /** \brief Constructor follows @ACE_Select_Reactor
+ \param QApplication *qapp, qapplication which runs events loop
+ */
+ ACE_QtReactor (QApplication *qapp = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = 0,
+ ACE_Reactor_Notify *notify = 0,
+ int mask_signals = 1,
+ int s_queue = ACE_SELECT_TOKEN::FIFO);
+
+ /** \brief Constructor follows @ACE_Select_Reactor
+ \param QApplication *qapp, qapplication which runs events loop
+ */
+ ACE_QtReactor (size_t size,
+ QApplication *qapp = 0,
+ 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,
+ int s_queue = ACE_SELECT_TOKEN::FIFO);
+
+ 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 @a 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 @a 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);
+
+ virtual int bit_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Select_Reactor_Handle_Set &handle_set,
+ int ops);
+
+ int set_enable_flag_by_mask (int flag_value, ACE_HANDLE handle, ACE_Reactor_Mask mask);
+ void create_notifiers_for_handle (ACE_HANDLE handle);
+ void destroy_notifiers_for_handle (ACE_HANDLE handle);
+
+ // 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);
+ /// reopens notification pipe to create SocketNotifier for it
+ void reopen_notification_pipe(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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_QTREACTOR_H */
diff --git a/ACE/ace/RB_Tree.cpp b/ACE/ace/RB_Tree.cpp
new file mode 100644
index 00000000000..91cefa0f037
--- /dev/null
+++ b/ACE/ace/RB_Tree.cpp
@@ -0,0 +1,1204 @@
+// $Id$
+
+#ifndef ACE_RB_TREE_CPP
+#define ACE_RB_TREE_CPP
+
+#include "ace/Global_Macros.h"
+#include "ace/RB_Tree.h"
+#include "ace/SString.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/RB_Tree.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Constructor.
+
+template <class EXT_ID, class INT_ID>
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::ACE_RB_Tree_Node (const EXT_ID &k, const INT_ID &t)
+ : k_ (k),
+ t_ (t),
+ color_ (RED),
+ parent_ (0),
+ left_ (0),
+ right_ (0)
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::ACE_RB_Tree_Node (const EXT_ID &k, const INT_ID &t)");
+}
+
+
+// Destructor.
+
+template <class EXT_ID, class INT_ID>
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::~ACE_RB_Tree_Node (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::~ACE_RB_Tree_Node");
+}
+
+// Constructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (ACE_Allocator *alloc)
+ : root_ (0),
+ current_size_ (0)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::"
+ "ACE_RB_Tree (ACE_Allocator *alloc)");
+ allocator_ = alloc;
+ if (this->open (alloc) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_RB_Tree::ACE_RB_Tree\n")));
+}
+
+// Copy constructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt)
+ : root_ (0),
+ current_size_ (0)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::"
+ "ACE_RB_Tree (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt)");
+ ACE_WRITE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+ allocator_ = rbt.allocator_;
+
+ // Make a deep copy of the passed tree.
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> iter(rbt);
+
+ for (iter.first ();
+
+ iter.is_done () == 0; iter.next ())
+ insert_i (*(iter.key ()),
+ *(iter.item ()));
+}
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (
+ void *location,
+ ACE_Allocator *alloc
+)
+{
+ if (location != this)
+ {
+ this->root_ = 0;
+ this->current_size_ = 0;
+ }
+
+ this->allocator_ = alloc;
+}
+// Destructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree ()
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree");
+
+ // Use the locked public method, to be totally safe, as the class
+ // can be used with an allocator and placement new.
+ this->close ();
+}
+
+// Assignment operator.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator = (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator =");
+ ACE_WRITE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ if (this != &rbt)
+ {
+ // Clear out the existing tree.
+ close_i ();
+
+ // Make a deep copy of the passed tree.
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> iter(rbt);
+
+ for (iter.first ();
+ iter.is_done () == 0;
+ iter.next ())
+ insert_i (*(iter.key ()),
+ *(iter.item ()));
+
+ // Use the same allocator as the rhs.
+ allocator_ = rbt.allocator_;
+ }
+}
+// Less than comparison function for keys, default functor
+// implementation returns 1 if k1 < k2, 0 otherwise.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::lessthan (const EXT_ID &k1, const EXT_ID &k2)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::lessthan");
+ return this->compare_keys_ (k1, k2);
+}
+
+// Method for right rotation of the tree about a given node.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_right (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_right");
+
+ if (!x)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nerror: x is a null pointer in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_right\n")));
+ else if (! (x->left()))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nerror: x->left () is a null pointer in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_right\n")));
+ else
+ {
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> * y;
+ y = x->left ();
+ x->left (y->right ());
+ if (y->right ())
+ y->right ()->parent (x);
+ y->parent (x->parent ());
+ if (x->parent ())
+ {
+ if (x == x->parent ()->right ())
+ x->parent ()->right (y);
+ else
+ x->parent ()->left (y);
+ }
+ else
+ root_ = y;
+ y->right (x);
+ x->parent (y);
+ }
+}
+
+// Method for left rotation of the tree about a given node.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_left (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_left");
+
+ if (! x)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nerror: x is a null pointer in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_left\n")));
+ else if (! (x->right()))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nerror: x->right () is a null pointer ")
+ ACE_TEXT ("in ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_left\n")));
+ else
+ {
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> * y;
+ y = x->right ();
+ x->right (y->left ());
+ if (y->left ())
+ y->left ()->parent (x);
+ y->parent (x->parent ());
+ if (x->parent ())
+ {
+ if (x == x->parent ()->left ())
+ x->parent ()->left (y);
+ else
+ x->parent ()->right (y);
+ }
+ else
+ root_ = y;
+ y->left (x);
+ x->parent (y);
+ }
+}
+
+// Method for restoring Red-Black properties after a specific deletion case.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::
+RB_delete_fixup (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_delete_fixup");
+
+ while (x != this->root_
+ && (!x
+ || x->color () == ACE_RB_Tree_Node_Base::BLACK))
+ {
+ if (x == parent->left ())
+ {
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *w = parent->right ();
+ if (w && w->color () == ACE_RB_Tree_Node_Base::RED)
+ {
+ w->color (ACE_RB_Tree_Node_Base::BLACK);
+ parent->color (ACE_RB_Tree_Node_Base::RED);
+ RB_rotate_left (parent);
+ w = parent->right ();
+ }
+ // CLR pp. 263 says that nil nodes are implicitly colored BLACK
+ if (w
+ && (!w->left ()
+ || w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK)
+ && (!w->right ()
+ || w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK))
+ {
+ w->color (ACE_RB_Tree_Node_Base::RED);
+ x = parent;
+ parent = x->parent ();
+ }
+ else
+ {
+ // CLR pp. 263 says that nil nodes are implicitly colored BLACK
+ if (w
+ && (!w->right ()
+ || w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK))
+ {
+ if (w->left ())
+ w->left ()->color (ACE_RB_Tree_Node_Base::BLACK);
+ w->color (ACE_RB_Tree_Node_Base::RED);
+ RB_rotate_right (w);
+ w = parent->right ();
+ }
+ if (w)
+ {
+ w->color (parent->color ());
+ if (w->right ())
+ w->right ()->color (ACE_RB_Tree_Node_Base::BLACK);
+ }
+ parent->color (ACE_RB_Tree_Node_Base::BLACK);
+ RB_rotate_left (parent);
+ x = root_;
+ }
+ }
+ else
+ {
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *w = parent->left ();
+ if (w && w->color () == ACE_RB_Tree_Node_Base::RED)
+ {
+ w->color (ACE_RB_Tree_Node_Base::BLACK);
+ parent->color (ACE_RB_Tree_Node_Base::RED);
+ RB_rotate_right (parent);
+ w = parent->left ();
+ }
+ // CLR pp. 263 says that nil nodes are implicitly colored BLACK
+ if (w
+ && (!w->left ()
+ || w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK)
+ && (!w->right ()
+ || w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK))
+ {
+ w->color (ACE_RB_Tree_Node_Base::RED);
+ x = parent;
+ parent = x->parent ();
+ }
+ else
+ {
+ // CLR pp. 263 says that nil nodes are implicitly colored BLACK
+ if (w
+ && (!w->left ()
+ || w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK))
+ {
+ w->color (ACE_RB_Tree_Node_Base::RED);
+ if (w->right ())
+ w->right ()->color (ACE_RB_Tree_Node_Base::BLACK);
+ RB_rotate_left (w);
+ w = parent->left ();
+ }
+ if (w)
+ {
+ w->color (parent->color ());
+ if (w->left ())
+ w->left ()->color (ACE_RB_Tree_Node_Base::BLACK);
+ }
+ parent->color (ACE_RB_Tree_Node_Base::BLACK);
+ RB_rotate_right (parent);
+ x = root_;
+ }
+ }
+ }
+
+ if (x)
+ x->color (ACE_RB_Tree_Node_Base::BLACK);
+}
+
+// Return a pointer to a matching node if there is one, a pointer to
+// the node under which to insert the item if the tree is not empty
+// and there is no such match, or 0 if the tree is empty.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_node (const EXT_ID &k, ACE_RB_Tree_Base::RB_SearchResult &result)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_node");
+
+ // Start at the root.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = root_;
+
+ while (current)
+ {
+ // While there are more nodes to examine.
+ if (this->lessthan (current->key (), k))
+ {
+ // If the search key is greater than the current node's key.
+ if (current->right ())
+ // If the right subtree is not empty, search to the right.
+ current = current->right ();
+ else
+ {
+ // If the right subtree is empty, we're done searching,
+ // and are positioned to the left of the insertion point.
+ result = LEFT;
+ break;
+ }
+ }
+ else if (this->lessthan (k, current->key ()))
+ {
+ // Else if the search key is less than the current node's key.
+ if (current->left ())
+ // If the left subtree is not empty, search to the left.
+ current = current->left ();
+ else
+ {
+ // If the left subtree is empty, we're done searching,
+ // and are positioned to the right of the insertion point.
+ result = RIGHT;
+ break;
+ }
+ }
+ else
+ {
+ // If the keys match exactly, we're done as well.
+ result = EXACT;
+ break;
+ }
+ }
+
+ return current;
+}
+
+// Rebalance the tree after insertion of a node.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rebalance (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rebalance");
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *y = 0;
+
+ while (x &&
+ x->parent ()
+ && x->parent ()->color () == ACE_RB_Tree_Node_Base::RED)
+ {
+ if (! x->parent ()->parent ())
+ {
+ // If we got here, something is drastically wrong!
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nerror: parent's parent is null in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rebalance\n")));
+ return;
+ }
+
+ if (x->parent () == x->parent ()->parent ()->left ())
+ {
+ y = x->parent ()->parent ()->right ();
+ if (y && y->color () == ACE_RB_Tree_Node_Base::RED)
+ {
+ // Handle case 1 (see CLR book, pp. 269).
+ x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK);
+ y->color (ACE_RB_Tree_Node_Base::BLACK);
+ x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED);
+ x = x->parent ()->parent ();
+ }
+ else
+ {
+ if (x == x->parent ()->right ())
+ {
+ // Transform case 2 into case 3 (see CLR book, pp. 269).
+ x = x->parent ();
+ RB_rotate_left (x);
+ }
+
+ // Handle case 3 (see CLR book, pp. 269).
+ x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK);
+ x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED);
+ RB_rotate_right (x->parent ()->parent ());
+ }
+ }
+ else
+ {
+ y = x->parent ()->parent ()->left ();
+ if (y && y->color () == ACE_RB_Tree_Node_Base::RED)
+ {
+ // Handle case 1 (see CLR book, pp. 269).
+ x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK);
+ y->color (ACE_RB_Tree_Node_Base::BLACK);
+ x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED);
+ x = x->parent ()->parent ();
+ }
+ else
+ {
+ if (x == x->parent ()->left ())
+ {
+ // Transform case 2 into case 3 (see CLR book, pp. 269).
+ x = x->parent ();
+ RB_rotate_right (x);
+ }
+
+ // Handle case 3 (see CLR book, pp. 269).
+ x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK);
+ x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED);
+ RB_rotate_left (x->parent ()->parent ());
+ }
+ }
+ }
+}
+
+// Method to find the successor node of the given node in the tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_successor (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_successor");
+
+ if (x == 0)
+ return 0;
+
+ if (x->right ())
+ return RB_tree_minimum (x->right ());
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *y = x->parent ();
+ while ((y) && (x == y->right ()))
+ {
+ x = y;
+ y = y->parent ();
+ }
+
+ return y;
+}
+
+// Method to find the predecessor node of the given node in the tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_predecessor (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_predecessor");
+ if (x == 0)
+ return 0;
+
+ if (x->left ())
+ return RB_tree_maximum (x->left ());
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *y = x->parent ();
+
+ while ((y) && (x == y->left ()))
+ {
+ x = y;
+ y = y->parent ();
+ }
+
+ return y;
+}
+
+// Method to find the minimum node of the subtree rooted at the given node.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_minimum (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_minimum");
+
+ while ((x) && (x->left ()))
+ x = x->left ();
+
+ return x;
+}
+
+// Method to find the maximum node of the subtree rooted at the given node.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_maximum (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_maximum");
+
+ while ((x) && (x->right ()))
+ x = x->right ();
+
+ return x;
+}
+
+// Delete children (left and right) of the node. Must be called with
+// lock held.
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+void ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::delete_children_i
+ (ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent)
+{
+ if (parent)
+ {
+ this->delete_children_i (parent->left ());
+ this->delete_children_i (parent->right ());
+ ACE_DES_FREE_TEMPLATE2
+ (parent->left (),
+ this->allocator_->free,
+ ACE_RB_Tree_Node,
+ EXT_ID, INT_ID);
+ ACE_DES_FREE_TEMPLATE2
+ (parent->right (),
+ this->allocator_->free,
+ ACE_RB_Tree_Node,
+ EXT_ID, INT_ID);
+ parent->left (0);
+ parent->right (0);
+ }
+ return;
+}
+
+// Close down an RB_Tree. this method should only be called with
+// locks already held.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::close_i ()
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::close_i");
+
+ this->delete_children_i (this->root_);
+ ACE_DES_FREE_TEMPLATE2 (this->root_,
+ this->allocator()->free,
+ ACE_RB_Tree_Node,
+ EXT_ID, INT_ID);
+ this->current_size_ = 0;
+ this->root_ = 0;
+ return 0;
+}
+
+// Returns a pointer to the item corresponding to the given key, or 0
+// if it cannot find the key in the tree. This method should only be
+// called with locks already held.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &k,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID>* &entry, int find_exact)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_i");
+
+ // Try to find a match.
+ RB_SearchResult result = LEFT;
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = find_node (k, result);
+
+ if (current)
+ {
+ // Found a match
+ if (!find_exact || result == EXACT)
+ entry = current; // Assign the entry for any match.
+ return (result == EXACT ? 0 : -1);
+ }
+ else
+ // The node is not there.
+ return -1;
+}
+
+// Inserts a *copy* of the key and the item into the tree: both the
+// key type EXT_ID and the item type INT_ID must have well defined
+// semantics for copy construction and < comparison. This method
+// returns a pointer to the inserted item copy, or 0 if an error
+// occurred. NOTE: if an identical key already exists in the tree, no
+// new item is created, and the returned pointer addresses the
+// existing item associated with the existing key. This method should
+// only be called with locks already held.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> INT_ID *
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k, const INT_ID &t)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k, const INT_ID &t)");
+
+ // Find the closest matching node, if there is one.
+ RB_SearchResult result = LEFT;
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = find_node (k, result);
+ if (current)
+ {
+ // If the keys match, just return a pointer to the node's item.
+ if (result == EXACT)
+ return &current->item ();
+
+ // Otherwise if we're to the left of the insertion point, insert
+ // into the right subtree.
+ else if (result == LEFT)
+ {
+ if (current->right ())
+ {
+ // If there is already a right subtree, complain.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nright subtree already present in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
+ 0);
+ }
+ else
+ {
+ // The right subtree is empty: insert new node there.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0;
+
+ ACE_NEW_MALLOC_RETURN
+ (tmp,
+ (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
+ (this->allocator_->malloc (sizeof (*tmp)))),
+ (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
+ 0);
+ current->right (tmp);
+
+ // If the node was successfully inserted, set its
+ // parent, rebalance the tree, color the root black, and
+ // return a pointer to the inserted item.
+ INT_ID *item = &(current->right ()->item ());
+ current->right ()->parent (current);
+ RB_rebalance (current->right ());
+ root_->color (ACE_RB_Tree_Node_Base::BLACK);
+ ++current_size_;
+ return item;
+ }
+ }
+ // Otherwise, we're to the right of the insertion point, so
+ // insert into the left subtree.
+ else // (result == RIGHT)
+ {
+ if (current->left ())
+ // If there is already a left subtree, complain.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nleft subtree already present in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
+ 0);
+ else
+ {
+ // The left subtree is empty: insert new node there.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0;
+ ACE_NEW_MALLOC_RETURN
+ (tmp,
+ (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
+ (this->allocator_->malloc (sizeof (*tmp)))),
+ (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
+ 0);
+ current->left (tmp);
+
+ // If the node was successfully inserted, set its
+ // parent, rebalance the tree, color the root black, and
+ // return a pointer to the inserted item.
+ INT_ID *item = &current->left ()->item ();
+ current->left ()->parent (current);
+ RB_rebalance (current->left ());
+ root_->color (ACE_RB_Tree_Node_Base::BLACK);
+ ++current_size_;
+ return item;
+ }
+ }
+ }
+ else
+ {
+ // The tree is empty: insert at the root and color the root
+ // black.
+ ACE_NEW_MALLOC_RETURN
+ (this->root_,
+ (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
+ (this->allocator_->malloc (sizeof (ACE_RB_Tree_Node<EXT_ID, INT_ID>)))),
+ (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
+ 0);
+ this->root_->color (ACE_RB_Tree_Node_Base::BLACK);
+ ++current_size_;
+ return &this->root_->item ();
+ }
+}
+
+// Inserts a *copy* of the key and the item into the tree: both the
+// key type EXT_ID and the item type INT_ID must have well defined
+// semantics for copy construction. The default implementation also
+// requires that the key type support well defined < semantics. This
+// method passes back a pointer to the inserted (or existing) node,
+// and the search status. If the node already exists, the method
+// returns 1. If the node does not exist, and a new one is
+// successfully created, and the method returns 0. If there was an
+// error, the method returns -1.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k,
+ const INT_ID &t,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k, const INT_ID &t, "
+ "ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)");
+
+ // Find the closest matching node, if there is one.
+ RB_SearchResult result = LEFT;
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = find_node (k, result);
+ if (current)
+ {
+ // If the keys match, just return a pointer to the node's item.
+ if (result == EXACT)
+ {
+ entry = current;
+ return 1;
+ }
+ // Otherwise if we're to the left of the insertion
+ // point, insert into the right subtree.
+ else if (result == LEFT)
+ {
+ if (current->right ())
+ {
+ // If there is already a right subtree, complain.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nright subtree already present in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
+ -1);
+ }
+ else
+ {
+ // The right subtree is empty: insert new node there.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0;
+ ACE_NEW_MALLOC_RETURN
+ (tmp,
+ (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
+ (this->allocator_->malloc (sizeof (*tmp)))),
+ (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
+ -1);
+ current->right (tmp);
+
+ // If the node was successfully inserted, set its parent, rebalance
+ // the tree, color the root black, and return a pointer to the
+ // inserted item.
+ entry = current->right ();
+ current->right ()->parent (current);
+ RB_rebalance (current->right ());
+ this->root_->color (ACE_RB_Tree_Node_Base::BLACK);
+ ++this->current_size_;
+ return 0;
+ }
+ }
+ // Otherwise, we're to the right of the insertion point, so
+ // insert into the left subtree.
+ else // (result == RIGHT)
+ {
+ if (current->left ())
+ // If there is already a left subtree, complain.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nleft subtree already present in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
+ -1);
+ else
+ {
+ // The left subtree is empty: insert new node there.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0;
+ ACE_NEW_MALLOC_RETURN
+ (tmp,
+ (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
+ (this->allocator_->malloc (sizeof (*tmp)))),
+ (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
+ -1);
+ current->left (tmp);
+ // If the node was successfully inserted, set its
+ // parent, rebalance the tree, color the root black, and
+ // return a pointer to the inserted item.
+ entry = current->left ();
+ current->left ()->parent (current);
+ RB_rebalance (current->left ());
+ this->root_->color (ACE_RB_Tree_Node_Base::BLACK);
+ ++this->current_size_;
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ // The tree is empty: insert at the root and color the root black.
+ ACE_NEW_MALLOC_RETURN
+ (this->root_,
+ (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
+ (this->allocator_->malloc (sizeof (ACE_RB_Tree_Node<EXT_ID, INT_ID>)))),
+ (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
+ -1);
+ this->root_->color (ACE_RB_Tree_Node_Base::BLACK);
+ ++this->current_size_;
+ entry = this->root_;
+ return 0;
+ }
+}
+
+// Removes the item associated with the given key from the tree and
+// destroys it. Returns 1 if it found the item and successfully
+// destroyed it, 0 if it did not find the item, or -1 if an error
+// occurred. This method should only be called with locks already
+// held.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (const EXT_ID &k, INT_ID &i)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (const EXT_ID &k, INT_ID &i)");
+
+ // Find a matching node, if there is one.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *z;
+ RB_SearchResult result = LEFT;
+ z = find_node (k, result);
+
+ // If there is a matching node: remove and destroy it.
+ if (z && result == EXACT)
+ {
+ // Return the internal id stored in the deleted node.
+ i = z->item ();
+ return -1 == this->remove_i (z) ? -1 : 1;
+ }
+
+ // No matching node was found: return 0.
+ return 0;
+}
+
+/// Recursive function to dump the state of an object.
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::
+dump_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *node) const
+{
+#if defined (ACE_HAS_DUMP)
+ if (node)
+ {
+ dump_node_i (*node);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ndown left\n")));
+ this->dump_i (node->left ());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nup left\n")));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ndown right\n")));
+ this->dump_i (node->right ());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nup right\n")));
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nNULL POINTER (BLACK)\n")));
+ }
+#else /* !ACE_HAS_DUMP */
+ ACE_UNUSED_ARG (node);
+#endif /* ACE_HAS_DUMP */
+}
+
+/// Function to dump node itself. Does not show parameterized node contents
+/// in its basic form, but template specialization can be used to
+/// provide definitions for various EXT_ID and INT_ID types.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::
+dump_node_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> &node) const
+{
+#if defined (ACE_HAS_DUMP)
+ const char * color_str = (node.color () == ACE_RB_Tree_Node_Base::RED)
+ ? "RED" : "BLACK";
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" color=[%s]\n"), color_str));
+#else /* !ACE_HAS_DUMP */
+ ACE_UNUSED_ARG (node);
+#endif /* ACE_HAS_DUMP */
+}
+
+/// Tests the red-black invariant(s) throughout the whole tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant (void)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ // Recurse from the root, starting with the measured black height at
+ // 0, and the expected black height at -1, which will cause the
+ // count from first measured path to a leaf to be used as the
+ // expected one from that point onward (the key is to check
+ // consistency).
+ int expected_black_height = -1;
+ if (this->test_invariant_recurse (this->root_, expected_black_height, 0) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("invariant holds\n")));
+ return 0;
+ }
+
+ return -1;
+}
+
+/// Recursive function to test the red-black invariant(s) at all nodes in a subtree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant_recurse (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x,
+ int & expected_black_height,
+ int measured_black_height)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant_recurse");
+
+ if (!x)
+ {
+ // Count each leaf (zero pointer) as a black node (per CLR algorithm description).
+ ++measured_black_height;
+
+ if (expected_black_height == -1)
+ {
+ expected_black_height = measured_black_height;
+ }
+ else if (expected_black_height != measured_black_height)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("\nexpected_black_height = %d but ")
+ ACE_TEXT ("\nmeasured_black_height = %d in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n"),
+ expected_black_height, measured_black_height),
+ -1);
+ }
+
+ return 0;
+ }
+
+ // Check the invariant that a red node cannot have a red child.
+ if (x->color () == ACE_RB_Tree_Node_Base::RED)
+ {
+ if (x->left () && x->left ()->color () == ACE_RB_Tree_Node_Base::RED)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nRED parent has RED left child in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n")),
+ -1);
+ }
+
+ if (x->right () && x->right ()->color () == ACE_RB_Tree_Node_Base::RED)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("\nRED parent has RED right child in ")
+ ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n")),
+ -1);
+ }
+ }
+ else
+ {
+ // Count each black node traversed.
+ ++measured_black_height;
+ }
+
+ return (test_invariant_recurse (x->left (), expected_black_height, measured_black_height) == 0)
+ ? test_invariant_recurse (x->right (), expected_black_height, measured_black_height)
+ : -1;
+}
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z)");
+
+ // Delete the node and reorganize the tree to satisfy the Red-Black
+ // properties.
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *x;
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *y;
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent;
+
+ if (z->left () && z->right ())
+ y = RB_tree_successor (z);
+ else
+ y = z;
+
+ if (!y)
+ return -1;
+
+ if (y->left ())
+ x = y->left ();
+ else
+ x = y->right ();
+
+ parent = y->parent ();
+ if (x)
+ {
+ x->parent (parent);
+ }
+
+ if (parent)
+ {
+ if (y == parent->left ())
+ parent->left (x);
+ else
+ parent->right (x);
+ }
+ else
+ this->root_ = x;
+
+ if (y != z)
+ {
+ // Copy the elements of y into z.
+ z->key () = y->key ();
+ z->item () = y->item ();
+ }
+
+ // CLR pp. 263 says that nil nodes are implicitly colored BLACK
+ if (!y || y->color () == ACE_RB_Tree_Node_Base::BLACK)
+ RB_delete_fixup (x, parent);
+
+ y->parent (0);
+ y->right (0);
+ y->left (0);
+ ACE_DES_FREE_TEMPLATE2 (y,
+ this->allocator_->free,
+ ACE_RB_Tree_Node,
+ EXT_ID, INT_ID);
+ --this->current_size_;
+
+ return 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Iterator_Base)
+
+// Constructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, int set_first)
+ : tree_ (&tree), node_ (0)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (ACE_RB_Tree, int)");
+
+ // Position the iterator at the first (or last) node in the tree.
+ if (set_first)
+ node_ = tree_->RB_tree_minimum (tree_->root_);
+ else
+ node_ = tree_->RB_tree_maximum (tree_->root_);
+}
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry)
+ : tree_ (&tree), node_ (0)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base(const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry)");
+ node_ = entry;
+}
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (const EXT_ID& key,ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree)
+ : tree_ (&tree), node_ (0)
+{
+ ACE_TRACE("ACE_RB_Tree_Iterator_Base (ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, const EXT_ID& key)");
+ ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry = 0;
+ tree.find_i(key, entry);
+ node_ = entry;
+}
+
+// Copy constructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &iter)
+ : tree_ (iter.tree_),
+ node_ (iter.node_)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (ACE_RB_Tree_Iterator_Base)");
+}
+
+// Assignment operator.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator= (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &iter)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator=");
+ if (this != &iter)
+ {
+ tree_ = iter.tree_;
+ node_ = iter.node_;
+ }
+}
+
+// Destructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator_Base ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator_Base");
+}
+
+// Dump the state of an object.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+void
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump_i (void) const
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump_i");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnode_ = %x\n"), this->node_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+
+ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Iterator)
+
+// Constructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
+ int set_first)
+ : ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (tree, set_first)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
+}
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry)
+ : ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (tree,entry)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
+}
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator (const EXT_ID& key,ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree)
+ : ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>(key,tree)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
+}
+
+// Destructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator");
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Reverse_Iterator)
+
+// Constructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, int set_last)
+ : ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (tree, set_last ? 0 : 1)
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
+}
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry)
+ : ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (tree,entry)
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
+}
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator (const EXT_ID& key,ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree)
+ : ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>(key,tree)
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
+}
+
+// Destructor.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Reverse_Iterator ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Reverse_Iterator");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_RB_TREE_CPP */
diff --git a/ACE/ace/RB_Tree.h b/ACE/ace/RB_Tree.h
new file mode 100644
index 00000000000..8d7924736df
--- /dev/null
+++ b/ACE/ace/RB_Tree.h
@@ -0,0 +1,904 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file RB_Tree.h
+ *
+ * $Id$
+ *
+ * @author Chris Gill
+ */
+//=============================================================================
+
+
+#ifndef ACE_RB_TREE_H
+#define ACE_RB_TREE_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Global_Macros.h"
+#include "ace/Functor_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_RB_Tree_Iterator_Base;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_RB_Tree_Iterator;
+
+// Forward decl.
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_RB_Tree_Reverse_Iterator;
+
+// Forward decl.
+class ACE_Allocator;
+
+class ACE_RB_Tree_Node_Base
+{
+public:
+ enum RB_Tree_Node_Color {RED, BLACK};
+};
+
+/**
+ * @class ACE_RB_Tree_Node
+ *
+ * @brief Implements a node in a Red-Black Tree ADT.
+ */
+template <class EXT_ID, class INT_ID>
+class ACE_RB_Tree_Node : public ACE_RB_Tree_Node_Base
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Constructor.
+ ACE_RB_Tree_Node (const EXT_ID &k, const INT_ID &t);
+
+ /// Destructor.
+ ~ACE_RB_Tree_Node (void);
+
+ /// Key accessor.
+ EXT_ID &key (void);
+
+ /// Item accessor.
+ INT_ID &item (void);
+
+ /// Set color of the node.
+ void color (RB_Tree_Node_Color c);
+
+ /// Get color of the node.
+ RB_Tree_Node_Color color (void);
+
+ /// Accessor for node's parent pointer.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent (void);
+
+ /// Mutator for node's parent pointer.
+ void parent (ACE_RB_Tree_Node<EXT_ID, INT_ID> * p);
+
+ /// Accessor for node's left child pointer.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *left (void);
+
+ /// Mutator for node's left child pointer.
+ void left (ACE_RB_Tree_Node<EXT_ID, INT_ID> *l);
+
+ /// Accessor for node's right child pointer.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *right (void);
+
+ /// Mutator for node's right child pointer
+ void right (ACE_RB_Tree_Node<EXT_ID, INT_ID> * r);
+
+private:
+
+ /// The key.
+ EXT_ID k_;
+
+ /// The item.
+ INT_ID t_;
+
+ /// Color of the node.
+ RB_Tree_Node_Color color_;
+
+ /// Pointer to node's parent.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent_;
+
+ /// Pointer to node's left child.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *left_;
+
+ /// Pointer to node's right child.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *right_;
+};
+
+class ACE_RB_Tree_Base
+{
+public:
+ /// Search result enumeration.
+ enum RB_SearchResult {LEFT, EXACT, RIGHT};
+
+ /// Get the allocator;
+ /**
+ * @note This method is inlined here rather than in RB_Tree.inl
+ * since that file may be included multiple times when
+ * inlining is disabled and on platforms where
+ * @c ACE_TEMPLATES_REQUIRE_SOURCE is defined. In those
+ * platform/configuration combinations, multiple definitions
+ * of this method occured. Placing the definition inline in
+ * the header avoids such errors.
+ */
+ ACE_Allocator * allocator (void) const { return this->allocator_; }
+
+protected:
+ // = Protected members.
+
+ /// Pointer to a memory allocator.
+ ACE_Allocator *allocator_;
+};
+
+/**
+ * @class ACE_RB_Tree
+ *
+ * @brief Implements a Red-Black Tree ADT, according to T. H. Corman,
+ * C. E. Leiserson, and R. L. Rivest, "Introduction to Algorithms"
+ * 1990, MIT, chapter 14.
+ *
+ * A number of Changes have been made to this class template
+ * in order to conform to the ACE_Hash_Map_Manager_Ex
+ * interface. All previously supported public methods are
+ * still part of this class. However, these are marked as
+ * DEPRECATED and will be removed from this class in
+ * a future version of ACE. Please migrate your code
+ * to the appropriate public methods indicated in the
+ * method deprecation comments.
+ * This class uses an ACE_Allocator to allocate memory. The
+ * user can make this a persistent class by providing an
+ * ACE_Allocator with a persistable memory pool.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure:
+ * Binary tree
+ * - Duplicates allowed?
+ * No
+ * - Random access allowed?
+ * No
+ * - Search speed:
+ * Log(n)
+ * - Insert/replace speed:
+ * Log(n)
+ * - Iterator still valid after change to container?
+ * Yes, except if the iterated-over element is removed.
+ * - Frees memory for removed elements?
+ * Yes
+ * - Items inserted by:
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator==
+ * -# operator<
+ */
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_RB_Tree : public ACE_RB_Tree_Base
+{
+
+public:
+ friend class ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>;
+ friend class ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>;
+
+ typedef EXT_ID KEY;
+ typedef INT_ID VALUE;
+ typedef ACE_LOCK lock_type;
+ typedef ACE_RB_Tree_Node<EXT_ID, INT_ID> ENTRY;
+
+ // = ACE-style iterator typedefs.
+ typedef ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> ITERATOR;
+ typedef ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> REVERSE_ITERATOR;
+
+ // = STL-style iterator typedefs.
+ typedef ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> iterator;
+ typedef ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> reverse_iterator;
+
+ // = Initialization and termination methods.
+
+ /// Constructor.
+ ACE_RB_Tree (ACE_Allocator *alloc = 0);
+
+
+ /// Copy constructor.
+ ACE_RB_Tree (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt);
+
+ /// Initialize an RB Tree.
+ int open (ACE_Allocator *alloc = 0);
+
+ /// Close down an RB_Tree and release dynamically allocated
+ /// resources.
+ int close (void);
+
+ /// Destructor.
+ virtual ~ACE_RB_Tree (void);
+
+ // = insertion, removal, and search methods.
+
+ /**
+ * Associate @a ext_id with @a int_id. If @a ext_id is already in the
+ * tree then the <ACE_RB_Tree_Node> is not changed. Returns 0 if a
+ * new entry is bound successfully, returns 1 if an attempt is made
+ * to bind an existing entry, and returns -1 if failures occur.
+ */
+ int bind (const EXT_ID &item,
+ const INT_ID &int_id);
+
+ /**
+ * Same as a normal bind, except the tree entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int bind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry);
+
+
+ /**
+ * Associate @a ext_id with @a int_id if and only if @a ext_id is not
+ * in the tree. If @a ext_id is already in the tree then the @a int_id
+ * parameter is assigned the existing value in the tree. Returns 0
+ * if a new entry is bound successfully, returns 1 if an attempt is
+ * made to bind an existing entry, and returns -1 if failures occur.
+ */
+ int trybind (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /**
+ * Same as a normal trybind, except the tree entry is also passed
+ * back to the caller. The entry in this case will either be the
+ * newly created entry, or the existing one.
+ */
+ int trybind (const EXT_ID &ext_id,
+ INT_ID &int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Reassociate @a ext_id with @a int_id. If @a ext_id is not in the
+ * tree then behaves just like <bind>. Returns 0 if a new entry is
+ * bound successfully, returns 1 if an existing entry was rebound,
+ * and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id);
+
+ /**
+ * Same as a normal rebind, except the tree entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id. If @a ext_id is not in the tree
+ * then behaves just like <bind>. Otherwise, store the old value of
+ * @a int_id into the "out" parameter and rebind the new parameters.
+ * Returns 0 if a new entry is bound successfully, returns 1 if an
+ * existing entry was rebound, and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id);
+
+ /**
+ * Same as a normal rebind, except the tree entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Associate @a ext_id with @a int_id. If @a ext_id is not in the tree
+ * then behaves just like <bind>. Otherwise, store the old values
+ * of @a ext_id and @a int_id into the "out" parameters and rebind the
+ * new parameters. This is very useful if you need to have an
+ * atomic way of updating <ACE_RB_Tree_Nodes> and you also need
+ * full control over memory allocation. Returns 0 if a new entry is
+ * bound successfully, returns 1 if an existing entry was rebound,
+ * and returns -1 if failures occur.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id);
+
+ /**
+ * Same as a normal rebind, except the tree entry is also passed back
+ * to the caller. The entry in this case will either be the newly
+ * created entry, or the existing one.
+ */
+ int rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry);
+
+ /// Locate @a ext_id and pass out parameter via @a int_id. If found,
+ /// return 0, returns -1 if not found.
+ int find (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /// Locate @a ext_id and pass out parameter via @a entry. If found,
+ /// return 0, returns -1 if not found.
+ int find (const EXT_ID &ext_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Unbind (remove) the @a ext_id from the tree. Don't return the
+ * @a int_id to the caller (this is useful for collections where the
+ * @c int_ids are *not* dynamically allocated...)
+ */
+ int unbind (const EXT_ID &ext_id);
+
+ /// Break any association of @a ext_id. Returns the value of @a int_id
+ /// in case the caller needs to deallocate memory.
+ int unbind (const EXT_ID &ext_id,
+ INT_ID &int_id);
+
+ /**
+ * Remove entry from tree. This method should be used with *extreme*
+ * caution, and only for optimization purposes. The node being passed
+ * in had better have been allocated by the tree that is unbinding it.
+ */
+ int unbind (ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry);
+
+ // = Public helper methods.
+
+ /// Returns the current number of nodes in the tree.
+ size_t current_size (void) const;
+
+ /// Assignment operator.
+ void operator= (const ACE_RB_Tree<EXT_ID,
+ INT_ID,
+ COMPARE_KEYS,
+ ACE_LOCK> &rbt);
+
+ /**
+ * Returns a reference to the underlying <ACE_LOCK>. This makes it
+ * possible to acquire the lock explicitly, which can be useful in
+ * some cases if you instantiate the ACE_Atomic_Op with an
+ * ACE_Recursive_Mutex or ACE_Process_Mutex, or if you need to
+ * guard the state of an iterator.
+ * @note The right name would be <lock>, but HP/C++ will choke on that!
+ */
+ ACE_LOCK &mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL styled iterator factory functions.
+
+ /// Return forward iterator positioned at first node in tree.
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> begin (void);
+
+ /// Return forward iterator positioned at last node in tree.
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> end (void);
+
+ /// Return reverse iterator positioned at last node in tree.
+ ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> rbegin (void);
+
+ /// Return reverse iterator positioned at first node in tree.
+ ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> rend (void);
+
+ /// Recursively tests the invariant red-black properties at each
+ /// node of the tree. Returns 0 if invariant holds, else -1.
+ /// This method is computationally expensive, and should only be
+ /// called for testing purposes, and not in code that depends on the
+ /// algorithmic complexity bounds provided by the other methods.
+ int test_invariant (void);
+
+ // = DEPRECATED methods.
+ // Please migrate your code to use the new methods instead
+
+ /**
+ * Returns a pointer to the item corresponding to the
+ * given key, or 0 if it cannot find the key in the tree.
+ *
+ * @deprecated signature will change to become
+ * int find (const EXT_ID &ext_id); which will return
+ * 0 if the @a ext_id is in the tree, otherwise -1.
+ */
+ INT_ID* find (const EXT_ID &k);
+
+ /**
+ * Inserts a *copy* of the key and the item into the tree: both the
+ * key type EXT_ID and the item type INT_ID must have well defined semantics
+ * for copy construction. The default implementation also requires that
+ * the key type support well defined < semantics. This method returns a
+ * pointer to the inserted item copy, or 0 if an error occurred.
+ * @note If an identical key already exists in the tree, no new item
+ * is created, and the returned pointer addresses the existing item
+ * associated with the existing key.
+ * @deprecated
+ */
+ INT_ID* insert (const EXT_ID &k, const INT_ID &t);
+
+ /**
+ * Removes the item associated with the given key from the tree and
+ * destroys it. Returns 1 if it found the item and successfully
+ * destroyed it, 0 if it did not find the item, or -1 if an error
+ * occurred.
+ * @deprecated
+ */
+ int remove (const EXT_ID &k);
+
+ /// @deprecated
+ /// Destroys all nodes and sets the root pointer null.
+ void clear (void);
+
+protected:
+ /// Reinitialize constructor.
+ /**
+ * This constructor is used to provide a valid vtable and allocator
+ * if the tree is reconstructed from shared memory. Constructor
+ * used by the derived class that has an allocator
+ */
+ ACE_RB_Tree (void *location,
+ ACE_Allocator *alloc);
+
+ // = Protected methods. These should only be called with locks held.
+
+ /// Recursively tests the invariant red-black properties at each
+ /// node of the tree. Returns 0 if invariant holds, else -1.
+ int test_invariant_recurse (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x,
+ int & expected_black_height,
+ int measured_black_height);
+
+ /// Method for right rotation of the tree about a given node.
+ void RB_rotate_right (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x);
+
+ /// Method for left rotation of the tree about a given node.
+ void RB_rotate_left (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x);
+
+ /// Method for restoring Red-Black properties after deletion.
+ void RB_delete_fixup (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> * parent);
+
+ /// Method to find the successor node of the given node in the tree.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ RB_tree_successor (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const;
+
+ /// Method to find the predecessor node of the given node in the
+ /// tree.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ RB_tree_predecessor (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const;
+
+ /// Method to find the minimum node of the subtree rooted at the
+ /// given node.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ RB_tree_minimum (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const;
+
+ /// Method to find the maximum node of the subtree rooted at the
+ /// given node.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ RB_tree_maximum (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const;
+
+ /**
+ * Returns a pointer to a matching node if there is one, a pointer
+ * to the node under which to insert the item if the tree is not
+ * empty and there is no such match, or 0 if the tree is empty.
+ * It stores the result of the search in the result argument:
+ * LEFT if the node is to the left of the node to be inserted,
+ * RIGHT if the node is to the right of the node to be inserted,
+ * or EXACT if an exactly matching node already exists.
+ */
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *find_node (const EXT_ID &k,
+ ACE_RB_Tree_Base::RB_SearchResult &result);
+
+ /// Rebalance the tree after insertion of a node.
+ void RB_rebalance (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x);
+
+ /// Delete children (left and right) of the node. Must be called with
+ /// lock held.
+ void delete_children_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent);
+
+ /// Close down an RB_Tree. this method should
+ /// only be called with locks already held.
+ int close_i (void);
+
+ /**
+ * Retrieves a pointer to the item corresponding to the
+ * given key. If find_exact==1, find the exact match node,
+ * otherwise just find a match node
+ * Returns 0 for success, or -1 if it cannot find the key in the tree.
+ */
+ int find_i (const EXT_ID &ext_id, ACE_RB_Tree_Node<EXT_ID, INT_ID>* &entry, int find_exact = 1);
+
+ /**
+ * Inserts a *copy* of the key and the item into the tree: both the
+ * key type EXT_ID and the item type INT_ID must have well defined semantics
+ * for copy construction. The default implementation also requires that
+ * the key type support well defined < semantics. This method returns a
+ * pointer to the inserted item copy, or 0 if an error occurred.
+ * @note If an identical key already exists in the tree, no new item
+ * is created, and the returned pointer addresses the existing item
+ * associated with the existing key.
+ */
+ INT_ID* insert_i (const EXT_ID &k, const INT_ID &t);
+
+ /**
+ * Inserts a *copy* of the key and the item into the tree: both the
+ * key type EXT_ID and the item type INT_ID must have well defined semantics
+ * for copy construction. The default implementation also requires that
+ * the key type support well defined < semantics. This method passes back
+ * a pointer to the inserted (or existing) node, and the search status. If
+ * the node already exists, the method returns 1. If the node does not
+ * exist, and a new one is successfully created, and the method returns 0.
+ * If there was an error, the method returns -1.
+ */
+ int insert_i (const EXT_ID &k, const INT_ID &t,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry);
+
+ /**
+ * Removes the item associated with the given key from the tree and
+ * destroys it. Returns 1 if it found the item and successfully
+ * destroyed it, 0 if it did not find the item, or -1 if an error
+ * occurred. Returns the stored internal id in the second argument.
+ */
+ int remove_i (const EXT_ID &k, INT_ID &i);
+
+ /// Removes the item associated with the given key from the tree and
+ /// destroys it.
+ int remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z);
+
+ /// Recursive function to dump the state of an object.
+ void dump_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *node) const;
+
+ /// Function to dump node contents. Does nothing in its
+ /// basic form, but template specialization can be used to
+ /// provide definitions for various EXT_ID and INT_ID types.
+ void dump_node_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> &node) const;
+
+ /// Less than comparison function for keys, using comparison functor.
+ int lessthan (const EXT_ID &k1, const EXT_ID &k2);
+
+private:
+
+ // = Private members.
+
+ /// Synchronization variable for the MT_SAFE ACE_RB_Tree.
+ ACE_LOCK lock_;
+
+ /// The root of the tree.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *root_;
+
+ /// Comparison functor for comparing nodes in the tree.
+ COMPARE_KEYS compare_keys_;
+
+ /// The current number of nodes in the tree.
+ size_t current_size_;
+};
+
+/**
+ * @class ACE_RB_Tree_Iterator_Base
+ *
+ * @brief Implements a common base class for iterators for a Red-Black Tree ADT.
+ */
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_RB_Tree_Iterator_Base
+{
+
+public:
+
+ /// Copy constructor.
+ ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &iter);
+
+ /// Assignment operator: copies both the tree reference and the position in the tree.
+ void operator= (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &iter);
+
+ // = Iteration methods.
+
+ /// Returns 1 when the iteration has completed, otherwise 0.
+ int done (void) const;
+
+ /// STL-like iterator dereference operator: returns a reference
+ /// to the node underneath the iterator.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> & operator* (void) const;
+
+ /// STL-like iterator dereference operator: returns a pointer
+ /// to the node underneath the iterator.
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> * operator-> (void) const;
+
+ /// Returns a const reference to the tree over which we're iterating.
+ const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree (void);
+
+ /// Comparison operator: returns 1 if both iterators point to the same position, otherwise 0.
+ bool operator== (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &) const;
+
+ /// Comparison operator: returns 1 if the iterators point to different positions, otherwise 0.
+ bool operator!= (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ // = Initialization and termination methods.
+
+ /// Create the singular iterator. No valid iterator can be equal to
+ /// it, it is illegal to dereference a singular iterator, etc. etc.
+ ACE_RB_Tree_Iterator_Base (void);
+
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate, and
+ * an integer indicating (if non-zero) to position the iterator
+ * at the first element in the tree (if this integer is 0, the
+ * iterator is positioned at the last element in the tree).
+ */
+ ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
+ int set_first);
+
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate, and
+ * a pointer to a node in the tree.
+ */
+ ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry);
+
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate, and a key.
+ * The key must come first to distinguish the case of EXT_ID == int.
+ */
+ ACE_RB_Tree_Iterator_Base (const EXT_ID& key,
+ ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS,ACE_LOCK> &tree);
+
+ /// Destructor.
+ ~ACE_RB_Tree_Iterator_Base (void);
+
+ // = Internal methods
+
+ /// Move forward by one element in the tree. Returns 0 when
+ /// there are no more elements in the tree, otherwise 1.
+ int forward_i (void);
+
+ /// Move back by one element in the tree. Returns 0 when
+ /// there are no more elements in the tree, otherwise 1.
+ int reverse_i (void);
+
+ /// Dump the state of an object.
+ void dump_i (void) const;
+
+ // = Protected members.
+
+ /// Reference to the ACE_RB_Tree over which we're iterating.
+ const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> *tree_;
+
+ /// Pointer to the node currently under the iterator.
+ ACE_RB_Tree_Node <EXT_ID, INT_ID> *node_;
+
+};
+
+/**
+ * @class ACE_RB_Tree_Iterator
+ *
+ * @brief Implements an iterator for a Red-Black Tree ADT.
+ */
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_RB_Tree_Iterator : public ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+{
+
+public:
+
+ // = Initialization and termination methods.
+ /**
+ * Create the singular iterator.
+ * It is illegal to deference the iterator, no valid iterator is
+ * equal to a singular iterator, etc. etc.
+ */
+ ACE_RB_Tree_Iterator (void);
+
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate, and
+ * an integer indicating (if non-zero) to position the iterator
+ * at the first element in the tree (if this integer is 0, the
+ * iterator is positioned at the last element in the tree).
+ */
+ ACE_RB_Tree_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
+ int set_first = 1);
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate
+ * and a pointer to a node in the tree.
+ */
+ ACE_RB_Tree_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry);
+
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate, and a key;
+ * the key comes first in order to distinguish the case of EXT_ID == int.
+ */
+ ACE_RB_Tree_Iterator (const EXT_ID &key,
+ ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree);
+
+ /// Destructor.
+ ~ACE_RB_Tree_Iterator (void);
+
+ // = ACE-style iteration methods.
+
+ /// Move forward by one element in the tree. Returns
+ /// 0 when all elements have been seen, else 1.
+ int advance (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL-style iteration methods.
+
+ /// Prefix advance.
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> & operator++ (void);
+
+ /// Postfix advance.
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> & operator-- (void);
+
+ /// Postfix reverse.
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /**
+ * Passes back the <entry> under the iterator. Returns 0 if
+ * the iteration has completed, otherwise 1. This method must
+ * be declared and defined in both the derived forward and
+ * reverse iterator classes rather than in the base iterator
+ * class because of a method signature resolution problem
+ * caused by the existence of the deprecated next (void)
+ * method in the derived forward iterator class. When that
+ * deprecated method is removed, this method should be removed
+ * from the derived classes and placed in the base class.
+ */
+ int next (ACE_RB_Tree_Node<EXT_ID, INT_ID> *&next_entry) const;
+
+ // = DEPRECATED methods. Please migrate your code to use the new methods instead
+
+ /// @deprecated
+ /// Accessor for key of node under iterator (if any).
+ EXT_ID *key (void);
+
+ /// @deprecated
+ /// Accessor for item of node under iterator (if any).
+ INT_ID *item (void);
+
+ /// @deprecated
+ /// Move to the first item in the iteration (and in the tree).
+ int first (void);
+
+ /// @deprecated
+ /// Move to the last item in the iteration (and in the tree).
+ int last (void);
+
+ /// @deprecated
+ /// Move to the next item in the iteration (and in the tree).
+ int next (void);
+
+ /// @deprecated
+ /// Move to the previous item in the iteration (and in the tree).
+ int previous (void);
+
+ /**
+ * @deprecated: use the base class <done> method instead.
+ * Returns 0 if the iterator is positioned over a valid ACE_RB_Tree
+ * node, returns 1 if not.
+ */
+ int is_done (void);
+
+};
+
+/**
+ * @class ACE_RB_Tree_Reverse_Iterator
+ *
+ * @brief Implements a reverse iterator for a Red-Black Tree ADT.
+ */
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+class ACE_RB_Tree_Reverse_Iterator : public ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+{
+
+public:
+
+ // = Initialization and termination methods.
+ /**
+ * Create the singular iterator.
+ * It is illegal to deference the iterator, no valid iterator is
+ * equal to a singular iterator, etc. etc.
+ */
+ ACE_RB_Tree_Reverse_Iterator (void);
+
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate, and
+ * an integer indicating (if non-zero) to position the iterator
+ * at the last element in the tree (if this integer is 0, the
+ * iterator is positioned at the first element in the tree).
+ */
+ ACE_RB_Tree_Reverse_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
+ int set_last = 1);
+
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate, and
+ * a point to a node in the tree.
+ */
+ ACE_RB_Tree_Reverse_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry);
+
+ /**
+ * Constructor. Takes an ACE_RB_Tree over which to iterate, and a key;
+ * the key comes first in order to distinguish the case of EXT_ID == int.
+ */
+ ACE_RB_Tree_Reverse_Iterator (const EXT_ID &key,
+ ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree);
+
+ /// Destructor.
+ ~ACE_RB_Tree_Reverse_Iterator (void);
+
+ // = ACE-style iteration methods.
+
+ /// Move forward by one element in the tree. Returns
+ /// 0 when all elements have been seen, else 1.
+ int advance (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL-style iteration methods.
+
+ /// Prefix advance.
+ ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> & operator++ (void);
+
+ /// Postfix advance.
+ ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> operator++ (int);
+
+ /// Prefix reverse.
+ ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> & operator-- (void);
+
+ /// Postfix reverse.
+ ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> operator-- (int);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /**
+ * Passes back the <entry> under the iterator. Returns 0 if
+ * the iteration has completed, otherwise 1. This method must
+ * be declared and defined in both the derived forward and
+ * reverse iterator classes rather than in the base iterator
+ * class because of a method signature resolution problem
+ * caused by the existence of the deprecated next (void)
+ * method in the derived forward iterator class. When that
+ * deprecated method is removed, this method should be removed
+ * from the derived classes and placed in the base class.
+ */
+ int next (ACE_RB_Tree_Node<EXT_ID, INT_ID> *&next_entry) const;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/RB_Tree.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/RB_Tree.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("RB_Tree.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ! defined (ACE_RB_TREE_H) */
diff --git a/ACE/ace/RB_Tree.inl b/ACE/ace/RB_Tree.inl
new file mode 100644
index 00000000000..7cbac0c9f7a
--- /dev/null
+++ b/ACE/ace/RB_Tree.inl
@@ -0,0 +1,1169 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Guard_T.h"
+#include "ace/Malloc_Base.h"
+#include "ace/Log_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/////////////////////////////////////////////////////
+// template class ACE_RB_Tree_Node<EXT_ID, INT_ID> //
+/////////////////////////////////////////////////////
+
+// Key accessor.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE EXT_ID &
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::key ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::key");
+ return k_;
+}
+
+
+// Item accessor.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE INT_ID &
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::item ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>:item");
+ return t_;
+}
+
+
+// Set color of the node.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE void
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::color (ACE_RB_Tree_Node_Base::RB_Tree_Node_Color c)
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::color mutator");
+ color_ = c;
+}
+
+
+// Get color of the node.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE ACE_RB_Tree_Node_Base::RB_Tree_Node_Color
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::color ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::color accessor");
+ return color_;
+}
+
+
+// Accessor for node's parent pointer.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::parent ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::parent accessor");
+ return parent_;
+}
+
+
+// Mutator for node's parent pointer.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE void
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::parent (ACE_RB_Tree_Node<EXT_ID, INT_ID> * p)
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::parent mutator");
+ parent_ = p;
+}
+
+
+
+// Accessor for node's left child pointer.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::left ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::left accessor");
+ return left_;
+}
+
+
+// Mutator for node's left child pointer.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE void
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::left (ACE_RB_Tree_Node<EXT_ID, INT_ID> * l)
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::left mutator");
+ left_ = l;
+}
+
+
+// Accessor for node's right child pointer.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::right ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::right accessor");
+ return right_;
+}
+
+
+// Mutator for node's right child pointer.
+
+template <class EXT_ID, class INT_ID>
+ACE_INLINE void
+ACE_RB_Tree_Node<EXT_ID, INT_ID>::right (ACE_RB_Tree_Node<EXT_ID, INT_ID> * r)
+{
+ ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::right mutator");
+ right_ = r;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// template class ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> //
+////////////////////////////////////////////////////////////////////////
+
+
+// Initialize an RB Tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::open (ACE_Allocator *alloc)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::open");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ // Calling this->close_i () ensures we release previously allocated
+ // memory before allocating new memory.
+ this->close_i ();
+
+ // If we were passed an allocator use it,
+ // otherwise use the default instance.
+
+ if (alloc == 0)
+ alloc = ACE_Allocator::instance ();
+
+ this->allocator_ = alloc;
+
+ return 0;
+}
+
+// Close down an RB_Tree and release dynamically allocated
+// resources.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::close (void)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::close");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->close_i ();
+}
+
+
+// Associate <ext_id> with <int_id>. If <ext_id> is already in the
+// tree then the <ACE_RB_Tree_Node> is not changed. Returns 0 if a
+// new entry is bound successfully, returns 1 if an attempt is made
+// to bind an existing entry, and returns -1 if failures occur.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &item, const INT_ID &int_id)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry;
+ return this->insert_i (ext_id, int_id, entry);
+}
+
+
+// Same as a normal bind, except the tree entry is also passed back
+// to the caller. The entry in this case will either be the newly
+// created entry, or the existing one.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::bind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)
+{
+ ACE_TRACE ("ACE_RB_Tree::bind (const EXT_ID &ext_id, const INT_ID &int_id, "
+ "ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->insert_i (ext_id, int_id, entry);
+}
+
+
+// Associate <ext_id> with <int_id> if and only if <ext_id> is not
+// in the tree. If <ext_id> is already in the tree then the <int_id>
+// parameter is assigned the existing value in the tree. Returns 0
+// if a new entry is bound successfully, returns 1 if an attempt is
+// made to bind an existing entry, and returns -1 if failures occur.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::trybind (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_TRACE ("ACE_RB_Tree::trybind (const EXT_ID &ext_id, INT_ID &int_id)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry;
+ int result = this->insert_i (ext_id, int_id, entry);
+
+ if (result == 1)
+ {
+ int_id = entry->item ();
+ }
+
+ return result;
+}
+
+
+// Same as a normal trybind, except the tree entry is also passed
+// back to the caller. The entry in this case will either be the
+// newly created entry, or the existing one.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::trybind (const EXT_ID &ext_id,
+ INT_ID &int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)
+{
+ ACE_TRACE ("ACE_RB_Tree::trybind (const EXT_ID &ext_id, INT_ID &int_id, "
+ "ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ int result = this->insert_i (ext_id, int_id, entry);
+
+ if (result == 1)
+ {
+ int_id = entry->item ();
+ }
+
+
+ return result;
+}
+
+
+// Reassociate <ext_id> with <int_id>. If <ext_id> is not in the
+// tree then behaves just like <bind>. Returns 0 if a new entry is
+// bound successfully, returns 1 if an existing entry was rebound,
+// and returns -1 if failures occur.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id)
+{
+ ACE_TRACE ("ACE_RB_Tree::rebind (const EXT_ID &ext_id, const INT_ID &int_id)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry;
+ int result = this->insert_i (ext_id, int_id, entry);
+
+ if (result == 1)
+ {
+ entry->key () = ext_id;
+ entry->item () = int_id;
+ }
+
+ return result;
+}
+
+
+// Same as a normal rebind, except the tree entry is also passed back
+// to the caller. The entry in this case will either be the newly
+// created entry, or the existing one.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)
+{
+ ACE_TRACE ("ACE_RB_Tree::rebind (const EXT_ID &ext_id, const INT_ID &int_id, "
+ "ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ int result = this->insert_i (ext_id, int_id, entry);
+
+ if (result == 1)
+ {
+ entry->key () = ext_id;
+ entry->item () = int_id;
+ }
+
+ return result;
+}
+
+
+// Associate <ext_id> with <int_id>. If <ext_id> is not in the tree
+// then behaves just like <bind>. Otherwise, store the old value of
+// <int_id> into the "out" parameter and rebind the new parameters.
+// Returns 0 if a new entry is bound successfully, returns 1 if an
+// existing entry was rebound, and returns -1 if failures occur.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id)
+{
+ ACE_TRACE ("ACE_RB_Tree::rebind (const EXT_ID &ext_id, "
+ "const INT_ID &int_id, INT_ID &old_int_id)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry;
+ int result = this->insert_i (ext_id, int_id, entry);
+
+ if (result == 1)
+ {
+ old_int_id = entry->item ();
+ entry->key () = ext_id;
+ entry->item () = int_id;
+ }
+
+ return result;
+}
+
+
+// Same as a normal rebind, except the tree entry is also passed back
+// to the caller. The entry in this case will either be the newly
+// created entry, or the existing one.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ INT_ID &old_int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)
+{
+ ACE_TRACE ("ACE_RB_Tree::rebind (const EXT_ID &ext_id, const INT_ID &int_id,"
+ "INT_ID &old_int_id, ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ int result = this->insert_i (ext_id, int_id, entry);
+
+ if (result == 1)
+ {
+ old_int_id = entry->item ();
+ entry->key () = ext_id;
+ entry->item () = int_id;
+ }
+
+ return result;
+}
+
+
+// Associate <ext_id> with <int_id>. If <ext_id> is not in the tree
+// then behaves just like <bind>. Otherwise, store the old values
+// of <ext_id> and <int_id> into the "out" parameters and rebind the
+// new parameters. This is very useful if you need to have an
+// atomic way of updating <ACE_RB_Tree_Nodes> and you also need
+// full control over memory allocation. Returns 0 if a new entry is
+// bound successfully, returns 1 if an existing entry was rebound,
+// and returns -1 if failures occur.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id)
+{
+ ACE_TRACE ("ACE_RB_Tree::rebind (const EXT_ID &ext_id, const INT_ID &int_id,"
+ "EXT_ID &old_ext_id, INT_ID &old_int_id)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry;
+ int result = this->insert_i (ext_id, int_id, entry);
+
+ if (result == 1)
+ {
+ old_ext_id = entry->key ();
+ old_int_id = entry->item ();
+ entry->key () = ext_id;
+ entry->item () = int_id;
+ }
+
+ return result;
+}
+
+
+// Same as a normal rebind, except the tree entry is also passed back
+// to the caller. The entry in this case will either be the newly
+// created entry, or the existing one.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rebind (const EXT_ID &ext_id,
+ const INT_ID &int_id,
+ EXT_ID &old_ext_id,
+ INT_ID &old_int_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)
+{
+ ACE_TRACE ("ACE_RB_Tree::rebind (const EXT_ID &ext_id, const INT_ID &int_id, "
+ "EXT_ID &old_ext_id, INT_ID &old_int_id, "
+ "ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ int result = this->insert_i (ext_id, int_id, entry);
+
+ if (result == 1)
+ {
+ old_ext_id = entry->key ();
+ old_int_id = entry->item ();
+ entry->key () = ext_id;
+ entry->item () = int_id;
+ }
+
+ return result;
+}
+
+
+// Locate <ext_id> and pass out parameter via <int_id>. If found,
+// return 0, returns -1 if not found.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_TRACE ("ACE_RB_Tree::find (const EXT_ID &ext_id, INT_ID &int_id)");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry = 0;
+
+ int result = this->find_i (ext_id, entry);
+ if (result == 0)
+ {
+ int_id = entry->item ();
+ }
+
+ return result;
+}
+
+// Locate <ext_id> and pass out parameter via <entry>. If found,
+// return 0, returns -1 if not found.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &ext_id,
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)
+{
+ ACE_TRACE ("ACE_RB_Tree::find (const EXT_ID &ext_id, ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->find_i (ext_id, entry);
+}
+
+
+// Unbind (remove) the <ext_id> from the tree. Don't return the
+// <int_id> to the caller (this is useful for collections where the
+// <int_id>s are *not* dynamically allocated...).
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::unbind (const EXT_ID &ext_id)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::unbind (const EXT_ID &ext_id)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ INT_ID int_id;
+ int result = this->remove_i (ext_id, int_id);
+
+ // Remap the return codes from the internal method: this
+ // is maintained this way in support of deprecated methods,
+ // and will be cleaned up when these methods are removed.
+ switch (result)
+ {
+ case 1:
+ // If the node was found and deleted, return success.
+ return 0;
+ case 0:
+ // If nothing was found, set errno and break.
+ errno = ENOENT;
+ break;
+ case -1:
+ // If an error happened, just break.
+ break;
+ }
+
+ // Return an error if we didn't already return success.
+ return -1;
+}
+
+
+// Break any association of <ext_id>. Returns the value of <int_id>
+// in case the caller needs to deallocate memory.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::unbind (const EXT_ID &ext_id,
+ INT_ID &int_id)
+{
+ ACE_TRACE ("ACE_RB_Tree::unbind (const EXT_ID &ext_id, INT_ID &int_id)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ int result = this->remove_i (ext_id, int_id);
+
+ // Remap the return codes from the internal method: this
+ // is maintained this way in support of deprecated methods,
+ // and will be cleaned up when these methods are removed.
+ switch (result)
+ {
+ case 1:
+ // If the node was found and deleted, return success.
+ return 0;
+ case 0:
+ // If nothing was found, set errno and break.
+ errno = ENOENT;
+ break;
+ case -1:
+ // If an error happened, just break.
+ break;
+ }
+
+ // Return an error if we didn't already return success.
+ return -1;
+}
+
+
+// Remove entry from the tree. This method should be used with *extreme*
+// caution, and only for optimization purposes. The node being passed
+// in had better have been allocated by the tree that is unbinding it.
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::unbind (ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::unbind (ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry)");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->remove_i (entry);
+}
+
+
+// Returns a reference to the underlying <ACE_LOCK>. This makes it
+// possible to acquire the lock explicitly, which can be useful in
+// some cases if you instantiate the <ACE_Atomic_Op> with an
+// <ACE_Recursive_Mutex> or <ACE_Process_Mutex>, or if you need to
+// guard the state of an iterator. NOTE: the right name would be
+// <lock>, but HP/C++ will choke on that!
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_LOCK &
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::mutex (void)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::mutex");
+ return this->lock_;
+}
+
+
+// Dump the state of an object.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncurrent_size_ = %d\n"), this->current_size_));
+ this->allocator_->dump ();
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nDumping nodes from root\n")));
+ this->dump_i (this->root_);
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+
+// Return forward iterator positioned at first node in tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::begin (void)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::begin");
+
+ return ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (*this);
+}
+
+
+// Return forward iterator positioned at last node in tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::end (void)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::end");
+
+ return ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> ();
+}
+
+
+// Return reverse iterator positioned at last node in tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rbegin (void)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rbegin");
+
+ return ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (*this);
+}
+
+
+// Return reverse iterator positioned at first node in tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rend (void)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::rend");
+
+ return ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> ();
+}
+
+
+// Returns a pointer to the item corresponding to the given key,
+// or 0 if it cannot find the key in the tree. DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE INT_ID*
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &k)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find (const EXT_ID &k)");
+
+ // The reinterpret cast is to ensure that when this deprecated
+ // method is removed, and is replaced (as planned) by a find method
+ // that takes the same argument signature but returns an int, that
+ // the compiler will cough if this return macro is not changed to
+ // just return an int (whose value will be -1). Please leave this
+ // as is.
+ ACE_READ_GUARD_RETURN (ACE_LOCK,
+ ace_mon,
+ this->lock_,
+ reinterpret_cast<INT_ID*> (0L));
+
+ ACE_RB_Tree_Node<EXT_ID, INT_ID> *entry = 0;
+ int result = this->find_i (k, entry);
+ return (result == 0) ? &(entry->item ()) : 0;
+}
+
+// Inserts a *copy* of the key and the item into the tree:
+// both the key type EXT_ID and the item type INT_ID must have well
+// defined semantics for copy construction and < comparison.
+// This method returns a pointer to the inserted item copy,
+// or 0 if an error occurred. NOTE: if an identical key
+// already exists in the tree, no new item is created, and
+// the returned pointer addresses the existing item
+// associated with the existing key. DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE INT_ID*
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert (const EXT_ID &k, const INT_ID &t)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK,
+ ace_mon,
+ this->lock_,
+ reinterpret_cast<INT_ID*> (0L));
+
+ return this->insert_i (k, t);
+}
+
+
+// Removes the item associated with the given key from the
+// tree and destroys it. Returns 1 if it found the item
+// and successfully destroyed it, 0 if it did not find the
+// item, or -1 if an error occurred. DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove (const EXT_ID &k)
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ INT_ID i;
+ return this->remove_i (k, i);
+}
+
+
+// Destroys all nodes and sets the root pointer null. DEPRECATED
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE void
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::clear ()
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::clear");
+ ACE_WRITE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ this->close_i ();
+}
+
+// Returns the current number of nodes in the tree.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE size_t
+ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::current_size () const
+{
+ ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::current_size");
+ return current_size_;
+}
+
+
+///////////////////////////////////////////////////////////////////////
+// template class //
+// ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> //
+///////////////////////////////////////////////////////////////////////
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (void)
+ : tree_ (0), node_ (0)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (void)");
+}
+
+// Returns 1 when the iteration has completed, otherwise 0.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::done (void) const
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::done");
+
+ return node_ ? 0 : 1;
+}
+
+
+// STL-like iterator dereference operator: returns a reference
+// to the node underneath the iterator.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Node<EXT_ID, INT_ID> &
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator* (void) const
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator*");
+ return *(this->node_);
+}
+
+
+// STL-like iterator dereference operator: returns a reference
+// to the node underneath the iterator.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Node<EXT_ID, INT_ID> *
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator-> (void) const
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator->");
+ return this->node_;
+}
+
+
+// Returns a reference to the tree over which we're iterating.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>ACE_INLINE const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::tree (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::tree");
+ return *tree_;
+}
+
+
+// Comparison operator: returns 1 if both iterators point to the same position, otherwise 0.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE bool
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator==
+ (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt) const
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator==");
+ return (this->node_ == rbt.node_) ? true : false;
+}
+
+
+// Comparison operator: returns 1 if the iterators point to different positions, otherwise 0.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE bool
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator!=
+ (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt) const
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator!=");
+ return (this->node_ == rbt.node_) ? false : true;
+}
+
+
+// Move forward by one element in the tree. Returns 0 when
+// there are no more elements in the tree, otherwise 1.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::forward_i (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::forward_i");
+
+ if (node_)
+ {
+ node_ = tree_->RB_tree_successor (node_);
+ }
+
+ return node_ ? 1 : 0;
+}
+
+
+// Move back by one element in the tree. Returns 0 when
+// there are no more elements in the tree, otherwise 1.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::reverse_i (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::reverse_i");
+
+ if (node_)
+ {
+ node_ = tree_->RB_tree_predecessor (node_);
+ }
+
+ return node_ ? 1 : 0;
+}
+
+
+//////////////////////////////////////////////////////////////////
+// template class //
+// ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> //
+//////////////////////////////////////////////////////////////////
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator (void)
+ : ACE_RB_Tree_Iterator_Base<EXT_ID,INT_ID,COMPARE_KEYS,ACE_LOCK> ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator (void)");
+}
+
+// Move forward by one element in the tree. Returns
+// 0 when all elements have been seen, else 1.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::advance");
+
+ return this->forward_i ();
+}
+
+
+// Dump the state of an object.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE void
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+
+// Prefix advance.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> operator++ (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+
+// Postfix advance.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> operator++ (int)");
+
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+
+// Prefix reverse.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> operator-- (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+
+// Postfix reverse.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> operator-- (int)");
+
+ ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+
+// Passes back the <entry> under the iterator. Returns 0 if
+// the iteration has completed, otherwise 1. This method must
+// be declared and defined in both the derived forward and
+// reverse iterator classes rather than in the base iterator
+// class because of a method signature resolution problem
+// caused by the existence of the deprecated next (void)
+// method in the derived forward iterator class. When that
+// deprecated method is removed, this method should be removed
+// from the derived classes and placed in the base class.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::next (ACE_RB_Tree_Node<EXT_ID, INT_ID> *&next_entry) const
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::next");
+
+ if (this->node_)
+ {
+ next_entry = this->node_;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+// Accessor for key of node under iterator (if any). DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE EXT_ID *
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::key ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::key");
+ return this->node_ ? (&(this->node_->key ())) : 0;
+}
+
+
+// Accessor for item of node under iterator (if any). DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE INT_ID *
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::item ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::item");
+ return this->node_ ? (&(this->node_->item ())) : 0;
+}
+
+
+// Move to the first item in the tree. DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::first ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::first");
+ this->node_ = this->tree_->RB_tree_minimum (this->tree_->root_);
+ return this->node_ ? 1 : 0;
+}
+
+
+// Move to the last item in the tree. DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::last ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::last");
+ this->node_ = this->tree_->RB_tree_maximum (this->tree_->root_);
+ return this->node_ ? 1 : 0;
+}
+
+
+// Moves to the next item in the tree,
+// returns 1 if there is a next item, 0 otherwise. DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::next ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::next");
+ this->node_ = this->tree_->RB_tree_successor (this->node_);
+ return this->node_ ? 1 : 0;
+}
+
+
+// Moves to the previous item in the tree,
+// returns 1 if there is a previous item, 0 otherwise. DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::previous ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::previous");
+ this->node_ = this->tree_->RB_tree_predecessor (this->node_);
+ return this->node_ ? 1 : 0;
+}
+
+
+// Returns 0 if the iterator is positioned over a valid ACE_RB_Tree
+// node, returns 1 if not. DEPRECATED.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::is_done ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::is_done");
+ return this->node_ ? 0 : 1;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// template class //
+// ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> //
+//////////////////////////////////////////////////////////////////////////
+
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator (void)
+ : ACE_RB_Tree_Iterator_Base<EXT_ID,INT_ID,COMPARE_KEYS,ACE_LOCK> ()
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator (void)");
+}
+
+// Move forward by one element in the tree. Returns
+// 0 when all elements have been seen, else 1.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::advance (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::advance");
+
+ return this->reverse_i ();
+}
+
+
+// Dump the state of an object.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE void
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump");
+
+ this->dump_i ();
+#endif /* ACE_HAS_DUMP */
+}
+
+
+// Prefix advance.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator++ (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator++ (void)");
+
+ this->reverse_i ();
+ return *this;
+}
+
+
+// Postfix advance.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator++ (int)
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator++ (int)");
+
+ ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ ++*this;
+ return retv;
+}
+
+
+// Prefix reverse.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator-- (void)
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator-- (void)");
+
+ this->forward_i ();
+ return *this;
+}
+
+
+// Postfix reverse.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator-- (int)
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator-- (int)");
+
+ ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> retv (*this);
+ --*this;
+ return retv;
+}
+
+
+// Passes back the <entry> under the iterator. Returns 0 if
+// the iteration has completed, otherwise 1. This method must
+// be declared and defined in both the derived forward and
+// reverse iterator classes rather than in the base iterator
+// class because of a method signature resolution problem
+// caused by the existence of the deprecated next (void)
+// method in the derived forward iterator class. When that
+// deprecated method is removed, this method should be removed
+// from the derived classes and placed in the base class.
+
+template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
+ACE_INLINE int
+ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::next (ACE_RB_Tree_Node<EXT_ID, INT_ID> *&next_entry) const
+{
+ ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::next");
+
+ if (this->node_)
+ {
+ next_entry = this->node_;
+ return 1;
+ }
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/README b/ACE/ace/README
new file mode 100644
index 00000000000..ab92c9225b0
--- /dev/null
+++ b/ACE/ace/README
@@ -0,0 +1,1876 @@
+// $Id$
+
+ACE Portability Macros
+----------------------
+
+The following describes the meaning of the C++ compiler macros that
+can be set in the config*.h file. When you port ACE to a new platform
+and/or C++ compiler, make sure that you check to see which of these
+need to be defined. It's helpful to check the various config*.h files
+in this directory to see what's already been defined. If you need to
+add new macros, please send them to me and I'll add them to this file.
+
+Eventually, most of this information should be auto-discovered via GNU
+autoconf, which is currently available in the ACE distribution.
+
+Macro Description
+----- -----------
+
+ACE_HAS_DUMP Used to enable the dump()
+ method bodies. If not
+ defined, the bodies are ifdef
+ out in order to reduce
+ footprint. By default, it is
+ not defined.
+ACE_CAST_CONST Used to work around broken
+ SunCC ANSI casts that require
+ an extra const.
+ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES
+ Win32 only. Users want to use
+ a predefined security
+ attributes defined in
+ ACE_OS::default_win32_security_attributes
+ as the default security
+ object.
+ACE_DISABLE_DEBUG_DLL_CHECK Define this if you don't want
+ debug version ACE search for
+ debug version DLLs first
+ before looking for the DLL
+ names specified.
+ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER
+ Application will allocate its
+ own object manager. This
+ implicitly defines
+ ACE_HAS_NONSTATIC_OBJECT_MANAGER.
+ Usually used with MFC
+ applications.
+ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO Platform does not initialize
+ sockaddr_in::sin_zero field in
+ calls to getpeername() and
+ getsockname(). As a result,
+ memcmp()-based equality
+ comparison can fail despite
+ the fact two sockaddr_in
+ instances refer to the same
+ addr characteristics.
+ACE_MAIN Renames "main (int, char *[])",
+ for platforms such as g++/VxWorks
+ that don't allow "main". Requires
+ the use of
+ ACE_HAS_NONSTATIC_OBJECT_MANAGER.
+ACE_MKDIR_LACKS_MODE This platform has a mkdir function with
+ a mode argument
+ACE_MT_SAFE Compile using multi-thread libraries
+ACE_NDEBUG Turns off debugging features
+ACE_NEW_THROWS_EXCEPTIONS Compiler's 'new' throws exception on
+ failure (ANSI C++ behavior).
+ACE_NLOGGING Turns off the LM_DEBUG and
+ LM_ERROR logging macros...
+ACE_NTRACE Turns off the tracing feature when = 1.
+ACE_HAS_TRACE Defined when ACE_NTRACE=0 to
+ help support tracing. Can
+ also be defined by users who
+ implement their own tracing
+ macros based on
+ ACE_TRACE_IMPL. Not defining
+ it helps reduce footprint by
+ not requiring applications to
+ link in Trace.o.
+ACE_PAGE_SIZE Defines the page size of the
+ system (not used on Win32 or
+ with ACE_HAS_GETPAGESIZE).
+ACE_REDEFINES_XTI_FUNCTIONS Platform redefines the t_... names (UnixWare)
+ACE_TEMPLATES_REQUIRE_PRAGMA Compiler's template mechanism
+ must use a pragma This is used
+ for AIX's C++ compiler.
+ACE_TEMPLATES_REQUIRE_SOURCE Compiler's template mechanim
+ must see source code (i.e.,
+ .cpp files). This is used for
+ GNU G++.
+ACE_TIMEPROBE_ASSERTS_FIXED_SIZE If enabled then ACE_Timeprobe_Ex<>::timeprobe()
+ will assert if the end of the
+ buffer is reached. If disabled, the
+ counter wraps around to start
+ at the beginning of the buffer.
+ACE_TIMER_SKEW If a timed ::select () can return
+ early, then ACE_TIMER_SKEW is the
+ maximum adjustment, in microseconds,
+ that ACE_Timer_Queue uses to
+ compensate for the early return.
+ACE_TLI_TCP_DEVICE Device the platform uses for TCP on
+ TLI. Only needed if not /dev/tcp.
+ACE_USE_POLL The OS platform supports the
+ poll() event demultiplexor
+ACE_USES_ASM_SYMBOL_IN_DLSYM Platform uses assembly symbols
+ instead of C symbols in
+ dlsym()
+ACE_USES_STATIC_MFC When linking MFC as a static library is desired
+ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB Platform has its standard c++
+ library in the namespace std.
+ACE_USES_EXPLICIT_STD_NAMESPACE Set this when ::fclose doesn't
+ work and you have to
+ explicitly specify the std
+ namespace. This is needed
+ with the Borland 6 and earlier
+ compilers.
+ACE_USES_GPROF ACE calls getitimer before spawning
+ a new thread and setitimer
+ after spawning the thread in
+ order to overcome the problems
+ of gprof with multithreaded
+ applications. It uses the idea from
+ http://sam.zoy.org/writings/programming/gprof.html
+ACE_USES_FIFO_SEM Directs ACE to use FIFO based semaphores on
+ platforms that support this (not having full
+ POSIX semaphore support, supporting mkfifo, select
+ and fcntl).
+ACE_WSOCK_VERSION A parameter list indicating
+ the version of WinSock (e.g.,
+ "1, 1" is version 1.1).
+ACE_HAS_AIO_CALLS Platform supports POSIX aio* calls.
+ Corresponds to _POSIX_ASYNCHRONOUS_IO
+ constant in <unistd.h>.
+ACE_HAS_ALT_CUSERID Use ACE's alternate cuserid()
+ implementation since a system
+ cuserid() may not exist, or it
+ is not desirable to use it.
+ The implementation requires
+ ACE_LACKS_PWD_FUNCTIONS to be
+ undefined and that the
+ geteuid() system call exists.
+ACE_HAS_DINKUM_STL Using the Dinkum STL library
+ACE_HAS_HEADER_ALLOCATED_CLASS_STATIC_CONST_INT_STOREAGE
+ Non-C++ Complient compilers that automatically
+ provide storeage for class static const int
+ when their declaration is seen. I.e. they object
+ to explicit definitions being seen in the .cpp
+ file.
+ACE_DEFAULT_THREAD_KEYS Number of TSS keys, with
+ ACE_HAS_TSS_EMULATION _only_.
+ Defaults to 64.
+ACE_DEFAULT_THREAD_STACKSIZE Default stack size specified for the
+ ACE thread spawning methods. Defaults
+ to 0, which defers to OS defaults.
+ACE_DEFAULT_LD_SEARCH_PATH Specify the platform default search
+ paths. This macro should only be
+ defined on platforms that don't
+ support environment variables at all
+ (i.e., Windows CE.)
+ACE_THREADS_DONT_INHERIT_LOG_MSG Specify this if you don't want
+ threads to inherit parent
+ thread's ACE_Log_Msg
+ properties.
+ACE_THREAD_MANAGER_USES_SAFE_SPAWN Disable the "check before lock" feature
+ in ACE_Thread_Manager. Defining this
+ macro avoids a potential race condition
+ on platforms with aggressive read/write
+ reordering.
+ACE_HAS_CPU_SET_T Platform delivers cpu_set_t.
+ACE_HAS_PRIOCNTL OS has priocntl (2).
+ACE_HAS_RECURSIVE_MUTEXES Mutexes are inherently recursive
+ (e.g., Win32)
+ACE_HAS_NONRECURSIVE_MUTEXES In addition to recursive mutexes,
+ platform has non-recursive ones also.
+ACE_HAS_RECV_TIMEDWAIT Platform has the MIT pthreads
+ APIs for
+ACE_HAS_RECVFROM_TIMEDWAIT timed send/recv operations
+ACE_HAS_RECVMSG_TIMEDWAIT
+ACE_HAS_RLIMIT_RESOURCE_ENUM Platform has enum instead of
+ int for first argument to
+ ::{get,set}rlimit (). The
+ value of this macro is the
+ enum definition, e.g., enum
+ __rlimit_resource, for Linux
+ glibc 2.0.
+ACE_HAS_RUSAGE_WHO_ENUM Platform has enum instead of
+ int for first argument to
+ ::getrusage (). The value of
+ this macro is the enum
+ definition, e.g., enum
+ __rusage_who, for Linux glibc
+ 2.0.
+ACE_HAS_SCANDIR Platform has a native scandir()
+ function. Without any other scandir-
+ related settings, it's assumed that
+ the selector and comparator functions
+ accept const ACE_DIRENT pointers.
+ACE_SCANDIR_CMP_USES_VOIDPTR The OS's scandir() comparator function
+ is int (*compare)(void*, void*).
+ACE_SCANDIR_CMP_USES_CONST_VOIDPTR The OS's scandir() comparator function
+ is int (*compare)(const void*,
+ const void*).
+ACE_SCANDIR_SEL_LACKS_CONST The OS's scandir() selector function
+ is int (*selector)(ACE_DIRENT*)
+ACE_HAS_SEND_TIMEDWAIT
+ACE_HAS_SENDTO_TIMEDWAIT
+ACE_HAS_SENDMSG_TIMEDWAIT
+ACE_HAS_STDARG_THR_DEST Platform has void (*)(...)
+ prototype for
+ pthread_key_create()
+ destructor (e.g., LynxOS).
+ACE_HAS_STL_MAP_CONFLICT Used when users want to
+ compile ACE with STL and STL
+ map class conflicts with
+ <net/if.h> map struct.
+ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS Platform/compiler supports
+ Win32 structural exceptions
+ACE_HAS_READ_TIMEDWAIT
+ACE_HAS_READV_TIMEDWAIT
+ACE_HAS_WRITE_TIMEDWAIT
+ACE_HAS_WRITEV_TIMEDWAIT
+ACE_HAS_4_4BSD_SENDMSG_RECVMSG Platform has BSD 4.4
+ sendmsg()/recvmsg() APIs.
+ACE_HAS_P_READ_WRITE Platform has pread() and
+ pwrite() support
+ACE_HAS_AIX_BROKEN_SOCKET_HEADER Platform, such as AIX4, needs
+ to wrap #include of
+ sys/socket.h with
+ #undef/#define of
+ __cplusplus.
+ACE_HAS_AIX_HI_RES_TIMER Platform has AIX4
+ ::read_real_time ()
+ACE_HAS_ALLOCA Compiler/platform supports
+ alloca()
+ACE_HAS_ALLOCA_H Compiler/platform has
+ <alloca.h>
+ACE_HAS_ALPHA_TIMER CPU is an Alpha, with the rpcc
+ instruction to read the tick timer.
+ Limited to 32 bits, so not recommended.
+ACE_HAS_AUTOMATIC_INIT_FINI Compiler/platform correctly
+ calls init()/fini() for shared
+ libraries
+ACE_HAS_BIG_FD_SET Compiler/platform has typedef
+ u_long fdmask (e.g., Linux and
+ SCO).
+ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+ Compiler handles explicit calling of
+ template destructor correctly. See
+ "ace/OS.h" for details.
+ACE_HAS_BROKEN_ACCEPT_ADDR Platform can't correctly deal
+ with a NULL addr to accept()
+ (e.g, VxWorks).
+ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS Compiler can't handle const char *
+ as rvalue in conditional operator.
+ACE_HAS_BROKEN_CTIME Compiler/platform uses macro
+ for ctime (e.g., MVS)
+ACE_HAS_BROKEN_DGRAM_SENDV Platform sendv() does not work
+ properly with datagrams,
+ i.e. it fails when the iovec
+ size is IOV_MAX.
+ACE_HAS_BROKEN_HPUX_TEMPLATES Earlier versions of HP/UX C++
+ are damned...
+ACE_HAS_BROKEN_MAP_FAILED Platform doesn't cast MAP_FAILED
+ to a void *.
+ACE_HAS_BROKEN_MSG_H Platform headers don't support
+ <msg.h> prototypes
+ACE_HAS_BROKEN_MMAP_H HP/UX does not wrap the
+ mmap(2) header files with
+ extern "C".
+ACE_HAS_BROKEN_NESTED_TEMPLATES MSVC has trouble with defining
+ STL containers for nested
+ structs and classes
+ACE_HAS_BROKEN_POSIX_TIME Platform defines struct
+ timespec in <sys/timers.h>
+ACE_HAS_BROKEN_RANDR OS/compiler's header files are
+ inconsistent with libC
+ definition of rand_r().
+ACE_HAS_BROKEN_T_ERROR Compiler/platform has the wrong
+ prototype for t_error(), i.e.,
+ t_error(char *) rather than
+ t_error(const char *).
+ACE_HAS_BSTRING Platform has <bstring.h>
+ (which contains bzero()
+ prototype)
+ACE_HAS_BYTESEX_H Platform has <bytesex.h>.
+ACE_HAS_CANCEL_IO Platform supports the Win32
+ CancelIO() function (WinNT 4.0
+ and beyond).
+ACE_HAS_CHARPTR_DL OS/platform uses char * for
+ dlopen/dlsym args, rather than
+ const char *.
+ACE_HAS_CHARPTR_SOCKOPT OS/platform uses char * for
+ sockopt, rather than const
+ char *
+ACE_HAS_CLOCK_GETTIME Platform supports POSIX.1b
+ clock_gettime () at least for clock-id CLOCK_REALTIME
+ACE_HAS_CLOCK_GETTIME_MONOTONIC Platform supports POSIX.1b
+ clock_gettime () with the clock-id CLOCK_MONOTONIC
+ACE_HAS_CLOCK_SETTIME Platform supports POSIX.1b
+ clock_settime ()
+ACE_HAS_CONFLICTING_XTI_MACROS OS's XTI header file defines some
+ TCP-related macros that netinet/tcp.h
+ also defines, but they conflict
+ (only seen on HP-UX 11).
+ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES Prototypes for both signal()
+ and struct sigaction are
+ consistent.
+ACE_HAS_CPLUSPLUS_HEADERS Compiler/platform has
+ correctly prototyped header
+ files
+ACE_HAS_DIRENT Compiler/platform has Dirent
+ iterator functions
+ACE_HAS_DLFCN_H_BROKEN_EXTERN_C For platforms, e.g., RedHat
+ 4.2/Linux 2.0.30/Alpha, that
+ don't declare dl* functions as
+ extern "C" in dlfcn.h.
+ACE_HAS_DLL Build ACE using the frigging
+ PC DLL nonsense...
+ACE_HAS_EBCDIC Compile in the ACE code set classes
+ that support EBCDIC.
+ACE_HAS_EXCEPTIONS Compiler supports C++
+ exception handling
+ACE_HAS_BROKEN_UNEXPECTED_EXCEPTIONS Compiler does not call
+ unexpected exception handler
+ if exception not listed in
+ exception specification is
+ thrown. In particular, the
+ exception specification is not
+ respected.
+ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT When a base-class is a
+ specialization of a class template
+ then this class template must be
+ explicitly exported
+ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION For the GCC compiler
+ on AIX, HPUX and VxWorks we have to
+ explicitly instantiate static template
+ members else we get multiple instances
+ of the same static.
+ACE_HAS_GETPAGESIZE Platform supports
+ getpagesize() call (otherwise,
+ ACE_PAGE_SIZE must be defined,
+ except on Win32)
+ACE_HAS_GETRUSAGE Platform supports the
+ getrusage() system call.
+ACE_HAS_GETRUSAGE_PROTOTYPE Platform has a getrusage ()
+ prototype in sys/resource.h
+ that differs from the one in
+ ace/OS.i.
+ACE_HAS_GNU_CSTRING_H Denotes that GNU has cstring.h
+ as standard which redefines
+ memchr()
+ACE_HAS_GPERF The GPERF utility is compiled
+ for this platform
+ACE_HAS_GETIFADDRS This platform has ifaddrs.h and
+ the getifaddrs() function. This
+ is used in preference to
+ the SIOCGIFCONF ioctl call, since
+ it is much simpler and supports
+ IPv6 and non-IP interfaces better.
+ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT Optimize
+ ACE_Handle_Set::count_bits for
+ select() operations (common
+ case)
+ACE_HAS_LLSEEK Platform supports llseek.
+ACE_HAS_HI_RES_TIMER Compiler/platform supports
+ SunOS high resolution timers
+ACE_HAS_IDTYPE_T Compiler/platform supports
+ idtype_t.
+ACE_HAS_INLINED_OSCALLS Inline all the static class OS
+ methods to remove call
+ overhead
+ACE_HAS_IP_MULTICAST Platform supports IP multicast
+ACE_HAS_IPV6 Platform supports IPv6.
+ACE_HAS_BROKEN_GETHOSTBYADDR_V4MAPPED gethostbyaddr does not handle
+ IPv6-mapped-IPv4 addresses
+ACE_USES_IPV4_IPV6_MIGRATION Enable IPv6 support in ACE on
+ platforms that don't have IPv6
+ turned on by default.
+ACE_HAS_IPV6_V6ONLY Platform supports the IPPROTO_IPV6
+ level IPV6_V6ONLY socket option.
+ACE_HAS_IRIX62_THREADS Platform supports the very odd
+ IRIX 6.2 threads...
+ACE_HAS_NONSTATIC_OBJECT_MANAGER Causes the ACE_Object_Manager
+ instance to be created in main
+ (int, char *[]), instead of as
+ a static (global) instance.
+ACE_HAS_THR_KEYDELETE Platform supports
+ thr_keydelete (e.g,. UNIXWARE)
+ACE_HAS_THR_MINSTACK Platform calls thr_minstack()
+ rather than thr_min_stack()
+ (e.g., Tandem).
+ACE_HAS_LIMITED_RUSAGE_T The rusage_t structure has
+ only two fields.
+ACE_HAS_LIMITED_SELECT The select is unable to deal with
+ large file descriptors.
+ACE_HAS_LINUX_NPTL Linux platform (with kernel >= 2.6.x)
+ with GLibc including new NPTL (Native
+ POSIX Thread Library).
+ This triggers extended POSIX checks
+ since the NPTL library is (almost) fully
+ POSIX compliant.
+ACE_HAS_LOG_MSG_NT_EVENT_LOG Platform supports Windows NT event
+ log so we can create an
+ ACE_Log_Msg_Backend to log to it.
+ACE_HAS_LONG_MAP_FAILED Platform defines MAP_FAILED as
+ a long constant.
+ACE_HAS_MALLOC_STATS Enabled malloc statistics
+ collection.
+ACE_HAS_MEMCHR Use native implementation of memchr.
+ACE_HAS_MINIMAL_ACE_OS Disables some #includes in ace/OS.*.
+ACE_HAS_MFC Platform supports Microsoft
+ Foundation Classes
+ACE_HAS_MSG Platform supports recvmsg and
+ sendmsg
+ACE_HAS_MT_SAFE_MKTIME Platform supports MT safe
+ mktime() call (do any of
+ them?)
+ACE_HAS_MUTEX_TIMEOUTS Compiler supports timed mutex
+ acquisitions
+ (e.g. pthread_mutex_timedlock()).
+ACE_HAS_NEW_NOTHROW Compiler offers new (nothrow).
+ACE_HAS_NONCONST_CHDIR Platform uses non-const char *
+ in call to chdir
+ACE_HAS_NONCONST_CLOCK_SETTIME Platform uses non-const
+ struct timespec * in call to
+ clock_settime
+ACE_HAS_NONCONST_OPENDIR Platform uses non-const char *
+ in call to opendir
+ACE_HAS_NONCONST_UNLINK Platform uses non-const char *
+ in call to unlink
+ACE_HAS_NONCONST_GETBY Platform uses non-const char *
+ in calls to gethostbyaddr,
+ gethostbyname, getservbyname
+ACE_HAS_NONCONST_MSGSND Platform has a non-const
+ parameter to msgsend() (e.g.,
+ SCO).
+ACE_HAS_NONCONST_READV Platform omits const qualifier from
+ iovec parameter in readv() prototype.
+ACE_HAS_NONCONST_SELECT_TIMEVAL Platform's select() uses
+ non-const timeval* (only found
+ on Linux right now)
+ACE_HAS_NONCONST_SENDMSG Platform omits const qualifier
+ from msghdr parameter in sendmsg()
+ prototype.
+ACE_HAS_NONCONST_SETRLIMIT Platform omits const qualifier
+ from rlimit parameter in setrlimit()
+ prototype.
+ACE_HAS_NONCONST_STAT Platform's stat function has non const
+ name argument
+ACE_HAS_NONCONST_SWAB Platform's swab function has non
+ const src argument
+ACE_HAS_NONCONST_WRITEV Platform omits const qualifier from
+ iovec parameter in writev() prototype.
+ACE_HAS_OLD_MALLOC Compiler/platform uses old
+ malloc()/free() prototypes
+ (ugh)
+ACE_HAS_ONLY_SCHED_FIFO Platform, e.g., HP NonStop OSS,
+ only supports SCHED_FIFO
+ POSIX scheduling policy.
+ACE_HAS_ONLY_SCHED_OTHER Platform, e.g., Solaris 2.5,
+ only supports SCHED_OTHER
+ POSIX scheduling policy.
+ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R Uses ctime_r & asctime_r with
+ only two parameters
+ vs. three.
+ACE_HAS_OSF_TIMOD_H Platform supports the OSF TLI
+ timod STREAMS module
+ACE_HAS_3_PARAM_WCSTOK Platform has 3-parameter version
+ of wcstok(), which was added in
+ 1994 in the ISO C standard Normative
+ Addendum 1. Other standards like XPG4
+ define a 2 parameter wcstok().
+ACE_HAS_PENTIUM Platform is an Intel Pentium
+ microprocessor.
+ACE_HAS_POLL Platform contains <poll.h>
+ACE_HAS_POSITION_INDEPENDENT_POINTERS Platform supports
+ "position-independent" features
+ provided by ACE_Based_Pointer<>.
+ACE_HAS_POSIX_MESSAGE_PASSING Platform supports POSIX message queues.
+ Corresponds to _POSIX_MESSAGE_PASSING
+ constant in <unistd.h>.
+ACE_HAS_POSIX_NONBLOCK Platform supports POSIX
+ O_NONBLOCK semantics
+ACE_HAS_POSIX_REALTIME_SIGNALS Platform supports POSIX RT signals.
+ Corresponds to _POSIX_REALTIME_SIGNALS
+ constant in <unistd.h>.
+ACE_HAS_POSIX_SEM Platform supports POSIX
+ real-time semaphores (e.g.,
+ VxWorks and Solaris). Corresponds
+ to _POSIX_SEMAPHORES constant
+ in <unistd.h>
+ACE_HAS_POSIX_SEM_TIMEOUT Platform supports timed wait operation
+ on POSIX realtime semaphores.
+ACE_HAS_POSIX_TIME Platform supports the POSIX
+ struct timespec type
+ACE_HAS_PROC_FS Platform supports the /proc
+ file system and defines tid_t
+ in <sys/procfs.h>
+ACE_HAS_POWERPC_TIMER Platform supports PowerPC
+ time-base register.
+ACE_HAS_PRUSAGE_T Platform supports the
+ prusage_t struct
+ACE_HAS_PTHREADS Platform supports POSIX
+ Pthreads, of one form or
+ another. This macro says the
+ platform has a pthreads
+ variety - should also define
+ one of the below to say which
+ one. Also may need some
+ ACE_HAS_... thing for
+ extensions.
+ACE_HAS_PTHREADS_DRAFT4 Platform's 'Pthreads' is .4a draft 4
+ACE_HAS_PTHREADS_DRAFT6 Platform's 'Pthreads' is .4a draft 6
+ACE_HAS_PTHREADS_DRAFT7 Platform's 'Pthreads' is .1c draft 7
+ACE_HAS_PTHREADS_STD Platform supports POSIX.1c-1995 threads
+ (This is the final standard
+ Pthreads).
+ACE_HAS_PTHREADS_UNIX98_EXT Platform has the UNIX98 extensions to
+ Pthreads (rwlocks)
+ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP Platform has
+ pthread_attr_setcreatesuspend_np().
+ACE_HAS_PTHREAD_CONDATTR_SETKIND_NP Platform has pthread_condattr_setkind_np().
+ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP Platform has
+ pthread_mutexattr_setkind_np().
+ACE_HAS_PTHREAD_GETCONCURRENCY Platform has pthread_getconcurrency().
+ACE_HAS_PTHREAD_SETCONCURRENCY Platform has pthread_setconcurrency().
+ACE_HAS_PTHREAD_PROCESS_ENUM pthread.h declares an enum with
+ PTHREAD_PROCESS_PRIVATE and
+ PTHREAD_PROCESS_SHARED values.
+ACE_HAS_PTHREAD_SETSTACK Platform has pthread_attr_setstack().
+ACE_HAS_PTHREAD_NP_H Platform has <pthread_np.h> FreeBSD
+ declares non-portable (*_np) pthread
+ functions in this header.
+ACE_HAS_PURIFY Purify'ing. Set by wrapper_macros.GNU.
+ACE_HAS_QUANTIFY Quantify'ing. Set by wrapper_macros.GNU.
+ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS Platform will recurse
+ infinitely on thread exits
+ from TSS cleanup routines
+ (e.g., AIX).
+ACE_HAS_REENTRANT_FUNCTIONS Platform supports reentrant
+ functions (i.e., all the POSIX
+ *_r functions).
+ACE_HAS_XPG4_MULTIBYTE_CHAR Platform has support for
+ multi-byte character support
+ compliant with the XPG4
+ Worldwide Portability
+ Interface wide-character
+ classification.
+ACE_HAS_REGEX Platform supports the POSIX
+ regular expression library
+ACE_HAS_DLSYM_SEGFAULT_ON_INVALID_HANDLE For OpenBSD: The dlsym call
+ segfaults when passed an invalid
+ handle. Other platforms handle
+ this more gracefully.
+ACE_HAS_SELECT_H Platform has special header for select().
+ACE_USE_SELECT_REACTOR_FOR_REACTOR_IMPL For Win32: Use Select_Reactor
+ as default implementation of
+ Reactor instead of
+ WFMO_Reactor.
+ACE_HAS_SEMUN Compiler/platform defines a
+ union semun for SysV shared
+ memory
+ACE_HAS_SET_T_ERRNO Platform has a function to set
+ t_errno (e.g., Tandem).
+ACE_HAS_SIGACTION_CONSTP2 Platform's sigaction() function takes
+ const sigaction* as 2nd parameter.
+ACE_HAS_SIGINFO_T Platform supports SVR4
+ extended signals
+ACE_HAS_SIGSUSPEND Platform supports sigsuspend()
+ACE_HAS_SIGISMEMBER_BUG Platform has bug with
+ sigismember() (HP/UX 11).
+ACE_HAS_SIG_MACROS Platform/compiler has macros
+ for sig{empty,fill,add,del}set
+ (e.g., SCO and FreeBSD)
+ACE_HAS_SIGNAL_OBJECT_AND_WAIT Platform supports the Win32
+ SignalObjectAndWait() function
+ (WinNT 4.0 and beyond).
+ACE_HAS_SIGWAIT Platform/compiler has the
+ sigwait(2) prototype
+ACE_HAS_SIG_ATOMIC_T Compiler/platform defines the
+ sig_atomic_t typedef
+ACE_HAS_SIG_C_FUNC Compiler requires extern "C"
+ functions for signals.
+ACE_HAS_SIZET_SOCKET_LEN OS/compiler uses size_t *
+ rather than int * for socket
+ lengths
+ACE_HAS_SOCKADDR_IN_SIN_LEN Platform has sin_len member in struct
+ sockaddr_in.
+ACE_HAS_SOCKADDR_IN6_SIN_LEN Platform has sin6_len member in struct
+ sockaddr_in6.
+ACE_HAS_SOCKADDR_MSG_NAME Platform requires (struct
+ sockaddr *) for msg_name field
+ of struct msghdr.
+ACE_HAS_SOCKLEN_T Platform provides socklen_t
+ type, such as Linux with
+ glibc2.
+ACE_HAS_SOCK_BUF_SIZE_MAX Platform limits the maximum socket
+ message size.
+ACE_HAS_SPARCWORKS_401_SIGNALS Compiler has brain-damaged
+ SPARCwork SunOS 4.x signal
+ prototype...
+ACE_HAS_SSIZE_T Compiler supports the ssize_t
+ typedef
+ACE_HAS_STHREADS Platform supports Solaris
+ threads
+ACE_HAS_STANDARD_CPP_LIBRARY Platform/compiler supports
+ Standard C++ Library
+ACE_HAS_STDCPP_STL_INCLUDES Standard C++ headers can be
+ included in the standard way.
+ e.g. #include <vector>
+ACE_HAS_STRBUF_T Compiler/platform supports
+ struct strbuf
+ACE_HAS_STRDUP_EMULATION Use ACE's strdup() emulation (even
+ if platform has a native strdup()).
+ This is useful if you need control
+ over what memory allocator is used.
+ACE_HAS_WCSDUP_EMULATION Use ACE's wcsdup() emulation (even
+ if platform has a native wcsdup()).
+ This is useful if you need control
+ over what memory allocator is used.
+ACE_HAS_STRNLEN Platform supports strnlen(3).
+ACE_HAS_STREAMS Platform supports STREAMS
+ACE_HAS_STREAM_PIPES Platform supports STREAM pipes
+ACE_HAS_STRERROR Compiler/platform supports strerror ()
+ACE_HAS_STRICT Use the STRICT compilation mode on Win32.
+ACE_HAS_STRING_CLASS Platform/Compiler supports a
+ String class (e.g., GNU or
+ Win32).
+ACE_HAS_STRUCT_NETDB_DATA Compiler/platform has strange
+ hostent API for socket *_r()
+ calls
+ACE_HAS_SUNOS4_SIGNAL_T Compiler has horrible SunOS
+ 4.x signal handlers...
+ACE_HAS_SVR4_DYNAMIC_LINKING Compiler/platform supports
+ SVR4 dynamic linking semantics
+ACE_HAS_SVR4_GETTIMEOFDAY Compiler/platform supports
+ SVR4 gettimeofday() prototype
+ACE_HAS_SVR4_SIGNAL_T Compiler/platform supports
+ SVR4 signal typedef
+ACE_HAS_SVR4_TLI Compiler/platform supports
+ SVR4 TLI; that is, TLI with extensions
+ like t_getname(). This is sometimes
+ used as a pseudonym for TLI on SunOS4.
+ This is a modifier to ACE_HAS_TLI and
+ isn't used if ACE_HAS_XTI is set.
+ACE_HAS_SYSCALL_GETRUSAGE HP/UX has an undefined syscall
+ for GETRUSAGE...
+ACE_HAS_SYSENT_H Platform provides <sysent.h>
+ header
+ACE_HAS_SYSINFO Platform supports system
+ configuration information
+ACE_HAS_SYSV_IPC Platform supports System V IPC
+ (most versions of UNIX, but
+ not Win32)
+ACE_HAS_SYS_ERRLIST Platform/compiler supports
+ _sys_errlist symbol
+ACE_HAS_SYS_FILIO_H Platform provides
+ <sys/filio.h> header
+ACE_HAS_SYS_LOADAVG_H Compiler/platform contains the
+ <sys/loadavg.h> file.
+ACE_HAS_SYS_PSTAT_H Compiler/platform contains the
+ <sys/pstat.h> file.
+ACE_HAS_SYS_SIGLIST Compiler/platform supports
+ _sys_siglist array
+ACE_HAS_SYS_SOCKIO_H Compiler/platform provides the
+ sockio.h file
+ACE_HAS_SYS_SYSCALL_H Compiler/platform contains the
+ <sys/syscall.h> file.
+ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA Compiler's template
+ instantiation mechanism
+ supports the use of "#pragma
+ instantiate". Edison Design
+ Group compilers, e.g., SGI C++
+ and Green Hills 1.8.8 and
+ later, support this.
+ACE_HAS_TEMPLATE_SPECIALIZATION Compiler implements template
+ specialization
+ACE_HAS_TEMPLATE_TYPEDEFS Compiler implements templates
+ that support typedefs inside
+ of classes used as formal
+ arguments to a template
+ class.
+ACE_HAS_TERMIO Platform has terminal ioctl
+ flags like TCGETS and TCSETS and
+ termio struct.
+ACE_HAS_TERMIOS Platform has POSIX terminal
+ interface and termios struct.
+ACE_HAS_LAZY_MAP_MANAGER ACE supports lazy Map Managers
+ that allow deletion of entries
+ during active iteration.
+ACE_HAS_THREADS Platform supports threads
+ACE_HAS_THREAD_SAFE_ACCEPT Platform allows multiple
+ threads to call accept() on
+ the same port (e.g., WinNT).
+ACE_HAS_THREAD_SELF Platform has thread_self()
+ rather than pthread_self()
+ (e.g., DCETHREADS and AIX)
+ACE_HAS_THREAD_SPECIFIC_STORAGE Compiler/platform has
+ thread-specific storage
+ACE_HAS_THR_C_DEST The pthread_keycreate()
+ routine *must* take extern C
+ functions.
+ACE_HAS_THR_C_FUNC The pthread_create() routine
+ *must* take extern C
+ functions.
+ACE_HAS_TIMEZONE Platform/compiler supports
+ global "timezone" variable.
+ACE_HAS_TIMEZONE_GETTIMEOFDAY Platform/compiler supports
+ timezone * as second parameter
+ to gettimeofday()
+ACE_HAS_TIMOD_H Platform supports TLI timod
+ STREAMS module
+ACE_HAS_TIUSER_H Platform provides TLI tiuser.h
+ header file.
+ACE_HAS_TLI Platform supports TLI. Also
+ see ACE_TLI_TCP_DEVICE. If the
+ platform supports XTI, set ACE_HAS_XTI
+ instead of this.
+ACE_HAS_TLI_PROTOTYPES Platform provides TLI function
+ prototypes
+ACE_HAS_TR24731_2005_CRT The platform provides an implementation
+ of C99 draft TR24731 (October 2005),
+ C run-time with more secure parameters.
+ACE_HAS_TSS_EMULATION ACE provides TSS emulation.
+ See also
+ ACE_DEFAULT_THREAD_KEYS.
+ACE_HAS_UALARM Platform supports ualarm()
+ACE_HAS_UCONTEXT_T Platform supports ucontext_t
+ (which is used in the extended
+ signal API).
+ACE_HAS_UNION_WAIT The wait() system call takes a
+ (union wait *) rather than int
+ *
+ACE_HAS_UNIXWARE_SVR4_SIGNAL_T Has inconsistent SVR4 signal
+ stuff, but not the same as the
+ other platforms
+ACE_HAS_VALGRIND Running with valgrind
+ACE_HAS_VERBOSE_NOTSUP Prints out console message in
+ ACE_NOTSUP. Useful for
+ tracking down origin of
+ ACE_NOTSUP.
+ACE_HAS_VERSIONED_NAMESPACE Wrap all library code within a
+ "versioned namespace" to
+ prevent symbol conflicts with
+ other versions of ACE shared
+ libraries in third party
+ libraries. Default namespace
+ name may be overridden by
+ defining preprocessor symbol
+ ACE_VERSIONED_NAMESPACE_NAME
+ to desired name.
+ACE_LACKS_INTMAX_T Platform lacks the intmax_t type
+ACE_LACKS_UINTMAX_T Platform lacks the uintmax_t type.
+ACE_LACKS_INTPTR_T Platform lacks the intptr_t type
+ACE_LACKS_UINTPTR_T Platform lacks the uintptr_t type.
+
+ACE_HAS_INT8_T Platform provides the int8_t type.
+ACE_HAS_INT16_T Platform provides the int16_t type.
+ACE_HAS_INT32_T Platform provides the int32_t type.
+ACE_HAS_INT64_T Platform provides the int64_t type.
+ACE_HAS_UINT8_T Platform provides the uint8_t type.
+ACE_HAS_UINT16_T Platform provides the uint16_t type.
+ACE_HAS_UINT32_T Platform provides the uint32_t type.
+ACE_HAS_UINT64_T Platform provides the uint64_t type.
+
+ACE_INT8_TYPE Specific type to use for ACE_INT8.
+ If not defined, ACE will attempt to
+ determine the correct type.
+ACE_INT16_TYPE Specific type to use for ACE_INT16.
+ If not defined, ACE will attempt to
+ determine the correct type.
+ACE_INT32_TYPE Specific type to use for ACE_INT32.
+ If not defined, ACE will attempt to
+ determine the correct type.
+ACE_INT64_TYPE Specific type to use for ACE_INT64.
+ If not defined, ACE will attempt to
+ determine the correct type.
+ACE_UINT8_TYPE Specific type to use for ACE_UINT8.
+ If not defined, ACE will attempt to
+ determine the correct type.
+ACE_UINT16_TYPE Specific type to use for ACE_UINT16.
+ If not defined, ACE will attempt to
+ determine the correct type.
+ACE_UINT32_TYPE Specific type to use for ACE_UINT32.
+ If not defined, ACE will attempt to
+ determine the correct type.
+ACE_UINT64_TYPE Specific type to use for ACE_UINT64.
+ If not defined, ACE will attempt to
+ determine the correct type.
+
+ACE_INT8_FORMAT_SPECIFIER String literal containing *printf
+ format specifier (including the '%')
+ to be used for ACE_INT8 values. If
+ not defined, ACE will attempt to
+ determine the correct setting.
+ACE_INT16_FORMAT_SPECIFIER String literal containing *printf
+ format specifier (including the '%')
+ to be used for ACE_INT16 values. If
+ not defined, ACE will attempt to
+ determine the correct setting.
+ACE_INT32_FORMAT_SPECIFIER String literal containing *printf
+ format specifier (including the '%')
+ to be used for ACE_INT32 values. If
+ not defined, ACE will attempt to
+ determine the correct setting.
+ACE_INT64_FORMAT_SPECIFIER String literal containing *printf
+ format specifier (including the '%')
+ to be used for ACE_INT64 values. If
+ not defined, ACE will attempt to
+ determine the correct setting.
+ACE_UINT8_FORMAT_SPECIFIER String literal containing *printf
+ format specifier (including the '%')
+ to be used for ACE_UINT8 values. If
+ not defined, ACE will attempt to
+ determine the correct setting.
+ACE_UINT16_FORMAT_SPECIFIER String literal containing *printf
+ format specifier (including the '%')
+ to be used for ACE_UINT16 values. If
+ not defined, ACE will attempt to
+ determine the correct setting.
+ACE_UINT32_FORMAT_SPECIFIER String literal containing *printf
+ format specifier (including the '%')
+ to be used for ACE_UINT32 values. If
+ not defined, ACE will attempt to
+ determine the correct setting.
+ACE_UINT64_FORMAT_SPECIFIER String literal containing *printf
+ format specifier (including the '%')
+ to be used for ACE_UINT64 values. If
+ not defined, ACE will attempt to
+ determine the correct setting.
+
+ACE_HAS_VOIDPTR_GETTIMEOFDAY Platform/compiler supports
+ void * as second parameter
+ to gettimeofday
+ACE_HAS_VOIDPTR_MMAP Platform requires void * for
+ mmap().
+ACE_HAS_VOIDPTR_SOCKOPT OS/compiler uses void * arg 4
+ setsockopt() rather than const
+ char *
+ACE_HAS_WCSNLEN Platform supports wcsnlen(3).
+ACE_HAS_WIN32_OVERLAPPED_IO Platform has Windows overlapped I/O;
+ requires I/O completion ports.
+ACE_HAS_WIN32_TRYLOCK The Win32 platform support
+ TryEnterCriticalSection()
+ (WinNT 4.0 and beyond)
+ACE_HAS_WINSOCK2 The Win32 platform supports
+ WinSock 2.0
+ACE_HAS_XLI Platform has the XLI version
+ of TLI
+ACE_HAS_XTI Platform has XTI
+ (X/Open-standardized superset
+ of TLI). Implies ACE_HAS_TLI
+ but uses a different header
+ file.
+ACE_INITIALIZE_MEMORY_BEFORE_USE Memory is explicitly initialized before
+ use. Useful when using a profiler like
+ purify or valgrind
+ACE_HRTIME_T_IS_BASIC_TYPE ACE_hrtime_t is a basic type that
+ doesn't require ACE_U64_TO_U32
+ conversion
+ACE_LACKS_ACCESS Platform lacks access() (e.g.,
+ VxWorks and Chorus)
+ACE_LACKS_ACE_IOSTREAM Platform can not build
+ ace/IOStream{,_T}.cpp. This
+ does not necessarily mean that
+ the platform does not support
+ iostreams.
+ACE_LACKS_AUTO_MMAP_REPLACEMENT No system support for replacing any
+ previous mappings.
+ACE_LACKS_BSEARCH Compiler/platform lacks the
+ standard C library bsearch()
+ function
+ACE_LACKS_CLEARERR Platform lacks the clearerr system
+ call.
+ACE_LACKS_CLOSEDIR Platform lacks closedir and the closedir
+ emulation must be used
+ACE_LACKS_OPENDIR Platform lacks opendir and the opendir
+ emulation must be used
+ACE_LACKS_READDIR Platform lacks readdir and the readdir
+ emulation must be used
+ACE_LACKS_CMSG_DATA_MACRO Platform has
+ ACE_HAS_4_4BSD_SENDMSG_RECVMSG but does
+ not define CMSG_DATA (cmsg) macro.
+ACE_LACKS_CMSG_DATA_MEMBER Platform has
+ ACE_HAS_4_4BSD_SENDMSG_RECVMSG but its
+ cmsghdr structure does not contain
+ an 'unsigned char cmsg_data[0]'
+ member. (This may be
+ 'unsigned char __cmsg_data[0]' on some
+ platforms, in which case we need
+ another macro.)
+ACE_LACKS_COND_TIMEDWAIT_RESET pthread_cond_timedwait does
+ *not* reset the time argument
+ when the lock is acquired.
+ACE_LACKS_CONST_STRBUF_PTR Platform uses struct strbuf *
+ rather than const struct
+ strbuf * (e.g., HP/UX 10.x)
+ACE_LACKS_CONST_TIMESPEC_PTR Platform forgot const in
+ cond_timewait (e.g., HP/UX).
+ACE_LACKS_COND_T Platform lacks condition
+ variables (e.g., Win32 and
+ VxWorks)
+ACE_LACKS_CONDATTR_PSHARED Platform has no implementation
+ of
+ pthread_condattr_setpshared(),
+ even though it supports
+ pthreads!
+ACE_LACKS_DIFFTIME Platform lacks difftime() implementation
+ACE_LACKS_DUP2 Platform lacks dup2().
+ACE_LACKS_FCNTL Platform lacks POSIX-style fcntl ().
+ACE_LACKS_FSYNC Platform lacks fsync().
+ACE_LACKS_INLINE_FUNCTIONS Platform can't handle "inline"
+ keyword correctly.
+ACE_LACKS_EXEC Platform lacks the exec()
+ family of system calls (e.g.,
+ Win32, VxWorks, Chorus)
+ACE_LACKS_FILELOCKS Platform lacks file locking
+ mechanism
+ACE_LACKS_FLOATING_POINT Platform does not support
+ floating point operations
+ (e.g., certain Chorus hardware
+ platforms)
+ACE_LACKS_FORK Platform lacks the fork()
+ system call (e.g., Win32,
+ VxWorks, Chorus)
+ACE_LACKS_GETOPT_PROTOTYPE Platform lacks the getopt()
+ prototype (e.g., LynxOS)
+ACE_LACKS_GETPGID Platform lacks getpgid() call
+ (e.g., Win32, Chorus, and
+ FreeBSD).
+ACE_LACKS_GETSERVBYNAME Platforms lacks
+ getservbyname() (e.g., VxWorks
+ and Chorus).
+ACE_LACKS_GETIPNODEBYADDR Platform lacks getipnodebyaddr().
+ACE_LACKS_GETIPNODEBYNAME Platform lacks getipnodebyname().
+ACE_LACKS_INET_ATON Platform lacks the inet_aton()
+ function.
+ACE_LACKS_INET_ATON_PROTOTYPE Platform/compiler lacks the
+ inet_aton() prototype (e.g.,
+ LynxOS)
+ACE_LACKS_IOSTREAMS_TOTALLY Iostreams are not supported
+ adequately on the given platform.
+ACE_LACKS_IOSTREAM_FX iostream header does not
+ declare ipfx (), opfx (),
+ etc.
+ACE_LACKS_KEY_T Platform lacks key_t (e.g.,
+ Chorus, VxWorks, Win32)
+ACE_LACKS_LINEBUFFERED_STREAMBUF Platform lacks streambuf
+ "linebuffered ()".
+ACE_LACKS_LONGLONG_T Compiler/platform does not
+ support the signed or unsigned long
+ long datatype.
+ACE_LACKS_LSTAT Platform lacks the lstat() function.
+ACE_LACKS_MADVISE Platform lacks madvise()
+ (e.g., Linux)
+ACE_LACKS_MALLOC_H Platform lacks malloc.h
+ACE_LACKS_MEMORY_H Platform lacks memory.h (e.g.,
+ VxWorks and Chorus)
+ACE_LACKS_MKFIFO Platform lacks mkfifo() e.g.,
+ VxWorks, Chorus, pSoS, and WinNT.
+ACE_LACKS_MKTEMP Platform lacks the mktemp() function.
+ACE_LACKS_MKTEMP_PROTOTYPE Platform/compiler lacks the
+ mktemp() prototype (e.g.,
+ LynxOS)
+ACE_LACKS_MKSTEMP Platform lacks the mkstemp() function.
+ACE_LACKS_MKSTEMP_PROTOTYPE Platform/compiler lacks the
+ mkstemp() prototype (e.g.,
+ LynxOS)
+ACE_LACKS_MMAP The platform doesn't have
+ mmap(2) (e.g., SCO UNIX).
+ACE_LACKS_MODE_MASKS Platform/compiler doesn't have
+ open() mode masks.
+ACE_LACKS_MPROTECT The platform doesn't have
+ mprotect(2) (e.g., EPLX real
+ time OS from CDC (based on
+ LYNX))
+ACE_LACKS_MSG_ACCRIGHTS Platform defines ACE_HAS_MSG,
+ but lacks msg_accrights{,len}.
+ACE_LACKS_MSG_WFMO Platform lacks
+ MsgWaitForMultipleObjects
+ (only needs to be defined when
+ ACE_WIN32 is also defined).
+ACE_LACKS_MSYNC Platform lacks msync() (e.g.,
+ Linux)
+ACE_LACKS_MUTEXATTR_PSHARED Platform lacks
+ pthread_mutexattr_setpshared().
+ACE_LACKS_NAMED_POSIX_SEM Platform lacks named POSIX
+ semaphores (e.g., Chorus)
+ACE_LACKS_NETDB_REENTRANT_FUNCTIONS Platform does not support
+ reentrant netdb functions
+ (getprotobyname_r,
+ getprotobynumber_r,
+ gethostbyaddr_r,
+ gethostbyname_r,
+ getservbyname_r).
+ACE_LACKS_NEW_H OS doesn't have, or we don't want to
+ use, new.h.
+ACE_LACKS_NULL_PTHREAD_STATUS OS requires non-null status pointer
+ for ::pthread_join ().
+ACE_LACKS_NUMERIC_LIMITS Platform lacks std::numeric_limits<>.
+ACE_LACKS_PERFECT_MULTICAST_FILTERING Platform lacks IGMPv3 "perfect" filtering
+ of multicast dgrams at the socket level.
+ If == 1, ACE_SOCK_Dgram_Mcast will bind
+ the first joined multicast group to the
+ socket, and all future joins on that
+ socket will fail with an error.
+ACE_LACKS_PRAGMA_ONCE Compiler complains about #pragma once
+ACE_LACKS_PRI_T Platform lacks pri_t (e.g.,
+ Tandem NonStop UNIX).
+ACE_LACKS_PTHREAD_CANCEL Platform lacks
+ pthread_cancel().
+ACE_LACKS_PTHREAD_SIGMASK Platform lacks pthread_sigmask ().
+ACE_LACKS_PTHREAD_THR_SIGSETMASK Platform lacks
+ pthread_thr_sigsetmask (e.g.,
+ MVS, HP/UX, and OSF/1 3.2)
+ACE_LACKS_PUTENV_PROTOTYPE Platform/compiler lacks the
+ putenv() prototype (e.g.,
+ LynxOS)
+ACE_LACKS_PWD_REENTRANT_FUNCTIONS Platform lacks getpwnam_r()
+ methods (e.g., SGI 6.2).
+ACE_LACKS_SID Platform lacks setsid()
+ACE_LACKS_QSORT Compiler/platform lacks the
+ standard C library qsort()
+ function
+ACE_LACKS_RAND_REENTRANT_FUNCTIONS Platform lacks rand_r()
+ACE_LACKS_READLINK Platform lacks the readlink() function.
+ACE_LACKS_READV Platform doesn't define readv,
+ so use our own
+ACE_LACKS_RENAME Platform lacks rename().
+ACE_LACKS_RLIMIT Platform/compiler lacks
+ {get,set}rlimit() function
+ (e.g., VxWorks, Chorus, and
+ SCO UNIX)
+ACE_LACKS_RLIMIT_PROTOTYPE Platform/compiler lacks
+ {get,set}rlimit() prototypes
+ (e.g., Tandem)
+ACE_LACKS_READDIR_R Platform uses ACE_HAS_DIRENT
+ but does not have readdir_r
+ ().
+ACE_LACKS_REALPATH Platform/compiler lacks
+ realpath () function (e.g.,
+ LynxOS)
+ACE_LACKS_RECVMSG Platform lacks recvmsg()
+ (e.g., Linux)
+ACE_LACKS_RWLOCK_T Platform lacks readers/writer
+ locks.
+ACE_LACKS_RWLOCKATTR_PSHARED Platform lacks
+ pthread_rwlockattr_setpshared().
+ACE_LACKS_SBRK Platform lacks a working
+ sbrk() (e.g., Win32 and
+ VxWorks)
+ACE_LACKS_SCANDIR_PROTOTYPE Platform/compiler lacks
+ scandir() prototype
+ (e.g., LynxOS)
+ACE_LACKS_SEEKDIR Platform uses ACE_HAS_DIRENT
+ but does not have seekdir ().
+ACE_LACKS_SEMBUF_T Platform lacks struct sembuf
+ (e.g., Win32 and VxWorks)
+ACE_LACKS_SETDETACH Platform lacks
+ pthread_attr_setdetachstate()
+ (e.g., HP/UX 10.x)
+ACE_LACKS_SETSCHED Platform lacks
+ pthread_attr_setsched()
+ (e.g. MVS)
+ACE_LACKS_SIGACTION Platform lacks struct
+ sigaction (e.g., Win32 and
+ Chorus)
+ACE_LACKS_SIGNED_CHAR Platform lacks "signed char"
+ type (broken!)
+ACE_LACKS_SIGSET Platform lacks signal sets
+ (e.g., Chorus and Win32)
+ACE_LACKS_STRPTIME Platform/compiler lacks the strptime()
+ function.
+ACE_LACKS_STRCHR Platform/compiler lacks strchr()
+ACE_LACKS_WCSCHR Platform/compiler lacks wcschr()
+ACE_LACKS_STRDUP Platform/compiler lacks strdup()
+ACE_LACKS_WCSDUP Platform/compiler lacks wcsdup()
+ACE_LACKS_STRRCHR Platform/compiler lacks strrchr()
+ACE_LACKS_WCSRCHR Platform/compiler lacks wcsrchr()
+ACE_LACKS_SWAB Platform/compiler lacks
+ swab () function.
+ACE_LACKS_SYS_MSG_H Platform lacks sys/msg.h
+ (e.g., Chorus and VxWorks)
+ACE_LACKS_SYS_PARAM_H Platform lacks <sys/param.h>
+ (e.g., MVS)
+ACE_LACKS_SENDMSG Platform lacks sendmsg()
+ (e.g., Linux)
+ACE_LACKS_SI_ADDR Platform lacks the si_addr
+ field of siginfo_t (e.g.,
+ VxWorks and HP/UX 10.x)
+ACE_LACKS_SYMLINKS Platform lacks symbolic links
+ACE_LACKS_SYSV_SHMEM Platform lacks System V shared
+ memory (e.g., Win32 and
+ VxWorks)
+ACE_LACKS_SIGINFO_H Platform lacks the siginfo.h
+ include file (e.g., MVS)
+ACE_LACKS_SOCKET_BUFSIZ Platform doesn't support
+ SO_SNDBUF/SO_RCVBUF
+ACE_LACKS_SOCKETPAIR Platform lacks the
+ socketpair() call (e.g., SCO
+ UNIX)
+ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES Compiler doesn't support
+ static data member templates
+ACE_LACKS_STRCASECMP Compiler/platform lacks
+ strcasecmp() (e.g., DG/UX,
+ UNIXWARE, VXWORKS)
+ACE_LACKS_STRCASECMP_PROTOTYPE Platform/compiler lacks the
+ strcasecmp() prototype (e.g.,
+ LynxOS)
+ACE_LACKS_STRNCASECMP_PROTOTYPE Platform/compiler lacks the
+ strncasecmp() prototype (e.g.,
+ LynxOS)
+ACE_LACKS_STRRECVFD Platform doesn't define struct
+ strrecvfd.
+ACE_LACKS_SYSCALL Platform doesn't have
+ syscall() prototype
+ACE_LACKS_T_ERRNO Header files lack t_errno for
+ TLI
+ACE_LACKS_TCP_NODELAY OS does not support TCP_NODELAY.
+ACE_LACKS_TELLDIR Platform uses ACE_HAS_DIRENT
+ but does not have telldir ().
+ACE_LACKS_THREAD_STACK_SIZE Platform lacks
+ pthread_attr_setstacksize()
+ (e.g., Linux pthreads)
+ACE_LACKS_THR_CONCURRENCY_FUNCS (ONLY APPLIES TO SOLARIS)
+ Platform does not support
+ thr_getconcurrency/thr_setconcurrency
+ functions, or their implementation
+ is effectively a "no-op". This
+ notably applies for Solaris >= 5.9.
+ Note that if you build on Solaris 8
+ and run on Solaris 9+, you can
+ encounter thread creation errors
+ unless you rebuild on the target
+ platform.
+ACE_LACKS_TIMEDWAIT_PROTOTYPES MIT pthreads platform lacks
+ the timedwait prototypes
+ACE_LACKS_TIMESPEC_T Platform does not define
+ timepec_t as a typedef for
+ struct timespec.
+ACE_LACKS_TRUNCATE Platform doesn't have truncate()
+ (e.g., vxworks)
+ACE_LACKS_U_LONGLONG_T Platform does not have
+ u_longlong_t typedef, and
+ "sun" is defined.
+ACE_LACKS_UALARM_PROTOTYPE Platform/compiler lacks the
+ ualarm() prototype (e.g.,
+ Solaris)
+ACE_LACKS_CHAR_RIGHT_SHIFTS Compiler does not have any istream
+ operator>> for chars, u_chars, or
+ signed chars.
+ACE_LACKS_CHAR_STAR_RIGHT_SHIFTS Compiler does not have
+ operator>> (istream &, u_char *) or
+ operator>> (istream &, signed char *)
+ACE_LACKS_UCONTEXT_H Platform lacks the ucontext.h
+ file
+ACE_LACKS_UMASK Platform lacks umask function
+ACE_LACKS_UNBUFFERED_STREAMBUF Platform lacks streambuf
+ "unbuffered ()".
+ACE_LACKS_UNISTD_H Platform lacks the unistd.h
+ file (e.g., VxWorks and Win32)
+ACE_LACKS_UNIX_DOMAIN_SOCKETS ACE platform has no UNIX
+ domain sockets
+ACE_LACKS_UNIX_SIGNALS Platform lacks full signal
+ support (e.g., Win32 and
+ Chorus).
+ACE_LACKS_UNSIGNEDLONGLONG_T Compiler/platform does not
+ support the unsigned long
+ long datatype.
+ACE_LACKS_UTSNAME_T Platform lacks struct utsname
+ (e.g., Win32 and VxWorks)
+ACE_LACKS_UNAME Platform lacks uname calls
+ACE_LACKS_WAIT The platform lacks wait
+ACE_LACKS_WILDCARD_BIND The bind() call will not
+ select the port if it's 0.
+ACE_LACKS_WIN32_GETPROCESSTIMES The Windows platform doesn't have
+ GetProcessTimes().
+ACE_LACKS_WIN32_MOVEFILEEX The Windows platform doesn't have
+ MoveFileEx().
+ACE_LACKS_WIN32_SECURITY_DESCRIPTORS The Windows platform doesn't have
+ security descriptor support.
+ACE_LACKS_WRITEV Platform doesn't define
+ writev, so use our own
+
+ACE_LEGACY_MODE When defined, it will enable
+ some code that is used to
+ provide some support for
+ backwards compatibility.
+
+ACE_NEEDS_DEV_IO_CONVERSION Necessary with some compilers
+ to pass ACE_TTY_IO as
+ parameter to DEV_Connector.
+ACE_NEEDS_FUNC_DEFINITIONS Compiler requires a definition
+ for a "hidden" function, e.g.,
+ a private, unimplemented copy
+ constructor or assignment
+ operator. The SGI C++
+ compiler needs this, in
+ template classes, with
+ ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA.
+ACE_NEEDS_HUGE_THREAD_STACKSIZE Required by platforms with
+ small default stacks.
+ACE_NEEDS_LWP_PRIO_SET OS has LWPs, and when the
+ priority of a bound thread is
+ set, then the LWP priority
+ must be set also.
+ACE_NEEDS_SCHED_H Platform needs to #include
+ <sched.h>
+ to get thread scheduling
+ defs.
+
+ACE_NO_WIN32_LEAN_AND_MEAN If this is set, then ACE does not
+ define WIN32_LEAN_AND_MEAN before
+ including <windows.h>. Needed for
+ code that uses non-lean Win32
+ facilities such as COM.
+
+ACE_ONLY_LATEST_AND_GREATEST A macro that indicates that
+ the "latest and greatest"
+ features of ACE/TAO should be
+ turned on. It has been
+ replaced by ACE_LEGACY_MODE,
+ which has the opposite meaning
+ but serves the same purpose.
+
+ACE_SHM_OPEN_REQUIRES_ONE_SLASH The path specified on shm_open() must
+ have a leading, single slash and not
+ have any other slashes.
+
+ACE_WSTRING_HAS_USHORT_SUPPORT If a platform has wchar_t as a
+ separate type, then
+ ACE_WString doesn't have a
+ constructor that understands
+ an ACE_USHORT16 string. So
+ this macro enables
+ one. (mostly used my ACE Name
+ Space).
+
+ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK
+ Under QNX/RTP the objects preallocated
+ in ACE_OS_Object_Manager cannot be
+ destroyed after a fork() call.
+ Since these objects are only destroyed
+ at application shutdown we take the
+ simpler approach of not destroying
+ them at all.
+ Both QNX/RTP and LynxOS suffer from
+ this problem.
+
+ACE_LACKS_MEMBER_TEMPLATES Compiler does not support
+ member template feature.
+
+ACE_LACKS_DEPRECATED_MACROS When this define is set, macros which
+ are deprecated are not defined. Usefull
+ to check whether deprecated macros are
+ not used anymore.
+
+ACE_DONT_INIT_WINSOCK This definition defines whether or not
+ to explicitly initialize Winsock during
+ ACE::init() (i.e., whether WSAStartup()
+ is called). Some Win32 platforms have
+ dependent characteristics between
+ ACE initialization and
+ network initialization.
+
+----------------------------------------
+
+The following macros determine the svc.conf file format ACE uses.
+
+Macro Description
+----- -----------
+ACE_HAS_CLASSIC_SVC_CONF This macro forces ACE to use
+ the classic svc.conf format.
+
+ACE_HAS_XML_SVC_CONF This macro forces ACE to use the XML
+ svc.conf format.
+
+ACE_USES_CLASSIC_SVC_CONF This macro should be defined
+ as 0 or 1, depending on the
+ preferred svc.conf file
+ format. Defining this macro
+ to 0 means ACE will use XML
+ svc.conf file format.
+ Defining it to 1 will force
+ ACE to use the classic
+ svc.conf format.
+ ** This macro takes precedence
+ ** over previous two macros.
+
+----------------------------------------
+The following is a partial list of where some of these macros are used
+in the code. This list was originally compiled by Jam Hamidi
+(jh1@core01.osi.com). It is now hopelessly out of date. Hopefully,
+someone will come along and update it....
+
+ACE_HAS_ALLOCA:
+---------------
+
+ Used in:
+ libsrc/IPC_SAP/SOCK_SAP/SOCK_Connect.C
+ for allocation of iovp
+A
+ libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Msg.C
+ for alocation of iovp
+
+ In solaris:
+ alloca() allocates size bytes of space in the stack frame of
+ the caller, and returns a pointer to the allocated block.
+ This temporary space is automatically freed when the caller
+ returns. Note: if the allocated block is beyond the current
+ stack limit, the resulting behavior is undefined.
+
+ In HPUX:
+ no equivalent.
+
+ Notes:
+ in HPUX it has to do new and delete. Affects performance.
+
+
+ACE_HAS_AUTOMATIC_INIT_FINI:
+----------------------------
+
+ Used in:
+ libsrc/Service_Configurator/Service_Repository.i
+ libsrc/Service_Configurator/Parse_Node.i
+ include/Parse_Node.i
+ include/Service_Repository.i
+
+ In solaris:
+ _init() initializes a loadable module. It is called before
+ any other routine in a loadable module.
+ _info() returns information about a loadable module.
+ _fini() should return the return value from mod_remove(9F).
+ This flag if set, doesn't do anything. If not set, forces
+ _init() and _fini() to be executed as is:
+ dlsym ((char *) handle, "_fini").
+
+ In HPUX:
+ don't set.
+ Maybe have to look into shl_load( ), shl_definesym( ),
+ shl_findsym( ), shl_gethandle( ), shl_getsymbols( ),
+ shl_unload( ), shl_get( )(3X) - explicit load of shared libraries
+ Means Service Configurator won't be available.
+ TBA.
+
+
+ACE_HAS_CPLUSPLUS_HEADERS:
+--------------------------
+
+ Used In:
+ ace/OS.h
+
+ HPUX:
+ set it.
+
+ Notes:
+ If this is not defined, libc.h and osfcn.h get included.
+ Only needed for older compiler/OS platforms that don't
+ provide standard C++ header files in /usr/include.
+
+ACE_HAS_HI_RES_TIMER:
+---------------------
+
+ Used In:
+ libsrc/Misc/High_Res_Timer.h
+ libsrc/Misc/High_Res_Timer.C
+ include/High_Res_Timer.h
+
+ In Solaris,
+ C++ wrapper around gethrtime(), which returns a long long.
+ gethrtime() returns the current high-resolution real time.
+ Time is expressed as nanoseconds since some arbitrary time
+ in the past; it is not correlated in any way to the time of
+ day, and thus is not subject to resetting, drifting, etc.
+
+ In HPUX
+ look into: getclock(), reltimer(), getitimer()
+ maybe even vtimes structure vm_utime, vm_stime ?
+
+ Notes:
+ TBA
+
+
+ACE_LACKS_T_ERRNO:
+-------------------
+
+ Used In:
+ ace/OS.h
+
+ HPUX:
+ set it.
+
+ Notes:
+ if set, adds:
+ extern int t_errno;
+
+
+ACE_HAS_POSIX_NONBLOCK:
+-----------------------
+
+ Used in:
+ ace/OS.h
+
+ HPUX:
+ set it.
+
+ Notes:
+ if defined, sets ACE_NONBLOCK and O_NONBLOCK
+ O_NONBLOCK is used in libsrc/Misc/misc.C to do a
+ fcntl (fd, F_SETFL, opt)
+ ACE_NONBLOCK is used in libsrc/IPC_SAP/FIFO_SAP/FIFO_Recv.C in the
+ disable member function and options passed to the open function
+ in libsrc/IPC_SAP/FIFO_SAP/FIFO.C
+
+
+ACE_HAS_PROC_FS:
+----------------
+
+ Used in:
+ ace/OS.h
+ libsrc/Misc/Profile_Timer.i
+
+ Notes:
+ if set, includes <sys/procfs.h>
+ the PIOCUSAGE define is used in Profile_Timer.
+
+ Solaris:
+ procfs.h defines things for the prpsinfo structure (basically to
+ do a "ps" from inside a program).
+
+ HPUX:
+ don't set: obviously a different mechanism.
+ Look into /usr/include/sys/proc.h. The structure is proc. The
+ pointer to the kernel's proc table may be obtained by
+ extern struct proc *proc, *procNPROC;
+ extern int nproc;
+
+
+ACE_HAS_PRUSAGE_T:
+------------------
+
+ Used in:
+ libsrc/Misc/Profile_Timer.h
+ libsrc/Misc/Profile_Timer.C
+
+ Notes:
+ If defined, declares the Profile_Timer class that does start(),
+ stop() and basically gets real_time, user_time, system_time for
+ an interval.
+ This stuff is highly non-portable.
+
+ HPUX:
+ don't set
+
+
+ACE_HAS_SEMUN:
+--------------
+
+ Used in:
+ libsrc/Semaphores/Semaphore_Simple.h
+
+ Notes:
+ if not defined, defines semun as:
+ union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
+ ushort *array; /* array for GETALL & SETALL */
+ };
+
+ HPUX:
+ don't set.
+ in /usr/include/sem.h:
+ /* The fourth argument to semctl() varies depending on the value of
+ its first argument. If desired, "union semun" can be declared
+ by the user, but this is not necessary since the individual
+ member can just be passed as the argument. */
+
+
+ACE_HAS_SIG_ATOMIC_T:
+---------------------
+
+ Used in:
+ ace/OS.h
+
+ Notes:
+ if not defined, does a:
+ typedef int sig_atomic_t;
+ This is used in the Reactor and service configurator.
+
+ HPUX:
+ set it.
+ in /usr/include/sys/signal.h:
+ typedef unsigned int sig_atomic_t;
+
+
+ACE_HAS_SSIZE_T:
+----------------
+
+ Used in:
+ ace/OS.h
+
+ Notes:
+ if not defined, does a
+ typedef int ssize_t;
+ used mostly in IPC_SAP. (don't confuse with size_t).
+
+ HPUX:
+ set it.
+ in /usr/include/sys/types.h
+
+
+ACE_HAS_STRBUF_T:
+-----------------
+
+ Used in:
+ include/Str_Buf.h
+
+ Notes:
+ if not defined, declares the strbuf structure as:
+ struct strbuf
+ {
+ int maxlen; /* no. of bytes in buffer */
+ int len; /* no. of bytes returned */
+ void *buf; /* pointer to data */
+ };
+
+ Solaris:
+ defined in /usr/include/sys/stropts.h
+ Sys V.4 Streams.
+ uses strbuf as parameter to putmsg, putpmsg:
+ int putmsg(int fildes, const struct strbuf *ctlptr,
+ const struct strbuf *dataptr, int flags);
+
+ HPUX:
+ don't set.
+ no SYS V.4 streams.
+
+
+ACE_HAS_STREAMS:
+----------------
+
+ Used In:
+ ace/OS.h
+ libsrc/IPC_SAP/SOCK_SAP/LSOCK.C
+
+ Notes:
+ if defined, includes <stropts.h>
+
+ HPUX:
+ don't set.
+ no SYS V.4 streams.
+
+
+ACE_HAS_STREAM_PIPES:
+---------------------
+
+ Used in:
+ libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Msg.h
+ libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Msg.C
+ libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Listener.h
+ libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Listener.C
+ libsrc/IPC_SAP/SPIPE_SAP/SPIPE.h
+ libsrc/IPC_SAP/SPIPE_SAP/SPIPE.C
+ libsrc/IPC_SAP/FIFO_SAP/FIFO_Send_Msg.h
+ libsrc/IPC_SAP/FIFO_SAP/FIFO_Send_Msg.C
+ libsrc/IPC_SAP/FIFO_SAP/FIFO_Send_Msg.i
+ libsrc/IPC_SAP/FIFO_SAP/FIFO_Recv_Msg.h
+ libsrc/IPC_SAP/FIFO_SAP/FIFO_Recv_Msg.C
+ libsrc/IPC_SAP/FIFO_SAP/FIFO_Recv_Msg.i
+
+ Notes:
+ if not set, won't be able to use the SPIPE class (IPC_SAP) with
+ rendezvous handles.
+
+ HPUX:
+ don't set.
+ No sysV.4 streams.
+
+
+ACE_HAS_STRERROR:
+-----------------
+
+ Used in:
+ ace/OS.h
+
+ Notes:
+ if not defined, does a:
+ #define strerror(err) sys_errlist[err]
+
+ Solaris:
+ /usr/include/string.h
+
+ HPUX:
+ set it.
+ in /usr/include/sys/errno.h and string.h
+ extern char *strerror (int);
+
+
+ACE_HAS_SVR4_DYNAMIC_LINKING:
+-----------------------------
+
+ Used in:
+ ace/OS.h
+ tests/Service_Configurator/CCM_App.C
+
+ Notes:
+ if defined, includes <dlfcn.h>
+ with dlopen(), dlsym(), etc..
+
+ HPUX:
+ don't set.
+ has its own:
+ shl_findsym( ), shl_gethandle( ), shl_getsymbols( ),
+ shl_unload( ), shl_get( )(3X) - explicit load of shared libraries
+
+
+ACE_HAS_SVR4_GETTIMEOFDAY:
+--------------------------
+
+ Used in:
+ ace/OS.h
+ libsrc/Reactor/Timer_Queue.i
+
+ Notes:
+ has to do with gettimeofday ().
+
+ Solaris:
+ gettimeofday (struct timeval *tp)
+
+ HPUX:
+ don't set.
+ it has gettimeofday (struct timeval *tp, struct timezone *tzp);
+ most calls do a:
+ #if defined (ACE_HAS_SVR4_GETTIMEOFDAY)
+ ::gettimeofday (&cur_time);
+ #else
+ ::gettimeofday (&cur_time, 0);
+ #endif /* ACE_HAS_SVR4_GETTIMEOFDAY */
+
+
+ACE_HAS_POLL:
+------------
+ Used in:
+ ace/OS.h
+
+ Notes:
+ #if defined (ACE_HAS_POLL)
+ #include /**/ <poll.h>
+ #endif /* ACE_HAS_POLL */
+
+ACE_USE_POLL_IMPLEMENTATION:
+------------------
+
+ Used in:
+ ace/OS.h
+
+ Notes:
+ Use the poll() event demultiplexor rather than select().
+
+ HPUX:
+ set it.
+
+
+ACE_HAS_SVR4_SIGNAL_T:
+----------------------
+
+ Used in:
+ ace/OS.h
+
+ Notes:
+ #if defined (ACE_HAS_SVR4_SIGNAL_T)
+ typedef void (*SignalHandler)(int);
+ typedef void (*SignalHandlerV)(void);
+ #elif defined (ACE_HAS_SIGNALHANDLERV_INT_ARG)
+ typedef void (*SignalHandler)(int);
+ typedef void (*SignalHandlerV)(int);
+ #else
+ #define SignalHandler SIG_PF
+ typedef void (*SignalHandlerV)(...);
+ #endif /* ACE_HAS_SVR4_SIGNAL_T */
+
+ HPUX:
+ set it.
+
+
+ACE_HAS_SVR4_TLI:
+-----------------
+
+ Used in:
+ libsrc/IPC_SAP/TLI_SAP/TLI.C
+ libsrc/IPC_SAP/TLI_SAP/TLI.h
+ libsrc/IPC_SAP/TLI_SAP/TLI_Stream.C
+
+ Notes:
+ TLI is the transport layer calls as in: t_bind(), t_open(), t_unbind(),
+ t_optmgmt(), ... in SunOS and Solaris.
+
+ HPUX:
+ don't set.
+ Not supported.
+
+
+ACE_HAS_SYS_FILIO_H:
+--------------------
+
+ Used in:
+ ace/OS.h
+
+ Notes:
+ if not defined, includes <sys/filio.h>.
+ didn't find any reference to anything in this file in the ACE code.
+
+ Solaris:
+ filio.h defines FIOCLEX, FIOASYNC, ... as _IO('f', 1), ..
+ for FIOLFS,.. solaris has this to say:
+ /*
+ * ioctl's for Online: DiskSuite.
+ * WARNING - the support for these ioctls may be withdrawn
+ * in the future OS releases.
+ */
+
+ HPUX:
+ <sys/ioctl.h> defines FIOASYNC and some other ones,
+ <sgtty.h> defines some like FIOCLEX.
+ some are never defined.
+ use #ifdef HP-UX to modify sysincludes.h
+
+
+ACE_HAS_SYS_SIGLIST:
+--------------------
+
+ Used in:
+ ace/OS.h
+ libsrc/Log_Msg/Log_Msg.C
+
+ Notes:
+ if not defined, does a:
+ extern const char **_sys_siglist;
+
+ Solaris:
+ This is an array holding signal descriptions.
+
+ HPUX:
+ don't set.
+ Some additional work is required. In libsrc/Log_Msg/Log_Msg.C,
+ sys_siglist is used regardless of ACE_HAS_SYS_SIGLIST.
+ have to add #ifdefs to remove them.
+
+
+ACE_HAS_TEMPLATE_TYPEDEFS:
+--------------------------
+
+ Used in:
+ libsrc/ASX/*.[Chi]
+
+ Notes:
+ cfront-based C++ compilers don't implement templates that support
+ classes with typedefs of other types as formal arguments. This
+ typedef uses the C++ preprocessor to work around this problem.
+
+ACE_HAS_THREADS:
+----------------
+
+ Used in:
+ libsrc/Service_Configurator/Svc_Conf.y.C
+ libsrc/Service_Configurator/Thread_Spawn.i
+ libsrc/Threads/Synch.C
+ libsrc/Threads/Synch.i
+ libsrc/Threads/Thr_Manager.i
+ libsrc/ASX/STREAM.C
+ libsrc/ASX/Queue.C
+ libsrc/ASX/Module.C
+ libsrc/ASX/Stream_Modules.C
+ libsrc/ASX/Multiplexor.C
+ libsrc/ASX/Message_List.C
+ include/Message_List.h
+ include/Module.h
+ include/Multiplexor.h
+ include/Queue.h
+ include/STREAM.h
+ include/Stream_Modules.h
+ include/Service_Types.h
+ include/Thread_Spawn.h
+ include/Synch.h
+ include/Thr_Manager.h
+
+ Notes:
+ We use Message_List.h even in a non-threaded environment.
+ our XOMessageList.h does this by #ifdefs around Threaded things.
+
+ HPUX:
+ not until 10.0.
+
+
+ACE_HAS_TIMOD_H:
+----------------
+
+ Used in:
+ ace/OS.h
+
+ Notes:
+ if defined, include <sys/timod.h>
+
+ Solaris:
+ timod is a STREAMS module for use with the Transport Inter-
+ face (TI) functions of the Network Services library. The
+ timod module converts a set of ioctl(2) calls into STREAMS
+ messages that may be consumed by a transport protocol pro-
+ vider that supports the Transport Interface. This allows a
+ user to initiate certain TI functions as atomic operations.
+
+ HPUX:
+ don't set.
+
+
+ACE_HAS_TIUSER_H:
+-----------------
+
+ Used in:
+ ace/OS.h
+
+ Notes:
+ if set, includes <tiuser.h>
+
+ Solaris:
+ in conjunction with t_bind, t_accept, etc.. transport layer.
+
+ HPUX:
+ don't set.
+
+
+ACE_USE_POLL_IMPLEMENTATION:
+----------------------------
+
+ Used in:
+ libsrc/Reactor/Reactor.i
+ include/Event_Handler.h
+ ace/OS.h
+ include/Reactor.h
+
+ Notes:
+ in the reactor, use poll instead of select. In general,
+ good thing to have set.
+
+ACE_USES_GPROF:
+----------------------------
+ Used in:
+ ace/Base_Thread_Adapter.h
+ ace/Base_Thread_Adapter.inl
+ ace/Base_Thread_Adapter.cpp
+
+ Notes:
+ When using gprof mainly on Linux, #define ACE_USES_GPROF
+ will add calls to getitimer/setitimer in order to initialize profile
+ timer and overcome the problem of gprof with multithreaded applications.
+
+ACE_QTREACTOR_CLEAR_PENDING_EVENTS:
+----------------------------
+ Used in:
+ ace/QtReactor.cpp:
+ QtReactor by default does not clear qt events pending for
+ activated socket. Clearing costs much, at least 2 hash accesses
+ in ACE, and 2 another in Qt. It is also better to not clear
+ pending events as some side effects are unknown. However,
+ when events are not clear, then some user applications may be
+ confused by handle_input/output/exception called without any
+ data eg. in ACE_Acceptor::make_svc_handler. This swithc is
+ intended to quickly fix user application which does not
+ follow some reactor rules.
+ Linux:
+ It seems linux::qt does not queue pending events. Do not define
+ this switch.
+ Windows:
+ Windows::qt queues pending events. If user application has handle_*
+ methods which cannot be called without data, then turn on this switch
+ to quickly fix the bug. However, one should seriously fix the
+ application then.
diff --git a/ACE/ace/RW_Mutex.cpp b/ACE/ace/RW_Mutex.cpp
new file mode 100644
index 00000000000..bfeac13c30b
--- /dev/null
+++ b/ACE/ace/RW_Mutex.cpp
@@ -0,0 +1,55 @@
+/**
+ * @file RW_Mutex.cpp
+ *
+ * $Id$
+ *
+ * Originally in Synch.cpp
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+
+#include "ace/RW_Mutex.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/RW_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, RW_Mutex, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_RW_Mutex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_RW_Mutex::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_RW_Mutex::ACE_RW_Mutex (int type, const ACE_TCHAR *name, void *arg)
+ : removed_ (0)
+{
+// ACE_TRACE ("ACE_RW_Mutex::ACE_RW_Mutex");
+ if (ACE_OS::rwlock_init (&this->lock_, type, name, arg) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_RW_Mutex::ACE_RW_Mutex")));
+}
+
+ACE_RW_Mutex::~ACE_RW_Mutex (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::~ACE_RW_Mutex");
+ this->remove ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/RW_Mutex.h b/ACE/ace/RW_Mutex.h
new file mode 100644
index 00000000000..1bc6b258d2b
--- /dev/null
+++ b/ACE/ace/RW_Mutex.h
@@ -0,0 +1,141 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file RW_Mutex.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_RW_MUTEX_H
+#define ACE_RW_MUTEX_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// ACE platform supports some form of threading.
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_RW_Mutex
+ *
+ * @brief Wrapper for readers/writer locks.
+ *
+ * These are most useful for applications that have many more
+ * parallel readers than writers...
+ */
+class ACE_Export ACE_RW_Mutex
+{
+public:
+ /// Initialize a readers/writer lock.
+ ACE_RW_Mutex (int type = USYNC_THREAD,
+ const ACE_TCHAR *name = 0,
+ void *arg = 0);
+
+ /// Implicitly destroy a readers/writer lock
+ ~ACE_RW_Mutex (void);
+
+ /**
+ * Explicitly destroy a readers/writer lock. Note that only one
+ * thread should call this method since it doesn't protect against
+ * race conditions.
+ */
+ int remove (void);
+
+ /// Acquire a read lock, but block if a writer hold the lock.
+ int acquire_read (void);
+
+ /// Acquire a write lock, but block if any readers or a
+ /// writer hold the lock.
+ int acquire_write (void);
+
+ /**
+ * Conditionally acquire a read lock (i.e., won't block). Returns
+ * -1 on failure. If we "failed" because someone else already had
+ * the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_read (void);
+
+ /// Conditionally acquire a write lock (i.e., won't block).
+ int tryacquire_write (void);
+
+ /**
+ * Conditionally upgrade a read lock to a write lock. This only
+ * works if there are no other readers present, in which case the
+ * method returns 0. Otherwise, the method returns -1 and sets
+ * @c errno to @c EBUSY. Note that the caller of this method *must*
+ * already possess this lock as a read lock (but this condition is
+ * not checked by the current implementation).
+ */
+ int tryacquire_write_upgrade (void);
+
+ /**
+ * Note, for interface uniformity with other synchronization
+ * wrappers we include the <acquire> method. This is implemented as
+ * a write-lock to safe...
+ */
+ int acquire (void);
+
+ /**
+ * Note, for interface uniformity with other synchronization
+ * wrappers we include the <tryacquire> method. This is implemented
+ * as a write-lock to be safe... Returns -1 on failure. If we
+ * "failed" because someone else already had the lock, @c errno is
+ * set to @c EBUSY.
+ */
+ int tryacquire (void);
+
+ /// Unlock a readers/writer lock.
+ int release (void);
+
+ /// Return the underlying lock.
+ const ACE_rwlock_t &lock (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Readers/writer lock.
+ ACE_rwlock_t lock_;
+
+ /// Keeps track of whether <remove> has been called yet to avoid
+ /// multiple <remove> calls, e.g., explicitly and implicitly in the
+ /// destructor. This flag isn't protected by a lock, so make sure
+ /// that you don't have multiple threads simultaneously calling
+ /// <remove> on the same object, which is a bad idea anyway...
+ int removed_;
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_RW_Mutex &);
+ ACE_RW_Mutex (const ACE_RW_Mutex &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/RW_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_RW_MUTEX_H */
diff --git a/ACE/ace/RW_Mutex.inl b/ACE/ace/RW_Mutex.inl
new file mode 100644
index 00000000000..47b95a3bb94
--- /dev/null
+++ b/ACE/ace/RW_Mutex.inl
@@ -0,0 +1,83 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE const ACE_rwlock_t &
+ACE_RW_Mutex::lock (void) const
+{
+// ACE_TRACE ("ACE_RW_Mutex::lock");
+ return this->lock_;
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::remove (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::remove");
+ int result = 0;
+ if (this->removed_ == 0)
+ {
+ this->removed_ = 1;
+ result = ACE_OS::rwlock_destroy (&this->lock_);
+ }
+ return result;
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::acquire_read (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::acquire_read");
+ return ACE_OS::rw_rdlock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::acquire_write (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::acquire_write");
+ return ACE_OS::rw_wrlock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::acquire (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::acquire");
+ return ACE_OS::rw_wrlock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::tryacquire_read (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::tryacquire_read");
+ return ACE_OS::rw_tryrdlock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::tryacquire_write (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::tryacquire_write");
+ return ACE_OS::rw_trywrlock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::tryacquire_write_upgrade (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::tryacquire_write_upgrade");
+ return ACE_OS::rw_trywrlock_upgrade (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::tryacquire (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::tryacquire");
+ return this->tryacquire_write ();
+}
+
+ACE_INLINE int
+ACE_RW_Mutex::release (void)
+{
+// ACE_TRACE ("ACE_RW_Mutex::release");
+ return ACE_OS::rw_unlock (&this->lock_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/RW_Process_Mutex.cpp b/ACE/ace/RW_Process_Mutex.cpp
new file mode 100644
index 00000000000..b30e176b8ed
--- /dev/null
+++ b/ACE/ace/RW_Process_Mutex.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+#include "ace/RW_Process_Mutex.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+
+ACE_RCSID(ace, RW_Process_Mutex, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/RW_Process_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Malloc_T.h"
+
+#if defined (ACE_WIN32)
+#include "ace/OS_NS_fcntl.h"
+#endif /* ACE_WIN32 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_RW_Process_Mutex)
+
+const ACE_TCHAR *
+ACE_RW_Process_Mutex::unique_name (void)
+{
+ ACE::unique_name (this, this->name_, ACE_UNIQUE_NAME_LEN);
+ return this->name_;
+}
+
+ACE_RW_Process_Mutex::ACE_RW_Process_Mutex (const ACE_TCHAR *name,
+ int flags,
+ mode_t mode )
+ : lock_ (name ? name : unique_name (), flags, mode)
+{
+// ACE_TRACE ("ACE_RW_Process_Mutex::ACE_RW_Process_Mutex");
+}
+
+ACE_RW_Process_Mutex::~ACE_RW_Process_Mutex (void)
+{
+// ACE_TRACE ("ACE_RW_Process_Mutex::~ACE_RW_Process_Mutex");
+}
+
+void
+ACE_RW_Process_Mutex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_RW_Process_Mutex::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/RW_Process_Mutex.h b/ACE/ace/RW_Process_Mutex.h
new file mode 100644
index 00000000000..83ae034a40c
--- /dev/null
+++ b/ACE/ace/RW_Process_Mutex.h
@@ -0,0 +1,133 @@
+// -*- C++ -*-
+//
+//=============================================================================
+/**
+ * @file RW_Process_Mutex.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_RW_PROCESS_MUTEX_H
+#define ACE_RW_PROCESS_MUTEX_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/File_Lock.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Default_Constants.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_RW_Process_Mutex
+ *
+ * @brief Wrapper for readers/writer locks that exist across processes.
+ *
+ * Note that because this class uses the
+ * <ACE_File_Lock> as its implementation it only can be reliably
+ * used between separate processes, rather than threads in the
+ * same process. This isn't a limitation of ACE, it's simply
+ * the file lock semantics on UNIX and Win32.
+ * \todo For systems with pthread_rwlockattr_setpshared one
+ * may consider using them to make the mutex faster.
+ */
+class ACE_Export ACE_RW_Process_Mutex
+{
+public:
+ /// Create a readers/writer <Process_Mutex>, passing in the optional
+ /// @a name, @a flags and @a mode \sa ACE_File_Lock.
+ /// If not specified, a name is generated and flags and mode are set
+ /// to default platform values.
+#if defined (ACE_WIN32)
+ ACE_RW_Process_Mutex (const ACE_TCHAR *name = 0,
+ int flags = O_CREAT|O_RDWR,
+ mode_t mode = ACE_DEFAULT_OPEN_PERMS);
+#else
+ ACE_RW_Process_Mutex (const ACE_TCHAR *name = 0,
+ int flags = O_CREAT|O_RDWR,
+ mode_t mode = S_IRUSR | S_IWUSR );
+#endif /* ACE_WIN32 */
+
+ ~ACE_RW_Process_Mutex (void);
+
+ /**
+ * Explicitly destroy the mutex. Note that only one thread should
+ * call this method since it doesn't protect against race
+ * conditions.
+ */
+ int remove (void);
+
+ /// Acquire lock ownership (wait on queue if necessary).
+ int acquire (void);
+
+ /**
+ * Conditionally acquire lock (i.e., don't wait on queue). Returns
+ * -1 on failure. If we "failed" because someone else already had
+ * the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire (void);
+
+ /// Release lock and unblock a thread at head of queue.
+ int release (void);
+
+ /// Acquire lock ownership (wait on queue if necessary).
+ int acquire_read (void);
+
+ /// Acquire lock ownership (wait on queue if necessary).
+ int acquire_write (void);
+
+ /**
+ * Conditionally acquire a lock (i.e., won't block). Returns -1 on
+ * failure. If we "failed" because someone else already had the
+ * lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_read (void);
+
+ /**
+ * Conditionally acquire a lock (i.e., won't block). Returns -1 on
+ * failure. If we "failed" because someone else already had the
+ * lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_write (void);
+
+ /// Attempt to upgrade a read lock to a write lock. Returns 0 on
+ /// success, -1 on failure.
+ int tryacquire_write_upgrade (void);
+
+ /// Return the underlying lock.
+ const ACE_File_Lock &lock (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// If the user does not provide a name we generate a unique name in
+ /// this buffer.
+ ACE_TCHAR name_[ACE_UNIQUE_NAME_LEN];
+
+ /// Create and return the unique name.
+ const ACE_TCHAR *unique_name (void);
+
+ /// We need this to get the readers/writer semantics...
+ ACE_File_Lock lock_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/RW_Process_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_RW_PROCESS_MUTEX_H */
diff --git a/ACE/ace/RW_Process_Mutex.inl b/ACE/ace/RW_Process_Mutex.inl
new file mode 100644
index 00000000000..e3bced0449c
--- /dev/null
+++ b/ACE/ace/RW_Process_Mutex.inl
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Explicitly destroy the mutex.
+ACE_INLINE int
+ACE_RW_Process_Mutex::remove (void)
+{
+ return this->lock_.remove ();
+}
+
+// Acquire lock ownership (wait on priority queue if necessary).
+ACE_INLINE int
+ACE_RW_Process_Mutex::acquire (void)
+{
+ return this->lock_.acquire ();
+}
+
+// Conditionally acquire lock (i.e., don't wait on queue).
+ACE_INLINE int
+ACE_RW_Process_Mutex::tryacquire (void)
+{
+ return this->lock_.tryacquire ();
+}
+
+// Release lock and unblock a thread at head of priority queue.
+ACE_INLINE int
+ACE_RW_Process_Mutex::release (void)
+{
+ return this->lock_.release ();
+}
+
+// Acquire lock ownership (wait on priority queue if necessary).
+ACE_INLINE int
+ACE_RW_Process_Mutex::acquire_read (void)
+{
+ return this->lock_.acquire_read ();
+}
+
+// Acquire lock ownership (wait on priority queue if necessary).
+ACE_INLINE int
+ACE_RW_Process_Mutex::acquire_write (void)
+{
+ return this->lock_.acquire_write ();
+}
+
+// Conditionally acquire a lock (i.e., won't block).
+ACE_INLINE int
+ACE_RW_Process_Mutex::tryacquire_read (void)
+{
+ return this->lock_.tryacquire_read ();
+}
+
+// Conditionally acquire a lock (i.e., won't block).
+ACE_INLINE int
+ACE_RW_Process_Mutex::tryacquire_write (void)
+{
+ return this->lock_.tryacquire_write ();
+}
+
+// Conditionally upgrade a lock (i.e., won't block).
+ACE_INLINE int
+ACE_RW_Process_Mutex::tryacquire_write_upgrade (void)
+{
+ return this->lock_.tryacquire_write_upgrade ();
+}
+
+ACE_INLINE const ACE_File_Lock &
+ACE_RW_Process_Mutex::lock (void) const
+{
+// ACE_TRACE ("ACE_RW_Process_Mutex::lock");
+ return this->lock_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/RW_Thread_Mutex.cpp b/ACE/ace/RW_Thread_Mutex.cpp
new file mode 100644
index 00000000000..bc1c9ecb44f
--- /dev/null
+++ b/ACE/ace/RW_Thread_Mutex.cpp
@@ -0,0 +1,45 @@
+/**
+ * @file RW_Thread_Mutex.cpp
+ *
+ * $Id$
+ *
+ * Originally in Synch.cpp
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+
+#include "ace/RW_Thread_Mutex.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/RW_Thread_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Guard_T.h"
+
+ACE_RCSID(ace, RW_Thread_Mutex, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_RW_Thread_Mutex)
+
+ACE_RW_Thread_Mutex::ACE_RW_Thread_Mutex (const ACE_TCHAR *name,
+ void *arg)
+ : ACE_RW_Mutex (USYNC_THREAD, name, arg)
+{
+// ACE_TRACE ("ACE_RW_Thread_Mutex::ACE_RW_Thread_Mutex");
+}
+
+void
+ACE_RW_Thread_Mutex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_RW_Thread_Mutex::dump");
+ ACE_RW_Mutex::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/RW_Thread_Mutex.h b/ACE/ace/RW_Thread_Mutex.h
new file mode 100644
index 00000000000..ba903df4f76
--- /dev/null
+++ b/ACE/ace/RW_Thread_Mutex.h
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file RW_Thread_Mutex.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_RW_THREAD_MUTEX_H
+#define ACE_RW_THREAD_MUTEX_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_HAS_THREADS)
+# include "ace/Null_Mutex.h"
+#else /* ACE_HAS_THREADS */
+// ACE platform supports some form of threading.
+
+#include "ace/RW_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_RW_Thread_Mutex
+ *
+ * @brief Wrapper for readers/writer locks that exist within a process.
+ */
+class ACE_Export ACE_RW_Thread_Mutex : public ACE_RW_Mutex
+{
+public:
+ ACE_RW_Thread_Mutex (const ACE_TCHAR *name = 0,
+ void *arg = 0);
+
+ /// Default dtor.
+ ~ACE_RW_Thread_Mutex (void);
+
+ /**
+ * Conditionally upgrade a read lock to a write lock. This only
+ * works if there are no other readers present, in which case the
+ * method returns 0. Otherwise, the method returns -1 and sets
+ * @c errno to @c EBUSY. Note that the caller of this method *must*
+ * already possess this lock as a read lock (but this condition is
+ * not checked by the current implementation).
+ */
+ int tryacquire_write_upgrade (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/RW_Thread_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* !ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_RW_THREAD_MUTEX_H */
diff --git a/ACE/ace/RW_Thread_Mutex.inl b/ACE/ace/RW_Thread_Mutex.inl
new file mode 100644
index 00000000000..9f4d315df4a
--- /dev/null
+++ b/ACE/ace/RW_Thread_Mutex.inl
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_RW_Thread_Mutex::tryacquire_write_upgrade (void)
+{
+// ACE_TRACE ("ACE_RW_Thread_Mutex::tryacquire_write_upgrade");
+ return ACE_OS::rw_trywrlock_upgrade (&this->lock_);
+}
+
+ACE_INLINE
+ACE_RW_Thread_Mutex::~ACE_RW_Thread_Mutex (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Reactor.cpp b/ACE/ace/Reactor.cpp
new file mode 100644
index 00000000000..ed9d70be269
--- /dev/null
+++ b/ACE/ace/Reactor.cpp
@@ -0,0 +1,512 @@
+// $Id$
+
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_ACE_SVCCONF)
+# include "ace/Service_Config.h"
+#endif /* !ACE_LACKS_ACE_SVCCONF */
+
+/*
+ * Hook to specialize the includes directly with the concrete
+ * Reactor type, e.g., select, thread pool reactor
+ * known at compile time. This hook results in all the
+ * #defines being commented
+ * out and the concrete header file directly included.
+ */
+//@@ REACTOR_SPL_COMMENT_INCLUDE_START_HOOK
+// Only include the headers needed to compile.
+#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) \
+ || defined (ACE_USE_DEV_POLL_REACTOR_FOR_REACTOR_IMPL)
+# if defined (ACE_USE_TP_REACTOR_FOR_REACTOR_IMPL)
+# include "ace/TP_Reactor.h"
+# else
+# if defined (ACE_USE_DEV_POLL_REACTOR_FOR_REACTOR_IMPL)
+# include "ace/Dev_Poll_Reactor.h"
+# else
+# include "ace/Select_Reactor.h"
+# endif /* ACE_USE_DEV_POLL_REACTOR_FOR_REACTOR_IMPL */
+# 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)
+# include "ace/Msg_WFMO_Reactor.h"
+# else
+# include "ace/WFMO_Reactor.h"
+# 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) */
+
+/*
+ * End comment hook.
+ */
+//@@ REACTOR_SPL_COMMENT_INCLUDE_END_HOOK
+
+#include "ace/Static_Object_Lock.h"
+#include "ace/Framework_Component.h"
+#include "ace/Guard_T.h"
+#include "ace/Recursive_Thread_Mutex.h"
+
+#if !defined (__ACE_INLINE__)
+ #include "ace/Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Reactor,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Reactor)
+
+ACE_Reactor::ACE_Reactor (ACE_Reactor_Impl *impl,
+ bool delete_implementation)
+ : implementation_ (0),
+ delete_implementation_ (delete_implementation)
+{
+ this->implementation (impl);
+
+ if (this->implementation () == 0)
+ {
+/*
+ * Hook to specialize the reactor implementation with the concrete
+ * Reactor implementation known at compile time. This hook will
+ * cause the conditionally defined code to be commented out and
+ * the concrete Reactor directly created.
+ */
+//@@ REACTOR_SPL_CONSTRUCTOR_COMMENT_HOOK_START
+#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) \
+ || defined (ACE_USE_DEV_POLL_REACTOR_FOR_REACTOR_IMPL)
+# if defined (ACE_USE_TP_REACTOR_FOR_REACTOR_IMPL)
+ ACE_NEW (impl,
+ ACE_TP_Reactor);
+# else
+# if defined (ACE_USE_DEV_POLL_REACTOR_FOR_REACTOR_IMPL)
+ ACE_NEW (impl,
+ ACE_Dev_Poll_Reactor);
+# else
+ ACE_NEW (impl,
+ ACE_Select_Reactor);
+# endif /* ACE_USE_DEV_POLL_REACTOR_FOR_REACTOR_IMPL */
+# 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) */
+
+/*
+ * End hook.
+ */
+//@@ REACTOR_SPL_CONSTRUCTOR_COMMENT_HOOK_END
+
+ this->implementation (impl);
+ this->delete_implementation_ = true;
+ }
+}
+
+ACE_Reactor::~ACE_Reactor (void)
+{
+ this->implementation ()->close ();
+ 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!)
+bool ACE_Reactor::delete_reactor_ = false;
+
+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_ = true;
+ ACE_REGISTER_FRAMEWORK_COMPONENT(ACE_Reactor, ACE_Reactor::reactor_)
+ }
+ }
+ return ACE_Reactor::reactor_;
+}
+
+ACE_Reactor *
+ACE_Reactor::instance (ACE_Reactor *r, bool 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_;
+ ACE_Reactor::delete_reactor_ = delete_reactor;
+
+ ACE_Reactor::reactor_ = r;
+
+ // We can't register the Reactor singleton as a framework component twice.
+ // Therefore we test to see if we had an existing reactor instance, which
+ // if so means it must have already been registered.
+ if (t == 0)
+ ACE_REGISTER_FRAMEWORK_COMPONENT(ACE_Reactor, ACE_Reactor::reactor_);
+
+ 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_ = false;
+ }
+}
+
+const ACE_TCHAR *
+ACE_Reactor::dll_name (void)
+{
+ return ACE_TEXT ("ACE");
+}
+
+const ACE_TCHAR *
+ACE_Reactor::name (void)
+{
+ return ACE_TEXT ("ACE_Reactor");
+}
+
+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 const 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 const 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;
+ }
+}
+
+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;
+}
+
+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)
+
+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 */
+
+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;
+}
+
+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;
+}
+
+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);
+
+ long 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;
+}
+
+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;
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Reactor.h b/ACE/ace/Reactor.h
new file mode 100644
index 00000000000..2704b096b74
--- /dev/null
+++ b/ACE/ace/Reactor.h
@@ -0,0 +1,875 @@
+// -*- 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"
+
+// Timer Queue is a complicated template class. A simple forward
+// declaration will not work.
+#include "ace/Timer_Queuefwd.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Contains the timer related interface for the Reactor.
+#include "ace/Reactor_Timer_Interface.h"
+
+// Event_Handler.h contains the definition of ACE_Reactor_Mask
+#include "ace/Event_Handler.h"
+
+// Get ACE_Time_Value in
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Reactor_Impl;
+class ACE_Handle_Set;
+class ACE_Sig_Action;
+class ACE_Sig_Handler;
+class ACE_Sig_Set;
+
+/*
+ * Hook to specialize the Reactor implementation with the concrete
+ * Reactor type, for exmaple, select, thread pool reactor known
+ * at compile time.
+ */
+//@@ REACTOR_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
+
+/**
+ * @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 ACE_Reactor_Timer_Interface
+{
+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 specify a hook function to event-handling methods that will
+ * be called after each iteration of event handling. If the hook function
+ * returns a non-zero value, the event loop will immediately resume
+ * waiting for the next event(s) to process without checking the error
+ * status of the just-completed iteration of event handling or the
+ * end-of-loop indication. If the hook function returns 0, the event
+ * handling error status and the end-of-loop indication will be checked
+ * as normal, just as if there is no hook function specified.
+ */
+ 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 @a delete_reactor == true then we'll delete the Reactor
+ * at destruction time.
+ */
+ static ACE_Reactor *instance (ACE_Reactor *, bool delete_reactor = false);
+
+ /// Delete the dynamically allocated Singleton
+ static void close_singleton (void);
+
+ /// Name of the dll in which the dll lives.
+ static const ACE_TCHAR *dll_name (void);
+
+ /// Name of the component--ACE_Reactor in this case.
+ static const ACE_TCHAR *name (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>.
+ *
+ * @deprecated Use ACE_Reactor::instance()->run_reactor_event_loop() instead
+ */
+ 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>.
+ *
+ * @deprecated Use ACE_Reactor::instance()->run_reactor_event_loop() instead
+ */
+ 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>.
+ *
+ * @deprecated Use ACE_Reactor::instance()->end_reactor_event_loop() instead
+ */
+ 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>.
+ *
+ * @deprecated Use ACE_Reactor::instance()->reactor_event_loop_done() instead
+ */
+ 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>.
+ *
+ * @deprecated Use ACE_Reactor::instance()->reset_reactor_event_loop()
+ * instead
+ */
+ 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.
+ */
+ int run_reactor_event_loop (REACTOR_EVENT_HOOK = 0);
+ 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.
+ */
+ int run_reactor_event_loop (ACE_Time_Value &tv,
+ REACTOR_EVENT_HOOK = 0);
+ 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.
+ * Any queued notifications remain queued on return from this method.
+ * If the event loop is restarted in the future, the notifications
+ * will be dispatched then. If the reactor is closed or deleted without
+ * further dispatching, the notifications will be lost.
+ */
+ int end_reactor_event_loop (void);
+
+ /// Indicate if the Reactor's event loop has been ended.
+ int reactor_event_loop_done (void);
+
+ /// Resets the <ACE_Reactor::end_event_loop_> static so that the
+ /// <run_event_loop> method can be restarted.
+ void reset_reactor_event_loop (void);
+
+ /**
+ * Create the Reactor using @a implementation. The flag
+ * @a delete_implementation tells the Reactor whether or not to
+ * delete the @a implementation on destruction.
+ */
+ ACE_Reactor (ACE_Reactor_Impl *implementation = 0,
+ bool delete_implementation = false);
+
+ /// Close down and release all resources.
+ /**
+ * Any notifications that remain queued on this reactor instance are
+ * lost.
+ */
+ 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.
+ */
+ 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.
+ int set_sig_handler (ACE_Sig_Handler *signal_handler);
+
+ /// Set a user-specified timer queue.
+ int timer_queue (ACE_Timer_Queue *tq);
+
+ /// Return the current ACE_Timer_Queue.
+ ACE_Timer_Queue *timer_queue (void) const;
+
+ /// Close down and release all resources.
+ 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".
+ */
+ int work_pending (const ACE_Time_Value &max_wait_time = ACE_Time_Value::zero);
+
+ /**
+ * This event loop driver blocks for up to @a max_wait_time before
+ * returning. It will return earlier if events occur. Note that
+ * @a max_wait_time can be 0, in which case this method blocks
+ * indefinitely until events occur.
+ *
+ * @a 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,
+ * @a 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_Handlers
+ * that were dispatched, 0 if the @a 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.
+ */
+ int handle_events (ACE_Time_Value *max_wait_time = 0);
+ int alertable_handle_events (ACE_Time_Value *max_wait_time = 0);
+
+ /**
+ * This method is just like the one above, except the
+ * @a 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.
+ */
+ int handle_events (ACE_Time_Value &max_wait_time);
+ int alertable_handle_events (ACE_Time_Value &max_wait_time);
+
+ // = Register and remove handlers.
+
+ /**
+ * Register handler for I/O events.
+ *
+ * A handler can be associated with multiple handles. A handle
+ * cannot be associated with multiple handlers.
+ *
+ * The handle will come from ACE_Event_Handler::get_handle().
+ *
+ * Reactor will call ACE_Event_Handler::add_reference() for a new
+ * handler/handle pair.
+ *
+ * If this handler/handle pair has already been registered, any new
+ * masks specified will be added. In this case,
+ * ACE_Event_Handler::add_reference() will not be called.
+ *
+ * If the registered handler is currently suspended, it will remain
+ * suspended. When the handler is resumed, it will have the
+ * existing masks plus any masks added through this call. Handlers
+ * do not have partial suspensions.
+ */
+ int register_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register handler for I/O events.
+ *
+ * Same as register_handler(ACE_Event_Handler*,ACE_Reactor_Mask),
+ * except handle is explicitly specified.
+ */
+ int register_handler (ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+#if defined (ACE_WIN32)
+
+ /**
+ * Register handler for OS events.
+ *
+ * Register an @a event_handler that will be notified when
+ * <event_handle> is signaled. This will call back its
+ * <handle_signal> hook method.
+ *
+ * Reactor will call ACE_Event_Handler::add_reference() for a new
+ * handler/handle pair.
+ *
+ * This interface is only available Win32 platforms because
+ * ACE_HANDLE is an int on non-Win32 platforms and 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).
+ */
+ int register_handler (ACE_Event_Handler *event_handler,
+ ACE_HANDLE event_handle = ACE_INVALID_HANDLE);
+
+#endif /* ACE_WIN32 */
+
+ /**
+ * Register handler for I/O events.
+ *
+ * Similar to
+ * register_handler(ACE_HANDLE,ACE_Event_Handler*,ACE_Reactor_Mask),
+ * except that the user gets to specify the event handle that will
+ * be used for this registration. This only applies to Reactors
+ * that use event handles for I/O registrations.
+ */
+ int register_handler (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register handler for multiple I/O events.
+ *
+ * Shorthand for calling
+ * register_handler(ACE_HANDLE,ACE_Event_Handler*,ACE_Reactor_Mask),
+ * multiple times for the same @a event_handler and @a masks but
+ * different <handles>.
+ */
+ int register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks);
+
+ /**
+ * Register handler for signals.
+ *
+ * Register @a new_sh to handle the signal @a signum using the
+ * @a new_disp. Returns the @a old_sh that was previously registered
+ * (if any), along with the @a old_disp of the signal handler.
+ *
+ * Reactor will call ACE_Event_Handler::add_reference() on @a new_sh
+ * and ACE_Event_Handler::remove_reference() on @a old_sh.
+ */
+ 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);
+
+ /**
+ * Register handler for multiple signals.
+ *
+ * Shorthand for calling
+ * register_handler(int,ACE_Event_Handler*,ACE_Sig_Action*,ACE_Event_Handler**,ACE_Sig_Action*)
+ * multiple times for the same @a event_handler and @a sig_action but
+ * different <signals>.
+ */
+ int register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *event_handler,
+ ACE_Sig_Action *sig_action = 0);
+
+ /**
+ * Remove @a masks from @a handle registration.
+ *
+ * For I/O handles, @a masks are removed from the Reactor. Unless
+ * @a masks includes ACE_Event_Handler::DONT_CALL,
+ * ACE_Event_Handler::handle_close() will be called with the @a masks
+ * that have been removed. If all masks have been removed,
+ * ACE_Event_Handler::remove_reference() will be called.
+ *
+ * For OS handles, the @a handle is removed from the Reactor. Unless
+ * @a masks includes ACE_Event_Handler::DONT_CALL,
+ * ACE_Event_Handler::handle_close() will be called with
+ * ACE_Event_Handler::NULL_MASK.
+ * ACE_Event_Handler::remove_reference() will also be called.
+ */
+ int remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks);
+
+ /**
+ * Remove @a masks from @a event_handler registration.
+ *
+ * Same as remove_handler(ACE_HANDLE,ACE_Reactor_Mask), except
+ * @a handle comes from ACE_Event_Handler::get_handle().
+ */
+ int remove_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks);
+
+ /**
+ * Remove @a masks from multiple <handle> registrations.
+ *
+ * Shorthand for calling remove_handler(ACE_HANDLE,ACE_Reactor_Mask)
+ * multiple times for the same @a masks but different @a handles.
+ */
+ int remove_handler (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask masks);
+
+ /**
+ * Remove signal handler registration.
+ *
+ * Remove the ACE_Event_Handler currently associated with @a signum.
+ * Install the new disposition (if given) and return the previous
+ * disposition (if desired by the caller).
+ *
+ * ACE_Event_Handler::handle_close() will be called with
+ * @c ACE_Event_Handler::SIGNAL_MASK.
+ * ACE_Event_Handler::remove_reference() will also be called.
+ */
+ int remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp = 0,
+ int sigkey = -1);
+
+ /**
+ * Remove multiple signal handler registrations.
+ *
+ * Shorthand for calling
+ * remove_handler(int,ACE_Sig_Action*,ACE_Sig_Action*,int) multiple
+ * times for every signal in @a sigset.
+ */
+ int remove_handler (const ACE_Sig_Set &sigset);
+
+ // = Suspend and resume Handlers.
+
+ /**
+ * Suspend @a handle temporarily.
+ */
+ int suspend_handler (ACE_HANDLE handle);
+
+ /**
+ * Suspend @a event_handler temporarily.
+ *
+ * Handle is obtained from ACE_Event_Handler::get_handle().
+ */
+ int suspend_handler (ACE_Event_Handler *event_handler);
+
+ /**
+ * Suspend @a handles temporarily.
+ *
+ * Shorthand for calling suspend_handler(ACE_HANDLE) with multiple
+ * <handles>.
+ */
+ int suspend_handler (const ACE_Handle_Set &handles);
+
+ /**
+ * Suspend all registered handles temporarily.
+ */
+ int suspend_handlers (void);
+
+ /**
+ * Resume @a handle.
+ */
+ int resume_handler (ACE_HANDLE handle);
+
+ /**
+ * Resume @a event_handler.
+ *
+ * Handle is obtained from ACE_Event_Handler::get_handle().
+ */
+ int resume_handler (ACE_Event_Handler *event_handler);
+
+ /**
+ * Resume @a handles.
+ *
+ * Shorthand for calling resume_handler(ACE_HANDLE) with multiple
+ * <handles>.
+ */
+ int resume_handler (const ACE_Handle_Set &handles);
+
+ /**
+ * Resume all registered handles.
+ */
+ 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.
+ int resumable_handler (void);
+
+ // = Timer management.
+
+ /**
+ * Schedule a timer event.
+ *
+ * Schedule a timer event that will expire after an <delay> amount
+ * of time. The return value of this method, a timer_id value,
+ * uniquely identifies the @a 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.
+ *
+ * Reactor will call ACE_Event_Handler::add_reference() on the
+ * handler. After the timeout occurs and
+ * ACE_Event_Handler::handle_timeout() has completed, the handler
+ * will be implicitly removed from the Reactor and
+ * ACE_Event_Handler::remove_reference() will be called.
+ *
+ * @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);
+
+ /**
+ * Reset recurring timer interval.
+ *
+ * Resets the interval of the timer represented by @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a interval is equal to
+ * ACE_Time_Value::zero, the timer will become a non-rescheduling
+ * timer. Returns 0 if successful, -1 if not.
+ *
+ * This change will not take effect until the next timeout.
+ */
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval);
+
+ /**
+ * Cancel timer.
+ *
+ * Cancel timer associated with @a timer_id that was returned from
+ * the schedule_timer() method. If arg 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 @a timer_id wasn't found.
+ *
+ * On successful cancellation, ACE_Event_Handler::handle_close()
+ * will be called with <ACE_Event_Handler::TIMER_MASK>.
+ * ACE_Event_Handler::remove_reference() will also be called.
+ */
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel all timers associated with event handler.
+ *
+ * Shorthand for calling cancel_timer(long,const void **,int)
+ * multiple times for all timer associated with @a event_handler.
+ *
+ * ACE_Event_Handler::handle_close() will be called with
+ * <ACE_Event_Handler::TIMER_MASK> only once irrespective of the
+ * number of timers associated with the event handler.
+ * ACE_Event_Handler::remove_reference() will also be called once
+ * for every timer associated with the event handler.
+ *
+ * Returns number of handlers cancelled.
+ */
+ virtual int cancel_timer (ACE_Event_Handler *event_handler,
+ int dont_call_handle_close = 1);
+
+ // = High-level Event_Handler scheduling operations
+
+ /// Add @a masks_to_be_added to the @a event_handler's entry.
+ /// @a 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.
+ int schedule_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_added);
+
+ /// Add @a masks_to_be_added to the @a handle's entry. <event_handler>
+ /// associated with @a 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.
+ int schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_added);
+
+ /// Clear @a masks_to_be_cleared from the @a 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.
+ int cancel_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_cleared);
+
+ /// Clear @a 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.
+ int cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_cleared);
+
+ // = Notification methods.
+
+ /**
+ * Dispatch user specified events.
+ *
+ * Handler will be dispatched irrespective of whether it is
+ * registered, not registered, or suspended in the Reactor.
+ *
+ * If user specified event is successfully queued,
+ * ACE_Event_Handler::add_reference() will be called. After the
+ * notify occurs and the upcall to the handler completes, the
+ * handler will be implicitly removed from the Reactor and
+ * ACE_Event_Handler::remove_reference() will be called. No other
+ * upcall reference counting is done.
+ *
+ * For I/O or OS events, the upcall is invoked with an
+ * ACE_INVALID_HANDLE.
+ *
+ * For timer events, the upcall is invoked with a null ACT.
+ *
+ * @param event_handler: IN - Handler on which the event will be
+ * dispatched.
+ * @param masks: IN - Events to be dispatched - multiple events can
+ * be OR'd together.
+ * @param timeout: INOUT - Relative time up to which to wait for
+ * user specified event to be queued. If tv is 0, wait
+ * indefinitely. When the call returns, tv has the time remaining
+ * after the call completes.
+ */
+ int notify (ACE_Event_Handler *event_handler = 0,
+ ACE_Reactor_Mask masks = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value *timeout = 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.
+ */
+ void max_notify_iterations (int iterations);
+
+ /**
+ * Get the maximum number of times that the ACE_Reactor will
+ * iterate and dispatch the ACE_Event_Handler's 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 @a 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.
+ *
+ * After the purging occurs, the handler will be implicitly removed
+ * from the Reactor and ACE_Event_Handler::remove_reference() will
+ * be called.
+ */
+ int purge_pending_notifications (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask =
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ // = Assorted helper methods.
+
+ /**
+ * Return the Event_Handler associated with @a handle. Return 0 if
+ * @a handle is not registered.
+ *
+ * Reactor will call ACE_Event_Handler::add_reference() on the
+ * handler before returning it.
+ */
+ ACE_Event_Handler *find_handler (ACE_HANDLE handle);
+
+ /**
+ * Check to see if @a handle is associated with a valid Event_Handler
+ * bound to @a mask. Return the @c event_handler associated with this
+ * @a handler if @a event_handler != 0.
+ *
+ * Reactor will call ACE_Event_Handler::add_reference() on the
+ * handler before returning it if @a event_handler != 0.
+ */
+ int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler = 0);
+
+ /**
+ * Check to see if @a signum is associated with a valid Event_Handler
+ * bound to a signal. Return the @a event_handler associated with
+ * this @c handler if @a event_handler != 0.
+ */
+ int handler (int signum,
+ ACE_Event_Handler **event_handler = 0);
+
+ /// Returns true if Reactor has been successfully initialized, else
+ /// false.
+ int initialized (void);
+
+ /// Returns the current size of the Reactor's internal descriptor
+ /// table.
+ size_t size (void) const;
+
+ /// Returns a reference to the Reactor's internal lock.
+ ACE_Lock &lock (void);
+
+ /// Wake up all threads in waiting in the event loop
+ void wakeup_all_threads (void);
+
+ /// Transfers ownership of Reactor to the @a new_owner.
+ int owner (ACE_thread_t new_owner,
+ ACE_thread_t *old_owner = 0);
+
+ /// Return the ID of the "owner" thread.
+ int owner (ACE_thread_t *owner);
+
+ /// Set position of the owner thread.
+ void requeue_position (int position);
+
+ /// Get position of the owner thread.
+ int requeue_position (void);
+
+ /// Get the existing restart value.
+ int restart (void);
+
+ /// Set a new value for restart and return the original value.
+ int restart (int r);
+
+ // = Low-level wait_set mask manipulation methods.
+
+ /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the
+ /// @a event_handler and @a mask.
+ 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 @a handle
+ /// and @a mask.
+ 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 @a event_handler
+ /// and @a mask.
+ 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 @a mask.
+ int ready_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// Get the implementation class
+ ACE_Reactor_Impl *implementation (void) const;
+
+ /**
+ * Returns 0, if the size of the current message has been put in
+ * @a size returns -1, if not. ACE_HANDLE allows the reactor to
+ * check if the caller is valid. Used for CLASSIX Reactor
+ * implementation.
+ */
+ 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.
+ 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.
+ 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
+ bool delete_implementation_;
+
+ /// Pointer to a process-wide ACE_Reactor singleton.
+ static ACE_Reactor *reactor_;
+
+ /// Must delete the reactor_ singleton if true.
+ static bool delete_reactor_;
+
+ /// Deny access since member-wise won't work...
+ ACE_Reactor (const ACE_Reactor &);
+ ACE_Reactor &operator = (const ACE_Reactor &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#if defined (__ACE_INLINE__)
+#include "ace/Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_REACTOR_H */
diff --git a/ACE/ace/Reactor.inl b/ACE/ace/Reactor.inl
new file mode 100644
index 00000000000..b381a1738c2
--- /dev/null
+++ b/ACE/ace/Reactor.inl
@@ -0,0 +1,498 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Reactor_Impl.h"
+
+/*
+ * Hook to specialize the Reactor with the concrete implementation
+ * known at compile time.
+ */
+//@@ REACTOR_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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::event_loop_done (void)
+{
+ ACE_TRACE ("ACE_Reactor::event_loop_done");
+ return ACE_Reactor::instance ()->reactor_event_loop_done ();
+}
+
+ACE_INLINE int
+ACE_Reactor::end_reactor_event_loop (void)
+{
+ ACE_TRACE ("ACE_Reactor::end_reactor_event_loop");
+
+ this->implementation_->deactivate (1);
+
+ return 0;
+}
+
+ACE_INLINE void
+ACE_Reactor::reset_reactor_event_loop (void)
+{
+ ACE_TRACE ("ACE_Reactor::reset_reactor_event_loop");
+
+ this->implementation_->deactivate (0);
+}
+
+ACE_INLINE int
+ACE_Reactor::resumable_handler (void)
+{
+ return this->implementation ()->resumable_handler ();
+}
+
+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);
+}
+
+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 ACE_Timer_Queue *
+ACE_Reactor::timer_queue (void) const
+{
+ return this->implementation ()->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 (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::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 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 ACE_Event_Handler *
+ACE_Reactor::find_handler (ACE_HANDLE handle)
+{
+ return this->implementation ()->find_handler (handle);
+}
+
+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 int
+ACE_Reactor::reactor_event_loop_done (void)
+{
+ ACE_TRACE ("ACE_Reactor::reactor_event_loop_done");
+ return this->implementation_->deactivated ();
+}
+
+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 ();
+}
+
+ACE_INLINE void
+ACE_Reactor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Reactor::dump");
+
+ implementation_->dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Reactor_Impl.cpp b/ACE/ace/Reactor_Impl.cpp
new file mode 100644
index 00000000000..96411b8b0c6
--- /dev/null
+++ b/ACE/ace/Reactor_Impl.cpp
@@ -0,0 +1,15 @@
+// $Id$
+
+#include "ace/Reactor_Impl.h"
+
+ACE_RCSID (ace,
+ Reactor_Impl,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Reactor_Impl::~ACE_Reactor_Impl (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Reactor_Impl.h b/ACE/ace/Reactor_Impl.h
new file mode 100644
index 00000000000..bbeeefd1a22
--- /dev/null
+++ b/ACE/ace/Reactor_Impl.h
@@ -0,0 +1,569 @@
+// -*- 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_Queuefwd.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/Event_Handler.h"
+#include "ace/Countdown_Time.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls
+class ACE_Handle_Set;
+class ACE_Reactor_Impl;
+class ACE_Sig_Action;
+class ACE_Sig_Handler;
+class ACE_Sig_Set;
+
+/**
+ * @class ACE_Reactor_Notify
+ *
+ * @internal This class is for ACE internal use only.
+ *
+ * @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 @a 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 @a timeout == 0, the
+ * caller will block until action is possible, else will wait until
+ * the relative time specified in *@a timeout elapses).
+ */
+ virtual int notify (ACE_Event_Handler *eh = 0,
+ ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value *timeout = 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
+ * @a 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;
+
+ /// Set a user-specified timer queue.
+ virtual int timer_queue (ACE_Timer_Queue *tq) = 0;
+
+ /// Return the current ACE_Timer_Queue.
+ 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 @a max_wait_time before
+ * returning. It will return earlier if events occur. Note that
+ * @a max_wait_time can be 0, in which case this method blocks
+ * indefinitely until events occur.
+ *
+ * @a 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,
+ * @a 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_Handlers that were
+ * dispatched, 0 if the @a 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
+ * @a 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 @a 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 @a event_handler with @a mask. The I/O handle will always
+ /// come from <get_handle> on the @a event_handler.
+ virtual int register_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask) = 0;
+
+ /// Register @a event_handler with @a 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 @a 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 @a event_handler that will be notified when
+ * <event_handle> is signaled. @a mask specifies the network events
+ * that the @a 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 @a 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 @a 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 @a event_handler. Note that the I/O handle will be
+ * obtained using <get_handle> method of @a event_handler . If
+ * @a mask == ACE_Event_Handler::DONT_CALL then the <handle_close>
+ * method of the @a event_handler is not invoked.
+ */
+ virtual int remove_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask) = 0;
+
+ /**
+ * Removes <handle>. If @a 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 @a 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 @a signum.
+ * Install the new disposition (if given) and return the previous
+ * disposition (if desired by the caller). Returns 0 on success and
+ * -1 if @a 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 @a 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 @a 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 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) = 0;
+
+ /**
+ * Resets the interval of the timer represented by @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a 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
+ /// @a 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 @a 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 @a 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 @a masks_to_be_added to the @a event_handler's entry.
+ /// @a 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 @a 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 @a 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 @a 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 @a event_handler of @a mask event. The ACE_Time_Value
+ * indicates how long to blocking trying to notify. If @a timeout ==
+ * 0, the caller will block until action is possible, else will wait
+ * until the relative time specified in @a 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;
+
+ /**
+ * Return the Event_Handler associated with <handle>. Return 0 if
+ * <handle> is not registered.
+ */
+ virtual ACE_Event_Handler *find_handler (ACE_HANDLE handle) = 0;
+
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to @a mask. Return the @a event_handler associated with this
+ * handler if @a event_handler != 0.
+ */
+ virtual int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler = 0) = 0;
+
+ /**
+ * Check to see if @a signum is associated with a valid Event_Handler
+ * bound to a signal. Return the @a event_handler associated with
+ * this handler if @a event_handler != 0.
+ */
+ virtual int handler (int signum,
+ ACE_Event_Handler ** = 0) = 0;
+
+ /// Returns true if Reactor has been successfully initialized, else
+ /// false.
+ virtual bool 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
+ /// @a event_handler and @a 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 @a 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 @a event_handler
+ /// and @a 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 @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_REACTOR_IMPL_H */
diff --git a/ACE/ace/Reactor_Notification_Strategy.cpp b/ACE/ace/Reactor_Notification_Strategy.cpp
new file mode 100644
index 00000000000..a029e2c10c2
--- /dev/null
+++ b/ACE/ace/Reactor_Notification_Strategy.cpp
@@ -0,0 +1,38 @@
+#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, Reactor_Notification_Strategy, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Reactor_Notification_Strategy.h b/ACE/ace/Reactor_Notification_Strategy.h
new file mode 100644
index 00000000000..d0cd247400e
--- /dev/null
+++ b/ACE/ace/Reactor_Notification_Strategy.h
@@ -0,0 +1,66 @@
+// -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 *eh, ACE_Reactor_Mask mask);
+
+ /// Get the reactor
+ ACE_Reactor *reactor (void);
+
+ /// Set the reactor
+ void reactor (ACE_Reactor *r);
+
+protected:
+ /// The Reactor
+ ACE_Reactor *reactor_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#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/ace/Reactor_Notification_Strategy.inl b/ACE/ace/Reactor_Notification_Strategy.inl
new file mode 100644
index 00000000000..328c2687a77
--- /dev/null
+++ b/ACE/ace/Reactor_Notification_Strategy.inl
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Reactor_Timer_Interface.cpp b/ACE/ace/Reactor_Timer_Interface.cpp
new file mode 100644
index 00000000000..6c07f21ac86
--- /dev/null
+++ b/ACE/ace/Reactor_Timer_Interface.cpp
@@ -0,0 +1,16 @@
+// $Id$
+
+#include "ace/Reactor_Timer_Interface.h"
+
+ACE_RCSID (ace,
+ Reactor_Timer_Interface,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Reactor_Timer_Interface::~ACE_Reactor_Timer_Interface()
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Reactor_Timer_Interface.h b/ACE/ace/Reactor_Timer_Interface.h
new file mode 100644
index 00000000000..d370a128df2
--- /dev/null
+++ b/ACE/ace/Reactor_Timer_Interface.h
@@ -0,0 +1,60 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Reactor_Timer_Interface.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali <irfan@oomworks.com>
+ */
+//=============================================================================
+
+#ifndef ACE_REACTOR_TIMER_INTERFACE_H
+#define ACE_REACTOR_TIMER_INTERFACE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Time_Value.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Event_Handler;
+
+/**
+ * @class ACE_Reactor_Timer_Interface
+ *
+ * @brief Interface for timer related methods on the Reactor.
+ */
+class ACE_Export ACE_Reactor_Timer_Interface
+{
+public:
+
+ virtual ~ACE_Reactor_Timer_Interface (void);
+
+ 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;
+
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval) = 0;
+
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1) = 0;
+
+ virtual int cancel_timer (ACE_Event_Handler *event_handler,
+ int dont_call_handle_close = 1) = 0;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_REACTOR_TIMER_INTERFACE_H */
diff --git a/ACE/ace/Reactor_Token_T.cpp b/ACE/ace/Reactor_Token_T.cpp
new file mode 100644
index 00000000000..73ab406db63
--- /dev/null
+++ b/ACE/ace/Reactor_Token_T.cpp
@@ -0,0 +1,70 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/Reactor_Token_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_TOKEN_TYPE> void
+ACE_Reactor_Token_T<ACE_TOKEN_TYPE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Reactor_Token_T::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class ACE_TOKEN_TYPE>
+ACE_Reactor_Token_T<ACE_TOKEN_TYPE>::ACE_Reactor_Token_T
+ (ACE_Reactor_Impl &r,
+ int s_queue)
+ : reactor_ (&r)
+{
+ ACE_TRACE ("ACE_Reactor_Token_T::ACE_Reactor_Token");
+
+ this->queueing_strategy (s_queue);
+}
+
+template <class ACE_TOKEN_TYPE>
+ACE_Reactor_Token_T<ACE_TOKEN_TYPE>::ACE_Reactor_Token_T (int s_queue)
+ : reactor_ (0)
+{
+ ACE_TRACE ("ACE_Reactor_Token_T::ACE_Reactor_Token");
+
+ this->queueing_strategy (s_queue);
+}
+
+template <class ACE_TOKEN_TYPE>
+ACE_Reactor_Token_T<ACE_TOKEN_TYPE>::~ACE_Reactor_Token_T (void)
+{
+ ACE_TRACE ("ACE_Reactor_Token_T::~ACE_Reactor_Token_T");
+}
+
+template <class ACE_TOKEN_TYPE> ACE_Reactor_Impl &
+ACE_Reactor_Token_T<ACE_TOKEN_TYPE>::reactor (void)
+{
+ return *this->reactor_;
+}
+
+template <class ACE_TOKEN_TYPE> void
+ACE_Reactor_Token_T<ACE_TOKEN_TYPE>::reactor (ACE_Reactor_Impl &reactor)
+{
+ this->reactor_ = &reactor;
+}
+
+// Used to wakeup the reactor.
+
+template <class ACE_TOKEN_TYPE> void
+ACE_Reactor_Token_T<ACE_TOKEN_TYPE>::sleep_hook (void)
+{
+ ACE_TRACE ("ACE_Reactor_Token_T::sleep_hook");
+ if (this->reactor_->notify () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("sleep_hook failed")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Reactor_Token_T.h b/ACE/ace/Reactor_Token_T.h
new file mode 100644
index 00000000000..945f05531df
--- /dev/null
+++ b/ACE/ace/Reactor_Token_T.h
@@ -0,0 +1,93 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Reactor_Token_T.h
+ *
+ * $Id$
+ *
+ * @author Steve Huston <shuston@riverace.com>
+ */
+//=============================================================================
+
+
+#ifndef ACE_REACTOR_TOKEN_T_H
+#define ACE_REACTOR_TOKEN_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Reactor_Impl.h"
+#include "ace/Token.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Reactor_Token_T
+ *
+ * @internal For ACE internal use only.
+ *
+ * @brief Used as a synchronization mechanism to coordinate concurrent
+ * access to an ACE_Reactor_Impl object.
+ *
+ * This class is used to make access to a reactor's internals and
+ * demultiplexing mechanism thread-safe. By default, the thread that
+ * runs the handle_events() loop holds the token, even when it is blocked
+ * in the demultiplexer. Whenever another thread wants to access the
+ * reactor, such as via the register_handler(), remove_handler(), etc.
+ * methods, it must ask the token owner for temporary release of the token.
+ * To accomplish this, this class reimplements the ACE_Token::sleep_hook()
+ * method through which the owning thread can be notified to temporarily
+ * release the token if the current situation permits.
+ *
+ * The owner of the token is responsible for deciding which
+ * request for the token can be granted. By using the
+ * ACE_Token::renew() method, 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
+ * original owner reclaims 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.
+ */
+template <class ACE_TOKEN_TYPE>
+class ACE_Reactor_Token_T : public ACE_TOKEN_TYPE
+{
+public:
+ ACE_Reactor_Token_T (ACE_Reactor_Impl &r,
+ int s_queue = ACE_TOKEN_TYPE::FIFO);
+ ACE_Reactor_Token_T (int s_queue = ACE_TOKEN_TYPE::FIFO);
+ virtual ~ACE_Reactor_Token_T (void);
+
+ /// Called just before a token waiter goes to sleep.
+ /// @see ACE_Token::sleep_hook
+ virtual void sleep_hook (void);
+
+ /// Get the reactor implementation
+ ACE_Reactor_Impl &reactor (void);
+
+ /// Set the reactor implementation
+ void reactor (ACE_Reactor_Impl &);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ACE_Reactor_Impl *reactor_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Reactor_Token_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Reactor_Token_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_REACTOR_TOKEN_T_H */
diff --git a/ACE/ace/Read_Buffer.cpp b/ACE/ace/Read_Buffer.cpp
new file mode 100644
index 00000000000..ec5c8b94ef1
--- /dev/null
+++ b/ACE/ace/Read_Buffer.cpp
@@ -0,0 +1,176 @@
+// $Id$
+
+#include "ace/Read_Buffer.h"
+
+#include "ace/config-all.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Read_Buffer.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/Malloc_Base.h"
+#include "ace/Service_Config.h"
+#include "ace/OS_NS_stdio.h"
+
+ACE_RCSID(ace, Read_Buffer, "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Read_Buffer::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Read_Buffer::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("size_ = %d"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\noccurrences_ = %d"), this->occurrences_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nstream_ = %x"), this->stream_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nallocator_ = %x"), this->allocator_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Read_Buffer::ACE_Read_Buffer (FILE *fp,
+ bool 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 ();
+}
+
+#if !defined (ACE_HAS_WINCE)
+ACE_Read_Buffer::ACE_Read_Buffer (ACE_HANDLE handle,
+ bool close_on_delete,
+ ACE_Allocator *alloc)
+ : stream_ (ACE_OS::fdopen (handle, ACE_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 ();
+}
+#endif // ACE_HAS_WINCE
+
+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 = ACE_OS::getc (this->stream_);
+
+ // Don't insert EOF into the buffer...
+ if (c == EOF)
+ {
+ ACE_OS::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 = 0;
+
+ // 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Read_Buffer.h b/ACE/ace/Read_Buffer.h
new file mode 100644
index 00000000000..cfa0dd0f791
--- /dev/null
+++ b/ACE/ace/Read_Buffer.h
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Read_Buffer.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Seth Widoff
+ */
+//==========================================================================
+
+#ifndef ACE_READ_BUFFER_H
+#define ACE_READ_BUFFER_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Global_Macros.h"
+#include "ace/os_include/os_stdio.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Allocator;
+
+/**
+ * @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,
+ bool close_on_delete = false,
+ ACE_Allocator * = 0);
+
+#if !defined (ACE_HAS_WINCE)
+ // Note that ACE_HANDLE = FILE under CE.
+
+ /// Read from an open HANDLE.
+ ACE_Read_Buffer (ACE_HANDLE handle,
+ bool close_on_delete = false,
+ ACE_Allocator * = 0);
+#endif // ACE_HAS_WINCE
+
+ /// 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 @a terminator. If @a search is >= 0 then all
+ * occurrences of the @a search value are substituted with the
+ * @a replace value. The last of the byte of data is a 0, so that
+ * @c 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 @c read.
+ size_t replaced (void) const;
+
+ /// Returns the size of the allocated buffer obtained during a
+ /// @c 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:
+
+ // Disallow copying and assignment...
+ void operator= (const ACE_Read_Buffer &);
+ ACE_Read_Buffer (const ACE_Read_Buffer &);
+
+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.
+ bool const close_on_delete_;
+
+ /// Pointer to the allocator.
+ ACE_Allocator *allocator_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Read_Buffer.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_READ_BUFFER_H */
diff --git a/ACE/ace/Read_Buffer.inl b/ACE/ace/Read_Buffer.inl
new file mode 100644
index 00000000000..1517e9c17e3
--- /dev/null
+++ b/ACE/ace/Read_Buffer.inl
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Recursive_Thread_Mutex.cpp b/ACE/ace/Recursive_Thread_Mutex.cpp
new file mode 100644
index 00000000000..285789dd696
--- /dev/null
+++ b/ACE/ace/Recursive_Thread_Mutex.cpp
@@ -0,0 +1,125 @@
+/**
+ * @file Recursive_Thread_Mutex.cpp
+ *
+ * $Id$
+ *
+ * Originally in Synch.cpp
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+
+#include "ace/Recursive_Thread_Mutex.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Recursive_Thread_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Recursive_Thread_Mutex, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Recursive_Thread_Mutex)
+
+ACE_Recursive_Thread_Mutex::ACE_Recursive_Thread_Mutex (const ACE_TCHAR *name,
+ ACE_mutexattr_t *arg)
+ : removed_ (false)
+{
+ // ACE_TRACE ("ACE_Recursive_Thread_Mutex::ACE_Recursive_Thread_Mutex");
+ if (ACE_OS::recursive_mutex_init (&this->lock_,
+ name,
+ arg) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recursive_mutex_init")));
+}
+
+ACE_Recursive_Thread_Mutex::~ACE_Recursive_Thread_Mutex (void)
+{
+ // ACE_TRACE ("ACE_Recursive_Thread_Mutex::~ACE_Recursive_Thread_Mutex");
+ this->remove ();
+}
+
+int
+ACE_Recursive_Thread_Mutex::remove (void)
+{
+// ACE_TRACE ("ACE_Recursive_Thread_Mutex::remove");
+ int result = 0;
+ if (this->removed_ == false)
+ {
+ this->removed_ = true;
+ result = ACE_OS::recursive_mutex_destroy (&this->lock_);
+ }
+ return result;
+}
+
+// The counter part of the following two functions for Win32 are
+// located in file Synch.i
+ACE_thread_t
+ACE_Recursive_Thread_Mutex::get_thread_id (void)
+{
+ // ACE_TRACE ("ACE_Recursive_Thread_Mutex::get_thread_id");
+#if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ // @@ The structure CriticalSection in Win32 doesn't hold the thread
+ // handle of the thread that owns the lock. However it is still not
+ // clear at this point how to translate a thread handle to its
+ // corresponding thread id.
+ errno = ENOTSUP;
+ return ACE_OS::NULL_thread;
+#else
+ ACE_thread_t owner_id;
+ ACE_OS::mutex_lock (&this->lock_.nesting_mutex_);
+ owner_id = this->lock_.owner_id_;
+ ACE_OS::mutex_unlock (&this->lock_.nesting_mutex_);
+ return owner_id;
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_Recursive_Thread_Mutex::get_nesting_level (void)
+{
+ // ACE_TRACE ("ACE_Recursive_Thread_Mutex::get_nesting_level");
+#if defined (ACE_HAS_WINCE) || defined (ACE_HAS_VXTHREADS)
+ ACE_NOTSUP_RETURN (-1);
+#elif defined (ACE_HAS_RECURSIVE_MUTEXES)
+# if defined (ACE_WIN32)
+ // This is really a Win32-ism...
+ // Nothing inside of a CRITICAL_SECTION object should ever be
+ // accessed directly. It is documented to change at any time.
+ //
+ // It has been reported that this this works for all three
+ // architectures. However, this does not work on Win64 before SP1.
+ return this->lock_.RecursionCount;
+# else
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_WIN32 */
+#else
+ int nesting_level = 0;
+ ACE_OS::mutex_lock (&this->lock_.nesting_mutex_);
+ nesting_level = this->lock_.nesting_level_;
+ ACE_OS::mutex_unlock (&this->lock_.nesting_mutex_);
+ return nesting_level;
+#endif /* !ACE_HAS_WINCE */
+}
+
+ACE_Recursive_Thread_Mutex::ACE_Recursive_Thread_Mutex (const ACE_Recursive_Thread_Mutex &)
+{
+}
+
+void
+ACE_Recursive_Thread_Mutex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Recursive_Thread_Mutex::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/Recursive_Thread_Mutex.h b/ACE/ace/Recursive_Thread_Mutex.h
new file mode 100644
index 00000000000..38effc66afb
--- /dev/null
+++ b/ACE/ace/Recursive_Thread_Mutex.h
@@ -0,0 +1,194 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Recursive_Thread_Mutex.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+ * Abdullah Sowayan <abdullah.sowayan@lmco.com>
+ */
+//==========================================================================
+
+#ifndef ACE_RECURSIVE_THREAD_MUTEX_H
+#define ACE_RECURSIVE_THREAD_MUTEX_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_HAS_THREADS)
+# include "ace/Null_Mutex.h"
+#else /* ACE_HAS_THREADS */
+// ACE platform supports some form of threading.
+
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Recursive_Thread_Mutex
+ *
+ * @brief Implement a C++ wrapper that allows nested acquisition and
+ * release of a mutex that occurs in the same thread.
+ */
+class ACE_Export ACE_Recursive_Thread_Mutex
+{
+public:
+ /// Initialize a recursive mutex.
+ ACE_Recursive_Thread_Mutex (const ACE_TCHAR *name = 0,
+ ACE_mutexattr_t *arg = 0);
+
+ /// Implicitly release a recursive mutex.
+ ~ACE_Recursive_Thread_Mutex (void);
+
+ /**
+ * Implicitly release a recursive mutex. Note that only one thread
+ * should call this method since it doesn't protect against race
+ * conditions.
+ */
+ int remove (void);
+
+ /**
+ * Acquire a recursive mutex (will increment the nesting level and
+ * not deadmutex if the owner of the mutex calls this method more
+ * than once).
+ */
+ int acquire (void);
+
+ /**
+ * Block the thread until we acquire the mutex or until @a tv times
+ * out, in which case -1 is returned with @c errno == @c ETIME. Note
+ * that @a tv is assumed to be in "absolute" rather than "relative"
+ * time. The value of @a tv is updated upon return to show the
+ * actual (absolute) acquisition time.
+ */
+ int acquire (ACE_Time_Value &tv);
+
+ /**
+ * If @a tv == 0 the call <acquire()> directly. Otherwise, Block the
+ * thread until we acquire the mutex or until @a tv times out, in
+ * which case -1 is returned with @c errno == @c ETIME. Note that
+ * <*tv> is assumed to be in "absolute" rather than "relative" time.
+ * The value of <*tv> is updated upon return to show the actual
+ * (absolute) acquisition time.
+ */
+ int acquire (ACE_Time_Value *tv);
+
+ /**
+ * Conditionally acquire a recursive mutex (i.e., won't block).
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire (void);
+
+ /**
+ * Acquire mutex ownership. This calls <acquire> and is only
+ * here to make the <ACE_Recusive_Thread_Mutex> interface consistent
+ * with the other synchronization APIs.
+ */
+ int acquire_read (void);
+
+ /**
+ * Acquire mutex ownership. This calls <acquire> and is only
+ * here to make the <ACE_Recusive_Thread_Mutex> interface consistent
+ * with the other synchronization APIs.
+ */
+ int acquire_write (void);
+
+ /**
+ * Conditionally acquire mutex (i.e., won't block). This calls
+ * <tryacquire> and is only here to make the
+ * <ACE_Recusive_Thread_Mutex> interface consistent with the other
+ * synchronization APIs. Returns -1 on failure. If we "failed"
+ * because someone else already had the lock, @c errno is set to
+ * @c EBUSY.
+ */
+ int tryacquire_read (void);
+
+ /**
+ * Conditionally acquire mutex (i.e., won't block). This calls
+ * <tryacquire> and is only here to make the
+ * <ACE_Recusive_Thread_Mutex> interface consistent with the other
+ * synchronization APIs. Returns -1 on failure. If we "failed"
+ * because someone else already had the lock, @c errno is set to
+ * @c EBUSY.
+ */
+ int tryacquire_write (void);
+
+ /**
+ * This is only here to make the ACE_Recursive_Thread_Mutex
+ * interface consistent with the other synchronization APIs.
+ * Assumes the caller has already acquired the mutex using one of
+ * the above calls, and returns 0 (success) always.
+ */
+ int tryacquire_write_upgrade (void);
+
+ /**
+ * Releases a recursive mutex (will not release mutex until all the
+ * nesting level drops to 0, which means the mutex is no longer
+ * held).
+ */
+ int release (void);
+
+ /// Return the id of the thread that currently owns the mutex.
+ ACE_thread_t get_thread_id (void);
+
+ /**
+ * Return the nesting level of the recursion. When a thread has
+ * acquired the mutex for the first time, the nesting level == 1.
+ * The nesting level is incremented every time the thread acquires
+ * the mutex recursively. Note that if the ACE_HAS_RECURSIVE_MUTEXES
+ * macro is enabled then this method may return -1 on platforms that
+ * do not expose the internal count.
+ */
+ int get_nesting_level (void);
+
+ /// Returns a reference to the recursive mutex;
+ ACE_recursive_thread_mutex_t &mutex (void);
+
+ /// Returns a reference to the recursive mutex's internal mutex;
+ ACE_thread_mutex_t &get_nesting_mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = This method should *not* be public (they hold no locks...)
+ void set_thread_id (ACE_thread_t t);
+
+ /// Recursive mutex.
+ ACE_recursive_thread_mutex_t lock_;
+
+ /// Keeps track of whether <remove> has been called yet to avoid
+ /// multiple <remove> calls, e.g., explicitly and implicitly in the
+ /// destructor. This flag isn't protected by a lock, so make sure
+ /// that you don't have multiple threads simultaneously calling
+ /// <remove> on the same object, which is a bad idea anyway...
+ bool removed_;
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Recursive_Thread_Mutex &);
+ ACE_Recursive_Thread_Mutex (const ACE_Recursive_Thread_Mutex &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Recursive_Thread_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* !ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_RECURSIVE_THREAD_MUTEX_H */
diff --git a/ACE/ace/Recursive_Thread_Mutex.inl b/ACE/ace/Recursive_Thread_Mutex.inl
new file mode 100644
index 00000000000..0269de24d6b
--- /dev/null
+++ b/ACE/ace/Recursive_Thread_Mutex.inl
@@ -0,0 +1,95 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_recursive_thread_mutex_t &
+ACE_Recursive_Thread_Mutex::mutex (void)
+{
+ return lock_;
+}
+
+ACE_INLINE ACE_thread_mutex_t &
+ACE_Recursive_Thread_Mutex::get_nesting_mutex (void)
+{
+#if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ return static_cast<ACE_thread_mutex_t &> (lock_);
+#else
+ return lock_.nesting_mutex_;
+#endif /* ACE_HAS_RECURSIVE_MUTEXES */
+}
+
+ACE_INLINE void
+ACE_Recursive_Thread_Mutex::set_thread_id (ACE_thread_t t)
+{
+// ACE_TRACE ("ACE_Recursive_Thread_Mutex::set_thread_id");
+#if defined (ACE_HAS_RECURSIVE_MUTEXES)
+ ACE_UNUSED_ARG (t);
+#else /* ! ACE_HAS_RECURSIVE_MUTEXES */
+ this->lock_.owner_id_ = t;
+#endif /* ! ACE_HAS_RECURSIVE_MUTEXES */
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::acquire (void)
+{
+ return ACE_OS::recursive_mutex_lock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::release (void)
+{
+ return ACE_OS::recursive_mutex_unlock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::tryacquire (void)
+{
+ return ACE_OS::recursive_mutex_trylock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::acquire (ACE_Time_Value &tv)
+{
+ return ACE_OS::recursive_mutex_lock (&this->lock_, tv);
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::acquire (ACE_Time_Value *tv)
+{
+ return ACE_OS::recursive_mutex_lock (&this->lock_, tv);
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::acquire_read (void)
+{
+ return this->acquire ();
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::acquire_write (void)
+{
+ return this->acquire ();
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::tryacquire_read (void)
+{
+ return this->tryacquire ();
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::tryacquire_write (void)
+{
+ return this->tryacquire ();
+}
+
+ACE_INLINE int
+ACE_Recursive_Thread_Mutex::tryacquire_write_upgrade (void)
+{
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
diff --git a/ACE/ace/Recyclable.cpp b/ACE/ace/Recyclable.cpp
new file mode 100644
index 00000000000..5da42cc8d15
--- /dev/null
+++ b/ACE/ace/Recyclable.cpp
@@ -0,0 +1,22 @@
+//$Id$
+#include "ace/Recyclable.h"
+
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Recyclable.inl"
+#endif /* __ACE_INLINE __ */
+
+ACE_RCSID(ace, Recyclable, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Recyclable::ACE_Recyclable (ACE_Recyclable_State initial_state)
+ : recycle_state_ (initial_state)
+{
+}
+
+ACE_Recyclable::~ACE_Recyclable (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Recyclable.h b/ACE/ace/Recyclable.h
new file mode 100644
index 00000000000..18487ab4094
--- /dev/null
+++ b/ACE/ace/Recyclable.h
@@ -0,0 +1,79 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Recyclable.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+#ifndef ACE_RECYCLABLE_H
+#define ACE_RECYCLABLE_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// States of a recyclable object.
+enum ACE_Recyclable_State
+{
+ /// Idle and can be purged.
+ ACE_RECYCLABLE_IDLE_AND_PURGABLE,
+
+ /// Idle but cannot be purged.
+ ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE,
+
+ /// Can be purged, but is not idle (mostly for debugging).
+ ACE_RECYCLABLE_PURGABLE_BUT_NOT_IDLE,
+
+ /// Busy (i.e., cannot be recycled or purged).
+ ACE_RECYCLABLE_BUSY,
+
+ /// Closed.
+ ACE_RECYCLABLE_CLOSED,
+
+ /// Unknown state.
+ ACE_RECYCLABLE_UNKNOWN
+};
+
+/**
+ * @class ACE_Recyclable
+ */
+class ACE_Export ACE_Recyclable
+{
+public:
+ /// Destructor.
+ virtual ~ACE_Recyclable (void);
+
+ /// Get the recyclable bit
+ ACE_Recyclable_State recycle_state (void) const;
+
+ /// Set the recyclable bit
+ void recycle_state (ACE_Recyclable_State new_state);
+
+protected:
+
+ /// Constructor.
+ ACE_Recyclable (ACE_Recyclable_State initial_state);
+
+protected:
+
+ /// Our state.
+ ACE_Recyclable_State recycle_state_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Recyclable.inl"
+#endif /* __ACE_INLINE __ */
+
+#include /**/ "ace/post.h"
+#endif /*ACE_RECYCLABLE_STATE_H*/
diff --git a/ACE/ace/Recyclable.inl b/ACE/ace/Recyclable.inl
new file mode 100644
index 00000000000..ef096ff62be
--- /dev/null
+++ b/ACE/ace/Recyclable.inl
@@ -0,0 +1,20 @@
+// -*- C++ -*-
+//
+//$Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_Recyclable_State
+ACE_Recyclable::recycle_state (void) const
+{
+ return this->recycle_state_;
+}
+
+ACE_INLINE void
+ACE_Recyclable::recycle_state (ACE_Recyclable_State new_state)
+{
+ if (this->recycle_state_ != ACE_RECYCLABLE_CLOSED)
+ this->recycle_state_ = new_state;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Refcountable.cpp b/ACE/ace/Refcountable.cpp
new file mode 100644
index 00000000000..902e4362f65
--- /dev/null
+++ b/ACE/ace/Refcountable.cpp
@@ -0,0 +1,20 @@
+// $Id$
+
+#include "ace/Refcountable.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Refcountable.inl"
+#endif /* __ACE_INLINE __ */
+
+
+ACE_RCSID (ace,
+ Refcountable,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Refcountable::~ACE_Refcountable (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Refcountable.h b/ACE/ace/Refcountable.h
new file mode 100644
index 00000000000..20670d49506
--- /dev/null
+++ b/ACE/ace/Refcountable.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Refcountable.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+#ifndef ACE_REFCOUNTABLE_H
+#define ACE_REFCOUNTABLE_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Refcountable
+ *
+ */
+class ACE_Export ACE_Refcountable
+{
+public:
+ /// Destructor.
+ virtual ~ACE_Refcountable (void);
+
+ // = Increment/Decrement refcount
+ int increment (void);
+ int decrement (void);
+
+ /// Returns the current refcount.
+ int refcount (void) const;
+
+protected:
+ /// Protected constructor.
+ ACE_Refcountable (int refcount);
+
+ /// Current refcount.
+ int refcount_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#if defined (__ACE_INLINE__)
+#include "ace/Refcountable.inl"
+#endif /* __ACE_INLINE __ */
+
+#include /**/ "ace/post.h"
+#endif /*ACE_REFCOUNTABLE_H*/
diff --git a/ACE/ace/Refcountable.inl b/ACE/ace/Refcountable.inl
new file mode 100644
index 00000000000..993af65d452
--- /dev/null
+++ b/ACE/ace/Refcountable.inl
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+//
+//$Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Refcountable::ACE_Refcountable (int refcount)
+ : refcount_ (refcount)
+{
+}
+
+ACE_INLINE int
+ACE_Refcountable::increment (void)
+{
+ return ++this->refcount_;
+}
+
+ACE_INLINE int
+ACE_Refcountable::decrement (void)
+{
+ return --this->refcount_;
+}
+
+ACE_INLINE int
+ACE_Refcountable::refcount (void) const
+{
+ return this->refcount_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Refcounted_Auto_Ptr.cpp b/ACE/ace/Refcounted_Auto_Ptr.cpp
new file mode 100644
index 00000000000..7dd9d862b64
--- /dev/null
+++ b/ACE/ace/Refcounted_Auto_Ptr.cpp
@@ -0,0 +1,18 @@
+// $Id$
+
+#ifndef ACE_REFCOUNTED_AUTO_PTR_CPP
+#define ACE_REFCOUNTED_AUTO_PTR_CPP
+
+#include "ace/Refcounted_Auto_Ptr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class X, class ACE_LOCK>
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::~ACE_Refcounted_Auto_Ptr (void)
+{
+ AUTO_REFCOUNTED_PTR_REP::detach (rep_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_REFCOUNTED_AUTO_PTR_CPP */
diff --git a/ACE/ace/Refcounted_Auto_Ptr.h b/ACE/ace/Refcounted_Auto_Ptr.h
new file mode 100644
index 00000000000..1647d862270
--- /dev/null
+++ b/ACE/ace/Refcounted_Auto_Ptr.h
@@ -0,0 +1,199 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Refcounted_Auto_Ptr.h
+ *
+ * $Id$
+ *
+ * @author John Tucker <JTucker@infoglide.com>
+ */
+//=============================================================================
+
+#ifndef ACE_REFCOUNTED_AUTO_PTR_H
+#define ACE_REFCOUNTED_AUTO_PTR_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Atomic_Op.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl.
+template <class X, class ACE_LOCK> class ACE_Refcounted_Auto_Ptr_Rep;
+template <class X, class ACE_LOCK> class ACE_Refcounted_Auto_Ptr;
+
+/**
+ * @class ACE_Refcounted_Auto_Ptr
+ *
+ * @brief This class implements support for a reference counted auto_ptr.
+ * Assigning or copying instances of an ACE_Refcounted_Auto_Ptr
+ * will automatically increment the reference count. When the last
+ * instance that references a ACE_Refcounted_Auto_Ptr instance is
+ * destroyed or overwritten, it will invoke delete on its underlying
+ * pointer.
+ *
+ * The ACE_Refcounted_Auto_Ptr works by maintaining a reference to a
+ * separate representation object, ACE_Refcounted_Auto_Ptr_Rep. That
+ * separate representation object contains the reference count and
+ * the actual pointer value.
+ */
+template <class X, class ACE_LOCK>
+class ACE_Refcounted_Auto_Ptr
+{
+public:
+
+ // = Initialization and termination methods.
+
+ /// Constructor that initializes an ACE_Refcounted_Auto_Ptr to
+ /// the specified pointer value.
+ explicit ACE_Refcounted_Auto_Ptr (X *p = 0);
+
+ /// Copy constructor binds the new ACE_Refcounted_Auto_Ptr to the
+ /// representation object referenced by @a r.
+ /// An ACE_Refcounted_Auto_Ptr_Rep is created if necessary.
+ ACE_Refcounted_Auto_Ptr (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r);
+
+ /// Destructor. Releases the reference to the underlying representation.
+ /// If the release of that reference causes its reference count to reach 0,
+ /// the representation object will also be destroyed.
+ virtual ~ACE_Refcounted_Auto_Ptr (void);
+
+ /// Assignment operator that binds the current object and @a r to the same
+ /// ACE_Refcounted_Auto_Ptr_Rep. An ACE_Refcounted_Auto_Ptr_Rep
+ /// is created if necessary.
+ void operator = (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r);
+
+ /// Equality operator that returns @c true if both
+ /// ACE_Refcounted_Auto_Ptr objects point to the same underlying
+ /// representation. It does not compare the actual pointers.
+ /**
+ * @note It also returns @c true if both objects have just been
+ * instantiated and not used yet.
+ */
+ bool operator == (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ bool operator != (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Redirection operator
+ X *operator-> (void) const;
+
+ /// Accessor method.
+ X &operator *() const;
+
+ /// Check rep easily.
+ bool operator !() const;
+
+ /// Check rep easily.
+ operator bool () const;
+
+ /// Releases the reference to the underlying representation object.
+ /// @retval The pointer value prior to releasing it.
+ X *release (void);
+
+ /// Releases the current pointer value and then sets a new
+ /// pointer value specified by @a p.
+ void reset (X *p = 0);
+
+ /// Get the pointer value.
+ X *get (void) const;
+
+ /// Get the reference count value.
+ long count (void) const;
+
+ /// Returns @c true if this object does not contain a valid pointer.
+ bool null (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// the ACE_Refcounted_Auto_Ptr_Rep
+ typedef ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> AUTO_REFCOUNTED_PTR_REP;
+
+ /// Protect operations on the ACE_Refcounted_Auto_Ptr.
+ AUTO_REFCOUNTED_PTR_REP *rep_;
+};
+
+/**
+ * @class ACE_Refcounted_Auto_Ptr_Rep
+ *
+ * @brief An ACE_Refcounted_Auto_Ptr_Rep object encapsulates a pointer
+ * to an object of type X. It uses a lock object of type ACE_LOCK to protect
+ * access to the reference count.
+ *
+ * @internal ACE_Refcounted_Auto_Ptr_Rep is used internally by the
+ * ACE_Refcounted_Auto_Ptr class and is only accessible through it.
+ */
+template <class X, class ACE_LOCK>
+class ACE_Refcounted_Auto_Ptr_Rep
+{
+private:
+ friend class ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>;
+
+ /// Get the pointer value.
+ X *get (void) const;
+
+ /// Get the reference count value.
+ long count (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // = Encapsulate reference count and object lifetime of instances.
+ // These methods must go after the others to work around a bug with
+ // Borland's C++ Builder...
+
+ /// Allocate a new ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> instance,
+ /// returning NULL if it cannot be created.
+ static ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *internal_create (X *p);
+
+ /// Create a ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> and initialize
+ /// the reference count.
+ static ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *create (X *p);
+
+ /// Increase the reference count on @a rep.
+ ///
+ /// @retval @a rep if success, 0 if there's an error obtaining the lock
+ /// on @a rep.
+ static ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *attach (ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *&rep);
+
+ /// Decreases the reference count and and deletes rep if there are no
+ /// more references to rep.
+ ///
+ /// Precondition (rep != 0)
+ static void detach (ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *&rep);
+
+ /// Pointer to the result.
+ ACE_Auto_Basic_Ptr<X> ptr_;
+
+ /// Reference count.
+ mutable ACE_Atomic_Op<ACE_LOCK, long> ref_count_;
+
+private:
+ // = Constructor and destructor private.
+ ACE_Refcounted_Auto_Ptr_Rep (X *p = 0);
+ ~ACE_Refcounted_Auto_Ptr_Rep (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include "ace/Refcounted_Auto_Ptr.inl"
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Refcounted_Auto_Ptr.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Refcounted_Auto_Ptr.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_REFCOUNTED_AUTO_PTR_H */
diff --git a/ACE/ace/Refcounted_Auto_Ptr.inl b/ACE/ace/Refcounted_Auto_Ptr.inl
new file mode 100644
index 00000000000..a8412d2d3a2
--- /dev/null
+++ b/ACE/ace/Refcounted_Auto_Ptr.inl
@@ -0,0 +1,190 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class X, class ACE_LOCK> inline long
+ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>::count (void) const
+{
+ return this->ref_count_.value();
+}
+
+template <class X, class ACE_LOCK> inline long
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::count (void) const
+{
+ return this->rep_->count ();
+}
+
+template <class X, class ACE_LOCK> inline bool
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::null (void) const
+{
+ return (this->rep_ == 0 || this->rep_->get () == 0);
+}
+
+template <class X, class ACE_LOCK> inline ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *
+ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>::internal_create (X *p)
+{
+ ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ (ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>) (p),
+ 0);
+ return temp;
+}
+
+template <class X, class ACE_LOCK> inline ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *
+ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>::create (X *p)
+{
+ // Yes set ref count to zero.
+ ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *temp = internal_create (p);
+#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 X, class ACE_LOCK> inline ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *
+ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>::attach (ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>*& rep)
+{
+ if (rep == 0)
+ return 0;
+
+ ++rep->ref_count_;
+
+ return rep;
+}
+
+template <class X, class ACE_LOCK> inline void
+ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>::detach (ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>*& rep)
+{
+ if (rep == 0)
+ return;
+
+ if (rep->ref_count_-- == 0)
+ delete rep;
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>::ACE_Refcounted_Auto_Ptr_Rep (X *p)
+ : ptr_ (p),
+ ref_count_ (0)
+{
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>::~ACE_Refcounted_Auto_Ptr_Rep (void)
+{
+}
+
+template <class X, class ACE_LOCK> inline X *
+ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>::get (void) const
+{
+ return this->ptr_.get ();
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::ACE_Refcounted_Auto_Ptr (X *p)
+ : rep_ (AUTO_REFCOUNTED_PTR_REP::create (p))
+{
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::ACE_Refcounted_Auto_Ptr (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r)
+ : rep_ (AUTO_REFCOUNTED_PTR_REP::attach (((ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &) r).rep_))
+{
+}
+
+template <class X, class ACE_LOCK> inline bool
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator== (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r) const
+{
+ return r.rep_ == this->rep_;
+}
+
+template <class X, class ACE_LOCK> inline bool
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator!= (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r) const
+{
+ return r.rep_ != this->rep_;
+}
+
+template <class X, class ACE_LOCK> inline X *
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator-> (void) const
+{
+ return this->rep_->get();
+}
+
+template<class X, class ACE_LOCK> inline X &
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator *() const
+{
+ return *this->rep_->get ();
+}
+
+template<class X, class ACE_LOCK> inline bool
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator !() const
+{
+ return this->rep_->get () == 0;
+}
+
+template<class X, class ACE_LOCK> inline
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator bool () const
+{
+ return this->rep_->get () != 0;
+}
+
+template <class X, class ACE_LOCK> inline X*
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::get (void) const
+{
+ // We return the ACE_Future_rep.
+ return this->rep_->get ();
+}
+
+template<class X, class ACE_LOCK> inline X *
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::release (void)
+{
+ X *p = this->get ();
+ AUTO_REFCOUNTED_PTR_REP::detach (this->rep_);
+ this->rep_ = 0;
+ return p;
+}
+
+template<class X, class ACE_LOCK> inline void
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::reset (X *p)
+{
+ // Avoid deleting the underlying auto_ptr if assigning the same actual
+ // pointer value.
+ if (this->get () == p)
+ return;
+
+ AUTO_REFCOUNTED_PTR_REP *old_rep = this->rep_;
+ if ((this->rep_ = AUTO_REFCOUNTED_PTR_REP::create (p)) != 0)
+ AUTO_REFCOUNTED_PTR_REP::detach (old_rep);
+ else
+ this->rep_ = old_rep;
+ return;
+}
+
+template <class X, class ACE_LOCK> inline void
+ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator = (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &rhs)
+{
+ // bind <this> to the same <ACE_Refcounted_Auto_Ptr_Rep> as <r>.
+ AUTO_REFCOUNTED_PTR_REP *old_rep = this->rep_;
+ if (rhs.rep_ != 0)
+ {
+ this->rep_ = AUTO_REFCOUNTED_PTR_REP::attach
+ (const_cast<ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>& > (rhs).rep_);
+ if (this->rep_ != 0)
+ AUTO_REFCOUNTED_PTR_REP::detach (old_rep);
+ }
+ else // Assign a 0 rep to this
+ {
+ AUTO_REFCOUNTED_PTR_REP::detach (old_rep);
+ this->rep_ = 0;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Registry.cpp b/ACE/ace/Registry.cpp
new file mode 100644
index 00000000000..3b638e49b25
--- /dev/null
+++ b/ACE/ace/Registry.cpp
@@ -0,0 +1,1127 @@
+// $Id$
+
+#include "ace/Registry.h"
+
+ACE_RCSID (ace,
+ Registry,
+ "$Id$")
+
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_REGISTRY)
+
+# include "ace/os_include/os_netdb.h"
+# include "ace/OS_NS_unistd.h"
+
+// Funky macro to deal with strange error passing semantics
+// of Win32 Reg*() functions
+#define ACE_REGISTRY_CALL_RETURN(X) \
+ do { \
+ if (X != ERROR_SUCCESS) \
+ { \
+ errno = X; \
+ return -1; \
+ } \
+ else \
+ return 0; \
+ } while (0)
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_TCHAR const ACE_Registry::STRING_SEPARATOR[] = ACE_TEXT ("\\");
+
+bool
+ACE_Registry::Name_Component::operator== (const Name_Component &rhs) const
+{
+ return
+ rhs.id_ == this->id_ &&
+ rhs.kind_ == this->kind_;
+}
+
+bool
+ACE_Registry::Name_Component::operator!= (const Name_Component &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+// Simple binding constructor
+ACE_Registry::Binding::Binding ()
+ : name_ (),
+ type_ (INVALID)
+{
+}
+
+
+// Binding constructor
+// (Name version)
+ACE_Registry::Binding::Binding (const Name &name,
+ Binding_Type type)
+ : name_ (ACE_Registry::make_string (name)),
+ type_ (type)
+{
+}
+
+
+// Binding constructor
+// (String version)
+ACE_Registry::Binding::Binding (const ACE_TString &name,
+ Binding_Type type)
+ : name_ (name),
+ type_ (type)
+{
+}
+
+
+bool
+ACE_Registry::Binding::operator== (const Binding &rhs) const
+{
+ return
+ rhs.name_ == this->name_ &&
+ rhs.type_ == this->type_;
+}
+
+bool
+ACE_Registry::Binding::operator!= (const Binding &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+// Name accessor
+// (Name version)
+void
+ACE_Registry::Binding::name (Name &name)
+{
+ name = ACE_Registry::make_name (this->name_);
+}
+
+
+// Name accessors
+// (String version)
+void
+ACE_Registry::Binding::name (ACE_TString &name)
+{
+ name = this->name_;
+}
+
+
+// Name accessors
+// (String version)
+ACE_TString
+ACE_Registry::Binding::name (void)
+{
+ return this->name_;
+}
+
+
+// Type accessor
+ACE_Registry::Binding_Type
+ACE_Registry::Binding::type (void)
+{
+ return this->type_;
+}
+
+
+// Simple object constructor
+ACE_Registry::Object::Object (void *data,
+ u_long size,
+ u_long type)
+ : data_ (data),
+ size_ (size),
+ type_ (type)
+{
+}
+
+// Object accessors and set methods
+void
+ACE_Registry::Object::data (void *data)
+{
+ this->data_ = data;
+}
+
+
+void *
+ACE_Registry::Object::data (void) const
+{
+ return this->data_;
+}
+
+
+void
+ACE_Registry::Object::size (u_long size)
+{
+ this->size_ = size;
+}
+
+
+u_long
+ACE_Registry::Object::size (void) const
+{
+ return this->size_;
+}
+
+
+void
+ACE_Registry::Object::type (u_long type)
+{
+ this->type_ = type;
+}
+
+
+u_long
+ACE_Registry::Object::type (void) const
+{
+ return this->type_;
+}
+
+
+// Simple context constructor
+ACE_Registry::Naming_Context::Naming_Context (void)
+ : key_ ((HKEY) 0),
+ parent_key_ ((HKEY) 0),
+ name_ ()
+{
+}
+
+
+// Context constructor
+ACE_Registry::Naming_Context::Naming_Context (const HKEY &key)
+ : key_ (key),
+ parent_key_ ((HKEY) 0),
+ name_ ()
+{
+}
+
+
+ACE_Registry::Naming_Context::Naming_Context (const Naming_Context &rhs)
+ : key_ (rhs.key_),
+ parent_key_ (rhs.parent_key_),
+ name_ (rhs.name_)
+{
+ // This is incorrect.
+ // Rather than copying key, we should call ::DuplicateHandle()
+ // But since this is private (and not used), I don't care much
+}
+
+
+const ACE_Registry::Naming_Context &
+ACE_Registry::Naming_Context::operator= (const Naming_Context &rhs)
+{
+ ACE_UNUSED_ARG(rhs);
+
+ // Not implemented
+ return *this;
+}
+
+
+// Destructor
+ACE_Registry::Naming_Context::~Naming_Context ()
+{
+ this->close ();
+}
+
+
+// Insert <object> with <name> into <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::bind_new (const Name &name,
+ const Object &object)
+{
+ return this->bind_new (ACE_Registry::make_string (name), object);
+}
+
+
+// Insert <object> with <name> into <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::bind_new (const ACE_TString &name,
+ const Object &object)
+{
+ // temporary object
+ Object temp;
+ long result = this->resolve (name, temp);
+ if (result == 0)
+ // resolve succeeded
+ result = -1;
+ else
+ // resolve failed
+ result = this->bind (name, object);
+ return result;
+}
+
+
+// Insert or update <object> with <name> into <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::bind (const Name &name,
+ const Object &object)
+{
+ return this->bind (ACE_Registry::make_string (name), object);
+}
+
+
+// Insert or update <object> with <name> into <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::bind (const ACE_TString &name,
+ const Object &object)
+{
+ long result = ACE_TEXT_RegSetValueEx (this->key_,
+ name.c_str (),
+ 0,
+ object.type (),
+ (const BYTE *) object.data (),
+ object.size ());
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Update <object> with <name> in <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::rebind (const Name &name,
+ const Object &new_object)
+{
+ return this->rebind (ACE_Registry::make_string (name), new_object);
+}
+
+
+// Update <object> with <name> in <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::rebind (const ACE_TString &name,
+ const Object &new_object)
+{
+ Object old_object;
+ // find the old one first
+ long result = this->resolve (name, old_object);
+ if (result == 0)
+ // no need to delete first
+ result = this->bind (name, new_object);
+ return result;
+}
+
+
+// Find <object> with <name> in <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::resolve (const Name &name,
+ Object &object)
+{
+ return this->resolve (ACE_Registry::make_string (name), object);
+}
+
+
+// Find <object> with <name> in <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::resolve (const ACE_TString &name,
+ Object &object)
+{
+ // Get object state
+ u_long type;
+ void *data = object.data ();
+ u_long size = object.size ();
+
+ long result = ACE_TEXT_RegQueryValueEx (this->key_,
+ name.c_str (),
+ 0,
+ &type,
+ (BYTE *)data,
+ &size);
+ if (result == ERROR_SUCCESS)
+ {
+ // Reset object state
+ // No need to set object.data()
+ object.type (type);
+ object.size (size);
+ }
+
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Remove object with <name> in <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::unbind (const Name &name)
+{
+ return this->unbind (ACE_Registry::make_string (name));
+}
+
+
+// Remove object with <name> in <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::unbind (const ACE_TString &name)
+{
+ long result = ACE_TEXT_RegDeleteValue (this->key_,
+ name.c_str ());
+
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Create new <naming_context> relative to <this> context
+// This method may not mean a lot in this implementation
+int
+ACE_Registry::Naming_Context::new_context (Naming_Context &naming_context)
+{
+ // Make sure that we reset the state and close keys
+ return naming_context.close ();
+}
+
+
+// Insert <naming_context> with <name> relative to <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::bind_new_context (const Name &name,
+ Naming_Context &naming_context,
+ u_long persistence,
+ u_long security_access,
+ LPSECURITY_ATTRIBUTES security_attributes)
+{
+ return this->bind_new_context (ACE_Registry::make_string (name),
+ naming_context,
+ persistence,
+ security_access,
+ security_attributes);
+}
+
+
+// Insert <naming_context> with <name> relative to <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::bind_new_context (const ACE_TString &name,
+ Naming_Context &naming_context,
+ u_long persistence,
+ u_long security_access,
+ LPSECURITY_ATTRIBUTES security_attributes)
+{
+ u_long reason;
+
+ long result = ACE_TEXT_RegCreateKeyEx (this->key_,
+ name.c_str (),
+ 0,
+ 0,
+ persistence,
+ security_access,
+ security_attributes,
+ &naming_context.key_,
+ &reason);
+ if (result == ERROR_SUCCESS)
+ // If create succeeds
+ {
+ if (reason == REG_CREATED_NEW_KEY)
+ // If new key: success
+ {
+ // Set the correct parent
+ naming_context.parent (this->key_);
+ // Set the correct name
+ naming_context.name (name);
+ }
+ else
+ // reason == REG_OPENED_EXISTING_KEY
+ // Failed to make new key
+ {
+ // reset result to failure
+ result = -1;
+ // Close the key first
+ ::RegCloseKey (naming_context.key_);
+ // Reset key
+ naming_context.key_ = (HKEY) 0;
+ }
+ }
+
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Insert or update <naming_context> with <name> relative to <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::bind_context (const Name &name,
+ /* const */ Naming_Context &naming_context,
+ u_long persistence,
+ u_long security_access,
+ LPSECURITY_ATTRIBUTES security_attributes)
+{
+ return this->bind_context (ACE_Registry::make_string (name),
+ naming_context,
+ persistence,
+ security_access,
+ security_attributes);
+}
+
+
+// Insert or update <naming_context> with <name> relative to <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::bind_context (const ACE_TString &name,
+ /* const */ Naming_Context &naming_context,
+ u_long persistence,
+ u_long security_access,
+ LPSECURITY_ATTRIBUTES security_attributes)
+{
+ u_long reason;
+
+ long result = ACE_TEXT_RegCreateKeyEx (this->key_,
+ name.c_str (),
+ 0,
+ 0,
+ persistence,
+ security_access,
+ security_attributes,
+ &naming_context.key_,
+ &reason);
+ if (result == ERROR_SUCCESS)
+ {
+ // Set the correct parent
+ naming_context.parent (this->key_);
+ // Set the correct name
+ naming_context.name (name);
+ }
+
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Rename <naming_context> to <name>
+// (Name version)
+int
+ACE_Registry::Naming_Context::rebind_context (const Name &name,
+ /* const */ Naming_Context &new_naming_context)
+{
+ return this->rebind_context (ACE_Registry::make_string (name),
+ new_naming_context);
+}
+
+
+// Rename <naming_context> to <name>
+// (String version)
+int
+ACE_Registry::Naming_Context::rebind_context (const ACE_TString &name,
+ /* const */ Naming_Context &new_naming_context)
+{
+ Naming_Context old_naming_context;
+ // find the old one first
+ long result = this->resolve_context (name,
+ old_naming_context);
+ if (result == 0)
+ {
+ // naming_context is found: delete entry
+ result = this->unbind_context (name);
+ if (result == 0)
+ {
+ // successful deletion; rebind
+ // beware of race conditions here
+ // (lets resolve this later)
+ result = this->bind_new_context (name, new_naming_context);
+ }
+ }
+ return result;
+}
+
+
+// Remove naming_context with <name> from <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::unbind_context (const Name &name)
+{
+ return this->unbind_context (ACE_Registry::make_string (name));
+}
+
+
+// Remove naming_context with <name> from <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::unbind_context (const ACE_TString &name)
+{
+ long result = ACE_TEXT_RegDeleteKey (this->key_,
+ name.c_str ());
+
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Find <naming_context> with <name> in <this> context
+// (Name version)
+int
+ACE_Registry::Naming_Context::resolve_context (const Name &name,
+ Naming_Context &naming_context,
+ u_long security_access)
+{
+ return this->resolve_context (ACE_Registry::make_string (name),
+ naming_context,
+ security_access);
+}
+
+
+// Find <naming_context> with <name> in <this> context
+// (String version)
+int
+ACE_Registry::Naming_Context::resolve_context (const ACE_TString &name,
+ Naming_Context &naming_context,
+ u_long security_access)
+{
+ long result = ACE_TEXT_RegOpenKeyEx (this->key_,
+ name.c_str (),
+ 0,
+ security_access,
+ &naming_context.key_);
+ if (result == ERROR_SUCCESS)
+ {
+ // set the correct parent
+ naming_context.parent (this->key_);
+ // set the correct name
+ naming_context.name (name);
+ }
+
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Same as unbind_context() with <this> as naming_context
+int
+ACE_Registry::Naming_Context::destroy (void)
+{
+ // hopefully the parent_key_ is still open
+ long result = ACE_TEXT_RegDeleteKey (this->parent_key_,
+ this->name_.c_str ());
+
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Sync content of context to disk
+int
+ACE_Registry::Naming_Context::flush (void)
+{
+ long result = ::RegFlushKey (this->key_);
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Close the handle of the context
+int
+ACE_Registry::Naming_Context::close (void)
+{
+ long result = this->key_ ? ::RegCloseKey (this->key_) : ERROR_SUCCESS;
+ ACE_REGISTRY_CALL_RETURN (result);
+}
+
+
+// Convert a <name> to a <string>
+ACE_TString
+ACE_Registry::make_string (const Name &const_name)
+{
+ ACE_TString string;
+ Name &name = const_cast<Name &> (const_name);
+
+ // Iterator through the components of name
+ for (Name::iterator iterator = name.begin ();
+ iterator != name.end ();
+ iterator++)
+ {
+ if (iterator != name.begin ())
+ // If this is not the first component, we will add separators
+ string += STRING_SEPARATOR;
+ const Name_Component &component = *iterator;
+ // Add to string
+ string += component.id_;
+ }
+
+ return string;
+}
+
+
+// Convert a <string> to a <name>
+ACE_Registry::Name
+ACE_Registry::make_name (const ACE_TString &string)
+{
+ ACE_TString::size_type new_position = 0;
+ ACE_TString::size_type last_position = 0;
+ Name name;
+
+ // Rememeber: NPOS is -1
+ while (new_position != ACE_TString::npos)
+ {
+ Name_Component component;
+ // Find the separator
+ new_position = string.find (STRING_SEPARATOR, new_position);
+ if (new_position != ACE_TString::npos)
+ // If we have not gone past the end
+ {
+ // Get the substring
+ component.id_ = string.substr (last_position,
+ new_position - last_position);
+ // Skip past the seperator
+ new_position +=
+ ACE_OS::strlen (STRING_SEPARATOR);
+ }
+ else
+ {
+ // Get the last substring
+ component.id_ = string.substr (last_position);
+ }
+ // Update positions
+ last_position = new_position;
+ // Insert component into name
+ name.insert (component);
+ }
+
+ return name;
+}
+
+
+// Set key
+void
+ACE_Registry::Naming_Context::key (HKEY key)
+{
+ this->key_ = key;
+}
+
+
+// Get key
+HKEY
+ACE_Registry::Naming_Context::key (void)
+{
+ return this->key_;
+}
+
+
+// Set parent
+void
+ACE_Registry::Naming_Context::parent (HKEY parent)
+{
+ this->parent_key_ = parent;
+}
+
+
+// Get parent
+HKEY
+ACE_Registry::Naming_Context::parent (void)
+{
+ return this->parent_key_;
+}
+
+
+// Set name
+// (Name version)
+void
+ACE_Registry::Naming_Context::name (const Name &name)
+{
+ this->name_ = ACE_Registry::make_string (name);
+}
+
+
+// Get name
+// (Name version)
+void
+ACE_Registry::Naming_Context::name (Name &name)
+{
+ name = ACE_Registry::make_name (this->name_);
+}
+
+
+// Set name
+// (String version)
+void
+ACE_Registry::Naming_Context::name (const ACE_TString &name)
+{
+ this->name_ = name;
+}
+
+
+// Get name
+// (String version)
+ACE_TString
+ACE_Registry::Naming_Context::name (void)
+{
+ return this->name_;
+}
+
+
+// Get name
+// (String version)
+void
+ACE_Registry::Naming_Context::name (ACE_TString &name)
+{
+ name = this->name_;
+}
+
+
+// listing function: iterator creator
+// This is useful when there are many objects and contexts
+// in <this> context and you only want to look at a few entries
+// at a time
+int
+ACE_Registry::Naming_Context::list (u_long how_many,
+ Binding_List &list,
+ Binding_Iterator &iter)
+{
+ // Empty list
+ static const ACE_Registry::Binding_List empty_list;
+ // Make sure that the list is empty
+ list = empty_list;
+
+ // Correctly initalize the iterator
+ iter.reset ();
+
+ // Make sure that the iterator uses <this> naming context
+ iter.naming_context (*this);
+
+ // Start iterations from the objects
+ iter.current_enumeration (iter.object_iteration_);
+
+ // Get the next <how_many> values
+ long result = iter.next_n (how_many,
+ list);
+ return result;
+}
+
+
+// listing function: iterator creator
+// This gives back a listing of all entries in <this> context.
+int
+ACE_Registry::Naming_Context::list (Binding_List &list)
+{
+ // Empty list
+ static const ACE_Registry::Binding_List empty_list;
+ // Make sure that the list is empty
+ list = empty_list;
+
+ // Create an iterator
+ ACE_Registry::Binding_Iterator iterator;
+
+ // Make sure that the iterator uses <this> naming context
+ iterator.naming_context (*this);
+
+ // Start iterations from the objects
+ iterator.current_enumeration (iterator.object_iteration_);
+
+ long result = 0;
+ while (1)
+ {
+ ACE_Registry::Binding binding;
+ result = iterator.next_one (binding);
+ if (result == 0)
+ list.insert (binding);
+ else
+ break;
+ }
+ return 0;
+}
+
+
+// Default constructor
+ACE_Registry::Binding_Iterator::Binding_Iterator ()
+{
+ this->object_iteration_.iterator (this);
+ this->context_iteration_.iterator (this);
+ this->iteration_complete_.iterator (this);
+ this->reset ();
+}
+
+
+void
+ACE_Registry::Binding_Iterator::reset ()
+{
+ this->current_enumeration_ = &this->iteration_complete_;
+ this->iteration_complete_.reset ();
+ this->object_iteration_.reset ();
+ this->context_iteration_.reset ();
+}
+
+
+void
+ACE_Registry::Binding_Iterator::Iteration_State::reset ()
+{
+ this->index_ = 0;
+}
+
+
+void
+ACE_Registry::Binding_Iterator::Iteration_State::iterator (Binding_Iterator *iter)
+{
+ this->parent_ = iter;
+}
+
+
+ACE_Registry::Binding_Iterator::Iteration_State::Iteration_State ()
+ : index_ (0)
+{
+}
+
+
+// Next entry
+int
+ACE_Registry::Binding_Iterator::next_one (Binding &binding)
+{
+ u_long how_many = 1;
+ Binding_List list;
+
+ // Get next n (where n is one)
+ long result = this->next_n (how_many, list);
+
+ if (result == 0)
+ // Success
+ binding = (*list.begin ());
+
+ return result;
+}
+
+
+// Next <how_many> entries
+int
+ACE_Registry::Binding_Iterator::next_n (u_long how_many,
+ Binding_List &list)
+{
+ // Empty list
+ static const ACE_Registry::Binding_List empty_list;
+ // Make sure that the list is empty
+ list = empty_list;
+
+ return this->current_enumeration_->next_n (how_many, list);
+}
+
+
+// Destroy iterator
+int
+ACE_Registry::Binding_Iterator::destroy (void)
+{
+ this->reset ();
+ return 0;
+}
+
+
+// Set/Get naming_context
+void
+ACE_Registry::Binding_Iterator::naming_context (Naming_Context &naming_context)
+{
+ this->naming_context_ = &naming_context;
+}
+
+
+ACE_Registry::Naming_Context &
+ACE_Registry::Binding_Iterator::naming_context (void)
+{
+ return *this->naming_context_;
+}
+
+
+// Set/Get current enumeration
+void
+ACE_Registry::Binding_Iterator::current_enumeration (Iteration_State &current_enumeration)
+{
+ this->current_enumeration_ = &current_enumeration;
+}
+
+
+ACE_Registry::Binding_Iterator::Iteration_State &
+ACE_Registry::Binding_Iterator::current_enumeration (void)
+{
+ return *this->current_enumeration_;
+}
+
+
+int
+ACE_Registry::Binding_Iterator::Object_Iteration::next_n (u_long how_many,
+ Binding_List &list)
+{
+ // Make a copy
+ u_long requested = how_many;
+
+ // While there are more entries to be added to the list
+ while (how_many > 0)
+ {
+ ACE_TCHAR string [ACE_Registry::Naming_Context::MAX_OBJECT_NAME_SIZE];
+ u_long size = sizeof string / sizeof (ACE_TCHAR);
+ long result = ACE_TEXT_RegEnumValue (this->parent_->naming_context ().key (),
+ this->index_,
+ string,
+ &size,
+ 0,
+ 0,
+ 0,
+ 0);
+ switch (result)
+ {
+ case ERROR_SUCCESS:
+ // Object found
+ {
+ // Readjust counters
+ this->index_++;
+ how_many--;
+
+ // Add to list
+ // Create binding
+ Binding binding (string, OBJECT);
+ // Add to binding list
+ list.insert (binding);
+ }
+ // Continue to add to list
+ break;
+
+ case ERROR_NO_MORE_ITEMS:
+ // Enumeration of objects complete
+ // Reset index
+ this->index_ = 0;
+
+ // Current enumeration will become CONTEXTS
+ this->parent_->current_enumeration (this->parent_->context_iteration_);
+ result = this->parent_->current_enumeration ().next_n (how_many,
+ list);
+ // If we were able to add objects
+ if (requested != how_many)
+ return 0;
+ else
+ return result;
+
+ default:
+ // Strange error
+ // Reset index
+ this->index_ = 0;
+ // Current enumeration will become COMPLETE
+ this->parent_->current_enumeration (this->parent_->iteration_complete_);
+ // strange error
+ return -1;
+ }
+ }
+ // If we reach here, all of <how_many> pairs were added to the list
+ // Since more entries may be available
+ // current enumeration will remain OBJECTS
+ return 0;
+}
+
+
+int
+ACE_Registry::Binding_Iterator::Context_Iteration::next_n (u_long how_many,
+ Binding_List &list)
+{
+ // Make a copy
+ u_long requested = how_many;
+
+ // While there are more entries to be added to the list
+ while (how_many > 0)
+ {
+ ACE_TCHAR string [ACE_Registry::Naming_Context::MAX_CONTEXT_NAME_SIZE];
+ u_long size = sizeof string / sizeof (ACE_TCHAR);
+ long result = ACE_TEXT_RegEnumKeyEx (this->parent_->naming_context (). key (),
+ this->index_,
+ string,
+ &size,
+ 0,
+ 0,
+ 0,
+ 0);
+ switch (result)
+ {
+ case ERROR_SUCCESS:
+ // Object found
+ {
+ // Readjust counters
+ this->index_++;
+ how_many--;
+
+ // Add to list
+ // Create binding
+ Binding binding (string, CONTEXT);
+ // Add to binding list
+ list.insert (binding);
+ }
+ // Continue to add to list
+ break;
+
+ case ERROR_NO_MORE_ITEMS:
+ // Enumeration of objects complete
+
+ /* FALL THROUGH */
+
+ default:
+ // Strange error
+
+ // Reset index
+ this->index_ = 0;
+ // Current enumeration will become CONTEXTS
+ this->parent_->current_enumeration (this->parent_->iteration_complete_);
+
+ // If we were able to add contexts
+ if (requested != how_many)
+ return 0;
+ else
+ return -1;
+ }
+ }
+ // If we reach here, all of <how_many> pairs were added to the list
+ // Since more entries may be available
+ // current enumeration will remain CONTEXTS
+ return 0;
+}
+
+
+int
+ACE_Registry::Binding_Iterator::Iteration_Complete::next_n (u_long how_many,
+ Binding_List &list)
+{
+ ACE_UNUSED_ARG(list);
+ ACE_UNUSED_ARG(how_many);
+
+ // No more values
+ return -1;
+}
+
+
+// Factory method to connect to predefined registries
+// This method works for both remote and local machines
+// However, for remote machines CLASSES_ROOT and CURRENT_USER
+// types are not allowed
+/* static */
+int
+ACE_Predefined_Naming_Contexts::connect (ACE_Registry::Naming_Context &naming_context,
+ HKEY predefined,
+ const ACE_TCHAR *machine_name)
+{
+#if defined (ACE_HAS_WINCE)
+ return -1;
+#else
+ long result = -1;
+
+ if (machine_name != 0 && ACE_OS::strcmp (ACE_TEXT ("localhost"), machine_name) == 0)
+ machine_name = 0;
+
+ if (predefined == HKEY_LOCAL_MACHINE || predefined == HKEY_USERS)
+ result =
+ ACE_TEXT_RegConnectRegistry (const_cast<ACE_TCHAR *> (machine_name),
+ predefined,
+ &naming_context.key_);
+ if (predefined == HKEY_CURRENT_USER || predefined == HKEY_CLASSES_ROOT)
+ // Make sure that for these types, the machine is local
+ if (machine_name == 0 ||
+ ACE_Predefined_Naming_Contexts::is_local_host (machine_name))
+ {
+ naming_context.key_ = predefined;
+ result = 0;
+ }
+ else
+ result = -1;
+
+ ACE_REGISTRY_CALL_RETURN (result);
+#endif // ACE_HAS_WINCE
+}
+
+// Check if <machine_name> is the local host
+/* static */
+int
+ACE_Predefined_Naming_Contexts::is_local_host (const ACE_TCHAR *machine_name)
+{
+ ACE_TCHAR local_host[MAXHOSTNAMELEN];
+ int result = ACE_OS::hostname (local_host, sizeof local_host / sizeof (ACE_TCHAR));
+ if (result == 0)
+ result = !ACE_OS::strcmp (local_host, machine_name);
+ else
+ result = 0;
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && !ACE_LACKS_WIN32_REGISTRY */
diff --git a/ACE/ace/Registry.h b/ACE/ace/Registry.h
new file mode 100644
index 00000000000..e7a882ee357
--- /dev/null
+++ b/ACE/ace/Registry.h
@@ -0,0 +1,559 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Registry.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali (irfan@cs.wustl.edu)
+ */
+//=============================================================================
+
+
+#ifndef ACE_REGISTRY_H
+#define ACE_REGISTRY_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_WIN32_REGISTRY)
+// This only works on registry-capable Win32 platforms.
+
+#include "ace/Containers.h"
+#include "ace/SString.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Registry
+ *
+ * @brief A Name Server implementation
+ *
+ * The registry interface is inspired by the interface
+ * specified in the CORBA Naming Service Specification.
+ * The implementation is done through Win32 <Reg*> functions.
+ * Other than providing an OO wrapper for the Win32 <Reg*>
+ * functions, ACE_Registry provides an abstraction for iteration
+ * over the elements of the Registry.
+ */
+class ACE_Export ACE_Registry
+{
+public:
+
+ /// International string
+ struct ACE_Export Name_Component
+ {
+ ACE_TString id_;
+ ACE_TString kind_;
+
+ bool operator== (const Name_Component &rhs) const;
+ bool operator!= (const Name_Component &rhs) const;
+ // Comparison
+ };
+ // The <id_> field is used,
+ // but the <kind_> field is currently ignored
+
+ /// A Name is an ordered collections of components (ids)
+ typedef ACE_Unbounded_Set<Name_Component> Name;
+
+ /// Separator for components in a name
+ static const ACE_TCHAR STRING_SEPARATOR[];
+
+ /// Convert a @a name to a @c string
+ static ACE_TString make_string (const Name &name);
+
+ /// Convert a @a string to a @c name
+ static Name make_name (const ACE_TString &string);
+
+ /// There are two types of bindings
+ enum Binding_Type {INVALID, OBJECT, CONTEXT};
+
+ struct ACE_Export Binding
+ {
+ /// Empty (default) constructor
+ Binding (void);
+
+ /// Constructor
+ /// (Name version)
+ Binding (const Name &binding_name,
+ Binding_Type binding_type);
+
+ /// Constructor
+ /// (String version)
+ Binding (const ACE_TString &binding_name,
+ Binding_Type binding_type);
+
+ bool operator== (const Binding &rhs) const;
+ bool operator!= (const Binding &rhs) const;
+ // Comparison
+
+ /// Name accessor
+ /// (Name version)
+ void name (Name &name);
+
+ /// Set Name (String version)
+ void name (ACE_TString &name);
+
+ /// Get Name (String version)
+ ACE_TString name (void);
+
+ /// Type accessor
+ Binding_Type type (void);
+
+ private:
+ /// A binding has a name
+ ACE_TString name_;
+
+ /// .... and a type
+ Binding_Type type_;
+ };
+
+ /// A list of bindings
+ typedef ACE_Unbounded_Set<Binding> Binding_List;
+
+ // Forward declaration of iterator
+ class Binding_Iterator;
+
+ /**
+ * @class Object
+ *
+ * @brief An object representation
+ *
+ * In CORBA, all objects inherit from (CORBA::Object).
+ * For the registry, this is used as a wrapper for an
+ * instance of a built-in data type.
+ * Think about an object as being similar to a file
+ * in a file system.
+ */
+ class ACE_Export Object
+ {
+ public:
+ /// Default constructor
+ Object (void *data = 0,
+ u_long size = 0,
+ u_long type = REG_NONE);
+
+ /// Set data
+ void data (void *data);
+
+ /// Get data
+ void *data (void) const;
+
+ /// Set size
+ void size (u_long size);
+
+ /// Get size
+ u_long size (void) const;
+
+ /// Set type
+ void type (u_long type);
+
+ /// Get type
+ u_long type (void) const;
+
+ private:
+ /// Pointer to data
+ void *data_;
+
+ /// Size of the data
+ u_long size_;
+
+ /// Type of data
+ u_long type_;
+ };
+
+ /**
+ * @class Naming_Context
+ *
+ * @brief An context representation
+ *
+ * Think about a context as being similar to a directory
+ * in a file system.
+ */
+ class ACE_Export Naming_Context
+ {
+ public:
+ /// Friend factory
+ friend class ACE_Predefined_Naming_Contexts;
+
+ enum {
+ /// Max sizes of names
+ /// (Not too sure about this value)
+ MAX_OBJECT_NAME_SIZE = BUFSIZ,
+
+ /// Max size of context name
+ MAX_CONTEXT_NAME_SIZE = MAXPATHLEN + 1
+ };
+
+ /// Empty constructor: keys will be NULL
+ Naming_Context (void);
+
+ /// Constructor: key_ will be set to @a key
+ Naming_Context (const HKEY &key);
+
+ /// Destructor will call <Naming_Context::close>.
+ ~Naming_Context (void);
+
+ // The following interfaces are for objects
+
+ /**
+ * Insert @a object with @a name into @c this context.
+ * This will fail if @a name already exists
+ * (Name version)
+ */
+ int bind_new (const Name &name,
+ const Object &object);
+
+ /**
+ * Insert @a object with @a name into @c this context
+ * This will fail if @a name already exists
+ * (String version)
+ */
+ int bind_new (const ACE_TString &name,
+ const Object &object);
+
+ /**
+ * Insert or update @a object with @a name into @c this context
+ * This will not fail if @a name already exists
+ * (Name version)
+ */
+ int bind (const Name &name,
+ const Object &object);
+
+ /**
+ * Insert or update <object> with @a name into @c this context
+ * This will not fail if @a name already exists
+ * (String version)
+ */
+ int bind (const ACE_TString &name,
+ const Object &object);
+
+ /// Update <object> with @a name in @c this context
+ /// (Name version)
+ int rebind (const Name &name,
+ const Object &object);
+
+ /// Update <object> with @a name in @c this context
+ int rebind (const ACE_TString &name,
+ const Object &object);
+
+ /// Find <object> with @a name in @c this context
+ /// (Name version)
+ int resolve (const Name &name,
+ Object &object);
+
+ /// Find <object> with @a name in @c this context
+ int resolve (const ACE_TString &name,
+ Object &object);
+
+ /// Delete object with @a name in @c this context
+ /// (Name version)
+ int unbind (const Name &name);
+
+ /// Delete object with @a name in @c this context
+ int unbind (const ACE_TString &name);
+
+
+ // The following interfaces are for Naming Context
+
+ /// Create new @c naming_context
+ int new_context (Naming_Context &naming_context);
+
+ /**
+ * Insert <naming_context> with @a name relative to @c this context
+ * This will fail if @a name already exists
+ * (Name version)
+ */
+ int bind_new_context (const Name &name,
+ Naming_Context &naming_context,
+ u_long persistence = REG_OPTION_NON_VOLATILE,
+ u_long security_access = KEY_ALL_ACCESS,
+ LPSECURITY_ATTRIBUTES security_attributes = 0);
+
+ /// Insert <naming_context> with @a name relative to @c this context
+ /// This will fail if @a name already exists
+ int bind_new_context (const ACE_TString &name,
+ Naming_Context &naming_context,
+ u_long persistence = REG_OPTION_NON_VOLATILE,
+ u_long security_access = KEY_ALL_ACCESS,
+ LPSECURITY_ATTRIBUTES security_attributes = 0);
+
+ /**
+ * Insert or update <naming_context> with @a name relative to @c this context
+ * This will not fail if @a name already exists
+ * (Name version)
+ */
+ int bind_context (const Name &name,
+ /* const */ Naming_Context &naming_context,
+ u_long persistence = REG_OPTION_NON_VOLATILE,
+ u_long security_access = KEY_ALL_ACCESS,
+ LPSECURITY_ATTRIBUTES security_attributes = 0);
+
+ /// Insert or update <naming_context> with @a name relative to @c this context
+ /// This will not fail if @a name already exists
+ int bind_context (const ACE_TString &name,
+ /* const */ Naming_Context &naming_context,
+ u_long persistence = REG_OPTION_NON_VOLATILE,
+ u_long security_access = KEY_ALL_ACCESS,
+ LPSECURITY_ATTRIBUTES security_attributes = 0);
+
+ /// Rename <naming_context> to @a name
+ /// (Name version)
+ int rebind_context (const Name &name,
+ /* const */ Naming_Context &naming_context);
+
+ /// Rename <naming_context> to @a name
+ int rebind_context (const ACE_TString &name,
+ /* const */ Naming_Context &naming_context);
+
+ /// Find <naming_context> with @a name in @c this context
+ /// (Name version)
+ int resolve_context (const Name &name,
+ Naming_Context &naming_context,
+ u_long security_access = KEY_ALL_ACCESS);
+
+ /// Find <naming_context> with @a name in @c this context
+ int resolve_context (const ACE_TString &name,
+ Naming_Context &naming_context,
+ u_long security_access = KEY_ALL_ACCESS);
+
+ /// Remove naming_context with @a name from @c this context
+ /// (Name version)
+ int unbind_context (const Name &name);
+
+ /// Remove naming_context with @a name from @c this context
+ int unbind_context (const ACE_TString &name);
+
+ /// Same as <unbind_context> with @c this as naming_context
+ int destroy (void);
+
+ /**
+ * listing function: iterator creator
+ * This is useful when there are many objects and contexts
+ * in @c this context and you only want to look at a few entries
+ * at a time
+ */
+ int list (u_long how_many,
+ Binding_List &list,
+ Binding_Iterator &iterator);
+
+ /// listing function: iterator creator
+ /// This gives back a listing of all entries in @c this context.
+ int list (Binding_List &list);
+
+ // Some other necessary functions which are
+ // not part of the CORBA interface
+
+ /// Sync content of context to disk
+ int flush (void);
+
+ /// Close the handle of the context
+ /// @note <close> does not call <flush>
+ int close (void);
+
+ // Accessors
+
+ /// Get key
+ HKEY key (void);
+
+ // void parent (HKEY parent);
+ /// Get parent
+ HKEY parent (void);
+
+ /// Get name
+ /// (Name version)
+ void name (Name &name);
+
+ /// Set name (String version)
+ void name (ACE_TString &name);
+
+ /// Get name (String version)
+ ACE_TString name (void);
+
+ protected:
+ /// Set key
+ void key (HKEY key);
+
+ /// Set parent
+ void parent (HKEY parent);
+
+ /// Set name
+ /// (Name version)
+ void name (const Name &name);
+
+ /// Set name
+ /// (String version)
+ void name (const ACE_TString &name);
+
+ private:
+ /// Disallow copy constructors
+ Naming_Context (const Naming_Context &rhs);
+
+ /// Disallow assignment
+ const Naming_Context &operator= (const Naming_Context &rhs);
+
+ /// Key for self
+ HKEY key_;
+
+ /// Key for parent
+ HKEY parent_key_;
+
+ /// Name of self
+ ACE_TString name_;
+ };
+
+ /**
+ * @class Binding_Iterator
+ *
+ * @brief An iterator
+ *
+ * Useful when iteratorating over a few entries at a time
+ */
+ class ACE_Export Binding_Iterator
+ {
+ public:
+ /// Friend factory
+ friend class Naming_Context;
+
+ /// Default constructor
+ Binding_Iterator (void);
+
+ /// Next entry
+ int next_one (Binding &binding);
+
+ /// Next <how_many> entries
+ int next_n (u_long how_many,
+ Binding_List &list);
+
+ /// Cleanup
+ int destroy (void);
+
+ /// Reset the internal state of the iterator
+ void reset (void);
+
+ /// Get naming_context that the iterator is iterating over
+ Naming_Context &naming_context (void);
+
+ private:
+
+ /// Set naming_context that the iterator is iterating over
+ void naming_context (Naming_Context& naming_context);
+
+ /// Reference to context
+ Naming_Context *naming_context_;
+
+ public:
+ // This should really be private
+ // But the compiler is broken
+
+ /**
+ * @class Iteration_State
+ *
+ * Base class for state
+ */
+ class ACE_Export Iteration_State
+ {
+ public:
+ /// Constructor
+ Iteration_State ();
+
+ /// Set the iterator reference.
+ void iterator (Binding_Iterator *iterator);
+
+ /// Next <how_many> entries
+ virtual int next_n (u_long how_many,
+ Binding_List &list) = 0;
+
+ /// Reset state
+ void reset (void);
+
+ protected:
+ /// Pointer to parent iterator
+ Binding_Iterator *parent_;
+
+ u_long index_;
+ };
+
+ private:
+ class ACE_Export Object_Iteration : public Iteration_State
+ {
+ /// Next <how_many> entries
+ int next_n (u_long how_many,
+ Binding_List &list);
+ };
+
+ class ACE_Export Context_Iteration : public Iteration_State
+ {
+ public:
+ /// Next @a how_many entries
+ int next_n (u_long how_many,
+ Binding_List &list);
+ };
+
+ class ACE_Export Iteration_Complete : public Iteration_State
+ {
+ public:
+ /// Next @a how_many entries
+ int next_n (u_long how_many,
+ Binding_List &list);
+ };
+
+ /// Friend states
+ friend class Iteration_State;
+ friend class Object_Iteration;
+ friend class Context_Iteration;
+ friend class Iteration_Complete;
+
+ /// Instances of all states
+ Object_Iteration object_iteration_;
+ Context_Iteration context_iteration_;
+ Iteration_Complete iteration_complete_;
+
+ /// Pointer to current state
+ Iteration_State *current_enumeration_;
+
+ /// Set current_enumeration
+ void current_enumeration (Iteration_State& current_enumeration);
+
+ /// Get current_enumeration
+ Iteration_State &current_enumeration (void);
+ };
+};
+
+/**
+ * @class ACE_Predefined_Naming_Contexts
+ *
+ * @brief A factory for predefined registries, which exist by default
+ * on Win32 platforms
+ *
+ * This factory can connect to both local and remote
+ * predefined registries.
+ */
+class ACE_Export ACE_Predefined_Naming_Contexts
+{
+public:
+ /**
+ * Factory method for connecting to predefined registries. This
+ * method works for both remote and local machines. However, for
+ * remote machines, HKEY_CLASSES_ROOT and HKEY_CURRENT_USER types
+ * are not allowed
+ */
+ static int connect (ACE_Registry::Naming_Context &naming_context,
+ HKEY predefined = HKEY_LOCAL_MACHINE,
+ const ACE_TCHAR *machine_name = 0);
+
+private:
+ /// Check if @a machine_name is the local host
+ static int is_local_host (const ACE_TCHAR *machine_name);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && !ACE_LACKS_WIN32_REGISTRY */
+#include /**/ "ace/post.h"
+#endif /* ACE_REGISTRY_H */
diff --git a/ACE/ace/Registry_Name_Space.cpp b/ACE/ace/Registry_Name_Space.cpp
new file mode 100644
index 00000000000..c2dd3618887
--- /dev/null
+++ b/ACE/ace/Registry_Name_Space.cpp
@@ -0,0 +1,293 @@
+// $Id$
+
+#include "ace/Registry_Name_Space.h"
+
+ACE_RCSID(ace, Registry_Name_Space, "$Id$")
+
+#if (defined (ACE_WIN32) && defined (ACE_USES_WCHAR))
+// This only works on Win32 platforms when ACE_USES_WCHAR is turned on
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"), ACE_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)
+{
+ ACE_UNUSED_ARG(type);
+
+ // Pointer to data
+ const ACE_WSTRING_TYPE *data = value.fast_rep ();
+
+ // Size
+ size_t size = value.length () * sizeof (ACE_WSTRING_TYPE);
+
+ // Represent value as an ACE_Registry::Object
+ ACE_Registry::Object object ((void *) data,
+ static_cast<u_long> (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)
+{
+ ACE_UNUSED_ARG(type);
+
+ // Pointer to data
+ const ACE_WSTRING_TYPE *data = value.fast_rep ();
+
+ // Size
+ size_t size = value.length () * sizeof (ACE_WSTRING_TYPE);
+
+ // Represent value as an ACE_Registry::Object
+ ACE_Registry::Object object ((void *) data,
+ static_cast<u_long> (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)
+{
+ ACE_UNUSED_ARG(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_WSTRING_TYPE));
+
+ // 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)
+{
+ ACE_UNUSED_ARG(set);
+ ACE_UNUSED_ARG(pattern);
+
+ return 0;
+}
+
+
+int
+ACE_Registry_Name_Space::list_name_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_UNUSED_ARG(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_TEXT ("%p\n"), ACE_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
+{
+#if defined (ACE_HAS_DUMP)
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
diff --git a/ACE/ace/Registry_Name_Space.h b/ACE/ace/Registry_Name_Space.h
new file mode 100644
index 00000000000..b54f99dc3af
--- /dev/null
+++ b/ACE/ace/Registry_Name_Space.h
@@ -0,0 +1,140 @@
+// -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (defined (ACE_WIN32) && defined (ACE_USES_WCHAR))
+// This only works on Win32 platforms when ACE_USES_WCHAR is turned on
+
+#include "ace/Registry.h"
+#include "ace/Naming_Context.h"
+#include "ace/Name_Space.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_REGISTRY_NAME_SPACE_H */
diff --git a/ACE/ace/Remote_Name_Space.cpp b/ACE/ace/Remote_Name_Space.cpp
new file mode 100644
index 00000000000..43fb8db9b19
--- /dev/null
+++ b/ACE/ace/Remote_Name_Space.cpp
@@ -0,0 +1,380 @@
+#include "ace/Remote_Name_Space.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Log_Msg.h"
+#include "ace/SString.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ Remote_Name_Space,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_TEXT ("%p\n"), ACE_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_WCHAR_T> name_urep (name.rep ());
+ ACE_Auto_Basic_Array_Ptr<ACE_WCHAR_T> value_urep (value.rep ());
+ ACE_UINT32 name_len =
+ static_cast<ACE_UINT32> (name.length () * sizeof (ACE_WCHAR_T));
+ ACE_UINT32 value_len =
+ static_cast<ACE_UINT32> (value.length () * sizeof (ACE_WCHAR_T));
+ ACE_UINT32 type_len =
+ static_cast<ACE_UINT32> (ACE_OS::strlen (type));
+ ACE_Name_Request request (ACE_Name_Request::BIND,
+ name_urep.get (),
+ name_len,
+ value_urep.get (),
+ value_len,
+ type,
+ type_len);
+ 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_WCHAR_T> name_urep (name.rep ());
+ ACE_Auto_Basic_Array_Ptr<ACE_WCHAR_T> value_urep (value.rep ());
+ ACE_UINT32 name_len =
+ static_cast<ACE_UINT32> (name.length () * sizeof (ACE_WCHAR_T));
+ ACE_UINT32 value_len =
+ static_cast<ACE_UINT32> (value.length () * sizeof (ACE_WCHAR_T));
+ ACE_UINT32 type_len =
+ static_cast<ACE_UINT32> (ACE_OS::strlen (type));
+ ACE_Name_Request request (ACE_Name_Request::REBIND,
+ name_urep.get (),
+ name_len,
+ value_urep.get (),
+ value_len,
+ type,
+ type_len);
+ 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_WCHAR_T> name_urep (name.rep ());
+ ACE_UINT32 name_len =
+ static_cast<ACE_UINT32> (name.length () * sizeof (ACE_WCHAR_T));
+ ACE_Name_Request request (ACE_Name_Request::RESOLVE,
+ name_urep.get (),
+ name_len,
+ 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_WCHAR_T));
+ 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_WCHAR_T> name_urep (name.rep ());
+ ACE_UINT32 name_len =
+ static_cast<ACE_UINT32> (name.length () * sizeof (ACE_WCHAR_T));
+ ACE_Name_Request request (ACE_Name_Request::UNBIND,
+ name_urep.get (),
+ name_len,
+ 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_WCHAR_T> pattern_urep (pattern.rep ());
+ ACE_UINT32 pattern_len =
+ static_cast<ACE_UINT32> (pattern.length () * sizeof (ACE_WCHAR_T));
+ ACE_Name_Request request (ACE_Name_Request::LIST_NAMES,
+ pattern_urep.get (),
+ pattern_len,
+ 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_TEXT ("%p\n"),
+ ACE_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_WCHAR_T));
+ 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_WCHAR_T> pattern_urep (pattern.rep ());
+ ACE_UINT32 pattern_len =
+ static_cast<ACE_UINT32> (pattern.length () * sizeof (ACE_WCHAR_T));
+ ACE_Name_Request request (ACE_Name_Request::LIST_VALUES,
+ pattern_urep.get (),
+ pattern_len,
+ 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_TEXT ("%p\n"),
+ ACE_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_WCHAR_T));
+ 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_WCHAR_T> pattern_urep (pattern.rep ());
+ ACE_UINT32 pattern_len =
+ static_cast<ACE_UINT32> (pattern.length () * sizeof (ACE_WCHAR_T));
+ ACE_Name_Request request (ACE_Name_Request::LIST_TYPES,
+ pattern_urep.get (),
+ pattern_len,
+ 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_TEXT ("%p\n"),
+ ACE_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_WCHAR_T> pattern_urep (pattern.rep ());
+ ACE_UINT32 pattern_len =
+ static_cast<ACE_UINT32> (pattern.length () * sizeof (ACE_WCHAR_T));
+ ACE_Name_Request request (ACE_Name_Request::LIST_NAME_ENTRIES,
+ pattern_urep.get (),
+ pattern_len,
+ 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_TEXT ("%p\n"),
+ ACE_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_WCHAR_T));
+ ACE_NS_WString value (reply.value (),
+ reply.value_len () / sizeof (ACE_WCHAR_T));
+ 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_WCHAR_T> pattern_urep (pattern.rep ());
+ ACE_UINT32 pattern_len =
+ static_cast<ACE_UINT32> (pattern.length () * sizeof (ACE_WCHAR_T));
+ ACE_Name_Request request (ACE_Name_Request::LIST_VALUE_ENTRIES,
+ pattern_urep.get (),
+ pattern_len,
+ 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_TEXT ("%p\n"),
+ ACE_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_WCHAR_T));
+ ACE_NS_WString value (reply.value (),
+ reply.value_len () / sizeof (ACE_WCHAR_T));
+ 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_WCHAR_T> pattern_urep (pattern.rep ());
+ ACE_UINT32 pattern_len =
+ static_cast<ACE_UINT32> (pattern.length () * sizeof (ACE_WCHAR_T));
+ ACE_Name_Request request (ACE_Name_Request::LIST_TYPE_ENTRIES,
+ pattern_urep.get (),
+ pattern_len,
+ 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_TEXT ("%p\n"),
+ ACE_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_WCHAR_T));
+ ACE_NS_WString value (reply.value (),
+ reply.value_len () / sizeof (ACE_WCHAR_T));
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ 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));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Remote_Name_Space.h b/ACE/ace/Remote_Name_Space.h
new file mode 100644
index 00000000000..1f7e8de6555
--- /dev/null
+++ b/ACE/ace/Remote_Name_Space.h
@@ -0,0 +1,147 @@
+// -*- 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_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Name_Proxy.h"
+#include "ace/Name_Space.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_NS_WString;
+
+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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_REMOTE_NAME_SPACE_H */
diff --git a/ACE/ace/Remote_Tokens.cpp b/ACE/ace/Remote_Tokens.cpp
new file mode 100644
index 00000000000..ce60205a77a
--- /dev/null
+++ b/ACE/ace/Remote_Tokens.cpp
@@ -0,0 +1,527 @@
+// $Id$
+
+#include "ace/Remote_Tokens.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#include "ace/Singleton.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Remote_Tokens.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Remote_Tokens,
+ "$Id$")
+
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+#define ACE_TSS_CONNECTION_MUTEX ACE_Thread_Mutex
+#else
+#define ACE_TSS_CONNECTION_MUTEX ACE_Null_Mutex
+#endif /* ACE_MT_SAFE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Make a typedef to simplify access to the Singleton below.
+typedef ACE_Singleton<ACE_TSS_Connection, ACE_TSS_CONNECTION_MUTEX> ACE_Token_Connections;
+
+// Initialize the statics from ACE_TSS_Connection;
+ACE_INET_Addr ACE_TSS_Connection::server_address_;
+
+// ************************************************************
+
+void
+ACE_TSS_Connection::set_server_address (const ACE_INET_Addr &server_address)
+{
+ ACE_TRACE ("ACE_TSS_Connection::set_server_address");
+ server_address_ = server_address;
+}
+
+// Necessary to make some compilers work...
+ACE_TSS_Connection::ACE_TSS_Connection (void)
+{
+ ACE_TRACE ("ACE_TSS_Connection::ACE_TSS_Connection");
+}
+
+ACE_TSS_Connection::~ACE_TSS_Connection (void)
+{
+ ACE_TRACE ("ACE_TSS_Connection::~ACE_TSS_Connection");
+}
+
+ACE_SOCK_Stream *
+ACE_TSS_Connection::get_connection (void)
+{
+ return ACE_TSS<ACE_SOCK_Stream>::operator-> ();
+}
+
+ACE_SOCK_Stream *
+ACE_TSS_Connection::make_TSS_TYPE (void) const
+{
+ ACE_TRACE ("ACE_TSS_Connection::make_TSS_TYPE");
+
+ ACE_SOCK_Connector connector;
+ ACE_SOCK_Stream *stream = 0;
+
+ ACE_NEW_RETURN (stream,
+ ACE_SOCK_Stream,
+ 0);
+
+ if (connector.connect (*stream, server_address_) == -1)
+ {
+ delete stream;
+ errno = ECONNREFUSED;
+ return 0;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_TSS_Connection new connection\n")));
+ return stream;
+}
+
+ACE_TSS_Connection::operator ACE_SOCK_Stream *(void)
+{
+ return this->get_connection ();
+}
+
+void
+ACE_TSS_Connection::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TSS_Connection::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_TSS_Connection::dump:\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("server_address_\n")));
+ server_address_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_TSS<ACE_SOCK_Stream>::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Remote_Token_Proxy::ACE_Remote_Token_Proxy (void)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::ACE_Remote_Token_Proxy");
+}
+
+ACE_Remote_Token_Proxy::~ACE_Remote_Token_Proxy (void)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::~ACE_Remote_Token_Proxy");
+}
+
+int
+ACE_Remote_Token_Proxy::open (const ACE_TCHAR *name,
+ int ignore_deadlock,
+ int debug)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::open");
+ ignore_shadow_deadlock_ = ignore_deadlock;
+ return ACE_Token_Proxy::open (name, 0, debug);
+}
+
+void
+ACE_Remote_Token_Proxy::set_server_address (const ACE_INET_Addr &server_address)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::set_server_address");
+ ACE_Token_Connections::instance ()->set_server_address (server_address);
+}
+
+int
+ACE_Remote_Token_Proxy::initiate_connection (void)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::initiate_connection");
+ if (token_ == 0)
+ {
+ errno = ENOENT;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE_Remote_Token_Proxy not open.\n")), -1);
+ }
+
+ ACE_SOCK_Stream *peer = ACE_Token_Connections::instance ()->get_connection ();
+ return peer == 0 ? 0 : 1;
+}
+
+// Do the work of sending a request and getting a reply.
+
+int
+ACE_Remote_Token_Proxy::request_reply (ACE_Token_Request &request,
+ ACE_Synch_Options &)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::request_reply");
+ void *buffer;
+ ssize_t length;
+
+ if ((length = request.encode (buffer)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("encode failed")), -1);
+
+ ACE_SOCK_Stream *peer = ACE_Token_Connections::instance ()->get_connection ();
+
+ if (peer == 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "BIG PROBLEMS with get_connection"), -1);
+
+ // Transmit request via a blocking send.
+
+ if (peer->send_n (buffer, length) != length)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("send_n failed")), -1);
+ else
+ {
+ ACE_Token_Reply reply;
+
+ // Receive reply via blocking read.
+
+ if (peer->recv (&reply, sizeof reply) != sizeof reply)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("recv failed")), -1);
+
+ if (reply.decode () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("decode failed")), -1);
+
+ errno = int (reply.errnum ());
+ if (errno != 0)
+ return -1;
+ else
+ return 0;
+ }
+}
+
+int
+ACE_Remote_Token_Proxy::acquire (int notify,
+ void (*sleep_hook)(void *),
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::acquire");
+
+ // First grab the local shadow mutex.
+ if (ACE_Token_Proxy::acquire (notify,
+ sleep_hook,
+ ACE_Synch_Options::asynch) == -1)
+ {
+ // Acquire failed, deal with it...
+ switch (errno)
+ {
+ case EWOULDBLOCK :
+ // Whoah, we detected wouldblock via the shadow mutex!
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) shadow: acquire will block, owner is %s\n"),
+ this->token_->owner_id ()));
+ // No error, but would block,
+ break;
+
+ case EDEADLK :
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) shadow: deadlock detected\n")));
+
+ if (ignore_shadow_deadlock_)
+ break;
+ else
+ {
+ errno = EDEADLK;
+ ACE_RETURN (-1);
+ }
+
+ default :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%t) %p shadow acquire failed\n"),
+ ACE_TEXT ("ACE_Remote_Token_Proxy")),
+ -1);
+ }
+ }
+
+ ACE_Token_Request request (token_->type (),
+ this->type (),
+ ACE_Token_Request::ACQUIRE,
+ this->name (),
+ this->client_id (),
+ options);
+
+ request.notify (notify);
+
+ int result = this->request_reply (request, options);
+
+ if (result == -1)
+ {
+ // Update the local shadow copy.
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("error on remote acquire, releasing shadow mutex.\n")));
+ ACE_Token_Proxy::release ();
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) acquired %s remotely.\n"), this->name ()));
+ // Our shadow call may have failed. However, it's still a race
+ // to the remote server. If we beat the client which holds the
+ // local token, we need to fix things locally to reflect the
+ // actual ownership. All that should happen is that our waiter
+ // is moved to the front of the waiter list.
+ token_->make_owner (waiter_);
+ }
+
+ return result;
+}
+
+int
+ACE_Remote_Token_Proxy::tryacquire (void (*sleep_hook)(void *))
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::tryacquire");
+
+ // If we can detect locally that the tryacquire will fail, there is
+ // no need to go remote.
+ if (ACE_Token_Proxy::tryacquire (sleep_hook) == -1)
+ {
+ if (debug_)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("shadow try acquire failed\n")));
+ }
+
+ return -1;
+ }
+
+ ACE_Token_Request request (token_->type (),
+ this->type (),
+ ACE_Token_Request::TRY_ACQUIRE,
+ this->name (),
+ this->client_id (),
+ ACE_Synch_Options::synch);
+
+ return this->request_reply (request,
+ ACE_Synch_Options::synch);
+}
+
+int
+ACE_Remote_Token_Proxy::renew (int requeue_position,
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::renew");
+
+ if (ACE_Token_Proxy::renew (requeue_position,
+ ACE_Synch_Options::asynch) == -1)
+ {
+ // Check for error.
+ if (errno != EWOULDBLOCK)
+ return -1;
+ else if (debug_)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) shadow: renew would block. owner %s.\n"),
+ this->token_->owner_id ()));
+ }
+
+ ACE_Token_Request request (token_->type (),
+ this->type (),
+ ACE_Token_Request::RENEW,
+ this->name (),
+ this->client_id (),
+ options);
+
+ request.requeue_position (requeue_position);
+
+ int result = this->request_reply (request, options);
+
+ if (result == -1)
+ {
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ ACE_Token_Proxy::release ();
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p error on remote renew, releasing shadow mutex.\n"),
+ ACE_TEXT ("ACE_Remote_Token_Proxy")), -1);
+ }
+ else
+ {
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) renewed %s remotely.\n"), this->name ()));
+ // Make sure that the local shadow reflects our new ownership.
+ token_->make_owner (waiter_);
+ return result;
+ }
+}
+
+int
+ACE_Remote_Token_Proxy::release (ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::release");
+
+ ACE_Token_Request request (token_->type (),
+ this->type (),
+ ACE_Token_Request::RELEASE,
+ this->name (),
+ this->client_id (),
+ options);
+
+ int result = this->request_reply (request, options);
+ if (result == 0)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) released %s remotely.\n"), this->name ()));
+
+ // whether success or failure, we're going to release the shadow.
+ // If race conditions exist such that we are no longer the owner,
+ // this release will perform a remove.
+ if (ACE_Token_Proxy::release () == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) shadow: release failed\n")));
+
+ return result;
+}
+
+int
+ACE_Remote_Token_Proxy::remove (ACE_Synch_Options &)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::remove");
+ return 0;
+}
+
+void
+ACE_Remote_Token_Proxy::token_acquired (ACE_TPQ_Entry *)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::token_acquired");
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) %s shadow token %s acquired\n"),
+ this->client_id (),
+ this->name ()));
+ // ACE_Token_Proxy::token_acquired (vp);
+}
+
+const ACE_TCHAR*
+ACE_Remote_Token_Proxy::owner_id (void)
+{
+ ACE_TRACE ("ACE_Remote_Token_Proxy::owner_id");
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("owner_id called\n")));
+ // @@ special operation
+ return 0;
+}
+
+void
+ACE_Remote_Token_Proxy::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Remote_Token_Proxy::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Tokens::dump:\n")
+ ACE_TEXT (" ignore_shadow_deadlock_ = %d\n"),
+ ignore_shadow_deadlock_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_Token_Proxy::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Token_Proxy *
+ACE_Remote_Mutex::clone (void) const
+{
+ ACE_Token_Proxy *temp;
+ ACE_NEW_RETURN (temp,
+ ACE_Remote_Mutex (this->name (),
+ ignore_deadlock_,
+ debug_),
+ 0);
+ return temp;
+}
+
+ACE_Tokens *
+ACE_Remote_Mutex::create_token (const ACE_TCHAR *name)
+{
+ ACE_Tokens *temp;
+ ACE_NEW_RETURN (temp,
+ ACE_Mutex_Token (name),
+ 0);
+ return temp;
+}
+
+void
+ACE_Remote_Mutex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Remote_Mutex::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Remote_Mutex::dump:\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_Remote_Token_Proxy::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Tokens *
+ACE_Remote_RLock::create_token (const ACE_TCHAR *name)
+{
+ ACE_Tokens *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_RW_Token (name),
+ 0);
+ return temp;
+}
+
+int
+ACE_Remote_RLock::type (void) const
+{
+ return ACE_RW_Token::READER;
+}
+
+ACE_Token_Proxy *
+ACE_Remote_RLock::clone (void) const
+{
+ ACE_Token_Proxy *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_Remote_RLock (this->name (),
+ ignore_deadlock_,
+ debug_),
+ 0);
+ return temp;
+}
+
+void
+ACE_Remote_RLock::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Remote_RLock::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Remote_RLock::dump:\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_Remote_Token_Proxy::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+
+ACE_Tokens *
+ACE_Remote_WLock::create_token (const ACE_TCHAR *name)
+{
+ ACE_Tokens *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_RW_Token (name),
+ 0);
+ return temp;
+}
+
+int
+ACE_Remote_WLock::type (void) const
+{
+ return ACE_RW_Token::WRITER;
+}
+
+ACE_Token_Proxy *
+ACE_Remote_WLock::clone (void) const
+{
+ ACE_Token_Proxy *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_Remote_WLock (this->name (),
+ ignore_deadlock_,
+ debug_),
+ 0);
+ return temp;
+}
+
+void
+ACE_Remote_WLock::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Remote_WLock::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Remote_WLock::dump:\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_Remote_Token_Proxy::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Remote_Tokens.h b/ACE/ace/Remote_Tokens.h
new file mode 100644
index 00000000000..288d0ca454f
--- /dev/null
+++ b/ACE/ace/Remote_Tokens.h
@@ -0,0 +1,322 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Remote_Tokens.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt (schmidt@cs.wustl.edu)
+ * @author Tim Harrison (harrison@cs.wustl.edu)
+ */
+//=============================================================================
+
+#ifndef ACE_REMOTE_MUTEX_H
+#define ACE_REMOTE_MUTEX_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/Synch_Options.h"
+#include "ace/Local_Tokens.h"
+#include "ace/Token_Request_Reply.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Remote_Token_Proxy
+ *
+ * @brief Proxy for acquiring, renewing, and releasing a distributed
+ * synchronization token.
+ *
+ * The Remote_Token_Proxy class implements the mechanisms for
+ * distributed token operations. It is similar to the
+ * ACE_Token_Proxy.
+ * = BUGS
+ * Distributed sleep_hooks have not been implemented. <owner_id>
+ * is not implemented.
+ */
+class ACE_Export ACE_Remote_Token_Proxy : public ACE_Token_Proxy
+{
+public:
+ /// Null construction.
+ ACE_Remote_Token_Proxy (void);
+
+ /// Death.
+ virtual ~ACE_Remote_Token_Proxy (void);
+
+ /**
+ * Same as Token_Proxy. @a name is the string uniquely identifying
+ * the token. <ignore_deadlock> can be 1 to disable deadlock
+ * notifications. <debug> prints debug messages.
+ */
+ int open (const ACE_TCHAR *name,
+ int ignore_deadlock = 0,
+ int debug = 0);
+
+
+ /**
+ * Open a connection with the token server. This only need be used
+ * when the user wishes to explicitly open a connection to check if
+ * the server exists. Connections are stored in the
+ * ACE_Token_Connections singleton as thread-specific data. That
+ * is, every thread has only one connection that is used for all
+ * remote tokens.
+ */
+ int initiate_connection (void);
+
+ /**
+ * Acquire the distributed token. If notify is specified and the
+ * token is already held, the owner is notified. options contains
+ * the timeout value for the acquire call. The timer is kept at the
+ * token server. Asynchronous operations are not supported.
+ * Returns 0 on success, -1 on failure with @c errno == problem.
+ */
+ virtual int acquire (int notify = 0,
+ void (*sleep_hook)(void *) = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::synch);
+
+ /**
+ * Try to acquire the distributed token. If the token is already
+ * held, the call returns without queueing the caller as a waiter.
+ * Returns 0 on success (the token was acquired), and -1 with
+ * EWOULDBLOCK if the token was already held.
+ */
+ virtual int tryacquire (void (*sleep_hook)(void *) = 0);
+
+ /**
+ * Renew the token by offering to release it if there are any other
+ * waiters, otherwise get the token back immediately. This renew
+ * has the same semantics as ACE_Local_Mutex release. It is
+ * semantically equivalent to <release> followed by <acquire>, but
+ * it is faster. options contains the timeout value used if renew
+ * blocks. As with acquire, the timer is maintained at the token
+ * server. If there are waiters and requeue_position == -1, the
+ * caller is queued at the rear of the waiter list. Otherwise,
+ * requeue_position specifies the number of waiters to "let by"
+ * before reacquiring the token (effectively, the position in the
+ * waiter list.)
+ */
+ virtual int renew (int requeue_position = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::synch);
+
+ /**
+ * Release the distributed token. Similar to ACE_Local_Mutex, if the
+ * caller is not the owner, it is removed from the waiter list (if
+ * applicable.) Returns 0 on success, -1 on failure with @c errno ==
+ * problem.
+ */
+ virtual int release (ACE_Synch_Options &options =
+ ACE_Synch_Options::synch);
+
+ /// Become interface compliant for ACE_Guard<>. This has no
+ /// functionality.
+ virtual int remove (ACE_Synch_Options &options =
+ ACE_Synch_Options::synch);
+
+ /// Override the default to do nothing.
+ virtual void token_acquired (ACE_TPQ_Entry *);
+
+ /// The client id of the current token holder
+ virtual const ACE_TCHAR* owner_id (void);
+
+ /**
+ * Sets the server address for all instances of ACE_Remote_Token_Proxy
+ * If this isn't called, the environment variable TOKEN_SERVER is
+ * checked for the server address. If that is not specified, all
+ * ACE_Remote_** operations will fail.
+ */
+ static void set_server_address (const ACE_INET_Addr &server_address);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+protected:
+
+ /// If shadows report deadlock, go remote anyway
+ int ignore_shadow_deadlock_;
+
+ /// Perform the request and wait for the reply.
+ int request_reply (ACE_Token_Request &request,
+ ACE_Synch_Options &options);
+};
+
+/**
+ * @class ACE_Remote_Mutex
+ *
+ * @brief Proxy for acquiring, renewing, and releasing a distributed
+ * mutex.
+ *
+ * This is the remote equivalent to ACE_Local_Mutex. The
+ * Remote_Mutex class offers methods for acquiring, renewing, and
+ * releasing a distributed synchronization mutex. Similar to
+ * ACE_Local_Mutex, ACE_Remote_Token_Proxy offers recursive
+ * acquisition, FIFO waiter ordering, and deadlock detection. It
+ * depends on the Token Server for its distributed synchronization
+ * semantics.
+ */
+class ACE_Export ACE_Remote_Mutex : public ACE_Remote_Token_Proxy
+{
+public:
+ /// Null creation. Remote_Token_Proxy::open must be called.
+ ACE_Remote_Mutex (void);
+
+ /// Calls Remote_Token_Proxy::open for you.
+ ACE_Remote_Mutex (const ACE_TCHAR *token_name,
+ int ignore_deadlock = 0,
+ int debug = 0);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Return deep copy.
+ virtual ACE_Token_Proxy *clone (void) const;
+
+protected:
+ /// Make the correct type of ACE_Tokens.
+ /// This is called by the ACE_Token_Manager.
+ virtual ACE_Tokens *create_token (const ACE_TCHAR *name);
+};
+
+/**
+ * @class ACE_Remote_RLock
+ *
+ * @brief Proxy for acquiring, renewing, and releasing a distributed
+ * readers lock.
+ *
+ * This is the remote equivalent to ACE_Local_RLock. Multiple
+ * readers can hold the lock simultaneously when no writers have
+ * the lock. Alternatively, when a writer holds the lock, no other
+ * participants (readers or writers) may hold the lock.
+ * ACE_Remote_RLock depends on the ACE Token Server for its
+ * distributed synchronization semantics.
+ */
+class ACE_Export ACE_Remote_RLock : public ACE_Remote_Token_Proxy
+{
+public:
+ ACE_Remote_RLock (void);
+
+ ACE_Remote_RLock (const ACE_TCHAR *token_name,
+ int ignore_deadlock = 0,
+ int debug = 0);
+
+ ACE_Remote_RLock (const ACE_Remote_RLock &mutex);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Returns ACE_RW_Token::RLOCK;
+ virtual int type (void) const;
+
+ /// Return deep copy.
+ virtual ACE_Token_Proxy *clone (void) const;
+
+protected:
+ /// Make the correct type of ACE_Tokens. This is called by the Token
+ /// Manager.
+ virtual ACE_Tokens *create_token (const ACE_TCHAR *name);
+};
+
+/**
+ * @class ACE_Remote_WLock
+ *
+ * @brief Proxy for acquiring, renewing, and releasing a distributed
+ * writers lock.
+ *
+ * Shields applications from details of interacting with the
+ * ACE_Token_Server. The token_name_ is just the string that the
+ * Token Server uses to identify the token. The client_id_ (also
+ * used by the Token Server,) identifies the owner of the token and
+ * is used for deadlock detection.
+ */
+class ACE_Export ACE_Remote_WLock : public ACE_Remote_Token_Proxy
+{
+public:
+ ACE_Remote_WLock (void);
+
+ ACE_Remote_WLock (const ACE_TCHAR *token_name,
+ int ignore_deadlock = 0,
+ int debug = 0);
+
+ ACE_Remote_WLock (const ACE_Remote_WLock &mutex);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Returns ACE_RW_Token::WLOCK;
+ virtual int type (void) const;
+
+ /// Return deep copy.
+ virtual ACE_Token_Proxy *clone (void) const;
+
+protected:
+ /// Make the correct type of ACE_Tokens. This is called by the Token
+ /// Manager.
+ virtual ACE_Tokens *create_token (const ACE_TCHAR *name);
+};
+
+/**
+ * @class ACE_TSS_Connection
+ *
+ * @brief Class for providing a connection per thread.
+ *
+ * ACE_TSS_Connection provides a single access point for all
+ * threads to access thread-specific connections. This prevents
+ * resource-sharing problems such as thread serialization.
+ */
+class ACE_Export ACE_TSS_Connection : public ACE_TSS<ACE_SOCK_Stream>
+{
+public:
+ // Necessary to make some compilers work...
+ ACE_TSS_Connection (void);
+ ~ACE_TSS_Connection (void);
+
+ /// Retrieve the thread's connection
+ ACE_SOCK_Stream *get_connection (void);
+
+ /// Factory Method that creates a new SOCK Stream.
+ virtual ACE_SOCK_Stream *make_TSS_TYPE (void) const;
+
+ /// Inheritence and operator overloading don't mix. Redefine this
+ /// from ACE_TSS so that we can use it.
+ operator ACE_SOCK_Stream *(void);
+
+ /// Set the server address.
+ static void set_server_address (const ACE_INET_Addr &server_address);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+protected:
+ /// The address of the Token Server used by all instances of
+ /// Token_Proxy.
+ static ACE_INET_Addr server_address_;
+
+private:
+ /// Private: should not be used
+ ACE_TSS_Connection (const ACE_TSS_Connection &);
+ void operator= (const ACE_TSS_Connection &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Remote_Tokens.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_REMOTE_TOKEN_H */
diff --git a/ACE/ace/Remote_Tokens.inl b/ACE/ace/Remote_Tokens.inl
new file mode 100644
index 00000000000..50487075225
--- /dev/null
+++ b/ACE/ace/Remote_Tokens.inl
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Remote_Mutex::ACE_Remote_Mutex (void)
+{
+ ACE_TRACE ("ACE_Remote_Mutex::ACE_Remote_Mutex");
+}
+
+ACE_INLINE
+ACE_Remote_Mutex::ACE_Remote_Mutex (const ACE_TCHAR *token_name,
+ int ignore_deadlock,
+ int debug)
+{
+ ACE_TRACE ("ACE_Remote_Mutex::ACE_Remote_Mutex");
+ this->open (token_name, ignore_deadlock, debug);
+}
+
+// ************************************************************
+
+ACE_INLINE
+ACE_Remote_RLock::ACE_Remote_RLock (const ACE_TCHAR *token_name,
+ int ignore_deadlock,
+ int debug)
+{
+ ACE_TRACE ("ACE_Remote_RLock::ACE_Remote_RLock");
+ this->open (token_name, ignore_deadlock, debug);
+}
+
+// ************************************************************
+
+ACE_INLINE
+ACE_Remote_WLock::ACE_Remote_WLock (const ACE_TCHAR *token_name,
+ int ignore_deadlock,
+ int debug)
+{
+ ACE_TRACE ("ACE_Remote_WLock::ACE_Remote_WLock");
+ this->open (token_name, ignore_deadlock, debug);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Reverse_Lock_T.cpp b/ACE/ace/Reverse_Lock_T.cpp
new file mode 100644
index 00000000000..348c81da62a
--- /dev/null
+++ b/ACE/ace/Reverse_Lock_T.cpp
@@ -0,0 +1,93 @@
+// $Id$
+
+#ifndef ACE_REVERSE_LOCK_T_CPP
+#define ACE_REVERSE_LOCK_T_CPP
+
+#include "ace/Reverse_Lock_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Reverse_Lock_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_LOCKING_MECHANISM>
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::~ACE_Reverse_Lock (void)
+{
+}
+
+// Explicitly destroy the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::remove (void)
+{
+ return this->lock_.remove ();
+}
+
+// Release the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::acquire (void)
+{
+ return this->lock_.release ();
+}
+
+// Release the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::tryacquire (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+// Acquire the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::release (void)
+{
+ if (this->acquire_method_ == ACE_Acquire_Method::ACE_READ)
+ return this->lock_.acquire_read ();
+ else if (this->acquire_method_ == ACE_Acquire_Method::ACE_WRITE)
+ return this->lock_.acquire_write ();
+ else
+ return this->lock_.acquire ();
+}
+
+// Release the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::acquire_read (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+// Release the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::acquire_write (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+// Release the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::tryacquire_read (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+// Release the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::tryacquire_write (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+// Release the lock.
+template <class ACE_LOCKING_MECHANISM> int
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::tryacquire_write_upgrade (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_REVERSE_LOCK_T_CPP */
diff --git a/ACE/ace/Reverse_Lock_T.h b/ACE/ace/Reverse_Lock_T.h
new file mode 100644
index 00000000000..98b39ef561e
--- /dev/null
+++ b/ACE/ace/Reverse_Lock_T.h
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Reverse_Lock_T.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_REVERSE_LOCK_T_H
+#define ACE_REVERSE_LOCK_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Lock.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @namespace ACE_Acquire_Method
+ *
+ * @brief An enum namespace.
+ *
+ * These enums should have been inside the reverse lock class, but
+ * some lame compilers cannot handle enums inside template classes.
+ *
+ * The METHOD_TYPE is used to indicate which acquire() method will be
+ * called on the real lock when the release() method is called on the
+ * reverse lock. REGULAR indicated the acquire() method, READ
+ * indicates the acquire_read() method, and WRITE indicates the
+ * acquire_write() method. Note that the try_*() methods are not
+ * represented here because we have to make sure that the release()
+ * method on the reverse lock acquires a lock on the real lock.
+ **/
+namespace ACE_Acquire_Method
+{
+ enum METHOD_TYPE
+ {
+ ACE_REGULAR,
+ ACE_READ,
+ ACE_WRITE
+ };
+}
+
+/**
+ * @class ACE_Reverse_Lock
+ *
+ * @brief A reverse (or anti) lock.
+ *
+ * This is an interesting adapter class that changes a lock into
+ * a reverse lock, i.e., <acquire> on this class calls <release>
+ * on the lock, and <release> on this class calls <acquire> on
+ * the lock.
+ * One motivation for this class is when we temporarily want to
+ * release a lock (which we have already acquired) but then
+ * reacquire it soon after. An alternative design would be to
+ * add a Anti_Guard or Reverse_Guard class which would <release>
+ * on construction and <acquire> destruction. However, there
+ * are *many* varieties of the Guard class and this design
+ * choice would lead to at least 6 new classes. One new
+ * ACE_Reverse_Lock class seemed more reasonable.
+ */
+template <class ACE_LOCKING_MECHANISM>
+class ACE_Reverse_Lock : public ACE_Lock
+{
+public:
+
+ typedef ACE_LOCKING_MECHANISM ACE_LOCK;
+
+ // = Initialization/Finalization methods.
+
+ /// Constructor. All locking requests will be forwarded to <lock>.
+ ACE_Reverse_Lock (ACE_LOCKING_MECHANISM &lock,
+ ACE_Acquire_Method::METHOD_TYPE acquire_method = ACE_Acquire_Method::ACE_REGULAR);
+
+ /// Destructor. If <lock_> was not passed in by the user, it will be
+ /// deleted.
+ virtual ~ACE_Reverse_Lock (void);
+
+ // = Lock accessors.
+ /// Release the lock.
+ virtual int acquire (void);
+
+ /// Release the lock.
+ virtual int tryacquire (void);
+
+ /// Acquire the lock.
+ virtual int release (void);
+
+ /// Release the lock.
+ virtual int acquire_read (void);
+
+ /// Release the lock.
+ virtual int acquire_write (void);
+
+ /// Release the lock.
+ virtual int tryacquire_read (void);
+
+ /// Release the lock.
+ virtual int tryacquire_write (void);
+
+ /// Release the lock.
+ virtual int tryacquire_write_upgrade (void);
+
+ /// Explicitly destroy the lock.
+ virtual int remove (void);
+
+private:
+ /// The concrete locking mechanism that all the methods delegate to.
+ ACE_LOCKING_MECHANISM &lock_;
+
+ /// This indicates what kind of acquire method will be called.
+ ACE_Acquire_Method::METHOD_TYPE acquire_method_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Reverse_Lock_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Reverse_Lock_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Reverse_Lock_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_REVERSE_LOCK_T_H */
diff --git a/ACE/ace/Reverse_Lock_T.inl b/ACE/ace/Reverse_Lock_T.inl
new file mode 100644
index 00000000000..0f8598ffd23
--- /dev/null
+++ b/ACE/ace/Reverse_Lock_T.inl
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/config-all.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_LOCKING_MECHANISM> ACE_INLINE
+ACE_Reverse_Lock<ACE_LOCKING_MECHANISM>::ACE_Reverse_Lock (
+ ACE_LOCKING_MECHANISM &lock,
+ ACE_Acquire_Method::METHOD_TYPE acquire_method)
+ : lock_ (lock),
+ acquire_method_ (acquire_method)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Rtems_init.c b/ACE/ace/Rtems_init.c
new file mode 100644
index 00000000000..5015e2eec2a
--- /dev/null
+++ b/ACE/ace/Rtems_init.c
@@ -0,0 +1,219 @@
+/*
+ * $Id$
+ */
+
+#if defined (ACE_HAS_RTEMS)
+
+#define RTEMS_BSP_NETWORK_DRIVER_NAME "ne1"
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_ne_driver_attach
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 256
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 100
+#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 300
+#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 300
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 100
+#define CONFIGURE_MAXIMUM_POSIX_TIMERS 100
+#define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 10
+#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 300
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+#define CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT Init
+#define CONFIGURE_MEMORY_FOR_POSIX (10*1024)
+#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (10*1024)
+
+#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_EXECUTIVE_RAM_SIZE (512*1024)
+
+#define CONFIGURE_MICROSECONDS_PER_TICK 10000
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES 100
+#define CONFIGURE_MAXIMUM_TASKS 100
+#define CONFIGURE_INIT_TASK_PRIORITY 120
+#define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \
+ RTEMS_NO_TIMESLICE | \
+ RTEMS_NO_ASR | \
+ RTEMS_INTERRUPT_LEVEL(0))
+
+#include <bsp.h>
+
+char *rtems_progname;
+
+#define CONFIGURE_INIT
+
+rtems_task Init (rtems_task_argument argument);
+
+#include <confdefs.h>
+
+#include <stdio.h>
+
+#if !defined (ACE_LACKS_NETWORKING)
+
+#include <rtems/rtems_bsdnet.h>
+
+/*
+ * Network configuration
+ *
+ ************************************************************
+ * EDIT THIS FILE TO REFLECT YOUR NETWORK CONFIGURATION *
+ * BEFORE RUNNING ANY RTEMS PROGRAMS WHICH USE THE NETWORK! *
+ ************************************************************
+ */
+
+#ifndef _RTEMS_NETWORKCONFIG_H_
+#define _RTEMS_NETWORKCONFIG_H_
+
+#ifndef RTEMS_BSP_NETWORK_DRIVER_NAME
+#warning "RTEMS_BSP_NETWORK_DRIVER_NAME is not defined"
+#define RTEMS_BSP_NETWORK_DRIVER_NAME "no_network1"
+#endif
+
+#ifndef RTEMS_BSP_NETWORK_DRIVER_ATTACH
+#warning "RTEMS_BSP_NETWORK_DRIVER_ATTACH is not defined"
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH 0
+#endif
+
+/* #define RTEMS_USE_BOOTP */
+
+#include <bsp.h>
+
+/*
+ * Define RTEMS_SET_ETHERNET_ADDRESS if you want to specify the
+ * Ethernet address here. If RTEMS_SET_ETHERNET_ADDRESS is not
+ * defined the driver will choose an address.
+ */
+#define RTEMS_SET_ETHERNET_ADDRESS
+#if (defined (RTEMS_SET_ETHERNET_ADDRESS))
+static char ethernet_address[6] = { 0x00, 0x80, 0x7F, 0x22, 0x61, 0x77 };
+
+#endif
+
+#define RTEMS_USE_LOOPBACK
+
+#ifdef RTEMS_USE_LOOPBACK
+/*
+ * Loopback interface
+ */
+int rtems_bsdnet_loopattach(struct rtems_bsdnet_ifconfig *, int);
+
+#ifdef RTEMS_USE_LOOPBACK_ONLY
+static struct rtems_bsdnet_ifconfig netdriver_config = {
+#else
+static struct rtems_bsdnet_ifconfig loopback_config = {
+#endif
+ "lo0", /* name */
+ rtems_bsdnet_loopattach, /* attach function */
+ 0, /* link to next interface */
+ "127.0.0.1", /* IP address */
+ "255.0.0.0", /* IP net mask */
+};
+#endif
+
+/*
+ * Default network interface
+ */
+#ifndef RTEMS_USE_LOOPBACK_ONLY
+static struct rtems_bsdnet_ifconfig netdriver_config = {
+ RTEMS_BSP_NETWORK_DRIVER_NAME, /* name */
+ RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* attach function */
+
+#ifdef RTEMS_USE_LOOPBACK
+ &loopback_config, /* link to next interface */
+#else
+ 0, /* No more interfaces */
+#endif
+
+#if (defined (RTEMS_USE_BOOTP))
+ 0, /* BOOTP supplies IP address */
+ 0, /* BOOTP supplies IP net mask */
+#else
+ "XXX.YYY.ZZZ.XYZ", /* IP address */
+ "255.255.255.0", /* IP net mask */
+#endif /* !RTEMS_USE_BOOTP */
+
+#if (defined (RTEMS_SET_ETHERNET_ADDRESS))
+ ethernet_address, /* Ethernet hardware address */
+#else
+ 0, /* Driver supplies hardware address */
+#endif
+ 0 /* Use default driver parameters */
+};
+#endif
+
+/*
+ * Network configuration
+ */
+struct rtems_bsdnet_config rtems_bsdnet_config = {
+ &netdriver_config,
+
+#if (defined (RTEMS_USE_BOOTP))
+ rtems_bsdnet_do_bootp,
+#else
+ 0,
+#endif
+
+ 0, /* Default network task priority */
+ 0, /* Default mbuf capacity */
+ 0, /* Default mbuf cluster capacity */
+
+#if (!defined (RTEMS_USE_BOOTP))
+ "rtems_host", /* Host name */
+ "nodomain.com", /* Domain name */
+ "XXX.YYY.ZZZ.1", /* Gateway */
+ "XXX.YYY.ZZZ.1", /* Log host */
+ {"XXX.YYY.ZZZ.1" }, /* Name server(s) */
+ {"XXX.YYY.ZZZ.1" }, /* NTP server(s) */
+
+ /*
+ * A real example -- DO NOT USE THIS YOURSELF!!!
+ */
+
+#if 0
+ "dy4", /* Host name */
+ "NOT_oarcorp.com", /* Domain name */
+ "192.168.1.2", /* Gateway */
+ "192.168.1.2", /* Log host */
+ {"192.168.1.2" }, /* Name server(s) */
+ {"192.168.1.2" }, /* NTP server(s) */
+#endif
+#endif /* !RTEMS_USE_BOOTP */
+
+};
+
+/*
+ * For TFTP test application
+ */
+#if (defined (RTEMS_USE_BOOTP))
+#define RTEMS_TFTP_TEST_HOST_NAME "BOOTP_HOST"
+#define RTEMS_TFTP_TEST_FILE_NAME "BOOTP_FILE"
+#else
+#define RTEMS_TFTP_TEST_HOST_NAME "XXX.YYY.ZZZ.XYZ"
+#define RTEMS_TFTP_TEST_FILE_NAME "tftptest"
+#endif
+
+#endif /* _RTEMS_NETWORKCONFIG_H_ */
+
+#endif /* ACE_LACKS_NETWORKING */
+
+extern int main (int, char *[]);
+
+/*
+ * RTEMS Startup Task
+ */
+rtems_task
+Init (rtems_task_argument not_used)
+{
+ int retval = 0;
+#if !defined (ACE_LACKS_NETWORKING)
+ retval = rtems_bsdnet_initialize_network ();
+#endif /* ACE_LACKS_NETWORKING */
+ if (retval == 0)
+ {
+ retval = main (0, 0);
+ }
+}
+
+#elif !defined (__GNUC__) && !defined (__INTEL_COMPILER)
+/* Make compilers stop complaining about an empty translation unit */
+static int shut_up_compiler = 0;
+#endif /* ACE_HAS_RTEMS */
diff --git a/ACE/ace/SOCK.cpp b/ACE/ace/SOCK.cpp
new file mode 100644
index 00000000000..fdeb4569d50
--- /dev/null
+++ b/ACE/ace/SOCK.cpp
@@ -0,0 +1,185 @@
+// $Id$
+
+#include "ace/SOCK.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK)
+
+void
+ACE_SOCK::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK::dump");
+#endif /* ACE_HAS_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 = 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 = 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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK::ACE_SOCK")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK.h b/ACE/ace/SOCK.h
new file mode 100644
index 00000000000..d1c67cd87ff
--- /dev/null
+++ b/ACE/ace/SOCK.h
@@ -0,0 +1,138 @@
+/* -*- 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_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Addr.h"
+#include "ace/IPC_SAP.h"
+#include "ace/OS_NS_stropts.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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:
+
+ /// 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 the socket.
+ * This method also sets the object's handle value to ACE_INVALID_HANDLE.
+ *
+ * @return The result of closing the socket; 0 if the handle value
+ * was already ACE_INVALID_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 @c socket system call (no QoS).
+ int open (int type,
+ int protocol_family,
+ int protocol,
+ int reuse_addr);
+
+ /// Wrapper around the QoS-enabled @c 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 @c 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 @c 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);
+
+ /// Protected destructor.
+ /**
+ * Not a virtual destructor. Protected destructor to prevent
+ * operator delete() from being called through a base class ACE_SOCK
+ * pointer/reference.
+ */
+ ~ACE_SOCK (void);
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_H */
diff --git a/ACE/ace/SOCK.inl b/ACE/ace/SOCK.inl
new file mode 100644
index 00000000000..c57fa36dfec
--- /dev/null
+++ b/ACE/ace/SOCK.inl
@@ -0,0 +1,39 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SOCK::~ACE_SOCK (void)
+{
+ // ACE_TRACE ("ACE_SOCK::~ACE_SOCK");
+}
+
+ACE_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.
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Acceptor.cpp b/ACE/ace/SOCK_Acceptor.cpp
new file mode 100644
index 00000000000..70cc5bcf449
--- /dev/null
+++ b/ACE/ace/SOCK_Acceptor.cpp
@@ -0,0 +1,406 @@
+// $Id$
+
+#include "ace/SOCK_Acceptor.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_Errno.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/os_include/os_fcntl.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+#if !defined (ACE_HAS_WINCE)
+#include "ace/OS_QoS.h"
+#endif // ACE_HAS_WINCE
+
+ACE_RCSID(ace, SOCK_Acceptor, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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);
+ if (addr)
+ remote_addr->set_type (addr->sa_family);
+ }
+ }
+
+ return this->shared_accept_finish (new_stream,
+ in_blocking_mode,
+ reset_new_handle);
+}
+
+#if !defined (ACE_HAS_WINCE)
+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);
+}
+#endif // ACE_HAS_WINCE
+
+void
+ACE_SOCK_Acceptor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_Acceptor::dump");
+#endif /* ACE_HAS_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)
+ if (protocol_family == PF_INET6)
+ {
+ sockaddr_in6 local_inet6_addr;
+ ACE_OS::memset (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 = *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 (),
+ 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 (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 = *reinterpret_cast<sockaddr_in *> (local_sap.get_addr ());
+ if (local_inet_addr.sin_port == 0)
+ {
+ if (ACE::bind_port (this->get_handle (),
+ ACE_NTOHL (ACE_UINT32 (local_inet_addr.sin_addr.s_addr))) == -1)
+ error = 1;
+ }
+ else if (ACE_OS::bind (this->get_handle (),
+ 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)
+ {
+ ACE_Errno_Guard g (errno); // Preserve across close() below.
+ 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_TEXT ("%p\n"),
+ ACE_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::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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_Acceptor")));
+}
+
+int
+ACE_SOCK_Acceptor::close (void)
+{
+ return ACE_SOCK::close ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Acceptor.h b/ACE/ace/SOCK_Acceptor.h
new file mode 100644
index 00000000000..2a14cb342db
--- /dev/null
+++ b/ACE/ace/SOCK_Acceptor.h
@@ -0,0 +1,178 @@
+/* -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+class ACE_Accept_QoS_Params;
+
+/**
+ * @class ACE_SOCK_Acceptor
+ *
+ * @brief Defines a factory that creates new ACE_Streams 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).
+ * @a local_sap is the address that we're going to listen for
+ * connections on. If @a reuse_addr is 1 then we'll use the
+ * @c 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).
+ * @a local_sap is the address that we're going to listen for
+ * connections on. If @a reuse_addr is 1 then we'll use the
+ * @c 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 @a timeout of 0
+ * means block forever, a @a timeout of {0, 0} means poll. <restart>
+ * == 1 means "restart if interrupted," i.e., if errno == EINTR.
+ * Note that @a new_stream inherits the "blocking mode" of @c this
+ * ACE_SOCK_Acceptor, i.e., if @c this acceptor factory is in
+ * non-blocking mode, the @a new_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;
+
+#if !defined (ACE_HAS_WINCE)
+ /**
+ * Accept a new ACE_SOCK_Stream connection using the QoS
+ * information in @a qos_params. A @a timeout of 0 means block
+ * forever, a @a timeout of {0, 0} means poll. @a restart == 1 means
+ * "restart if interrupted," i.e., if errno == EINTR. Note that
+ * @a new_stream inherits the "blocking mode" of @c this
+ * ACE_SOCK_Acceptor, i.e., if @c this acceptor factory is in
+ * non-blocking mode, the @a new_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;
+#endif // ACE_HAS_WINCE
+
+ // = 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_ACCEPTOR_H */
diff --git a/ACE/ace/SOCK_Acceptor.inl b/ACE/ace/SOCK_Acceptor.inl
new file mode 100644
index 00000000000..a4456ed3ab6
--- /dev/null
+++ b/ACE/ace/SOCK_Acceptor.inl
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SOCK_Acceptor::~ACE_SOCK_Acceptor (void)
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::~ACE_SOCK_Acceptor");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_CODgram.cpp b/ACE/ace/SOCK_CODgram.cpp
new file mode 100644
index 00000000000..eb1d3f18291
--- /dev/null
+++ b/ACE/ace/SOCK_CODgram.cpp
@@ -0,0 +1,112 @@
+// $Id$
+
+#include "ace/SOCK_CODgram.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_socket.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_CODgram.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK_CODgram, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_CODgram)
+
+void
+ACE_SOCK_CODgram::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_CODgram::dump");
+#endif /* ACE_HAS_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_TEXT ("%p\n"), ACE_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;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_CODgram.h b/ACE/ace/SOCK_CODgram.h
new file mode 100644
index 00000000000..04f9c55ceb1
--- /dev/null
+++ b/ACE/ace/SOCK_CODgram.h
@@ -0,0 +1,78 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_IO.h"
+#include "ace/Addr.h"
+#include "ace/INET_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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);
+
+ // = 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_CODgram.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_CODGRAM_H */
diff --git a/ACE/ace/SOCK_CODgram.inl b/ACE/ace/SOCK_CODgram.inl
new file mode 100644
index 00000000000..de7b0570973
--- /dev/null
+++ b/ACE/ace/SOCK_CODgram.inl
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SOCK_CODgram::ACE_SOCK_CODgram (void)
+{
+ ACE_TRACE ("ACE_SOCK_CODgram::ACE_SOCK_CODgram");
+}
+
+ACE_INLINE
+ACE_SOCK_CODgram::~ACE_SOCK_CODgram (void)
+{
+ ACE_TRACE ("ACE_SOCK_CODgram::~ACE_SOCK_CODgram");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Connector.cpp b/ACE/ace/SOCK_Connector.cpp
new file mode 100644
index 00000000000..2dda434d258
--- /dev/null
+++ b/ACE/ace/SOCK_Connector.cpp
@@ -0,0 +1,359 @@
+// $Id$
+
+#include "ace/SOCK_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/os_include/os_fcntl.h"
+
+#if !defined (ACE_HAS_WINCE)
+#include "ace/OS_QoS.h"
+#endif // ACE_HAS_WINCE
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK_Connector, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Connector)
+
+void
+ACE_SOCK_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_Connector::dump");
+#endif /* ACE_HAS_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 = reinterpret_cast<sockaddr *> (local_sap.get_addr ());
+ int 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)
+ {
+#if defined(ACE_WIN32)
+ // In order to detect when the socket that has been
+ // bound to is in TIME_WAIT we need to do the connect
+ // (which will always return EWOULDBLOCK) and then do an
+ // ACE::handle_timed_complete() (with timeout==0,
+ // i.e. poll). This will do a select() on the handle
+ // which will immediately return with the handle in an
+ // error state. The error code is then retrieved with
+ // getsockopt(). Good sockets however will return from
+ // the select() with ETIME - in this case return
+ // EWOULDBLOCK so the wait strategy can complete the
+ // connection.
+ if(ACE::handle_timed_complete (new_stream.get_handle (),
+ timeout) == ACE_INVALID_HANDLE)
+ {
+ int const tmp = errno;
+ if (tmp != ETIME)
+ {
+ error = tmp;
+ }
+ else
+ error = EWOULDBLOCK;
+ }
+ else
+ result = 0;
+#else /* ACE_WIN32 */
+ error = EWOULDBLOCK;
+#endif /* ACE_WIN32 */
+ }
+ // 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)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::connect");
+
+ if (this->shared_open (new_stream,
+ remote_sap.get_type (),
+ 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 (),
+ reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
+ remote_sap.get_size ());
+
+ return this->shared_connect_finish (new_stream,
+ timeout,
+ result);
+}
+
+#if !defined (ACE_HAS_WINCE)
+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 */)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::connect");
+
+ if (this->shared_open (new_stream,
+ remote_sap.get_type (),
+ 0,
+ 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 (),
+ reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
+ remote_sap.get_size (),
+ qos_params);
+
+ return this->shared_connect_finish (new_stream,
+ timeout,
+ result);
+}
+#endif // ACE_HAS_WINCE
+
+// 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 = 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)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
+
+ if (this->connect (new_stream,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ protocol) == -1
+ && timeout != 0
+ && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_Connector::ACE_SOCK_Connector")));
+}
+
+#if !defined (ACE_HAS_WINCE)
+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)
+{
+ 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) == -1
+ && timeout != 0
+ && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_Connector::ACE_SOCK_Connector")));
+}
+#endif // ACE_HAS_WINCE
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Connector.h b/ACE/ace/SOCK_Connector.h
new file mode 100644
index 00000000000..3873d7c95d4
--- /dev/null
+++ b/ACE/ace/SOCK_Connector.h
@@ -0,0 +1,321 @@
+// -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_QoS_Params;
+class ACE_Time_Value;
+
+/**
+ * @class ACE_SOCK_Connector
+ *
+ * @brief Defines a factory that actively connects to a remote IP
+ * address and TCP port, creating a new @c ACE_SOCK_Stream object.
+ *
+ * The @c ACE_SOCK_Connector doesn't have a socket of its own,
+ * i.e., it simply "borrows" the one from the @c 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
+ * @c ACE_SOCK_Connector from @c ACE_SOCK. A nice side-effect of
+ * this is that @c ACE_SOCK_Connector objects do not store state so
+ * they can be used reentrantly in multithreaded programs.
+ */
+class ACE_Export ACE_SOCK_Connector
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SOCK_Connector (void);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SOCK_Stream
+ * object if the connection succeeds.
+ *
+ * @param new_stream The @c ACE_SOCK_Stream object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ * @param protocol (optional) If value is 0, default SOCK_STREAM
+ * protocol is selected by kernel (typically TCP).
+ */
+ 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 = 0);
+
+#if !defined (ACE_HAS_WINCE)
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SOCK_Stream
+ * object if the connection succeeds.
+ *
+ * @param new_stream The @c ACE_SOCK_Stream object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param qos_params Contains QoS parameters that are passed to the
+ * IntServ (RSVP) and DiffServ protocols.
+ * @see ACE_QoS_Params.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms 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);
+#endif // ACE_HAS_WINCE
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SOCK_Stream
+ * object if the connection succeeds.
+ *
+ * @param new_stream The @c ACE_SOCK_Stream object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ * @param protocol (optional) If value is 0, default SOCK_STREAM
+ * protocol is selected by kernel (typically TCP).
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ 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 = 0);
+
+#if !defined (ACE_HAS_WINCE)
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SOCK_Stream
+ * object if the connection succeeds.
+ *
+ * @param new_stream The @c ACE_SOCK_Stream object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param qos_params Contains QoS parameters that are passed to the
+ * IntServ (RSVP) and DiffServ protocols.
+ * @see ACE_QoS_Params.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ 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);
+#endif // ACE_HAS_WINCE
+
+ /// Default dtor.
+ ~ACE_SOCK_Connector (void);
+
+ // = Completion routine.
+ /**
+ * Try to complete a nonblocking connection that was begun by a
+ * previous call to connect with a {0, 0} ACE_Time_Value timeout.
+ * @see connect().
+ *
+ * @param new_stream The @c ACE_SOCK_Stream object that will be connected
+ * to the peer.
+ * @param remote_sap If non-0, it points to the @c ACE_INET_Addr object
+ * that will contain the address of the connected peer.
+ * @param timeout Same values and return value possibilites as for
+ * connect(). @see connect().
+ */
+ 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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_CONNECTOR_H */
diff --git a/ACE/ace/SOCK_Connector.inl b/ACE/ace/SOCK_Connector.inl
new file mode 100644
index 00000000000..bdbf5cd19f6
--- /dev/null
+++ b/ACE/ace/SOCK_Connector.inl
@@ -0,0 +1,38 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This constructor is used by a client when it wants to connect to
+// the specified REMOTE_SAP address using a blocking open.
+
+ACE_INLINE
+ACE_SOCK_Connector::~ACE_SOCK_Connector (void)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::~ACE_SOCK_Connector");
+}
+
+// Do-nothing constructor...
+
+ACE_INLINE
+ACE_SOCK_Connector::ACE_SOCK_Connector (void)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
+}
+
+ACE_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,
+ 0,
+ 0);
+#else /* !defined ACE_HAS_WINSOCK2 */
+ ACE_UNUSED_ARG (handle);
+ return 0;
+#endif /* ACE_WIN32 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Dgram.cpp b/ACE/ace/SOCK_Dgram.cpp
new file mode 100644
index 00000000000..c059647c6d5
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram.cpp
@@ -0,0 +1,750 @@
+#include "ace/SOCK_Dgram.h"
+
+#include "ace/Handle_Set.h"
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/os_include/net/os_if.h"
+#include "ace/Truncate.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/SOCK_Dgram.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_HAS_IPV6) && defined (ACE_WIN32)
+#include /**/ <Iphlpapi.h>
+#endif
+
+ACE_RCSID (ace,
+ SOCK_Dgram,
+ "$Id$")
+
+// 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_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_SOCK_Dgram)
+
+void
+ACE_SOCK_Dgram::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_Dgram::dump");
+#endif /* ACE_HAS_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).
+ int select_width;
+# if defined (ACE_WIN32)
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles.
+ select_width = 0;
+# else
+ select_width = int (this->get_handle ()) + 1;
+# endif /* ACE_WIN32 */
+ switch (ACE_OS::select (select_width,
+ 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 ();
+ int inlen;
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ FIONREAD,
+ &inlen) == -1)
+ return -1;
+ else if (inlen > 0)
+ {
+ ACE_NEW_RETURN (io_vec->iov_base,
+ char[inlen],
+ -1);
+ ssize_t rcv_len = ACE_OS::recvfrom (this->get_handle (),
+ (char *) io_vec->iov_base,
+ inlen,
+ flags,
+ (sockaddr *) saddr,
+ &addr_len);
+ if (rcv_len < 0)
+ {
+ delete [] (char *)io_vec->iov_base;
+ io_vec->iov_base = 0;
+ }
+ else
+ {
+ io_vec->iov_len = ACE_Utils::truncate_cast<size_t> (rcv_len);
+ addr.set_size (addr_len);
+ }
+ return rcv_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");
+ bool error = false;
+
+ if (local == ACE_Addr::sap_any)
+ {
+ if (protocol_family == PF_INET
+#if defined (ACE_HAS_IPV6)
+ || protocol_family == PF_INET6
+#endif /* ACE_HAS_IPV6 */
+ )
+ {
+ if (ACE::bind_port (this->get_handle (),
+ INADDR_ANY,
+ protocol_family) == -1)
+ error = true;
+ }
+ }
+ else if (ACE_OS::bind (this->get_handle (),
+ reinterpret_cast<sockaddr *> (local.get_addr ()),
+ local.get_size ()) == -1)
+ error = true;
+
+ if (error)
+ 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::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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_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[],
+ int 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[],
+ int 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);
+ addr.set_type (((sockaddr_in *) addr.get_addr())->sin_family);
+ 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[],
+ int n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::send");
+
+ size_t length = 0;
+ int i;
+
+ // Determine the total length of all the buffers in <iov>.
+ for (i = 0; i < n; i++)
+#if ! (defined(__BORLANDC__) || defined(linux) || defined(ACE_HAS_RTEMS))
+ // The iov_len is unsigned on Linux, RTEMS and with 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 = 0;
+
+#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[],
+ int n,
+ ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::recv");
+
+ ssize_t length = 0;
+ int i;
+
+ for (i = 0; i < n; i++)
+#if ! (defined(__BORLANDC__) || defined(linux) || defined(ACE_HAS_RTEMS))
+ // The iov_len is unsigned on Linux, RTEMS and with 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 = 0;
+
+#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.
+ int select_width;
+#if defined (ACE_WIN32)
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles.
+ select_width = 0;
+#else
+ select_width = int (this->get_handle ()) + 1;
+#endif /* ACE_WIN32 */
+ switch (ACE_OS::select (select_width,
+ 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.
+ int select_width;
+#if defined (ACE_WIN32)
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles.
+ select_width = 0;
+#else
+ select_width = int (this->get_handle ()) + 1;
+#endif /* ACE_WIN32 */
+ switch (ACE_OS::select (select_width,
+ 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);
+ }
+}
+
+int
+ACE_SOCK_Dgram::set_nic (const ACE_TCHAR *net_if,
+ int addr_family)
+{
+#if defined (IP_MULTICAST_IF) && (IP_MULTICAST_IF != 0)
+# if defined (ACE_HAS_IPV6)
+ bool ipv6_mif_set = false;
+ if (addr_family == AF_INET6 || addr_family == AF_UNSPEC)
+ {
+ ACE_INET_Addr addr;
+ addr.set (static_cast<u_short> (0), ACE_IPV6_ANY);
+ ipv6_mreq send_mreq;
+ if (this->make_multicast_ifaddr6 (&send_mreq,
+ addr,
+ net_if) == -1)
+ return -1;
+
+ // Only let this attempt to set unknown interface when INET6 is
+ // specifically requested. Otherwise we will just try INET.
+ if (send_mreq.ipv6mr_interface != 0 || addr_family == AF_INET6)
+ {
+ if (this->ACE_SOCK::set_option
+ (IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ &(send_mreq.ipv6mr_interface),
+ sizeof send_mreq.ipv6mr_interface) == -1)
+ return -1;
+ }
+ ipv6_mif_set = send_mreq.ipv6mr_interface != 0;
+ }
+
+# if defined (ACE_WIN32)
+ // For Win32 net_if is distintly different between INET6 and INET
+ // so it is always either an INET6 if or an INET if.
+ if (!ipv6_mif_set && (addr_family == AF_INET || addr_family == AF_UNSPEC))
+# else
+ if (addr_family == AF_INET || addr_family == AF_UNSPEC)
+# endif
+ {
+ ACE_INET_Addr addr (static_cast<u_short> (0));
+ ip_mreq send_mreq;
+ if (this->make_multicast_ifaddr (&send_mreq,
+ addr,
+ net_if) == -1)
+ {
+ if (!ipv6_mif_set)
+ return -1;
+ }
+ else if (this->ACE_SOCK::set_option (IPPROTO_IP,
+ IP_MULTICAST_IF,
+ &(send_mreq.imr_interface),
+ sizeof send_mreq.imr_interface) == -1)
+ {
+ if (!ipv6_mif_set)
+ return -1;
+ }
+ }
+# else /* ACE_HAS_IPV6 */
+ ACE_UNUSED_ARG (addr_family);
+ ACE_INET_Addr addr (static_cast<u_short> (0));
+ ip_mreq send_mreq;
+ if (this->make_multicast_ifaddr (&send_mreq,
+ addr,
+ net_if) == -1)
+ return -1;
+ if (this->ACE_SOCK::set_option (IPPROTO_IP,
+ IP_MULTICAST_IF,
+ &(send_mreq.imr_interface),
+ sizeof send_mreq.imr_interface) == -1)
+ return -1;
+# endif /* !ACE_HAS_IPV6 */
+#else /* IP_MULTICAST_IF */
+ // Send interface option not supported - ignore it.
+ // (We may have been invoked by ::subscribe, so we have to allow
+ // a non-null interface parameter in this function.)
+ ACE_UNUSED_ARG (net_if);
+ ACE_UNUSED_ARG (addr_family);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Send interface specification not ")
+ ACE_TEXT ("supported - IGNORED.\n")));
+#endif /* !IP_MULTICAST_IF */
+
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram::make_multicast_ifaddr (ip_mreq *ret_mreq,
+ const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_ifaddr");
+ ip_mreq lmreq; // Scratch copy.
+ if (net_if != 0)
+ {
+#if defined (ACE_WIN32) || defined(__INTERIX)
+ // 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;
+ lmreq.imr_interface.s_addr =
+ ACE_HTONL (interface_addr.get_ip_address ());
+#else
+ ifreq if_address;
+
+ ACE_OS::strcpy (if_address.ifr_name, ACE_TEXT_ALWAYS_CHAR (net_if));
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ SIOCGIFADDR,
+ &if_address) == -1)
+ return -1;
+
+ sockaddr_in *socket_address =
+ reinterpret_cast<sockaddr_in*> (&if_address.ifr_addr);
+ lmreq.imr_interface.s_addr = socket_address->sin_addr.s_addr;
+#endif /* ACE_WIN32 || __INTERIX */
+ }
+ else
+ lmreq.imr_interface.s_addr = INADDR_ANY;
+
+ lmreq.IMR_MULTIADDR.s_addr = ACE_HTONL (mcast_addr.get_ip_address ());
+
+ // Set return info, if requested.
+ if (ret_mreq)
+ *ret_mreq = lmreq;
+
+ return 0;
+}
+
+#if defined (ACE_HAS_IPV6)
+// XXX: This will not work on any operating systems that do not support
+// if_nametoindex or that is not Win32 >= Windows XP/Server 2003
+int
+ACE_SOCK_Dgram::make_multicast_ifaddr6 (ipv6_mreq *ret_mreq,
+ const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_ifaddr6");
+ ipv6_mreq lmreq; // Scratch copy.
+
+ ACE_OS::memset (&lmreq,
+ 0,
+ sizeof (lmreq));
+
+#if defined(__linux__)
+ if (net_if != 0)
+ {
+ lmreq.ipv6mr_interface = ACE_OS::if_nametoindex (ACE_TEXT_ALWAYS_CHAR(net_if));
+ }
+ else
+#elif defined (ACE_WIN32)
+ if (net_if != 0)
+ {
+ int if_ix = 0;
+ bool num_if =
+ ACE_OS::ace_isdigit (net_if[0]) &&
+ (if_ix = ACE_OS::atoi (net_if)) > 0;
+
+ IP_ADAPTER_ADDRESSES tmp_addrs;
+ // Initial call to determine actual memory size needed
+ DWORD dwRetVal;
+ ULONG bufLen = 0;
+ if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
+ 0,
+ 0,
+ &tmp_addrs,
+ &bufLen)) != ERROR_BUFFER_OVERFLOW)
+ return -1; // With output bufferlength 0 this can't be right.
+
+ // Get required output buffer and retrieve info for real.
+ PIP_ADAPTER_ADDRESSES pAddrs;
+ char *buf;
+ ACE_NEW_RETURN (buf,
+ char[bufLen],
+ -1);
+ pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
+ if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
+ 0,
+ 0,
+ pAddrs,
+ &bufLen)) != NO_ERROR)
+ {
+ delete[] buf; // clean up
+ return -1;
+ }
+
+ lmreq.ipv6mr_interface = 0; // initialize
+ while (pAddrs)
+ {
+ if ((num_if && pAddrs->Ipv6IfIndex == static_cast<unsigned int>(if_ix))
+ || (!num_if &&
+ (ACE_OS::strcmp (ACE_TEXT_ALWAYS_CHAR (net_if),
+ pAddrs->AdapterName) == 0
+ || ACE_OS::strcmp (ACE_TEXT_ALWAYS_CHAR (net_if),
+ ACE_Wide_To_Ascii (pAddrs->FriendlyName).char_rep()) == 0)))
+ {
+ lmreq.ipv6mr_interface = pAddrs->Ipv6IfIndex;
+ break;
+ }
+
+ pAddrs = pAddrs->Next;
+ }
+
+ delete[] buf; // clean up
+ }
+ else
+#else /* ACE_WIN32 */
+ ACE_UNUSED_ARG(net_if);
+#endif /* ACE_WIN32 */
+ lmreq.ipv6mr_interface = 0;
+
+ // now set the multicast address
+ ACE_OS::memcpy (&lmreq.ipv6mr_multiaddr,
+ &((sockaddr_in6 *) mcast_addr.get_addr ())->sin6_addr,
+ sizeof (in6_addr));
+
+ // Set return info, if requested.
+ if (ret_mreq)
+ *ret_mreq = lmreq;
+
+ return 0;
+}
+#endif /* __linux__ && ACE_HAS_IPV6 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Dgram.h b/ACE/ace/SOCK_Dgram.h
new file mode 100644
index 00000000000..7249f8cb8cb
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram.h
@@ -0,0 +1,239 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SOCK_Dgram.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#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"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @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 @a 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 @a 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 @a n byte @a 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 @a n byte @a 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 @a n to the datagram socket (uses
+ /// <sendmsg(3)>).
+ ssize_t send (const iovec iov[],
+ int n,
+ const ACE_Addr &addr,
+ int flags = 0) const;
+
+ /// Recv an <iovec> of size @a n to the datagram socket (uses
+ /// <recvmsg(3)>).
+ ssize_t recv (iovec iov[],
+ int n,
+ ACE_Addr &addr,
+ int flags = 0) const;
+
+ /**
+ * Wait up to @a timeout amount of time to receive a datagram into
+ * @a buf. The ACE_Time_Value indicates how long to blocking
+ * trying to receive. If @a timeout == 0, the caller will block
+ * until action is possible, else will wait until the relative time
+ * specified in *@a timeout elapses). If <recv> times out a -1 is
+ * returned with @c 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 @a timeout amount of time to send a datagram to
+ * @a buf. The ACE_Time_Value indicates how long to blocking
+ * trying to receive. If @a timeout == 0, the caller will block
+ * until action is possible, else will wait until the relative time
+ * specified in *@a timeout elapses). If <send> times out a -1 is
+ * returned with @c 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 @a buffers to @a addr using overlapped
+ /// I/O (uses <WSASendTo>). 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 @a buffers from @a 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 @a n byte @a buf to the datagram socket (uses <WSASendTo>).
+ 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 @a n byte @a 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;
+
+ // = Meta-type info.
+ typedef ACE_INET_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Set NIC to use as multicast interface.
+ int set_nic (const ACE_TCHAR *net_if,
+ int addr_family = AF_UNSPEC);
+
+ /// 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);
+
+ /// Create a multicast addr/if pair, in format useful for system calls.
+ /// If mreq param is NULL, just verify the passed addr/interface specs.
+ int make_multicast_ifaddr (ip_mreq *mreq, // Put result here, if != NULL.
+ const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if);
+
+#if defined (ACE_HAS_IPV6)
+ /// Create a multicast addr/if pair, in format useful for system calls.
+ /// If mreq param is NULL, just verify the passed addr/interface specs.
+ int make_multicast_ifaddr6 (ipv6_mreq *mreq, // Put result here, if != NULL.
+ const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if);
+
+#endif /* ACE_HAS_IPV6 */
+
+private:
+ /// Do not allow this function to percolate up to this interface...
+ int get_remote_addr (ACE_Addr &) const;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_Dgram.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_DGRAM_H */
diff --git a/ACE/ace/SOCK_Dgram.inl b/ACE/ace/SOCK_Dgram.inl
new file mode 100644
index 00000000000..2bcdfef7c3e
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram.inl
@@ -0,0 +1,167 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// SOCK_Dgram.i
+
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Here's the simple-minded constructor.
+
+ACE_INLINE
+ACE_SOCK_Dgram::ACE_SOCK_Dgram (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
+}
+
+ACE_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).
+
+ACE_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 ();
+ int 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).
+
+ACE_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 const status = ACE_OS::recvfrom (this->get_handle (),
+ (char *) buf,
+ n,
+ flags,
+ (sockaddr *) saddr,
+ &addr_len);
+ addr.set_size (addr_len);
+ addr.set_type (saddr->sa_family);
+ return status;
+}
+
+ACE_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 ();
+ int 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);
+}
+
+ACE_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);
+ addr.set_type (saddr->sa_family);
+ return status;
+}
+
+// <sendto> an N byte datagram to <addr> (connectionless version).
+
+ACE_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 = static_cast<u_long> (n); // Betting on < 4G
+ 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).
+
+ACE_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 = static_cast<u_long> (n); // Betting on < 4G
+ 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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Dgram_Bcast.cpp b/ACE/ace/SOCK_Dgram_Bcast.cpp
new file mode 100644
index 00000000000..b2a1f2e9204
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram_Bcast.cpp
@@ -0,0 +1,380 @@
+// $Id$
+
+#include "ace/SOCK_Dgram_Bcast.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/net/os_if.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/OS_Memory.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_Dgram_Bcast.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK_Dgram_Bcast, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::dump");
+#endif /* ACE_HAS_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_;
+ this->if_list_ = 0;
+
+ // 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_TEXT ("%p\n"),
+ ACE_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)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: setsockopt failed"),
+ -1);
+
+#if !defined (ACE_WIN32) && !defined(__INTERIX)
+ 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 (ACE_TEXT_ALWAYS_CHAR (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 */
+ }
+
+
+#if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_VXWORKS) && !defined(__APPLE__)
+ for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
+ n--, ifr++)
+#else
+ /*
+ There are addresses longer than sizeof (struct sockaddr) eg. IPv6
+ or QNX::links. In this case address does not fit into struct ifreq.
+ The code below could be applied everywhere, but not every system
+ provides sockaddr.sa_len field.
+ */
+ for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
+ ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
+ (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
+ ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
+ (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
+ ifr = (struct ifreq *)
+ ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
+ (nbytes -= sizeof (struct ifreq), ifr++)))
+#endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_VXWORKS) && !defined(__APPLE__) */
+ {
+#if defined (__QNX__) || defined (ACE_VXWORKS)
+ // Silently skip link interfaces
+ if (ifr->ifr_addr.sa_family == AF_LINK)
+ continue;
+#endif /* __QNX__ */
+ // 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 ())
+ 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 [%s]\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface flags)",
+ flags.ifr_name));
+ continue;
+ }
+
+ if (ACE_BIT_ENABLED (flags.ifr_flags,
+ IFF_UP) == 0)
+ {
+ ACE_ERROR ((LM_ERROR, "%p [%s]\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: Network interface is not up",
+ flags.ifr_name));
+ 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 [%s]\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get broadaddr)",
+ flags.ifr_name));
+ else
+ {
+ ACE_INET_Addr addr (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
+ {
+ if (host_name != 0)
+ ACE_ERROR ((LM_ERROR, "%p [%s]\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not enable for this interface.",
+ flags.ifr_name));
+ }
+ }
+#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 && !__INTERIX */
+ if (this->if_list_ == 0)
+ {
+ errno = ENXIO;
+ return -1;
+ }
+ else
+ return 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");
+ ssize_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[],
+ int 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 = temp->next_)
+ {
+ temp->bcast_addr_.set_port_number (port_number);
+
+ 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[],
+ int 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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Dgram_Bcast.h b/ACE/ace/SOCK_Dgram_Bcast.h
new file mode 100644
index 00000000000..deda3297339
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram_Bcast.h
@@ -0,0 +1,140 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Bcast_Node
+ *
+ * @brief Linked list of broadcast interfaces.
+ */
+class ACE_Export ACE_Bcast_Node
+{
+public:
+ /// Default constructor.
+ ACE_Bcast_Node (ACE_INET_Addr &,
+ ACE_Bcast_Node *);
+
+ /// Destructor.
+ ~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 @c iov datagrams to every interface. Returns the
+ /// average number of bytes sent.
+ ssize_t send (const iovec iov[],
+ int 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 @a iovec of size @a n to @a addr as a datagram (note
+ * that addr must be preassigned to the broadcast address of the
+ * subnet...)
+ */
+ ssize_t send (const iovec iov[],
+ int 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_Dgram_Bcast.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_DGRAM_BCAST_H */
diff --git a/ACE/ace/SOCK_Dgram_Bcast.inl b/ACE/ace/SOCK_Dgram_Bcast.inl
new file mode 100644
index 00000000000..00bb342be5e
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram_Bcast.inl
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Bcast_Node::~ACE_Bcast_Node (void)
+{
+}
+
+ACE_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...)
+
+ACE_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 ();
+ int len = addr.get_size ();
+ return ACE_OS::sendto (this->get_handle (), (const char *) buf, n, flags,
+ (struct sockaddr *) saddr, len);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Dgram_Mcast.cpp b/ACE/ace/SOCK_Dgram_Mcast.cpp
new file mode 100644
index 00000000000..baa49f521e5
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram_Mcast.cpp
@@ -0,0 +1,928 @@
+// $Id$
+
+#include "ace/SOCK_Dgram_Mcast.h"
+
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/os_include/net/os_if.h"
+#include "ace/os_include/arpa/os_inet.h"
+
+#if defined (__linux__) && defined (ACE_HAS_IPV6)
+#include "ace/OS_NS_sys_socket.h"
+#endif
+
+#if defined (ACE_HAS_IPV6) && defined (ACE_WIN32)
+#include /**/ <Iphlpapi.h>
+#endif
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_Dgram_Mcast.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ SOCK_Dgram_Mcast,
+ "$Id$")
+
+#include "ace/Log_Msg.h"
+
+// 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_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Helper (inline) functions.
+class ACE_SDM_helpers
+{
+public:
+ // Convert ACE_INET_Addr to string, using local formatting rules.
+
+ static void addr_to_string (const ACE_INET_Addr &ip_addr,
+ ACE_TCHAR *ret_string, // results here.
+ size_t len,
+ int clip_portnum) // clip port# info?
+ {
+ if (ip_addr.addr_to_string (ret_string, len, 1) == -1)
+ ACE_OS::strcpy (ret_string, ACE_TEXT ("<?>"));
+ else
+ {
+ ACE_TCHAR *pc = ACE_OS::strrchr (ret_string, ACE_TEXT (':'));
+ if (clip_portnum && pc)
+ *pc = ACE_TEXT ('\0'); // clip port# info.
+ }
+ }
+ // op== for ip_mreq structs.
+ static int is_equal (const ip_mreq &m1, const ip_mreq &m2)
+ {
+ return m1.IMR_MULTIADDR.s_addr == m2.IMR_MULTIADDR.s_addr
+ && m1.imr_interface.s_addr == m2.imr_interface.s_addr;
+ }
+};
+
+ACE_ALLOC_HOOK_DEFINE (ACE_SOCK_Dgram_Mcast)
+
+void
+ACE_SOCK_Dgram_Mcast::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+# if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
+ ACE_TCHAR addr_string[MAXNAMELEN + 1];
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\nOptions: bindaddr=%s, nulliface=%s\n"),
+ ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES) ?
+ ACE_TEXT ("<Bound>") : ACE_TEXT ("<Not Bound>"),
+ ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL) ?
+ ACE_TEXT ("<All Ifaces>") : ACE_TEXT ("<Default Iface>")));
+
+ // Show default send addr, port#, and interface.
+ ACE_SDM_helpers::addr_to_string (this->send_addr_, addr_string,
+ sizeof addr_string, 0);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Send addr=%s iface=%s\n"),
+ addr_string,
+ this->send_net_if_ ? this->send_net_if_
+ : ACE_TEXT ("<default>")));
+
+ // Show list of subscribed addresses.
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Subscription list:\n")));
+
+ ACE_MT (ACE_GUARD (ACE_SDM_LOCK, guard, this->subscription_list_lock_));
+ subscription_list_iter_t iter (this->subscription_list_);
+ for ( ; !iter.done (); iter.advance ())
+ {
+ ACE_TCHAR iface_string[MAXNAMELEN + 1];
+ ip_mreq *pm = iter.next ();
+
+ // Get subscribed address (w/out port# info - not relevant).
+ ACE_INET_Addr ip_addr (static_cast<u_short> (0),
+ ACE_NTOHL (pm->IMR_MULTIADDR.s_addr));
+ ACE_SDM_helpers::addr_to_string (ip_addr, addr_string,
+ sizeof addr_string, 1);
+
+ // Get interface address/specification.
+ ACE_INET_Addr if_addr (static_cast<u_short> (0),
+ ACE_NTOHL (pm->imr_interface.s_addr));
+ ACE_SDM_helpers::addr_to_string (if_addr, iface_string,
+ sizeof iface_string, 1);
+ if (ACE_OS::strcmp (iface_string, ACE_TEXT ("0.0.0.0")) == 0)
+ // Receives on system default iface. (Note that null_iface_opt_
+ // option processing has already occurred.)
+ ACE_OS::strcpy (iface_string, ACE_TEXT ("<default>"));
+
+ // Dump info.
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\taddr=%s iface=%s\n"),
+ addr_string,
+ iface_string));
+ }
+# endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// Constructor.
+ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast
+ (ACE_SOCK_Dgram_Mcast::options opts)
+ : opts_ (opts),
+ send_net_if_ (0)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast");
+}
+
+// Destructor.
+ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast");
+
+ // Free memory and optionally unsubscribe from currently subscribed group(s).
+ delete [] this->send_net_if_;
+ this->clear_subs_list ();
+}
+
+int
+ACE_SOCK_Dgram_Mcast::open (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open");
+
+ // Only perform the <open> initialization if we haven't been opened
+ // earlier.
+ // No sanity check? We should probably flag an error if the user
+ // makes multiple calls to open().
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ return 0;
+
+ // Invoke lower-layer ::open.
+ if (ACE_SOCK::open (SOCK_DGRAM,
+ mcast_addr.get_type (),
+ 0, // always use 0
+ reuse_addr) == -1)
+ return -1;
+
+ return this->open_i (mcast_addr, net_if, reuse_addr);
+}
+
+int
+ACE_SOCK_Dgram_Mcast::open_i (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open_i");
+ // ACE_SOCK::open calls this if reuse_addr is set, so we only need to
+ // process port reuse option.
+ if (reuse_addr)
+ {
+#if defined (SO_REUSEPORT)
+ int one = 1;
+ if (this->ACE_SOCK::set_option (SOL_SOCKET,
+ SO_REUSEPORT,
+ &one,
+ sizeof one) == -1)
+ return -1;
+#endif /* SO_REUSEPORT */
+ }
+
+ // Create an address/port# to bind the socket to. Use mcast_addr to
+ // initialize bind_addy to pick up the correct protocol family. If
+ // OPT_BINDADDR_YES is set, then we're done. Else use mcast_addr's
+ // port number and use the "any" address.
+ ACE_INET_Addr bind_addy (mcast_addr);
+ if (ACE_BIT_DISABLED (this->opts_, OPT_BINDADDR_YES))
+ {
+#if defined (ACE_HAS_IPV6)
+ if (mcast_addr.get_type () == PF_INET6)
+ {
+ if (bind_addy.set (mcast_addr.get_port_number (), "::",
+ 1, AF_INET6) == -1)
+ return -1;
+ }
+ else
+ // Bind to "any" address and explicit port#.
+ if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
+ return -1;
+#else
+ // Bind to "any" address and explicit port#.
+ if (bind_addy.set (mcast_addr.get_port_number ()) == -1)
+ return -1;
+#endif /* ACE_HAS_IPV6 */
+ }
+
+ // Bind to the address (which may be INADDR_ANY) and port# (which may be 0)
+ if (ACE_SOCK_Dgram::shared_open (bind_addy, bind_addy.get_type ()) == -1)
+ return -1;
+
+ // Cache the actual bound address (which may be INADDR_ANY)
+ // and the actual bound port# (which will be a valid, non-zero port#).
+ ACE_INET_Addr bound_addy;
+ if (this->get_local_addr (bound_addy) == -1)
+ {
+ // (Unexpected failure - should be bound to something)
+ if (bound_addy.set (bind_addy) == -1)
+ {
+ // (Shouldn't happen - bind_addy is a valid addy; punt.)
+ return -1;
+ }
+ }
+
+ this->send_addr_ = mcast_addr;
+ this->send_addr_.set_port_number (bound_addy.get_port_number ());
+ if (net_if)
+ {
+ if (this->set_nic (net_if, mcast_addr.get_type ()))
+ return -1;
+
+ this->send_net_if_ = new ACE_TCHAR[ACE_OS::strlen (net_if) + 1];
+ ACE_OS::strcpy (this->send_net_if_, net_if);
+ }
+
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_ifs");
+
+ if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
+ && net_if == 0)
+ {
+#if defined (ACE_HAS_IPV6)
+ if (mcast_addr.get_type () == AF_INET6)
+ {
+ size_t nr_subscribed = 0;
+# if defined(__linux__)
+ struct if_nameindex *intf;
+
+ intf = ACE_OS::if_nameindex ();
+
+ if (intf == 0)
+ return -1;
+
+ int index = 0;
+ while (intf[index].if_index != 0 || intf[index].if_name != 0)
+ {
+ if (this->join (mcast_addr, reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
+ ++nr_subscribed;
+
+ ++index;
+ }
+
+ ACE_OS::if_freenameindex (intf);
+
+# elif defined (ACE_WIN32)
+
+ IP_ADAPTER_ADDRESSES tmp_addrs;
+ // Initial call to determine actual memory size needed
+ DWORD dwRetVal;
+ ULONG bufLen = 0;
+ if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
+ 0,
+ 0,
+ &tmp_addrs,
+ &bufLen)) != ERROR_BUFFER_OVERFLOW)
+ return -1; // With output bufferlength 0 this can't be right.
+
+ // Get required output buffer and retrieve info for real.
+ PIP_ADAPTER_ADDRESSES pAddrs;
+ char *buf;
+ ACE_NEW_RETURN (buf,
+ char[bufLen],
+ -1);
+ pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
+ if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
+ 0,
+ 0,
+ pAddrs,
+ &bufLen)) != NO_ERROR)
+ {
+ delete[] buf; // clean up
+ return -1;
+ }
+
+ while (pAddrs)
+ {
+ if (this->join (mcast_addr, reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
+ ++nr_subscribed;
+
+ pAddrs = pAddrs->Next;
+ }
+
+ delete[] buf; // clean up
+
+# endif /* ACE_WIN32 */
+
+ if (nr_subscribed == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ return 1;
+ }
+ else
+ {
+ // Subscribe on all local multicast-capable network interfaces, by
+ // doing recursive calls with specific interfaces.
+
+ 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->join (mcast_addr,
+ reuse_addr,
+ ACE_TEXT ("0.0.0.0")) == 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_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
+ continue;
+ if (this->join (mcast_addr,
+ reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR
+ (if_addrs[if_cnt].get_host_addr ())) == 0)
+ ++nr_subscribed;
+ }
+ }
+
+ delete [] if_addrs;
+
+ if (nr_subscribed == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ // 1 indicates a "short-circuit" return. This handles the
+ // recursive behavior of checking all the interfaces.
+ return 1;
+
+ }
+#else
+ // Subscribe on all local multicast-capable network interfaces, by
+ // doing recursive calls with specific interfaces.
+
+ 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->join (mcast_addr,
+ reuse_addr,
+ ACE_TEXT ("0.0.0.0")) == 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].is_loopback ())
+ continue;
+ if (this->join (mcast_addr,
+ reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR
+ (if_addrs[if_cnt].get_host_addr ())) == 0)
+ ++nr_subscribed;
+ }
+ }
+
+ delete [] if_addrs;
+
+ if (nr_subscribed == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ // 1 indicates a "short-circuit" return. This handles the
+ // recursive behavior of checking all the interfaces.
+ return 1;
+#endif /* ACE_HAS_IPV6 */
+ }
+
+#if defined (ACE_HAS_IPV6)
+ if (mcast_addr.get_type () == AF_INET6)
+ {
+ if (this->make_multicast_ifaddr6 (0, mcast_addr, net_if) == -1)
+ return -1;
+ }
+ else
+ {
+ // Validate passed multicast addr and iface specifications.
+ if (this->make_multicast_ifaddr (0,
+ mcast_addr,
+ net_if) == -1)
+ return -1;
+ }
+#else
+ // Validate passed multicast addr and iface specifications.
+ if (this->make_multicast_ifaddr (0,
+ mcast_addr,
+ net_if) == -1)
+ return -1;
+#endif /* ACE_HAS_IPV6 */
+
+ return 0;
+
+}
+
+int
+ACE_SOCK_Dgram_Mcast::join (const ACE_INET_Addr &mcast_addr,
+ int reuse_addr,
+ const ACE_TCHAR *net_if)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::join");
+ ACE_INET_Addr subscribe_addr = mcast_addr;
+
+ // If port# is 0, insert bound port# if it is set. (To satisfy lower-level
+ // port# validation.)
+ u_short def_port_number = this->send_addr_.get_port_number ();
+ if (subscribe_addr.get_port_number () == 0
+ && def_port_number != 0)
+ {
+ subscribe_addr.set_port_number (def_port_number);
+ }
+
+ // Check for port# different than bound port#.
+ u_short sub_port_number = mcast_addr.get_port_number ();
+ if (sub_port_number != 0
+ && def_port_number != 0
+ && sub_port_number != def_port_number)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Subscribed port# (%u) different than bound ")
+ ACE_TEXT ("port# (%u).\n"),
+ (u_int) sub_port_number,
+ (u_int) def_port_number));
+ errno = ENXIO;
+ return -1;
+ }
+
+ // If bind_addr_opt_ is enabled, check for address different than
+ // bound address.
+ ACE_INET_Addr tmp_addr (this->send_addr_);
+ tmp_addr.set_port_number (mcast_addr.get_port_number ()); // force equal port numbers
+ if (ACE_BIT_ENABLED (this->opts_, OPT_BINDADDR_YES)
+ && !this->send_addr_.is_any ()
+ && this->send_addr_ != mcast_addr)
+ {
+ ACE_TCHAR sub_addr_string[MAXNAMELEN + 1];
+ ACE_TCHAR bound_addr_string[MAXNAMELEN + 1];
+ ACE_SDM_helpers::addr_to_string (mcast_addr, sub_addr_string,
+ sizeof sub_addr_string, 1);
+ ACE_SDM_helpers::addr_to_string (this->send_addr_, bound_addr_string,
+ sizeof bound_addr_string, 1);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Subscribed address (%s) different than ")
+ ACE_TEXT ("bound address (%s).\n"),
+ sub_addr_string,
+ bound_addr_string));
+ errno = ENXIO;
+ return -1;
+ }
+
+ // Attempt subscription.
+ int result = this->subscribe_i (subscribe_addr, reuse_addr, net_if);
+
+#if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
+ if (result == 0)
+ {
+ // Add this addr/iface info to the list of subscriptions.
+ // (Assumes this is unique addr/iface combo - most systems don't allow
+ // re-sub to same addr/iface.)
+ ip_mreq *pmreq = new ip_mreq;
+ // (should not fail)
+ if (this->make_multicast_ifaddr (pmreq, subscribe_addr, net_if) != -1)
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
+ this->subscription_list_lock_, -1));
+ this->subscription_list_.insert_tail (pmreq);
+ return 0;
+ }
+ // this still isn't really right. If ACE_GUARD_RETURN fails, we leak.
+ // Need to add one of Chris' fancy ace auto pointers (bound?).
+ delete pmreq;
+ }
+#endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
+
+ return result >= 0 ? 0 : result;
+}
+
+// Attempt subscribe and return status.
+int
+ACE_SOCK_Dgram_Mcast::subscribe_i (const ACE_INET_Addr &mcast_addr,
+ int reuse_addr,
+ const ACE_TCHAR *net_if)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_i");
+ ip_mreq mreq;
+#if defined (ACE_HAS_IPV6)
+ ipv6_mreq mreq6;
+#endif /* __linux__ && ACE_HAS_IPV6 */
+
+ // Open the socket IFF this is the first ::subscribe and ::open
+ // was not explicitly invoked.
+ if (this->open (mcast_addr,
+ net_if,
+ reuse_addr) == -1)
+ return -1;
+
+ // Only do this if net_if == 0, i.e., INADDR_ANY
+ if (net_if == 0)
+ {
+ int result = this->subscribe_ifs (mcast_addr,
+ net_if,
+ reuse_addr);
+ // Check for error or "short-circuit" return.
+ if (result != 0)
+ return result;
+ }
+
+#if defined (ACE_HAS_IPV6)
+ if (mcast_addr.get_type () == AF_INET6)
+ {
+ if (this->make_multicast_ifaddr6 (&mreq6, mcast_addr, net_if) == -1)
+ return -1;
+ // Tell IP stack to pass messages sent to this group.
+ else if (this->ACE_SOCK::set_option (IPPROTO_IPV6,
+ IPV6_JOIN_GROUP,
+ &mreq6,
+ sizeof mreq6) == -1)
+ return -1;
+
+ return 0;
+ }
+ // Fall through for IPv4 case
+#endif /* ACE_HAS_IPV6 */
+
+ // Create multicast addr/if struct.
+ if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
+ return -1;
+ // Tell IP stack to pass messages sent to this group.
+ else if (this->ACE_SOCK::set_option (IPPROTO_IP,
+ IP_ADD_MEMBERSHIP,
+ &mreq,
+ sizeof mreq) == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast::unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_ifs");
+
+
+ if (ACE_BIT_ENABLED (this->opts_, OPT_NULLIFACE_ALL)
+ && net_if == 0)
+ {
+#if defined (ACE_HAS_IPV6)
+ if (mcast_addr.get_type () == AF_INET6)
+ {
+ size_t nr_unsubscribed = 0;
+# if defined(__linux__)
+
+ struct if_nameindex *intf;
+
+ intf = ACE_OS::if_nameindex ();
+
+ if (intf == 0)
+ return -1;
+
+ int index = 0;
+ while (intf[index].if_index != 0 || intf[index].if_name != 0)
+ {
+ if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(intf[index].if_name)) == 0)
+ ++nr_unsubscribed;
+
+ ++index;
+ }
+
+ ACE_OS::if_freenameindex (intf);
+
+# elif defined (ACE_WIN32)
+
+ IP_ADAPTER_ADDRESSES tmp_addrs;
+ // Initial call to determine actual memory size needed
+ DWORD dwRetVal;
+ ULONG bufLen = 0;
+ if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
+ 0,
+ 0,
+ &tmp_addrs,
+ &bufLen)) != ERROR_BUFFER_OVERFLOW)
+ return -1; // With output bufferlength 0 this can't be right.
+
+ // Get required output buffer and retrieve info for real.
+ PIP_ADAPTER_ADDRESSES pAddrs;
+ char *buf;
+ ACE_NEW_RETURN (buf,
+ char[bufLen],
+ -1);
+ pAddrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES> (buf);
+ if ((dwRetVal = ::GetAdaptersAddresses (AF_INET6,
+ 0,
+ 0,
+ pAddrs,
+ &bufLen)) != NO_ERROR)
+ {
+ delete[] buf; // clean up
+ return -1;
+ }
+
+ while (pAddrs)
+ {
+ if (this->leave (mcast_addr, ACE_TEXT_CHAR_TO_TCHAR(pAddrs->AdapterName)) == 0)
+ ++nr_unsubscribed;
+
+ pAddrs = pAddrs->Next;
+ }
+
+ delete[] buf; // clean up
+
+# endif /* ACE_WIN32 */
+
+ if (nr_unsubscribed == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ return 1;
+
+
+ }
+ else
+ {
+ // Unsubscribe on all local multicast-capable network interfaces, by
+ // doing recursive calls with specific interfaces.
+
+ ACE_INET_Addr *if_addrs = 0;
+ size_t if_cnt;
+
+ // NOTE - <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 <get_ip_interfaces> works with
+ // old versions of MSVC. The reliable way of getting the interface
+ // list is available only with MSVC 5 and newer.
+ if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
+ return -1;
+
+ size_t nr_unsubscribed = 0;
+
+ if (if_cnt < 2)
+ {
+ if (this->leave (mcast_addr,
+ ACE_TEXT ("0.0.0.0")) == 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_type () != AF_INET || if_addrs[if_cnt].is_loopback ())
+ continue;
+ if (this->leave (mcast_addr,
+ ACE_TEXT_CHAR_TO_TCHAR
+ (if_addrs[if_cnt].get_host_addr ())) == 0)
+ ++nr_unsubscribed;
+ }
+ }
+
+ delete [] if_addrs;
+
+ if (nr_unsubscribed == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ return 1;
+
+ }
+#else /* ACE_HAS_IPV6 */
+ // Unsubscribe on all local multicast-capable network interfaces, by
+ // doing recursive calls with specific interfaces.
+
+ ACE_INET_Addr *if_addrs = 0;
+ size_t if_cnt;
+
+ // NOTE - <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 <get_ip_interfaces> works with
+ // old versions of MSVC. The reliable way of getting the interface list
+ // is available only with MSVC 5 and newer.
+ if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
+ return -1;
+
+ size_t nr_unsubscribed = 0;
+
+ if (if_cnt < 2)
+ {
+ if (this->leave (mcast_addr,
+ ACE_TEXT ("0.0.0.0")) == 0)
+ ++nr_unsubscribed;
+ }
+ else
+ {
+ while (if_cnt > 0)
+ {
+ --if_cnt;
+ // Convert to 0-based for indexing, next loop check
+ if (if_addrs[if_cnt].is_loopback ())
+ continue;
+ if (this->leave (mcast_addr,
+ ACE_TEXT_CHAR_TO_TCHAR
+ (if_addrs[if_cnt].get_host_addr ())) == 0)
+ ++nr_unsubscribed;
+ }
+ }
+
+ delete [] if_addrs;
+
+ if (nr_unsubscribed == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ return 1;
+#endif /* !ACE_HAS_IPV6 */
+ }
+
+ return 0;
+}
+
+
+int
+ACE_SOCK_Dgram_Mcast::leave (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::leave");
+ // Unsubscribe.
+ int result = this->unsubscribe_i (mcast_addr,
+ net_if);
+
+#if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
+ // (Unconditionally) Remove this addr/if from subscription list.
+ // (Addr/if is removed even if unsubscribe failed)
+ ip_mreq tgt_mreq;
+ if (this->make_multicast_ifaddr (&tgt_mreq,
+ mcast_addr,
+ net_if) != -1)
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
+ this->subscription_list_lock_, -1));
+ subscription_list_iter_t iter (this->subscription_list_);
+ for (; !iter.done (); iter.advance ())
+ {
+ ip_mreq *pm = iter.next ();
+ if (ACE_SDM_helpers::is_equal (*pm, tgt_mreq))
+ {
+ iter.remove ();
+ delete pm;
+ break;
+ }
+ }
+ }
+#endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
+
+ return result >= 0 ? 0 : result;
+}
+
+// Attempt unsubscribe and return status.
+int
+ACE_SOCK_Dgram_Mcast::unsubscribe_i (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_i");
+
+ int result = this->unsubscribe_ifs (mcast_addr,
+ net_if);
+
+ // Check for error or "short-circuit" return.
+ if (result != 0)
+ return result;
+
+#if defined (ACE_HAS_IPV6)
+ if (mcast_addr.get_type () == AF_INET6)
+ {
+ // Validate addr/if specifications and create addr/if struct.
+ ipv6_mreq mreq;
+ if (this->make_multicast_ifaddr6 (&mreq, mcast_addr, net_if) == -1)
+ {
+ return -1;
+ }
+ // Tell network device driver to stop reading datagrams with the
+ // <mcast_addr>.
+ else if (ACE_SOCK::set_option (IPPROTO_IPV6,
+ IPV6_LEAVE_GROUP,
+ &mreq,
+ sizeof mreq) == -1)
+ {
+ return -1;
+ }
+
+ }
+ else // IPv4
+ {
+ // Validate addr/if specifications and create addr/if struct.
+ ip_mreq mreq;
+ if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
+ {
+ return -1;
+ }
+ // Tell network device driver to stop reading datagrams with the
+ // <mcast_addr>.
+ else if (ACE_SOCK::set_option (IPPROTO_IP,
+ IP_DROP_MEMBERSHIP,
+ &mreq,
+ sizeof mreq) == -1)
+ {
+ return -1;
+ }
+
+ }
+#else
+ // Validate addr/if specifications and create addr/if struct.
+ ip_mreq mreq;
+ if (this->make_multicast_ifaddr (&mreq, mcast_addr, net_if) == -1)
+ {
+ return -1;
+ }
+ // Tell network device driver to stop reading datagrams with the
+ // <mcast_addr>.
+ // Note, this is not IPv6 friendly...
+ else if (ACE_SOCK::set_option (IPPROTO_IP,
+ IP_DROP_MEMBERSHIP,
+ &mreq,
+ sizeof mreq) == -1)
+ {
+ return -1;
+ }
+#endif /* ACE_HAS_IPV6 */
+
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast::clear_subs_list (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::clear_subs_list");
+ int result = 0;
+
+#if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
+ ACE_MT (ACE_GUARD_RETURN (ACE_SDM_LOCK, guard,
+ this->subscription_list_lock_, -1));
+ subscription_list_iter_t iter (this->subscription_list_);
+ for (; !iter.done (); /*Hack: Do _not_ ::advance after remove*/)
+ {
+ ip_mreq *pm = iter.next ();
+ iter.remove ();
+ delete pm;
+ }
+#endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Dgram_Mcast.h b/ACE/ace/SOCK_Dgram_Mcast.h
new file mode 100644
index 00000000000..a7e668b4be0
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram_Mcast.h
@@ -0,0 +1,384 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SOCK_Dgram_Mcast.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyrali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Bill Fulton <bill_a_fulton@raytheon.com>
+ * @author Don Hinton <dhinton@objectsciences.com>
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_DGRAM_MCAST_H
+#define ACE_SOCK_DGRAM_MCAST_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+
+#if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
+# include "ace/Containers_T.h"
+# include "ace/Synch_Traits.h"
+# include "ace/Thread_Mutex.h"
+# if !defined (ACE_SDM_LOCK)
+# define ACE_SDM_LOCK ACE_SYNCH_MUTEX
+# endif /* ACE_SDM_LOCK */
+#endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SOCK_Dgram_Mcast
+ *
+ * @brief Defines the ACE socket wrapper for UDP/IP multicast.
+ *
+ * Supports multiple simultaneous subscriptions, unsubscription from one or
+ * all subscriptions, and independent send/recv address and interface
+ * specifications. Template parameters and/or ctor arguments determine
+ * per-instance optional functionality.
+ *
+ * Note that multicast semantics and implementation details are _very_
+ * environment-specific; this class is just a wrapper around the underlying
+ * implementation and does not try to normalize the concept of multicast
+ * communications.
+ *
+ * Usage Notes:
+ * - Send and Recv addresses and network interfaces, but not port#, are
+ * independent. While this instance is open, 1 send interface (and a default
+ * send address) is in effect and 0, 1, or multiple recv addresses/interfaces
+ * are in effect.
+ * - The first <open>/<subscribe> invocation defines the network interface
+ * and default address used for all sends by this instance, defines the
+ * port# and optionally the multicast address bound to the underlying
+ * socket, and defines the (one) port# that is used for all subscribes
+ * (subsequent subscribes must pass the same port# or '0').
+ * - The default loopback state is not explicitly set; the environment will
+ * determine the default state. Note that some environments (e.g. some Win32)
+ * do not allow the default to be changed, and that the semantics of
+ * loopback control are environment dependent (e.g. sender vs receiver
+ * control).
+ * - In general, due to multicast design and implementation quirks/bugs, it is
+ * difficult to tell which address a received message was sent to or which
+ * interface it was received on (even if only one subscription is active).
+ * However; there are filtering options that can be applied, to narrow it
+ * down considerably.
+ *
+ * Interface specification notes (for <subscribe> and <unsubscribe>):
+ * - If net_if == 0, the null_iface_opt option determines whether only the
+ * system "default" interface or all interfaces is affected. Specifying
+ * "all" interfaces is supported only for environments for which
+ * <ACE_Sock_Connect::get_ip_interfaces> is properly implemented.
+ * - Multiple subscriptions for the same address but different interfaces is
+ * normally supported, but re-subscription to an address/interface that is
+ * already subscribed is normally not allowed.
+ * - The <net_if> interface specification syntax is environment-specific.
+ * UNIX systems will normally use device specifications such as "le0" or
+ * "elxl1", while other systems will use the IP address of the interface.
+ * Some platforms, such as pSoS, support only cardinal numbers as network
+ * interface specifications; for these platforms, just give these numbers in
+ * alphanumeric form and <subscribe> will convert them into numbers via
+ * <ACE_OS::atoi>.
+ */
+class ACE_Export ACE_SOCK_Dgram_Mcast : public ACE_SOCK_Dgram
+{
+public:
+
+ /**
+ * @brief Option parameters.
+ *
+ * These control per-instance optional functionality. They are set via
+ * optional constructor arguments.
+ * @note Certain option values are not valid for all environments (see
+ * comments in source file for environment-specific restrictions). Default
+ * values are always valid values for the compilation environment.
+ */
+ enum options
+ {
+ // Define whether a specific (multicast) address (in addition to the port#)
+ // is bound to the socket.
+ // Notes:
+ // - Effect of doing this is stack/environment dependent, but in most
+ // environments can be used to filter out unwanted unicast, broadcast, and
+ // (other) multicast messages sent to the same port#.
+ // - Some IP stacks (e.g. some Win32) do not support binding multicast
+ // addresses. Using this option will always cause an <open> error.
+ // - It's not strictly possible for user code to do this level of filtering
+ // w/out the bind; some environments support ways to determine which address
+ // a message was sent _to_, but this class interface does not support access
+ // to that info.
+ // - The address (and port#) passed to <open> (or the first <subscribe>, if
+ // <open> is not explicitly invoked) is the one that is bound.
+ //
+ /// Disable address bind. (Bind only port.)
+ // Note that this might seem odd, but we need a way to distinquish between
+ // default behavior, which might or might not be to bind, and explicitely
+ // choosing to bind or not to bind--which "is the question." ;-)
+ OPT_BINDADDR_NO = 0,
+ /// Enable address bind. (Bind port and address.)
+ OPT_BINDADDR_YES = 1,
+ /// Default value for BINDADDR option. (Environment-dependent.)
+#if defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING) \
+ && (ACE_LACKS_PERFECT_MULTICAST_FILTERING == 1)
+ // Platforms that don't support perfect filtering. Note that perfect
+ // filtering only really applies to multicast traffic, not unicast
+ // or broadcast.
+ DEFOPT_BINDADDR = OPT_BINDADDR_YES,
+# else
+ // At least some Win32 OS's can not bind mcast addr, so disable it.
+ // General-purpose default behavior is 'disabled', since effect is
+ // environment-specific and side-effects might be surprising.
+ DEFOPT_BINDADDR = OPT_BINDADDR_NO,
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING = 1) */
+ //
+ /// Define the interpretation of 'NULL' as a recv interface specification.
+ // If the interface part of a multicast address specification is NULL, it
+ // will be interpreted to mean either "the default interface" or "all
+ // interfaces", depending on the setting of this option.
+ // Notes:
+ // - The 'nulliface_all' option can not be used in environments which do
+ // not fully support the <ACE_Sock_Connect::get_ip_interfaces> method
+ // (e.g. non-Windows).
+ // If it is, using NULL for iface will _always_ fail.
+ // - The default behavior in most IP stacks is to use the 'default' interface,
+ // where 'default' has rather ad-hoc semantics.
+ // - This applies only to receives, not sends (which always use only one
+ // interface; NULL means use the "system default" interface).
+ // Supported values:
+ /// If (net_if==NULL), use default interface.
+ // Note that this might seem odd, but we need a way to distinquish between
+ // default behavior, which might or might not be to bind, and explicitely
+ // choosing to bind or not to bind--which "is the question." ;-)
+ OPT_NULLIFACE_ONE = 0,
+ /// If (net_if==NULL), use all mcast interfaces.
+ OPT_NULLIFACE_ALL = 2,
+ /// Default value for NULLIFACE option. (Environment-dependent.)
+#ifdef ACE_WIN32
+ // This is the (ad-hoc) legacy behavior for Win32/WinSock.
+ // Notice: Older version of WinSock/MSVC may not get all multicast-capable
+ // interfaces (e.g. PPP interfaces).
+ DEFOPT_NULLIFACE = OPT_NULLIFACE_ALL,
+#else
+ // General-purpose default behavior (as per legacy behavior).
+ DEFOPT_NULLIFACE = OPT_NULLIFACE_ONE,
+#endif /* ACE_WIN32 */
+ /// All default options.
+ DEFOPTS = DEFOPT_BINDADDR | DEFOPT_NULLIFACE
+ };
+
+ // = Initialization routines.
+
+ /// Ctor - Create an unitialized instance and define per-instance optional
+ /// functionality.
+ /**
+ * You must invoke <open> or <subscribe>, to create/bind a socket and define
+ * operational parameters, before performing any I/O with this instance.
+ */
+ ACE_SOCK_Dgram_Mcast (options opts = DEFOPTS);
+
+ /// Dtor - Release all resources and implicitly or explicitly unsubscribe
+ /// from all currently subscribed groups.
+ /**
+ * The OPT_DTORUNSUB_YES_ option defines whether an explicit <unsusbcribe> is
+ * done by the destructor. If not, most systems will automatically
+ * unsubscribe upon the close of the socket.
+ */
+ ~ACE_SOCK_Dgram_Mcast (void);
+
+ /// Explicitly open/bind the socket and define the network interface
+ /// and default multicast address used for sending messages.
+ /**
+ * This method is optional; if not explicitly invoked, it is invoked by
+ * the first <subscribe>, using the subscribed address/port# and network
+ * interface paramters.
+ * The <mcast_addr> parameter defines the default send address/port# and
+ * also the port# and, if the OPT_BINDADDR_YES option is used,
+ * the multicast address that is bound to this socket.
+ * If the <send_net_if> parameter != 0, it defines the network interface
+ * used for all sends by this instance, otherwise the system "default"
+ * interface is used. (The <send_net_if> parameter is ignored if this
+ * feature is not supported by the envriornment.)
+ * The port# in <mcast_addr> may be 0, in which case a system-assigned
+ * (ephemeral) port# is used for sending and receiving.
+ * If @a reuse_addr != 0, the SO_REUSEADDR option and, if it is supported,
+ * the SO_REUSEPORT option are enabled.
+ *
+ * Returns: -1 if the call fails. Failure can occur due to problems with
+ * the address, port#, and/or interface parameters or during system open()
+ * or socket option processing.
+ */
+ int open (const ACE_INET_Addr &mcast_addr, // Bound & sendto address.
+ const ACE_TCHAR *net_if = 0, // Net interface for sends.
+ int reuse_addr = 1); // Reuse addr/port sock opt.
+
+ // = Multicast group subscribe/unsubscribe routines.
+
+ /// Join a multicast group on a given interface (or all interfaces, if
+ /// supported).
+ /**
+ * The given group is joined on the specified interface. If option
+ * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is joined on
+ * all multicast capable interfaces (IFF supported). Multiple subscriptions
+ * to various address and interface combinations are supported and tracked.
+ * If this is the first invocation of <subscribe>, and <open> was not
+ * previously invoked, <open> will be invoked using <mcast_addr> for binding
+ * the socket and <net_if> as the interface for <send>.
+ *
+ * Returns: -1 if the call fails. Failure can occur due to problems with
+ * the address, port#, and/or interface parameters or during the subscription
+ * attempt. Once bind() has been invoked (by the first <open> or
+ * <subscribe>), returns errno of ENXIO if the port# is not 0 and does not
+ * match the bound port#, or if OPT_BINDADDR_YES option is used
+ * and the address does not match the bound address. Returns errno of
+ * ENODEV if the addr/port#/interface parameters appeared valid, but no
+ * subscription(s) succeeded. An error is unconditionally returned if
+ * option OPT_NULLIFACE_ALL is used, <net_if> is NULL, and
+ * <ACE_Sock_Connect::get_ip_interfaces> is not implemented in this
+ * environment.
+ *
+ * Note that the optional @a reuse_addr parameter does not apply to
+ * subscriptions; it is only used if <open> is implicitly invoked (see above).
+ *
+ * Uses the mcast_addr to determine protocol_family, and protocol which
+ * we always pass as 0 anyway.
+ */
+ int join (const ACE_INET_Addr &mcast_addr,
+ int reuse_addr = 1, // (see above)
+ const ACE_TCHAR *net_if = 0);
+
+
+ /// Leave a multicast group on a given interface (or all interfaces, if
+ /// supported).
+ /**
+ * The specified group/interface combination is unsubscribed. If option
+ * OPT_NULLIFACE_ALL is used and <net_if> is = 0, the group is unsubscribed
+ * from all interfaces (IFF supported).
+ *
+ * Returns: -1 if the unsubscribe failed. Most environments will return -1
+ * if there was no active subscription for this address/interface combination.
+ * An error is unconditionally returned if option OPT_NULLIFACE_ALL is used,
+ * <net_if> is = 0, and <ACE_Sock_Connect::get_ip_interfaces> is not
+ * implemented in this environment (_even if_ the <subscribe> specifies a
+ * non- NULL <net_if>).
+ *
+ * leave() replaces unsubscribe() and uses mcast_addr to determine
+ * protocol_family, and protocol which we always pass as 0 anyway.
+ */
+ int leave (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if = 0);
+
+ // = Data transfer routines.
+
+ /// Send @a n bytes in @a buf, using the multicast address and network interface
+ /// defined by the first <open> or <subscribe>.
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags = 0) const;
+
+ /// Send @a n <iovecs>, using the multicast address and network interface
+ /// defined by the first <open> or <subscribe>.
+ ssize_t send (const iovec iov[],
+ int n,
+ int flags = 0) const;
+
+ // = Options.
+
+ /// Set a socket option.
+ /**
+ * 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, but only works for
+ * IPPROTO_IP or IPPROTO_IPV6 level options.
+ *
+ * Returns 0 on success, -1 on failure.
+ *
+ * @deprecated This method has been deprecated since it cannot be used
+ * easily with with IPv6 options. Use ACE_SOCK::set_option instead.
+ */
+ int set_option (int option, char optval);
+
+ /// Dump the state of an object.
+ /**
+ * Logs the setting of all options, the bound address, the send address and
+ * interface, and the list of current subscriptions.
+ */
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /// Subscribe to a multicast address on one or more network interface(s).
+ /// (No QoS support.)
+ int subscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if,
+ int reuse_addr);
+
+ /// Do subscription processing w/out updating the subscription list.
+ // (Layered method for <subscribe> processing).
+ int subscribe_i (const ACE_INET_Addr &mcast_addr,
+ int reuse_addr = 1,
+ const ACE_TCHAR *net_if = 0);
+
+ /// Unsubscribe from a multicast address on one or more network interface(s).
+ int unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if = 0);
+
+ /// Do unsubscription processing w/out udpating subscription list.
+ // (Layered method for <unsubscribe> processing).
+ int unsubscribe_i (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if = 0);
+
+protected:
+
+ /// Contains common open functionality so that inheriting classes can
+ /// reuse it.
+ int open_i (const ACE_INET_Addr &mcast_addr, // Bound & sendto address.
+ const ACE_TCHAR *net_if = 0, // Net interface for sends.
+ int reuse_addr = 1);
+
+ /// Empty the dynamic subscription list.
+ int clear_subs_list (void);
+
+private:
+
+ /// Per-instance options..
+ int opts_;
+
+ /// Multicast address to which local <send> methods send datagrams.
+ ACE_INET_Addr send_addr_;
+ /// Network interface to which all <send> methods send multicast datagrams.
+ ACE_TCHAR *send_net_if_;
+
+#if defined (ACE_SOCK_DGRAM_MCAST_DUMPABLE)
+ typedef ACE_DLList<ip_mreq> subscription_list_t;
+ typedef ACE_DLList_Iterator<ip_mreq> subscription_list_iter_t;
+ /// List of currently subscribed addr/iface pairs (and assc. types).
+ mutable subscription_list_t subscription_list_;
+ /// Lock used to protect subscription list.
+ mutable ACE_SDM_LOCK subscription_list_lock_;
+ // (Lock type does not need to support recursive locking.)
+#endif /* ACE_SOCK_DGRAM_MCAST_DUMPABLE */
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_Dgram_Mcast.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_DGRAM_MCAST_H */
diff --git a/ACE/ace/SOCK_Dgram_Mcast.inl b/ACE/ace/SOCK_Dgram_Mcast.inl
new file mode 100644
index 00000000000..bf3574cfd54
--- /dev/null
+++ b/ACE/ace/SOCK_Dgram_Mcast.inl
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_SOCK_Dgram_Mcast::set_option (int option,
+ char optval)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::set_option");
+
+ if (this->get_handle () == ACE_INVALID_HANDLE)
+ return -1;
+
+ int level = IPPROTO_IP;
+#if defined (IPPROTO_IPV6) && ! defined (INTEGRITY)
+ if (this->send_addr_.get_type () == PF_INET6)
+ level = IPPROTO_IPV6;
+#endif /* IPPROTO_IPV6 */
+
+ return this->ACE_SOCK::set_option (level,
+ option,
+ &optval,
+ sizeof (optval));
+}
+
+ACE_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->send_addr_,
+ flags);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_Dgram_Mcast::send (const iovec iov[],
+ int n,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
+ return this->ACE_SOCK_Dgram::send (iov,
+ n,
+ this->send_addr_,
+ flags);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_IO.cpp b/ACE/ace/SOCK_IO.cpp
new file mode 100644
index 00000000000..31d5db47dc6
--- /dev/null
+++ b/ACE/ace/SOCK_IO.cpp
@@ -0,0 +1,181 @@
+// $Id$
+
+#include "ace/SOCK_IO.h"
+
+#include "ace/Handle_Set.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_Memory.h"
+#include "ace/Truncate.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_IO.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK_IO, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_IO)
+
+void
+ACE_SOCK_IO::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_IO::dump");
+#endif /* ACE_HAS_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.
+ int select_width;
+# if defined (ACE_WIN32)
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles.
+ select_width = 0;
+# else
+ select_width = int (this->get_handle ()) + 1;
+# endif /* ACE_WIN32 */
+ switch (ACE_OS::select (select_width,
+ 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;
+ }
+
+ int inlen = 0;
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ FIONREAD,
+ &inlen) == -1)
+ return -1;
+ else if (inlen > 0)
+ {
+ ACE_NEW_RETURN (io_vec->iov_base,
+ char[inlen],
+ -1);
+ // It's ok to blindly cast this value since 'inlen' is an int and, thus,
+ // we can't get more than that back. Besides, if the recv() fails, we
+ // don't want that value cast to unsigned and returned.
+ ssize_t recv_len = this->recv (io_vec->iov_base, inlen);
+ if (recv_len > 0)
+ // u_long is the Windows type; size_t is everyone else's. A u_long
+ // should go into a size_t anywhere without an issue.
+ io_vec->iov_len = static_cast<u_long> (recv_len);
+ return recv_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;
+ int total_tuples = ACE_Utils::truncate_cast<int> (n / 2);
+ iovec *iovp = 0;
+#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 (int 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::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;
+ int total_tuples = ACE_Utils::truncate_cast<int> (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 (int 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::recvv (this->get_handle (),
+ iovp,
+ total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_IO.h b/ACE/ace/SOCK_IO.h
new file mode 100644
index 00000000000..6ef390e114d
--- /dev/null
+++ b/ACE/ace/SOCK_IO.h
@@ -0,0 +1,136 @@
+// -*- 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 */
+
+#include "ace/ACE.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SOCK_IO
+ *
+ * @brief Defines the methods for the ACE socket wrapper I/O routines
+ * (e.g., send/recv).
+ *
+ * If @a 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,
+ * -1 will be returned with errno == EWOULDBLOCK if no action is
+ * immediately possible.
+ * If @a timeout != 0, the call will wait until the relative time
+ * specified in *@a timeout elapses.
+ * Errors are reported by -1 and 0 return values. If the
+ * operation times out, -1 is returned with @c errno == ETIME.
+ * If it succeeds the number of bytes transferred is returned.
+ * Methods with the extra @a flags argument will always result in
+ * <send> getting called. Methods without the extra @a 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 @a 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 @a 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 @a n from the connected socket.
+ ssize_t recvv (iovec iov[],
+ int 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;
+
+ /// Recv @a n varargs messages to the connected socket.
+ ssize_t recv (size_t n,
+ ...) const;
+
+ /// Recv @a n bytes via Win32 <ReadFile> using overlapped I/O.
+ ssize_t recv (void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Send an @a 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 @a 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 @a n to the connected socket.
+ ssize_t sendv (const iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send @a n varargs messages to the connected socket.
+ ssize_t send (size_t n,
+ ...) const;
+
+ /// Send @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_IO.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SOCK_IO_H */
diff --git a/ACE/ace/SOCK_IO.inl b/ACE/ace/SOCK_IO.inl
new file mode 100644
index 00000000000..0721c33fd0d
--- /dev/null
+++ b/ACE/ace/SOCK_IO.inl
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Send an n byte message to the connected socket.
+
+ACE_INLINE
+ACE_SOCK_IO::ACE_SOCK_IO (void)
+{
+ // ACE_TRACE ("ACE_SOCK_IO::ACE_SOCK_IO");
+}
+
+ACE_INLINE
+ACE_SOCK_IO::~ACE_SOCK_IO (void)
+{
+ // ACE_TRACE ("ACE_SOCK_IO::~ACE_SOCK_IO");
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_IO::recvv (iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recvv");
+ return ACE::recvv (this->get_handle (),
+ iov,
+ n,
+ timeout);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_IO::sendv (const iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::sendv");
+ return ACE::sendv (this->get_handle (),
+ iov,
+ n,
+ timeout);
+}
+
+ACE_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 (),
+ buf,
+ n,
+ overlapped);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Netlink.cpp b/ACE/ace/SOCK_Netlink.cpp
new file mode 100644
index 00000000000..3e6566767be
--- /dev/null
+++ b/ACE/ace/SOCK_Netlink.cpp
@@ -0,0 +1,113 @@
+// $Id$
+
+#include /* */ "ace/SOCK_Netlink.h"
+
+#ifdef ACE_HAS_NETLINK
+
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/SOCK_Netlink.h"
+#include "ace/OS_NS_sys_socket.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_Netlink.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_SOCK_Netlink)
+
+int ACE_SOCK_Netlink::open (ACE_Netlink_Addr &local,
+ int protocol_family,
+ int protocol) //! protocol of your choosing
+{
+ ACE_TRACE ("ACE_SOCK_Netlink::open");
+
+ if ( ACE_SOCK::open (SOCK_RAW,
+ protocol_family, //! RAW or DGRAM valid
+ protocol,0) < 0 ) {
+ ACE_TRACE ("ACE_SOCK_Netlink::open failed to open");
+ return -1;
+ }
+
+ if (ACE_OS::bind(this->get_handle(),
+ (sockaddr*)local.get_addr(),
+ local.get_addr_size()) == -1 ) {
+ ACE_TRACE ("ACE_SOCK_Netlink::open failed to bind socket");
+ return -1;
+ }
+ return 0;
+}
+
+
+ACE_SOCK_Netlink::ACE_SOCK_Netlink (ACE_Netlink_Addr &local,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Netlink::ACE_SOCK_Netlink");
+
+ if (this->open (local,
+ protocol_family,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_Netlink")));
+}
+
+ssize_t
+ACE_SOCK_Netlink::send (const iovec iov[],
+ int n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Netlink::send");
+ msghdr send_msg;
+
+ send_msg.msg_iov = (iovec *) iov;
+ send_msg.msg_iovlen = n;
+ send_msg.msg_name = (char *) addr.get_addr ();
+ send_msg.msg_namelen = addr.get_size ();
+ send_msg.msg_control = 0;
+ send_msg.msg_controllen = 0;
+ send_msg.msg_flags = 0;
+
+ return ACE_OS::sendmsg (this->get_handle (),
+ &send_msg,
+ flags);
+}
+
+ssize_t
+ACE_SOCK_Netlink::recv (iovec iov[],
+ int n,
+ ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Netlink::recv");
+ msghdr recv_msg;
+
+ recv_msg.msg_iov = (iovec *) iov;
+ recv_msg.msg_iovlen = n;
+ recv_msg.msg_name = (char *) addr.get_addr ();
+ recv_msg.msg_namelen = addr.get_size ();
+ recv_msg.msg_control = 0;
+ recv_msg.msg_controllen = 0;
+ recv_msg.msg_flags = 0;
+
+ ssize_t status = ACE_OS::recvmsg (this->get_handle (),
+ &recv_msg,
+ flags);
+
+ if (recv_msg.msg_flags & MSG_TRUNC)
+ return -1;
+
+ addr.set_size (recv_msg.msg_namelen);
+ addr.set_type (((sockaddr_in *) addr.get_addr())->sin_family);
+
+ return status;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_NETLINK */
diff --git a/ACE/ace/SOCK_Netlink.h b/ACE/ace/SOCK_Netlink.h
new file mode 100644
index 00000000000..f4e4a31748a
--- /dev/null
+++ b/ACE/ace/SOCK_Netlink.h
@@ -0,0 +1,106 @@
+// $Id$
+//=============================================================================
+/**
+ * @file SOCK_Netlink.h
+ *
+ * $Id$
+ *
+ * @author Robert Iakobashvilli <coroberti@gmail.com>
+ * @author Raz Ben Yehuda <raziebe@013.net.il>
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_NETLINK_H
+#define ACE_SOCK_NETLINK_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+ #pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#ifdef ACE_HAS_NETLINK
+
+#include "ace/SOCK.h"
+#include "ace/Netlink_Addr.h"
+#include "ace/Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SOCK_Netlink
+ *
+ * @brief Defines the member functions for the ACE_SOCK Netlink
+ * abstraction.
+
+ * Netlink sockets are used in Linux as a communication facilty of kernel to user
+ * and user to kernel.
+ * This code was created so one could use ACE reactor
+ * as a gateway to a linux kernel.
+ *
+ */
+class ACE_Export ACE_SOCK_Netlink : public ACE_SOCK {
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SOCK_Netlink(void);
+ ~ACE_SOCK_Netlink(void);
+ ACE_SOCK_Netlink (ACE_Netlink_Addr &local,
+ int protocol_family,
+ int protocol);
+ /**
+ * opens a RAW socket over an ACE_SOCK and binds it
+ *
+ **/
+ int open (ACE_Netlink_Addr &local,
+ int protocol_family,
+ int protocol);
+
+ /**
+ * receives abuffer with the size n
+ */
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags) const;
+ /**
+ * send a buffer of size n bytes
+ *
+ */
+ ssize_t send (void *buf,
+ size_t n,
+ int flags) const;
+
+ /**
+ * Recieves an iovec of size @a n to the netlink socket
+ */
+ ssize_t recv (iovec iov[],
+ int n,
+ ACE_Addr &addr,
+ int flags = 0) const;
+
+ /**
+ * Sends an iovec of size @a n to the netlink socket
+ */
+ ssize_t send (const iovec iov[],
+ int n,
+ const ACE_Addr &addr,
+ int flags = 0) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_Netlink.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_NETLINK */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SOCK_NETLINK_H */
+
diff --git a/ACE/ace/SOCK_Netlink.inl b/ACE/ace/SOCK_Netlink.inl
new file mode 100644
index 00000000000..bf97d6f2dc5
--- /dev/null
+++ b/ACE/ace/SOCK_Netlink.inl
@@ -0,0 +1,37 @@
+// $Id$
+
+#ifdef ACE_HAS_NETLINK
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SOCK_Netlink::ACE_SOCK_Netlink (void)
+{
+ ACE_TRACE ("ACE_SOCK_Netlink::ACE_SOCK_Netlink");
+}
+
+ACE_INLINE
+ACE_SOCK_Netlink::~ACE_SOCK_Netlink (void)
+{
+ ACE_TRACE ("ACE_SOCK_Netlink::~ACE_SOCK_Netlink");
+}
+
+ACE_INLINE ssize_t ACE_SOCK_Netlink::recv ( void *buf,
+ size_t n,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Netlink::recv");
+ return ACE_OS::recv (this->get_handle (),(char *) buf,n,flags);
+}
+
+ACE_INLINE ssize_t ACE_SOCK_Netlink::send (void *buf,
+ size_t n,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Netlink::send");
+ return ACE_OS::send (this->get_handle (),(char *) buf,n,flags);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_NETLINK */
diff --git a/ACE/ace/SOCK_SEQPACK_Acceptor.cpp b/ACE/ace/SOCK_SEQPACK_Acceptor.cpp
new file mode 100644
index 00000000000..2a4664b1609
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Acceptor.cpp
@@ -0,0 +1,596 @@
+// $Id$
+
+#include "ace/SOCK_SEQPACK_Acceptor.h"
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/os_include/os_fcntl.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_SEQPACK_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK_SEQPACK_Acceptor, "SOCK_SEQPACK_Acceptor.cpp,v 4.30 2002/03/08 23:18:09 spark Exp")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_SEQPACK_Acceptor)
+
+// Do nothing routine for constructor.
+
+ACE_SOCK_SEQPACK_Acceptor::ACE_SOCK_SEQPACK_Acceptor (void)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Acceptor::ACE_SOCK_SEQPACK_Acceptor");
+}
+
+// Performs the timed accept operation.
+
+int
+ACE_SOCK_SEQPACK_Acceptor::shared_accept_start (ACE_Time_Value *timeout,
+ int restart,
+ int &in_blocking_mode) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_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_SEQPACK_Acceptor::shared_accept_finish (ACE_SOCK_SEQPACK_Association new_association,
+ int in_blocking_mode,
+ int reset_new_handle) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Acceptor::shared_accept_finish ()");
+
+ ACE_HANDLE new_handle = new_association.get_handle ();
+
+ // Check to see if we were originally in blocking mode, and if so,
+ // set the <new_association>'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_SEQPACK_Acceptor::accept (ACE_SOCK_SEQPACK_Association &new_association,
+ ACE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_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_association.set_handle (ACE_OS::accept (this->get_handle (),
+ addr,
+ len_ptr));
+ while (new_association.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_association.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_association,
+ in_blocking_mode,
+ reset_new_handle);
+}
+
+void
+ACE_SOCK_SEQPACK_Acceptor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Acceptor::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_SOCK_SEQPACK_Acceptor::shared_open (const ACE_Addr &local_sap,
+ int protocol_family,
+ int backlog)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_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 (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 = *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 (),
+ 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 (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 = *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 (),
+ 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;
+}
+
+// Multihomed version of same.
+
+int
+ACE_SOCK_SEQPACK_Acceptor::shared_open (const ACE_Multihomed_INET_Addr &local_sap,
+ int protocol_family,
+ int backlog)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Acceptor::shared_open");
+ int error = 0;
+
+ // TODO: Add multi-address support to IPV6
+#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 (reinterpret_cast<void *> (&local_inet6_addr),
+ 0,
+ sizeof local_inet6_addr);
+
+ if (local_sap.ACE_Addr::operator== (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 = *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 (),
+ 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 (reinterpret_cast<void *> (&local_inet_addr),
+ 0,
+ sizeof local_inet_addr);
+
+ if (local_sap.ACE_Addr::operator== (ACE_Addr::sap_any))
+ {
+ local_inet_addr.sin_port = 0;
+ }
+ else
+ local_inet_addr = *reinterpret_cast<sockaddr_in *> (local_sap.get_addr ());
+
+// A port number of 0 means that the user is requesting that the
+// operating system choose an arbitrary, unused port. Since some
+// operating systems don't provide this service, ACE provides an
+// emulation layer. Therefore, the "ACE way" to bind an arbitrary,
+// unused port is to call ACE:bind_port, which either
+//
+// (1) Calls ACE_OS::bind with port 0, if the operating system
+// directly supports the automated selection, or
+//
+// (2) Performs more complicated logic to emulate this feature if
+// it's missing from the OS.
+//
+// The emulation logic in choice (2) is compiled if and only if
+// ACE_LACKS_WILDCARD_BIND is defined at compile time.
+//
+// Along these lines, the following block of code seems like it would
+// be sufficient to support the wildcard bind operation:
+//
+// if (local_inet_addr.sin_port == 0)
+// {
+// if (ACE::bind_port (this->get_handle (),
+// ACE_NTOHL (ACE_UINT32 (local_inet_addr.sin_addr.s_addr))) == -1)
+// error = 1;
+//
+// }
+// else
+//
+// Unfortunately, this code is insufficient because it does not
+// address the possibility of secondary addresses.
+//
+// However, rather than writing the correct code now, I'm putting it
+// off, because this class, ACE_SOCK_SEQPACK_Acceptor, is currently
+// only used with SCTP, and ACE currently supports SCTP only through
+// the OpenSS7 and LKSCTP implmentations, which are available only on
+// Linux. Linux has native support for the wildcard bind, so the
+// following code works regardless of whether or not the port is 0.
+
+ {
+ // The total number of addresses is the number of secondary
+ // addresses plus one.
+ size_t num_addresses = local_sap.get_num_secondary_addresses() + 1;
+
+ // Create an array of sockaddr_in to hold the underlying
+ // representations of the primary and secondary
+ // addresses.
+ sockaddr_in* local_inet_addrs = 0;
+ ACE_NEW_NORETURN (local_inet_addrs,
+ sockaddr_in[num_addresses]);
+
+ if (!local_inet_addrs)
+ error = 1;
+ else
+ {
+ // Populate the array by invoking the get_addresses method
+ // on the Multihomed_INET_Addr
+ local_sap.get_addresses(local_inet_addrs,
+ num_addresses);
+
+#if defined (ACE_HAS_LKSCTP)
+
+ sockaddr_in *local_sockaddr = 0;
+
+ // bind the primary first
+ if (ACE_OS::bind (this->get_handle (),
+ reinterpret_cast<sockaddr *> (&(local_inet_addrs[0])),
+ sizeof(sockaddr)) == -1)
+ {
+ error = 1;
+ }
+
+ // do we need to bind multiple addresses?
+ if (num_addresses > 1)
+ {
+ ACE_NEW_NORETURN(local_sockaddr,
+ sockaddr_in[num_addresses - 1]);
+
+ // all of the secondary addresses need the local port set
+ for (size_t i = 1; i < num_addresses; i++)
+ {
+ local_inet_addrs[i].sin_port = local_inet_addrs[0].sin_port;
+ }
+
+ // copy only the sockaddrs that we need to bindx
+ for (size_t i = 0; i < num_addresses - 1; i++)
+ {
+ ACE_OS::memcpy(&(local_sockaddr[i]),
+ &(local_inet_addrs[i + 1]),
+ sizeof(sockaddr_in));
+ }
+
+ // now call bindx
+ if (!error && sctp_bindx(this->get_handle (),
+ reinterpret_cast<sockaddr *> (local_sockaddr),
+ num_addresses - 1,
+ SCTP_BINDX_ADD_ADDR))
+ {
+ error = 1;
+ }
+
+ delete [] local_sockaddr;
+ }
+#else
+ // Call bind
+ size_t name_len = (sizeof local_inet_addr) * num_addresses;
+ if (ACE_OS::bind (this->get_handle (),
+ reinterpret_cast<sockaddr *> (local_inet_addrs),
+ static_cast<int> (name_len)) == -1)
+ error = 1;
+#endif /* ACE_HAS_LKSCTP */
+ }
+
+ delete [] local_inet_addrs;
+ }
+ }
+ 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_SEQPACK_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_SEQPACK_Acceptor::open");
+
+ if (protocol_family == PF_UNSPEC)
+ protocol_family = local_sap.get_type ();
+
+#if defined (ACE_HAS_LKSCTP)
+ if (ACE_SOCK::open (SOCK_STREAM,
+#else
+ if (ACE_SOCK::open (SOCK_SEQPACKET,
+#endif
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return this->shared_open (local_sap,
+ protocol_family,
+ backlog);
+}
+
+ACE_SOCK_SEQPACK_Acceptor::ACE_SOCK_SEQPACK_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_SEQPACK_Acceptor::ACE_SOCK_SEQPACK_Acceptor");
+ if (this->open (local_sap,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_SEQPACK_Acceptor")));
+}
+
+// General purpose routine for performing server ACE_SOCK creation.
+
+int
+ACE_SOCK_SEQPACK_Acceptor::open (const ACE_Addr &local_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_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::ipv6_enabled () ? PF_INET6 : PF_INET;
+#else
+ protocol_family = PF_INET;
+#endif /* ACE_HAS_IPV6 */
+ }
+
+#if defined (ACE_HAS_LKSCTP)
+ if (ACE_SOCK::open (SOCK_STREAM,
+#else
+ if (ACE_SOCK::open (SOCK_SEQPACKET,
+#endif
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return this->shared_open (local_sap,
+ protocol_family,
+ backlog);
+}
+
+// Multihomed version of same.
+
+int
+ACE_SOCK_SEQPACK_Acceptor::open (const ACE_Multihomed_INET_Addr &local_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Acceptor::open");
+
+ if (local_sap.ACE_Addr::operator!= (ACE_Addr::sap_any))
+ protocol_family = local_sap.get_type ();
+ else if (protocol_family == PF_UNSPEC)
+ {
+#if defined (ACE_HAS_IPV6)
+ protocol_family = ACE::ipv6_enabled () ? PF_INET6 : PF_INET;
+#else
+ protocol_family = PF_INET;
+#endif /* ACE_HAS_IPV6 */
+ }
+
+#if defined (ACE_HAS_LKSCTP)
+ if (ACE_SOCK::open (SOCK_STREAM,
+#else
+ if (ACE_SOCK::open (SOCK_SEQPACKET,
+#endif
+ 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_SEQPACK_Acceptor::ACE_SOCK_SEQPACK_Acceptor (const ACE_Addr &local_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Acceptor::ACE_SOCK_SEQPACK_Acceptor");
+ if (this->open (local_sap,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_SEQPACK_Acceptor")));
+}
+
+// Multihomed version of same.
+
+ACE_SOCK_SEQPACK_Acceptor::ACE_SOCK_SEQPACK_Acceptor (const ACE_Multihomed_INET_Addr &local_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Acceptor::ACE_SOCK_SEQPACK_Acceptor");
+ if (this->open (local_sap,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_SEQPACK_Acceptor")));
+}
+
+int
+ACE_SOCK_SEQPACK_Acceptor::close (void)
+{
+ return ACE_SOCK::close ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_SEQPACK_Acceptor.h b/ACE/ace/SOCK_SEQPACK_Acceptor.h
new file mode 100644
index 00000000000..0d5501dd204
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Acceptor.h
@@ -0,0 +1,190 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SOCK_SEQPACK_Acceptor.h
+ *
+ * $Id$
+ * @author Patrick J. Lardieri <plardier@atl.lmco.com>
+ * @author Gaurav Naik, Lockheed Martin ATL
+ * @author based on SOCK_STREAM_Acceptor
+ * by Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_SEQ_ACCEPTOR_H
+#define ACE_SOCK_SEQ_ACCEPTOR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_SEQPACK_Association.h"
+#include "ace/Multihomed_INET_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_SOCK_SEQPACK_Acceptor
+ *
+ * @brief Defines a factory that creates new ACE_Associations passively.
+ *
+ * The <ACE_SOCK_SEQPACK_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_SEQPACK_Association encapsulates.
+ * Therefore, by inheriting from <ACE_SOCK>, <ACE_SOCK_SEQPACK_Acceptor>
+ * gets its very own socket.
+ */
+class ACE_Export ACE_SOCK_SEQPACK_Acceptor : public ACE_SOCK
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SOCK_SEQPACK_Acceptor (void);
+
+ /**
+ * Initialize a passive-mode BSD-style acceptor socket (no QoS).
+ * @a local_sap is the address that we're going to listen for
+ * connections on. If @a reuse_addr is 1 then we'll use the
+ * @c SO_REUSEADDR to reuse this address.
+ */
+ ACE_SOCK_SEQPACK_Acceptor (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 132);
+
+ /// Multihomed version of same
+
+ ACE_SOCK_SEQPACK_Acceptor (const ACE_Multihomed_INET_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 132);
+
+ /// Initialize a passive-mode QoS-enabled acceptor socket. Returns 0
+ /// on success and -1 on failure.
+ ACE_SOCK_SEQPACK_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 = 132);
+
+
+ /**
+ * Initialize a passive-mode BSD-style acceptor socket (no QoS).
+ * @a local_sap is the address that we're going to listen for
+ * connections on. If @a reuse_addr is 1 then we'll use the
+ * @c 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 = 132);
+
+ /// Multihomed version of same
+
+ int open (const ACE_Multihomed_INET_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 132);
+
+
+ /// 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 = 132);
+
+ /// Close the socket. Returns 0 on success and -1 on failure.
+ int close (void);
+
+ /// Default dtor.
+ ~ACE_SOCK_SEQPACK_Acceptor (void);
+
+ // = Passive connection <accept> methods.
+ /**
+ * Accept a new ACE_SOCK_SEQPACK_Association connection. A @a timeout of 0
+ * means block forever, a @a timeout of {0, 0} means poll. <restart>
+ * == 1 means "restart if interrupted," i.e., if errno == EINTR.
+ * Note that <new_association> inherits the "blocking mode" of @c this
+ * <ACE_SOCK_SEQPACK_Acceptor>, i.e., if @c this acceptor factory is in
+ * non-blocking mode, the <net_association> will be in non-blocking mode
+ * and vice versa.
+ */
+ int accept (ACE_SOCK_SEQPACK_Association &new_association,
+ ACE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0) const;
+
+ // = Meta-type info
+ typedef ACE_Multihomed_INET_Addr PEER_ADDR;
+ typedef ACE_SOCK_SEQPACK_Association 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_SEQPACK_Association new_association,
+ 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);
+
+ /// Multihomed version of same.
+
+ int shared_open (const ACE_Multihomed_INET_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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_SEQPACK_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SOCK_SEQ_ACCEPTOR_H */
diff --git a/ACE/ace/SOCK_SEQPACK_Acceptor.inl b/ACE/ace/SOCK_SEQPACK_Acceptor.inl
new file mode 100644
index 00000000000..0a0b591d75f
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Acceptor.inl
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SOCK_SEQPACK_Acceptor::~ACE_SOCK_SEQPACK_Acceptor (void)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Acceptor::~ACE_SOCK_SEQPACK_Acceptor");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_SEQPACK_Association.cpp b/ACE/ace/SOCK_SEQPACK_Association.cpp
new file mode 100644
index 00000000000..9a17e0ddb33
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Association.cpp
@@ -0,0 +1,339 @@
+// $Id$
+
+#include "ace/SOCK_SEQPACK_Association.h"
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_SEQPACK_Association.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK_SEQPACK_Association, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_SEQPACK_Association)
+
+void
+ACE_SOCK_SEQPACK_Association::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_SOCK_SEQPACK_Association::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 ();
+}
+
+// Developed according to the API discussed in 7.1.4 of
+// draft-ietf-tsvwg-sctpsocket-09.txt to abruptly free a transport
+// transport association's resources.
+int
+ACE_SOCK_SEQPACK_Association::abort (void)
+{
+ //
+ // setsockopt() SO_LINGER configures socket to reap immediately.
+ // Normal close then aborts the association.
+ //
+ linger slinger;
+
+ slinger.l_onoff = 1;
+ slinger.l_linger = 0;
+
+ if (-1 == ACE_OS::setsockopt (this->get_handle (),
+ SOL_SOCKET,
+ SO_LINGER,
+ reinterpret_cast<const char *> (&slinger),
+ sizeof (linger)))
+ {
+ return -1;
+ }
+
+ return this->close ();
+}
+
+int
+ACE_SOCK_SEQPACK_Association::get_local_addrs (ACE_INET_Addr *addrs, size_t &size) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::get_local_addrs");
+
+#if defined (ACE_HAS_LKSCTP)
+ /*
+ The size of ACE_INET_Addr must be large enough to hold the number of
+ local addresses on the machine. If the array is too small, the function
+ will only return the number of addresses that will fit. If the array is
+ too large, the 'size' parameter will be modified to indicate the number
+ of addrs.
+
+ We will call sctp_getladdrs() which accepts 3 parameters
+ 1. a socket fd
+ 2. a sctp association_id which will be ignored since we are using
+ tcp sockets
+ 3. a pointer to sockaddr
+
+ lksctp/draft will allocate memory and we are responsible for freeing
+ it by calling sctp_freeladdrs().
+ */
+
+ sockaddr_in *si = 0;
+ sockaddr *laddrs = 0;
+ int err = 0;
+ size_t len = 0;
+
+ err = sctp_getladdrs(this->get_handle(), 0, &laddrs);
+ if (err > 0)
+ {
+ len = err;
+ // check to see if we have more addresses than we have
+ // space in our ACE_INET_Addr array
+ if (len > size)
+ {
+ // since our array is too small, we will only copy the first
+ // few that fit
+ len = size;
+ }
+
+ for (size_t i = 0; i < len; i++)
+ {
+ // first we cast the sockaddr to sockaddr_in
+ // since we only support ipv4 at this time.
+ si = (sockaddr_in *) (&(laddrs[i]));
+
+ // now we fillup the ace_inet_addr array
+ addrs[i].set_addr(si, sizeof(sockaddr_in));
+ addrs[i].set_type(si->sin_family);
+ addrs[i].set_size(sizeof(sockaddr_in));
+ }
+ }
+ else /* err < 0 */
+ {
+ // sctp_getladdrs will return -1 on error
+ return -1;
+ }
+
+ // indicate the num of addrs returned to the calling function
+ size = len;
+
+ // make sure we free the struct using the system function
+ sctp_freeladdrs(laddrs);
+
+#else
+
+ /*
+ We will be calling ACE_OS::getsockname, which accepts (and
+ potentially modifies) two reference parameters:
+
+ 1. a sockaddr_in* that points to a buffer
+ 2. an int* that points to the size of this buffer
+
+ The OpenSS7 implementation of SCTP copies an array of ipv4
+ sockaddr_in into the buffer. Then, if the size of the buffer is
+ greater than the size used, the size parameter is reduced
+ accordingly.
+
+ */
+
+ // The array of sockaddr_in will be stored in an ACE_Auto_Array_Ptr,
+ // which causes dynamically-allocated memory to be released as soon
+ // as the ACE_Auto_Array_Ptr goes out of scope.
+ ACE_Auto_Array_Ptr<sockaddr_in> addr_structs;
+
+ // Allocate memory for this array. Return -1 if the memory cannot
+ // be allocated. (This activity requires a temporary variable---a
+ // bare sockaddr_in* --- because ACE_NEW_RETURN cannot act directory on
+ // an ACE_Auto_Array_Ptr.)
+ {
+ sockaddr_in *addr_structs_bootstrap = 0;
+ ACE_NEW_RETURN (addr_structs_bootstrap, sockaddr_in[size], -1);
+ addr_structs.reset(addr_structs_bootstrap);
+ }
+
+ // Physical size of this array is its logical size multiplied by
+ // the physical size of one of its elements.
+ size_t physical_size = size * sizeof(sockaddr_in);
+
+ /* Clear the array */
+ ACE_OS::memset(addr_structs.get(),
+ 0,
+ physical_size);
+
+ /*
+ ** Populate the array with real values from the getsockname system
+ ** call. addr_structs is modified, and name_size is modified to contain
+ ** the number of bytes written to addr_structs.
+ ** Use name_size to get the data types right across the call.
+ */
+ int name_size = static_cast<int> (physical_size);
+ if (ACE_OS::getsockname (this->get_handle (),
+ reinterpret_cast<sockaddr *> (addr_structs.get()),
+ &name_size) == -1)
+ return -1;
+
+ /* Calculate the NEW physical size of the array */
+ name_size /= sizeof (sockaddr_in);
+ size = static_cast<size_t> (name_size);
+
+ /* Copy each sockaddr_in to the address structure of an ACE_Addr from
+ the passed-in array */
+ const int addrlen (static_cast<int> (sizeof (sockaddr_in)));
+ for (int i = 0; i < name_size; ++i)
+ {
+ addrs[i].set_addr (&(addr_structs[i]), addrlen);
+ addrs[i].set_type (addr_structs[i].sin_family);
+ addrs[i].set_size (addrlen);
+ }
+#endif /* ACE_HAS_LKSCTP */
+ return 0;
+}
+
+
+int
+ACE_SOCK_SEQPACK_Association::get_remote_addrs (ACE_INET_Addr *addrs, size_t &size) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::get_remote_addrs");
+#if defined (ACE_HAS_LKSCTP)
+ /*
+ The size of ACE_INET_Addr must be large enough to hold the number of
+ remotes addresses in the association. If the array is too small, the
+ function will only return the number of addresses that will fit. If the
+ array is too large, the 'size' parameter will be modified to indicate
+ the number of addrs.
+
+ We will call sctp_getpaddrs() which accepts 3 parameters
+ 1. a socket fd
+ 2. a sctp association_id which will be ignored since we are using
+ tcp sockets
+ 3. a pointer to a sockaddr
+
+ lksctp/draft will allocate memory and we are responsible for freeing
+ it by calling sctp_freepaddrs().
+ */
+
+ sockaddr_in *si = 0;
+ sockaddr *paddrs = 0;
+ int err = 0;
+ size_t len = 0;
+
+ err = sctp_getpaddrs(this->get_handle(), 0, &paddrs);
+ if (err > 0)
+ {
+ len = err;
+ // check to see if we have more addresses than we have
+ // space in our ACE_INET_Addr array
+ if (len > size)
+ {
+ // since our array is too small, we will only copy the first
+ // few that fit
+ len = size;
+ }
+
+ for (size_t i = 0; i < len; i++)
+ {
+ // first we cast the sockaddr to sockaddr_in
+ // since we only support ipv4 at this time.
+ si = (sockaddr_in *) (&(paddrs[i]));
+
+ // now we fillup the ace_inet_addr array
+ addrs[i].set_addr(si, sizeof(sockaddr_in));
+ addrs[i].set_type(si->sin_family);
+ addrs[i].set_size(sizeof(sockaddr_in));
+ }
+ }
+ else /* err < 0 */
+ {
+ // sctp_getpaddrs will return -1 on error
+ return -1;
+ }
+
+ // indicate the num of addrs returned to the calling function
+ size = len;
+
+ // make sure we free the struct using the system function
+ sctp_freepaddrs(paddrs);
+
+#else
+
+ /*
+ We will be calling ACE_OS::getpeername, which accepts (and
+ potentially modifies) two reference parameters:
+
+ 1. a sockaddr_in* that points to a buffer
+ 2. an int* that points to the size of this buffer
+
+ The OpenSS7 implementation of SCTP copies an array of ipv4
+ sockaddr_in into the buffer. Then, if the size of the buffer is
+ greater than the size used, the size parameter is reduced
+ accordingly.
+
+ */
+
+ // The array of sockaddr_in will be stored in an ACE_Auto_Array_Ptr,
+ // which causes dynamically-allocated memory to be released as soon
+ // as the ACE_Auto_Array_Ptr goes out of scope.
+ ACE_Auto_Array_Ptr<sockaddr_in> addr_structs;
+
+ // Allocate memory for this array. Return -1 if the memory cannot
+ // be allocated. (This activity requires a temporary variable---a
+ // bare sockaddr_in* --- because ACE_NEW_RETURN cannot act directory on
+ // an ACE_Auto_Array_Ptr.)
+ {
+ sockaddr_in *addr_structs_bootstrap = 0;
+ ACE_NEW_RETURN (addr_structs_bootstrap, sockaddr_in[size], -1);
+ addr_structs.reset(addr_structs_bootstrap);
+ }
+
+ // Physical size of this array is its logical size multiplied by
+ // the physical size of one of its elements.
+ size_t physical_size = size * sizeof(sockaddr_in);
+
+ /* Clear the array */
+ ACE_OS::memset(addr_structs.get(),
+ 0,
+ physical_size);
+
+ /*
+ ** Populate the array with real values from the getpeername system
+ ** call. addr_structs is modified, and name_size is modified to contain
+ ** the number of bytes written to addr_structs.
+ ** Use name_size to get the data types right across the call.
+ */
+ int name_size = static_cast<int> (physical_size);
+ if (ACE_OS::getpeername (this->get_handle (),
+ reinterpret_cast<sockaddr *> (addr_structs.get()),
+ &name_size) == -1)
+ return -1;
+
+ /* Calculate the NEW physical size of the array */
+ name_size /= sizeof (sockaddr_in);
+ size = static_cast<size_t> (name_size);
+
+ /* Copy each sockaddr_in to the address structure of an ACE_Addr from
+ the passed-in array */
+ const int addrlen (static_cast<int> (sizeof (sockaddr_in)));
+ for (int i = 0; i < name_size; ++i)
+ {
+ addrs[i].set_addr (&(addr_structs[i]), addrlen);
+ addrs[i].set_type (addr_structs[i].sin_family);
+ addrs[i].set_size (addrlen);
+ }
+#endif /* ACE_HAS_LKSCTP */
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_SEQPACK_Association.h b/ACE/ace/SOCK_SEQPACK_Association.h
new file mode 100644
index 00000000000..beb211fa292
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Association.h
@@ -0,0 +1,202 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ *
+ * @file SOCK_SEQPACK_Association.h
+ *
+ * $Id$
+ *
+ * @author Patrick J. Lardieri <plardier@atl.lmco.com>
+ * @author Gaurav Naik, Lockheed Martin ATL
+ * @author based on SOCK_Stream
+ * by Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_SEQPACK_ASSOCIATION_H
+#define ACE_SOCK_SEQPACK_ASSOCIATION_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_IO.h"
+#include "ace/Multihomed_INET_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+class ACE_Message_Block;
+
+/**
+ * @class ACE_SOCK_SEQPACK_Association
+ *
+ * @brief Defines the methods in the ACE_SOCK_SEQPACK_Association abstraction.
+ *
+ * This adds additional wrapper methods atop the <ACE_SOCK_IO>
+ * class.
+ *
+ * @a buf is the buffer to write from or receive into.
+ * @a len is the number of bytes to transfer.
+ * The @a timeout parameter in the following methods indicates how
+ * long to blocking trying to transfer data. If @a 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 @a timeout != 0, the call will wait for data to arrive no longer
+ * than the relative time specified in *@a 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. @a 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 @a flags argument will always result in
+ * <send> getting called. Methods without the extra @a flags argument
+ * will result in <send> getting called on Win32 platforms, and
+ * <write> getting called on non-Win32 platforms.
+ */
+class ACE_Export ACE_SOCK_SEQPACK_Association : public ACE_SOCK_IO
+{
+public:
+ // Initialization and termination methods.
+ /// Constructor.
+ ACE_SOCK_SEQPACK_Association (void);
+
+ /// Constructor (sets the underlying ACE_HANDLE with <h>).
+ ACE_SOCK_SEQPACK_Association (ACE_HANDLE h);
+
+ /// Destructor.
+ ~ACE_SOCK_SEQPACK_Association (void);
+
+ /**
+ * Return local endpoint addresses in the referenced array of
+ * ACE_INET_Addr, which should have the specified @a size. If the
+ * number of local endpoint addresses is less than @a size, then
+ * @a size will be set to this number. If successful, the method
+ * returns 0, otherwise returns -1.
+ */
+ int get_local_addrs (ACE_INET_Addr *addrs, size_t &size) const;
+
+ /**
+ * Return remote endpoint addresses in the referenced array of
+ * ACE_INET_Addr, which should have the specified @a size. If the
+ * number of remote endpoint addresses is less than @a size, then
+ * @a size will be set to this number. If successful, the method
+ * returns 0, otherwise returns -1.
+ */
+ int get_remote_addrs (ACE_INET_Addr *addrs, size_t &size) const;
+
+ // = I/O functions.
+
+ /// Try to recv exactly @a len bytes into @a 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 @a len bytes into @a 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[],
+ int iovcnt,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Try to send exactly @a len bytes from @a 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 @a len bytes from @a 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 @a message_blocks 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[],
+ int 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);
+
+ /**
+ * Abort the association according to RFC 2960 9.1 through the API
+ * in draft-ietf-tsvwg-sctpsocket-09 7.1.4.
+ */
+ int abort (void);
+
+ // = Meta-type info
+ typedef ACE_Multihomed_INET_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_SEQPACK_Association.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SOCK_SEQPACK_ASSOCIATION_H */
diff --git a/ACE/ace/SOCK_SEQPACK_Association.inl b/ACE/ace/SOCK_SEQPACK_Association.inl
new file mode 100644
index 00000000000..a156a946257
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Association.inl
@@ -0,0 +1,177 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/SOCK_SEQPACK_Association.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SOCK_SEQPACK_Association::ACE_SOCK_SEQPACK_Association (void)
+{
+ // ACE_TRACE ("ACE_SOCK_SEQPACK_Association::ACE_SOCK_SEQPACK_Association");
+}
+
+ACE_INLINE
+ACE_SOCK_SEQPACK_Association::ACE_SOCK_SEQPACK_Association (ACE_HANDLE h)
+{
+ // ACE_TRACE ("ACE_SOCK_SEQPACK_Association::ACE_SOCK_SEQPACK_Association");
+ this->set_handle (h);
+}
+
+ACE_INLINE
+ACE_SOCK_SEQPACK_Association::~ACE_SOCK_SEQPACK_Association (void)
+{
+ // ACE_TRACE ("ACE_SOCK_SEQPACK_Association::~ACE_SOCK_SEQPACK_Association");
+}
+
+ACE_INLINE int
+ACE_SOCK_SEQPACK_Association::close_reader (void)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::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.
+
+ACE_INLINE int
+ACE_SOCK_SEQPACK_Association::close_writer (void)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::close_writer");
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ return ACE_OS::shutdown (this->get_handle (), ACE_SHUTDOWN_WRITE);
+ else
+ return 0;
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::recv_n (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::recv_n");
+ return ACE::recv_n (this->get_handle (),
+ buf,
+ len,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::recv_n (void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::recv_n");
+ return ACE::recv_n (this->get_handle (),
+ buf,
+ len,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::recvv_n (iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::recvv_n");
+ return ACE::recvv_n (this->get_handle (),
+ iov,
+ n,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::send_n (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::send_n");
+ return ACE::send_n (this->get_handle (),
+ buf,
+ len,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::send_n (const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::send_n");
+ return ACE::send_n (this->get_handle (),
+ buf,
+ len,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::sendv_n (const iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::sendv_n");
+ return ACE::sendv_n (this->get_handle (),
+ iov,
+ n,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::send_n (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::send_n");
+ return ACE::send_n (this->get_handle (),
+ message_block,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::send_urg (const void *ptr,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::send_urg");
+ return ACE::send (this->get_handle (),
+ ptr,
+ len,
+ MSG_OOB,
+ timeout);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_SEQPACK_Association::recv_urg (void *ptr,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Association::recv_urg");
+ return ACE::recv (this->get_handle (),
+ ptr,
+ len,
+ MSG_OOB,
+ timeout);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_SEQPACK_Connector.cpp b/ACE/ace/SOCK_SEQPACK_Connector.cpp
new file mode 100644
index 00000000000..7027b460fe7
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Connector.cpp
@@ -0,0 +1,443 @@
+// $Id$
+
+#include "ace/SOCK_SEQPACK_Connector.h"
+
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/os_include/os_fcntl.h"
+
+#if defined (ACE_WIN32)
+#include "ace/OS_NS_unistd.h"
+#endif /* ACE_WIN32 */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_SEQPACK_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK_SEQPACK_Connector, "SOCK_SEQPACK_Connector.cpp,v 4.35 2002/03/08 23:18:09 spark Exp")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_SEQPACK_Connector)
+
+void
+ACE_SOCK_SEQPACK_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association &new_association,
+ int protocol_family,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_open");
+
+
+
+ // Only open a new socket if we don't already have a valid handle.
+ if (new_association.get_handle () == ACE_INVALID_HANDLE &&
+#if defined (ACE_HAS_LKSCTP)
+ new_association.open (SOCK_STREAM,
+#else
+ new_association.open (SOCK_SEQPACKET,
+#endif /* ACE_HAS_LKSCTP */
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association &new_association,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_open");
+
+ // Only open a new socket if we don't already have a valid handle.
+ if (new_association.get_handle () == ACE_INVALID_HANDLE &&
+#if defined (ACE_HAS_LKSCTP)
+ new_association.open (SOCK_STREAM,
+#else
+ new_association.open (SOCK_SEQPACKET,
+#endif /* ACE_HAS_LKSCTP */
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_SOCK_SEQPACK_Connector::shared_connect_start (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_start");
+
+ if (local_sap != ACE_Addr::sap_any)
+ {
+ sockaddr *laddr = reinterpret_cast<sockaddr *> (local_sap.get_addr ());
+ int size = local_sap.get_size ();
+
+ if (ACE_OS::bind (new_association.get_handle (),
+ laddr,
+ size) == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ new_association.close ();
+ return -1;
+ }
+ }
+
+ // Enable non-blocking, if required.
+ if (timeout != 0
+ && new_association.enable (ACE_NONBLOCK) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+// Multihomed version of same
+int
+ACE_SOCK_SEQPACK_Connector::shared_connect_start (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Time_Value *timeout,
+ const ACE_Multihomed_INET_Addr &local_sap)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_start");
+
+ if (local_sap.ACE_Addr::operator!= (ACE_Addr::sap_any))
+ {
+ // The total number of addresses is the number of secondary
+ // addresses plus one.
+ size_t num_addresses = local_sap.get_num_secondary_addresses() + 1;
+
+ // Create an array of sockaddr_in to hold the underlying
+ // representations of the primary and secondary
+ // addresses.
+ sockaddr_in* local_inet_addrs = 0;
+ ACE_NEW_NORETURN (local_inet_addrs, sockaddr_in[num_addresses]);
+ if (!local_inet_addrs)
+ return -1;
+
+ // Populate the array by invoking the get_addresses method on
+ // the Multihomed_INET_Addr
+ local_sap.get_addresses(local_inet_addrs, num_addresses);
+
+#if defined (ACE_HAS_LKSCTP)
+ sockaddr_in *local_sockaddr = 0;
+ sockaddr_in portst;
+ int sn = sizeof(sockaddr);
+
+ // bind to the primary addr first
+ if (ACE_OS::bind(new_association.get_handle (),
+ reinterpret_cast<sockaddr *> (&(local_inet_addrs[0])),
+ sizeof(sockaddr)))
+ {
+ ACE_Errno_Guard error (errno);
+ new_association.close ();
+ return -1;
+ }
+
+ // do we need to bind multiple addrs
+ if (num_addresses > 1)
+ {
+ // allocate enough memory to hold the number of secondary addrs
+ ACE_NEW_NORETURN(local_sockaddr,
+ sockaddr_in[num_addresses - 1]);
+
+ // get sockaddr_in for the local handle
+ if (ACE_OS::getsockname(new_association.get_handle (),
+ reinterpret_cast<sockaddr *> (&portst),
+ &sn))
+ {
+ ACE_Errno_Guard error (errno);
+ new_association.close ();
+ return -1;
+ }
+
+ // set the local port # assigned by the os to every secondary addr
+ for (size_t i = 1; i < num_addresses; i++)
+ {
+ local_inet_addrs[i].sin_port = portst.sin_port;
+ }
+
+ // copy all of the secondary addrs into a sockaddr structure
+ for (size_t i = 0; i < num_addresses - 1; i++)
+ {
+ ACE_OS::memcpy(&(local_sockaddr[i]),
+ &(local_inet_addrs[i + 1]),
+ sizeof(sockaddr_in));
+ }
+
+ // bind other ifaces
+ if (sctp_bindx(new_association.get_handle(),
+ reinterpret_cast<sockaddr *> (local_sockaddr),
+ num_addresses - 1,
+ SCTP_BINDX_ADD_ADDR))
+ {
+ ACE_Errno_Guard error (errno);
+ new_association.close ();
+ return -1;
+ }
+
+ delete [] local_sockaddr;
+ }
+#else
+
+ // Call bind
+ size_t name_len = (sizeof (sockaddr_in)) * num_addresses;
+ if (ACE_OS::bind (new_association.get_handle (),
+ reinterpret_cast<sockaddr *> (local_inet_addrs),
+ static_cast<int> (name_len)) == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ new_association.close ();
+ return -1;
+ }
+#endif /* ACE_HAS_LKSCTP */
+
+ delete [] local_inet_addrs;
+ }
+
+ // Enable non-blocking, if required.
+ if (timeout != 0
+ && new_association.enable (ACE_NONBLOCK) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_SOCK_SEQPACK_Connector::shared_connect_finish (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Time_Value *timeout,
+ int result)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_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_association,
+ 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_association>.
+ new_association.disable (ACE_NONBLOCK);
+ else if (!(error == EWOULDBLOCK || error == ETIMEDOUT))
+ new_association.close ();
+
+ return result;
+}
+
+// Actively connect and produce a new ACE_SOCK_SEQPACK_Association if things go well...
+
+
+int
+ACE_SOCK_SEQPACK_Connector::connect (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int /* flags */,
+ int /* perms */,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
+
+ if (this->shared_open (new_association,
+ remote_sap.get_type (),
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+ else if (this->shared_connect_start (new_association,
+ timeout,
+ local_sap) == -1)
+ return -1;
+
+ int result = ACE_OS::connect (new_association.get_handle (),
+ reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
+ remote_sap.get_size ());
+
+ return this->shared_connect_finish (new_association,
+ timeout,
+ result);
+}
+
+// Multihomed version of same
+int
+ACE_SOCK_SEQPACK_Connector::connect (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout,
+ const ACE_Multihomed_INET_Addr &local_sap,
+ int reuse_addr,
+ int /* flags */,
+ int /* perms */,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
+
+ if (this->shared_open (new_association,
+ remote_sap.get_type (),
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+ else if (this->shared_connect_start (new_association,
+ timeout,
+ local_sap) == -1)
+ return -1;
+
+ int result = ACE_OS::connect (new_association.get_handle (),
+ reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
+ remote_sap.get_size ());
+
+ return this->shared_connect_finish (new_association,
+ timeout,
+ result);
+}
+
+// Try to complete a non-blocking connection.
+
+int
+ACE_SOCK_SEQPACK_Connector::complete (ACE_SOCK_SEQPACK_Association &new_association,
+ ACE_Addr *remote_sap,
+ const ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::complete");
+ ACE_HANDLE h = ACE::handle_timed_complete (new_association.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_association.get_handle (),
+ tv);
+ if (h == ACE_INVALID_HANDLE)
+ {
+#endif /* ACE_WIN32 */
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ new_association.close ();
+ return -1;
+#if defined (ACE_WIN32)
+ }
+#endif /* ACE_WIN32 */
+ }
+
+ if (remote_sap != 0)
+ {
+ int len = remote_sap->get_size ();
+ sockaddr *addr = reinterpret_cast<sockaddr *> (remote_sap->get_addr ());
+ if (ACE_OS::getpeername (h,
+ addr,
+ &len) == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ new_association.close ();
+ return -1;
+ }
+ }
+
+ // Start out with non-blocking disabled on the <new_association>.
+ new_association.disable (ACE_NONBLOCK);
+ return 0;
+}
+
+ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
+
+ if (this->connect (new_association,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ protocol) == -1
+ && timeout != 0
+ && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
+}
+
+// Multihomed version of same
+ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout,
+ const ACE_Multihomed_INET_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
+
+ if (this->connect (new_association,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ protocol) == -1
+ && timeout != 0
+ && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_SEQPACK_Connector.h b/ACE/ace/SOCK_SEQPACK_Connector.h
new file mode 100644
index 00000000000..ac689917fa8
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Connector.h
@@ -0,0 +1,331 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SOCK_SEQPACK_Connector.h
+ *
+ * $Id$
+ *
+ * @author Patrick J. Lardieri <plardier@atl.lmco.com>
+ * @author Gaurav Naik, Lockheed Martin ATL
+ * @author based on SOCK_STREAM_Connector
+ * by Douglas C. Schmidt <schmidt@dre.vanderbilt.edu>
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_SEQPACK_CONNECTOR_H
+#define ACE_SOCK_SEQPACK_CONNECTOR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#include "ace/SOCK_SEQPACK_Association.h"
+#include "ace/Multihomed_INET_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+class ACE_Time_Value;
+
+/**
+ * @class ACE_SOCK_SEQPACK_Connector
+ *
+ * @brief Defines a factory that actively connects to a remote IP
+ * address and TCP port, creating a new @c ACE_SOCK_SEQPACK_Association object.
+ *
+ * The @c ACE_SOCK_SEQPACK_Connector doesn't have a socket of its own,
+ * i.e., it simply "borrows" the one from the @c ACE_SOCK_SEQPACK_Association
+ * 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
+ * @c ACE_SOCK_SEQPACK_Connector from @c ACE_SOCK. A nice side-effect of
+ * this is that @c ACE_SOCK_SEQPACK_Connector objects do not store state so
+ * they can be used reentrantly in multithreaded programs.
+ */
+class ACE_Export ACE_SOCK_SEQPACK_Connector
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SOCK_SEQPACK_Connector (void);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SOCK_SEQPACK_Association
+ * object if the connection succeeds.
+ *
+ * @param new_association The @c ACE_SOCK_SEQPACK_Association object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ * @param protocol (optional) If value is 0, default SOCK_STREAM
+ * protocol is selected by kernel (typically TCP).
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association &new_association,
+ 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 = 132);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SOCK_SEQPACK_Association
+ * object if the connection succeeds.
+ *
+ * @param new_association The @c ACE_SOCK_SEQPACK_Association object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The set of local addresses for SCTP to
+ * bind to.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ * @param protocol (optional) If value is 0, default SOCK_STREAM
+ * protocol is selected by kernel (typically TCP).
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout,
+ const ACE_Multihomed_INET_Addr &local_sap,
+ int reuse_addr = 0,
+ int flags = 0,
+ int perms = 0,
+ int protocol = 132);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SOCK_SEQPACK_Association
+ * object if the connection succeeds.
+ *
+ * @param new_association The @c ACE_SOCK_SEQPACK_Association object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ * @param protocol (optional) If value is 0, default SOCK_STREAM
+ * protocol is selected by kernel (typically TCP).
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ int connect (ACE_SOCK_SEQPACK_Association &new_association,
+ 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 = 132);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SOCK_SEQPACK_Association
+ * object if the connection succeeds.
+ *
+ * @param new_association The @c ACE_SOCK_SEQPACK_Association object that will be connected
+ * to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The set of local addresses for SCTP to
+ * bind to.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ * @param protocol (optional) If value is 0, default SOCK_STREAM
+ * protocol is selected by kernel (typically TCP).
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+
+ int connect (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout,
+ const ACE_Multihomed_INET_Addr &local_sap,
+ int reuse_addr = 0,
+ int flags = 0,
+ int perms = 0,
+ int protocol = 132);
+
+ /// Default dtor.
+ ~ACE_SOCK_SEQPACK_Connector (void);
+
+ // = Completion routine.
+ /**
+ * Try to complete a nonblocking connection that was begun by a
+ * previous call to connect with a {0, 0} ACE_Time_Value timeout.
+ * @see connect().
+ *
+ * @param new_association The @c ACE_SOCK_SEQPACK_Association object that will be connected
+ * to the peer.
+ * @param remote_sap If non-0, it points to the @c ACE_INET_Addr object
+ * that will contain the address of the connected peer.
+ * @param timeout Same values and return value possibilites as for
+ * connect(). @see connect().
+ */
+ int complete (ACE_SOCK_SEQPACK_Association &new_association,
+ 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_Multihomed_INET_Addr PEER_ADDR;
+ typedef ACE_SOCK_SEQPACK_Association 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_SEQPACK_Association &new_association,
+ 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_SEQPACK_Association &new_association,
+ 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_SEQPACK_Association &new_association,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap);
+
+ int shared_connect_start (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Time_Value *timeout,
+ const ACE_Multihomed_INET_Addr &local_sap);
+
+ /// Perform operations that must be called after <ACE_OS::connect>.
+ int shared_connect_finish (ACE_SOCK_SEQPACK_Association &new_association,
+ const ACE_Time_Value *timeout,
+ int result);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_SEQPACK_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SOCK_SEQPACK_CONNECTOR_H */
diff --git a/ACE/ace/SOCK_SEQPACK_Connector.inl b/ACE/ace/SOCK_SEQPACK_Connector.inl
new file mode 100644
index 00000000000..c932ad2eed6
--- /dev/null
+++ b/ACE/ace/SOCK_SEQPACK_Connector.inl
@@ -0,0 +1,38 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This constructor is used by a client when it wants to connect to
+// the specified REMOTE_SAP address using a blocking open.
+
+ACE_INLINE
+ACE_SOCK_SEQPACK_Connector::~ACE_SOCK_SEQPACK_Connector (void)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::~ACE_SOCK_SEQPACK_Connector");
+}
+
+// Do-nothing constructor...
+
+ACE_INLINE
+ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (void)
+{
+ ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
+}
+
+ACE_INLINE int
+ACE_SOCK_SEQPACK_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ // Reset the event association
+ return ::WSAEventSelect ((SOCKET) handle,
+ 0,
+ 0);
+#else /* !defined ACE_HAS_WINSOCK2 */
+ ACE_UNUSED_ARG (handle);
+ return 0;
+#endif /* ACE_WIN32 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Stream.cpp b/ACE/ace/SOCK_Stream.cpp
new file mode 100644
index 00000000000..6b4946fd939
--- /dev/null
+++ b/ACE/ace/SOCK_Stream.cpp
@@ -0,0 +1,40 @@
+// $Id$
+
+#include "ace/SOCK_Stream.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SOCK_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SOCK_Stream, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Stream)
+
+void
+ACE_SOCK_Stream::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SOCK_Stream::dump");
+#endif /* ACE_HAS_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 us 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.
+ (void) this->close_writer ();
+ #endif /* ACE_WIN32 */
+
+ // Close down the socket.
+ return ACE_SOCK::close ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SOCK_Stream.h b/ACE/ace/SOCK_Stream.h
new file mode 100644
index 00000000000..40b64c7bcc2
--- /dev/null
+++ b/ACE/ace/SOCK_Stream.h
@@ -0,0 +1,184 @@
+// -*- 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"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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.
+ *
+ * @sa ACE_SOCK_IO
+ */
+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 @a h).
+ ACE_SOCK_Stream (ACE_HANDLE h);
+
+ /// Destructor.
+ ~ACE_SOCK_Stream (void);
+
+ /** @name Counted send/receive methods
+ *
+ * The counted send/receive methods attempt to transfer a specified number
+ * of bytes even if they must block and retry the operation in order to
+ * transfer the entire amount. The time spent blocking for the entire
+ * transfer can be limited by a specified ACE_Time_Value object which is
+ * a relative time (i.e., a fixed amount of time, not an absolute time
+ * of day). These methods return the count of transferred bytes, or -1
+ * if an error occurs or the operation times out before the entire requested
+ * amount of data has been transferred. In error or timeout situations it's
+ * possible that some data was transferred before the error
+ * or timeout. The @c bytes_transferred parameter is used to obtain the
+ * count of bytes transferred before the error or timeout occurred. If the
+ * total specified number of bytes is transferred without error, the
+ * method return value should equal the value of @c bytes_transferred.
+ *
+ * @param buf The buffer to write from or receive into.
+ * @param iov An I/O vector containing a specified number of
+ * count/pointer pairs directing the data to be transferred.
+ * @param iovcnt The number of I/O vectors to be used from @a iov.
+ * @param len The number of bytes to transfer.
+ * @param flags Flags that will be passed through to the @c recv()
+ * system call.
+ * @param timeout Indicates how long to blocking trying to transfer data.
+ * If no timeout is supplied (timeout == 0) the method will
+ * wait indefinitely or until an error occurs for the
+ * specified number of bytes to be transferred.
+ * To avoid any waiting, specify a timeout value with
+ * 0 seconds.
+ * @param bytes_transferred If non-0, points to a location which receives
+ * the total number of bytes transferred before the method
+ * returns, even if it's less than the number requested.
+ *
+ * @retval len, the complete number of bytes transferred.
+ * @retval 0 EOF, i.e., the peer closed the connection.
+ * @retval -1 an error occurred before the entire amount was
+ * transferred. Check @c errno for more information.
+ * If the @a timeout period is reached, errno is ETIME.
+ *
+ * On partial transfers, i.e., if any data is transferred before
+ * timeout/error/EOF, *@a bytes_transferred will contain the number of
+ * bytes transferred.
+ */
+ //@{
+ /// Try to recv exactly @a len bytes into @a 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 @a len bytes into @a 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 @c iovec of size @a iovcnt from the connected socket.
+ ssize_t recvv_n (iovec iov[],
+ int iovcnt,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Try to send exactly @a len bytes from @a 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 @a len bytes from @a 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 blocks chained through their @c next and
+ /// @c 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 @c iovec of size @a iovcnt to the connected socket.
+ ssize_t sendv_n (const iovec iov[],
+ int 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SOCK_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SOCK_STREAM_H */
diff --git a/ACE/ace/SOCK_Stream.inl b/ACE/ace/SOCK_Stream.inl
new file mode 100644
index 00000000000..ed5e8b231b8
--- /dev/null
+++ b/ACE/ace/SOCK_Stream.inl
@@ -0,0 +1,177 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/SOCK_Stream.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SOCK_Stream::ACE_SOCK_Stream (void)
+{
+ // ACE_TRACE ("ACE_SOCK_Stream::ACE_SOCK_Stream");
+}
+
+ACE_INLINE
+ACE_SOCK_Stream::ACE_SOCK_Stream (ACE_HANDLE h)
+{
+ // ACE_TRACE ("ACE_SOCK_Stream::ACE_SOCK_Stream");
+ this->set_handle (h);
+}
+
+ACE_INLINE
+ACE_SOCK_Stream::~ACE_SOCK_Stream (void)
+{
+ // ACE_TRACE ("ACE_SOCK_Stream::~ACE_SOCK_Stream");
+}
+
+ACE_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.
+
+ACE_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;
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_Stream::recvv_n (iovec iov[],
+ int 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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_INLINE ssize_t
+ACE_SOCK_Stream::sendv_n (const iovec iov[],
+ int 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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE.cpp b/ACE/ace/SPIPE.cpp
new file mode 100644
index 00000000000..b6b1300b26d
--- /dev/null
+++ b/ACE/ace/SPIPE.cpp
@@ -0,0 +1,82 @@
+// $Id$
+
+#include "ace/SPIPE.h"
+
+#include "ace/OS_NS_unistd.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SPIPE.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SPIPE, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SPIPE::dump");
+#endif /* ACE_HAS_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 ());
+#if defined (ACE_HAS_STREAM_PIPES)
+ result = (ACE_OS::close (duplex_pipe_handle_) || result);
+#endif /* ACE_HAS_STREAM_PIPES */
+ 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;
+}
+
+#if defined (ACE_HAS_STREAM_PIPES)
+/// Temporary store of duplex pipe handle.
+void
+ACE_SPIPE::set_duplex_handle (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_SPIPE::set_duplex_handle");
+ this->duplex_pipe_handle_ = handle;
+}
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE.h b/ACE/ace/SPIPE.h
new file mode 100644
index 00000000000..99bc370b84d
--- /dev/null
+++ b/ACE/ace/SPIPE.h
@@ -0,0 +1,116 @@
+/* -*- 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"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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;
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ /// Temporary store of duplex pipe handle.
+ void set_duplex_handle (ACE_HANDLE handle);
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+#if defined (ACE_HAS_STREAM_PIPES)
+ /// Duplex to the pipe I/O handle.
+ /// Stored here for latter cleaning.
+ ACE_HANDLE duplex_pipe_handle_;
+#endif /* ACE_HAS_STREAM_PIPES */
+
+protected:
+ /// Ensure that this class is an abstract base class
+ ACE_SPIPE (void);
+
+ /// Our local address.
+ ACE_SPIPE_Addr local_addr_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SPIPE.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SPIPE_H */
diff --git a/ACE/ace/SPIPE.inl b/ACE/ace/SPIPE.inl
new file mode 100644
index 00000000000..45814117a51
--- /dev/null
+++ b/ACE/ace/SPIPE.inl
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE_Acceptor.cpp b/ACE/ace/SPIPE_Acceptor.cpp
new file mode 100644
index 00000000000..285ddb2438d
--- /dev/null
+++ b/ACE/ace/SPIPE_Acceptor.cpp
@@ -0,0 +1,337 @@
+// $Id$
+
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_sys_time.h"
+
+#if defined (ACE_HAS_STREAM_PIPES)
+# include "ace/OS_NS_unistd.h"
+#endif // ACE_HAS_STREAM_PIPES
+
+ACE_RCSID(ace, SPIPE_Acceptor, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (void)
+#if defined (ACE_HAS_WIN32_NAMED_PIPES)
+ : sa_ (0), pipe_handle_ (ACE_INVALID_HANDLE)
+#endif /* ACE_HAS_WIN32_NAMED_PIPES */
+{
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SPIPE_Acceptor::dump");
+#endif /* ACE_HAS_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,
+ LPSECURITY_ATTRIBUTES sa,
+ int pipe_mode)
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::open");
+ ACE_UNUSED_ARG (reuse_addr);
+
+ this->local_addr_ = local_sap;
+ this->set_handle (ACE_INVALID_HANDLE);
+#if defined (ACE_HAS_WIN32_NAMED_PIPES)
+ this->sa_ = sa;
+ this->pipe_mode_ = pipe_mode;
+#else
+ ACE_UNUSED_ARG (sa);
+ ACE_UNUSED_ARG (pipe_mode);
+#endif /* ACE_HAS_WIN32_NAMED_PIPES */
+
+ 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 (-1 == ACE_OS::fattach(spipe[0],
+ ACE_TEXT_ALWAYS_CHAR (
+ this->local_addr_.get_path_name ())))
+ return -1;
+
+ this->set_duplex_handle (spipe[0]);
+ this->set_handle (spipe[1]);
+ return 0;
+
+#elif defined (ACE_HAS_WIN32_NAMED_PIPES)
+ // 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_mode_,
+ PIPE_UNLIMITED_INSTANCES,
+ 1024 * 10,
+ 1024 * 10,
+ ACE_DEFAULT_TIMEOUT,
+ this->sa_);
+
+ 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. If the client also disconnects before
+ // this call, the error status will be ERROR_NO_DATA. In both
+ // cases, 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_UNUSED_ARG (result);
+ // ConnectNamePipe is suppose to always
+ // "fail" when passed in overlapped i/o
+ ACE_ASSERT (!result);
+
+ status = ::GetLastError ();
+ switch (status)
+ {
+ case ERROR_IO_PENDING:
+ break;
+ case ERROR_PIPE_CONNECTED:
+ case ERROR_NO_DATA:
+ this->already_connected_ = 1;
+ // Set the associated event as signaled so any reactors or
+ // proactors waiting for this will respond.
+ this->event_.signal ();
+ break;
+ default:
+ ACE_ASSERT (FALSE); // An undocumented error was returned.
+ this->close (); // Sets handle to ACE_INVALID_HANDLE.
+ break;
+ }
+ }
+ 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_HAS_WIN32_NAMED_PIPES)
+
+ // Check to see if we have a valid pipe; if not, nothing to do.
+ if (this->pipe_handle_ == ACE_INVALID_HANDLE)
+ return -1;
+
+ // Substitute the pipe handle back in so it's closed properly in the
+ // ACE_OS wrapper. But leave the pipe_handle_ value so we can clean up the
+ // hanging overlapped operation afterwards.
+ this->set_handle (this->pipe_handle_);
+
+#endif /* ACE_HAS_WIN32_NAMED_PIPES */
+
+ // 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 (ACE_TEXT_ALWAYS_CHAR (this->local_addr_.get_path_name ()));
+#elif defined (ACE_HAS_WIN32_NAMED_PIPES)
+
+ // open () started the Connect in asynchronous mode, and accept() restarts
+ // the ConnectNamedPipe in overlapped mode. To avoid leaving a hanging
+ // overlapped operation that'll write into members of this object,
+ // wait for the event in the OVERLAPPED structure to be signalled.
+ if (this->already_connected_ == 0)
+ {
+ if (this->event_.wait () != -1)
+ {
+ // Should be here with the ConnectNamedPipe operation complete.
+ // Steal the already_connected_ flag to record the results.
+ DWORD unused;
+ ::GetOverlappedResult (this->pipe_handle_,
+ &this->overlapped_,
+ &unused,
+ FALSE);
+ }
+ this->pipe_handle_ = ACE_INVALID_HANDLE;
+ this->already_connected_ = 0;
+ }
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ return result;
+}
+
+ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (const ACE_SPIPE_Addr &local_sap,
+ int reuse_addr,
+ int perms,
+ LPSECURITY_ATTRIBUTES sa,
+ int pipe_mode)
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor");
+
+ if (this->open (local_sap, reuse_addr, perms, sa, pipe_mode) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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_HAS_WIN32_NAMED_PIPES)
+ 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 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE_Acceptor.h b/ACE/ace/SPIPE_Acceptor.h
new file mode 100644
index 00000000000..2c7d9958756
--- /dev/null
+++ b/ACE/ace/SPIPE_Acceptor.h
@@ -0,0 +1,168 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SPIPE_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#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_HAS_WIN32_NAMED_PIPES)
+#include "ace/Manual_Event.h"
+#endif /* ACE_HAS_WIN32_NAMED_PIPES */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SPIPE_Acceptor
+ *
+ * @brief A factory class that produces ACE_SPIPE_Stream objects.
+ *
+ * ACE_SPIPE_Acceptor is a factory class that accepts SPIPE connections.
+ * Each accepted connection produces an ACE_SPIPE_Stream object.
+ *
+ * @warning Windows: Works only on Windows NT 4 and higher. To use this
+ * class with the ACE_Reactor framework, note that the handle to
+ * demultiplex on is an event handle and should be registered with the
+ * ACE_Reactor::register_handler (ACE_Event_Handler *, ACE_HANDLE) method.
+ *
+ * @warning Works on non-Windows platforms only when @c ACE_HAS_STREAM_PIPES
+ * is defined.
+ *
+ */
+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.
+ /**
+ * @param local_sap The name of the pipe instance to open and listen on.
+ * @param reuse_addr Optional, and ignored. Needed for API compatibility
+ * with other acceptor classes.
+ * @param perms Optional, the protection mask to create the pipe
+ * with. Ignored on Windows.
+ * @param sa Optional, ignored on non-Windows. The
+ * SECURITY_ATTRIBUTES to create the named pipe
+ * instances with. This pointer is remembered and
+ * reused on each new named pipe instance, so only
+ * pass a value that remains valid as long as this
+ * object does.
+ * @param pipe_mode Optional, ignored on non-Windows. The NT pipe
+ * mode used when creating the pipe.
+ */
+ ACE_SPIPE_Acceptor (const ACE_SPIPE_Addr &local_sap,
+ int reuse_addr = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ int pipe_mode = PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
+
+ /// Initiate a passive-mode STREAM pipe listener.
+ /**
+ * @param local_sap The name of the pipe instance to open and listen on.
+ * @param reuse_addr Optional, and ignored. Needed for API compatibility
+ * with other acceptor classes.
+ * @param perms Optional, the protection mask to create the pipe
+ * with. Ignored on Windows.
+ * @param sa Optional, ignored on non-Windows. The
+ * SECURITY_ATTRIBUTES to create the named pipe
+ * instances with. This pointer is remembered and
+ * reused on each new named pipe instance, so only
+ * pass a value that remains valid as long as this
+ * object does.
+ * @param pipe_mode Optional, ignored on non-Windows. The NT pipe
+ * mode used when creating the pipe.
+ *
+ * @retval 0 for success.
+ * @retval -1 for failure.
+ */
+ int open (const ACE_SPIPE_Addr &local_sap,
+ int reuse_addr = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ int pipe_mode = PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
+
+ /// 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.
+ *
+ * @param ipc_sap_spipe The ACE_SPIPE_Stream to initialize with the
+ * newly-accepted pipe.
+ * @param remote_addr Optional, accepts the address of the peer.
+ * @param timeout 0 means block forever, {0, 0} means poll.
+ * @param restart 1 means "restart if interrupted."
+ *
+ * @retval 0 for success.
+ * @retval -1 for failure.
+ */
+ 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_HAS_WIN32_NAMED_PIPES)
+ // On Windows, the SECURITY_ATTRIBUTES specified for the initial accept
+ // operation is reused on all subsequent pipe instances as well.
+ LPSECURITY_ATTRIBUTES sa_;
+
+ // On Windows, the pipe mode to create the pipe in. This can be in
+ // either a bytestream-oriented mode or a message-oriented mode.
+ DWORD pipe_mode_;
+
+ // 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_HAS_WIN32_NAMED_PIPES */
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SPIPE_ACCEPTOR_H */
diff --git a/ACE/ace/SPIPE_Addr.cpp b/ACE/ace/SPIPE_Addr.cpp
new file mode 100644
index 00000000000..bbba12f9242
--- /dev/null
+++ b/ACE/ace/SPIPE_Addr.cpp
@@ -0,0 +1,167 @@
+// $Id$
+
+#include "ace/SPIPE_Addr.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/os_include/sys/os_socket.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SPIPE_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SPIPE_Addr, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Addr)
+
+void
+ACE_SPIPE_Addr::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+#endif /* ACE_HAS_DUMP */
+}
+
+// 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);
+}
+
+// Return the address.
+
+void *
+ACE_SPIPE_Addr::get_addr (void) const
+{
+ return (void *) &this->SPIPE_addr_;
+}
+
+
+// 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_);
+}
+
+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;
+}
+
+// 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_TEXT ( "\\\\.\\pipe\\"));
+ ACE_OS::strcat (temp, addr);
+ }
+ else
+ {
+
+ if (ACE_OS::strncmp (addr,
+ ACE_TEXT ("localhost"),
+ ACE_OS::strlen ("localhost")) == 0)
+ // change "localhost" to "."
+ ACE_OS::strcpy (temp, ACE_TEXT ("\\\\."));
+ else
+ {
+ ACE_OS::strcpy (temp, ACE_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_TEXT ('\0');
+ ACE_OS::strcat (temp, t);
+
+ ACE_OS::free (t);
+ }
+
+ ACE_OS::strcat (temp, ACE_TEXT ("\\pipe\\"));
+ ACE_OS::strcat (temp, colonp + 1);
+ }
+ len += static_cast<int> (ACE_OS::strlen (temp));
+ this->ACE_Addr::base_set (AF_SPIPE, 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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE_Addr.h b/ACE/ace/SPIPE_Addr.h
new file mode 100644
index 00000000000..7344a1b5a5b
--- /dev/null
+++ b/ACE/ace/SPIPE_Addr.h
@@ -0,0 +1,122 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file SPIPE_Addr.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_SPIPE_ADDR_H
+#define ACE_SPIPE_ADDR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Addr.h"
+#include "ace/os_include/sys/os_types.h"
+#include "ace/os_include/os_dirent.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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.
+ bool operator == (const ACE_SPIPE_Addr &SAP) const;
+
+ /// Check for inequality
+ bool 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.
+ uid_t user_id (void) const;
+
+ /// Set user id.
+ void user_id (uid_t uid);
+
+ /// Set group ids.
+ void group_id (gid_t gid);
+
+ /// Get group ids.
+ 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
+ {
+ /// Group id.
+ gid_t gid_;
+
+ /// User id.
+ uid_t uid_;
+
+ /// Pathname in the file system.
+ ACE_TCHAR rendezvous_[MAXPATHLEN + 1];
+
+ } SPIPE_addr_;
+ // Contents of an SPIPE address.
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SPIPE_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SPIPE_ADDR_H */
diff --git a/ACE/ace/SPIPE_Addr.inl b/ACE/ace/SPIPE_Addr.inl
new file mode 100644
index 00000000000..ea4c71ef682
--- /dev/null
+++ b/ACE/ace/SPIPE_Addr.inl
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#include "ace/SString.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Compare two addresses for equality.
+
+ACE_INLINE bool
+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 bool
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE_Connector.cpp b/ACE/ace/SPIPE_Connector.cpp
new file mode 100644
index 00000000000..80dd4c9e4ce
--- /dev/null
+++ b/ACE/ace/SPIPE_Connector.cpp
@@ -0,0 +1,160 @@
+// $Id$
+
+#include "ace/SPIPE_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_unistd.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SPIPE_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SPIPE_Connector, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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,
+ LPSECURITY_ATTRIBUTES sa,
+ int pipe_mode)
+{
+ ACE_TRACE ("ACE_SPIPE_Connector::ACE_SPIPE_Connector");
+ if (this->connect (new_io, remote_sap, timeout, local_sap,
+ reuse_addr, flags, perms, sa, pipe_mode) == -1
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("address %s, %p\n"),
+ remote_sap.get_path_name (), ACE_TEXT ("ACE_SPIPE_Connector")));
+}
+
+void
+ACE_SPIPE_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SPIPE_Connector::dump");
+#endif /* ACE_HAS_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,
+ LPSECURITY_ATTRIBUTES sa,
+ int pipe_mode)
+{
+ ACE_TRACE ("ACE_SPIPE_Connector::connect");
+ // Make darn sure that the O_CREAT flag is not set!
+ ACE_CLR_BITS (flags, O_CREAT);
+
+ ACE_HANDLE handle;
+
+ ACE_UNUSED_ARG (pipe_mode);
+#if defined (ACE_WIN32) && \
+ !defined (ACE_HAS_PHARLAP) && !defined (ACE_HAS_WINCE)
+ // We need to allow for more than one attempt to connect,
+ // calculate the absolute time at which we give up.
+ ACE_Time_Value absolute_time;
+ if (timeout != 0)
+ absolute_time = ACE_OS::gettimeofday () + *timeout;
+
+ // Loop until success or failure.
+ for (;;)
+ {
+ handle = ACE_OS::open (remote_sap.get_path_name(), flags, perms, sa);
+ if (handle != ACE_INVALID_HANDLE)
+ // Success!
+ break;
+
+ // Check if we have a busy pipe condition.
+ if (::GetLastError() != ERROR_PIPE_BUSY)
+ // Nope, this is a failure condition.
+ break;
+
+ // This will hold the time out value used in the ::WaitNamedPipe
+ // call.
+ DWORD time_out_value;
+
+ // Check if we are to block until we connect.
+ if (timeout == 0)
+ // Wait for as long as it takes.
+ time_out_value = NMPWAIT_WAIT_FOREVER;
+ else
+ {
+ // Calculate the amount of time left to wait.
+ ACE_Time_Value relative_time (absolute_time - ACE_OS::gettimeofday ());
+ // Check if we have run out of time.
+ if (relative_time <= ACE_Time_Value::zero)
+ {
+ // Mimick the errno value returned by
+ // ACE::handle_timed_open.
+ if (*timeout == ACE_Time_Value::zero)
+ errno = EWOULDBLOCK;
+ else
+ errno = ETIMEDOUT;
+ // Exit the connect loop with the failure.
+ break;
+ }
+ // Get the amount of time remaining for ::WaitNamedPipe.
+ time_out_value = relative_time.msec ();
+
+ }
+
+ // Wait for the named pipe to become available.
+ ACE_TEXT_WaitNamedPipe (remote_sap.get_path_name (),
+ time_out_value);
+
+ // Regardless of the return value, we'll do one more attempt to
+ // connect to see if it is now available and to return
+ // consistent error values.
+ }
+
+ // Set named pipe mode if we have a valid handle.
+ if (handle != ACE_INVALID_HANDLE)
+ {
+ // Check if we are changing the pipe mode from the default.
+ if (pipe_mode != (PIPE_READMODE_BYTE | PIPE_WAIT))
+ {
+ DWORD dword_pipe_mode = pipe_mode;
+ if (!::SetNamedPipeHandleState (handle,
+ &dword_pipe_mode,
+ 0,
+ 0))
+ {
+ // We were not able to put the pipe into the requested
+ // mode.
+ ACE_OS::close (handle);
+ handle = ACE_INVALID_HANDLE;
+ }
+ }
+ }
+#else /* ACE_WIN32 && !ACE_HAS_PHARLAP */
+ handle = ACE::handle_timed_open (timeout,
+ remote_sap.get_path_name (),
+ flags, perms, sa);
+#endif /* !ACE_WIN32 || ACE_HAS_PHARLAP || ACE_HAS_WINCE */
+
+ new_io.set_handle (handle);
+ new_io.remote_addr_ = remote_sap; // class copy.
+
+ return handle == ACE_INVALID_HANDLE ? -1 : 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE_Connector.h b/ACE/ace/SPIPE_Connector.h
new file mode 100644
index 00000000000..51e3476816b
--- /dev/null
+++ b/ACE/ace/SPIPE_Connector.h
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SPIPE_Connector.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author 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"
+#include "ace/os_include/os_fcntl.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SPIPE_Connector
+ *
+ * @brief Defines an active connection factory for ACE_SPIPE_Stream.
+ * On Windows this is mapped to Named Pipes, whereas on UNIX it is
+ * mapped to STREAM pipes.
+ */
+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 @a remote_sap is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a reuse_addr == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The @a flags and @a perms arguments are passed down to the <open>
+ * method. The @a pipe_mode argument is only used in NT and is used to
+ * establish the NT pipe mode.
+ */
+ 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,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ int pipe_mode = PIPE_READMODE_MESSAGE | PIPE_WAIT);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The @a remote_sap is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a reuse_addr == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The @a flags and @a perms arguments are passed down to the <open>
+ * method. The @a pipe_mode argument is only used in NT and is used to
+ * establish the NT pipe mode.
+ */
+ 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,
+ LPSECURITY_ATTRIBUTES sa = 0,
+ int pipe_mode = PIPE_READMODE_MESSAGE | PIPE_WAIT);
+
+ /// 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SPIPE_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SPIPE_CONNECTOR_H */
diff --git a/ACE/ace/SPIPE_Connector.inl b/ACE/ace/SPIPE_Connector.inl
new file mode 100644
index 00000000000..bbec9b8f468
--- /dev/null
+++ b/ACE/ace/SPIPE_Connector.inl
@@ -0,0 +1,15 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE_Stream.cpp b/ACE/ace/SPIPE_Stream.cpp
new file mode 100644
index 00000000000..fcc695d6271
--- /dev/null
+++ b/ACE/ace/SPIPE_Stream.cpp
@@ -0,0 +1,104 @@
+// $Id$
+
+#include "ace/SPIPE_Stream.h"
+#include "ace/OS_Memory.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SPIPE_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SPIPE_Stream, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Stream)
+
+void
+ACE_SPIPE_Stream::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SPIPE_Stream::dump");
+#endif /* ACE_HAS_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;
+ int total_tuples = static_cast<int> (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 (int 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;
+ int total_tuples = static_cast<int> (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 (int 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SPIPE_Stream.h b/ACE/ace/SPIPE_Stream.h
new file mode 100644
index 00000000000..9293224b7ed
--- /dev/null
+++ b/ACE/ace/SPIPE_Stream.h
@@ -0,0 +1,171 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SPIPE_Stream.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#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"
+#include "ace/ACE.h"
+#include "ace/OS_NS_stropts.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SPIPE_Stream
+ *
+ * @brief Defines the methods in the ACE_SPIPE_Stream abstraction.
+ *
+ * @a buf is the buffer to write from or receive into.
+ * @a len is the number of bytes to transfer.
+ *
+ * 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.
+ *
+ * The return values for the "*_n()" methods match the return values
+ * from the non "_n()" methods and are specified as follows:
+ * - The number of bytes transferred is returned.
+ * - On error, -1 is returned, errno is set to appropriate error.
+ * - On EOF, 0 is returned, errno is irrelevant.
+ *
+ * Methods with <iovec> parameter are I/O vector variants of the I/O
+ * operations.
+ *
+ * The <send> and <revc> operations use "message" semantics rather
+ * than "bytestream" semantics.
+ */
+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 @a len bytes, keep trying until @a len are sent.
+ ssize_t send_n (const void *buf, size_t len) const;
+
+ /// Recv @a len bytes, keep trying until @a len are received.
+ ssize_t recv_n (void *buf, size_t len) const;
+
+ /// Send bytes via STREAM pipes using "band" mode.
+ ssize_t send (const void *buf, size_t len) const;
+
+ /// Recv bytes via STREAM pipes using "band" mode.
+ ssize_t recv (void *buf, size_t len) 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 the OS "gather-write" operation.
+ ssize_t send (const iovec iov[], int len) const;
+
+ /// Recv iovecs via the OS "scatter-read" operation.
+ ssize_t recv (iovec iov[], int len) 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 len, ...) 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 len, ...) const;
+
+ /// Send @a len bytes via Win32 <WriteFile> using overlapped I/O.
+ ssize_t send (const void *buf, size_t len, ACE_OVERLAPPED *overlapped) const;
+
+ /// Recv @a len bytes via Win32 <ReadFile> using overlapped I/O.
+ ssize_t recv (void *buf, size_t len, ACE_OVERLAPPED *overlapped) const;
+
+ /// Send an <iovec> of size @a len to the stream.
+ ssize_t sendv (const iovec iov[],
+ int len) const;
+
+ /// Send an <iovec> of size @a len to the stream. Will block until all
+ /// bytes are sent or an error occurs.
+ ssize_t sendv_n (const iovec iov[],
+ int len) const;
+
+ /// Receive an <iovec> of size @a len to the stream.
+ ssize_t recvv_n (iovec iov[],
+ int len) 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SPIPE_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SPIPE_STREAM_H */
diff --git a/ACE/ace/SPIPE_Stream.inl b/ACE/ace/SPIPE_Stream.inl
new file mode 100644
index 00000000000..94ca51dcf65
--- /dev/null
+++ b/ACE/ace/SPIPE_Stream.inl
@@ -0,0 +1,275 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_sys_uio.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_unistd.h"
+#if defined (ACE_WIN32)
+#include "ace/OS_NS_sys_socket.h"
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Create an ACE_SPIPE_Stream.
+
+ACE_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.
+
+ACE_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.
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_INLINE ssize_t
+ACE_SPIPE_Stream::send (const iovec iov[], int n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::send");
+ return ACE_OS::writev (this->get_handle (), iov, n);
+}
+
+ACE_INLINE ssize_t
+ACE_SPIPE_Stream::recv (iovec iov[], int 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.
+
+ACE_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);
+#elif defined (ACE_WIN32) && \
+ (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) && \
+ !defined (ACE_HAS_WINCE) /* CE4 has WS2 but not WSADuplicateSocket */
+ DWORD procID;
+ WSAPROTOCOL_INFO protInfo;
+ ssize_t res = this->recv(&procID, sizeof(procID));
+ if (res != sizeof(procID))
+ {
+ if(res != -1)
+ errno = ENXIO;
+ return -1;
+ }
+ if (::WSADuplicateSocket ((SOCKET)handle, procID, &protInfo) == -1)
+ {
+ ACE_OS::set_errno_to_wsa_last_error();
+ return -1;
+ }
+ res = this->send(&protInfo, sizeof(protInfo));
+ if (res != sizeof(protInfo))
+ {
+ if(res != -1)
+ errno = ENXIO;
+ return -1;
+ }
+ // This is just for synchronization, we will ignore the data
+ res = this->recv(&procID, sizeof(procID));
+ if (res != sizeof(procID))
+ {
+ if(res != -1)
+ errno = ENXIO;
+ return -1;
+ }
+ return 0;
+#else
+ handle = handle;
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+// This file receives an open file descriptor from this socket.
+
+ACE_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;
+ }
+#elif defined (ACE_WIN32) && \
+ (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+ pid_t procID = ACE_OS::getpid();
+ WSAPROTOCOL_INFO protInfo;
+ ssize_t res = this->send(&procID, sizeof(procID));
+ if (res != sizeof(procID))
+ {
+ if(res != -1)
+ errno = ENXIO;
+ return -1;
+ }
+ res = this->recv(&protInfo, sizeof(protInfo));
+ if (res != sizeof(protInfo))
+ {
+ if(res != -1)
+ errno = ENXIO;
+ return -1;
+ }
+ handle = ACE_OS::socket (FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
+ &protInfo, 0, 0);
+ if (handle == ACE_INVALID_HANDLE)
+ {
+ return -1;
+ }
+ // Since it does not matter what the data is, just send something to
+ // synchronize the end of the exchange
+ res = this->send(&procID, sizeof(procID));
+ if (res != sizeof(procID))
+ {
+ if(res != -1)
+ errno = ENXIO;
+ return -1;
+ }
+ 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...
+
+ACE_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 */
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_INLINE ssize_t
+ACE_SPIPE_Stream::sendv_n (const iovec iov[],
+ int 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.
+
+ACE_INLINE ssize_t
+ACE_SPIPE_Stream::recvv_n (iovec iov[],
+ int 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.
+
+ACE_INLINE ssize_t
+ACE_SPIPE_Stream::sendv (const iovec iov[],
+ int n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::sendv");
+ return ACE_OS::writev (this->get_handle (),
+ iov,
+ n);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
diff --git a/ACE/ace/SSL/ACE_SSL.pc.in b/ACE/ace/SSL/ACE_SSL.pc.in
new file mode 100644
index 00000000000..51c04a18ff1
--- /dev/null
+++ b/ACE/ace/SSL/ACE_SSL.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE_SSL
+Description: ACE SSL Library
+Requires: ACE
+Version: @VERSION@
+Libs: -L${libdir} @ACE_TLS_LDFLAGS@ -lACE_SSL @ACE_TLS_LIBS@
+Cflags: -I${includedir} @ACE_TLS_CPPFLAGS@
diff --git a/ACE/ace/SSL/Makefile.am b/ACE/ace/SSL/Makefile.am
new file mode 100644
index 00000000000..135fa9b937b
--- /dev/null
+++ b/ACE/ace/SSL/Makefile.am
@@ -0,0 +1,85 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## ./bin/mwc.pl -type automake -noreldefs ACE.mwc
+
+includedir = @includedir@/ace/SSL
+pkgconfigdir = @libdir@/pkgconfig
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.SSL.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+
+lib_LTLIBRARIES = libACE_SSL.la
+
+libACE_SSL_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ @ACE_TLS_CPPFLAGS@ \
+ -DACE_SSL_BUILD_DLL
+
+libACE_SSL_la_SOURCES = \
+ SSL_Asynch_BIO.cpp \
+ SSL_Asynch_Stream.cpp \
+ SSL_Context.cpp \
+ SSL_SOCK.cpp \
+ SSL_SOCK_Acceptor.cpp \
+ SSL_SOCK_Connector.cpp \
+ SSL_SOCK_Stream.cpp
+
+libACE_SSL_la_LDFLAGS = \
+ -release @ACE_VERSION_NAME@ @ACE_TLS_LDFLAGS@
+
+libACE_SSL_la_LIBADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ @ACE_TLS_LIBS@
+
+nobase_include_HEADERS = \
+ SSL_Asynch_BIO.h \
+ SSL_Asynch_Stream.h \
+ SSL_Context.h \
+ SSL_Context.inl \
+ SSL_Export.h \
+ SSL_SOCK.h \
+ SSL_SOCK.inl \
+ SSL_SOCK_Acceptor.h \
+ SSL_SOCK_Acceptor.inl \
+ SSL_SOCK_Connector.h \
+ SSL_SOCK_Connector.inl \
+ SSL_SOCK_Stream.h \
+ SSL_SOCK_Stream.inl \
+ sslconf.h
+
+pkgconfig_DATA = \
+ ACE_SSL.pc
+
+CLEANFILES = \
+ ACE_SSL.pc
+
+ACE_SSL.pc: ${top_builddir}/config.status ${srcdir}/ACE_SSL.pc.in
+ ${top_builddir}/config.status --file $@:${srcdir}/ACE_SSL.pc.in
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+EXTRA_DIST = \
+ ACE_SSL.pc.in
+
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/ace/SSL/SSL_Asynch_BIO.cpp b/ACE/ace/SSL/SSL_Asynch_BIO.cpp
new file mode 100644
index 00000000000..b287cf80ac8
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Asynch_BIO.cpp
@@ -0,0 +1,252 @@
+// -*- C++ -*-
+
+#include "SSL_Asynch_BIO.h"
+
+#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+
+#include "SSL_Asynch_Stream.h"
+#include "ace/OS_NS_string.h"
+
+
+ACE_RCSID (ACE_SSL,
+ SSL_Asynch_BIO,
+ "$Id$")
+
+
+#if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
+# define ACE_ASYNCH_BIO_WRITE_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_write)
+# define ACE_ASYNCH_BIO_READ_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_read)
+# define ACE_ASYNCH_BIO_PUTS_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_puts)
+# define ACE_ASYNCH_BIO_CTRL_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_ctrl)
+# define ACE_ASYNCH_BIO_NEW_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_new)
+# define ACE_ASYNCH_BIO_FREE_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_free)
+#else
+# define ACE_ASYNCH_BIO_WRITE_NAME ACE_Asynch_BIO_write
+# define ACE_ASYNCH_BIO_READ_NAME ACE_Asynch_BIO_read
+# define ACE_ASYNCH_BIO_PUTS_NAME ACE_Asynch_BIO_puts
+# define ACE_ASYNCH_BIO_CTRL_NAME ACE_Asynch_BIO_ctrl
+# define ACE_ASYNCH_BIO_NEW_NAME ACE_Asynch_BIO_new
+# define ACE_ASYNCH_BIO_FREE_NAME ACE_Asynch_BIO_free
+#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+/**
+ * @name OpenSSL BIO Helper Methods for use with ACE's Asynchronous
+ * SSL I/O support.
+ */
+//@{
+extern "C"
+{
+ int ACE_ASYNCH_BIO_WRITE_NAME (BIO *pBIO, const char *buf, int len);
+ int ACE_ASYNCH_BIO_READ_NAME (BIO *pBIO, char *buf, int len);
+ int ACE_ASYNCH_BIO_PUTS_NAME (BIO *pBIO, const char *str);
+ long ACE_ASYNCH_BIO_CTRL_NAME (BIO *pBIO, int cmd, long arg1, void *arg2);
+ int ACE_ASYNCH_BIO_NEW_NAME (BIO *pBIO);
+ int ACE_ASYNCH_BIO_FREE_NAME (BIO *pBIO);
+}
+//@}
+
+#define BIO_TYPE_ACE ( 21 | BIO_TYPE_SOURCE_SINK )
+
+static BIO_METHOD methods_ACE =
+ {
+ BIO_TYPE_ACE, // BIO_TYPE_PROXY_SERVER,
+ "ACE_Asynch_BIO",
+ ACE_ASYNCH_BIO_WRITE_NAME,
+ ACE_ASYNCH_BIO_READ_NAME,
+ ACE_ASYNCH_BIO_PUTS_NAME,
+ 0, /* ACE_ASYNCH_BIO_GETS_NAME, */
+ ACE_ASYNCH_BIO_CTRL_NAME,
+ ACE_ASYNCH_BIO_NEW_NAME,
+ ACE_ASYNCH_BIO_FREE_NAME,
+ 0
+ };
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+BIO *
+ACE_SSL_make_BIO (void * ssl_asynch_stream)
+{
+ BIO * const pBIO = BIO_new (&methods_ACE);
+
+ if (pBIO)
+ BIO_ctrl (pBIO,
+ BIO_C_SET_FILE_PTR,
+ 0,
+ ssl_asynch_stream);
+
+ return pBIO;
+}
+
+/**
+ * @struct @c ACE_SSL_Asynch_Stream_Accessor
+ *
+ * @brief Privileged @c ACE_SSL_Asynch_Stream accessor.
+ *
+ * This structure is a @c friend to the @c ACE_SSL_Asynch_Stream
+ * class so that it can gain access to the protected
+ * ssl_bio_{read,write}() methods in that class. It is full declared
+ * in this implementation file to hide its interface from users to
+ * prevent potential abuse of the friend relationship between it and
+ * the @c ACE_SSL_Asynch_Stream class.
+ */
+struct ACE_SSL_Asynch_Stream_Accessor
+{
+ static int read (ACE_SSL_Asynch_Stream * stream,
+ char * buf,
+ size_t len,
+ int & errval)
+ {
+ return stream->ssl_bio_read (buf, len, errval);
+ }
+
+ static int write (ACE_SSL_Asynch_Stream * stream,
+ const char * buf,
+ size_t len,
+ int & errval)
+ {
+ return stream->ssl_bio_write (buf, len, errval);
+ }
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_ASYNCH_BIO_NEW_NAME (BIO * pBIO)
+{
+ pBIO->init = 0; // not initialized
+ pBIO->num = 0; // still zero ( we can use it )
+ pBIO->ptr = 0; // will be pointer to ACE_SSL_Asynch_Stream
+ pBIO->flags = 0; //
+
+ return 1;
+}
+
+int
+ACE_ASYNCH_BIO_FREE_NAME (BIO * pBIO)
+{
+ if (pBIO && pBIO->shutdown)
+ {
+ pBIO->ptr = 0;
+ pBIO->init = 0;
+ pBIO->num = 0;
+ pBIO->flags = 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+ACE_ASYNCH_BIO_READ_NAME (BIO * pBIO, char * buf, int len)
+{
+ BIO_clear_retry_flags (pBIO);
+
+ ACE_SSL_Asynch_Stream * const p_stream =
+ static_cast<ACE_SSL_Asynch_Stream *> (pBIO->ptr);
+
+ if (pBIO->init == 0 || p_stream == 0 || buf == 0 || len <= 0)
+ return -1;
+
+ BIO_clear_retry_flags (pBIO);
+
+ int errval = 0;
+
+ int retval =
+ ACE_SSL_Asynch_Stream_Accessor::read (p_stream,
+ buf,
+ len,
+ errval);
+
+ if (retval >= 0)
+ return retval;
+
+ if (errval == EINPROGRESS)
+ BIO_set_retry_read (pBIO);
+
+ return -1;
+}
+
+int
+ACE_ASYNCH_BIO_WRITE_NAME (BIO * pBIO, const char * buf, int len)
+{
+ BIO_clear_retry_flags (pBIO);
+
+ ACE_SSL_Asynch_Stream * p_stream =
+ static_cast<ACE_SSL_Asynch_Stream *> (pBIO->ptr);
+
+ if (pBIO->init == 0 || p_stream == 0 || buf == 0 || len <= 0)
+ return -1;
+
+ BIO_clear_retry_flags (pBIO);
+
+ int errval = 0;
+
+ int retval =
+ ACE_SSL_Asynch_Stream_Accessor::write (p_stream,
+ buf,
+ len,
+ errval);
+
+ if (retval >= 0)
+ return retval;
+
+ if (errval == EINPROGRESS)
+ BIO_set_retry_write (pBIO);
+
+ return -1;
+}
+
+long
+ACE_ASYNCH_BIO_CTRL_NAME (BIO * pBIO, int cmd, long num, void *ptr)
+{
+ long ret = 1;
+
+ switch (cmd)
+ {
+ case BIO_C_SET_FILE_PTR:
+ pBIO->shutdown = static_cast<int> (num);
+ pBIO->ptr = ptr;
+ pBIO->init = 1;
+ break;
+
+ case BIO_CTRL_INFO:
+ ret = 0;
+ break;
+
+ case BIO_CTRL_GET_CLOSE:
+ ret = pBIO->shutdown;
+ break;
+
+ case BIO_CTRL_SET_CLOSE:
+ pBIO->shutdown = static_cast<int> (num);
+ break;
+
+ case BIO_CTRL_PENDING:
+ case BIO_CTRL_WPENDING:
+ ret = 0;
+ break;
+
+ case BIO_CTRL_DUP:
+ case BIO_CTRL_FLUSH:
+ ret = 1;
+ break;
+
+ default:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+int
+ACE_ASYNCH_BIO_PUTS_NAME (BIO *pBIO, const char *str)
+{
+ size_t const n = ACE_OS::strlen (str);
+
+ return ACE_ASYNCH_BIO_WRITE_NAME (pBIO, str, n);
+}
+
+#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 ||
+ ACE_HAS_AIO_CALLS) */
diff --git a/ACE/ace/SSL/SSL_Asynch_BIO.h b/ACE/ace/SSL/SSL_Asynch_BIO.h
new file mode 100644
index 00000000000..22c6202754b
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Asynch_BIO.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_Asynch_BIO.h
+ *
+ * $Id$
+ *
+ * @author Alexander Libman <alibman@baltimore.com>
+ * @author Ossama Othman <ossama@uci.edu>
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_SSL_ASYNCH_BIO_H
+#define ACE_SSL_ASYNCH_BIO_H
+
+#include /**/ "ace/pre.h"
+
+#include "SSL_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// This must be included before any <openssl> include on LynxOS
+#include "ace/os_include/os_stdio.h"
+
+#include <openssl/bio.h>
+
+#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+extern BIO * ACE_SSL_make_BIO (void * ssl_asynch_stream);
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL (ACE_WIN32 ||
+ ACE_HAS_AIO_CALLS) */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_ASYNCH_BIO_H */
diff --git a/ACE/ace/SSL/SSL_Asynch_Stream.cpp b/ACE/ace/SSL/SSL_Asynch_Stream.cpp
new file mode 100644
index 00000000000..877125d19c4
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Asynch_Stream.cpp
@@ -0,0 +1,1042 @@
+#include "SSL_Asynch_Stream.h"
+
+ACE_RCSID (ACE_SSL,
+ SSL_Asynch_Stream,
+ "$Id$")
+
+// This only works on platforms with Asynchronous IO support.
+#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+
+#if defined (ACE_WIN32)
+# include "ace/WIN32_Proactor.h"
+#else
+# include "ace/POSIX_Proactor.h"
+#endif /* ACE_WIN32 */
+
+#include "ace/OS_NS_string.h"
+#include "ace/Proactor.h"
+
+#include <openssl/err.h>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_SSL_Asynch_Write_Stream_Result::ACE_SSL_Asynch_Write_Stream_Result
+ (ACE_Handler & handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block & message_block,
+ size_t bytes_to_write,
+ const void * act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number
+ )
+ : AWS_RESULT (handler.proxy (),
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number
+ )
+{
+}
+
+ACE_SSL_Asynch_Read_Stream_Result::ACE_SSL_Asynch_Read_Stream_Result
+ (ACE_Handler & handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block & message_block,
+ size_t bytes_to_read,
+ const void * act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number
+ )
+ : ARS_RESULT (handler.proxy (),
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number
+ )
+{
+}
+
+ACE_SSL_Asynch_Result::ACE_SSL_Asynch_Result (ACE_Handler & handler)
+ : A_RESULT (handler.proxy (),
+ 0, // act,
+ ACE_INVALID_HANDLE,
+ 0, // Offset
+ 0, // OffsetHigh
+ 0, // Priority
+ ACE_SIGRTMIN //signal_number
+ )
+{
+}
+
+void
+ACE_SSL_Asynch_Result::complete (size_t /* bytes_transferred */,
+ int /* success */,
+ const void * /* completion_key */,
+ u_long /* error */)
+{
+ this->handler_proxy_->handler ()->handle_wakeup ();
+}
+
+// ************************************************************
+// ACE_SSL_Asynch_Stream Constructor / Destructor
+// ************************************************************
+ACE_SSL_Asynch_Stream::ACE_SSL_Asynch_Stream (
+ ACE_SSL_Asynch_Stream::Stream_Type s_type,
+ ACE_SSL_Context * context)
+ : type_ (s_type),
+ handle_ (ACE_INVALID_HANDLE),
+ proactor_ (0),
+ ext_handler_ (0),
+ ext_read_result_ (0),
+ ext_write_result_(0),
+ flags_ (0),
+ ssl_ (0),
+ bio_ (0),
+ bio_istream_ (),
+ bio_inp_msg_ (),
+ bio_inp_errno_(0),
+ bio_inp_flag_ (0),
+ bio_ostream_ (),
+ bio_out_msg_ (),
+ bio_out_errno_(0),
+ bio_out_flag_ (0),
+ mutex_ ()
+{
+ ACE_TRACE ("ACE_SSL_Asynch_Stream::ACE_SSL_Asynch_Stream");
+ // was honestly copied from ACE_SSL_SOCK_Stream :)
+
+ ACE_SSL_Context * ctx =
+ (context == 0 ? ACE_SSL_Context::instance () : context);
+
+ this->ssl_ = ::SSL_new (ctx->context ());
+
+ if (this->ssl_ == 0)
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("- cannot allocate new SSL structure")
+ ));
+
+}
+
+ACE_SSL_Asynch_Stream::~ACE_SSL_Asynch_Stream (void)
+{
+ ACE_TRACE ("ACE_SSL_Asynch_Stream::~ACE_SSL_Asynch_Stream");
+
+
+ // It is safe to delete stream if all notifications are received,
+ // i.e., state is SF_DELETE_ENABLE or if proactor event loop is
+ // done.
+ if (this->flags_ & SF_STREAM_OPEN) // open
+ if ((this->flags_ & SF_DELETE_ENABLE) == 0) // but ..
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("ACE_SSL_Asynch_Stream::DTOR-")
+ ACE_TEXT("possible access violation ")
+ ACE_TEXT("if proactor still handles events\n")));
+
+ ::SSL_free (this->ssl_);
+
+ // Was honestly copied from ACE_SSL_SOCK_Stream :)
+
+ // @@ Question: should we reference count the Context object or
+ // leave that to the application developer? We do not reference
+ // count reactors (for example) and following some simple rules
+ // seems to work fine!
+}
+
+// ************************************************************
+// close ()
+// returns :
+// 0 - Stream is in the state SF_DELETE_ENABLE,
+// so it is safe to delete stream
+// -1 - Stream has pending AIO requests,
+// close should be repeated later one more
+// ************************************************************
+
+int
+ACE_SSL_Asynch_Stream::close (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if ((flags_ & SF_STREAM_OPEN) == 0) // not open
+ flags_ |= SF_DELETE_ENABLE;
+
+ if (flags_ & SF_DELETE_ENABLE)
+ return 0;
+
+ flags_ |= SF_REQ_SHUTDOWN;
+
+ this->do_SSL_state_machine ();
+
+ return -1;
+}
+
+// ************************************************************
+// Asynch_Operation interface
+// cancel
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::cancel (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if ((flags_ & SF_STREAM_OPEN) == 0) // not open
+ return 1; // AIO_ALLDONE
+
+ // attempt to cancel internal, i.e. user's read/write
+ int rc_r_int = bio_istream_.cancel();
+ int rc_w_int = bio_ostream_.cancel();
+
+ // attempt to cancel external, i.e. bio_ssl read/write
+ int rc_r_ext = notify_read (0, ERR_CANCELED);
+ int rc_w_ext = notify_write (0, ERR_CANCELED);
+
+ if (rc_r_int < 0 || rc_w_int < 0
+ && rc_r_ext < 0 || rc_w_ext < 0)
+ return -1; // at least one error
+
+ if (rc_r_int == 1 && rc_w_int == 1
+ && rc_r_ext == 1 && rc_w_ext == 1)
+ return 1; // AIO_ALLDONE
+
+ if (rc_r_int == 2 || rc_w_int == 2
+ && rc_r_ext == 2 || rc_w_ext == 2)
+ return 2; // AIO_NOT_CANCELED , at least one not canceled
+
+ return 0; // AIO_CANCELED, at least will be one notification
+}
+
+// ************************************************************
+// Asynch_Operation interface
+// open
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::open (ACE_Handler & handler,
+ ACE_HANDLE handle,
+ const void * completion_key,
+ ACE_Proactor * proactor)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if (this->flags_ & SF_STREAM_OPEN)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- already opened")),
+ -1);
+
+ if (this->ssl_ == 0)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- SSL structure is absent")),
+ -1);
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- invalid handle")),
+ -1);
+
+
+ // Get a proactor for/from the user.
+ this->proactor_ = this->get_proactor (proactor, handler);
+ this->ext_handler_ = & handler;
+ this->handle_ = handle;
+
+ // Open internal input stream
+ if (this->bio_istream_.open (*this, // real callbacks to this
+ handle,
+ completion_key,
+ this->proactor_) != 0)
+ return -1;
+
+ // Open internal output stream
+ if (this->bio_ostream_.open (*this, // real callbacks to this
+ handle,
+ completion_key,
+ this->proactor_) != 0)
+ return -1;
+
+ this->bio_ = ACE_SSL_make_BIO (this);
+
+ if (this->bio_ == 0)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- cannot allocate new BIO structure")),
+ -1);
+
+ ::SSL_set_bio (this->ssl_ , this->bio_ , this->bio_);
+
+ switch (this->type_)
+ {
+ case ST_CLIENT:
+ ::SSL_set_connect_state (this->ssl_);
+ break;
+
+ case ST_SERVER:
+ ::SSL_set_accept_state (this->ssl_);
+ break;
+
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- invalid stream type")),
+ -1);
+ }
+
+ this->flags_ |= SF_STREAM_OPEN;
+
+ this->do_SSL_state_machine ();
+
+ return 0;
+}
+
+
+// ************************************************************
+// Asynch_Operation interface
+// read
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::read (ACE_Message_Block & message_block,
+ size_t bytes_to_read,
+ const void * act,
+ int priority,
+ int signal_number)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if ((this->flags_ & SF_STREAM_OPEN) == 0) // not open
+ return -1;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ return -1;
+
+ // only one read operation is allowed now
+ // later it will be possible to make a queue
+
+ if (this->ext_read_result_ != 0)
+ return -1;
+
+ // create result for future notification
+ ACE_NEW_RETURN (this->ext_read_result_,
+ ACE_SSL_Asynch_Read_Stream_Result (
+ *this->ext_handler_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ this->proactor_->get_handle(),
+ priority,
+ signal_number),
+ -1);
+
+ this->do_SSL_state_machine (); // ignore return code
+
+ return 0;
+}
+
+// ************************************************************
+// Asynch_Operation interface
+// write
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::write (ACE_Message_Block & message_block,
+ size_t bytes_to_write,
+ const void * act,
+ int priority,
+ int signal_number)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if ((this->flags_ & SF_STREAM_OPEN) == 0) // not open
+ return -1;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ return -1;
+
+ // only one read operation is allowed now
+ // later it will be possible to make a queue
+
+ if (this->ext_write_result_ != 0)
+ return -1;
+
+ // create result for future notification
+ ACE_NEW_RETURN (this->ext_write_result_,
+ ACE_SSL_Asynch_Write_Stream_Result (
+ *this->ext_handler_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ this->proactor_->get_handle(),
+ priority,
+ signal_number),
+ -1);
+
+ this->do_SSL_state_machine ();
+
+ return 0;
+}
+
+// ************************************************************
+// Main SSL engine
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_state_machine (void)
+{
+ // this protected member should be called
+ // with locked mutex_
+
+ int retval = this->do_SSL_handshake ();
+
+ if (retval == 0) // handshake in progress ?
+ return 0;
+
+ if (retval < 0)
+ this->flags_ |= SF_REQ_SHUTDOWN;
+
+ this->do_SSL_read (); // execute user read request
+ this->do_SSL_write (); // execute user write request
+
+ if ((this->flags_ & SF_REQ_SHUTDOWN) == 0) // Do we have any errors
+ return 0;
+
+ this->do_SSL_shutdown ();
+
+ this->notify_close ();
+
+ return 0;
+}
+
+// ************************************************************
+// do_SSL_shutdown
+// return code:
+// 1 SSL shutdown is finished already, success
+// 0 SSL shutdown in progress
+// -1 failure
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_shutdown (void)
+{
+ if (this->flags_ & SF_SHUTDOWN_DONE) // already done
+ return 1;
+
+ this->flags_ |= SF_REQ_SHUTDOWN;
+
+ // if we have any uncompleted user requests
+ // than cancel its
+ this->notify_read (0, ERR_CANCELED);
+ this->notify_write (0, ERR_CANCELED);
+
+ int retval = ::SSL_shutdown (this->ssl_);
+
+ int status = ::SSL_get_error (this->ssl_, retval);
+
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ case SSL_ERROR_ZERO_RETURN:
+ case SSL_ERROR_SYSCALL:
+ retval = 1;
+ break;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ // case SSL_ERROR_WANT_ACCEPT:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return 0;
+
+ default:
+ this->print_error (status,
+ ACE_TEXT ("Shutdown error"));
+ retval = -1;
+ break;
+ }
+
+ this->flags_ |= SF_SHUTDOWN_DONE;
+
+ return retval;
+}
+
+// ************************************************************
+// Do SSL handshake if necessary
+// return code:
+// 1 SSL handshake is finished already, success
+// 0 SSL handshake in progress
+// -1 failure
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_handshake (void)
+{
+ if (SSL_is_init_finished (this->ssl_))
+ return 1;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ return -1;
+
+ int retval = -1;
+
+ switch (this->type_)
+ {
+ case ST_CLIENT:
+ retval = ::SSL_connect (this->ssl_);
+ break;
+
+ case ST_SERVER:
+ retval = ::SSL_accept (this->ssl_);
+ break;
+
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("- invalid stream type")),
+ -1);
+ }
+
+ int status = ::SSL_get_error (this->ssl_, retval);
+
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ break;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ //case SSL_ERROR_WANT_ACCEPT:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return 0;
+
+ case SSL_ERROR_ZERO_RETURN:
+ case SSL_ERROR_SYSCALL:
+ default:
+ this->print_error (status,
+ ACE_TEXT ("Handshake error"));
+ return -1;
+ }
+
+ return 1;
+}
+
+// ************************************************************
+// Perform SSL_read call if necessary and notify user
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_read (void)
+{
+ if (this->ext_read_result_ == 0) // nothing to do
+ return 0;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ {
+ this->notify_read (0, ERR_CANCELED);
+ return -1;
+ }
+
+ ACE_Message_Block & mb = this->ext_read_result_->message_block ();
+ size_t bytes_req = this->ext_read_result_->bytes_to_read ();
+
+ ERR_clear_error();
+
+ const int bytes_trn = ::SSL_read (this->ssl_,
+ mb.wr_ptr (),
+ bytes_req);
+
+ int const status = ::SSL_get_error (this->ssl_, bytes_trn);
+
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ this->notify_read (bytes_trn, 0);
+ return 1;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ return 0;
+
+ case SSL_ERROR_ZERO_RETURN:
+ this->notify_read (0, 0);
+ return 1;
+
+ case SSL_ERROR_SYSCALL:
+ if (bytes_trn == 0)
+ {
+ this->notify_read (0, 0);
+ return 1;
+ }
+ // If not an EOF, then fall through to "default" case.
+
+ default:
+ break;
+ }
+
+ this->notify_read (0, EFAULT);
+ this->print_error (status,
+ ACE_TEXT ("SSL_read error"));
+
+ return -1;
+}
+
+// ************************************************************
+// Perform SSL_write call if necessary and notify user
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_write (void)
+{
+ if (this->ext_write_result_ == 0) // nothing to do
+ return 0;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ {
+ this->notify_write (0, ERR_CANCELED);
+ return -1;
+ }
+
+ ACE_Message_Block & mb = this->ext_write_result_->message_block ();
+ size_t bytes_req = this->ext_write_result_->bytes_to_write ();
+
+ ERR_clear_error();
+
+ const int bytes_trn = ::SSL_write (this->ssl_,
+ mb.rd_ptr (),
+ bytes_req);
+
+ int const status = ::SSL_get_error (this->ssl_, bytes_trn);
+
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ this->notify_write (bytes_trn, 0);
+ return 1;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ return 0;
+
+ case SSL_ERROR_ZERO_RETURN:
+ this->notify_write (bytes_trn, 0);
+ return 1;
+
+ case SSL_ERROR_SYSCALL:
+ default:
+ break;
+ }
+
+ this->notify_write(0, EFAULT);
+ this->print_error (status,
+ ACE_TEXT ("SSL_write error"));
+
+ return -1;
+}
+
+// ************************************************************
+// notify external user handler that
+// it is now to safe destroy stream
+// Return code looks like cancel() return code
+// 0 - notified NOTIFIED
+// 1 - nothing to notify ALLDONE
+// 2 - unable to notify NOT NOTIFIED
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::notify_close (void)
+{
+ if (this->flags_ & SF_CLOSE_NTF_SENT) // already sent
+ return 1;
+
+ if ((this->flags_ & SF_SHUTDOWN_DONE) == 0) // only after shutdown
+ return 2; // too early , we will do later
+
+ if (this->pending_BIO_count () != 0) // wait for all internal IO
+ return 2; // too early , we will do later
+
+ // create result for future notification
+ ACE_SSL_Asynch_Result * close_result = 0;
+
+ ACE_NEW_RETURN (close_result,
+ ACE_SSL_Asynch_Result (*this),
+ 2);
+ //@@ Not exception safe!
+
+ int retval =
+ close_result->post_completion (this->proactor_->implementation ());
+
+ if (retval == 0)
+ {
+ this->flags_ |= SF_CLOSE_NTF_SENT;
+ return 0;
+ }
+
+ delete close_result;
+ return 2;
+}
+
+// ************************************************************
+// notify external user handler about user write completion
+// Return code looks like cancel() return code
+// 0 - notified NOTIFIED/CANCELED
+// 1 - nothing to notify ALLDONE
+// 2 - unable to notify NOT NOTIFIED/CANCELED
+// ************************************************************
+
+int
+ACE_SSL_Asynch_Stream::notify_read (int bytes_transferred,
+ int error)
+{
+ if (ext_read_result_ == 0) //nothing to notify
+ return 1;
+
+ this->ext_read_result_->set_bytes_transferred (bytes_transferred);
+ this->ext_read_result_->set_error (error);
+
+ int retval =
+ this->ext_read_result_->post_completion (proactor_->implementation ());
+
+ if (retval == 0)
+ {
+ this->ext_read_result_ = 0;
+ return 0; // success
+ }
+
+ return 2; // unable to notify
+}
+
+// ************************************************************
+// notify external user handler about user write completion
+// Return code looks like cancel() return code
+// 0 - notified NOTIFIED/CANCELED
+// 1 - nothing to notify ALLDONE
+// 2 - unable to notify NOT NOTIFIED/CANCELED
+// ************************************************************
+
+int
+ACE_SSL_Asynch_Stream::notify_write (int bytes_transferred,
+ int error)
+{
+ if (this->ext_write_result_ == 0) //nothing to notify
+ return 1;
+
+ this->ext_write_result_->set_bytes_transferred (bytes_transferred);
+ this->ext_write_result_->set_error (error);
+
+ int retval =
+ this->ext_write_result_->post_completion (
+ this->proactor_->implementation ());
+
+ if (retval == 0)
+ {
+ this->ext_write_result_ = 0;
+ return 0; // success
+ }
+
+ return 2; // unable to notify
+}
+
+// ************************************************************
+// Print SSL errors
+// ************************************************************
+void
+ACE_SSL_Asynch_Stream::print_error (int err_ssl,
+ const ACE_TCHAR * pText)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "SSL-error:%d %s\n" ,
+ err_ssl,
+ pText));
+
+#if OPENSSL_VERSION_NUMBER >= 0x0090601fL
+ // OpenSSL < 0.9.6a doesn't have ERR_error_string_n() function.
+ unsigned long lerr = 0;
+ char buf[1024];
+
+ while ((lerr = ERR_get_error()) != 0)
+ {
+ ERR_error_string_n (lerr, buf, sizeof buf);
+
+ ACE_DEBUG ((LM_DEBUG, "%s\n", buf));
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
+}
+
+// ************************************************************
+// BIO helper functions
+// SSL library will ask BIO to do raw I/O
+// BIO will call us to do this
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::ssl_bio_read (char * buf,
+ size_t len,
+ int & errval)
+{
+ // We do not have to acquire mutex
+ // as we called already with locked mutex
+ // from do_SSL_state_machine()
+
+ errval = 0;
+
+ size_t cur_len = this->bio_inp_msg_.length ();
+
+ if (cur_len > 0) // there are more data buffered
+ {
+ const char * rd_ptr = this->bio_inp_msg_.rd_ptr ();
+
+ if (cur_len > len)
+ cur_len = len;
+
+ ACE_OS::memcpy (buf, rd_ptr, cur_len);
+
+ this->bio_inp_msg_.rd_ptr (cur_len); // go ahead
+
+ return cur_len;
+ }
+
+ if (this->bio_inp_errno_ != 0) // if was error - it is permanent !
+ {
+ errval = this->bio_inp_errno_;
+ return -1;
+ }
+
+ if (this->bio_inp_flag_ & BF_EOS) // End of stream
+ return 0;
+
+ errval = EINPROGRESS; // SSL will try later
+
+ if (this->bio_inp_flag_ & BF_AIO) // we are busy
+ return -1;
+
+ if (this->bio_inp_msg_.size (len) != 0)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l ((%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("error in ACE_Message_Block::size() ")
+ ));
+
+ errval = EINVAL;
+ return -1;
+ }
+
+ char * base = this->bio_inp_msg_.base ();
+
+ this->bio_inp_msg_.rd_ptr (base);
+ this->bio_inp_msg_.wr_ptr (base);
+
+ if (this->bio_istream_.read (
+ bio_inp_msg_, // message block
+ len, // priority
+ 0, // act
+ 0, // priority
+ ACE_SIGRTMIN // default signal
+ ) == -1)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l (%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("attempt read failed")
+ ));
+
+ errval = EINVAL; // may be leave EINPROGRESS ??
+ return -1; // to try later
+ }
+
+ this->bio_inp_flag_ |= BF_AIO; // AIO is active
+
+ return -1;
+}
+
+
+int
+ACE_SSL_Asynch_Stream::ssl_bio_write (const char * buf,
+ size_t len,
+ int & errval)
+{
+ // We do not have to acquire mutex
+ // as we called already with locked mutex
+ // from do_SSL_state_machine
+
+ errval = 0;
+
+ if (this->bio_out_flag_ & BF_AIO) // sorry, we are busy
+ {
+ errval = EINPROGRESS; // try later
+ return -1;
+ }
+
+ if (this->bio_out_errno_ != 0) // no recovery
+ {
+ errval = this->bio_out_errno_;
+ return -1;
+ }
+
+ if (this->bio_out_msg_.size (len) != 0)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l ((%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("error in ACE_Message_Block::size() ")
+ ));
+
+ errval = EINVAL;
+ return -1;
+ }
+
+ char * base = this->bio_out_msg_.base ();
+
+ this->bio_out_msg_.rd_ptr (base);
+ this->bio_out_msg_.wr_ptr (base);
+
+ if (this->bio_out_msg_.copy (buf, len) == -1)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l ((%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("error in ACE_Message_Block::copy() ")
+ ));
+
+ errval = EINVAL;
+ return -1;
+ }
+
+
+ if (this->bio_ostream_.write (
+ this->bio_out_msg_, // message block
+ len, // priority
+ 0, // act
+ 0, // priority
+ ACE_SIGRTMIN // default signal
+ ) == -1)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l ((%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("attempt write failed")
+ ));
+
+ errval = EINVAL; // may be leave EINPROGRESS ??
+ return -1; // to try later
+ }
+
+ this->bio_out_flag_ |= BF_AIO; // AIO is active
+ errval = 0; // Ok, go ahead
+
+ return len;
+}
+
+// ************************************************************
+// Internal IO handlers
+// virtual from ACE_Service_Handler
+// ************************************************************
+void
+ACE_SSL_Asynch_Stream::handle_write_stream (
+ const ACE_Asynch_Write_Stream::Result &result)
+{
+ ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->mutex_));
+
+ this->bio_out_flag_ &= ~BF_AIO;
+
+ ACE_Message_Block & mb = result.message_block ();
+
+ size_t bytes_req = result.bytes_to_write ();
+ size_t bytes_trn = result.bytes_transferred ();
+ u_long errval = result.error ();
+ size_t len = bytes_req - bytes_trn;
+
+ if (errval != 0) // error ?
+ this->bio_out_errno_ = errval; // save err code
+ else if (len > 0) // TCP/IP overloaded ?
+ { // continue, rd_ptr at right place
+ if (this->bio_ostream_.write (
+ mb, // message block
+ len, // priority
+ 0, // act
+ 0, // priority
+ ACE_SIGRTMIN // default signal
+ ) == 0)
+ {
+ this->bio_out_flag_ |= BF_AIO;
+ return;
+ }
+
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("attempt write failed")
+ ));
+
+ this->bio_out_errno_ = EINVAL;
+ }
+
+ this->do_SSL_state_machine ();
+
+ return;
+}
+
+void
+ACE_SSL_Asynch_Stream::handle_read_stream (
+ const ACE_Asynch_Read_Stream::Result &result)
+{
+ ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->mutex_));
+
+ this->bio_inp_flag_ &= ~BF_AIO;
+
+ size_t bytes_trn = result.bytes_transferred ();
+ u_long errval = result.error ();
+
+ if (errval != 0) // error ?
+ this->bio_inp_errno_ = errval; // save err code
+ else if (bytes_trn == 0) // end of stream ?
+ this->bio_inp_flag_ |= BF_EOS; // set flag EOS
+
+ this->do_SSL_state_machine ();
+
+ return;
+}
+
+void
+ACE_SSL_Asynch_Stream::handle_wakeup (void)
+{
+ ACE_Handler * user_handler = 0;
+
+ {
+ ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->mutex_));
+
+ this->flags_ |= SF_DELETE_ENABLE;
+
+ user_handler = this->ext_handler_;
+ }
+
+ if (user_handler != 0)
+ user_handler->handle_wakeup();
+}
+
+int
+ACE_SSL_Asynch_Stream::pending_BIO_count (void)
+{
+ int ret = 0;
+
+ if (this->bio_inp_flag_ & BF_AIO)
+ ++ret;
+
+ if (this->bio_out_flag_ & BF_AIO)
+ ++ret;
+
+ return ret;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 ||
+ ACE_HAS_AIO_CALLS) */
diff --git a/ACE/ace/SSL/SSL_Asynch_Stream.h b/ACE/ace/SSL/SSL_Asynch_Stream.h
new file mode 100644
index 00000000000..671cca46c24
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Asynch_Stream.h
@@ -0,0 +1,425 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_Asynch_Stream.h
+ *
+ * $Id$
+ *
+ * @author Alexander Libman <alibman@baltimore.com>
+ */
+//=============================================================================
+
+#ifndef ACE_SSL_ASYNCH_STREAM_H
+#define ACE_SSL_ASYNCH_STREAM_H
+
+#include /**/ "ace/pre.h"
+#include "SSL_Context.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+
+#include "SSL_Asynch_BIO.h"
+
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Message_Block.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Thread_Mutex.h"
+
+/*
+ * This facility doesn't follow the normal ACE asynch I/O support classes'
+ * interface/implementation arrangement. It's not needed because rather than
+ * branching off to platform-specific APIs, all platforms use the OpenSSL
+ * API. Thus, you can think of this class as the implementation class (for
+ * OpenSSL) and there's no separate interface class.
+ * Also, since both read and write operations are defined in one I/O
+ * factory, there's no single Result class defined as there is for
+ * ACE_Asynch_Read_Stream, et al. There are separate result classes defined
+ * for read and write operations.
+ */
+
+#if defined (ACE_WIN32)
+# include "ace/WIN32_Asynch_IO.h"
+typedef ACE_WIN32_Asynch_Result A_RESULT;
+typedef ACE_WIN32_Asynch_Read_Stream_Result ARS_RESULT;
+typedef ACE_WIN32_Asynch_Write_Stream_Result AWS_RESULT;
+
+# define ERR_CANCELED ERROR_OPERATION_ABORTED
+
+#else
+# include "ace/POSIX_Asynch_IO.h"
+typedef ACE_POSIX_Asynch_Result A_RESULT;
+typedef ACE_POSIX_Asynch_Read_Stream_Result ARS_RESULT;
+typedef ACE_POSIX_Asynch_Write_Stream_Result AWS_RESULT;
+
+# define ERR_CANCELED ECANCELED
+
+#endif /* ACE_WIN32 */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_SSL_Asynch_Stream; // Forward decl for use in result class def.
+
+/**
+ * @class ACE_SSL_Asynch_Read_Stream_Result
+ *
+ * Result class that communicates result of read operations initiated on
+ * an ACE_SSL_Asynch_Stream object.
+ */
+class ACE_SSL_Asynch_Read_Stream_Result : public ARS_RESULT
+{
+ /// Factory class will have special permissions.
+ friend class ACE_SSL_Asynch_Stream;
+
+protected:
+ ACE_SSL_Asynch_Read_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+};
+
+/**
+ * @class ACE_SSL_Asynch_Write_Stream_Result
+ *
+ * Result class that communicates result of write operations initiated on
+ * an ACE_SSL_Asynch_Stream object.
+ */
+class ACE_SSL_Asynch_Write_Stream_Result : public AWS_RESULT
+{
+ /// Factory class will have special permissions.
+ friend class ACE_SSL_Asynch_Stream;
+
+protected:
+ ACE_SSL_Asynch_Write_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+};
+
+
+/**
+ * @class ACE_SSL_Asynch_Result
+ *
+ * Result class that is used internally for socket close notifications.
+ */
+class ACE_SSL_Asynch_Result : public A_RESULT
+{
+public:
+ ACE_SSL_Asynch_Result (ACE_Handler &handler);
+
+ void complete (size_t bytes_transferred,
+ int success,
+ const void * completion_key,
+ u_long error);
+};
+
+
+// Only provide forward declarations to prevent possible abuse of the
+// friend declarations in ACE_SSL_Asynch_Stream.
+struct ACE_SSL_Asynch_Stream_Accessor;
+
+/**
+ * @class ACE_SSL_Asynch_Stream
+ *
+ * @brief This class is a factory for initiating asynchronous reads
+ * and writes on an SSL stream.
+ *
+ * Once open() is called, multiple asynchronous read and write operations
+ * can be started using this class. The handler object (derived from
+ * ACE_Handler) specified in open() will receive completion events for the
+ * operations initiated via this class.
+ */
+class ACE_SSL_Export ACE_SSL_Asynch_Stream
+ : public ACE_Asynch_Operation,
+ public ACE_Handler
+{
+public:
+
+ // Use a class/struct to work around scoping
+ // problems for extern "C" free functions with some compilers. For
+ // example, some can't handle
+ //
+ // friend ::some_extern_c_free_function (...)
+ //
+ // Note that we could use a straight C++ (i.e. not extern "C") free
+ // function, but using a class or struct allows us to hide the
+ // interface from the user, which prevents abuse of this friend
+ // relationship.
+ friend struct ACE_SSL_Asynch_Stream_Accessor;
+
+ enum Stream_Type
+ {
+ ST_CLIENT = 0x0001,
+ ST_SERVER = 0x0002
+ };
+
+ /// Constructor.
+ /**
+ * @arg context Pointer to an ACE_SSL_Context instance containing
+ * the OpenSSL information to be associated with this
+ * ACE_SSL_Asynch_Stream. The needed SSL data will be
+ * copied before return. Therefore, this object can be
+ * reused, modified, or deleted upon return. If a 0 pointer
+ * is passed, the ACE_SSL_Context::instance() method will
+ * be called to get access to a singleton.
+ */
+ ACE_SSL_Asynch_Stream (Stream_Type s_type = ST_SERVER,
+ ACE_SSL_Context * context = 0);
+
+ /// Destructor
+ virtual ~ACE_SSL_Asynch_Stream (void);
+
+ int cancel (void);
+
+ int close (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call.
+ *
+ * @arg handler The ACE_Handler that will be called to handle completions
+ * for operations initiated using this factory.
+ * @arg handle The handle that future read/write operations will use.
+ *
+ * @retval 0 for success.
+ * @retval -1 for failure; consult @c errno for further information.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * Initiates an asynchronous read. If the operation is successfully
+ * initiated, the handle_read_stream() method will be called on the
+ * ACE_Handler object passed to open() when the operation completes.
+ * Data is read into the specified ACE_Message_Block beginning at its
+ * write pointer; the block's write pointer is updated to reflect any
+ * added data when the operation completes.
+ *
+ * @arg message_block The specified ACE_Message_Block will receive any
+ * data that is read. Data will be read into the
+ * block beginning at the block's write pointer.
+ * @arg num_bytes_to_read The maximum number of bytes to read. The actual
+ * amount read may be less.
+ * @arg act ACT which is passed to the completion handler in
+ * the result object.
+ * @arg priority Specifies the operation priority. This has an
+ * affect on POSIX only. Works like @i 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. This parameter has no
+ * affect on Win32.
+ * @arg signal_number The POSIX4 real-time signal number to be used
+ * for the operation. signal_number ranges from
+ * ACE_SIGRTMIN to ACE_SIGRTMAX. This argument is
+ * unused on non-POSIX4 systems.
+ *
+ * @retval 0 for success.
+ * @retval -1 for failure; consult @c errno for further information.
+ */
+ int read (ACE_Message_Block &message_block,
+ size_t num_bytes_to_read,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /**
+ * Initiates an asynchronous write. If the operation is successfully
+ * initiated, the handle_write_stream() method will be called on the
+ * ACE_Handler object passed to open() when the operation completes.
+ * Data is taken from the specified ACE_Message_Block beginning at its
+ * read pointer; the block's read pointer is updated to reflect any
+ * data successfully sent when the operation completes.
+ *
+ * @arg message_block The specified ACE_Message_Block is the source of
+ * data that is written. Data will be taken from the
+ * block beginning at the block's read pointer.
+ * @arg bytes_to_write The maximum number of bytes to write. The actual
+ * amount written may be less.
+ * @arg act ACT which is passed to the completion handler in
+ * the result object.
+ * @arg priority Specifies the operation priority. This has an
+ * affect on POSIX only. Works like @i 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. This parameter has no
+ * affect on Win32.
+ * @arg signal_number The POSIX4 real-time signal number to be used
+ * for the operation. signal_number ranges from
+ * ACE_SIGRTMIN to ACE_SIGRTMAX. This argument is
+ * unused on non-POSIX4 systems.
+ *
+ * @retval 0 for success.
+ * @retval -1 for failure; consult @c errno for further information.
+ */
+ int write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+protected:
+ /// Virtual from ACE_Asynch_Operation. Since this class is essentially an
+ /// implementation class, simply return 0.
+ virtual ACE_Asynch_Operation_Impl *implementation (void) const { return 0; }
+
+ /// virtual from ACE_Handler
+
+ /// This method is called when BIO write request is completed. It
+ /// processes the IO completion and calls do_SSL_state_machine().
+ virtual void handle_write_stream
+ (const ACE_Asynch_Write_Stream::Result &result);
+
+ /// This method is called when BIO read request is completed. It
+ /// processes the IO completion and calls do_SSL_state_machine().
+ virtual void handle_read_stream
+ (const ACE_Asynch_Read_Stream::Result &result);
+
+ /// This method is called when all SSL sessions are closed and no
+ /// more pending AIOs exist. It also calls users handle_wakeup().
+ virtual void handle_wakeup (void);
+
+ /**
+ * @name SSL State Machine
+ */
+ //@{
+ int do_SSL_state_machine (void);
+ int do_SSL_handshake (void);
+ int do_SSL_read (void);
+ int do_SSL_write(void);
+ int do_SSL_shutdown(void);
+ //@}
+
+ void print_error (int err_ssl,
+ const ACE_TCHAR *pText);
+
+ int pending_BIO_count (void);
+
+ /// This method is called to notify user handler when user's read in
+ /// done.
+ int notify_read (int bytes_transferred, int error);
+
+ /// This method is called to notify user handler when user's write
+ /// in done.
+ int notify_write (int bytes_transferred, int error);
+
+ /// This method is called to notify ourself that SSL session is
+ /// shutdown and that there is no more I/O activity now and in the
+ /// future.
+ int notify_close(void);
+
+ /**
+ * @name BIO Helpers
+ */
+ //@{
+ int ssl_bio_read (char * buf, size_t len, int & errval);
+ int ssl_bio_write (const char * buf, size_t len, int & errval);
+ //@}
+
+private:
+
+ // Preventing copying through construction or assignment.
+ ACE_SSL_Asynch_Stream (ACE_SSL_Asynch_Stream const &);
+ ACE_SSL_Asynch_Stream & operator= (ACE_SSL_Asynch_Stream const &);
+
+protected:
+
+ /// Stream Type ST_CLIENT/ST_SERVER
+ Stream_Type type_;
+
+ /// The real file/socket handle
+ ACE_HANDLE handle_;
+
+ /// The proactor
+ ACE_Proactor * proactor_;
+
+ /// External,i.e user handler
+ ACE_Handler * ext_handler_;
+
+ /// External, i.e. read result faked for user
+ ACE_SSL_Asynch_Read_Stream_Result * ext_read_result_ ;
+
+ /// External, i.e. write result faked for user
+ ACE_SSL_Asynch_Write_Stream_Result * ext_write_result_ ;
+
+ /// Stream state/flags
+ enum Stream_Flag
+ {
+ /// istream_ open OK
+ SF_STREAM_OPEN = 0x0001,
+ /// request to SSL shutdown
+ SF_REQ_SHUTDOWN = 0x0002,
+ /// SSL shutdown finished
+ SF_SHUTDOWN_DONE = 0x0004,
+ /// Close notification sent
+ SF_CLOSE_NTF_SENT = 0x0008,
+ /// Stream can be safely destroyed
+ SF_DELETE_ENABLE = 0x0010
+ };
+
+ int flags_;
+
+ /// The SSL session.
+ SSL * ssl_;
+
+ /// The BIO implementation
+ BIO * bio_;
+
+ /// The real streams which work under the ssl connection.
+ /// BIO performs I/O via this streams
+ enum BIO_Flag // internal IO flags
+ {
+ /// End of stream
+ BF_EOS = 0x01,
+ /// Real AIO in progress
+ BF_AIO = 0x02
+ };
+
+ /**
+ * @name Internal stream, buffer and info for BIO read
+ */
+ //@{
+ ACE_Asynch_Read_Stream bio_istream_;
+ ACE_Message_Block bio_inp_msg_;
+ int bio_inp_errno_;
+ int bio_inp_flag_;
+ //@}
+
+ /**
+ * @name Internal stream, buffer and info for BIO write
+ */
+ //@{
+ ACE_Asynch_Write_Stream bio_ostream_;
+ ACE_Message_Block bio_out_msg_;
+ int bio_out_errno_;
+ int bio_out_flag_;
+ //@}
+
+ /// Mutex to protect work
+ ACE_SYNCH_MUTEX mutex_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 ||
+ ACE_HAS_AIO_CALLS) */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_ASYNCH_STREAM_H */
diff --git a/ACE/ace/SSL/SSL_Context.cpp b/ACE/ace/SSL/SSL_Context.cpp
new file mode 100644
index 00000000000..158f42e80d8
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Context.cpp
@@ -0,0 +1,636 @@
+#include "SSL_Context.h"
+
+#include "sslconf.h"
+
+#if !defined(__ACE_INLINE__)
+#include "SSL_Context.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Guard_T.h"
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+#include "ace/Singleton.h"
+#include "ace/Synch_Traits.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+
+#ifdef ACE_HAS_THREADS
+# include "ace/Thread_Mutex.h"
+# include "ace/OS_NS_Thread.h"
+#endif /* ACE_HAS_THREADS */
+
+#include <openssl/x509.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/safestack.h>
+
+ACE_RCSID (ACE_SSL,
+ SSL_Context,
+ "$Id$")
+
+
+namespace
+{
+ /// Reference count of the number of times the ACE_SSL_Context was
+ /// initialized.
+ int ssl_library_init_count = 0;
+
+ // @@ This should also be done with a singleton, otherwise it is not
+ // thread safe and/or portable to some weird platforms...
+
+#ifdef ACE_HAS_THREADS
+ /// Array of mutexes used internally by OpenSSL when the SSL
+ /// application is multithreaded.
+ ACE_SSL_Context::lock_type * ssl_locks = 0;
+
+ // @@ This should also be managed by a singleton.
+#endif
+}
+
+#ifdef ACE_HAS_THREADS
+
+# if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
+# define ACE_SSL_LOCKING_CALLBACK_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_locking_callback)
+# define ACE_SSL_THREAD_ID_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_thread_id)
+# else
+# define ACE_SSL_LOCKING_CALLBACK_NAME ACE_SSL_locking_callback
+# define ACE_SSL_THREAD_ID_NAME ACE_SSL_thread_id
+# endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
+
+
+
+extern "C"
+{
+ void
+ ACE_SSL_LOCKING_CALLBACK_NAME (int mode,
+ int type,
+ const char * /* file */,
+ int /* line */)
+ {
+ // #ifdef undef
+ // fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
+ // CRYPTO_thread_id(),
+ // (mode&CRYPTO_LOCK)?"l":"u",
+ // (type&CRYPTO_READ)?"r":"w",file,line);
+ // #endif
+ // /*
+ // if (CRYPTO_LOCK_SSL_CERT == type)
+ // fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
+ // CRYPTO_thread_id(),
+ // mode,file,line);
+ // */
+ if (mode & CRYPTO_LOCK)
+ (void) ssl_locks[type].acquire ();
+ else
+ (void) ssl_locks[type].release ();
+ }
+
+ // -------------------------------
+
+ // Return the current thread ID. OpenSSL uses this on platforms
+ // that need it.
+ unsigned long
+ ACE_SSL_THREAD_ID_NAME (void)
+ {
+ return (unsigned long) ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::thr_self ();
+ }
+}
+#endif /* ACE_HAS_THREADS */
+
+
+// ****************************************************************
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#ifdef ACE_HAS_THREADS
+ACE_SSL_Context::lock_type * ACE_SSL_Context::locks_ = 0;
+#endif /* ACE_HAS_THREADS */
+
+ACE_SSL_Context::ACE_SSL_Context (void)
+ : context_ (0),
+ mode_ (-1),
+ default_verify_mode_ (SSL_VERIFY_NONE),
+ have_ca_ (0)
+{
+ ACE_SSL_Context::ssl_library_init ();
+}
+
+ACE_SSL_Context::~ACE_SSL_Context (void)
+{
+ if (this->context_)
+ {
+ ::SSL_CTX_free (this->context_);
+ this->context_ = 0;
+ }
+
+ ACE_SSL_Context::ssl_library_fini ();
+}
+
+ACE_SSL_Context *
+ACE_SSL_Context::instance (void)
+{
+ return ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::instance ();
+}
+
+void
+ACE_SSL_Context::ssl_library_init (void)
+{
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
+ ace_ssl_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ if (ssl_library_init_count == 0)
+ {
+ // Initialize the locking callbacks before initializing anything
+ // else.
+#ifdef ACE_HAS_THREADS
+ int const num_locks = ::CRYPTO_num_locks ();
+
+ this->locks_ = new lock_type[num_locks];
+ ssl_locks = this->locks_;
+
+# if !defined (WIN32)
+ // This call isn't necessary on some platforms. See the CRYPTO
+ // library's threads(3) man page for details.
+ ::CRYPTO_set_id_callback (ACE_SSL_THREAD_ID_NAME);
+# endif /* !WIN32 */
+ ::CRYPTO_set_locking_callback (ACE_SSL_LOCKING_CALLBACK_NAME);
+#endif /* ACE_HAS_THREADS */
+
+ ::SSLeay_add_ssl_algorithms ();
+ ::SSL_load_error_strings ();
+
+ // Seed the random number generator. Note that the random
+ // number generator can be seeded more than once to "stir" its
+ // state.
+
+#ifdef WIN32
+ // Seed the random number generator by sampling the screen.
+ ::RAND_screen ();
+#endif /* WIN32 */
+
+#if OPENSSL_VERSION_NUMBER >= 0x00905100L
+ // OpenSSL < 0.9.5 doesn't have EGD support.
+
+ const char *egd_socket_file =
+ ACE_OS::getenv (ACE_SSL_EGD_FILE_ENV);
+
+ if (egd_socket_file != 0)
+ (void) this->egd_file (egd_socket_file);
+#endif /* OPENSSL_VERSION_NUMBER */
+
+ const char *rand_file =
+ ACE_OS::getenv (ACE_SSL_RAND_FILE_ENV);
+
+ if (rand_file != 0)
+ (void) this->seed_file (rand_file);
+
+ // Initialize the mutexes that will be used by the SSL and
+ // crypto library.
+
+ }
+
+ ++ssl_library_init_count;
+}
+
+void
+ACE_SSL_Context::ssl_library_fini (void)
+{
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
+ ace_ssl_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ --ssl_library_init_count;
+ if (ssl_library_init_count == 0)
+ {
+ ::ERR_free_strings ();
+ ::EVP_cleanup ();
+
+ // Clean up the locking callbacks after everything else has been
+ // cleaned up.
+#ifdef ACE_HAS_THREADS
+ ::CRYPTO_set_locking_callback (0);
+ ssl_locks = 0;
+
+ delete [] this->locks_;
+ this->locks_ = 0;
+
+#endif /* ACE_HAS_THREADS */
+ }
+}
+
+int
+ACE_SSL_Context::set_mode (int mode)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_ssl_mon,
+ *ACE_Static_Object_Lock::instance (),
+ -1));
+
+ if (this->context_ != 0)
+ return -1;
+
+ SSL_METHOD *method = 0;
+
+ switch (mode)
+ {
+ case ACE_SSL_Context::SSLv2_client:
+ method = ::SSLv2_client_method ();
+ break;
+ case ACE_SSL_Context::SSLv2_server:
+ method = ::SSLv2_server_method ();
+ break;
+ case ACE_SSL_Context::SSLv2:
+ method = ::SSLv2_method ();
+ break;
+ case ACE_SSL_Context::SSLv3_client:
+ method = ::SSLv3_client_method ();
+ break;
+ case ACE_SSL_Context::SSLv3_server:
+ method = ::SSLv3_server_method ();
+ break;
+ case ACE_SSL_Context::SSLv3:
+ method = ::SSLv3_method ();
+ break;
+ case ACE_SSL_Context::SSLv23_client:
+ method = ::SSLv23_client_method ();
+ break;
+ case ACE_SSL_Context::SSLv23_server:
+ method = ::SSLv23_server_method ();
+ break;
+ case ACE_SSL_Context::SSLv23:
+ method = ::SSLv23_method ();
+ break;
+ case ACE_SSL_Context::TLSv1_client:
+ method = ::TLSv1_client_method ();
+ break;
+ case ACE_SSL_Context::TLSv1_server:
+ method = ::TLSv1_server_method ();
+ break;
+ case ACE_SSL_Context::TLSv1:
+ method = ::TLSv1_method ();
+ break;
+ default:
+ method = ::SSLv3_method ();
+ break;
+ }
+
+ this->context_ = ::SSL_CTX_new (method);
+ if (this->context_ == 0)
+ return -1;
+
+ this->mode_ = mode;
+
+ // Load the trusted certificate authority (default) certificate
+ // locations. But do not return -1 on error, doing so confuses CTX
+ // allocation (severe error) with the less important loading of CA
+ // certificate location error. If it is important for your
+ // application then call ACE_SSL_Context::have_trusted_ca(),
+ // immediately following this call to set_mode().
+ (void) this->load_trusted_ca ();
+
+ return 0;
+}
+
+int
+ACE_SSL_Context::load_trusted_ca (const char* ca_file,
+ const char* ca_dir,
+ bool use_env_defaults)
+{
+ this->check_context ();
+
+ if (ca_file == 0 && use_env_defaults)
+ {
+ // Use the default environment settings.
+ ca_file = ACE_OS::getenv (ACE_SSL_CERT_FILE_ENV);
+ if (ca_file == 0)
+ ca_file = ACE_DEFAULT_SSL_CERT_FILE;
+ }
+
+ if (ca_dir == 0 && use_env_defaults)
+ {
+ // Use the default environment settings.
+ ca_dir = ACE_OS::getenv (ACE_SSL_CERT_DIR_ENV);
+ if (ca_dir == 0)
+ ca_dir = ACE_DEFAULT_SSL_CERT_DIR;
+ }
+
+ // NOTE: SSL_CTX_load_verify_locations() returns 0 on error.
+ if (::SSL_CTX_load_verify_locations (this->context_,
+ ca_file,
+ ca_dir) <= 0)
+ {
+ if (ACE::debug ())
+ ACE_SSL_Context::report_error ();
+ return -1;
+ }
+
+ ++this->have_ca_;
+
+ // For TLS/SSL servers scan all certificates in ca_file and ca_dir and
+ // list them as acceptable CAs when requesting a client certificate.
+ if (mode_ == SSLv23
+ || mode_ == SSLv23_server
+ || mode_ == TLSv1
+ || mode_ == TLSv1_server
+ || mode_ == SSLv3
+ || mode_ == SSLv3_server
+ || mode_ == SSLv2
+ || mode_ == SSLv2_server)
+ {
+ // Note: The STACK_OF(X509_NAME) pointer is a copy of the pointer in
+ // the CTX; any changes to it by way of these function calls will
+ // change the CTX directly.
+ STACK_OF (X509_NAME) * cert_names = 0;
+ cert_names = ::SSL_CTX_get_client_CA_list (this->context_);
+ bool error = false;
+
+ // Add CAs from both the file and dir, if specified. There should
+ // already be a STACK_OF(X509_NAME) in the CTX, but if not, we create
+ // one.
+ if (ca_file)
+ {
+ if (cert_names == 0)
+ {
+ if ((cert_names = ::SSL_load_client_CA_file (ca_file)) != 0)
+ ::SSL_CTX_set_client_CA_list (this->context_, cert_names);
+ else
+ error = true;
+ }
+ else
+ {
+ // Add new certificate names to the list.
+ error = (0 == ::SSL_add_file_cert_subjects_to_stack (cert_names,
+ ca_file));
+ }
+
+ if (error)
+ {
+ if (ACE::debug ())
+ ACE_SSL_Context::report_error ();
+ return -1;
+ }
+ }
+
+ // SSL_add_dir_cert_subjects_to_stack is defined at 0.9.8a (but not
+ // on OpenVMS or Mac Classic); it may be available earlier. Change
+ // this comparison if so.
+#if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090801fL)
+# if !defined (OPENSSL_SYS_VMS) && !defined (OPENSSL_SYS_MACINTOSH_CLASSIC)
+
+ if (ca_dir != 0)
+ {
+ if (cert_names == 0)
+ {
+ if ((cert_names = sk_X509_NAME_new_null ()) == 0)
+ {
+ if (ACE::debug ())
+ ACE_SSL_Context::report_error ();
+ return -1;
+ }
+ ::SSL_CTX_set_client_CA_list (this->context_, cert_names);
+ }
+ if (0 == ::SSL_add_dir_cert_subjects_to_stack (cert_names, ca_dir))
+ {
+ if (ACE::debug ())
+ ACE_SSL_Context::report_error ();
+ return -1;
+ }
+ }
+# endif /* !OPENSSL_SYS_VMS && !OPENSSL_SYS_MACINTOSH_CLASSIC */
+#endif /* OPENSSL_VERSION_NUMBER >= 0.9.8a release */
+
+ }
+
+ return 0;
+}
+
+
+int
+ACE_SSL_Context::private_key (const char *file_name,
+ int type)
+{
+ if (this->private_key_.type () != -1)
+ return 0;
+
+ this->check_context ();
+
+ this->private_key_ = ACE_SSL_Data_File (file_name, type);
+
+ if (::SSL_CTX_use_PrivateKey_file (this->context_,
+ this->private_key_.file_name (),
+ this->private_key_.type ()) <= 0)
+ {
+ this->private_key_ = ACE_SSL_Data_File ();
+ return -1;
+ }
+ else
+ return this->verify_private_key ();
+}
+
+int
+ACE_SSL_Context::verify_private_key (void)
+{
+ this->check_context ();
+
+ return (::SSL_CTX_check_private_key (this->context_) <= 0 ? -1 : 0);
+}
+
+int
+ACE_SSL_Context::certificate (const char *file_name,
+ int type)
+{
+ if (this->certificate_.type () != -1)
+ return 0;
+
+ this->certificate_ = ACE_SSL_Data_File (file_name, type);
+
+ this->check_context ();
+
+ if (::SSL_CTX_use_certificate_file (this->context_,
+ this->certificate_.file_name (),
+ this->certificate_.type ()) <= 0)
+ {
+ this->certificate_ = ACE_SSL_Data_File ();
+ return -1;
+ }
+ else
+ return 0;
+}
+
+int
+ACE_SSL_Context::certificate (X509* cert)
+{
+ // Is it really a good idea to return 0 if we're not setting the
+ // certificate?
+ if (this->certificate_.type () != -1)
+ return 0;
+
+ this->check_context();
+
+ if (::SSL_CTX_use_certificate (this->context_, cert) <= 0)
+ {
+ return -1;
+ }
+ else
+ {
+ // No file is associated with the certificate, set this to a fictional
+ // value so we don't reset it later.
+ this->certificate_ = ACE_SSL_Data_File ("MEMORY CERTIFICATE");
+
+ return 0;
+ }
+}
+
+void
+ACE_SSL_Context::set_verify_peer (int strict, int once, int depth)
+{
+ this->check_context ();
+
+ // Setup the peer verififcation mode.
+
+ int verify_mode = SSL_VERIFY_PEER;
+ if (once)
+ verify_mode |= SSL_VERIFY_CLIENT_ONCE;
+ if (strict)
+ verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+
+ // set the default verify mode
+ this->default_verify_mode (verify_mode);
+
+ // Set the max certificate depth but later let the verify_callback
+ // catch the depth error by adding one to the required depth.
+ if (depth > 0)
+ ::SSL_CTX_set_verify_depth (this->context_, depth + 1);
+}
+
+
+int
+ACE_SSL_Context::random_seed (const char * seed)
+{
+ ::RAND_seed (seed, ACE_OS::strlen (seed));
+
+#if OPENSSL_VERSION_NUMBER >= 0x00905100L
+ // RAND_status() returns 1 if the PRNG has enough entropy.
+ return (::RAND_status () == 1 ? 0 : -1);
+#else
+ return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
+#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
+}
+
+int
+ACE_SSL_Context::egd_file (const char * socket_file)
+{
+#if OPENSSL_VERSION_NUMBER < 0x00905100L
+ // OpenSSL < 0.9.5 doesn't have EGD support.
+ ACE_UNUSED_ARG (socket_file);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ // RAND_egd() returns the amount of entropy used to seed the random
+ // number generator. The actual value should be greater than 16,
+ // i.e. 128 bits.
+ if (::RAND_egd (socket_file) > 0)
+ return 0;
+ else
+ return -1;
+#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
+}
+
+int
+ACE_SSL_Context::seed_file (const char * seed_file, long bytes)
+{
+ // RAND_load_file() returns the number of bytes used to seed the
+ // random number generator. If the file reads ok, check RAND_status to
+ // see if it got enough entropy.
+ if (::RAND_load_file (seed_file, bytes) > 0)
+#if OPENSSL_VERSION_NUMBER >= 0x00905100L
+ // RAND_status() returns 1 if the PRNG has enough entropy.
+ return (::RAND_status () == 1 ? 0 : -1);
+#else
+ return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
+#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
+ else
+ return -1;
+}
+
+void
+ACE_SSL_Context::report_error (unsigned long error_code)
+{
+ if (error_code == 0)
+ return;
+
+ char error_string[256];
+
+ (void) ::ERR_error_string (error_code, error_string);
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_SSL (%P|%t) error code: %u - %C\n"),
+ error_code,
+ error_string));
+}
+
+void
+ACE_SSL_Context::report_error (void)
+{
+ unsigned long err = ::ERR_get_error ();
+ ACE_SSL_Context::report_error (err);
+ ACE_OS::last_error (err);
+}
+
+int
+ACE_SSL_Context::dh_params (const char *file_name,
+ int type)
+{
+ if (this->dh_params_.type () != -1)
+ return 0;
+
+ // For now we only support PEM encodings
+ if (type != SSL_FILETYPE_PEM)
+ return -1;
+
+ this->dh_params_ = ACE_SSL_Data_File (file_name, type);
+
+ this->check_context ();
+
+ {
+ // Swiped from Rescorla's examples and the OpenSSL s_server.c app
+ DH * ret=0;
+ BIO * bio = 0;
+
+ if ((bio = ::BIO_new_file (this->dh_params_.file_name (), "r")) == 0)
+ {
+ this->dh_params_ = ACE_SSL_Data_File ();
+ return -1;
+ }
+
+ ret = PEM_read_bio_DHparams (bio, 0, 0, 0);
+ BIO_free (bio);
+
+ if (ret == 0)
+ {
+ this->dh_params_ = ACE_SSL_Data_File ();
+ return -1;
+ }
+
+ if (::SSL_CTX_set_tmp_dh (this->context_, ret) < 0)
+ {
+ this->dh_params_ = ACE_SSL_Data_File ();
+ return -1;
+ }
+ DH_free (ret);
+ }
+
+ return 0;
+}
+
+// ****************************************************************
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+
+template ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX> *
+ ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::singleton_;
+
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_Context.h b/ACE/ace/SSL/SSL_Context.h
new file mode 100644
index 00000000000..1d7067fa204
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Context.h
@@ -0,0 +1,384 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_Context.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@ece.uci.edu>
+ * @author Ossama Othman <ossama@dre.vanderbilt.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SSL_CONTEXT_H
+#define ACE_SSL_CONTEXT_H
+
+#include /**/ "ace/pre.h"
+
+#include "SSL_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SString.h"
+
+#ifdef ACE_HAS_THREADS
+# include "ace/Synch_Traits.h"
+#endif /* ACE_HAS_THREADS */
+
+#include <openssl/ssl.h>
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_SSL_Export ACE_SSL_Data_File
+{
+public:
+
+ /// Default constructor
+ ACE_SSL_Data_File (void);
+
+ /// Contructor from a file name and the file type.
+ ACE_SSL_Data_File (const char *file_name,
+ int type = SSL_FILETYPE_PEM);
+
+ /// The file name
+ const char *file_name (void) const;
+
+ /// The type
+ int type (void) const;
+
+private:
+
+ /// The file name
+ ACE_CString file_name_;
+
+ /// The type, used by the SSL library to parse the file contents.
+ int type_;
+};
+
+// ****************************************************************
+
+
+/**
+ * @class ACE_SSL_Context
+ *
+ * @brief A wrapper for the OpenSSL SSL_CTX related functions.
+ *
+ * This class provides a wrapper for the SSL_CTX data structure.
+ * Since most applications have a single SSL_CTX structure, this class
+ * can be used as a singleton.
+ */
+class ACE_SSL_Export ACE_SSL_Context
+{
+public:
+
+#ifdef ACE_HAS_THREADS
+ typedef ACE_SYNCH_MUTEX lock_type;
+#endif /* ACE_HAS_THREADS */
+
+ enum {
+ INVALID_METHOD = -1,
+ SSLv2_client = 1,
+ SSLv2_server,
+ SSLv2,
+ SSLv3_client,
+ SSLv3_server,
+ SSLv3,
+ SSLv23_client,
+ SSLv23_server,
+ SSLv23,
+ TLSv1_client,
+ TLSv1_server,
+ TLSv1
+ };
+
+ /// Constructor
+ ACE_SSL_Context (void);
+
+ /// Destructor
+ ~ACE_SSL_Context (void);
+
+ /// The Singleton context, the SSL components use the singleton if
+ /// nothing else is available.
+ static ACE_SSL_Context *instance (void);
+
+ /**
+ * Set the CTX mode. The mode can be set only once, afterwards the
+ * function has no effect and returns -1.
+ * Once the mode is set the underlying SSL_CTX is initialized and
+ * the class can be used.
+ * If the mode is not set, then the class automatically initializes
+ * itself to the default mode.
+ */
+ int set_mode (int mode = ACE_SSL_Context::SSLv23);
+
+ int get_mode (void) const;
+
+ /// Get the SSL context
+ SSL_CTX *context (void);
+
+ /// Get the file name and file format used for the private key
+ int private_key_type (void) const;
+ const char *private_key_file_name (void) const;
+
+ /// Set the private key file.
+ /**
+ * @note This method should only be called after a certificate has
+ * been set since key verification is performed against the
+ * certificate, among other things.
+ */
+ int private_key (const char *file_name, int type = SSL_FILETYPE_PEM);
+
+ /// Verify that the private key is valid.
+ /**
+ * @note This method should only be called after a certificate has
+ * been set since key verification is performed against the
+ * certificate, among other things.
+ */
+ int verify_private_key (void);
+
+ /// Get the file name and file format used for the certificate file
+ int certificate_type (void) const;
+ const char *certificate_file_name (void) const;
+
+ /// Set the certificate file.
+ int certificate (const char *file_name,
+ int type = SSL_FILETYPE_PEM);
+
+ /// Load certificate from memory rather than a file.
+ int certificate (X509* cert);
+
+ /**
+ * Load the location of the trusted certification authority
+ * certificates. Note that CA certificates are stored in PEM format
+ * as a sequence of certificates in @a ca_file or as a set of
+ * individual certificates in @a ca_dir (or both).
+ *
+ * Note this method is called by set_mode() to load the default
+ * environment settings for @a ca_file and @a ca_dir, if any. This
+ * allows for automatic service configuration (and backward
+ * compatibility with previous versions).
+ *
+ * Note that the underlying SSL function will add valid file and
+ * directory names to the load location lists maintained as part of
+ * the SSL_CTX table. It therefore doesn't make sense to keep a
+ * copy of the file and path name of the most recently added
+ * @a ca_file or @a ca_path.
+ *
+ * @param[in] ca_file CA file pathname. Passed to
+ * @c SSL_CTX_load_verify_locations() if not
+ * 0. If 0, behavior depends on the value of
+ * @a use_env_defaults.
+ * @param[in] ca_dir CA directory pathname. Passed to
+ * @c SSL_CTX_load_verify_locations() if not
+ * 0. If 0, behavior depends on the value of
+ * @a use_env_defaults.
+ * @param[in] use_env_defaults If false, the specified @a ca_file argument
+ * is passed to
+ * @c SSL_CTX_load_verify_locations(),
+ * regardless of its value.
+ * If true (the default), additional defaults
+ * can be applied to either @a ca_file,
+ * @a ca_dir, or both. The following
+ * additional defaults are applied when the
+ * @a ca_file argument is 0:
+ * - The @c SSL_CERT_FILE environment variable
+ * will be queried for a file name to use as
+ * the @a ca_file argument. The environment
+ * variable name to query can be changed by
+ * supplying a @c ACE_SSL_CERT_FILE_ENV
+ * configuration item when building ACE.
+ * - If there is no @c SSL_CERT_FILE in the
+ * current environment, the file specified
+ * by the @c ACE_DEFAULT_SSL_CERT_FILE ACE
+ * configuration item will be used. The
+ * default value is "cert.pem" on Windows
+ * and "/etc/ssl/cert.pem" on all other
+ * platforms.
+ * The following additional defaults are
+ * applied when the @a ca_dir argument is 0:
+ * - The @c SSL_CERT_DIR environment variable
+ * will be queried for a file name to use as
+ * the @a ca_dir argument. The environment
+ * variable name to query can be changed by
+ * supplying a @c ACE_SSL_CERT_DIR_ENV
+ * configuration item when building ACE.
+ * - If there is no @c SSL_CERT_DIR in the
+ * current environment, the directory
+ * specified by the @c
+ * ACE_DEFAULT_SSL_CERT_DIR ACE
+ * configuration item will be used. The
+ * default value is "certs" on Windows
+ * and "/etc/ssl/certs" on all other
+ * platforms.
+ *
+ * @return 0 for success or -1 on error.
+ *
+ * @see OpenSSL manual SSL_CTX_load_verify_locations(3) for a
+ * detailed description of the CA file and directory requirements
+ * and processing.
+ */
+ int load_trusted_ca (const char* ca_file = 0,
+ const char* ca_dir = 0,
+ bool use_env_defaults = true);
+
+ /**
+ * Test whether any CA locations have been successfully loaded and
+ * return the number of successful attempts.
+ *
+ * @retval >0 The number of successful CA load attempts.
+ * @retval 0 If all CA load attempts have failed.
+ */
+ int have_trusted_ca (void) const;
+
+
+ /**
+ * @todo Complete this documentation where elipses(...) are used
+ *
+ * @doc Use this method when certificate chain verification is
+ * required. The default server behaviour is SSL_VERIFY_NONE
+ * i.e. client certicates are requested for verified. This method
+ * can be used to configure server to request client certificates
+ * and perform the certificate verification. If <strict> is set
+ * true the client connection is rejected when certificate
+ * verification fails. Otherwise the session is accepted with a
+ * warning, which is the default behaviour. If <once> is set true
+ * (default), certificates are requested only once per session.
+ * The last parameter <depth> can be used to set the verification
+ * depth.
+ *
+ * Note for verification to work correctly there should be a valid
+ * CA name list set using load_trusted_ca().
+ *
+ * @see OpenSSL documentation of SSL_CTX_set_verify(3) for details of
+ * the verification process.
+ *
+ * @see OpenSSL documentation ... set_verify_depth(3) ...
+ *
+ * Note that this method overrides the use of the
+ * default_verify_mode() method.
+ */
+ void set_verify_peer (int strict = 0, int once = 1, int depth = 0);
+
+
+ /// TODO: a implementation that will lookup the CTX table for the list
+ /// of files and paths etc.
+ /// Query the location of trusted certification authority
+ /// certificates.
+ // const char* ca_file_name(void) const;
+ // const char* ca_dir_name(void) const;
+
+ /**
+ * Set and query the default verify mode for this context, it is
+ * inherited by all the ACE_SSL objects created using the context.
+ * It can be overriden on a per-ACE_SSL object.
+ */
+ void default_verify_mode (int mode);
+ int default_verify_mode (void) const;
+
+ /**
+ * @name OpenSSL Random Number Generator Seed Related Methods
+ *
+ * These are methods that can be used to seed OpenSSL's
+ * pseudo-random number generator. These methods can be called more
+ * than once.
+ */
+ //@{
+ /// Seed the underlying random number generator. This value should
+ /// have at least 128 bits of entropy.
+ static int random_seed (const char * seed);
+
+ /// Set the Entropy Gathering Daemon (EGD) UNIX domain socket file to
+ /// read random seed values from.
+ static int egd_file (const char * socket_file);
+
+ /**
+ * Set the file that contains the random seed value state, and the
+ * amount of bytes to read. "-1" bytes causes the entire file to be
+ * read.
+ */
+ static int seed_file (const char * seed_file, long bytes = -1);
+ //@}
+
+ /// Print SSL error corresponding to the given error code.
+ static void report_error (unsigned long error_code);
+
+ /// Print the last SSL error for the current thread.
+ static void report_error (void);
+
+ /**
+ * @name Diffie-Hellman (DH) Parameters
+ *
+ * When using DSS-based certificates, Diffie-Hellman keys need to be
+ * exchanged. These must be provided in the form of DH key
+ * generation parameters loaded in, or as fixed keys hardcoded into
+ * the code itself. ACE_SSL supports loaded parameters.
+ *
+ */
+ //@{
+ /**
+ * Load Diffie-Hellman parameters from file_name. The specified file can be
+ * a standalone file containing only DH parameters (e.g., as created
+ * by <code>openssl dhparam</code>), or it can be a certificate which has
+ * a PEM-encoded set of DH params concatenated on to i.
+ */
+ int dh_params (const char *file_name, int type = SSL_FILETYPE_PEM);
+ const char *dh_params_file_name () const;
+ int dh_params_file_type () const;
+ //@}
+
+private:
+
+ /// Verify if the context has been initialized or not.
+ void check_context (void);
+
+ /// @@ More to document
+ void ssl_library_init ();
+ void ssl_library_fini ();
+
+ // = Prevent assignment and copy initialization.
+ //@{
+ ACE_SSL_Context (const ACE_SSL_Context &);
+ ACE_SSL_Context & operator= (const ACE_SSL_Context &);
+ //@}
+
+private:
+
+ /// The SSL_CTX structure
+ SSL_CTX *context_;
+
+ /// Cache the mode so we can answer fast
+ int mode_;
+
+ /// The private key, certificate, and Diffie-Hellman paramters files
+ ACE_SSL_Data_File private_key_;
+ ACE_SSL_Data_File certificate_;
+ ACE_SSL_Data_File dh_params_;
+
+ /// The default verify mode.
+ int default_verify_mode_;
+
+ /// count of successful CA load attempts
+ int have_ca_;
+
+#ifdef ACE_HAS_THREADS
+ /// Array of mutexes used internally by OpenSSL when the SSL
+ /// application is multithreaded.
+ static lock_type * locks_;
+#endif /* ACE_HAS_THREADS */
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined(__ACE_INLINE__)
+#include "SSL_Context.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_CONTEXT_H */
diff --git a/ACE/ace/SSL/SSL_Context.inl b/ACE/ace/SSL/SSL_Context.inl
new file mode 100644
index 00000000000..9962ad09bdc
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Context.inl
@@ -0,0 +1,113 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SSL_Data_File::ACE_SSL_Data_File (void)
+ : type_ (-1)
+{
+}
+
+ACE_INLINE
+ACE_SSL_Data_File::ACE_SSL_Data_File (const char *file_name,
+ int type)
+ : file_name_ (file_name),
+ type_ (type)
+{
+}
+
+ACE_INLINE const char *
+ACE_SSL_Data_File::file_name (void) const
+{
+ return this->file_name_.c_str ();
+}
+
+ACE_INLINE int
+ACE_SSL_Data_File::type (void) const
+{
+ return this->type_;
+}
+
+// ****************************************************************
+
+ACE_INLINE void
+ACE_SSL_Context::check_context (void)
+{
+ if (this->context_ == 0)
+ {
+ this->set_mode ();
+ }
+
+ ::SSL_CTX_set_verify (this->context_, this->default_verify_mode (), 0);
+}
+
+ACE_INLINE SSL_CTX *
+ACE_SSL_Context::context (void)
+{
+ this->check_context ();
+ return this->context_;
+}
+
+ACE_INLINE int
+ACE_SSL_Context::private_key_type (void) const
+{
+ return this->private_key_.type ();
+}
+
+ACE_INLINE const char*
+ACE_SSL_Context::private_key_file_name (void) const
+{
+ return this->private_key_.file_name ();
+}
+
+ACE_INLINE int
+ACE_SSL_Context::certificate_type (void) const
+{
+ return this->certificate_.type ();
+}
+
+ACE_INLINE const char*
+ACE_SSL_Context::certificate_file_name (void) const
+{
+ return this->certificate_.file_name ();
+}
+
+ACE_INLINE int
+ACE_SSL_Context::dh_params_file_type (void) const
+{
+ return this->dh_params_.type ();
+}
+
+ACE_INLINE const char*
+ACE_SSL_Context::dh_params_file_name (void) const
+{
+ return this->dh_params_.file_name ();
+}
+
+ACE_INLINE void
+ACE_SSL_Context::default_verify_mode (int mode)
+{
+ this->default_verify_mode_ = mode;
+}
+
+ACE_INLINE int
+ACE_SSL_Context::default_verify_mode (void) const
+{
+ return this->default_verify_mode_;
+}
+
+ACE_INLINE int
+ACE_SSL_Context::get_mode (void) const
+{
+ return this->mode_;
+}
+
+ACE_INLINE int
+ACE_SSL_Context::have_trusted_ca (void) const
+{
+ return this->have_ca_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_Export.h b/ACE/ace/SSL/SSL_Export.h
new file mode 100644
index 00000000000..542ec536f5a
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Export.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by
+// generate_export_file.pl
+// ------------------------------
+#if !defined (ACE_SSL_EXPORT_H)
+#define ACE_SSL_EXPORT_H
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_SSL_HAS_DLL)
+# define ACE_SSL_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ACE_SSL_HAS_DLL */
+
+#if !defined (ACE_SSL_HAS_DLL)
+#define ACE_SSL_HAS_DLL 1
+#endif /* ! ACE_SSL_HAS_DLL */
+
+#if defined (ACE_SSL_HAS_DLL)
+# if (ACE_SSL_HAS_DLL == 1)
+# if defined (ACE_SSL_BUILD_DLL)
+# define ACE_SSL_Export ACE_Proper_Export_Flag
+# define ACE_SSL_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else
+# define ACE_SSL_Export ACE_Proper_Import_Flag
+# define ACE_SSL_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ACE_SSL_BUILD_DLL */
+# else
+# define ACE_SSL_Export
+# define ACE_SSL_SINGLETON_DECLARATION(T)
+# define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ! ACE_SSL_HAS_DLL == 1 */
+#else
+# define ACE_SSL_Export
+# define ACE_SSL_SINGLETON_DECLARATION(T)
+# define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* ACE_SSL_HAS_DLL */
+
+#endif /* ACE_SSL_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/SSL/SSL_SOCK.cpp b/ACE/ace/SSL/SSL_SOCK.cpp
new file mode 100644
index 00000000000..fdcc95ddd11
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK.cpp
@@ -0,0 +1,72 @@
+// $Id$
+
+#include "SSL_SOCK.h"
+
+#if !defined (__ACE_INLINE__)
+#include "SSL_SOCK.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/OS_NS_errno.h"
+#include "ace/os_include/os_signal.h"
+
+ACE_RCSID (ACE_SSL,
+ SSL_SOCK,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_SSL_SOCK::ACE_SSL_SOCK (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK::ACE_SSL_SOCK");
+}
+
+ACE_SSL_SOCK::~ACE_SSL_SOCK (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK::~ACE_SSL_SOCK");
+}
+
+int
+ACE_SSL_SOCK::enable (int value) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK::enable");
+
+ switch (value)
+ {
+#ifdef SIGURG
+ case SIGURG:
+ case ACE_SIGURG:
+#endif /* SIGURG */
+ case SIGIO:
+ case ACE_SIGIO:
+ case ACE_CLOEXEC:
+ ACE_NOTSUP_RETURN (-1);
+ case ACE_NONBLOCK:
+ return ACE_IPC_SAP::enable (value);
+ default:
+ return -1;
+ }
+}
+
+int
+ACE_SSL_SOCK::disable (int value) const
+{
+ ACE_TRACE("ACE_SSL_SOCK::disable");
+ switch (value)
+ {
+#ifdef SIGURG
+ case SIGURG:
+ case ACE_SIGURG:
+#endif /* SIGURG */
+ case SIGIO:
+ case ACE_SIGIO:
+ case ACE_CLOEXEC:
+ ACE_NOTSUP_RETURN (-1);
+ case ACE_NONBLOCK:
+ return ACE_IPC_SAP::disable (value);
+ default:
+ return -1;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_SOCK.h b/ACE/ace/SSL/SSL_SOCK.h
new file mode 100644
index 00000000000..ad24db3a3cd
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK.h
@@ -0,0 +1,103 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_SOCK.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@ece.uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SSL_SOCK_H
+#define ACE_SSL_SOCK_H
+
+#include /**/ "ace/pre.h"
+
+#include "SSL_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK.h"
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+# define ACE_SSL_SOCK_ACCEPTOR ACE_SSL_SOCK_Acceptor
+# define ACE_SSL_SOCK_CONNECTOR ACE_SSL_SOCK_Connector
+# define ACE_SSL_SOCK_STREAM ACE_SSL_SOCK_Stream
+#else
+# define ACE_SSL_SOCK_ACCEPTOR ACE_SSL_SOCK_Acceptor, ACE_INET_Addr
+# define ACE_SSL_SOCK_CONNECTOR ACE_SSL_SOCK_Connector, ACE_INET_Addr
+# define ACE_SSL_SOCK_STREAM ACE_SSL_SOCK_Stream, ACE_INET_Addr
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SSL_SOCK
+ *
+ * @brief An abstract class that forms the basis for more specific
+ * classes, such as "ACE_SSL_SOCK_Acceptor" and
+ * "ACE_SSL_SOCK_Stream". Do not instantiate this class.
+ *
+ * This class provides functions that are common to all of the
+ * ACE_SSL_SOCK_* classes. ACE_SSL_SOCK provides the ability
+ * to get and set socket options, get the local and remote
+ * addresses, and close the socket.
+ */
+class ACE_SSL_Export ACE_SSL_SOCK : public ACE_SOCK
+{
+public:
+
+ /**
+ * Override ACE_SOCK base class implementations with these SSL
+ * specific ones.
+ */
+ //@{
+ int set_option (int level,
+ int option,
+ void *optval,
+ int optlen) const;
+ int get_option (int level,
+ int option,
+ void *optval,
+ int *optlen) const;
+ int enable (int value) const;
+ int disable (int value) const;
+ void set_handle (ACE_HANDLE);
+ ACE_HANDLE get_handle (void) const;
+ int control (int cmd, void *arg) const;
+ //@}
+
+protected:
+
+ /// Default constructor is private to prevent instances of this class
+ /// from being defined.
+ ACE_SSL_SOCK (void);
+
+ /// Destructor
+ /**
+ * Not a virtual destructor. Protected destructor to prevent
+ * operator delete() from being called through a base class
+ * ACE_SSL_SOCK pointer/reference.
+ */
+ ~ACE_SSL_SOCK (void);
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "SSL_SOCK.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_SOCK_H */
+
+
+
+
diff --git a/ACE/ace/SSL/SSL_SOCK.inl b/ACE/ace/SSL/SSL_SOCK.inl
new file mode 100644
index 00000000000..1a39d5214dc
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK.inl
@@ -0,0 +1,71 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_SSL_SOCK::set_handle (ACE_HANDLE fd)
+{
+ this->ACE_SOCK::set_handle (fd);
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_SSL_SOCK::get_handle (void) const
+{
+ // return this->ssl_ ? (ACE_HANDLE) ::SSL_get_fd (this->ssl_) : ACE_INVALID_HANDLE;
+ return this->ACE_SOCK::get_handle ();
+}
+
+
+ACE_INLINE int
+ACE_SSL_SOCK::control (int cmd, void *arg) const
+{
+ return ACE_OS::ioctl (this->get_handle (), cmd, arg);
+}
+
+ACE_INLINE int
+ACE_SSL_SOCK::set_option (int level,
+ int option,
+ void *optval,
+ int optlen) const
+{
+// switch (option)
+// {
+// case SO_SNDBUF:
+// return ::BIO_set_write_buffer_size (this->io_bio_, *((int *) optval));
+// case SO_RCVCBUF:
+// return ::BIO_set_read_buffer_size (this->io_bio_, *((int *) optval));
+// default:
+ return ACE_OS::setsockopt (this->get_handle (),
+ level,
+ option, (char *) optval,
+ optlen);
+// }
+}
+
+// Provides access to the ACE_OS::getsockopt system call.
+
+ACE_INLINE int
+ACE_SSL_SOCK::get_option (int level,
+ int option,
+ void *optval,
+ int *optlen) const
+{
+// switch (option)
+// {
+// case SO_SNDBUF:
+// return ::BIO_get_write_buffer_size (this->io_bio_, *((int *) optval));
+// case SO_RCVCBUF:
+// return ::BIO_get_read_buffer_size (this->io_bio_, *((int *) optval));
+// default:
+ return ACE_OS::getsockopt (this->get_handle (),
+ level,
+ option, (char *) optval,
+ optlen);
+// }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_SOCK_Acceptor.cpp b/ACE/ace/SSL/SSL_SOCK_Acceptor.cpp
new file mode 100644
index 00000000000..80b62b5c1ce
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Acceptor.cpp
@@ -0,0 +1,249 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#include "SSL_SOCK_Acceptor.h"
+
+#include "ace/Handle_Set.h"
+#include "ace/OS_Errno.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+#include "ace/Countdown_Time.h"
+
+#if !defined (__ACE_INLINE__)
+#include "SSL_SOCK_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ACE_SSL,
+ SSL_SOCK_Acceptor,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Acceptor)
+
+ACE_SSL_SOCK_Acceptor::~ACE_SSL_SOCK_Acceptor (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Acceptor::~ACE_SSL_SOCK_Acceptor");
+}
+
+
+int
+ACE_SSL_SOCK_Acceptor::ssl_accept (ACE_SSL_SOCK_Stream &new_stream,
+ ACE_Time_Value *timeout) const
+{
+ SSL *ssl = new_stream.ssl ();
+
+ if (SSL_is_init_finished (ssl))
+ return 0;
+
+ if (!SSL_in_accept_init (ssl))
+ ::SSL_set_accept_state (ssl);
+
+ ACE_HANDLE handle = new_stream.get_handle ();
+
+ // We're going to call SSL_accept, optionally doing ACE::select and
+ // retrying the SSL_accept, until the SSL handshake is done or
+ // it fails.
+ // To get the timeout affect, set the socket to nonblocking mode
+ // before beginning if there is a timeout specified. If the timeout
+ // is 0 (wait as long as it takes) then don't worry about the blocking
+ // status; we'll block in SSL_accept if the socket is blocking, and
+ // block in ACE::select if not.
+ int reset_blocking_mode = 0;
+ if (timeout != 0)
+ {
+ reset_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 (reset_blocking_mode
+ && ACE::set_flags (handle,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ }
+
+ // Take into account the time between each select() call below.
+ ACE_Countdown_Time countdown (timeout);
+
+ int status;
+ do
+ {
+ // These handle sets are used to set up for whatever SSL_accept
+ // says it wants next. They're reset on each pass around the loop.
+ ACE_Handle_Set rd_handle;
+ ACE_Handle_Set wr_handle;
+
+ status = ::SSL_accept (ssl);
+ switch (::SSL_get_error (ssl, status))
+ {
+ case SSL_ERROR_NONE:
+ status = 0; // To tell caller about success
+ break; // Done
+
+ case SSL_ERROR_WANT_WRITE:
+ wr_handle.set_bit (handle);
+ status = 1; // Wait for more activity
+ break;
+
+ case SSL_ERROR_WANT_READ:
+ rd_handle.set_bit (handle);
+ status = 1; // Wait for more activity
+ break;
+
+ case SSL_ERROR_ZERO_RETURN:
+ // The peer has notified us that it is shutting down via
+ // the SSL "close_notify" message so we need to
+ // shutdown, too.
+ status = -1;
+ break;
+
+ case SSL_ERROR_SYSCALL:
+ // On some platforms (e.g. MS Windows) OpenSSL does not
+ // store the last error in errno so explicitly do so.
+ //
+ // Explicitly check for EWOULDBLOCK since it doesn't get
+ // converted to an SSL_ERROR_WANT_{READ,WRITE} on some
+ // platforms. If SSL_accept failed outright, though, don't
+ // bother checking more. This can happen if the socket gets
+ // closed during the handshake.
+ if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK &&
+ status == -1)
+ {
+ // Although the SSL_ERROR_WANT_READ/WRITE isn't getting
+ // set correctly, the read/write state should be valid.
+ // Use that to decide what to do.
+ status = 1; // Wait for more activity
+ if (SSL_want_write (ssl))
+ wr_handle.set_bit (handle);
+ else if (SSL_want_read (ssl))
+ rd_handle.set_bit (handle);
+ else
+ status = -1; // Doesn't want anything - bail out
+ }
+ else
+ status = -1;
+ break;
+
+ default:
+ ACE_SSL_Context::report_error ();
+ status = -1;
+ break;
+ }
+
+ if (status == 1)
+ {
+ // Must have at least one handle to wait for at this point.
+ ACE_ASSERT (rd_handle.num_set() == 1 || wr_handle.num_set () == 1);
+ status = ACE::select (int (handle) + 1,
+ &rd_handle,
+ &wr_handle,
+ 0,
+ timeout);
+
+ (void) countdown.update ();
+
+ // 0 is timeout, so we're done.
+ // -1 is error, so we're done.
+ // Could be both handles set (same handle in both masks) so
+ // set to 1.
+ if (status >= 1)
+ status = 1;
+ else // Timeout or failure
+ status = -1;
+ }
+
+ } while (status == 1 && !SSL_is_init_finished (ssl));
+
+ if (reset_blocking_mode)
+ {
+ ACE_Errno_Guard eguard (errno);
+ ACE::clr_flags (handle, ACE_NONBLOCK);
+ }
+
+ return (status == -1 ? -1 : 0);
+
+}
+
+// General purpose routine for accepting new connections.
+// Since our underlying acceptor is of the plain old ACE_SOCK_Acceptor
+// variety, get the basic socket setup done with it, then take care of
+// the SSL handshake if the socket is accepted.
+int
+ACE_SSL_SOCK_Acceptor::accept (ACE_SSL_SOCK_Stream &new_stream,
+ ACE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Acceptor::accept");
+
+ // Take into account the time to complete the basic TCP handshake
+ // and the SSL handshake.
+ ACE_Countdown_Time countdown (timeout);
+
+ ACE_SOCK_Stream temp_stream;
+ if (-1 == this->acceptor_.accept (temp_stream,
+ remote_addr,
+ timeout,
+ restart,
+ reset_new_handle))
+ return -1;
+
+ (void) countdown.update ();
+
+ new_stream.set_handle (temp_stream.get_handle ());
+ temp_stream.set_handle (ACE_INVALID_HANDLE);
+
+ if (this->ssl_accept (new_stream, timeout) == -1)
+ {
+ new_stream.close ();
+ new_stream.set_handle (ACE_INVALID_HANDLE);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int
+ACE_SSL_SOCK_Acceptor::accept (ACE_SSL_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_SSL_SOCK_Acceptor::accept");
+
+ // Take into account the time to complete the basic TCP handshake
+ // and the SSL handshake.
+ ACE_Countdown_Time countdown (timeout);
+
+ ACE_SOCK_Stream temp_stream;
+ if (-1 == this->acceptor_.accept (temp_stream,
+ qos_params,
+ remote_addr,
+ timeout,
+ restart,
+ reset_new_handle))
+ return -1;
+
+ (void) countdown.update ();
+
+ new_stream.set_handle (temp_stream.get_handle ());
+ temp_stream.set_handle (ACE_INVALID_HANDLE);
+
+ if (this->ssl_accept (new_stream, timeout) == -1)
+ {
+ new_stream.close ();
+ new_stream.set_handle (ACE_INVALID_HANDLE);
+ return -1;
+ }
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_SOCK_Acceptor.h b/ACE/ace/SSL/SSL_SOCK_Acceptor.h
new file mode 100644
index 00000000000..0c4609c2c73
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Acceptor.h
@@ -0,0 +1,198 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_SOCK_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author John Heitmann
+ * @author Chris Zimman
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SSL_SOCK_ACCEPTOR_H
+#define ACE_SSL_SOCK_ACCEPTOR_H
+
+#include /**/ "ace/pre.h"
+
+#include "SSL_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "SSL_SOCK_Stream.h"
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/OS_QoS.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SSL_SOCK_Acceptor
+ *
+ * @brief Defines a factory that creates new @c ACE_SSL_SOCK_Stream
+ * objects passively.
+ *
+ * The ACE_SSL_SOCK_Acceptor has its own @c ACE_SOCK_Acceptor
+ * which handles the basic socket acceptance. This class is a
+ * wrapper which adds the SSL acceptance handshake handling.
+ * Since SSL is record oriented, some additional steps must be taken
+ * after the basic socket acceptance to complete the SSL handshake that
+ * takes place at session establishment.
+ *
+ * @note The user must currently ensure that only one thread services
+ * a given SSL session at any given time since some underlying
+ * SSL implementations, such as OpenSSL, are not entirely
+ * thread-safe or reentrant.
+ */
+class ACE_SSL_Export ACE_SSL_SOCK_Acceptor : public ACE_SSL_SOCK
+{
+public:
+
+ /// Default constructor.
+ ACE_SSL_SOCK_Acceptor (void);
+
+ /// Default destructor.
+ ~ACE_SSL_SOCK_Acceptor (void);
+
+ /**
+ * Initiate a passive mode SSL/BSD-style acceptor socket.
+ * @param local_sap The address that we're going to listen for
+ * connections on. If this is @c ACE_Addr::sap_any,
+ * this socket listens on an the "any" IP address
+ * and selects an unused port. To find out what port
+ * was selected, call this object's
+ * @c ACE_SOCK::get_local_addr(ACE_Addr&) method
+ * upon return.
+ */
+ ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /**
+ * Initiate a passive-mode QoS-enabled acceptor socket.
+ * @param local_sap The address that we're going to listen for
+ * connections on. If this is @c ACE_Addr::sap_any,
+ * this socket listens on an the "any" IP address
+ * and selects an unused port. To find out what port
+ * was selected, call this object's
+ * @c ACE_SOCK::get_local_addr(ACE_Addr&) method
+ * upon return.
+ */
+ ACE_SSL_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);
+
+ /**
+ * Initiate a passive mode SSL/BSD-style acceptor socket.
+ * @param local_sap The address that we're going to listen for
+ * connections on. If this is @c ACE_Addr::sap_any,
+ * this socket listens on an the "any" IP address
+ * and selects an unused port. To find out what port
+ * was selected, call this object's
+ * @c ACE_SOCK::get_local_addr(ACE_Addr&) method
+ * upon return.
+ *
+ * @return 0 if success; -1 for failure (errno contains error code).
+ */
+ int open (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /// Close the listening socket.
+ int close (void);
+
+ /**
+ * @name Passive Connection "accept" Methods
+ *
+ * These are the canonical methods exposed by the Acceptor pattern.
+ */
+ //@{
+ /**
+ * Accept a new ACE_SSL_SOCK_Stream connection. On successful return,
+ * the socket has been accepted and the SSL handshake has been completed.
+ * @param new_stream The @c ACE_SSL_SOCK_Stream object that will receive
+ * the new SSL socket.
+ * @param remote_addr Pointer to an @c ACE_INET_Addr object that will
+ * receive the address of the peer that connected.
+ * @param timeout The maximum time to wait for the combined socket
+ * acceptance and handshake completion. 0 means
+ * block forever, a timeout of {0, 0} means poll.
+ * @param restart 1 means "restart if interrupted," that is,
+ * if errno == EINTR.
+ *
+ * @return 0 if success; -1 for failure (errno contains error code).
+ */
+ int accept (ACE_SSL_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_SSL_SOCK_Stream connection using the RVSP QoS
+ * information in qos_params.
+ * @param new_stream The @c ACE_SSL_SOCK_Stream object that will receive
+ * the new SSL socket.
+ * @param remote_addr Pointer to an @c ACE_INET_Addr object that will
+ * receive the address of the peer that connected.
+ * @param timeout The maximum time to wait for the combined socket
+ * acceptance and handshake completion. 0 means
+ * block forever, a timeout of {0, 0} means poll.
+ * @param restart 1 means "restart if interrupted," that is,
+ * if errno == EINTR.
+ *
+ * @return 0 if success; -1 for failure (errno contains error code).
+ */
+ int accept (ACE_SSL_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_SSL_SOCK_Stream PEER_STREAM;
+ //@}
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ /// Complete SSL passive connection establishment.
+ int ssl_accept (ACE_SSL_SOCK_Stream &new_stream,
+ ACE_Time_Value *timeout) const;
+
+private:
+
+ /// The BSD-socket workhorse
+ ACE_SOCK_Acceptor acceptor_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "SSL_SOCK_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_SOCK_ACCEPTOR_H */
diff --git a/ACE/ace/SSL/SSL_SOCK_Acceptor.inl b/ACE/ace/SSL/SSL_SOCK_Acceptor.inl
new file mode 100644
index 00000000000..7fd8cb04095
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Acceptor.inl
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor (void)
+ : acceptor_ ()
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor");
+}
+
+ACE_INLINE
+ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+ : acceptor_ (local_sap,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor");
+
+ this->set_handle (this->acceptor_.get_handle ());
+}
+
+ACE_INLINE
+ACE_SSL_SOCK_Acceptor::ACE_SSL_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)
+ : acceptor_ (local_sap,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor");
+
+ this->set_handle (this->acceptor_.get_handle ());
+}
+
+ACE_INLINE int
+ACE_SSL_SOCK_Acceptor::open (const ACE_Addr &local_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Acceptor::open");
+ if (this->acceptor_.open (local_sap,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol) != 0)
+ return -1;
+ else
+ this->set_handle (this->acceptor_.get_handle ());
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_SSL_SOCK_Acceptor::close (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Acceptor::close ()");
+
+ int result = this->acceptor_.close ();
+ this->set_handle (ACE_INVALID_HANDLE);
+
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_SOCK_Connector.cpp b/ACE/ace/SSL/SSL_SOCK_Connector.cpp
new file mode 100644
index 00000000000..0c6569e59ac
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Connector.cpp
@@ -0,0 +1,411 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "SSL_SOCK_Connector.h"
+
+#include "ace/OS_NS_errno.h"
+#include "ace/Handle_Set.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/Countdown_Time.h"
+
+#include <openssl/err.h>
+
+#if !defined (__ACE_INLINE__)
+#include "SSL_SOCK_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ACE_SSL,
+ SSL_SOCK_Connector,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Connector)
+
+ACE_SSL_SOCK_Connector::~ACE_SSL_SOCK_Connector (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::~ACE_SSL_SOCK_Connector");
+}
+
+int
+ACE_SSL_SOCK_Connector::ssl_connect (ACE_SSL_SOCK_Stream &new_stream,
+ const ACE_Time_Value *timeout)
+{
+ SSL *ssl = new_stream.ssl ();
+
+ if (SSL_is_init_finished (ssl))
+ return 0;
+
+ // Check if a connection is already pending for the given SSL
+ // structure.
+ if (!SSL_in_connect_init (ssl))
+ ::SSL_set_connect_state (ssl);
+
+ ACE_HANDLE handle = new_stream.get_handle ();
+
+ // We're going to call SSL_connect, optionally doing ACE::select and
+ // retrying the SSL_connect, until the SSL handshake is done or
+ // it fails.
+ // To get the timeout affect, set the socket to nonblocking mode
+ // before beginning if there is a timeout specified. If the timeout
+ // is 0 (wait as long as it takes) then don't worry about the blocking
+ // status; we'll block in SSL_connect if the socket is blocking, and
+ // block in ACE::select if not.
+ int reset_blocking_mode = 0;
+ if (timeout != 0)
+ {
+ reset_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 (reset_blocking_mode
+ && ACE::set_flags (handle,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ }
+
+ ACE_Time_Value t;
+ if (timeout != 0)
+ t = *timeout; // Need a non-const copy.
+
+ // Take into account the time between each select() call below.
+ ACE_Countdown_Time countdown ((timeout == 0 ? 0 : &t));
+
+ int status;
+ do
+ {
+ // These handle sets are used to set up for whatever SSL_connect
+ // says it wants next. They're reset on each pass around the loop.
+ ACE_Handle_Set rd_handle;
+ ACE_Handle_Set wr_handle;
+
+ status = ::SSL_connect (ssl);
+ switch (::SSL_get_error (ssl, status))
+ {
+ case SSL_ERROR_NONE:
+ // Start out with non-blocking disabled on the SSL stream.
+ new_stream.disable (ACE_NONBLOCK);
+ status = 0; // To tell caller about success
+ break; // Done
+
+ case SSL_ERROR_WANT_WRITE:
+ wr_handle.set_bit (handle);
+ status = 1; // Wait for more activity
+ break;
+
+ case SSL_ERROR_WANT_READ:
+ rd_handle.set_bit (handle);
+ status = 1; // Wait for more activity
+ break;
+
+ case SSL_ERROR_ZERO_RETURN:
+ // The peer has notified us that it is shutting down via
+ // the SSL "close_notify" message so we need to
+ // shutdown, too.
+ status = -1;
+ break;
+
+ case SSL_ERROR_SYSCALL:
+ // On some platforms (e.g. MS Windows) OpenSSL does not
+ // store the last error in errno so explicitly do so.
+ //
+ // Explicitly check for EWOULDBLOCK since it doesn't get
+ // converted to an SSL_ERROR_WANT_{READ,WRITE} on some
+ // platforms. If SSL_connect failed outright, though, don't
+ // bother checking more. This can happen if the socket gets
+ // closed during the handshake.
+ if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK &&
+ status == -1)
+ {
+ // Although the SSL_ERROR_WANT_READ/WRITE isn't getting
+ // set correctly, the read/write state should be valid.
+ // Use that to decide what to do.
+ status = 1; // Wait for more activity
+ if (SSL_want_write (ssl))
+ wr_handle.set_bit (handle);
+ else if (SSL_want_read (ssl))
+ rd_handle.set_bit (handle);
+ else
+ status = -1; // Doesn't want anything - bail out
+ }
+ else
+ status = -1;
+ break;
+
+ default:
+ ACE_SSL_Context::report_error ();
+ status = -1;
+ break;
+ }
+
+ if (status == 1)
+ {
+ // Must have at least one handle to wait for at this point.
+ ACE_ASSERT (rd_handle.num_set () == 1 || wr_handle.num_set () == 1);
+
+ // Block indefinitely if timeout pointer is zero.
+ status = ACE::select (int (handle) + 1,
+ &rd_handle,
+ &wr_handle,
+ 0,
+ (timeout == 0 ? 0 : &t));
+
+ (void) countdown.update ();
+
+ // 0 is timeout, so we're done.
+ // -1 is error, so we're done.
+ // Could be both handles set (same handle in both masks) so set to 1.
+ if (status >= 1)
+ status = 1;
+ else // Timeout or socket failure
+ status = -1;
+ }
+
+ } while (status == 1 && !SSL_is_init_finished (ssl));
+
+ if (reset_blocking_mode)
+ {
+ ACE_Errno_Guard eguard (errno);
+ ACE::clr_flags (handle, ACE_NONBLOCK);
+ }
+
+ return (status == -1 ? -1 : 0);
+
+}
+
+int
+ACE_SSL_SOCK_Connector::connect (ACE_SSL_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)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::connect");
+
+ // Take into account the time to complete the basic TCP handshake
+ // and the SSL handshake.
+ ACE_Time_Value time_copy;
+ ACE_Countdown_Time countdown (&time_copy);
+ if (timeout != 0)
+ {
+ time_copy += *timeout;
+ countdown.start ();
+ }
+
+ int result =
+ this->connector_.connect (new_stream.peer (),
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms);
+
+ int error = 0;
+ if (result == -1)
+ error = errno; // Save us some TSS accesses.
+
+ // Obtain the handle from the underlying SOCK_Stream and set it in
+ // the SSL_SOCK_Stream. Note that the case where a connection is in
+ // progress is also handled. In that case, the handle must also be
+ // set in the SSL_SOCK_Stream so that the correct handle is returned
+ // when performing non-blocking connect()s.
+ if (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && (result == 0
+ || (result == -1 && (error == EWOULDBLOCK
+ || error == EINPROGRESS))))
+ new_stream.set_handle (new_stream.peer ().get_handle ());
+
+ if (result == -1)
+ return result;
+
+ // If using a timeout, update the countdown timer to reflect the time
+ // spent on the connect itself, then pass the remaining time to
+ // ssl_connect to bound the time on the handshake.
+ if (timeout != 0)
+ {
+ countdown.update ();
+ timeout = &time_copy;
+ }
+
+ result = this->ssl_connect (new_stream, timeout);
+
+ if (result == -1)
+ new_stream.close ();
+
+ return result;
+}
+
+int
+ACE_SSL_SOCK_Connector::connect (ACE_SSL_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)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::connect");
+
+ // Take into account the time to complete the basic TCP handshake
+ // and the SSL handshake.
+ ACE_Time_Value time_copy;
+ ACE_Countdown_Time countdown (&time_copy);
+ if (timeout != 0)
+ {
+ time_copy += *timeout;
+ countdown.start ();
+ }
+
+ int result = this->connector_.connect (new_stream.peer (),
+ remote_sap,
+ qos_params,
+ timeout,
+ local_sap,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr,
+ perms);
+
+ int error = 0;
+ if (result == -1)
+ error = errno; // Save us some TSS accesses.
+
+ // Obtain the handle from the underlying SOCK_Stream and set it in
+ // the SSL_SOCK_Stream. Note that the case where a connection is in
+ // progress is also handled. In that case, the handle must also be
+ // set in the SSL_SOCK_Stream so that the correct handle is returned
+ // when performing non-blocking connect()s.
+ if (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && (result == 0
+ || (result == -1 && (error == EWOULDBLOCK
+ || error == EINPROGRESS))))
+ new_stream.set_handle (new_stream.peer ().get_handle ());
+
+ if (result == -1)
+ return result;
+
+ // If using a timeout, update the countdown timer to reflect the time
+ // spent on the connect itself, then pass the remaining time to
+ // ssl_connect to bound the time on the handshake.
+ if (timeout != 0)
+ {
+ countdown.update ();
+ timeout = &time_copy;
+ }
+
+ result = this->ssl_connect (new_stream, timeout);
+
+ if (result == -1)
+ new_stream.close ();
+
+ return result;
+}
+
+// Try to complete a non-blocking connection.
+
+int
+ACE_SSL_SOCK_Connector::complete (ACE_SSL_SOCK_Stream &new_stream,
+ ACE_Addr *remote_sap,
+ const ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::complete");
+
+ // Take into account the time to complete the basic TCP handshake
+ // and the SSL handshake.
+ ACE_Time_Value time_copy;
+ ACE_Countdown_Time countdown (&time_copy);
+ if (tv != 0)
+ {
+ time_copy += *tv;
+ countdown.start ();
+ }
+
+ // Only attempt to complete the TCP connection if it that hasn't
+ // already been done.
+ ACE_INET_Addr raddr;
+ if (new_stream.peer ().get_remote_addr (raddr) != 0
+ && this->connector_.complete (new_stream.peer (),
+ remote_sap,
+ tv) == -1)
+ return -1;
+
+ // The handle in the SSL_SOCK_Stream should have already been set in
+ // the connect() method.
+
+ // If using a timeout, update the countdown timer to reflect the time
+ // spent on the connect itself, then pass the remaining time to
+ // ssl_connect to bound the time on the handshake.
+ if (tv != 0)
+ {
+ countdown.update ();
+ tv = &time_copy;
+ }
+
+ if (this->ssl_connect (new_stream, tv) == -1)
+ {
+ new_stream.close ();
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector (
+ ACE_SSL_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)
+ : connector_ ()
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");
+ this->connect (new_stream,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector (
+ ACE_SSL_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)
+ : connector_ ()
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");
+
+ this->connect (new_stream,
+ remote_sap,
+ qos_params,
+ timeout,
+ local_sap,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr,
+ perms);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_SOCK_Connector.h b/ACE/ace/SSL/SSL_SOCK_Connector.h
new file mode 100644
index 00000000000..5419161cf4e
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Connector.h
@@ -0,0 +1,318 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_SOCK_Connector.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ * @author John Heitmann
+ * @author Chris Zimman
+ */
+//=============================================================================
+
+
+#ifndef ACE_SSL_SOCK_CONNECTOR_H
+#define ACE_SSL_SOCK_CONNECTOR_H
+
+#include /**/ "ace/pre.h"
+
+#include "SSL_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "SSL_SOCK_Stream.h"
+
+#include "ace/SOCK_Connector.h"
+#include "ace/OS_QoS.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SSL_SOCK_Connector
+ *
+ * @brief Defines a factory that creates new <ACE_SSL_SOCK_Stream>s
+ * actively.
+ *
+ * The ACE_SSL_SOCK_Connector doesn't have a socket of its own,
+ * i.e., it simply "borrows" the one from the ACE_SSL_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_SSL_SOCK_Connector from ACE_SSL_SOCK.
+ *
+ * Since SSL is record-oriented, some additional work is done after
+ * the plain socket is connected.
+ *
+ * @note The user must currently ensure that only one thread services
+ * a given SSL session at any given time since some underlying
+ * SSL implementations, such as OpenSSL, are not entirely
+ * thread-safe or reentrant.
+ */
+class ACE_SSL_Export ACE_SSL_SOCK_Connector
+{
+
+public:
+
+ /// Default constructor.
+ ACE_SSL_SOCK_Connector (void);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SSL_SOCK_Stream
+ * object if the connection succeeds. This method performs both the
+ * initial socket connect and the SSL handshake.
+ *
+ * @param new_stream The @c ACE_SSL_SOCK_Stream object that will be
+ * connected to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ ACE_SSL_SOCK_Connector (ACE_SSL_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);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SSL_SOCK_Stream
+ * object if the connection succeeds. This method performs both the
+ * initial socket connect and the SSL handshake.
+ *
+ * @param new_stream The @c ACE_SSL_SOCK_Stream object that will be
+ * connected to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param qos_params Contains QoS parameters that are passed to the
+ * IntServ (RSVP) and DiffServ protocols.
+ * @see ACE_QoS_Params.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ ACE_SSL_SOCK_Connector (ACE_SSL_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);
+
+ /// Default dtor.
+ ~ACE_SSL_SOCK_Connector (void);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SSL_SOCK_Stream
+ * object if the connection succeeds. This method performs both the
+ * initial socket connect and the SSL handshake.
+ *
+ * @param new_stream The @c ACE_SSL_SOCK_Stream object that will be
+ * connected to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ int connect (ACE_SSL_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);
+
+ /**
+ * Actively connect to a peer, producing a connected @c ACE_SSL_SOCK_Stream
+ * object if the connection succeeds. This method performs both the
+ * initial socket connect and the SSL handshake.
+ *
+ * @param new_stream The @c ACE_SSL_SOCK_Stream object that will be
+ * connected to the peer.
+ * @param remote_sap The address that we are trying to connect to.
+ * The protocol family of @c remote_sap is used for
+ * the connected socket. That is, if @c remote_sap
+ * contains an IPv6 address, a socket with family
+ * PF_INET6 will be used, else it will be PF_INET.
+ * @param qos_params Contains QoS parameters that are passed to the
+ * IntServ (RSVP) and DiffServ protocols.
+ * @see ACE_QoS_Params.
+ * @param timeout Pointer to an @c ACE_Time_Value object with amount
+ * of time to wait to connect. If the pointer is 0
+ * then the call blocks until the connection attempt
+ * is complete, whether it succeeds or fails. If
+ * *timeout == {0, 0} then the connection is done
+ * using nonblocking mode. In this case, if the
+ * connection can't be made immediately, this method
+ * returns -1 and errno == EWOULDBLOCK.
+ * If *timeout > {0, 0} then this is the maximum amount
+ * of time to wait before timing out; if the specified
+ * amount of time passes before the connection is made,
+ * this method returns -1 and 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.
+ * @param local_sap (optional) The local address to bind to. If it's
+ * the default value of @c ACE_Addr::sap_any then the
+ * OS will choose an unused port.
+ * @param reuse_addr (optional) If the value is 1, the local address
+ * (@c local_sap) is reused, even if it hasn't been
+ * cleaned up yet.
+ * @param flags Ignored.
+ * @param perms Ignored.
+ *
+ * @return Returns 0 if the connection succeeds. If it fails,
+ * -1 is returned and errno contains a specific error
+ * code.
+ */
+ int connect (ACE_SSL_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);
+
+ /**
+ * Try to complete a non-blocking connection.
+ * If connection completion is successful then <new_stream> contains
+ * the connected ACE_SSL_SOCK_Stream. If <remote_sap> is non-NULL
+ * then it will contain the address of the connected peer.
+ */
+ int complete (ACE_SSL_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_SSL_SOCK_Stream PEER_STREAM;
+ //@}
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ /// Complete non-blocking SSL active connection.
+ int ssl_connect (ACE_SSL_SOCK_Stream &new_stream,
+ const ACE_Time_Value *timeout);
+
+private:
+
+ /// The class that does all of the non-secure socket connection.
+ /// It is default contructed, and subsequently used by connect().
+ ACE_SOCK_Connector connector_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "SSL_SOCK_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_SOCK_CONNECTOR_H */
diff --git a/ACE/ace/SSL/SSL_SOCK_Connector.inl b/ACE/ace/SSL/SSL_SOCK_Connector.inl
new file mode 100644
index 00000000000..67b5ef01540
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Connector.inl
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector (void)
+ : connector_ ()
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");
+}
+
+ACE_INLINE int
+ACE_SSL_SOCK_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::reset_new_handle");
+ return this->connector_.reset_new_handle (handle);
+}
+
+ACE_INLINE void
+ACE_SSL_SOCK_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Connector::dump");
+ this->connector_.dump ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_SOCK_Stream.cpp b/ACE/ace/SSL/SSL_SOCK_Stream.cpp
new file mode 100644
index 00000000000..46130a79fc7
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Stream.cpp
@@ -0,0 +1,583 @@
+// $Id$
+
+#include "ace/Handle_Set.h"
+#include "ace/Log_Msg.h"
+#include "ace/Countdown_Time.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_Memory.h"
+
+#include <openssl/err.h>
+
+#include "SSL_SOCK_Stream.h"
+
+#if !defined (__ACE_INLINE__)
+#include "SSL_SOCK_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ACE_SSL,
+ SSL_SOCK_Stream,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Stream)
+
+ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream (ACE_SSL_Context *context)
+ : ssl_ (0),
+ stream_ ()
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream");
+
+ ACE_SSL_Context * ctx =
+ (context == 0 ? ACE_SSL_Context::instance () : context);
+
+ this->ssl_ = ::SSL_new (ctx->context ());
+
+ if (this->ssl_ == 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) ACE_SSL_SOCK_Stream "
+ "- cannot allocate new SSL structure %p\n",
+ ACE_TEXT ("")));
+ }
+}
+
+ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream");
+
+ ::SSL_free (this->ssl_);
+
+ // @@ Question: should we reference count the Context object or
+ // leave that to the application developer? We do not reference
+ // count reactors (for example) and following some simple rules
+ // seems to work fine!
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::sendv (const iovec iov[],
+ size_t n,
+ const ACE_Time_Value *max_wait_time) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv");
+
+ // There is subtle problem in this method that occurs when using
+ // non-blocking IO. The semantics of a non-blocking scatter write
+ // (sendv()) are not possible to retain with the emulation in this
+ // method.
+
+ ssize_t bytes_sent = 0;
+
+ ACE_Time_Value t;
+ ACE_Time_Value *timeout = const_cast<ACE_Time_Value *> (max_wait_time);
+
+ if (max_wait_time != 0)
+ {
+ // Make a copy since ACE_Countdown_Time modifies the
+ // ACE_Time_Value.
+ t = *max_wait_time;
+ timeout = &t;
+ }
+
+ // Take into account the time between each send.
+ ACE_Countdown_Time countdown (timeout);
+
+ for (size_t i = 0; i < n; ++i)
+ {
+ ssize_t const result = this->send (iov[i].iov_base,
+ iov[i].iov_len,
+ timeout);
+
+ if (result == -1)
+ {
+ // There is a subtle difference in behaviour depending on
+ // whether or not any data was sent. If no data was sent,
+ // then always return -1. Otherwise return bytes_sent.
+ // This gives the caller an opportunity to keep track of
+ if (bytes_sent > 0)
+ break;
+ else
+ return -1;
+ }
+ else
+ {
+ bytes_sent += result;
+
+ // Do not continue on to the next loop iteration if the
+ // amount of data sent was less than the amount data given.
+ // This avoids a subtle problem where "holes" in the data
+ // stream would occur if partial sends of a given buffer in
+ // the iovec array occured.
+ if (static_cast<size_t> (result) < static_cast<size_t> (iov[i].iov_len))
+ break;
+ }
+
+ (void) countdown.update ();
+ }
+
+ return bytes_sent;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::recvv (iovec *io_vec,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv");
+
+ // From 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;
+ }
+
+ int inlen;
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ FIONREAD,
+ &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 */
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::send (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
+
+ // If SSL has data in the buffer, i.e. SSL_pending() returns a
+ // non-zero value, then don't block on select().
+ if (timeout == 0 || ::SSL_pending (this->ssl_))
+ return this->send (buf, len, flags);
+
+ int val = 0;
+ if (ACE::enter_send_timedwait (this->get_handle (),
+ timeout,
+ val) == -1)
+ return -1;
+
+ ssize_t const bytes_transferred = this->send (buf, len, flags);
+
+ ACE::restore_non_blocking_mode (this->get_handle (), val);
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::recv (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
+
+ return this->recv_i (buf, n, flags, timeout);
+}
+
+
+ssize_t
+ACE_SSL_SOCK_Stream::send (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
+
+ size_t const total_tuples = n / 2;
+
+ va_list argp;
+ va_start (argp, n);
+
+ ssize_t bytes_sent = 0;
+
+ // NOTE: This method used to fill an IO vector (e.g. iovec) and then
+ // send it using a scatter write (sendv()). However, it is
+ // not possible to emulate a non-blocking scatter write over
+ // SSL. As such, there is no point in attempting to use
+ // scatter writes over SSL.
+ for (size_t i = 0; i < total_tuples; ++i)
+ {
+ ssize_t const data_len = va_arg (argp, ssize_t);
+ ssize_t const result = this->send (va_arg (argp, char *), data_len);
+
+ if (result == -1)
+ {
+ // There is a subtle difference in behaviour depending on
+ // whether or not any data was sent. If no data was sent,
+ // then always return -1. Otherwise return bytes_sent.
+ // This gives the caller an opportunity to keep track of
+ // which data was actually sent.
+ if (bytes_sent > 0)
+ break;
+ else
+ {
+ va_end (argp);
+ return -1;
+ }
+ }
+ else
+ {
+ bytes_sent += result;
+
+ // Do not continue on to the next loop iteration if the
+ // amount of data sent was less than the amount of data
+ // given. This avoids a subtle problem where "holes" in the
+ // data stream would occur if partial sends of a given
+ // buffer in the varargs occured.
+ if (result < data_len)
+ break;
+
+ }
+ }
+
+ va_end (argp);
+
+ return bytes_sent;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::recv (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
+
+ size_t const total_tuples = n / 2;
+
+ va_list argp;
+ va_start (argp, n);
+
+ ssize_t bytes_recv = 0;
+
+ for (size_t i = 0; i < total_tuples; ++i)
+ {
+ ssize_t const data_len = va_arg (argp, ssize_t);
+ ssize_t const result = this->recv (va_arg (argp, char *), data_len);
+
+ if (result == -1)
+ {
+ // There is a subtle difference in behaviour depending on
+ // whether or not any data was received. If no data was
+ // received, then always return -1. Otherwise return
+ // bytes_received. This gives the caller an opportunity to
+ // keep track of which data was actually received.
+ if (bytes_recv > 0)
+ break;
+ else
+ {
+ va_end (argp);
+ return -1;
+ }
+ }
+ else
+ {
+ bytes_recv += result;
+
+ // Do not continue on to the next loop iteration if the
+ // amount of data received was less than the amount of data
+ // desired. This avoids a subtle problem where "holes" in
+ // the data stream would occur if partial receives of a
+ // given buffer in the varargs occured.
+ if (result < data_len)
+ break;
+
+ }
+ }
+
+ va_end (argp);
+
+ return bytes_recv;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::send_n (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bt) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
+
+ // No support for send flags in SSL.
+ if (flags != 0)
+ ACE_NOTSUP_RETURN (-1);
+
+ /* This code mimics ACE::send_n */
+ // Total number of bytes written.
+ size_t temp = 0;
+ size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
+
+ // Actual number of bytes written in each <send> attempt
+ ssize_t n = 0;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ n = this->send ((const char*) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags,
+ timeout);
+
+ if (n < 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ // If blocked, try again.
+ n = 0;
+ continue;
+ }
+ else
+ return -1;
+ }
+ else if (n == 0)
+ break;
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::recv_n (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bt) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
+
+ if (flags != 0)
+ {
+ if ((flags | MSG_PEEK) != MSG_PEEK)
+ ACE_NOTSUP_RETURN (-1);
+ }
+
+ size_t temp = 0;
+ size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
+
+ ssize_t n = 0;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ n = this->recv ((char*) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags,
+ timeout);
+
+ if (n < 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ // If blocked, try again.
+ n = 0;
+ continue;
+ }
+ else
+ return -1;
+ }
+ else if (n == 0)
+ break;
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::recv_n (void *buf, int len, int flags) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
+
+ if (flags != 0)
+ {
+ if ((flags | MSG_PEEK) != MSG_PEEK)
+ ACE_NOTSUP_RETURN (-1);
+ }
+
+ ssize_t bytes_transferred = 0;
+ ssize_t n = 0;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < len;
+ bytes_transferred += n)
+ {
+ n = this->recv ((char*) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+
+ if (n < 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ // If blocked, try again.
+ n = 0;
+ continue;
+ }
+ else
+ return -1;
+ }
+ else if (n == 0)
+ break;
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::send_n (const void *buf, int len, int flags) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
+
+ // Send flags are unsupported in SSL
+ if (flags != 0)
+ ACE_NOTSUP_RETURN (-1);
+
+ /* The following code mimics <ACE::send_n> */
+ size_t bytes_transferred = 0;
+ ssize_t n = 0;
+
+ for (bytes_transferred = 0;
+ bytes_transferred < (size_t) len;
+ bytes_transferred += n)
+ {
+ n = this->send ((const char*) buf + bytes_transferred,
+ len - bytes_transferred,
+ flags);
+
+ if (n < 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ // If blocked, try again.
+ n = 0;
+ continue;
+ }
+ else
+ return -1;
+ }
+ else if (n == 0)
+ break;
+ }
+
+ return bytes_transferred;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::sendv_n (const iovec iov[], size_t iovcnt) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv_n");
+
+ ssize_t bytes_sent = 0;
+
+ for (size_t i = 0; i < iovcnt; ++i)
+ {
+ ssize_t result = this->send_n (iov[i].iov_base,
+ iov[i].iov_len);
+
+
+ if (result == -1)
+ {
+ // There is a subtle difference in behaviour depending on
+ // whether or not any data was sent. If no data was sent,
+ // then always return -1. Otherwise return bytes_sent.
+ // This gives the caller an opportunity to keep track of
+ // which data was actually sent.
+ if (bytes_sent > 0)
+ break;
+ else
+ return -1;
+ }
+ else
+ bytes_sent += result;
+ }
+
+ return bytes_sent;
+}
+
+ssize_t
+ACE_SSL_SOCK_Stream::recvv_n (iovec iov[], size_t iovcnt) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv_n");
+
+ ssize_t bytes_read = 0;
+
+ for (size_t i = 0; i < iovcnt; ++i)
+ {
+ ssize_t const result = this->recv_n (iov[i].iov_base,
+ iov[i].iov_len);
+
+ if (result == -1)
+ {
+ // There is a subtle difference in behaviour depending on
+ // whether or not any data was read. If no data was read,
+ // then always return -1. Otherwise return bytes_read.
+ // This gives the caller an opportunity to keep track of
+ // which data was actually read.
+ if (bytes_read > 0)
+ break;
+ else
+ return -1;
+ }
+ else
+ bytes_read += result;
+ }
+
+ return bytes_read;
+}
+
+int
+ACE_SSL_SOCK_Stream::get_remote_addr (ACE_Addr &addr) const
+{
+ // Some applications use get_remote_addr() as a way of determining
+ // whether or not a connection has been established. In SSL's case,
+ // the remote addr will be available once the TCP handshake has been
+ // complete. Despite that fact, the SSL connection may not have
+ // been completed. In such a case, a successful return from
+ // get_remote_addr() would be misleading.
+
+ if (SSL_is_init_finished (this->ssl_))
+ return this->ACE_SSL_SOCK::get_remote_addr (addr);
+
+ if (this->get_handle () == ACE_INVALID_HANDLE)
+ errno = EBADF;
+ else
+ errno = ENOTCONN;
+
+ return -1;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/SSL_SOCK_Stream.h b/ACE/ace/SSL/SSL_SOCK_Stream.h
new file mode 100644
index 00000000000..0690dce9839
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Stream.h
@@ -0,0 +1,321 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_SOCK_Stream.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ * @author John Heitmann
+ */
+//=============================================================================
+
+
+#ifndef ACE_SSL_SOCK_STREAM_H
+#define ACE_SSL_SOCK_STREAM_H
+
+#include /**/ "ace/pre.h"
+
+#include "SSL_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// This must be included before any <openssl> include on LynxOS
+#include "ace/os_include/os_stdio.h"
+
+#include <openssl/err.h>
+
+#include "SSL_SOCK.h"
+#include "SSL_Context.h"
+
+#include "ace/SOCK_Stream.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SSL_SOCK_Stream
+ *
+ * @brief Defines methods in the ACE_SSL_SOCK_Stream abstraction.
+ *
+ * This class encapsulates the methods and functionality necessary to
+ * send and receive data over TLS/SSL.
+ * @par
+ * Since SSL is record-oriented, some additional steps must be taken
+ * to make the ACE_SSL_SOCK_Stream interact properly with the
+ * Reactor (if one is used) when performing non-blocking IO. In
+ * particular, if ::SSL_pending (ssl), where "ssl" is a pointer to the
+ * SSL data structure returned from ACE_SSL_SOCK_Stream::ssl(),
+ * returns a non-zero value then the event handler that calls the IO
+ * methods in this class should return a value greater than zero to
+ * force the Reactor to invoke the event handler before polling for
+ * additional events (e.g. blocking on select()).
+ *
+ * @note The user must currently ensure that only one thread services
+ * a given SSL session at any given time since underlying SSL
+ * implementations, such as OpenSSL, are not entirely
+ * thread-safe or reentrant.
+ */
+class ACE_SSL_Export ACE_SSL_SOCK_Stream : public ACE_SSL_SOCK
+{
+public:
+
+ /// Constructor
+ /**
+ * @param context Pointer to @c ACE_SSL_Context instance containing
+ * the OpenSSL @c SSL data structure to be associated
+ * with this @c ACE_SSL_SOCK_Stream. The @c SSL data
+ * structure will be copied to make it at least
+ * logically independent of the supplied @a context.
+ */
+ ACE_SSL_SOCK_Stream (ACE_SSL_Context *context =
+ ACE_SSL_Context::instance ());
+
+ /// Destructor
+ ~ACE_SSL_SOCK_Stream (void);
+
+ /// Send an n byte buffer to the ssl socket using the semantics of
+ /// send(3n).
+ /**
+ * ACE_SSL supports no flags for sending at this time.
+ */
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags) const;
+
+ /// Recv an n byte buffer from the ssl socket using the semantics of
+ /// recv(3n).
+ /**
+ * ACE_SSL supports MSG_PEEK, but no other flags at this time.
+ */
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags) const;
+
+ /// Send an n byte buffer to the ssl socket using the semantics of
+ /// write(2).
+ ssize_t send (const void *buf,
+ size_t n) const;
+
+ /// Recv an n byte buffer from the ssl socket using the semantics of
+ /// read(2).
+ ssize_t recv (void *buf,
+ size_t n) const;
+
+ /// Send an iovec of size n to the ssl socket.
+ /**
+ * Note that it is not possible to perform a "scattered" write with
+ * the underlying OpenSSL implementation. As such, the expected
+ * semantics are not fully reproduced with this implementation.
+ */
+ ssize_t sendv (const 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;
+
+ /**
+ * Wait to timeout amount of time to send up to n bytes into buf
+ * (uses the send() call). If send() times out -1 is returned with
+ * errno == ETIME. If it succeeds the number of bytes sent is
+ * returned. No flags are supported.
+ */
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout) const;
+
+ /**
+ * Wait up to timeout amount of time to receive up to n bytes into
+ * buf (uses the recv() call). If recv() times out -1 is returned
+ * with errno == ETIME. If it succeeds the number of bytes received
+ * is returned. MSG_PEEK is the only supported flag.
+ */
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout) const;
+
+ /**
+ * Wait to to timeout amount of time to send up to n bytes into
+ * buf (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) const;
+
+ /**
+ * Wait up to timeout amount of time to receive up to n bytes
+ * into buf (uses the recv() call). If recv() times
+ * out a -1 is returned with @c 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) const;
+
+ /// Send n varargs messages to the connected ssl socket.
+ ssize_t send (size_t n,
+ ...) const;
+
+ /// Recv n varargs messages to the connected ssl socket.
+ ssize_t recv (size_t n,
+ ...) const;
+
+ /// Send n bytes, keep trying until n are sent.
+ ssize_t send_n (const void *buf, int n) const;
+
+ /// Recv n bytes, keep trying until n are received.
+ ssize_t recv_n (void *buf, int n) const;
+
+ /**
+ * @note In the following four methods, only MSG_PEEK is supported
+ * for recv_n(), and no flags are supported for send_n().
+ */
+ //@{
+ /// Send n bytes, keep trying until n are sent.
+ ssize_t send_n (const void *buf, int n, int flags) const;
+
+ /// Recv n bytes, keep trying until n are sent.
+ ssize_t recv_n (void *buf, int n, int flags) const;
+
+ /**
+ * Try to send exactly len bytes into buf (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,
+ size_t *bytes_transferred = 0) const;
+
+ /**
+ * Try to receive exactly len bytes into buf (uses the recv() 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,
+ size_t *bytes_transferred = 0) const;
+ //@}
+
+ /**
+ * Send an iovec of size n to the connected socket. 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;
+
+
+ /**
+ * Selectively close endpoints.
+ */
+ //@{
+ /// Close down the reader.
+ int close_reader (void);
+
+ /// Close down the writer.
+ int close_writer (void);
+ //@}
+
+ ///Close down the socket.
+ int close (void);
+
+ /// Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Overridden set_handle() method.
+ /**
+ * Only an ACE_SSL_SOCK_Acceptor or ACE_SSL_SOCK_Connector should
+ * access this method since some state in the underlying "ssl_" data
+ * structure is set during SSL connection establishment.
+ */
+ void set_handle (ACE_HANDLE fd);
+
+ /// Return a pointer to the underlying SSL structure.
+ SSL *ssl (void) const;
+
+ /**
+ * Return the address of the remotely connected peer (if there is
+ * one), in the referenced <ACE_Addr>. Returns 0 if successful, else
+ * -1.
+ *
+ * @note If the TCP connection has been completed but the SSL
+ * connection has not been completed yet, -1 will be
+ * returned.
+ */
+ int get_remote_addr (ACE_Addr &) const;
+
+ /// Return the underlying ACE_SOCK_Stream which ACE_SSL runs atop of.
+ ACE_SOCK_Stream & peer (void);
+
+protected:
+
+ /// Underlying send() helper method common to all public send()
+ /// methods.
+ ssize_t send_i (const void *buf,
+ size_t n,
+ int flags) const;
+
+ /// Underlying send() helper method common to all public send()
+ /// methods.
+ ssize_t recv_i (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout) const;
+
+private:
+
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_SSL_SOCK_Stream &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_SSL_SOCK_Stream (const ACE_SSL_SOCK_Stream &))
+
+protected:
+
+ /// The SSL session.
+ SSL *ssl_;
+
+ /// The stream which works under the ssl connection.
+ ACE_SOCK_Stream stream_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "SSL_SOCK_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_SOCK_STREAM_H */
diff --git a/ACE/ace/SSL/SSL_SOCK_Stream.inl b/ACE/ace/SSL/SSL_SOCK_Stream.inl
new file mode 100644
index 00000000000..f28b55997a5
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Stream.inl
@@ -0,0 +1,323 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void
+ACE_SSL_SOCK_Stream::set_handle (ACE_HANDLE fd)
+{
+ if (this->ssl_ == 0 || fd == ACE_INVALID_HANDLE)
+ {
+ this->ACE_SSL_SOCK::set_handle (ACE_INVALID_HANDLE);
+ return;
+ }
+ else
+ {
+ (void) ::SSL_set_fd (this->ssl_, (int) fd);
+ this->ACE_SSL_SOCK::set_handle (fd);
+ this->stream_.set_handle (fd);
+ }
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::send_i (const void *buf,
+ size_t n,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::send_i");
+
+ // NOTE: Caller must provide thread-synchronization.
+
+ // No send flags are supported in SSL.
+ if (flags != 0)
+ ACE_NOTSUP_RETURN (-1);
+
+ int const bytes_sent = ::SSL_write (this->ssl_,
+ static_cast<const char *> (buf),
+ n);
+
+ switch (::SSL_get_error (this->ssl_, bytes_sent))
+ {
+ case SSL_ERROR_NONE:
+ return bytes_sent;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ errno = EWOULDBLOCK;
+
+ return -1;
+
+ case SSL_ERROR_ZERO_RETURN:
+ // The peer has notified us that it is shutting down via the SSL
+ // "close_notify" message so we need to shutdown, too.
+ (void) ::SSL_shutdown (this->ssl_);
+
+ return bytes_sent;
+
+ case SSL_ERROR_SYSCALL:
+ if (bytes_sent == 0)
+ // An EOF occured but the SSL "close_notify" message was not
+ // sent. This is a protocol error, but we ignore it.
+ return 0;
+
+ // If not an EOF, then fall through to "default" case.
+
+ // On some platforms (e.g. MS Windows) OpenSSL does not store
+ // the last error in errno so explicitly do so.
+ ACE_OS::set_errno_to_last_error ();
+
+ break;
+
+ default:
+ // Reset errno to prevent previous values (e.g. EWOULDBLOCK)
+ // from being associated with fatal SSL errors.
+ errno = 0;
+
+ ACE_SSL_Context::report_error ();
+
+ break;
+ }
+
+ return -1;
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::send (const void *buf,
+ size_t n,
+ int flags) const
+{
+ return this->send_i (buf, n, flags);
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::recv_i (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_i");
+
+ // NOTE: Caller must provide thread-synchronization.
+
+ int bytes_read = 0;
+ ACE_HANDLE const handle = this->get_handle ();
+
+ // Value for current I/O mode (blocking/non-blocking)
+ int val = 0;
+
+ if (timeout != 0)
+ ACE::record_and_set_non_blocking_mode (handle,
+ val);
+
+ // Only block on select() with a timeout if no data in the
+ // internal OpenSSL buffer is pending read completion for
+ // the same reasons stated above, i.e. all data must be read
+ // before blocking on select().
+ if (timeout != 0
+ && !::SSL_pending (this->ssl_))
+ {
+ if (ACE::enter_recv_timedwait (handle,
+ timeout,
+ val) == -1)
+ return -1;
+ }
+
+ if (flags)
+ {
+ if (ACE_BIT_ENABLED (flags, MSG_PEEK))
+ bytes_read = ::SSL_peek (this->ssl_,
+ static_cast<char *> (buf),
+ n);
+ else
+ ACE_NOTSUP_RETURN (-1);
+ }
+ else
+ {
+ bytes_read = ::SSL_read (this->ssl_,
+ static_cast<char *> (buf),
+ n);
+ }
+
+ int const status = ::SSL_get_error (this->ssl_, bytes_read);
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ if (timeout != 0)
+ ACE::restore_non_blocking_mode (handle, val);
+
+ return bytes_read;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ errno = EWOULDBLOCK;
+
+ return -1;
+
+ case SSL_ERROR_ZERO_RETURN:
+ if (timeout != 0)
+ ACE::restore_non_blocking_mode (handle, val);
+
+ // The peer has notified us that it is shutting down via the SSL
+ // "close_notify" message so we need to shutdown, too.
+ (void) ::SSL_shutdown (this->ssl_);
+
+ return bytes_read;
+
+ case SSL_ERROR_SYSCALL:
+ if (bytes_read == 0)
+ // An EOF occured but the SSL "close_notify" message was not
+ // sent. This is a protocol error, but we ignore it.
+ return 0;
+
+ // If not an EOF, then fall through to "default" case.
+
+ // On some platforms (e.g. MS Windows) OpenSSL does not store
+ // the last error in errno so explicitly do so.
+ ACE_OS::set_errno_to_last_error ();
+
+ break;
+
+ default:
+ // Reset errno to prevent previous values (e.g. EWOULDBLOCK)
+ // from being associated with a fatal SSL error.
+ errno = 0;
+
+ ACE_SSL_Context::report_error ();
+
+ break;
+ }
+
+ return -1;
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::recv (void *buf,
+ size_t n,
+ int flags) const
+{
+ return this->recv_i (buf, n, flags, 0);
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::send (const void *buf,
+ size_t n) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
+
+ return this->send_i (buf, n, 0);
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::recv (void *buf,
+ size_t n) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
+
+ return this->recv_i (buf, n, 0, 0);
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::send (const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
+ return this->send (buf, len, 0, timeout);
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
+ return this->recv (buf, n, 0, timeout);
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::recv_n (void *buf, int buf_size) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
+ return this->recv_n (buf, buf_size, 0);
+}
+
+ACE_INLINE ssize_t
+ACE_SSL_SOCK_Stream::send_n (const void *buf, int len) const
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
+ return this->send_n (buf, len, 0);
+}
+
+ACE_INLINE int
+ACE_SSL_SOCK_Stream::close_reader (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::close_reader");
+ return this->stream_.close_reader ();
+}
+
+ACE_INLINE int
+ACE_SSL_SOCK_Stream::close_writer (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::close_writer");
+ return this->stream_.close_writer ();
+}
+
+ACE_INLINE int
+ACE_SSL_SOCK_Stream::close (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::close");
+
+ if (this->ssl_ == 0 || this->get_handle () == ACE_INVALID_HANDLE)
+ return 0; // SSL_SOCK_Stream was never opened.
+
+ // SSL_shutdown() returns 1 on successful shutdown of the SSL
+ // connection, not 0.
+ int const status = ::SSL_shutdown (this->ssl_);
+
+ switch (::SSL_get_error (this->ssl_, status))
+ {
+ case SSL_ERROR_NONE:
+ case SSL_ERROR_SYSCALL: // Ignore this error condition.
+
+ // Reset the SSL object to allow another connection to be made
+ // using this ACE_SSL_SOCK_Stream instance. This prevents the
+ // previous SSL session state from being associated with the new
+ // SSL session/connection.
+ (void) ::SSL_clear (this->ssl_);
+ this->set_handle (ACE_INVALID_HANDLE);
+ return this->stream_.close ();
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ errno = EWOULDBLOCK;
+ break;
+
+ default:
+ ACE_SSL_Context::report_error ();
+
+ ACE_Errno_Guard error (errno); // Save/restore errno
+ (void) this->stream_.close ();
+
+ return -1;
+ }
+
+ return -1;
+}
+
+ACE_INLINE ACE_SOCK_Stream &
+ACE_SSL_SOCK_Stream::peer (void)
+{
+ ACE_TRACE ("ACE_SSL_SOCK_Stream::peer");
+ return this->stream_;
+}
+
+ACE_INLINE SSL *
+ACE_SSL_SOCK_Stream::ssl (void) const
+{
+ return this->ssl_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SSL/ssl.mpc b/ACE/ace/SSL/ssl.mpc
new file mode 100644
index 00000000000..1b8b5ed7c24
--- /dev/null
+++ b/ACE/ace/SSL/ssl.mpc
@@ -0,0 +1,13 @@
+// -*- MPC -*-
+// $Id$
+
+project(SSL) : acelib, ace_output, install, ace_openssl {
+ avoids += ace_for_tao
+ requires += ssl
+ sharedname = ACE_SSL
+ dynamicflags = ACE_SSL_BUILD_DLL
+
+ pkgconfig_files {
+ ACE_SSL.pc.in
+ }
+}
diff --git a/ACE/ace/SSL/ssl_for_tao.mpc b/ACE/ace/SSL/ssl_for_tao.mpc
new file mode 100644
index 00000000000..54915488d7e
--- /dev/null
+++ b/ACE/ace/SSL/ssl_for_tao.mpc
@@ -0,0 +1,42 @@
+// -*- MPC -*-
+//
+// $Id$
+
+project(SSL_FOR_TAO) : acelib, ace_output, install, ace_openssl {
+ requires += ssl ace_for_tao
+ sharedname = ACE_SSL_FOR_TAO
+ dynamicflags = ACE_SSL_BUILD_DLL
+
+ Source_Files {
+ SSL_Context.cpp
+ SSL_SOCK.cpp
+ SSL_SOCK_Acceptor.cpp
+ SSL_SOCK_Connector.cpp
+ SSL_SOCK_Stream.cpp
+ }
+
+ Header_Files {
+ SSL_Context.h
+ SSL_Export.h
+ SSL_SOCK.h
+ SSL_SOCK_Acceptor.h
+ SSL_SOCK_Connector.h
+ SSL_SOCK_Stream.h
+ sslconf.h
+ }
+
+ Inline_Files {
+ SSL_SOCK.inl
+ SSL_SOCK_Acceptor.inl
+ SSL_SOCK_Connector.inl
+ SSL_Context.inl
+ SSL_SOCK_Stream.inl
+ }
+
+ Template_Files {
+ }
+
+ pkgconfig_files {
+ ACE_SSL.pc.in
+ }
+}
diff --git a/ACE/ace/SSL/sslconf.h b/ACE/ace/SSL/sslconf.h
new file mode 100644
index 00000000000..f456558fce9
--- /dev/null
+++ b/ACE/ace/SSL/sslconf.h
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file sslconf.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@ece.uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SSLCONF_H
+#define ACE_SSLCONF_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_DEFAULT_SSL_CERT_FILE)
+# ifdef WIN32
+# define ACE_DEFAULT_SSL_CERT_FILE "cert.pem"
+# else
+# define ACE_DEFAULT_SSL_CERT_FILE "/etc/ssl/cert.pem"
+# endif /* WIN32 */
+#endif /* ACE_DEFAULT_SSL_CERT_FILE */
+
+#if !defined (ACE_DEFAULT_SSL_CERT_DIR)
+# ifdef WIN32
+# define ACE_DEFAULT_SSL_CERT_DIR "certs"
+# else
+# define ACE_DEFAULT_SSL_CERT_DIR "/etc/ssl/certs"
+# endif /* WIN32 */
+#endif /* ACE_DEFAULT_SSL_CERT_DIR */
+
+#if !defined (ACE_SSL_CERT_FILE_ENV)
+#define ACE_SSL_CERT_FILE_ENV "SSL_CERT_FILE"
+#endif /* ACE_SSL_CERT_FILE_ENV */
+
+#if !defined (ACE_SSL_CERT_DIR_ENV)
+#define ACE_SSL_CERT_DIR_ENV "SSL_CERT_DIR"
+#endif /* ACE_SSL_CERT_DIR_ENV */
+
+#if !defined (ACE_SSL_EGD_FILE_ENV)
+#define ACE_SSL_EGD_FILE_ENV "SSL_EGD_FILE"
+#endif /* ACE_SSL_EGD_FILE_ENV */
+
+#if !defined (ACE_SSL_RAND_FILE_ENV)
+#define ACE_SSL_RAND_FILE_ENV "SSL_RAND_FILE"
+#endif /* ACE_SSL_RAND_FILE_ENV */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSLCONF_H */
diff --git a/ACE/ace/SString.cpp b/ACE/ace/SString.cpp
new file mode 100644
index 00000000000..6305bee14f8
--- /dev/null
+++ b/ACE/ace/SString.cpp
@@ -0,0 +1,550 @@
+// $Id$
+
+#include "ace/Malloc_T.h"
+#include "ace/OS_Memory.h"
+#if !defined (ACE_HAS_WINCE)
+//# include "ace/Service_Config.h"
+#endif /* !ACE_HAS_WINCE */
+#include "ace/SString.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Numeric_Limits.h"
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+// FUZZ: disable check_for_streams_include
+# include "ace/streams.h"
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SString.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ SString,
+ "SString.cpp,v 4.61 2001/03/04 00:55:30 brunsch Exp")
+
+
+// ************************************************************
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ACE_OSTREAM_TYPE &
+operator<< (ACE_OSTREAM_TYPE &os, const ACE_CString &cs)
+{
+ if (cs.fast_rep () != 0)
+ os << cs.fast_rep ();
+ return os;
+}
+
+ACE_OSTREAM_TYPE &
+operator<< (ACE_OSTREAM_TYPE &os, const ACE_WString &ws)
+{
+ // @@ Need to figure out how to print the "wide" string
+ // on platforms that don't support "wide" strings.
+#if defined (ACE_HAS_WCHAR)
+ os << ACE_Wide_To_Ascii (ws.fast_rep ()).char_rep ();
+#else
+ ACE_UNUSED_ARG (ws);
+ os << "(*non-printable string*)";
+#endif
+ return os;
+}
+
+ACE_OSTREAM_TYPE &
+operator<< (ACE_OSTREAM_TYPE &os, const ACE_SString &ss)
+{
+ if (ss.fast_rep () != 0)
+ os << ss.fast_rep ();
+ return os;
+}
+#endif /* !ACE_LACKS_IOSTREAM_TOTALLY */
+
+// *****************************************************************
+
+char *
+ACE_NS_WString::char_rep (void) const
+{
+ ACE_TRACE ("ACE_NS_WString::char_rep");
+ if (this->len_ == 0)
+ return 0;
+ else
+ {
+ char *t = 0;
+
+ ACE_NEW_RETURN (t,
+ char[this->len_ + 1],
+ 0);
+
+ for (size_type i = 0; i < this->len_; ++i)
+ // Note that this cast may lose data if wide chars are
+ // actually used!
+ t[i] = char (this->rep_[i]);
+
+ t[this->len_] = '\0';
+ return t;
+ }
+}
+
+ACE_USHORT16 *
+ACE_NS_WString::ushort_rep (void) const
+{
+ ACE_TRACE ("ACE_NS_WString::ushort_rep");
+ if (this->len_ <= 0)
+ return 0;
+ else
+ {
+ ACE_USHORT16 *t = 0;
+
+ ACE_NEW_RETURN (t,
+ ACE_USHORT16[this->len_ + 1],
+ 0);
+
+ for (size_type i = 0; i < this->len_; ++i)
+ // Note that this cast may lose data if wide chars are
+ // actually used!
+ t[i] = (ACE_USHORT16)this->rep_[i];
+
+ t[this->len_] = 0;
+ return t;
+ }
+}
+
+ACE_NS_WString::ACE_NS_WString (const char *s,
+ ACE_Allocator *alloc)
+ : ACE_WString (alloc)
+{
+ if (s == 0)
+ return;
+
+ this->len_ = this->buf_len_ = ACE_OS::strlen (s);
+
+ if (this->buf_len_ == 0)
+ return;
+
+ ACE_ALLOCATOR (this->rep_,
+ (ACE_WSTRING_TYPE *)
+ this->allocator_->malloc ((this->buf_len_ + 1) *
+ sizeof (ACE_WSTRING_TYPE)));
+ this->release_ = 1;
+ for (size_type i = 0; i <= this->buf_len_; ++i)
+ this->rep_[i] = s[i];
+}
+
+#if defined (ACE_WSTRING_HAS_USHORT_SUPPORT)
+ACE_NS_WString::ACE_NS_WString (const ACE_USHORT16 *s,
+ size_type len,
+ ACE_Allocator *alloc)
+ : ACE_WString (alloc)
+{
+ if (s == 0)
+ return;
+
+ this->buf_len_ = len;
+
+ if (this->buf_len_ == 0)
+ return;
+
+ ACE_ALLOCATOR (this->rep_,
+ (ACE_WSTRING_TYPE *)
+ this->allocator_->malloc ((this->buf_len_) *
+ sizeof (ACE_WSTRING_TYPE)));
+ this->release_ = 1;
+ for (size_type i = 0; i < this->buf_len_; ++i)
+ this->rep_[i] = s[i];
+}
+#endif /* ACE_WSTRING_HAS_USHORT_SUPPORT */
+
+// *****************************************************************
+
+ACE_SString::size_type const ACE_SString::npos =
+ ACE_Numeric_Limits<ACE_SString::size_type>::max ();
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SString)
+
+void
+ACE_SString::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SString::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+// Copy constructor.
+
+ACE_SString::ACE_SString (const ACE_SString &s)
+ : allocator_ (s.allocator_),
+ len_ (s.len_)
+{
+ ACE_TRACE ("ACE_SString::ACE_SString");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ this->rep_ = (char *) this->allocator_->malloc (s.len_ + 1);
+ ACE_OS::memcpy ((void *) this->rep_,
+ (const void *) s.rep_,
+ this->len_);
+ this->rep_[this->len_] = '\0';
+}
+
+// Default constructor.
+
+ACE_SString::ACE_SString (ACE_Allocator *alloc)
+ : allocator_ (alloc),
+ len_ (0),
+ rep_ (0)
+
+{
+ ACE_TRACE ("ACE_SString::ACE_SString");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ this->len_ = 0;
+ this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1);
+ this->rep_[this->len_] = '\0';
+}
+
+// Set the underlying pointer (does not copy memory).
+
+void
+ACE_SString::rep (char *s)
+{
+ ACE_TRACE ("ACE_SString::rep");
+
+ this->rep_ = s;
+
+ if (s == 0)
+ this->len_ = 0;
+ else
+ this->len_ = ACE_OS::strlen (s);
+}
+
+// Constructor that actually copies memory.
+
+ACE_SString::ACE_SString (const char *s,
+ ACE_Allocator *alloc)
+ : allocator_ (alloc)
+{
+ ACE_TRACE ("ACE_SString::ACE_SString");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ if (s == 0)
+ {
+ this->len_ = 0;
+ this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1);
+ this->rep_[this->len_] = '\0';
+ }
+ else
+ {
+ this->len_ = ACE_OS::strlen (s);
+ this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1);
+ ACE_OS::strcpy (this->rep_, s);
+ }
+}
+
+ACE_SString::ACE_SString (char c,
+ ACE_Allocator *alloc)
+ : allocator_ (alloc)
+{
+ ACE_TRACE ("ACE_SString::ACE_SString");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ this->len_ = 1;
+ this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1);
+ this->rep_[0] = c;
+ this->rep_[this->len_] = '\0';
+}
+
+// Constructor that actually copies memory.
+
+ACE_SString::ACE_SString (const char *s,
+ size_type len,
+ ACE_Allocator *alloc)
+ : allocator_ (alloc)
+{
+ ACE_TRACE ("ACE_SString::ACE_SString");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ if (s == 0)
+ {
+ this->len_ = 0;
+ this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1);
+ this->rep_[this->len_] = '\0';
+ }
+ else
+ {
+ this->len_ = len;
+ this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1);
+ ACE_OS::memcpy (this->rep_, s, len);
+ this->rep_[len] = '\0'; // Make sure to NUL terminate this!
+ }
+}
+
+// Assignment operator (does copy memory).
+
+ACE_SString &
+ACE_SString::operator= (const ACE_SString &s)
+{
+ ACE_TRACE ("ACE_SString::operator=");
+ // Check for identify.
+
+ if (this != &s)
+ {
+ // Only reallocate if we don't have enough space...
+ if (this->len_ < s.len_)
+ {
+ this->allocator_->free (this->rep_);
+ this->rep_ = (char *) this->allocator_->malloc (s.len_ + 1);
+ }
+ this->len_ = s.len_;
+ ACE_OS::strcpy (this->rep_, s.rep_);
+ }
+
+ return *this;
+}
+
+// Return substring.
+ACE_SString
+ACE_SString::substring (size_type offset,
+ size_type length) const
+{
+ size_t count = length;
+
+ // case 1. empty string
+ if (len_ == 0)
+ return ACE_SString ();
+
+ // case 2. start pos l
+ if (offset >= len_)
+ return ACE_SString ();
+
+ // get all remaining bytes
+ if (length == npos || count > (this->len_ - offset))
+ count = len_ - offset;
+
+ return ACE_SString (&rep_[offset], count, this->allocator_);
+}
+
+// ************************************************************
+
+ACE_Tokenizer::ACE_Tokenizer (ACE_TCHAR *buffer)
+ : buffer_ (buffer),
+ index_ (0),
+ preserves_index_ (0),
+ delimiter_index_ (0)
+{
+}
+
+int
+ACE_Tokenizer::delimiter (ACE_TCHAR d)
+{
+ if (delimiter_index_ == MAX_DELIMITERS)
+ return -1;
+
+ delimiters_[delimiter_index_].delimiter_ = d;
+ delimiters_[delimiter_index_].replace_ = 0;
+ delimiter_index_++;
+ return 0;
+}
+
+int
+ACE_Tokenizer::delimiter_replace (ACE_TCHAR d,
+ ACE_TCHAR replacement)
+{
+ // Make it possible to replace delimiters on-the-fly, e.g., parse
+ // string until certain token count and then copy rest of the
+ // original string.
+ for (int i = 0; i < delimiter_index_; i++)
+ if (delimiters_[i].delimiter_ == d)
+ {
+ delimiters_[i].replacement_ = replacement;
+ delimiters_[i].replace_ = 1;
+ return 0;
+ }
+
+ if (delimiter_index_ >= MAX_DELIMITERS)
+ return -1;
+
+ delimiters_[delimiter_index_].delimiter_ = d;
+ delimiters_[delimiter_index_].replacement_ = replacement;
+ delimiters_[delimiter_index_].replace_ = 1;
+ delimiter_index_++;
+ return 0;
+}
+
+int
+ACE_Tokenizer::preserve_designators (ACE_TCHAR start,
+ ACE_TCHAR stop,
+ int strip)
+{
+ if (preserves_index_ == MAX_PRESERVES)
+ return -1;
+
+ preserves_[preserves_index_].start_ = start;
+ preserves_[preserves_index_].stop_ = stop;
+ preserves_[preserves_index_].strip_ = strip;
+ preserves_index_++;
+ return 0;
+}
+
+int
+ACE_Tokenizer::is_delimiter (ACE_TCHAR d,
+ int &replace,
+ ACE_TCHAR &r)
+{
+ replace = 0;
+
+ for (int x = 0; x < delimiter_index_; x++)
+ if (delimiters_[x].delimiter_ == d)
+ {
+ if (delimiters_[x].replace_)
+ {
+ r = delimiters_[x].replacement_;
+ replace = 1;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Tokenizer::is_preserve_designator (ACE_TCHAR start,
+ ACE_TCHAR &stop,
+ int &strip)
+{
+ for (int x = 0; x < preserves_index_; x++)
+ if (preserves_[x].start_ == start)
+ {
+ stop = preserves_[x].stop_;
+ strip = preserves_[x].strip_;
+ return 1;
+ }
+
+ return 0;
+}
+
+ACE_TCHAR *
+ACE_Tokenizer::next (void)
+{
+ // Check if the previous pass was the last one in the buffer.
+ if (index_ == -1)
+ {
+ index_ = 0;
+ return 0;
+ }
+
+ ACE_TCHAR replacement = 0;
+ int replace;
+ ACE_TCHAR *next_token;
+
+ // Skip all leading delimiters.
+ for (;;)
+ {
+ // Check for end of string.
+ if (buffer_[index_] == '\0')
+ {
+ // If we hit EOS at the start, return 0.
+ index_ = 0;
+ return 0;
+ }
+
+ if (this->is_delimiter (buffer_[index_],
+ replace,
+ replacement))
+ index_++;
+ else
+ break;
+ }
+
+ // When we reach this point, buffer_[index_] is a non-delimiter and
+ // not EOS - the start of our next_token.
+ next_token = buffer_ + index_;
+
+ // A preserved region is it's own token.
+ ACE_TCHAR stop;
+ int strip;
+ if (this->is_preserve_designator (buffer_[index_],
+ stop,
+ strip))
+ {
+ while (++index_)
+ {
+ if (buffer_[index_] == '\0')
+ {
+ index_ = -1;
+ goto EXIT_LABEL;
+ }
+
+ if (buffer_[index_] == stop)
+ break;
+ }
+
+ if (strip)
+ {
+ // Skip start preserve designator.
+ next_token += 1;
+ // Zap the stop preserve designator.
+ buffer_[index_] = '\0';
+ // Increment to the next token.
+ index_++;
+ }
+
+ goto EXIT_LABEL;
+ }
+
+ // Step through finding the next delimiter or EOS.
+ for (;;)
+ {
+ // Advance pointer.
+ index_++;
+
+ // Check for delimiter.
+ if (this->is_delimiter (buffer_[index_],
+ replace,
+ replacement))
+ {
+ // Replace the delimiter.
+ if (replace != 0)
+ buffer_[index_] = replacement;
+
+ // Move the pointer up and return.
+ index_++;
+ goto EXIT_LABEL;
+ }
+
+ // A preserve designator signifies the end of this token.
+ if (this->is_preserve_designator (buffer_[index_],
+ stop,
+ strip))
+ goto EXIT_LABEL;
+
+ // Check for end of string.
+ if (buffer_[index_] == '\0')
+ {
+ index_ = -1;
+ goto EXIT_LABEL;
+ }
+ }
+
+EXIT_LABEL:
+ return next_token;
+}
+
+// *************************************************************
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template char ACE_String_Base<char>::NULL_String_;
+template ACE_WSTRING_TYPE ACE_String_Base<ACE_WSTRING_TYPE>::NULL_String_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SString.h b/ACE/ace/SString.h
new file mode 100644
index 00000000000..b52c732ef55
--- /dev/null
+++ b/ACE/ace/SString.h
@@ -0,0 +1,499 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SString.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt (schmidt@cs.wustl.edu)
+ */
+//=============================================================================
+
+#ifndef ACE_SSTRING_H
+#define ACE_SSTRING_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SStringfwd.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/String_Base.h"
+
+#if !defined (ACE_DEFAULT_GROWSIZE)
+#define ACE_DEFAULT_GROWSIZE 32
+#endif /* ACE_DEFAULT_GROWSIZE */
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+#include "ace/iosfwd.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+ACE_Export ACE_OSTREAM_TYPE &operator << (ACE_OSTREAM_TYPE &, const ACE_CString &);
+ACE_Export ACE_OSTREAM_TYPE &operator << (ACE_OSTREAM_TYPE &, const ACE_WString &);
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT
+template class ACE_Export ACE_String_Base<char>;
+template class ACE_Export ACE_String_Base<ACE_WSTRING_TYPE>;
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT */
+
+/**
+ * @class ACE_NS_WString
+ *
+ * @brief This class retain the backward compatibility for
+ * ACE_Naming_Context and related classes. The only addition to
+ * ACE_WString is a very naive "wchar" to "char" conversion
+ * function.
+ */
+class ACE_Export ACE_NS_WString : public ACE_WString
+{
+public:
+
+ using ACE_WString::size_type;
+
+ /// Default constructor.
+ ACE_NS_WString (ACE_Allocator *alloc = 0);
+
+ /// Constructor that copies @a s into dynamically allocated memory.
+ ACE_NS_WString (const char *s,
+ ACE_Allocator *alloc = 0);
+
+ /// Constructor that copies @a s into dynamically allocated memory.
+ ACE_NS_WString (const ACE_WSTRING_TYPE *s,
+ ACE_Allocator *alloc = 0);
+
+#if defined (ACE_WSTRING_HAS_USHORT_SUPPORT)
+ /// Constructor that takes in a ushort16 string (mainly used by the
+ /// ACE Name_Space classes)
+ ACE_NS_WString (const ACE_USHORT16 *s,
+ size_type len,
+ ACE_Allocator *alloc = 0);
+#endif /* ACE_WSTRING_HAS_USHORT_SUPPORT */
+
+ /// Constructor that copies @a len ACE_WSTRING_TYPE's of @a s into dynamically
+ /// allocated memory (will NUL terminate the result).
+ ACE_NS_WString (const ACE_WSTRING_TYPE *s,
+ size_type len,
+ ACE_Allocator *alloc = 0);
+
+ /// Constructor that dynamically allocates memory for @a len + 1
+ /// ACE_WSTRING_TYPE characters. The newly created memory is set memset to 0.
+ ACE_NS_WString (size_type len, ACE_Allocator *alloc = 0);
+
+ /// Copy constructor.
+ ACE_NS_WString (const ACE_NS_WString &s);
+
+ /// Constructor that copies @a c into dynamically allocated memory.
+ ACE_NS_WString (ACE_WSTRING_TYPE c, ACE_Allocator *alloc = 0);
+
+ /// Transform into a copy of the ASCII character representation.
+ /// (caller must delete)
+ char *char_rep (void) const;
+
+ /// Transform into a copy of a USHORT16 representation (caller must
+ /// delete). Note, behavior is undefined when sizeof (wchar_t) != 2.
+ ACE_USHORT16 *ushort_rep (void) const;
+};
+
+ACE_Export
+ACE_NS_WString operator + (const ACE_NS_WString &,
+ const ACE_NS_WString &);
+
+// -----------------------------------------------------------------
+
+/**
+ * @class ACE_SString
+ *
+ * @brief A very Simple String ACE_SString class. This is not a
+ * general-purpose string class, and you should probably consider
+ * using ACE_CString is you don't understand why this class
+ * exists...
+ *
+ * This class is optimized for efficiency, so it doesn't provide
+ * any internal locking.
+ * CAUTION: This class is only intended for use with applications
+ * that understand how it works. In particular, its destructor
+ * does not deallocate its memory when it is destroyed... We need
+ * this class since the ACE_Map_Manager requires an object that
+ * supports the operator == and operator !=. This class uses an
+ * ACE_Allocator to allocate memory. The user can make this a
+ * persistant class by providing an ACE_Allocator with a
+ * persistable memory pool.
+ */
+class ACE_Export ACE_SString
+{
+public:
+
+ typedef ACE_Allocator::size_type size_type;
+
+ /// No position constant
+ static const size_type npos;
+
+ /// Default constructor.
+ ACE_SString (ACE_Allocator *alloc = 0);
+
+ /// Constructor that copies @a s into dynamically allocated memory.
+ ACE_SString (const char *s, ACE_Allocator *alloc = 0);
+
+ /// Constructor that copies @a len chars of @s into dynamically
+ /// allocated memory (will NUL terminate the result).
+ ACE_SString (const char *s, size_type len, ACE_Allocator *alloc = 0);
+
+ /// Copy constructor.
+ ACE_SString (const ACE_SString &);
+
+ /// Constructor that copies @a c into dynamically allocated memory.
+ ACE_SString (char c, ACE_Allocator *alloc = 0);
+
+ /// Default destructor.
+ ~ACE_SString (void);
+
+ /// Return the <slot'th> character in the string (doesn't perform
+ /// bounds checking).
+ char operator [] (size_type slot) const;
+
+ /// Return the <slot'th> character by reference in the string
+ /// (doesn't perform bounds checking).
+ char &operator [] (size_type slot);
+
+ /// Assignment operator (does copy memory).
+ ACE_SString &operator = (const ACE_SString &);
+
+ /**
+ * Return a substring given an offset and length, if length == npos
+ * use rest of str return empty substring if offset or offset/length
+ * are invalid
+ */
+ ACE_SString substring (size_type offset, size_type length = npos) const;
+
+ /// Same as substring
+ ACE_SString substr (size_type offset, size_type length = npos) const;
+
+ /// Returns a hash value for this string.
+ u_long hash (void) const;
+
+ /// Return the length of the string.
+ size_type length (void) const;
+
+ /// Set the underlying pointer. Since this does not copy memory or
+ /// delete existing memory use with extreme caution!!!
+ void rep (char *s);
+
+ /// Get the underlying pointer.
+ const char *rep (void) const;
+
+ /// Get the underlying pointer.
+ const char *fast_rep (void) const;
+
+ /// Same as STL String's <c_str> and <fast_rep>.
+ const char *c_str (void) const;
+
+ /// Comparison operator that will match substrings. Returns the
+ /// slot of the first location that matches, else @c npos.
+ size_type strstr (const ACE_SString &s) const;
+
+ /// Find <str> starting at pos. Returns the slot of the first
+ /// location that matches (will be >= pos), else npos.
+ size_type find (const ACE_SString &str, size_type pos = 0) const;
+
+ /// Find <s> starting at pos. Returns the slot of the first
+ /// location that matches (will be >= pos), else npos.
+ size_type find (const char *s, size_type pos = 0) const;
+
+ /// Find <c> starting at pos. Returns the slot of the first
+ /// location that matches (will be >= pos), else npos.
+ size_type find (char c, size_type pos = 0) const;
+
+ /// Find <c> starting at pos (counting from the end). Returns the
+ /// slot of the first location that matches, else npos.
+ size_type rfind (char c, size_type pos = npos) const;
+
+ /// Equality comparison operator (must match entire string).
+ bool operator == (const ACE_SString &s) const;
+
+ /// Less than comparison operator.
+ bool operator < (const ACE_SString &s) const;
+
+ /// Greater than comparison operator.
+ bool operator > (const ACE_SString &s) const;
+
+ /// Inequality comparison operator.
+ bool operator != (const ACE_SString &s) const;
+
+ /// Performs a <strcmp>-style comparison.
+ int compare (const ACE_SString &s) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to a memory allocator.
+ ACE_Allocator *allocator_;
+
+ /// Length of the ACE_SString (not counting the trailing '\0').
+ size_type len_;
+
+ /// Pointer to data.
+ char *rep_;
+};
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ACE_Export ACE_OSTREAM_TYPE &operator << (ACE_OSTREAM_TYPE &, const ACE_SString &);
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+// This allows one to use W or C String based on the Unicode
+// setting
+#if defined (ACE_USES_WCHAR)
+typedef ACE_WString ACE_TString;
+#else /* ACE_USES_WCHAR */
+typedef ACE_CString ACE_TString;
+#endif /* ACE_USES_WCHAR */
+
+
+// ************************************************************
+
+/**
+ * @class ACE_Tokenizer
+ *
+ * @brief Tokenizer
+ *
+ * Tokenizes a buffer. Allows application to set delimiters and
+ * preserve designators. Does not allow special characters, yet
+ * (e.g., printf ("\"like a quoted string\"")).
+ */
+class ACE_Export ACE_Tokenizer
+{
+public:
+ /**
+ * \a buffer will be parsed. Notice that ACE_Tokenizer will modify
+ * \a buffer if you use <code> delimiter_replace </code> or <code>
+ * preserve_designators </code> to do character substitution.
+ * @note You should NOT pass a constant string or string literal
+ * to this constructor, since ACE_Tokenizer will try to modify
+ * the string.
+ * \sa preserve_designators
+ * \sa preserve_designators
+ */
+ ACE_Tokenizer (ACE_TCHAR *buffer);
+
+ /**
+ * \a d is a delimiter.
+ * \return Returns 0 on success, -1 if there is no memory left.
+ *
+ * <B>Example:</B>
+ * \verbatim
+ char buf[30];
+ ACE_OS::strcpy(buf, "William/Joseph/Hagins");
+
+ ACE_Tokenizer tok (buf);
+ tok.delimiter ('/');
+ for (char *p = tok.next (); p; p = tok.next ())
+ cout << p << endl;
+ \endverbatim
+ *
+ * This will print out:
+ * \verbatim
+ William/Joseph/Hagins
+ Joseph/Hagins
+ Hagins \endverbatim
+ */
+ int delimiter (ACE_TCHAR d);
+
+ /**
+ * \a d is a delimiter and, when found, will be replaced by
+ * \a replacement.
+ * \return 0 on success, -1 if there is no memory left.
+ *
+ * <B>Example:</B>
+ * \verbatim
+ char buf[30];
+ ACE_OS::strcpy(buf, "William/Joseph/Hagins");
+
+ ACE_Tokenizer tok (buf);
+ tok.delimiter_replace ('/', 0);
+ for (char *p = tok.next (); p; p = tok.next ())
+ cout << p << endl;
+ \endverbatim
+ *
+ * This will print out:
+ * \verbatim
+ William
+ Joseph
+ Hagins \endverbatim
+ */
+ int delimiter_replace (ACE_TCHAR d, ACE_TCHAR replacement);
+
+ /**
+ * Extract string between a pair of designator characters.
+ * For instance, quotes, or '(' and ')'.
+ * \a start specifies the begin designator.
+ * \a stop specifies the end designator.
+ * \a strip If \a strip == 1, then the preserve
+ * designators will be stripped from the tokens returned by next.
+ * \return 0 on success, -1 if there is no memory left.
+ *
+ * <B>Example with strip = 0:</B>
+ * \verbatim
+ char buf[30];
+ ACE_OS::strcpy(buf, "William(Joseph)Hagins");
+
+ ACE_Tokenizer tok (buf);
+ tok.preserve_designators ('(', ')', 0);
+ for (char *p = tok.next (); p; p = tok.next ())
+ cout << p << endl;
+ \endverbatim
+ *
+ * This will print out:
+ * \verbatim
+ William(Joseph)Hagins
+ (Joseph)Hagins
+ )Hagins \endverbatim
+ *
+ * <B>Example with strip = 1:</B>
+ * \verbatim
+ char buf[30];
+ ACE_OS::strcpy(buf, "William(Joseph)Hagins");
+
+ ACE_Tokenizer tok (buf);
+ tok.preserve_designators ('(', ')', 1);
+ for (char *p = tok.next (); p; p = tok.next ())
+ cout << p << endl;
+ \endverbatim
+ *
+ * This will print out:
+ * \verbatim
+ William
+ Joseph
+ Hagins \endverbatim
+ */
+ int preserve_designators (ACE_TCHAR start, ACE_TCHAR stop, int strip=1);
+
+ /// Returns the next token.
+ ACE_TCHAR *next (void);
+
+ enum {
+ MAX_DELIMITERS=16,
+ MAX_PRESERVES=16
+ };
+
+protected:
+ /// Returns 1 if <d> is a delimiter, 0 otherwise. If <d> should be
+ /// replaced with @a r, <replace> is set to 1, otherwise 0.
+ int is_delimiter (ACE_TCHAR d, int &replace, ACE_TCHAR &r);
+
+ /**
+ * If <start> is a start preserve designator, returns 1 and sets
+ * <stop> to the stop designator. Returns 0 if <start> is not a
+ * preserve designator.
+ */
+ int is_preserve_designator (ACE_TCHAR start, ACE_TCHAR &stop, int &strip);
+
+ ACE_TCHAR *buffer_;
+ int index_;
+
+ /**
+ * @class Preserve_Entry
+ *
+ * @brief Preserve Entry
+ *
+ * Defines a set of characters that designate an area that
+ * should not be parsed, but should be treated as a complete
+ * token. For instance, in: (this is a preserve region), start
+ * would be a left paren -(- and stop would be a right paren
+ * -)-. The strip determines whether the designators should be
+ * removed from the token.
+ */
+ class Preserve_Entry
+ {
+ public:
+ /**
+ * E.g., "(".
+ * E.g., ")".
+ * Whether the designators should be removed from the token.
+ */
+ ACE_TCHAR start_;
+ ACE_TCHAR stop_;
+ int strip_;
+ };
+
+ /// The application can specify MAX_PRESERVES preserve designators.
+ Preserve_Entry preserves_[MAX_PRESERVES];
+
+ /// Pointer to the next free spot in preserves_.
+ int preserves_index_;
+
+ /**
+ * @class Delimiter_Entry
+ *
+ * @brief Delimiter Entry
+ *
+ * Describes a delimiter for the tokenizer.
+ */
+ class Delimiter_Entry
+ {
+ public:
+ /**
+ * Most commonly a space ' '.
+ * What occurrences of delimiter_ should be replaced with.
+ * Whether replacement_ should be used. This should be replaced
+ * with a technique that sets replacement_ = delimiter by
+ * default. I'll do that next iteration.
+ */
+ ACE_TCHAR delimiter_;
+ ACE_TCHAR replacement_;
+ int replace_;
+ };
+
+ /// The tokenizer allows MAX_DELIMITERS number of delimiters.
+ Delimiter_Entry delimiters_[MAX_DELIMITERS];
+
+ /// Pointer to the next free space in delimiters_.
+ int delimiter_index_;
+};
+
+// ****************************************************************
+
+/**
+ * @class ACE_Auto_String_Free
+ *
+ * @brief Simple class to automatically de-allocate strings
+ *
+ * Keeps a pointer to a string and deallocates it (using
+ * <ACE_OS::free>) on its destructor.
+ * If you need to delete using "delete[]" the
+ * ACE_Auto_Array_Ptr<char> is your choice.
+ * The class plays the same role as auto_ptr<>
+ */
+class ACE_Export ACE_Auto_String_Free
+{
+public:
+ explicit ACE_Auto_String_Free (char* p = 0);
+ ACE_Auto_String_Free (ACE_Auto_String_Free &rhs);
+ ACE_Auto_String_Free& operator= (ACE_Auto_String_Free &rhs);
+ ~ACE_Auto_String_Free (void);
+
+ char* operator* () const;
+ char operator[] (size_t i) const;
+ char* get (void) const;
+ char* release (void);
+ void reset (char* p = 0);
+
+private:
+ char* p_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SString.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SSTRING_H */
diff --git a/ACE/ace/SString.inl b/ACE/ace/SString.inl
new file mode 100644
index 00000000000..8aae9df08a8
--- /dev/null
+++ b/ACE/ace/SString.inl
@@ -0,0 +1,299 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// Include ACE.h only if it hasn't already been included, e.g., if
+// ACE_TEMPLATES_REQUIRE_SOURCE, ACE.h won't have been pulled in by
+// String_Base.cpp.
+#ifndef ACE_ACE_H
+# include "ace/ACE.h"
+#endif /* !ACE_ACE_H */
+
+#include "ace/OS_NS_stdlib.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_NS_WString::ACE_NS_WString (ACE_Allocator *alloc)
+ : ACE_WString (alloc)
+{
+}
+
+ACE_INLINE
+ACE_NS_WString::ACE_NS_WString (const ACE_WSTRING_TYPE *s,
+ size_type len,
+ ACE_Allocator *alloc)
+ : ACE_WString (s, len, alloc)
+{
+}
+
+ACE_INLINE
+ACE_NS_WString::ACE_NS_WString (const ACE_WSTRING_TYPE *s,
+ ACE_Allocator *alloc)
+ : ACE_WString (s, alloc)
+{
+}
+
+ACE_INLINE
+ACE_NS_WString::ACE_NS_WString (size_type len, ACE_Allocator *alloc)
+ : ACE_WString (len, 0, alloc)
+{
+}
+
+ACE_INLINE
+ACE_NS_WString::ACE_NS_WString (const ACE_NS_WString &s)
+ : ACE_WString (s)
+{
+}
+
+ACE_INLINE
+ACE_NS_WString::ACE_NS_WString (ACE_WSTRING_TYPE c, ACE_Allocator *alloc)
+ : ACE_WString (c, alloc)
+{
+}
+
+ACE_INLINE ACE_NS_WString
+operator+ (const ACE_NS_WString &s, const ACE_NS_WString &t)
+{
+ ACE_NS_WString temp (s);
+ temp += t;
+ return temp;
+}
+
+// -------------------------------------------------------
+
+ACE_INLINE
+ACE_SString::~ACE_SString (void)
+{
+}
+
+ACE_INLINE ACE_SString
+ACE_SString::substr (size_type offset,
+ size_type length) const
+{
+ return this->substring (offset, length);
+}
+
+// Return the <slot'th> character in the string.
+
+ACE_INLINE char
+ACE_SString::operator[] (size_type slot) const
+{
+ ACE_TRACE ("ACE_SString::operator[]");
+ return this->rep_[slot];
+}
+
+// Return the <slot'th> character in the string by reference.
+
+ACE_INLINE char &
+ACE_SString::operator[] (size_type slot)
+{
+ ACE_TRACE ("ACE_SString::operator[]");
+ return this->rep_[slot];
+}
+
+// Get the underlying pointer (does not make a copy, so beware!).
+
+ACE_INLINE const char *
+ACE_SString::rep (void) const
+{
+ ACE_TRACE ("ACE_SString::rep");
+ return this->rep_;
+}
+
+// Get the underlying pointer (does not make a copy, so beware!).
+
+ACE_INLINE const char *
+ACE_SString::fast_rep (void) const
+{
+ ACE_TRACE ("ACE_SString::fast_rep");
+ return this->rep_;
+}
+
+// Get the underlying pointer (does not make a copy, so beware!).
+
+ACE_INLINE const char *
+ACE_SString::c_str (void) const
+{
+ ACE_TRACE ("ACE_SString::c_str");
+ return this->rep_;
+}
+
+// Comparison operator.
+
+ACE_INLINE bool
+ACE_SString::operator== (const ACE_SString &s) const
+{
+ ACE_TRACE ("ACE_SString::operator==");
+ return this->len_ == s.len_
+ && ACE_OS::strcmp (this->rep_, s.rep_) == 0;
+}
+
+// Less than comparison operator.
+
+ACE_INLINE bool
+ACE_SString::operator < (const ACE_SString &s) const
+{
+ ACE_TRACE ("ACE_SString::operator <");
+
+ return (this->rep_ && s.rep_)
+ ? ACE_OS::strcmp (this->rep_, s.rep_) < 0
+ : ((s.rep_) ? true : false);
+}
+
+// Greater than comparison operator.
+
+ACE_INLINE bool
+ACE_SString::operator > (const ACE_SString &s) const
+{
+ ACE_TRACE ("ACE_SString::operator >");
+
+ return (this->rep_ && s.rep_)
+ ? ACE_OS::strcmp (this->rep_, s.rep_) > 0
+ : ((this->rep_) ? true : false );
+}
+
+// Comparison operator.
+
+ACE_INLINE bool
+ACE_SString::operator!= (const ACE_SString &s) const
+{
+ ACE_TRACE ("ACE_SString::operator!=");
+ return !(*this == s);
+}
+
+ACE_INLINE int
+ACE_SString::compare (const ACE_SString &s) const
+{
+ ACE_TRACE ("ACE_SString::compare");
+ return ACE_OS::strcmp (this->rep_, s.rep_);
+}
+
+ACE_INLINE ACE_SString::size_type
+ACE_SString::find (const char *s, size_type pos) const
+{
+ char *substr = this->rep_ + pos;
+ char *pointer = ACE_OS::strstr (substr, s);
+ if (pointer == 0)
+ return ACE_SString::npos;
+ else
+ return pointer - this->rep_;
+}
+
+ACE_INLINE ACE_SString::size_type
+ACE_SString::find (char c, size_type pos) const
+{
+ char *substr = this->rep_ + pos;
+ char *pointer = ACE_OS::strchr (substr, c);
+ if (pointer == 0)
+ return ACE_SString::npos;
+ else
+ return pointer - this->rep_;
+}
+
+ACE_INLINE ACE_SString::size_type
+ACE_SString::strstr (const ACE_SString &s) const
+{
+ ACE_TRACE ("ACE_SString::strstr");
+
+ return this->find (s.rep_);
+}
+
+ACE_INLINE ACE_SString::size_type
+ACE_SString::find (const ACE_SString &str, size_type pos) const
+{
+ return this->find (str.rep_, pos);
+}
+
+ACE_INLINE ACE_SString::size_type
+ACE_SString::rfind (char c, size_type pos) const
+{
+ if (pos == ACE_SString::npos)
+ pos = this->len_;
+
+ // Do not change to prefix operator! Proper operation of this loop
+ // depends on postfix decrement behavior.
+ for (size_type i = pos; i-- != 0; )
+ if (this->rep_[i] == c)
+ return i;
+
+ return ACE_SString::npos;
+}
+
+ACE_INLINE u_long
+ACE_SString::hash (void) const
+{
+ return ACE::hash_pjw (this->rep_);
+}
+
+ACE_INLINE ACE_SString::size_type
+ACE_SString::length (void) const
+{
+ ACE_TRACE ("ACE_SString::length");
+ return this->len_;
+}
+
+ACE_INLINE
+ACE_Auto_String_Free::ACE_Auto_String_Free (char* p)
+ : p_ (p)
+{
+}
+
+ACE_INLINE
+ACE_Auto_String_Free::ACE_Auto_String_Free (ACE_Auto_String_Free& rhs)
+ : p_ (rhs.p_)
+{
+ rhs.p_ = 0;
+}
+
+ACE_INLINE void
+ACE_Auto_String_Free::reset (char* p)
+{
+ ACE_OS::free (this->p_);
+ this->p_ = p;
+}
+
+ACE_INLINE ACE_Auto_String_Free&
+ACE_Auto_String_Free::operator= (ACE_Auto_String_Free& rhs)
+{
+ if (this != &rhs)
+ {
+ this->reset (rhs.p_);
+ rhs.p_ = 0;
+ }
+ return *this;
+}
+
+ACE_INLINE
+ACE_Auto_String_Free::~ACE_Auto_String_Free (void)
+{
+ this->reset (0);
+}
+
+ACE_INLINE char*
+ACE_Auto_String_Free::operator* (void) const
+{
+ return this->p_;
+}
+
+ACE_INLINE char
+ACE_Auto_String_Free::operator[] (size_t i) const
+{
+ return this->p_[i];
+}
+
+ACE_INLINE char*
+ACE_Auto_String_Free::get (void) const
+{
+ return this->p_;
+}
+
+ACE_INLINE char*
+ACE_Auto_String_Free::release (void)
+{
+ char* p = this->p_;
+ this->p_ = 0;
+ return p;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SStringfwd.h b/ACE/ace/SStringfwd.h
new file mode 100644
index 00000000000..fb28ee8a469
--- /dev/null
+++ b/ACE/ace/SStringfwd.h
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SStringfwd.h
+ *
+ * $Id$
+ *
+ * Forward declarations and typedefs of ACE string types.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SSTRINGFWD_H
+#define ACE_SSTRINGFWD_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Basic_Types.h" /* ACE_WCHAR_T definition */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (defined (__HP_aCC) && (36300 <= __HP_aCC) && (__HP_aCC <= 37300))
+// Due to a bug in the aCC 3.xx compiler need to define the ACE_String_Base
+// template before we can typedef ACE_CString
+# include "ace/String_Base.h"
+#endif /* __HP_aCC */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class CHAR> class ACE_String_Base; // Forward declaration.
+
+typedef ACE_WCHAR_T ACE_WSTRING_TYPE;
+
+typedef ACE_String_Base<char> ACE_CString;
+typedef ACE_String_Base<ACE_WSTRING_TYPE> ACE_WString;
+
+// This allows one to use W or C String based on the Unicode
+// setting
+#if defined (ACE_USES_WCHAR)
+typedef ACE_WString ACE_TString;
+#else /* ACE_USES_WCHAR */
+typedef ACE_CString ACE_TString;
+#endif /* ACE_USES_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSTRINGFWD_H */
diff --git a/ACE/ace/SUN_Proactor.cpp b/ACE/ace/SUN_Proactor.cpp
new file mode 100644
index 00000000000..8b280045b97
--- /dev/null
+++ b/ACE/ace/SUN_Proactor.cpp
@@ -0,0 +1,324 @@
+// $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"
+
+
+ACE_RCSID (ace,
+ POSIX_CB_Proactor,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 ();
+
+ // we should start pseudo-asynchronous accept task
+ // one per all future acceptors
+
+ this->get_asynch_pseudo_task ().start ();
+}
+
+// Destructor.
+ACE_SUN_Proactor::~ACE_SUN_Proactor (void)
+{
+ this->close ();
+}
+
+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_i (&wait_time);
+}
+
+int
+ACE_SUN_Proactor::handle_events (void)
+{
+ return this->handle_events_i (0);
+}
+
+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 (this->num_started_aio_ != 0) // double check
+ return 0;
+
+ return this->condition_.wait (abstime);
+
+#else
+
+ return 0; // or -1 ???
+
+#endif /* ACE_MT_SAFE */
+}
+
+int
+ACE_SUN_Proactor::handle_events_i (ACE_Time_Value *delta)
+{
+ int retval = 0;
+ aio_result_t *result = 0;
+
+ if (0 == delta)
+ {
+ if (this->num_started_aio_ == 0)
+ this->wait_for_start (0);
+
+ result = aiowait (0);
+ }
+ else
+ {
+ if (this->num_started_aio_ == 0)
+ {
+ // Decrement delta with the amount of time spent waiting
+ ACE_Countdown_Time countdown (delta);
+ ACE_Time_Value tv (*delta);
+ tv += ACE_OS::gettimeofday ();
+ if (this->wait_for_start (&tv) == -1)
+ return -1;
+ }
+ struct timeval delta_tv = *delta;
+ result = aiowait (&delta_tv);
+ }
+
+ if (result == 0)
+ {
+ // timeout, do nothing,
+ // we should process "post_completed" queue
+ }
+ else if (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;
+ size_t transfer_count = 0;
+
+ ACE_POSIX_Asynch_Result *asynch_result =
+ find_completed_aio (result,
+ error_status,
+ transfer_count);
+
+ if (asynch_result != 0)
+ {
+ // Call the application code.
+ this->application_specific_code (asynch_result,
+ transfer_count,
+ 0, // No completion key.
+ error_status); // Error
+ retval++;
+ }
+ }
+
+ // process post_completed results
+ retval += this->process_result_queue ();
+
+ return retval > 0 ? 1 : 0 ;
+
+}
+
+int
+ACE_SUN_Proactor::get_result_status (ACE_POSIX_Asynch_Result* asynch_result,
+ int &error_status,
+ size_t &transfer_count)
+{
+
+ // Get the error status of the aio_ operation.
+ error_status = asynch_result->aio_resultp.aio_errno;
+ ssize_t op_return = asynch_result->aio_resultp.aio_return;
+
+ // ****** from Sun man pages *********************
+ // Upon completion of the operation both aio_return and aio_errno
+ // are set to reflect the result of the operation.
+ // AIO_INPROGRESS is not a value used by the system
+ // so the client may detect a change in state
+ // by initializing aio_return to this value.
+
+ if (error_status == EINPROGRESS || op_return == AIO_INPROGRESS)
+ return 0; // not completed
+
+ if (op_return < 0)
+ transfer_count = 0; // zero bytes transferred
+ else
+ transfer_count = static_cast<size_t> (op_return);
+
+ return 1; // completed
+}
+
+ACE_POSIX_Asynch_Result *
+ACE_SUN_Proactor::find_completed_aio (aio_result_t *result,
+ int &error_status,
+ size_t &transfer_count)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, 0));
+
+ size_t ai;
+ error_status = -1;
+ transfer_count = 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; // means somebody else uses aio directly!!!
+
+ ACE_POSIX_Asynch_Result *asynch_result = result_list_[ai];
+
+ if (this->get_result_status (asynch_result,
+ error_status,
+ transfer_count) == 0)
+ { // should never be
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_SUN_Proactor::find_completed_aio:"
+ "should never be !!!\n"));
+ return 0;
+ }
+
+ 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_i 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_i (ACE_POSIX_Asynch_Result *result)
+{
+ ACE_TRACE ("ACE_SUN_Proactor::start_aio_i");
+
+ int ret_val;
+ const ACE_TCHAR *ptype;
+
+ // ****** from Sun man pages *********************
+ // Upon completion of the operation both aio_return and aio_errno
+ // are set to reflect the result of the operation.
+ // AIO_INPROGRESS is not a value used by the system
+ // so the client may detect a change in state
+ // by initializing aio_return to this value.
+ result->aio_resultp.aio_return = AIO_INPROGRESS;
+ result->aio_resultp.aio_errno = EINPROGRESS;
+
+ // Start IO
+ switch (result->aio_lio_opcode)
+ {
+ case LIO_READ :
+ ptype = ACE_TEXT ("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 = ACE_TEXT ("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 = ACE_TEXT ("?????");
+ ret_val = -1;
+ break;
+ }
+
+ if (ret_val == 0)
+ {
+ this->num_started_aio_++;
+ if (this->num_started_aio_ == 1) // wake up condition
+ this->condition_.broadcast ();
+ }
+ else // if (ret_val == -1)
+ {
+ if (errno == EAGAIN || errno == ENOMEM) // Defer - retry this later.
+ ret_val = 1;
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%N:%l:(%P | %t)::start_aio: aio%s %p\n"),
+ ptype,
+ ACE_TEXT ("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
+ {
+ // 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
+
+ result->set_error (ECANCELED);
+ result->set_bytes_transferred (0);
+ this->putq_result (result);
+ return 0;
+ }
+
+ return 2;
+}
+
+ACE_POSIX_Proactor::Proactor_Type
+ACE_SUN_Proactor::get_impl_type (void)
+{
+ return PROACTOR_SUN;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_AIO_CALLS && sun */
diff --git a/ACE/ace/SUN_Proactor.h b/ACE/ace/SUN_Proactor.h
new file mode 100644
index 00000000000..d81a1407d5a
--- /dev/null
+++ b/ACE/ace/SUN_Proactor.h
@@ -0,0 +1,126 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SUN_Proactor.h
+ *
+ * $Id$
+ *
+ * @author Alexander Libman <alibman@baltimore.com>
+ */
+//=============================================================================
+
+#ifndef ACE_SUN_PROACTOR_H
+#define ACE_SUN_PROACTOR_H
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_AIO_CALLS) && defined (sun)
+
+#include "ace/POSIX_Proactor.h"
+#include /**/ <sys/asynch.h> // Sun native aio calls
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a 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. 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);
+
+ /// Internal completion detection and dispatching.
+ int handle_events_i (ACE_Time_Value *delta);
+
+ /// Initiate an aio operation.
+ virtual int start_aio_i (ACE_POSIX_Asynch_Result *result);
+
+ /// Check AIO for completion, error and result status
+ /// Return: 1 - AIO completed , 0 - not completed yet
+ virtual int get_result_status (ACE_POSIX_Asynch_Result* asynch_result,
+ int &error_status,
+ size_t &transfer_count);
+
+ /// Extract the results of aio.
+ ACE_POSIX_Asynch_Result *find_completed_aio (aio_result_t *result,
+ int &error_status,
+ size_t &transfer_count);
+
+ /// From ACE_POSIX_AIOCB_Proactor.
+ /// Attempt to cancel running request
+ virtual int cancel_aiocb (ACE_POSIX_Asynch_Result *result);
+
+ /// Specific Sun aiowait
+ int wait_for_start (ACE_Time_Value * abstime);
+
+ /// Condition variable .
+ /// used to wait the first AIO start
+ ACE_SYNCH_CONDITION condition_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_AIO_CALLS && sun */
+#endif /* ACE_SUN_PROACTOR_H*/
diff --git a/ACE/ace/SV_Message.cpp b/ACE/ace/SV_Message.cpp
new file mode 100644
index 00000000000..15368235910
--- /dev/null
+++ b/ACE/ace/SV_Message.cpp
@@ -0,0 +1,24 @@
+// SV_Message.cpp
+// $Id$
+
+#include "ace/SV_Message.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SV_Message.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SV_Message, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Message)
+
+void
+ACE_SV_Message::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SV_Message::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Message.h b/ACE/ace/SV_Message.h
new file mode 100644
index 00000000000..38d64d58b56
--- /dev/null
+++ b/ACE/ace/SV_Message.h
@@ -0,0 +1,67 @@
+// -*- 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_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_SV_Message
+ *
+ * @brief Defines the header file for the C++ wrapper for message queues.
+ */
+class ACE_Export ACE_SV_Message
+{
+public:
+ /// Constructor
+ ACE_SV_Message (long type = 0);
+
+ /// Destructor
+ ~ACE_SV_Message (void);
+
+ /// Get the message type.
+ long type (void) const;
+
+ /// Set the message type.
+ 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#if defined (__ACE_INLINE__)
+#include "ace/SV_Message.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SV_MESSAGE_H */
diff --git a/ACE/ace/SV_Message.inl b/ACE/ace/SV_Message.inl
new file mode 100644
index 00000000000..3f698bd5071
--- /dev/null
+++ b/ACE/ace/SV_Message.inl
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+#include "ace/config-all.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Message_Queue.cpp b/ACE/ace/SV_Message_Queue.cpp
new file mode 100644
index 00000000000..7f4c76b9b7a
--- /dev/null
+++ b/ACE/ace/SV_Message_Queue.cpp
@@ -0,0 +1,44 @@
+// $Id$
+
+#include "ace/SV_Message_Queue.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SV_Message_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SV_Message_Queue, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Message_Queue)
+
+void
+ACE_SV_Message_Queue::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SV_Message_Queue::dump");
+#endif /* ACE_HAS_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SV_Message_Queue::ACE_SV_Message_Queue")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Message_Queue.h b/ACE/ace/SV_Message_Queue.h
new file mode 100644
index 00000000000..8acd9f1e2aa
--- /dev/null
+++ b/ACE/ace/SV_Message_Queue.h
@@ -0,0 +1,105 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file SV_Message_Queue.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@uci.edu>
+ */
+//===========================================================================
+
+#ifndef ACE_SV_MESSAGE_QUEUE_H
+#define ACE_SV_MESSAGE_QUEUE_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/SV_Message.h"
+#include "ace/os_include/sys/os_stat.h"
+#include "ace/os_include/sys/os_ipc.h"
+#include "ace/Default_Constants.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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.
+ ssize_t 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 the underly internal id.
+ int get_id (void) const;
+
+ /// Set the underly internal id.
+ 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SV_Message_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SV_MESSAGE_QUEUE_H */
diff --git a/ACE/ace/SV_Message_Queue.inl b/ACE/ace/SV_Message_Queue.inl
new file mode 100644
index 00000000000..b84f6379901
--- /dev/null
+++ b/ACE/ace/SV_Message_Queue.inl
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+#include "ace/OS_NS_sys_msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Open a message queue using the <external_id>.
+
+ACE_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?!
+
+ACE_INLINE int
+ACE_SV_Message_Queue::close (void)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::close");
+ this->internal_id_ = -1;
+ return 1;
+}
+
+ACE_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,
+ (struct msqid_ds *) arg);
+}
+
+ACE_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;
+}
+
+ACE_INLINE int
+ACE_SV_Message_Queue::get_id (void) const
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::get_id");
+ return this->internal_id_;
+}
+
+ACE_INLINE void
+ACE_SV_Message_Queue::set_id (int id)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::set_id");
+ this->internal_id_ = id;
+}
+
+ACE_INLINE ssize_t
+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);
+}
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Semaphore_Complex.cpp b/ACE/ace/SV_Semaphore_Complex.cpp
new file mode 100644
index 00000000000..73d0ccdc01b
--- /dev/null
+++ b/ACE/ace/SV_Semaphore_Complex.cpp
@@ -0,0 +1,259 @@
+// SV_Semaphore_Complex.cpp
+// $Id$
+
+#include "ace/SV_Semaphore_Complex.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_Thread.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SV_Semaphore_Complex.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SV_Semaphore_Complex, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Semaphore_Complex)
+
+void
+ACE_SV_Semaphore_Complex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::dump");
+#endif /* ACE_HAS_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,
+ short create,
+ int initial_value,
+ u_short nsems,
+ mode_t 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 (u_short 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,
+ short flags,
+ int initial_value,
+ u_short nsems,
+ mode_t 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,
+ short flags,
+ int initial_value,
+ u_short nsems,
+ mode_t 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_TEXT ("%p\n"), ACE_TEXT ("ACE_SV_Semaphore_Complex")));
+}
+
+ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (const char *name,
+ short flags,
+ int initial_value,
+ u_short nsems,
+ mode_t 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_TEXT ("%p\n"), ACE_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 ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Semaphore_Complex.h b/ACE/ace/SV_Semaphore_Complex.h
new file mode 100644
index 00000000000..de48fc09359
--- /dev/null
+++ b/ACE/ace/SV_Semaphore_Complex.h
@@ -0,0 +1,159 @@
+// -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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,
+ short create = ACE_SV_Semaphore_Complex::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS);
+ ACE_SV_Semaphore_Complex (const char *name,
+ short create = ACE_SV_Semaphore_Complex::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t 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,
+ short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t 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,
+ short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t 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, short flags = 0) const;
+
+ /// Acquire a semaphore for reading.
+ int acquire_read (u_short n = 0, short flags = 0) const;
+
+ /// Acquire a semaphore for writing
+ int acquire_write (u_short n = 0, short flags = 0) const;
+
+ /// Try to acquire the semaphore.
+ int tryacquire (u_short n = 0, short flags = 0) const;
+
+ /// Try to acquire the semaphore for reading.
+ int tryacquire_read (u_short n = 0, short flags = 0) const;
+
+ /// Try to acquire the semaphore for writing.
+ int tryacquire_write (u_short n = 0, short flags = 0) const;
+
+ /// Release the semaphore.
+ int release (u_short n = 0, short flags = 0) const;
+
+ // = Semaphore operation methods.
+ int op (short val, u_short n = 0, short 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...
+ using ACE_SV_Semaphore_Simple::get_id;
+ 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];
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SV_Semaphore_Complex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SV_SEMAPHORE_COMPLEX_H */
diff --git a/ACE/ace/SV_Semaphore_Complex.inl b/ACE/ace/SV_Semaphore_Complex.inl
new file mode 100644
index 00000000000..8b80748ebf5
--- /dev/null
+++ b/ACE/ace/SV_Semaphore_Complex.inl
@@ -0,0 +1,84 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_SV_Semaphore_Complex::acquire (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire");
+ return ACE_SV_Semaphore_Simple::acquire ((u_short) n + 2, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Complex::acquire_read (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_read");
+ return this->acquire (n, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Complex::acquire_write (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_write");
+ return this->acquire (n, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Complex::tryacquire (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire");
+ return ACE_SV_Semaphore_Simple::tryacquire ((u_short) n + 2, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Complex::tryacquire_read (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read");
+ return this->tryacquire (n, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Complex::tryacquire_write (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_write");
+ return this->tryacquire (n, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Complex::release (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::release");
+ return ACE_SV_Semaphore_Simple::release ((u_short) n + 2, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Complex::op (short val, u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
+ return ACE_SV_Semaphore_Simple::op (val, (u_short) n + 2, flags);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Semaphore_Simple.cpp b/ACE/ace/SV_Semaphore_Simple.cpp
new file mode 100644
index 00000000000..6a6949e6f7f
--- /dev/null
+++ b/ACE/ace/SV_Semaphore_Simple.cpp
@@ -0,0 +1,237 @@
+#include "ace/SV_Semaphore_Simple.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/os_include/sys/os_sem.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SV_Semaphore_Simple.inl"
+#endif /* !__ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ SV_Semaphore_Simple,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_SV_Semaphore_Simple)
+
+void
+ACE_SV_Semaphore_Simple::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::dump");
+#endif /* ACE_HAS_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 (short val, u_short n, short 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,
+ short flags,
+ int initial_value,
+ u_short n,
+ mode_t perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::open");
+ union semun ivalue;
+
+ if (k == IPC_PRIVATE || k == 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,
+ short flags,
+ int initial_value,
+ u_short n,
+ mode_t 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_TEXT ("%p\n"), ACE_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 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)
+#if defined (ACE_WIN64)
+ // The cast below is legit...
+# pragma warning(push)
+# pragma warning(disable : 4312)
+#endif /* ACE_WIN64 */
+ return (key_t) ACE::crc32 (name);
+#if defined (ACE_WIN64)
+# pragma warning(pop)
+#endif /* ACE_WIN64 */
+}
+
+// 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,
+ short flags,
+ int initial_value,
+ u_short n,
+ mode_t 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,
+ short flags,
+ int initial_value,
+ u_short n,
+ mode_t 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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple")));
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple (const wchar_t *name,
+ short flags,
+ int initial_value,
+ u_short nsems,
+ mode_t perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple(wchar_t)");
+ if (this->open (ACE_Wide_To_Ascii (name).char_rep (),
+ flags,
+ initial_value,
+ nsems,
+ perms) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple")));
+}
+#endif /* ACE_HAS_WCHAR */
+
+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 const result = this->control (IPC_RMID);
+ ((ACE_SV_Semaphore_Simple *) this)->init ();
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Semaphore_Simple.h b/ACE/ace/SV_Semaphore_Simple.h
new file mode 100644
index 00000000000..8950369225e
--- /dev/null
+++ b/ACE/ace/SV_Semaphore_Simple.h
@@ -0,0 +1,197 @@
+// -*- 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_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_stat.h"
+#include "ace/os_include/sys/os_ipc.h"
+#include "ace/os_include/sys/os_sem.h"
+#include "ace/Default_Constants.h"
+
+#if defined (ACE_WIN32)
+ // Default semaphore key and mutex name
+# if !defined (ACE_DEFAULT_SEM_KEY)
+# define ACE_DEFAULT_SEM_KEY "ACE_SEM_KEY"
+# endif /* ACE_DEFAULT_SEM_KEY */
+#else /* !defined (ACE_WIN32) */
+ // Default semaphore key
+# if !defined (ACE_DEFAULT_SEM_KEY)
+# define ACE_DEFAULT_SEM_KEY 1234
+# endif /* ACE_DEFAULT_SEM_KEY */
+#endif /* ACE_WIN32 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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,
+ short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS);
+ ACE_SV_Semaphore_Simple (const char *name,
+ short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS);
+#if defined (ACE_HAS_WCHAR)
+ ACE_SV_Semaphore_Simple (const wchar_t *name,
+ short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS);
+#endif /* ACE_HAS_WCHAR */
+
+ ~ACE_SV_Semaphore_Simple (void);
+
+ int open (const char *name,
+ short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS);
+
+#if defined (ACE_HAS_WCHAR)
+ int open (const wchar_t *name,
+ short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t perms = ACE_DEFAULT_FILE_PERMS);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Open or create one or more SV_Semaphores. We return 0 if all is
+ /// OK, else -1.
+ int open (key_t key,
+ short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ mode_t 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, short flags = 0) const;
+
+ /// Acquire a semaphore for reading.
+ int acquire_read (u_short n = 0, short flags = 0) const;
+
+ /// Acquire a semaphore for writing
+ int acquire_write (u_short n = 0, short flags = 0) const;
+
+ /// Non-blocking version of <acquire>.
+ int tryacquire (u_short n = 0, short flags = 0) const;
+
+ /// Try to acquire the semaphore for reading.
+ int tryacquire_read (u_short n = 0, short flags = 0) const;
+
+ /// Try to acquire the semaphore for writing.
+ int tryacquire_write (u_short n = 0, short flags = 0) const;
+
+ /// Increment ACE_SV_Semaphore by one. Dijkstra's V operation,
+ /// Tannenbaums UP operation.
+ int release (u_short n = 0, short 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 (short val, u_short semnum = 0, short 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 = static_cast<key_t> (ACE_INVALID_SEM_KEY),
+ int i = -1);
+ key_t name_2_key (const char *name);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SV_Semaphore_Simple.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* _SV_SEMAPHORE_SIMPLE_H */
diff --git a/ACE/ace/SV_Semaphore_Simple.inl b/ACE/ace/SV_Semaphore_Simple.inl
new file mode 100644
index 00000000000..5dde75ffff6
--- /dev/null
+++ b/ACE/ace/SV_Semaphore_Simple.inl
@@ -0,0 +1,128 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WCHAR)
+// Semaphores don't offer wide-char names, so convert the name and forward
+// to the narrow-char open().
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::open (const wchar_t *name,
+ short flags,
+ int initial_value,
+ u_short nsems,
+ mode_t perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::open (wchar_t)");
+ return this->open (ACE_Wide_To_Ascii (name).char_rep (),
+ flags,
+ initial_value,
+ nsems,
+ perms);
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_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...
+
+ACE_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.
+
+ACE_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.
+
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::acquire (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire");
+ return this->op (-1, n, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::acquire_read (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire_read");
+ return this->acquire (n, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::acquire_write (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire_write");
+ return this->acquire (n, flags);
+}
+
+// Non-blocking version of acquire().
+
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::tryacquire (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::tryacquire");
+ return this->op (-1, n, flags | IPC_NOWAIT);
+}
+
+// Non-blocking version of acquire().
+
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::tryacquire_read (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::tryacquire_read");
+ return this->tryacquire (n, flags);
+}
+
+// Non-blocking version of acquire().
+
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::tryacquire_write (u_short n, short 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.
+
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::release (u_short n, short flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::release");
+ return this->op (1, n, flags);
+}
+
+ACE_INLINE int
+ACE_SV_Semaphore_Simple::get_id (void) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::get_id");
+ return this->internal_id_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Shared_Memory.cpp b/ACE/ace/SV_Shared_Memory.cpp
new file mode 100644
index 00000000000..a2966307af0
--- /dev/null
+++ b/ACE/ace/SV_Shared_Memory.cpp
@@ -0,0 +1,88 @@
+// $Id$
+
+#include "ace/SV_Shared_Memory.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SV_Shared_Memory.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SV_Shared_Memory, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Shared_Memory)
+
+void
+ACE_SV_Shared_Memory::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_SV_Shared_Memory::dump");
+#endif /* ACE_HAS_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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/SV_Shared_Memory.h b/ACE/ace/SV_Shared_Memory.h
new file mode 100644
index 00000000000..2b0c7dcb254
--- /dev/null
+++ b/ACE/ace/SV_Shared_Memory.h
@@ -0,0 +1,121 @@
+// -*- 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_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_stat.h"
+#include "ace/os_include/sys/os_ipc.h"
+#include "ace/Default_Constants.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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;
+ size_t 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.
+ size_t size_;
+
+ /// Pointer to the beginning of the segment.
+ void *segment_ptr_;
+
+ /// Round up to an appropriate page size.
+ size_t round_up (size_t len);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/SV_Shared_Memory.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SV_SHARED_MEMORY_H */
diff --git a/ACE/ace/SV_Shared_Memory.inl b/ACE/ace/SV_Shared_Memory.inl
new file mode 100644
index 00000000000..8ca16d52e47
--- /dev/null
+++ b/ACE/ace/SV_Shared_Memory.inl
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_sys_shm.h"
+#include "ace/Global_Macros.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE size_t
+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 size_t
+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_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Sample_History.cpp b/ACE/ace/Sample_History.cpp
new file mode 100644
index 00000000000..9bd2ca47852
--- /dev/null
+++ b/ACE/ace/Sample_History.cpp
@@ -0,0 +1,73 @@
+// $Id$
+
+#include "ace/Sample_History.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Sample_History.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Basic_Stats.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_Memory.h"
+
+ACE_RCSID(ace, Sample_History, "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Sample_History::ACE_Sample_History (size_t max_samples)
+ : max_samples_ (max_samples)
+ , sample_count_ (0)
+{
+ ACE_NEW(this->samples_, ACE_UINT64[this->max_samples_]);
+}
+
+ACE_Sample_History::~ACE_Sample_History (void)
+{
+ delete[] this->samples_;
+}
+
+size_t
+ACE_Sample_History::max_samples (void) const
+{
+ return this->max_samples_;
+}
+
+size_t
+ACE_Sample_History::sample_count (void) const
+{
+ return this->sample_count_;
+}
+
+void
+ACE_Sample_History::dump_samples (const ACE_TCHAR *msg,
+ ACE_UINT32 scale_factor) const
+{
+#ifndef ACE_NLOGGING
+ for (size_t i = 0; i != this->sample_count_; ++i)
+ {
+ const ACE_UINT64 val = this->samples_[i] / scale_factor;
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%s: ")
+ ACE_SIZE_T_FORMAT_SPECIFIER
+ ACE_TEXT ("\t%Q\n"),
+ msg,
+ i,
+ val));
+ }
+#else
+ ACE_UNUSED_ARG (msg);
+ ACE_UNUSED_ARG (scale_factor);
+#endif /* ACE_NLOGGING */
+}
+
+void
+ACE_Sample_History::collect_basic_stats (ACE_Basic_Stats &stats) const
+{
+ for (size_t i = 0; i != this->sample_count_; ++i)
+ {
+ stats.sample (this->samples_[i]);
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Sample_History.h b/ACE/ace/Sample_History.h
new file mode 100644
index 00000000000..2c060737cfb
--- /dev/null
+++ b/ACE/ace/Sample_History.h
@@ -0,0 +1,91 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Sample_History.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SAMPLE_HISTORY_H
+#define ACE_SAMPLE_HISTORY_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include "ace/Basic_Types.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Basic_Stats;
+
+/// Save multiple samples in an array
+/**
+ * Save multiple samples (usually latency numbers), into an array, and
+ * later print them in several formats.
+ */
+class ACE_Export ACE_Sample_History
+{
+public:
+ /// Constructor
+ /**
+ * The number of samples is pre-allocated, and cannot changes once
+ * the class is initialized.
+ */
+ ACE_Sample_History (size_t max_samples);
+
+ /// Destructor
+ ~ACE_Sample_History (void);
+
+ /// Record one sample.
+ /**
+ * Return 0 on success, -1 if the sample could not be stored
+ */
+ int sample (ACE_UINT64 value);
+
+ /// Returns the maximum number of samples
+ size_t max_samples (void) const;
+
+ /// Returns the current number of samples
+ size_t sample_count (void) const;
+
+ /// Dump all the samples
+ /**
+ * Prints out all the samples, using @a msg as a prefix for each
+ * message.
+ */
+ void dump_samples (const ACE_TCHAR *msg,
+ ACE_UINT32 scale_factor) const;
+
+ /// Collect the summary for all the samples
+ void collect_basic_stats (ACE_Basic_Stats &) const;
+
+ /// Get a sample
+ ACE_UINT64 get_sample (size_t i) const;
+
+private:
+ /// The maximum number of samples
+ size_t max_samples_;
+
+ /// The current number of samples
+ size_t sample_count_;
+
+ /// The samples
+ ACE_UINT64 *samples_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Sample_History.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SAMPLE_HISTORY_H */
diff --git a/ACE/ace/Sample_History.inl b/ACE/ace/Sample_History.inl
new file mode 100644
index 00000000000..42eca62e69b
--- /dev/null
+++ b/ACE/ace/Sample_History.inl
@@ -0,0 +1,26 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Sample_History::sample (ACE_UINT64 value)
+{
+ if (this->sample_count_ >= this->max_samples_)
+ return -1;
+
+ this->samples_[this->sample_count_++] = value;
+ return 0;
+}
+
+ACE_INLINE ACE_UINT64
+ACE_Sample_History::get_sample (size_t i) const
+{
+ if (this->sample_count_ <= i)
+ return 0;
+
+ return this->samples_[i];
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Sbrk_Memory_Pool.cpp b/ACE/ace/Sbrk_Memory_Pool.cpp
new file mode 100644
index 00000000000..b747fb9ce15
--- /dev/null
+++ b/ACE/ace/Sbrk_Memory_Pool.cpp
@@ -0,0 +1,124 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Sbrk_Memory_Pool.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Sbrk_Memory_Pool, "$Id$")
+
+#if !defined (ACE_LACKS_SBRK)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_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_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d, new break = %u\n"), nbytes, rounded_bytes, cp));
+ return cp;
+}
+
+/* No-op for now... */
+
+int
+ACE_Sbrk_Memory_Pool::release (int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::release");
+ return 0;
+}
+
+int
+ACE_Sbrk_Memory_Pool::sync (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync");
+ return 0;
+}
+
+int
+ACE_Sbrk_Memory_Pool::sync (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync");
+ return 0;
+}
+
+int
+ACE_Sbrk_Memory_Pool::protect (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect");
+ return 0;
+}
+
+int
+ACE_Sbrk_Memory_Pool::protect (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect");
+ return 0;
+}
+
+// Ask system for initial chunk of local memory.
+
+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);
+}
+
+void
+ACE_Sbrk_Memory_Pool::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool (const ACE_TCHAR *,
+ const OPTIONS *)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool");
+}
+
+ACE_Sbrk_Memory_Pool::~ACE_Sbrk_Memory_Pool (void)
+{
+}
+
+void *
+ACE_Sbrk_Memory_Pool::base_addr (void) const
+{
+ return 0;
+}
+
+// Round up the request to a multiple of the page size.
+
+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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_LACKS_SBRK */
diff --git a/ACE/ace/Sbrk_Memory_Pool.h b/ACE/ace/Sbrk_Memory_Pool.h
new file mode 100644
index 00000000000..3442d5719cf
--- /dev/null
+++ b/ACE/ace/Sbrk_Memory_Pool.h
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Sbrk_Memory_Pool.h
+ *
+ * $Id$
+ *
+ * @author Dougls C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SBRK_MEMORY_POOL_H
+#define ACE_SBRK_MEMORY_POOL_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_SBRK)
+
+#include "ace/ACE.h"
+#include "ace/os_include/sys/os_mman.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a nbytes from the memory pool. @a 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 (int destroy = 1);
+
+ /**
+ * Sync @a len bytes of the memory region to the backing store
+ * starting at @c this->base_addr_. If @a len == -1 then sync the
+ * whole region.
+ */
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync @a len bytes of the memory region to the backing store
+ /// starting at @a addr.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to @a prot
+ * starting at @c this->base_addr_ up to @a len bytes. If @a 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 @a prot
+ /// starting at @a addr up to @a 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;
+
+ /// Return the base address of this memory pool, 0 if base_addr
+ /// never changes.
+ virtual void *base_addr (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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_LACKS_SBRK */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SBRK_MEMORY_POOL_H */
diff --git a/ACE/ace/Sched_Params.cpp b/ACE/ace/Sched_Params.cpp
new file mode 100644
index 00000000000..9a699c773f9
--- /dev/null
+++ b/ACE/ace/Sched_Params.cpp
@@ -0,0 +1,332 @@
+
+//=============================================================================
+/**
+ * @file Sched_Params.cpp
+ *
+ * $Id$
+ *
+ * @author David Levine
+ */
+//=============================================================================
+
+
+#include "ace/Sched_Params.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Sched_Params.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_HAS_PRIOCNTL) && defined (ACE_HAS_STHREADS)
+# include "ace/OS_NS_string.h"
+# include /**/ <sys/priocntl.h>
+#endif /* ACE_HAS_PRIOCNTL && ACE_HAS_THREADS */
+
+ACE_RCSID(ace, Sched_Params, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE_Sched_Params::priority_min (const Policy policy,
+ const int scope)
+{
+#if defined (ACE_HAS_PRIOCNTL) && defined (ACE_HAS_STHREADS)
+ ACE_UNUSED_ARG (scope);
+
+ // Assume that ACE_SCHED_OTHER indicates TS class, and that other
+ // policies indicate RT class.
+
+ // Call ACE_OS::priority_control only for processes (lightweight
+ // or otherwise). Calling ACE_OS::priority_control for thread
+ // priorities gives incorrect results.
+ if (scope == ACE_SCOPE_PROCESS || scope == ACE_SCOPE_LWP)
+ {
+ if (policy == ACE_SCHED_OTHER)
+ {
+ // Get the priority class ID and attributes.
+ pcinfo_t pcinfo;
+ // The following is just to avoid Purify warnings about unitialized
+ // memory reads.
+ ACE_OS::memset (&pcinfo, 0, sizeof pcinfo);
+ ACE_OS::strcpy (pcinfo.pc_clname, "TS");
+
+ if (ACE_OS::priority_control (P_ALL /* ignored */,
+ P_MYID /* ignored */,
+ PC_GETCID,
+ (char *) &pcinfo) == -1)
+ // Just hope that priority range wasn't configured from -1
+ // .. 1
+ return -1;
+
+ // OK, now we've got the class ID in pcinfo.pc_cid. In
+ // addition, the maximum configured time-share priority is in
+ // ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri. The minimum
+ // priority is just the negative of that.
+
+ return -((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri;
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ // Here we handle the case for ACE_SCOPE_THREAD. Calling
+ // ACE_OS::priority_control for thread scope gives incorrect
+ // results.
+ switch (policy)
+ {
+ case ACE_SCHED_FIFO:
+ return ACE_THR_PRI_FIFO_MIN;
+ case ACE_SCHED_RR:
+ return ACE_THR_PRI_RR_MIN;
+ case ACE_SCHED_OTHER:
+ default:
+ return ACE_THR_PRI_OTHER_MIN;
+ }
+ }
+#elif defined(ACE_HAS_PTHREADS) && \
+ (!defined(ACE_LACKS_SETSCHED) || defined (ACE_TANDEM_T1248_PTHREADS) || \
+ defined (ACE_HAS_PTHREAD_SCHEDPARAM))
+
+ switch (scope)
+ {
+ case ACE_SCOPE_THREAD:
+ switch (policy)
+ {
+ case ACE_SCHED_FIFO:
+ return ACE_THR_PRI_FIFO_MIN;
+ case ACE_SCHED_RR:
+ return ACE_THR_PRI_RR_MIN;
+ case ACE_SCHED_OTHER:
+ default:
+ return ACE_THR_PRI_OTHER_MIN;
+ }
+
+ case ACE_SCOPE_PROCESS:
+ default:
+ switch (policy)
+ {
+ case ACE_SCHED_FIFO:
+ return ACE_PROC_PRI_FIFO_MIN;
+ case ACE_SCHED_RR:
+ return ACE_PROC_PRI_RR_MIN;
+ case ACE_SCHED_OTHER:
+ default:
+ return ACE_PROC_PRI_OTHER_MIN;
+ }
+ }
+
+#elif defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+ return THREAD_PRIORITY_IDLE;
+#elif defined (ACE_VXWORKS)
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+# if defined (VX_TASK_PRIORITY_MAX)
+ return VX_TASK_PRIORITY_MAX;
+# else
+ return 255;
+# endif
+#else
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_PRIOCNTL && defined (ACE_HAS_STHREADS) */
+}
+
+int
+ACE_Sched_Params::priority_max (const Policy policy,
+ const int scope)
+{
+#if defined (ACE_HAS_PRIOCNTL) && defined (ACE_HAS_STHREADS)
+ ACE_UNUSED_ARG (scope);
+
+ // Call ACE_OS::priority_control only for processes (lightweight
+ // or otherwise). Calling ACE_OS::priority_control for thread
+ // priorities gives incorrect results.
+ if (scope == ACE_SCOPE_PROCESS || scope == ACE_SCOPE_LWP)
+ {
+ // Assume that ACE_SCHED_OTHER indicates TS class, and that other
+ // policies indicate RT class.
+
+ // Get the priority class ID and attributes.
+ pcinfo_t pcinfo;
+ // The following is just to avoid Purify warnings about unitialized
+ // memory reads.
+ ACE_OS::memset (&pcinfo, 0, sizeof pcinfo);
+ ACE_OS::strcpy (pcinfo.pc_clname,
+ policy == ACE_SCHED_OTHER ? "TS" : "RT");
+
+ if (ACE_OS::priority_control (P_ALL /* ignored */,
+ P_MYID /* ignored */,
+ PC_GETCID,
+ (char *) &pcinfo) == -1)
+ return -1;
+
+ // OK, now we've got the class ID in pcinfo.pc_cid. In addition,
+ // the maximum configured real-time priority is in ((rtinfo_t *)
+ // pcinfo.pc_clinfo)->rt_maxpri, or similarly for the TS class.
+
+ return policy == ACE_SCHED_OTHER
+ ? ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri
+ : ((rtinfo_t *) pcinfo.pc_clinfo)->rt_maxpri;
+ }
+ else
+ {
+ // Here we handle the case for ACE_SCOPE_THREAD. Calling
+ // ACE_OS::priority_control for thread scope gives incorrect
+ // results.
+ switch (policy)
+ {
+ case ACE_SCHED_FIFO:
+ return ACE_THR_PRI_FIFO_MAX;
+ case ACE_SCHED_RR:
+ return ACE_THR_PRI_RR_MAX;
+ case ACE_SCHED_OTHER:
+ default:
+ return ACE_THR_PRI_OTHER_MAX;
+ }
+ }
+#elif defined(ACE_HAS_PTHREADS) && \
+ (!defined(ACE_LACKS_SETSCHED) || defined (ACE_TANDEM_T1248_PTHREADS) || \
+ defined (ACE_HAS_PTHREAD_SCHEDPARAM))
+
+ switch (scope)
+ {
+ case ACE_SCOPE_THREAD:
+ switch (policy)
+ {
+ case ACE_SCHED_FIFO:
+ return ACE_THR_PRI_FIFO_MAX;
+ case ACE_SCHED_RR:
+ return ACE_THR_PRI_RR_MAX;
+ case ACE_SCHED_OTHER:
+ default:
+ return ACE_THR_PRI_OTHER_MAX;
+ }
+
+ case ACE_SCOPE_PROCESS:
+ default:
+ switch (policy)
+ {
+ case ACE_SCHED_FIFO:
+ return ACE_PROC_PRI_FIFO_MAX;
+ case ACE_SCHED_RR:
+ return ACE_PROC_PRI_RR_MAX;
+ case ACE_SCHED_OTHER:
+ default:
+ return ACE_PROC_PRI_OTHER_MAX;
+ }
+ }
+
+#elif defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+ return THREAD_PRIORITY_TIME_CRITICAL;
+#elif defined (ACE_VXWORKS)
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+# if defined (VX_TASK_PRIORITY_MIN)
+ return VX_TASK_PRIORITY_MIN;
+# else
+ return 0;
+# endif
+#else
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_PRIOCNTL && defined (ACE_HAS_STHREADS) */
+}
+
+int
+ACE_Sched_Params::next_priority (const Policy policy,
+ const int priority,
+ const int scope)
+{
+#if defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+ switch (priority)
+ {
+ case THREAD_PRIORITY_IDLE:
+ return THREAD_PRIORITY_LOWEST;
+ case THREAD_PRIORITY_LOWEST:
+ return THREAD_PRIORITY_BELOW_NORMAL;
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ return THREAD_PRIORITY_NORMAL;
+ case THREAD_PRIORITY_NORMAL:
+ return THREAD_PRIORITY_ABOVE_NORMAL;
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ return THREAD_PRIORITY_HIGHEST;
+ case THREAD_PRIORITY_HIGHEST:
+ return THREAD_PRIORITY_TIME_CRITICAL;
+ case THREAD_PRIORITY_TIME_CRITICAL:
+ return THREAD_PRIORITY_TIME_CRITICAL;
+ default:
+ return priority; // unknown priority: should never get here
+ }
+#elif defined(ACE_HAS_THREADS) && \
+ (!defined(ACE_LACKS_SETSCHED) || defined (ACE_TANDEM_T1248_PTHREADS) || \
+ defined (ACE_HAS_PTHREAD_SCHEDPARAM))
+ // including STHREADS, and PTHREADS
+ int const max = priority_max (policy, scope);
+ return priority < max ? priority + 1 : max;
+#elif defined (ACE_VXWORKS)
+ return priority > priority_max (policy, scope)
+ ? priority - 1
+ : priority_max (policy, scope);
+#else
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+ ACE_UNUSED_ARG (priority);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+int
+ACE_Sched_Params::previous_priority (const Policy policy,
+ const int priority,
+ const int scope)
+{
+#if defined (ACE_HAS_WTHREADS)
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+ switch (priority)
+ {
+ case THREAD_PRIORITY_IDLE:
+ return THREAD_PRIORITY_IDLE;
+ case THREAD_PRIORITY_LOWEST:
+ return THREAD_PRIORITY_IDLE;
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ return THREAD_PRIORITY_LOWEST;
+ case THREAD_PRIORITY_NORMAL:
+ return THREAD_PRIORITY_BELOW_NORMAL;
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ return THREAD_PRIORITY_NORMAL;
+ case THREAD_PRIORITY_HIGHEST:
+ return THREAD_PRIORITY_ABOVE_NORMAL;
+ case THREAD_PRIORITY_TIME_CRITICAL:
+ return THREAD_PRIORITY_HIGHEST;
+ default:
+ return priority; // unknown priority: should never get here
+ }
+#elif defined(ACE_HAS_THREADS) && \
+ (!defined(ACE_LACKS_SETSCHED) || defined (ACE_TANDEM_T1248_PTHREADS) || \
+ defined (ACE_HAS_PTHREAD_SCHEDPARAM))
+ // including STHREADS and PTHREADS
+ int const min = priority_min (policy, scope);
+
+ return priority > min ? priority - 1 : min;
+#elif defined (ACE_VXWORKS)
+ return priority < priority_min (policy, scope)
+ ? priority + 1
+ : priority_min (policy, scope);
+#else
+ ACE_UNUSED_ARG (policy);
+ ACE_UNUSED_ARG (scope);
+ ACE_UNUSED_ARG (priority);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_THREADS */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Sched_Params.h b/ACE/ace/Sched_Params.h
new file mode 100644
index 00000000000..36e2935bb87
--- /dev/null
+++ b/ACE/ace/Sched_Params.h
@@ -0,0 +1,232 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Sched_Params.h
+ *
+ * $Id$
+ *
+ * @author David Levine <levine@cs.wustl.edu>
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SCHED_PARAMS_H
+#define ACE_SCHED_PARAMS_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Sched_Params
+ *
+ * @brief Container for scheduling-related parameters.
+ *
+ * ACE_Sched_Params are passed via <ACE_OS::sched_params> to the
+ * OS to specify scheduling parameters. These parameters include
+ * scheduling policy, such as FIFO (ACE_SCHED_FIFO), round-robin
+ * (ACE_SCHED_RR), or an implementation-defined "OTHER"
+ * (ACE_SCHED_OTHER), to which many systems default; priority;
+ * and a time-slice quantum for round-robin scheduling. A
+ * "scope" parameter specifies whether the ACE_Sched_Params
+ * applies to the current process, current lightweight process
+ * (LWP) (on Solaris), or current thread. Please see the "NOTE"
+ * below about not all combinations of parameters being legal on
+ * a particular platform.
+ * For the case of thread priorities, it is intended that
+ * <ACE_OS::sched_params> usually be called from <main> before
+ * any threads have been spawned. If spawned threads inherit
+ * their parent's priority (I think that's the default behavior
+ * for all of our platforms), then this sets the default base
+ * priority. Individual thread priorities can be adjusted as
+ * usual using <ACE_OS::thr_prio> or via the ACE_Thread
+ * interface. See the parameter descriptions in the private:
+ * section below.
+ * @note This class does not do any checking of parameters. It
+ * is just a container class. If it is constructed with values
+ * that are not supported on a platform, the call to
+ * <ACE_OS::sched_params> will fail by returning -1 with EINVAL
+ * (available through <ACE_OS::last_error>).
+ */
+class ACE_Export ACE_Sched_Params
+{
+ // NOTE: Solaris 2.5.x threads in the RT class must set the
+ // priority of their LWP. The only way to do that through ACE is
+ // for the RT thread itself to call <ACE_OS::thr_setprio> with
+ // it's own priority.
+
+ // OS Scheduling parameters are complicated and often confusing.
+ // Many thanks to Thilo Kielmann
+ // <kielmann@informatik.uni-siegen.de> for his careful review of
+ // this class design, thoughtful comments, and assistance with
+ // implementation, especially for PTHREADS platforms. Please
+ // send any comments or corrections to the ACE developers.
+public:
+ typedef int Policy;
+
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Sched_Params (const Policy policy,
+ const ACE_Sched_Priority priority,
+ const int scope = ACE_SCOPE_THREAD,
+ const ACE_Time_Value &quantum = ACE_Time_Value::zero);
+
+ /// Termination.
+ ~ACE_Sched_Params (void);
+
+ // = Get/Set methods:
+
+ // = Get/Set policy
+ Policy policy (void) const;
+ void policy (const Policy);
+
+ // = Get/Set priority.
+ ACE_Sched_Priority priority (void) const;
+ void priority (const ACE_Sched_Priority);
+
+ // = Get/Set scope.
+ int scope (void) const;
+ void scope(const int);
+
+ // = Get/Set quantum.
+ const ACE_Time_Value &quantum (void) const;
+ void quantum (const ACE_Time_Value &);
+
+ // = Accessors for OS-specific priorities.
+ // These return priority values for ACE_SCHED_OTHER if the Policy value
+ // is invalid.
+ static int priority_min (const Policy,
+ const int scope = ACE_SCOPE_THREAD);
+ static int priority_max (const Policy,
+ const int scope = ACE_SCOPE_THREAD);
+
+ /**
+ * The next higher priority. "Higher" refers to scheduling priority,
+ * not to the priority value itself. (On some platforms, higher scheduling
+ * priority is indicated by a lower priority value.) If "priority" is
+ * already the highest priority (for the specified policy), then it is
+ * returned.
+ */
+ static int next_priority (const Policy,
+ const int priority,
+ const int scope = ACE_SCOPE_THREAD);
+
+ /**
+ * The previous, lower priority. "Lower" refers to scheduling priority,
+ * not to the priority value itself. (On some platforms, lower scheduling
+ * priority is indicated by a higher priority value.) If "priority" is
+ * already the lowest priority (for the specified policy), then it is
+ * returned.
+ */
+ static int previous_priority (const Policy,
+ const int priority,
+ const int scope = ACE_SCOPE_THREAD);
+
+private:
+ /// Scheduling policy.
+ Policy policy_;
+
+ /// Default <priority_>: for setting the priority for the process, LWP,
+ /// or thread, as indicated by the scope_ parameter.
+ ACE_Sched_Priority priority_;
+
+ /**
+ * <scope_> must be one of the following:
+ * ACE_SCOPE_PROCESS: sets the scheduling policy for the
+ * process, and the process priority. On some platforms,
+ * such as Win32, the scheduling policy can _only_ be
+ * set at process scope.
+ * ACE_SCOPE_LWP: lightweight process scope, only used with
+ * Solaris threads.
+ * ACE_SCOPE_THREAD: sets the scheduling policy for the thread,
+ * if the OS supports it, such as with Posix threads, and the
+ * thread priority.
+ * NOTE: I don't think that these are the same as POSIX
+ * contention scope. POSIX users who are interested in,
+ * and understand, contention scope will have to set it
+ * by using system calls outside of ACE.
+ */
+ int scope_;
+
+ /**
+ * The <quantum_> is for time slicing. An ACE_Time_Value of 0 has
+ * special significance: it means time-slicing is disabled; with
+ * that, a thread that is running on a CPU will continue to run
+ * until it blocks or is preempted. Currently ignored if the OS
+ * doesn't directly support time slicing, such as on VxWorks, or
+ * setting the quantum (can that be done on Win32?).
+ */
+ ACE_Time_Value quantum_;
+};
+
+/**
+ * @class ACE_Sched_Priority_Iterator
+ *
+ * @brief An iterator over the OS-defined scheduling priorities.
+ *
+ * The order of priorities (numeric value vs. importance) is OS
+ * dependant, it can be the case that the priorities are not even
+ * contigous. This class permits iteration over priorities using
+ * the iterator pattern.
+ */
+class ACE_Export ACE_Sched_Priority_Iterator
+{
+public:
+ /// Initialize the iterator, the arguments define the scheduling
+ /// policy and scope for the priorities (see ACE_Sched_Param).
+ ACE_Sched_Priority_Iterator (const ACE_Sched_Params::Policy &policy,
+ int scope = ACE_SCOPE_THREAD);
+
+ /// Default dtor.
+ ~ACE_Sched_Priority_Iterator (void);
+
+ /// Check if there are more priorities.
+ int more (void) const;
+
+ /// Return the current priority.
+ int priority (void) const;
+
+ /// Move to the next priority.
+ /// The iteration is from lowest to highest importance.
+ void next (void);
+
+ /// Accessor for the scheduling policy over which we are iterating.
+ const ACE_Sched_Params::Policy &policy (void) const;
+
+ /// Accessor for the scheduling
+ int scope (void) const;
+
+private:
+ /// The Scheduling policy (FIFO, RR, etc.) and scheduling scope
+ /// (PROCESS, SYSTEM) we are iterating on.
+ ACE_Sched_Params::Policy policy_;
+ int scope_;
+
+ /// The current priority.
+ int priority_;
+
+ /**
+ * This is set to 1 when there are no more priorities. Cannot easily
+ * compare against the highest priority on platforms were priorities
+ * are non-contigous or descending.
+ */
+ int done_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Sched_Params.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SCHED_PARAMS_H */
diff --git a/ACE/ace/Sched_Params.inl b/ACE/ace/Sched_Params.inl
new file mode 100644
index 00000000000..043ebbeae1c
--- /dev/null
+++ b/ACE/ace/Sched_Params.inl
@@ -0,0 +1,134 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Sched_Params.inl
+ *
+ * $Id$
+ *
+ * @author David Levine
+ */
+//=============================================================================
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Sched_Params::ACE_Sched_Params (
+ const Policy policy,
+ const ACE_Sched_Priority priority,
+ const int scope,
+ const ACE_Time_Value &quantum)
+ : policy_ (policy),
+ priority_ (priority),
+ scope_ (scope),
+ quantum_ (quantum)
+{
+}
+
+ACE_INLINE ACE_Sched_Params::~ACE_Sched_Params (void)
+{
+}
+
+ACE_INLINE ACE_Sched_Params::Policy
+ACE_Sched_Params::policy (void) const
+{
+ return this->policy_;
+}
+
+ACE_INLINE void
+ACE_Sched_Params::policy (const ACE_Sched_Params::Policy policy)
+{
+ this->policy_ = policy;
+}
+
+ACE_INLINE ACE_Sched_Priority
+ACE_Sched_Params::priority (void) const
+{
+ return this->priority_;
+}
+
+ACE_INLINE void
+ACE_Sched_Params::priority (const ACE_Sched_Priority priority)
+{
+ this->priority_ = priority;
+}
+
+ACE_INLINE int
+ACE_Sched_Params::scope (void) const
+{
+ return this->scope_;
+}
+
+ACE_INLINE void
+ACE_Sched_Params::scope (const int scope)
+{
+ this->scope_ = scope;
+}
+
+ACE_INLINE const ACE_Time_Value &
+ACE_Sched_Params::quantum (void) const
+{
+ return this->quantum_;
+}
+
+ACE_INLINE void
+ACE_Sched_Params::quantum (const ACE_Time_Value &quant)
+{
+ this->quantum_ = quant;
+}
+
+ACE_INLINE const ACE_Sched_Params::Policy &
+ACE_Sched_Priority_Iterator::policy (void) const
+{
+ return this->policy_;
+}
+
+ACE_INLINE int
+ACE_Sched_Priority_Iterator::scope (void) const
+{
+ return this->scope_;
+}
+
+ACE_INLINE
+ACE_Sched_Priority_Iterator::ACE_Sched_Priority_Iterator (const ACE_Sched_Params::Policy &policy,
+ int scope)
+ : policy_ (policy),
+ scope_ (scope),
+ priority_ (0),
+ done_ (0)
+{
+ priority_ = ACE_Sched_Params::priority_min (this->policy (), this->scope ());
+}
+
+ACE_INLINE
+ACE_Sched_Priority_Iterator::~ACE_Sched_Priority_Iterator (void)
+{
+}
+
+ACE_INLINE int
+ACE_Sched_Priority_Iterator::more (void) const
+{
+ return !this->done_;
+}
+
+ACE_INLINE int
+ACE_Sched_Priority_Iterator::priority (void) const
+{
+ return this->priority_;
+}
+
+ACE_INLINE void
+ACE_Sched_Priority_Iterator::next (void)
+{
+ if (this->done_)
+ return;
+
+ int old_priority = this->priority_;
+ priority_ = ACE_Sched_Params::next_priority (this->policy (),
+ this->priority (),
+ this->scope ());
+ this->done_ = old_priority == priority_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Select_Reactor.h b/ACE/ace/Select_Reactor.h
new file mode 100644
index 00000000000..8e7b1697ce3
--- /dev/null
+++ b/ACE/ace/Select_Reactor.h
@@ -0,0 +1,69 @@
+// -*- 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"
+#include "ace/Reactor_Token_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//@@ TAO_REACTOR_SPL_COMMENT_HOOK_START
+typedef ACE_Reactor_Token_T<ACE_SELECT_TOKEN> ACE_Select_Reactor_Token;
+
+typedef ACE_Select_Reactor_T<ACE_Select_Reactor_Token> ACE_Select_Reactor;
+//@@ TAO_REACTOR_SPL_COMMENT_HOOK_END
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE == 0)
+/**
+ * @class ACE_Guard< ACE_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.
+ */
+template<>
+class ACE_Export ACE_Guard< ACE_Reactor_Token_T<ACE_Noop_Token> >
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Guard (ACE_Reactor_Token_T<ACE_Noop_Token> &) {}
+ ACE_Guard (ACE_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:
+ // Disallow copying and assignment.
+ ACE_Guard (const ACE_Guard< ACE_Reactor_Token_T<ACE_Noop_Token> > &);
+ void operator= (const ACE_Guard< ACE_Reactor_Token_T<ACE_Noop_Token> > &);
+
+};
+#endif /* ACE_MT_SAFE && ACE_MT_SAFE == 0 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SELECT_REACTOR_H */
diff --git a/ACE/ace/Select_Reactor_Base.cpp b/ACE/ace/Select_Reactor_Base.cpp
new file mode 100644
index 00000000000..5b40ddfab5b
--- /dev/null
+++ b/ACE/ace/Select_Reactor_Base.cpp
@@ -0,0 +1,1104 @@
+// $Id$
+
+#include "ace/Select_Reactor_Base.h"
+#include "ace/Reactor.h"
+#include "ace/Thread.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Timer_Queue.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/OS_NS_fcntl.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Select_Reactor_Base.inl"
+#endif /* __ACE_INLINE__ */
+
+#ifndef ACE_WIN32
+# include <algorithm>
+#endif /* !ACE_WIN32 */
+
+ACE_RCSID (ace,
+ Select_Reactor_Base,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<typename iterator>
+inline ACE_Event_Handler *
+ACE_SELECT_REACTOR_EVENT_HANDLER (iterator i)
+{
+#ifdef ACE_WIN32
+ return (*i).item ();
+#else
+ return (*i);
+#endif /* ACE_WIN32 */
+}
+
+// Performs sanity checking on the ACE_HANDLE.
+
+bool
+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
+ || static_cast<size_type> (handle) >= this->event_handlers_.size ())
+#endif /* ACE_WIN32 */
+ {
+ errno = EINVAL;
+ return true;
+ }
+
+ return false;
+}
+
+// Performs sanity checking on the ACE_HANDLE.
+
+bool
+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 true;
+ }
+
+ // Don't bother setting errno. It isn't used in the select()-based
+ // reactors and incurs a TSS access.
+ // errno = EINVAL;
+
+ return false;
+}
+
+int
+ACE_Select_Reactor_Handler_Repository::open (size_t size)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::open");
+
+#if defined (ACE_WIN32)
+ if (this->event_handlers_.open (size) == -1)
+ return -1;
+#else
+ if (this->event_handlers_.size (size) == -1)
+ return -1;
+
+ // Initialize the ACE_Event_Handler pointers to 0.
+ std::fill (this->event_handlers_.begin (),
+ this->event_handlers_.end (),
+ static_cast<ACE_Event_Handler *> (0));
+
+ this->max_handlep1_ = 0;
+#endif /* ACE_WIN32 */
+
+ // Try to increase the number of handles if <size> is greater than
+ // the current limit.
+ return ACE::set_handle_limit (static_cast<int> (size), 1);
+}
+
+// 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),
+#ifndef ACE_WIN32
+ max_handlep1_ (0),
+#endif /* !ACE_WIN32 */
+ event_handlers_ ()
+{
+ 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.
+#ifdef ACE_WIN32
+ map_type::iterator const end = this->event_handlers_.end ();
+ for (map_type::iterator pos = this->event_handlers_.begin ();
+ pos != end;
+ )
+ {
+ // Post-increment (*not* pre-increment) before unbind()ing since
+ // the current iterator will be invalidated during the unbind()
+ // operation.
+ map_type::iterator const the_pos (pos++);
+
+ ACE_HANDLE const handle = (*the_pos).key ();
+ (void) this->unbind (handle,
+ the_pos,
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+ }
+#else
+ // We could use the "end()" iterator but leveraging max_handlep1_
+ // allows us to optimize away unnecessary accesses of nil event
+ // handler pointers.
+ map_type::iterator pos =
+ this->event_handlers_.begin (); // iterator == ACE_Event_Handler*
+
+ for (ACE_HANDLE handle = 0;
+ handle < this->max_handlep1_;
+ ++handle)
+ {
+ (void) this->unbind (handle,
+ pos,
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+ ++pos;
+ }
+#endif /* ACE_WIN32 */
+
+ return 0;
+}
+
+int
+ACE_Select_Reactor_Handler_Repository::close (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::close");
+
+ return this->unbind_all ();
+}
+
+ACE_Select_Reactor_Handler_Repository::map_type::iterator
+ACE_Select_Reactor_Handler_Repository::find_eh (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::find_eh");
+
+ map_type::iterator pos (this->event_handlers_.end ());
+
+ // this code assumes the handle is in range.
+#if defined (ACE_WIN32)
+ this->event_handlers_.find (handle, pos);
+#else
+ map_type::iterator const tmp = &this->event_handlers_[handle];
+
+ if (*tmp != 0)
+ pos = tmp;
+#endif /* ACE_WIN32 */
+
+ return pos;
+}
+
+// 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 (event_handler == 0)
+ return -1;
+
+ if (handle == ACE_INVALID_HANDLE)
+ handle = event_handler->get_handle ();
+
+ if (this->invalid_handle (handle))
+ return -1;
+
+ // Is this handle already in the Reactor?
+ bool existing_handle = false;
+
+#if defined (ACE_WIN32)
+
+ map_type::ENTRY * entry = 0;
+
+ int const result =
+ this->event_handlers_.bind (handle, event_handler, entry);
+
+ if (result == -1)
+ {
+ return -1;
+ }
+ else if (result == 1) // Entry already exists.
+ {
+ // Cannot use a different handler for an existing handle.
+ if (event_handler != entry->item ())
+ {
+ return -1;
+ }
+ else
+ {
+ // Remember that this handle is already registered in the
+ // Reactor.
+ existing_handle = true;
+ }
+ }
+
+#else
+
+ // Check if this handle is already registered.
+ ACE_Event_Handler * const current_handler =
+ this->event_handlers_[handle];
+
+ if (current_handler)
+ {
+ // Cannot use a different handler for an existing handle.
+ if (current_handler != event_handler)
+ return -1;
+
+ // Remember that this handle is already registered in the
+ // Reactor.
+ existing_handle = true;
+ }
+
+ this->event_handlers_[handle] = event_handler;
+
+ if (this->max_handlep1_ < handle + 1)
+ this->max_handlep1_ = handle + 1;
+
+#endif /* ACE_WIN32 */
+
+ if (this->select_reactor_.is_suspended_i (handle))
+ {
+ this->select_reactor_.bit_ops (handle,
+ mask,
+ this->select_reactor_.suspend_set_,
+ ACE_Reactor::ADD_MASK);
+ }
+ else
+ {
+ 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;
+ }
+
+ // If new entry, call add_reference() if needed.
+ if (!existing_handle)
+ event_handler->add_reference ();
+
+ return 0;
+}
+
+// Remove the binding of <ACE_HANDLE>.
+
+int
+ACE_Select_Reactor_Handler_Repository::unbind (
+ ACE_HANDLE handle,
+ map_type::iterator pos,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::unbind");
+
+ // Retrieve event handler before unbinding it from the map. The
+ // iterator pointing to it will no longer be valid once the handler
+ // is unbound.
+ ACE_Event_Handler * const event_handler =
+ (pos == this->event_handlers_.end ()
+ ? 0
+ : ACE_SELECT_REACTOR_EVENT_HANDLER (pos));
+
+ // 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;
+
+ // If there are no longer any outstanding events on this <handle>
+ // then we can totally shut down the Event_Handler.
+
+ bool const has_any_wait_mask =
+ (this->select_reactor_.wait_set_.rd_mask_.is_set (handle)
+ || this->select_reactor_.wait_set_.wr_mask_.is_set (handle)
+ || this->select_reactor_.wait_set_.ex_mask_.is_set (handle));
+ bool const has_any_suspend_mask =
+ (this->select_reactor_.suspend_set_.rd_mask_.is_set (handle)
+ || this->select_reactor_.suspend_set_.wr_mask_.is_set (handle)
+ || this->select_reactor_.suspend_set_.ex_mask_.is_set (handle));
+
+ bool complete_removal = false;
+
+ if (!has_any_wait_mask && !has_any_suspend_mask)
+ {
+#if defined (ACE_WIN32)
+ if (event_handler != 0 && this->event_handlers_.unbind (pos) == -1)
+ return -1; // Should not happen!
+#else
+ this->event_handlers_[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 const wait_rd_max =
+ this->select_reactor_.wait_set_.rd_mask_.max_set ();
+ ACE_HANDLE const wait_wr_max =
+ this->select_reactor_.wait_set_.wr_mask_.max_set ();
+ ACE_HANDLE const wait_ex_max =
+ this->select_reactor_.wait_set_.ex_mask_.max_set ();
+
+ ACE_HANDLE const suspend_rd_max =
+ this->select_reactor_.suspend_set_.rd_mask_.max_set ();
+ ACE_HANDLE const suspend_wr_max =
+ this->select_reactor_.suspend_set_.wr_mask_.max_set ();
+ ACE_HANDLE const 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 */
+
+ // The handle has been completely removed.
+ complete_removal = true;
+ }
+
+ if (event_handler == 0)
+ return -1;
+
+ bool const requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ // Close down the <Event_Handler> unless we've been instructed not
+ // to.
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0)
+ (void) event_handler->handle_close (handle, mask);
+
+ // Call remove_reference() if the removal is complete and reference
+ // counting is needed.
+ if (complete_removal && requires_reference_counting)
+ {
+ (void) event_handler->remove_reference ();
+ }
+
+ return 0;
+}
+
+ACE_Select_Reactor_Handler_Repository_Iterator::ACE_Select_Reactor_Handler_Repository_Iterator
+ (ACE_Select_Reactor_Handler_Repository const * s)
+ : rep_ (s),
+ current_ (s->event_handlers_.begin ())
+{
+}
+
+// Pass back the <next_item> that hasn't been seen in the Set.
+// Returns 0 when all items have been seen, else 1.
+
+bool
+ACE_Select_Reactor_Handler_Repository_Iterator::next (
+ ACE_Event_Handler *&next_item)
+{
+ bool result = true;
+
+ if (this->done ())
+ result = false;
+ else
+ next_item = ACE_SELECT_REACTOR_EVENT_HANDLER (this->current_);
+
+ return result;
+}
+
+// Move forward by one element in the set.
+
+bool
+ACE_Select_Reactor_Handler_Repository_Iterator::advance (void)
+{
+#ifdef ACE_WIN32
+ // No need to explicitly limit search to "current" to
+ // max_handlep1_ range.
+ const_base_iterator const end = this->rep_->event_handlers_.end ();
+#else
+ // Don't use ACE_Array_Base::end() since it may be larger than
+ // event_handlers[max_handlep1_].
+ const_base_iterator const end =
+ &this->rep_->event_handlers_[this->rep_->max_handlep1 ()];
+#endif /* ACE_WIN32 */
+
+ if (this->current_ != end)
+ ++this->current_;
+
+#ifndef ACE_WIN32
+ // Advance to the next element containing a non-zero event handler.
+ // There's no need to do this for the Windows case since the hash
+ // map will only contain non-zero event handlers.
+ while (this->current_ != end && (*(this->current_) == 0))
+ ++this->current_;
+#endif /* !ACE_WIN32 */
+
+ return this->current_ != end;
+}
+
+// Dump the state of an object.
+
+void
+ACE_Select_Reactor_Handler_Repository_Iterator::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository_Iterator::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("rep_ = %u"), this->rep_));
+# ifdef ACE_WIN32
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("current_ = ")));
+ this->current_.dump ();
+# else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("current_ = %@"), this->current_));
+# endif /* ACE_WIN32 */
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Select_Reactor_Handler_Repository::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::dump");
+
+# ifdef ACE_WIN32
+# define ACE_HANDLE_FORMAT_SPECIFIER ACE_TEXT("%@")
+# define ACE_MAX_HANDLEP1_FORMAT_SPECIFIER ACE_TEXT("%u")
+# else
+# define ACE_HANDLE_FORMAT_SPECIFIER ACE_TEXT("%d")
+# define ACE_MAX_HANDLEP1_FORMAT_SPECIFIER ACE_TEXT("%d")
+# endif /* ACE_WIN32 */
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("max_handlep1_ = ")
+ ACE_MAX_HANDLEP1_FORMAT_SPECIFIER
+ ACE_TEXT ("\n"),
+ this->max_handlep1 ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("[")));
+
+ ACE_Event_Handler *event_handler = 0;
+
+ for (ACE_Select_Reactor_Handler_Repository_Iterator iter (this);
+ iter.next (event_handler) != 0;
+ iter.advance ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT (" (event_handler = %@,")
+ ACE_TEXT (" event_handler->handle_ = ")
+ ACE_HANDLE_FORMAT_SPECIFIER
+ ACE_TEXT ("\n"),
+ event_handler,
+ event_handler->get_handle ()));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" ]\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Select_Reactor_Handler_Repository_Iterator)
+
+ACE_Select_Reactor_Notify::ACE_Select_Reactor_Notify (void)
+ : max_notify_iterations_ (-1)
+{
+}
+
+ACE_Select_Reactor_Notify::~ACE_Select_Reactor_Notify (void)
+{
+}
+
+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)
+
+ return notification_queue_.purge_pending_notifications(eh, mask);
+
+#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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Select_Reactor_Notify::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("select_reactor_ = %x"), this->select_reactor_));
+ this->notification_pipe_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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_ =
+ 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)
+ if (notification_queue_.open() == -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)
+ notification_queue_.reset();
+#else
+ if (this->notification_pipe_.read_handle() != ACE_INVALID_HANDLE)
+ {
+ // Please see Bug 2820, if we just close the pipe then we break
+ // the reference counting rules. Basically, all the event
+ // handlers "stored" in the pipe had their reference counts
+ // increased. We need to decrease them before closing the
+ // pipe....
+ ACE_Notification_Buffer b;
+ for (int r = read_notify_pipe(notification_pipe_.read_handle(), b);
+ r > 0;
+ r = read_notify_pipe(notification_pipe_.read_handle(), b))
+ {
+ if (b.eh_ != 0)
+ {
+ b.eh_->remove_reference();
+ }
+ }
+ }
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ return this->notification_pipe_.close ();
+}
+
+int
+ACE_Select_Reactor_Notify::notify (ACE_Event_Handler *event_handler,
+ 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;
+
+ ACE_Event_Handler_var safe_handler (event_handler);
+
+ if (event_handler)
+ event_handler->add_reference ();
+
+ ACE_Notification_Buffer buffer (event_handler, mask);
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ int const notification_required =
+ notification_queue_.push_new_notification(buffer);
+
+ if (notification_required == -1)
+ {
+ return -1;
+ }
+
+ if (notification_required == 0)
+ {
+ // No failures, the handler is now owned by the notification queue
+ safe_handler.release ();
+
+ return 0;
+ }
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ ssize_t const n = ACE::send (this->notification_pipe_.write_handle (),
+ (char *) &buffer,
+ sizeof buffer,
+ timeout);
+ if (n == -1)
+ return -1;
+
+ // No failures.
+ safe_handler.release ();
+
+ return 0;
+}
+
+// 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 const 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 ();
+}
+
+
+int
+ACE_Select_Reactor_Notify::is_dispatchable (ACE_Notification_Buffer &buffer)
+{
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ ACE_UNUSED_ARG(buffer);
+ return 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;
+ }
+ else
+ {
+ // has no dispatchable buffer
+ return 0;
+ }
+#endif /*ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+}
+
+int
+ACE_Select_Reactor_Notify::dispatch_notify (ACE_Notification_Buffer &buffer)
+{
+ int result = 0;
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ // Dispatch one message from the notify queue, and put another in
+ // the pipe if one is available. Remember, the idea is to keep
+ // exactly one message in the pipe at a time.
+
+ bool more_messages_queued = false;
+ ACE_Notification_Buffer next;
+
+ result = notification_queue_.pop_next_notification(buffer,
+ more_messages_queued,
+ next);
+
+ if (result == 0)
+ {
+ return 0;
+ }
+
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if(more_messages_queued)
+ {
+ (void) ACE::send(this->notification_pipe_.write_handle(),
+ (char *)&next, sizeof(ACE_Notification_Buffer));
+ }
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ // 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)
+ {
+ ACE_Event_Handler *event_handler = buffer.eh_;
+
+ bool const requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ switch (buffer.mask_)
+ {
+ case ACE_Event_Handler::READ_MASK:
+ case ACE_Event_Handler::ACCEPT_MASK:
+ result = event_handler->handle_input (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::WRITE_MASK:
+ result = event_handler->handle_output (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::EXCEPT_MASK:
+ result = event_handler->handle_exception (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::QOS_MASK:
+ result = event_handler->handle_qos (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::GROUP_QOS_MASK:
+ result = event_handler->handle_group_qos (ACE_INVALID_HANDLE);
+ break;
+ default:
+ // Should we bail out if we get an invalid mask?
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("invalid mask = %d\n"),
+ buffer.mask_));
+ }
+
+ if (result == -1)
+ event_handler->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::EXCEPT_MASK);
+
+ if (requires_reference_counting)
+ {
+ event_handler->remove_reference ();
+ }
+ }
+
+ 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 const 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 const 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;
+}
+
+// -------------------------------------------
+
+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);
+}
+
+
+// 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 (0,
+ this->mask_signals_); // 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;
+ // State was changed. we need to reflect that change in the
+ // dispatch_mask I assume that only ACE_Reactor::CLR_MASK should
+ // be treated here which means we need to clear the handle|mask
+ // from the current dispatch handler
+ this->clear_dispatch_mask (handle, mask);
+ /* 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;
+}
+
+void
+ACE_Select_Reactor_Impl::clear_dispatch_mask (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Impl::clear_dispatch_mask");
+
+ // Use handle and mask in order to modify the sets
+ // (wait/suspend/ready/dispatch), that way, the dispatch_io_set loop
+ // will not be interrupt, and there will no reason to rescan the
+ // wait_set and re-calling select function, which is *very*
+ // expensive. It seems that wait/suspend/ready sets are getting
+ // updated in register/remove bind/unbind etc functions. The only
+ // thing need to be updated is the dispatch_set (also can be found
+ // in that file code as dispatch_mask). Because of that, we need
+ // that dispatch_set to be member of the ACE_Select_Reactor_impl in
+ // Select_Reactor_Base.h file That way we will have access to that
+ // member in that function.
+
+ // We kind of invalidate the iterator in dispatch_io_set because its
+ // an array and index built from the original dispatch-set. Take a
+ // look at dispatch_io_set for more details.
+
+ // We only need to clr_bit, because we are interested in clearing the
+ // handles that was removed, so no dispatching to these handles will
+ // occur.
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK) ||
+ ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ {
+ this->dispatch_set_.rd_mask_.clr_bit (handle);
+ }
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
+ {
+ this->dispatch_set_.wr_mask_.clr_bit (handle);
+ }
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ {
+ this->dispatch_set_.ex_mask_.clr_bit (handle);
+ }
+
+ // That will make the dispatch_io_set iterator re-start and rescan
+ // the dispatch set.
+ this->state_changed_ = true;
+}
+
+
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Select_Reactor_Base.h b/ACE/ace/Select_Reactor_Base.h
new file mode 100644
index 00000000000..7d001e1a8ec
--- /dev/null
+++ b/ACE/ace/Select_Reactor_Base.h
@@ -0,0 +1,611 @@
+// -*- 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/Timer_Queuefwd.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event_Handler.h"
+#include "ace/Handle_Set.h"
+#include "ace/Pipe.h"
+#include "ace/Reactor_Impl.h"
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+# include "ace/Notification_Queue.h"
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+#ifdef ACE_WIN32
+# include "ace/Null_Mutex.h"
+# include "ace/Hash_Map_Manager_T.h"
+# include "ace/Functor.h" /* For ACE_Hash<void *> */
+# include <functional> /* For std::equal_to<> */
+#else
+# include "ace/Array_Base.h"
+#endif /* ACE_WIN32 */
+
+#if !defined (ACE_DISABLE_NOTIFY_PIPE_DEFAULT)
+# define ACE_DISABLE_NOTIFY_PIPE_DEFAULT 0
+#endif /* ACE_DISABLE_NOTIFY_PIPE_DEFAULT */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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_Sig_Handler;
+
+/*
+ * Hook to specialize the Select_Reactor_Base implementation
+ * with the concrete reactor, e.g., select or tp reactor
+ * specified at build/compilation time.
+ */
+//@@ REACTOR_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
+
+/**
+ * @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_Event_Tuple
+{
+public:
+
+ /// Default constructor.
+ ACE_Event_Tuple (void);
+
+ /// Constructor.
+ ACE_Event_Tuple (ACE_Event_Handler *eh, ACE_HANDLE h);
+
+ /// Equality operator.
+ bool operator== (const ACE_Event_Tuple &rhs) const;
+
+ /// Inequality operator.
+ bool operator!= (const ACE_Event_Tuple &rhs) const;
+
+public:
+
+ /// 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 @c select or @c 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 @c notify, the appropriate @c 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:
+ /// Constructor.
+ ACE_Select_Reactor_Notify (void);
+
+ /// Destructor.
+ virtual ~ACE_Select_Reactor_Notify (void);
+
+ // = Initialization and termination methods.
+ /// Initialize.
+ virtual int open (ACE_Reactor_Impl *,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = ACE_DISABLE_NOTIFY_PIPE_DEFAULT);
+
+ /// 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 @c select/poll. Pass over both the
+ * @c Event_Handler *and* the @c mask to allow the caller to dictate
+ * which @c 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 @a timeout == 0,
+ * the caller will block until action is possible, else will wait
+ * until the relative time specified in @c *timeout elapses).
+ */
+ virtual int notify (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value * timeout = 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 @c 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 @a handle into the
+ /// @a 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 @a 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 *sh,
+ ACE_Reactor_Mask 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)
+ /**
+ * @brief A user-space queue to store the notifications.
+ *
+ * The notification pipe has OS-specific size restrictions. That
+ * is, no more than a certain number of bytes may be stored in the
+ * pipe without blocking. This limit may be too small for certain
+ * applications. In this case, ACE can be configured to store all
+ * the events in user-space. The pipe is still needed to wake up
+ * the reactor thread, but only one event is sent through the pipe
+ * at a time.
+ */
+ ACE_Notification_Queue notification_queue_;
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+};
+
+/**
+ * @class ACE_Select_Reactor_Handler_Repository
+ *
+ * @brief Used to map ACE_HANDLEs 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;
+
+ typedef ACE_HANDLE key_type;
+ typedef ACE_Event_Handler * value_type;
+
+ // = The mapping from <HANDLES> to <Event_Handlers>.
+#ifdef ACE_WIN32
+ /**
+ * The NT version implements this via a hash map
+ * @c ACE_Event_Handler*. Since NT implements @c ACE_HANDLE
+ * as a void * we can't directly index into this array. Therefore,
+ * we must explicitly map @c ACE_HANDLE to @c ACE_Event_Handler.
+ */
+ typedef ACE_Hash_Map_Manager_Ex<key_type,
+ value_type,
+ ACE_Hash<key_type>,
+ std::equal_to<key_type>,
+ ACE_Null_Mutex> map_type;
+
+ typedef map_type::size_type max_handlep1_type;
+#else
+ /**
+ * The UNIX version implements this via a dynamically allocated
+ * array of @c ACE_Event_Handler* that is indexed directly using
+ * the @c ACE_HANDLE value.
+ */
+ typedef ACE_Array_Base<value_type> map_type;
+ typedef ACE_HANDLE max_handlep1_type;
+#endif /* ACE_WIN32 */
+
+ typedef map_type::size_type size_type;
+
+ // = Initialization and termination methods.
+ /// Default "do-nothing" constructor.
+ ACE_Select_Reactor_Handler_Repository (ACE_Select_Reactor_Impl &);
+
+ /// Initialize a repository of the appropriate @a 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_type size);
+
+ /// Close down the repository.
+ int close (void);
+
+ // = Search structure operations.
+
+ /**
+ * Return the @c ACE_Event_Handler* associated with @c ACE_HANDLE.
+ */
+ ACE_Event_Handler * find (ACE_HANDLE handle);
+
+ /// 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 @a 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 @a handle to make sure it's a valid @c ACE_HANDLE that
+ // is within the range of legal handles (i.e., >= 0 && < max_size_).
+ bool invalid_handle (ACE_HANDLE handle);
+
+ // Check the @c handle to make sure it's a valid @c ACE_HANDLE that
+ // within the range of currently registered handles (i.e., >= 0 && <
+ // @c max_handlep1_).
+ bool handle_in_range (ACE_HANDLE handle);
+
+ // = Accessors.
+ /// Returns the current table size.
+ size_type size (void) const;
+
+ /// Maximum ACE_HANDLE value, plus 1.
+ max_handlep1_type max_handlep1 (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /// Remove the binding of @a handle corresponding to position @a pos
+ /// in accordance with the @a mask.
+ int unbind (ACE_HANDLE handle,
+ map_type::iterator pos,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * @return @c iterator corresponding @c ACE_Event_Handler*
+ * associated with @c ACE_HANDLE.
+ */
+ map_type::iterator find_eh (ACE_HANDLE handle);
+
+private:
+ /// Reference to our @c Select_Reactor.
+ ACE_Select_Reactor_Impl &select_reactor_;
+
+#ifndef ACE_WIN32
+ /// The highest currently active handle, plus 1 (ranges between 0 and
+ /// @c max_size_.
+ max_handlep1_type max_handlep1_;
+#endif /* !ACE_WIN32 */
+
+ /// Underlying table of event handlers.
+ map_type event_handlers_;
+};
+
+/**
+ * @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:
+
+ typedef
+ ACE_Select_Reactor_Handler_Repository::map_type::const_iterator const_base_iterator;
+
+ // = Initialization method.
+ ACE_Select_Reactor_Handler_Repository_Iterator (
+ ACE_Select_Reactor_Handler_Repository const * s);
+
+ // = Iteration methods.
+
+ /// Pass back the @a next_item that hasn't been seen in the Set.
+ /// Returns @c false when all items have been seen, else @c true.
+ bool next (ACE_Event_Handler* & next_item);
+
+ /// Returns @c true when all items have been seen, else @c false.
+ bool done (void) const;
+
+ /// Move forward by one element in the set. Returns @c false when
+ /// all the items in the set have been seen, else @c true.
+ bool 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.
+ ACE_Select_Reactor_Handler_Repository const * const rep_;
+
+ /// Pointer to the current iteration level.
+ const_base_iterator 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
+ * @c 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 (bool mask_signals = true);
+
+ 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);
+
+ /*
+ * Hook to add concrete methods required to specialize the
+ * implementation with concrete methods required for the concrete
+ * reactor implementation, for example, select, tp reactors.
+ */
+ //@@ REACTOR_SPL_PUBLIC_METHODS_ADD_HOOK
+
+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 &handle_set,
+ int ops);
+
+ /// Enqueue ourselves into the list of waiting threads at the
+ /// appropriate point specified by <requeue_position_>.
+ virtual void renew (void) = 0;
+
+ /// Check to see if the <Event_Handler> associated with @a handle is
+ /// suspended. Returns 0 if not, 1 if so.
+ virtual int is_suspended_i (ACE_HANDLE handle) = 0;
+
+ /// When register/unregister occur, then we need to re-eval our
+ /// wait/suspend/dispatch set.
+ virtual void clear_dispatch_mask (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /// Table that maps <ACE_HANDLEs> to <ACE_Event_Handler *>'s.
+ ACE_Select_Reactor_Handler_Repository handler_rep_;
+
+ /// Tracks handles that are ready for dispatch from <select>
+ ACE_Select_Reactor_Handle_Set dispatch_set_;
+
+ /// 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_;
+
+ /// Handle signals without requiring global/static variables.
+ ACE_Sig_Handler *signal_handler_;
+
+ /// Callback object that unblocks the ACE_Select_Reactor if it's
+ /// sleeping.
+ ACE_Reactor_Notify *notify_handler_;
+
+ /// Keeps track of whether we should delete the timer queue (if we
+ /// didn't create it, then we don't delete it).
+ bool delete_timer_queue_;
+
+ /// Keeps track of whether we should delete the signal handler (if we
+ /// didn't create it, then we don't delete it).
+ bool delete_signal_handler_;
+
+ /// Keeps track of whether we need to delete the notify handler (if
+ /// we didn't create it, then we don't delete it).
+ bool delete_notify_handler_;
+
+ /// True if we've been initialized yet...
+ bool initialized_;
+
+ /// 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_;
+
+ /// 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.
+ */
+ bool state_changed_;
+
+ /**
+ * 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.
+ */
+ bool mask_signals_;
+
+ /// 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 &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Select_Reactor_Base.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SELECT_REACTOR_BASE_H */
diff --git a/ACE/ace/Select_Reactor_Base.inl b/ACE/ace/Select_Reactor_Base.inl
new file mode 100644
index 00000000000..178a8373291
--- /dev/null
+++ b/ACE/ace/Select_Reactor_Base.inl
@@ -0,0 +1,152 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Reactor.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_Select_Reactor_Handler_Repository::size_type
+ACE_Select_Reactor_Handler_Repository::size (void) const
+{
+#ifdef ACE_WIN32
+ return this->event_handlers_.total_size ();
+#else
+ return this->event_handlers_.size ();
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE ACE_Select_Reactor_Handler_Repository::max_handlep1_type
+ACE_Select_Reactor_Handler_Repository::max_handlep1 (void) const
+{
+#ifdef ACE_WIN32
+ return this->event_handlers_.current_size ();
+#else
+ return this->max_handlep1_;
+#endif /* ACE_WIN32 */
+}
+
+ACE_INLINE int
+ACE_Select_Reactor_Handler_Repository::unbind (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ // Do not refactor this code to optimize the call to the unbind impl.
+ // To resolve bug 2653, unbind must be called even when find_eh returns
+ // event_handlers_.end().
+
+ return !this->handle_in_range (handle) ? -1
+ : this->unbind (handle,
+ this->find_eh (handle),
+ mask);
+}
+
+ACE_INLINE ACE_Event_Handler *
+ACE_Select_Reactor_Handler_Repository::find (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::find");
+
+ ACE_Event_Handler * eh = 0;
+
+ if (this->handle_in_range (handle))
+ {
+ map_type::iterator const pos = this->find_eh (handle);
+
+ if (pos != this->event_handlers_.end ())
+ {
+#ifdef ACE_WIN32
+ eh = (*pos).item ();
+#else
+ eh = *pos;
+#endif /* ACE_WIN32 */
+ }
+ }
+ // Don't bother setting errno. It isn't used in the select()-based
+ // reactors and incurs a TSS access.
+ // else
+ // {
+ // errno = ENOENT;
+ // }
+
+ return eh;
+}
+
+// ------------------------------------------------------------------
+
+ACE_INLINE bool
+ACE_Select_Reactor_Handler_Repository_Iterator::done (void) const
+{
+#ifdef ACE_WIN32
+ return this->current_ != this->rep_->event_handlers_.end ();
+#else
+ return this->current_ != (this->rep_->event_handlers_.begin ()
+ + this->rep_->max_handlep1 ());
+#endif /* ACE_WIN32 */
+}
+
+// ------------------------------------------------------------------
+
+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 bool
+ACE_Event_Tuple::operator== (const ACE_Event_Tuple &rhs) const
+{
+ return this->handle_ == rhs.handle_;
+}
+
+ACE_INLINE bool
+ACE_Event_Tuple::operator!= (const ACE_Event_Tuple &rhs) const
+{
+ return !(*this == rhs);
+}
+
+#if defined (ACE_WIN32_VC8) || defined (ACE_WIN32_VC9)
+# pragma warning (push)
+# pragma warning (disable:4355) /* Use of 'this' in initializer list */
+#endif
+ACE_INLINE
+ACE_Select_Reactor_Impl::ACE_Select_Reactor_Impl (bool ms)
+ : handler_rep_ (*this)
+ , timer_queue_ (0)
+ , signal_handler_ (0)
+ , notify_handler_ (0)
+ , delete_timer_queue_ (false)
+ , delete_signal_handler_ (false)
+ , delete_notify_handler_ (false)
+ , initialized_ (false)
+ , restart_ (0)
+ , requeue_position_ (-1) // Requeue at end of waiters by default.
+ , state_changed_ (0)
+ , mask_signals_ (ms)
+ , supress_renew_ (0)
+{
+}
+#if defined (ACE_WIN32_VC8) || defined (ACE_WIN32_VC9)
+# pragma warning (pop)
+#endif
+
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Select_Reactor_T.cpp b/ACE/ace/Select_Reactor_T.cpp
new file mode 100644
index 00000000000..0d94dffdba3
--- /dev/null
+++ b/ACE/ace/Select_Reactor_T.cpp
@@ -0,0 +1,1594 @@
+// $Id$
+
+#ifndef ACE_SELECT_REACTOR_T_CPP
+#define ACE_SELECT_REACTOR_T_CPP
+
+#include "ace/Select_Reactor_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/ACE.h"
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+#include "ace/Thread.h"
+#include "ace/Timer_Heap.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_NS_sys_stat.h"
+
+// For timer_queue_
+#include "ace/Recursive_Thread_Mutex.h"
+
+/*
+ * ACE Reactor specialization hook.
+ */
+//@@ REACTOR_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Select_Reactor_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Select_Reactor_T,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Select_Reactor_T)
+
+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)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::any_ready_i");
+
+ int number_ready = this->ready_set_.rd_mask_.num_set ()
+ + this->ready_set_.wr_mask_.num_set ()
+ + this->ready_set_.ex_mask_.num_set ();
+
+ // number_ready > 0 meaning there are handles in the ready_set
+ // &wait_set != &(this->ready_set_) means that we need to copy
+ // the handles from the ready_set to the wait set because the
+ // wait_set_ doesn't contain all the handles in the ready_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 = handler;
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> bool
+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_, false));
+ 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 const 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_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");
+
+ // 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.
+
+ ssize_t const 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> ACE_Event_Handler *
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::find_handler
+ (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::find_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, 0));
+ return this->find_handler_i (handle);
+}
+
+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_)
+ 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);
+
+ this->delete_signal_handler_ = true;
+ }
+
+ // Allows the timer queue to be overridden.
+ if (result != -1 && this->timer_queue_ == 0)
+ {
+ ACE_NEW_RETURN (this->timer_queue_,
+ ACE_Timer_Heap,
+ -1);
+
+ this->delete_timer_queue_ = true;
+ }
+
+ // 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);
+
+ this->delete_notify_handler_ = true;
+ }
+
+ if (result != -1 && this->handler_rep_.open (size) == -1)
+ result = -1;
+ else if (this->notify_handler_->open (this,
+ 0,
+ disable_notify_pipe) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("notification pipe open failed")));
+ result = -1;
+ }
+
+ if (result != -1)
+ // We're all set to go.
+ this->initialized_ = true;
+ 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->delete_signal_handler_)
+ delete this->signal_handler_;
+ this->signal_handler_ = signal_handler;
+ this->delete_signal_handler_ = false;
+ 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->delete_timer_queue_)
+ delete this->timer_queue_;
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = false;
+ return 0;
+}
+
+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,
+ int s_queue)
+ : ACE_Select_Reactor_Impl (mask_signals)
+ , token_ (s_queue)
+ , lock_adapter_ (token_)
+ , deactivated_ (0)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::ACE_Select_Reactor_T");
+
+ this->token_.reactor (*this);
+ // 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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Select_Reactor_T::open ")
+ ACE_TEXT ("failed inside ")
+ ACE_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,
+ int s_queue)
+ : ACE_Select_Reactor_Impl (mask_signals)
+ , token_ (s_queue)
+ , lock_adapter_ (token_)
+ , deactivated_ (0)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::ACE_Select_Reactor_T");
+
+ this->token_.reactor (*this);
+ if (this->open (size,
+ rs,
+ sh,
+ tq,
+ disable_notify_pipe,
+ notify) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Select_Reactor_T::open ")
+ ACE_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_ = false;
+ }
+
+ this->handler_rep_.close ();
+
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->timer_queue_ = 0;
+ this->delete_timer_queue_ = false;
+ }
+
+ 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_ = false;
+ }
+
+ this->initialized_ = false;
+
+ 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)
+ for (int s = 1; s < ACE_NSIG; ++s)
+ if ((sigset.is_member (s) == 1)
+ && this->signal_handler_->register_handler (s,
+ new_sh,
+ new_disp) == -1)
+ result = -1;
+#else /* ACE_NSIG <= 0 */
+ ACE_UNUSED_ARG (sigset);
+ ACE_UNUSED_ARG (new_sh);
+ ACE_UNUSED_ARG (new_disp);
+#endif /* ACE_NSIG <= 0 */
+ 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)
+ for (int s = 1; s < ACE_NSIG; ++s)
+ if ((sigset.is_member (s) == 1)
+ && this->signal_handler_->remove_handler (s) == -1)
+ result = -1;
+#else /* ACE_NSIG <= 0 */
+ ACE_UNUSED_ARG (sigset);
+#endif /* ACE_NSIG <= 0 */
+
+ return result;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> 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");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ if (this->timer_queue_ != 0)
+ return this->timer_queue_->cancel (handler, dont_call_handle_close);
+ else
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> 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");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ if (this->timer_queue_ != 0)
+ return this->timer_queue_->cancel (timer_id,
+ arg,
+ dont_call_handle_close);
+ else
+ return 0;
+}
+
+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));
+
+ if (0 != this->timer_queue_)
+ return this->timer_queue_->schedule
+ (handler,
+ arg,
+ timer_queue_->gettimeofday () + delay_time,
+ interval);
+
+ errno = ESHUTDOWN;
+ return -1;
+}
+
+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));
+
+ if (0 != this->timer_queue_)
+ return this->timer_queue_->reset_interval (timer_id, interval);
+
+ errno = ESHUTDOWN;
+ return -1;
+}
+
+// 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 defined (linux) && defined (ERESTARTNOHAND)
+ int const error = errno; // Avoid multiple TSS accesses.
+ if (error == EINTR || error == ERESTARTNOHAND)
+ return this->restart_;
+#else
+ if (errno == EINTR)
+ return this->restart_;
+#endif /* linux && ERESTARTNOHAND */
+#if defined (__MVS__) || defined (ACE_WIN32) || defined (ACE_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
+ else if (errno == EBADF)
+ return this->check_handles ();
+ 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;
+
+ bool const reference_counting_required =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ // Call add_reference() if needed.
+ if (reference_counting_required)
+ {
+ event_handler->add_reference ();
+ }
+
+ int status = (event_handler->*ptmf) (handle);
+
+ if (status < 0)
+ this->remove_handler_i (handle, mask);
+ else if (status > 0)
+ ready_mask.set_bit (handle);
+
+ // Call remove_reference() if needed.
+ if (reference_counting_required)
+ event_handler->remove_reference ();
+}
+
+// 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));
+
+ // If the handle is not suspended, then set the ops on the
+ // <wait_set_>, otherwise set the <suspend_set_>.
+
+ if (this->is_suspended_i (handle))
+ return this->bit_ops (handle, mask,
+ this->suspend_set_,
+ ops);
+ else
+ return this->bit_ops (handle, mask,
+ this->wait_set_,
+ ops);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> ACE_Event_Handler *
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::find_handler_i
+ (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::find_handler_i");
+
+ ACE_Event_Handler *event_handler =
+ this->handler_rep_.find (handle);
+
+ if (event_handler)
+ event_handler->add_reference ();
+
+ return event_handler;
+}
+
+// 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 **eh)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::handler_i");
+ ACE_Event_Handler *event_handler =
+ this->handler_rep_.find (handle);
+
+ if (event_handler == 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 (eh != 0)
+ {
+ *eh = event_handler;
+ event_handler->add_reference ();
+ }
+
+ 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);
+ }
+
+ // Kobi: we need to remove that handle from the
+ // dispatch set as well. We use that function with all the relevant
+ // masks - rd/wr/ex - all the mask. it is completely suspended
+ this->clear_dispatch_mask (handle, ACE_Event_Handler::RWE_MASK);
+ 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 &max_wait_time)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::work_pending");
+
+ ACE_Time_Value mwt (max_wait_time);
+ ACE_MT (ACE_Countdown_Time countdown (&mwt));
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN,
+ ace_mon,
+ this->token_,
+ -1));
+
+ if (this->deactivated_)
+ return 0;
+
+ // Update the countdown to reflect time waiting for the mutex.
+ ACE_MT (countdown.update ());
+
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value *this_timeout =
+ this->timer_queue_->calculate_timeout (&mwt, &timer_buf);
+
+ // Check if we have timers to fire.
+ bool const timers_pending =
+ (this_timeout != 0 && *this_timeout != mwt ? true : false);
+
+#ifdef ACE_WIN32
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles.
+ int const width = 0;
+#else
+ int const width = this->handler_rep_.max_handlep1 ();
+#endif /* ACE_WIN32 */
+
+ 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_;
+
+ int const nfds = ACE_OS::select (width,
+ fd_set.rd_mask_,
+ fd_set.wr_mask_,
+ fd_set.ex_mask_,
+ this_timeout);
+
+ // If timers are pending, override any timeout from the select()
+ // call.
+ return (nfds == 0 && timers_pending ? 1 : nfds);
+}
+
+// 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");
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value *this_timeout = 0;
+
+ 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_ == 0)
+ return 0;
+
+ this_timeout =
+ this->timer_queue_->calculate_timeout (max_wait_time,
+ &timer_buf);
+#ifdef ACE_WIN32
+ // This arg is ignored on Windows and causes pointer
+ // truncation warnings on 64-bit compiles.
+ int const width = 0;
+#else
+ int const width = this->handler_rep_.max_handlep1 ();
+#endif /* ACE_WIN32 */
+
+ 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 (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 */
+ }
+ else if (number_of_active_handles == -1)
+ {
+ // Normally, select() will reset the bits in dispatch_set
+ // so that only those filed descriptors that are ready will
+ // have bits set. However, when an error occurs, the bit
+ // set remains as it was when the select call was first made.
+ // Thus, we now have a dispatch_set that has every file
+ // descriptor that was originally waited for, which is not
+ // correct. We must clear all the bit sets because we
+ // have no idea if any of the file descriptors is ready.
+ //
+ // NOTE: We dont have a test case to reproduce this
+ // problem. But pleae dont ignore this and remove it off.
+ dispatch_set.rd_mask_.reset ();
+ dispatch_set.wr_mask_.reset ();
+ dispatch_set.ex_mask_.reset ();
+ }
+ }
+
+ // 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 ();
+
+ 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 const 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;
+ number_of_active_handles -= n;
+ }
+
+ // Same as dispatch_timer_handlers
+ // No need to do anything with the state changed. That is because
+ // unbind already handles the case where someone unregister some
+ // kind of handle and unbind it. (::unbind calls the function
+ // state_changed () to reflect ant change with that)
+ // return this->state_changed_ ? -1 : 0;
+ return 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_TRACE ("ACE_Select_Reactor_T::dispatch_io_set");
+ 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)
+ {
+ ++number_of_handlers_dispatched;
+
+ this->notify_handle (handle,
+ mask,
+ ready_mask,
+ this->handler_rep_.find (handle),
+ callback);
+
+ // clear the bit from that dispatch mask,
+ // so when we need to restart the iteration (rebuilding the iterator...)
+ // we will not dispatch the already dispatched handlers
+ this->clear_dispatch_mask (handle, mask);
+
+ if (this->state_changed_)
+ {
+
+ handle_iter.reset_state ();
+ this->state_changed_ = false;
+ }
+ }
+
+ 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)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::dispatch_io_handlers");
+
+ // 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).
+
+ 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_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_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
+ {
+ // We expect that the loop will decrease the number of active
+ // handles in each iteration. If it does not, then something is
+ // inconsistent in the state of the Reactor and we should avoid
+ // the loop. Please read the comments on bug 2540 for more
+ // details.
+ int initial_handle_count = active_handle_count;
+
+ // 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_ = false;
+
+ // 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;
+
+ // if state changed, we need to re-eval active_handle_count,
+ // so we will not end with an endless loop
+ if (initial_handle_count == active_handle_count
+ || this->state_changed_)
+ {
+ active_handle_count = this->any_ready (dispatch_set);
+ }
+ }
+ 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");
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ // 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);
+
+ 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
+ {
+ // We use the data member dispatch_set_ as the current dispatch
+ // set.
+
+ // We need to start from a clean dispatch_set
+ this->dispatch_set_.rd_mask_.reset ();
+ this->dispatch_set_.wr_mask_.reset ();
+ this->dispatch_set_.ex_mask_.reset ();
+
+ int number_of_active_handles =
+ this->wait_for_multiple_events (this->dispatch_set_,
+ max_wait_time);
+
+ result =
+ this->dispatch (number_of_active_handles,
+ this->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.
+ }
+
+ 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_VXWORKS)
+ ACE_Time_Value time_poll = ACE_Time_Value::zero;
+ ACE_Handle_Set rd_mask;
+#endif /* ACE_WIN32 || MVS || ACE_VXWORKS */
+
+ int result = 0;
+
+ /*
+ * It's easier to run through the handler repository iterator, but that
+ * misses handles that are registered on a handler that doesn't implement
+ * get_handle(). So, build a handle set that's the union of the three
+ * wait_sets (rd, wrt, ex) and run through that. Bad handles get cleared
+ * out of all sets.
+ */
+ ACE_HANDLE h;
+ ACE_Handle_Set check_set (this->wait_set_.rd_mask_);
+ ACE_Handle_Set_Iterator wr_iter (this->wait_set_.wr_mask_);
+ while ((h = wr_iter ()) != ACE_INVALID_HANDLE)
+ check_set.set_bit (h);
+ ACE_Handle_Set_Iterator ex_iter (this->wait_set_.ex_mask_);
+ while ((h = ex_iter ()) != ACE_INVALID_HANDLE)
+ check_set.set_bit (h);
+
+ ACE_Handle_Set_Iterator check_iter (check_set);
+ while ((h = check_iter ()) != ACE_INVALID_HANDLE)
+ {
+
+#if defined (ACE_WIN32) || defined (__MVS__) || defined (ACE_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 (h);
+
+ int select_width;
+# if defined (ACE_WIN32)
+ // This arg is ignored on Windows and causes pointer truncation
+ // warnings on 64-bit compiles.
+ select_width = 0;
+# else
+ select_width = int (h) + 1;
+# endif /* ACE_WIN32 */
+
+ if (ACE_OS::select (select_width,
+ rd_mask, 0, 0,
+ &time_poll) < 0)
+ {
+ result = 1;
+ this->remove_handler_i (h, ACE_Event_Handler::ALL_EVENTS_MASK);
+ }
+ rd_mask.clr_bit (h);
+#else /* !ACE_WIN32 && !MVS && !VXWORKS */
+ struct stat temp;
+
+ if (ACE_OS::fstat (h, &temp) == -1)
+ {
+ result = 1;
+ this->remove_handler_i (h, ACE_Event_Handler::ALL_EVENTS_MASK);
+ }
+#endif /* ACE_WIN32 || MVS */
+ }
+
+ return result;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> void
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ 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_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;)
+ ACE_DEBUG ((LM_DEBUG, ACE_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;)
+ ACE_DEBUG ((LM_DEBUG, ACE_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;)
+ ACE_DEBUG ((LM_DEBUG, ACE_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;)
+ ACE_DEBUG ((LM_DEBUG, ACE_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;)
+ ACE_DEBUG ((LM_DEBUG, ACE_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;)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("except_handle_ready = %d\n"), h));
+
+ for (ACE_Handle_Set_Iterator handle_iter_su_ready (this->suspend_set_.wr_mask_);
+ (h = handle_iter_su_ready ()) != ACE_INVALID_HANDLE;)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("write_handle_suspend = %d\n"), h));
+
+ for (ACE_Handle_Set_Iterator handle_iter_su_ready (this->suspend_set_.rd_mask_);
+ (h = handle_iter_su_ready ()) != ACE_INVALID_HANDLE;)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("read_handle_suspend = %d\n"), h));
+
+ for (ACE_Handle_Set_Iterator handle_iter_su_ready (this->suspend_set_.ex_mask_);
+ (h = handle_iter_su_ready ()) != ACE_INVALID_HANDLE;)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("except_handle_suspend = %d\n"), h));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("restart_ = %d\n"), this->restart_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("requeue_position_ = %d\n"), this->requeue_position_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("initialized_ = %d\n"), this->initialized_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("owner_ = %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_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_SELECT_REACTOR_T_CPP */
diff --git a/ACE/ace/Select_Reactor_T.h b/ACE/ace/Select_Reactor_T.h
new file mode 100644
index 00000000000..b5b2cec83b9
--- /dev/null
+++ b/ACE/ace/Select_Reactor_T.h
@@ -0,0 +1,718 @@
+// -*- 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 */
+
+#include "ace/Lock_Adapter_T.h"
+#include "ace/Token.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/*
+ * Hook for specializing the reactor with the concrete
+ * type, for example, select, or thread pool.
+ */
+//@@ REACTOR_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+typedef ACE_Token ACE_SELECT_TOKEN;
+#else
+typedef ACE_Noop_Token ACE_SELECT_TOKEN;
+#endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+
+/**
+ * @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_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 @a 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 @a mask_signals is
+ /// 1 the reactor is "signal-safe" when dispatching handlers to
+ /// signal events, whereas if @a 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 = ACE_DISABLE_NOTIFY_PIPE_DEFAULT,
+ ACE_Reactor_Notify *notify = 0,
+ int mask_signals = 1,
+ int s_queue = ACE_SELECT_TOKEN::FIFO);
+
+ /// 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 = ACE_DISABLE_NOTIFY_PIPE_DEFAULT,
+ ACE_Reactor_Notify *notify = 0,
+ int mask_signals = 1,
+ int s_queue = ACE_SELECT_TOKEN::FIFO);
+
+ /**
+ * 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 = ACE_DISABLE_NOTIFY_PIPE_DEFAULT,
+ 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);
+
+ /// Set a user-specified timer queue.
+ virtual int timer_queue (ACE_Timer_Queue *tq);
+
+ /// Return the current ACE_Timer_Queue.
+ 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 @a max_wait_time before
+ * returning. It will return earlier if timer events, I/O events,
+ * or signal events occur. Note that @a max_wait_time can be 0, in
+ * which case this method blocks indefinitely until events occur.
+ *
+ * @a 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,
+ * @a 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 @a 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
+ * @a 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 @a 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_Handlers.
+ /**
+ * Register a @a eh with a particular @a 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 @a eh with a particular @a mask. Note that since the
+ * @a 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 @a eh with all the @a handles in the <Handle_Set>.
+ virtual int register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register @a new_sh to handle the signal @a signum using the
+ * @a new_disp. Returns the @a old_sh that was previously registered
+ * (if any), along with the @a 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 @a new_sh to handle a set of signals @a sigset using the
+ /// @a new_disp.
+ virtual int register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0);
+
+ /**
+ * Removes the @a 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 @a 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 @a 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 @a 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 @a 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 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 @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a 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 @a 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 @a 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 @a 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 @a 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 @a mask.
+ virtual int schedule_wakeup (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /// ADD the dispatch MASK "bit" bound with the <handle> and the @a mask.
+ virtual int schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /// CLR the dispatch MASK "bit" bound with the <eh> and the @a mask.
+ virtual int cancel_wakeup (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /// CLR the dispatch MASK "bit" bound with the <handle> and the @a 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
+ * @a 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 @a timeout == 0, the caller will block until
+ * action is possible, else will wait until the relative time
+ * specified in *@a 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
+ /// @a 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 @a 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 @a 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 @a 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.
+
+ /**
+ * Return the Event_Handler associated with <handle>. Return 0 if
+ * <handle> is not registered.
+ */
+ virtual ACE_Event_Handler *find_handler (ACE_HANDLE handle);
+
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to @a mask. Return the @a eh associated with this @a handler
+ * if <eh> != 0.
+ */
+ virtual int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **eh = 0);
+
+ /**
+ * Check to see if @a 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 bool 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_Reactor_Token that is
+ * used to serialize the internal 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 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
+ /// @a 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
+ /// @a 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 ACE_Event_Handler *find_handler_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_Handlers for time
+ * events, I/O events, and signal events. Returns the total number
+ * of ACE_Event_Handlers 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 @a 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_;
+
+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> &) )
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Select_Reactor_T.inl"
+#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/ace/Select_Reactor_T.inl b/ACE/ace/Select_Reactor_T.inl
new file mode 100644
index 00000000000..ebbdfba1e5f
--- /dev/null
+++ b/ACE/ace/Select_Reactor_T.inl
@@ -0,0 +1,236 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Reactor.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 *,
+ ACE_HANDLE )
+{
+ // Don't have an implementation for this yet...
+ 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 ,
+ ACE_HANDLE ,
+ ACE_Event_Handler *,
+ ACE_Reactor_Mask )
+{
+ // Don't have an implementation for this yet...
+ 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.
+
+// 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)
+{
+ {
+ ACE_MT (ACE_GUARD (ACE_SELECT_REACTOR_TOKEN,
+ ace_mon,
+ this->token_));
+ 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 ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Semaphore.cpp b/ACE/ace/Semaphore.cpp
new file mode 100644
index 00000000000..06de81756ed
--- /dev/null
+++ b/ACE/ace/Semaphore.cpp
@@ -0,0 +1,62 @@
+// $Id$
+
+#include "ace/Semaphore.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Semaphore.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+
+ACE_RCSID (ace,
+ Semaphore,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Semaphore)
+
+void
+ACE_Semaphore::dump (void) const
+{
+// ACE_TRACE ("ACE_Semaphore::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_Semaphore::ACE_Semaphore (unsigned int count,
+ int type,
+ const ACE_TCHAR *name,
+ void *arg,
+ int max)
+ : removed_ (false)
+{
+// ACE_TRACE ("ACE_Semaphore::ACE_Semaphore");
+#if defined(ACE_LACKS_UNNAMED_SEMAPHORE)
+// if the user does not provide a name, we generate a unique name here
+ ACE_TCHAR iname[ACE_UNIQUE_NAME_LEN];
+ if (name == 0)
+ ACE::unique_name (this, iname, ACE_UNIQUE_NAME_LEN);
+ if (ACE_OS::sema_init (&this->semaphore_, count, type,
+ name ? name : iname,
+ arg, max) != 0)
+#else
+ if (ACE_OS::sema_init (&this->semaphore_, count, type,
+ name, arg, max) != 0)
+#endif
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Semaphore::ACE_Semaphore")));
+}
+
+ACE_Semaphore::~ACE_Semaphore (void)
+{
+// ACE_TRACE ("ACE_Semaphore::~ACE_Semaphore");
+
+ this->remove ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Semaphore.h b/ACE/ace/Semaphore.h
new file mode 100644
index 00000000000..1fb8c5fa2f3
--- /dev/null
+++ b/ACE/ace/Semaphore.h
@@ -0,0 +1,183 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Semaphore.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_SEMAPHORE_H
+#define ACE_SEMAPHORE_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Semaphore
+ *
+ * @brief Wrapper for Dijkstra style general semaphores.
+ */
+class ACE_Export ACE_Semaphore
+{
+public:
+ // = Initialization and termination.
+ /// Initialize the semaphore, with initial value of "count".
+ ACE_Semaphore (unsigned int count = 1, // By default make this unlocked.
+ int type = USYNC_THREAD,
+ const ACE_TCHAR *name = 0,
+ void * = 0,
+ int max = 0x7fffffff);
+
+ /// Implicitly destroy the semaphore.
+ ~ACE_Semaphore (void);
+
+ /**
+ * Explicitly destroy the semaphore. Note that only one thread
+ * should call this method since it doesn't protect against race
+ * conditions.
+ */
+ int remove (void);
+
+ /// Block the thread until the semaphore count becomes
+ /// greater than 0, then decrement it.
+ int acquire (void);
+
+ /**
+ * Block the thread until the semaphore count becomes greater than 0
+ * (at which point it is decremented) or until @a tv times out (in
+ * which case -1 is returned and @c errno == @c ETIME). Note that @a tv
+ * is assumed to be in "absolute" rather than "relative" time. The
+ * value of @a tv is updated upon return to show the actual
+ * (absolute) acquisition time.
+ *
+ * @note Solaris threads do not support timed semaphores.
+ * Therefore, if you're running on Solaris you might want to
+ * consider using the ACE POSIX pthreads implementation instead,
+ * which can be enabled by compiling ACE with
+ * -DACE_HAS_PTHREADS, rather than -DACE_HAS_STHREADS or
+ * -DACE_HAS_POSIX_SEM.
+ */
+ int acquire (ACE_Time_Value &tv);
+
+ /**
+ * If @a tv == 0 then call <acquire()> directly. Otherwise, Block
+ * the thread until the semaphore count becomes greater than 0
+ * (at which point it is decremented) or until @a tv times out (in
+ * which case -1 is returned and @c errno == @c ETIME). Note that
+ * <*tv> is assumed to be in "absolute" rather than "relative" time.
+ * The value of <*tv> is updated upon return to show the actual
+ * (absolute) acquisition time.
+ *
+ * @note Solaris threads do not support timed semaphores.
+ * Therefore, if you're running on Solaris you might want to
+ * consider using the ACE POSIX pthreads implementation instead,
+ * which can be enabled by compiling ACE with
+ * -DACE_HAS_PTHREADS, rather than -DACE_HAS_STHREADS or
+ * -DACE_HAS_POSIX_SEM. */
+ int acquire (ACE_Time_Value *tv);
+
+ /**
+ * Conditionally decrement the semaphore if count is greater than 0
+ * (i.e., won't block). Returns -1 on failure. If we "failed"
+ * because someone else already had the lock, @c errno is set to
+ * @c EBUSY.
+ */
+ int tryacquire (void);
+
+ /// Increment the semaphore by 1, potentially unblocking a waiting
+ /// thread.
+ int release (void);
+
+ /// Increment the semaphore by @a release_count, potentially
+ /// unblocking waiting threads.
+ int release (unsigned int release_count);
+
+ /**
+ * Acquire semaphore ownership. This calls <acquire> and is only
+ * here to make the ACE_Semaphore interface consistent with the
+ * other synchronization APIs.
+ */
+ int acquire_read (void);
+
+ /**
+ * Acquire semaphore ownership. This calls <acquire> and is only
+ * here to make the ACE_Semaphore interface consistent with the
+ * other synchronization APIs.
+ */
+ int acquire_write (void);
+
+ /**
+ * Conditionally acquire semaphore (i.e., won't block). This calls
+ * <tryacquire> and is only here to make the ACE_Semaphore
+ * interface consistent with the other synchronization APIs.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_read (void);
+
+ /**
+ * Conditionally acquire semaphore (i.e., won't block). This calls
+ * <tryacquire> and is only here to make the ACE_Semaphore
+ * interface consistent with the other synchronization APIs.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_write (void);
+
+ /**
+ * This is only here to make the ACE_Semaphore
+ * interface consistent with the other synchronization APIs.
+ * Assumes the caller has already acquired the semaphore using one of
+ * the above calls, and returns 0 (success) always.
+ */
+ int tryacquire_write_upgrade (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Return the underlying lock.
+ const ACE_sema_t &lock (void) const;
+
+protected:
+ ACE_sema_t semaphore_;
+
+ /// Keeps track of whether <remove> has been called yet to avoid
+ /// multiple <remove> calls, e.g., explicitly and implicitly in the
+ /// destructor. This flag isn't protected by a lock, so make sure
+ /// that you don't have multiple threads simultaneously calling
+ /// <remove> on the same object, which is a bad idea anyway...
+ bool removed_;
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Semaphore &);
+ ACE_Semaphore (const ACE_Semaphore &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Semaphore.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SEMAPHORE_H */
diff --git a/ACE/ace/Semaphore.inl b/ACE/ace/Semaphore.inl
new file mode 100644
index 00000000000..238117585ac
--- /dev/null
+++ b/ACE/ace/Semaphore.inl
@@ -0,0 +1,119 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE const ACE_sema_t &
+ACE_Semaphore::lock (void) const
+{
+// ACE_TRACE ("ACE_Semaphore::lock");
+ return this->semaphore_;
+}
+
+ACE_INLINE int
+ACE_Semaphore::remove (void)
+{
+// ACE_TRACE ("ACE_Semaphore::remove");
+ int result = 0;
+ if (!this->removed_)
+ {
+ this->removed_ = true;
+ result = ACE_OS::sema_destroy (&this->semaphore_);
+ }
+ return result;
+}
+
+ACE_INLINE int
+ACE_Semaphore::acquire (void)
+{
+// ACE_TRACE ("ACE_Semaphore::acquire");
+ return ACE_OS::sema_wait (&this->semaphore_);
+}
+
+ACE_INLINE int
+ACE_Semaphore::acquire (ACE_Time_Value &tv)
+{
+// ACE_TRACE ("ACE_Semaphore::acquire");
+ return ACE_OS::sema_wait (&this->semaphore_, tv);
+}
+
+ACE_INLINE int
+ACE_Semaphore::acquire (ACE_Time_Value *tv)
+{
+// ACE_TRACE ("ACE_Semaphore::acquire");
+ return ACE_OS::sema_wait (&this->semaphore_, tv);
+}
+
+ACE_INLINE int
+ACE_Semaphore::tryacquire (void)
+{
+// ACE_TRACE ("ACE_Semaphore::tryacquire");
+ return ACE_OS::sema_trywait (&this->semaphore_);
+}
+
+ACE_INLINE int
+ACE_Semaphore::release (void)
+{
+// ACE_TRACE ("ACE_Semaphore::release");
+ return ACE_OS::sema_post (&this->semaphore_);
+}
+
+ACE_INLINE int
+ACE_Semaphore::release (unsigned int release_count)
+{
+// ACE_TRACE ("ACE_Semaphore::release");
+ return ACE_OS::sema_post (&this->semaphore_, release_count);
+}
+
+// Acquire semaphore ownership. This calls <acquire> and is only
+// here to make the <ACE_Semaphore> interface consistent with the
+// other synchronization APIs.
+
+ACE_INLINE int
+ACE_Semaphore::acquire_read (void)
+{
+ return this->acquire ();
+}
+
+// Acquire semaphore ownership. This calls <acquire> and is only
+// here to make the <ACE_Semaphore> interface consistent with the
+// other synchronization APIs.
+
+ACE_INLINE int
+ACE_Semaphore::acquire_write (void)
+{
+ return this->acquire ();
+}
+
+// Conditionally acquire semaphore (i.e., won't block). This calls
+// <tryacquire> and is only here to make the <ACE_Semaphore>
+// interface consistent with the other synchronization APIs.
+
+ACE_INLINE int
+ACE_Semaphore::tryacquire_read (void)
+{
+ return this->tryacquire ();
+}
+
+// Conditionally acquire semaphore (i.e., won't block). This calls
+// <tryacquire> and is only here to make the <ACE_Semaphore>
+// interface consistent with the other synchronization APIs.
+
+ACE_INLINE int
+ACE_Semaphore::tryacquire_write (void)
+{
+ return this->tryacquire ();
+}
+
+// This is only here to make the <ACE_Semaphore> interface consistent
+// with the other synchronization APIs. Assumes the caller has
+// already acquired the semaphore using one of the above calls, and
+// returns 0 (success) always.
+ACE_INLINE int
+ACE_Semaphore::tryacquire_write_upgrade (void)
+{
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Config.cpp b/ACE/ace/Service_Config.cpp
new file mode 100644
index 00000000000..02fc863790c
--- /dev/null
+++ b/ACE/ace/Service_Config.cpp
@@ -0,0 +1,586 @@
+// $Id$
+
+#include "ace/Service_Config.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Service_Config.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Service_Types.h"
+#include "ace/Reactor.h"
+#include "ace/Singleton.h"
+#include "ace/Service_Repository.h"
+
+#ifndef ACE_LACKS_UNIX_SIGNALS
+# include "ace/Sig_Adapter.h"
+#endif /* !ACE_LACKS_UNIX_SIGNALS */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Get_Opt.h"
+#include "ace/ARGV.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID (ace,
+ Service_Config,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @c ACE_Service_Config is supposed to be a Singleton. This is the
+ * only Configuration Gestalt available for access from static
+ * initializers at proces start-up time. Using Unmanaged Singleton
+ * is safer because (a) the Object Manager may not yet be fully initialized
+ * in the context of a static initializer that uses SC, and (b) because we
+ * know that upon process exit the SC will still be automaticaly and explicitly
+ * closed by @c ACE_Object_Manager::fini().
+ */
+typedef ACE_Unmanaged_Singleton<ACE_Service_Config,
+ ACE_SYNCH_RECURSIVE_MUTEX> ACE_SERVICE_CONFIG_SINGLETON;
+
+
+///
+ACE_Service_Config_Guard::ACE_Service_Config_Guard (ACE_Service_Gestalt * psg)
+ : saved_ (ACE_Service_Config::instance ())
+{
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SCG:<ctor=%@>")
+ ACE_TEXT (" - config=%@ repo=%@ superceded by repo=%@\n"),
+ this,
+ this->saved_,
+ this->saved_->repo_,
+ psg->repo_));
+
+ // Modify the TSS if the repo has changed
+ if (saved_ != psg)
+ (void)ACE_Service_Config::current (psg);
+}
+
+ACE_Service_Config_Guard::~ACE_Service_Config_Guard (void)
+{
+ ACE_Service_Config::current (this->saved_);
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SCG:<dtor=%@>")
+ ACE_TEXT (" - new repo=%@\n"),
+ this,
+ this->saved_->repo_));
+}
+
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Service_Config)
+
+// Set the signal handler to point to the handle_signal() function.
+ACE_Sig_Adapter *ACE_Service_Config::signal_handler_ = 0;
+
+// Trigger a reconfiguration.
+sig_atomic_t ACE_Service_Config::reconfig_occurred_ = 0;
+
+// = Set by command-line options.
+
+/// Pathname of file to write process id.
+ACE_TCHAR *ACE_Service_Config::pid_file_name_ = 0;
+
+/// Shall we become a daemon process?
+bool ACE_Service_Config::be_a_daemon_ = false;
+
+// Number of the signal used to trigger reconfiguration.
+int ACE_Service_Config::signum_ = SIGHUP;
+
+
+void
+ACE_Service_Config::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Service_Config::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Service_Config::parse_args_i (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Service_Config::parse_args_i");
+
+ // Using PERMUTE_ARGS (default) in order to have all
+ // unrecognized options and their value arguments moved
+ // to the end of the argument vector. We'll pick them up
+ // after processing our options and pass them on to the
+ // base class for further parsing.
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_Get_Opt getopt (argc,
+ argv,
+ ACE_TEXT ("bs:p:"),
+ 1 , // Start at argv[1].
+ 0, // Do not report errors
+ ACE_Get_Opt::RETURN_IN_ORDER);
+ //FUZZ: enable check_for_lack_ACE_OS
+
+ // Keep a list of all unknown arguments, begin with the
+ // executable's name
+ ACE_ARGV superargv;
+ superargv.add (argv[0]);
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ for (int c; (c = getopt ()) != -1; )
+ //FUZZ: enable check_for_lack_ACE_OS
+ switch (c)
+ {
+ case 'p':
+ ACE_Service_Config::pid_file_name_ = getopt.opt_arg ();
+ break;
+ case 'b':
+ ACE_Service_Config::be_a_daemon_ = true;
+ break;
+ case 's':
+ {
+ // There's no point in dealing with this on NT since it
+ // doesn't really support signals very well...
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+ ACE_Service_Config::signum_ =
+ ACE_OS::atoi (getopt.opt_arg ());
+
+ if (ACE_Reactor::instance ()->register_handler
+ (ACE_Service_Config::signum_,
+ ACE_Service_Config::signal_handler_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("cannot obtain signal handler\n")),
+ -1);
+#endif /* ACE_LACKS_UNIX_SIGNALS */
+ break;
+ }
+ default:
+ superargv.add (argv[getopt.opt_ind () - 1], true);
+ }
+
+ // Collect any argumets that were left
+ for (int c = getopt.opt_ind (); c < argc; ++c)
+ superargv.add (argv[c-1], true);
+
+ return ACE_Service_Gestalt::parse_args_i (superargv.argc (),
+ superargv.argv ());
+
+} /* parse_args_i () */
+
+
+int
+ACE_Service_Config::open_i (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key,
+ bool ignore_static_svcs,
+ bool ignore_default_svc_conf_file,
+ bool ignore_debug_flag)
+{
+ int result = 0;
+ ACE_TRACE ("ACE_Service_Config::open_i");
+ ACE_Log_Msg *log_msg = ACE_LOG_MSG;
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SC::open_i - this=%@, opened=%d, ")
+ ACE_TEXT ("loadstatics=%d\n"),
+ this, this->is_opened_, this->no_static_svcs_));
+
+ // Guard against reentrant processing. For example,
+ // if the singleton gestalt (ubergestalt) was already open,
+ // do not open it again...
+ // The base class open_i increments this and we are
+ // forwarding to it, so we don't have to increment here.
+ if (this->is_opened_ != 0)
+ return ACE_Service_Gestalt::open_i (program_name,
+ logger_key,
+ ignore_static_svcs,
+ ignore_default_svc_conf_file,
+ ignore_debug_flag);
+
+ // Check for things we need to do on a per-process basis and which
+ // may not be safe, or wise to do an a per instance basis
+
+ // Override any defaults, if required
+ this->no_static_svcs_ = ignore_static_svcs;
+
+ // Become a daemon before doing anything else.
+ if (this->be_a_daemon_)
+ ACE::daemonize ();
+
+ // Write process id to file.
+ if (this->pid_file_name_ != 0)
+ {
+ FILE* pidf = ACE_OS::fopen (this->pid_file_name_,
+ ACE_TEXT("w"));
+
+ if (pidf != 0)
+ {
+ ACE_OS::fprintf (pidf,
+ "%ld\n",
+ static_cast<long> (ACE_OS::getpid()));
+ ACE_OS::fclose (pidf);
+ }
+ }
+
+ u_long flags = log_msg->flags ();
+
+ // Only use STDERR if the caller hasn't already set the flags.
+ if (flags == 0)
+ flags = (u_long) ACE_Log_Msg::STDERR;
+
+ const ACE_TCHAR *key = logger_key;
+
+ if (key == 0 || ACE_OS::strcmp (key, ACE_DEFAULT_LOGGER_KEY) == 0)
+ // Only use the static <logger_key_> if the caller doesn't
+ // override it in the parameter list or if the key supplied is
+ // equal to the default static logger key.
+ key = this->logger_key_;
+ else
+ ACE_SET_BITS (flags, ACE_Log_Msg::LOGGER);
+
+ if (log_msg->open (program_name,
+ flags,
+ key) == -1)
+ result = -1;
+ else
+ {
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_STARTUP,
+ ACE_TEXT ("starting up daemon %n\n")));
+
+ // Initialize the Service Repository (this will still work if
+ // user forgets to define an object of type ACE_Service_Config).
+ ACE_Service_Repository::instance (ACE_Service_Config::MAX_SERVICES);
+
+ // Initialize the ACE_Reactor (the ACE_Reactor should be the
+ // same size as the ACE_Service_Repository).
+ ACE_Reactor::instance ();
+
+ // There's no point in dealing with this on NT since it doesn't
+ // really support signals very well...
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+ // Only attempt to register a signal handler for positive
+ // signal numbers.
+ if (ACE_Service_Config::signum_ > 0)
+ {
+ ACE_Sig_Set ss;
+ ss.sig_add (ACE_Service_Config::signum_);
+ if ((ACE_Reactor::instance () != 0) &&
+ (ACE_Reactor::instance ()->register_handler
+ (ss, ACE_Service_Config::signal_handler_) == -1))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("can't register signal handler\n")));
+ }
+#endif /* ACE_LACKS_UNIX_SIGNALS */
+ }
+
+ if (result == -1)
+ return -1;
+
+ if (this->init_svc_conf_file_queue () == -1)
+ return -1;
+
+ // Check if the default file exists before attempting to queue it
+ // for processing
+ if (!ignore_default_svc_conf_file)
+ {
+ FILE *fp = ACE_OS::fopen (ACE_DEFAULT_SVC_CONF,
+ ACE_TEXT ("r"));
+ ignore_default_svc_conf_file = (fp == 0);
+ if (fp != 0)
+ ACE_OS::fclose (fp);
+ }
+
+ if (!ignore_default_svc_conf_file
+ && this->svc_conf_file_queue_->is_empty ())
+ {
+ // Load the default "svc.conf" entry here if there weren't
+ // overriding -f arguments in <parse_args>.
+ if (this->svc_conf_file_queue_->enqueue_tail
+ (ACE_TString (ACE_DEFAULT_SVC_CONF)) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("enqueuing ")
+ ACE_DEFAULT_SVC_CONF
+ ACE_TEXT(" file")),
+ -1);
+ }
+ }
+
+ return ACE_Service_Gestalt::open_i (program_name,
+ logger_key,
+ ignore_static_svcs,
+ ignore_default_svc_conf_file,
+ ignore_debug_flag);
+}
+
+// This method has changed to return the gestalt instead of the
+// container, underlying the service repository and defined
+// ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor*). This way
+// the existing source code can keep using
+// ACE_Service_Config::static_svcs(), however now it is not necessary
+// to expose the repository storage *and* it is much easier to debug
+// service registration problems.
+
+ACE_Service_Gestalt *
+ACE_Service_Config::static_svcs (void)
+{
+ return ACE_Service_Config::instance ();
+}
+
+/// Return the global configuration instance. Always returns the same
+/// instance
+ACE_Service_Config *
+ACE_Service_Config::global (void)
+{
+ return ACE_SERVICE_CONFIG_SINGLETON::instance ();
+}
+
+int
+ACE_Service_Config::insert (ACE_Static_Svc_Descriptor* stsd)
+{
+ return ACE_Service_Config::instance ()->insert (stsd);
+}
+
+
+// Totally remove <svc_name> from the daemon by removing it from the
+// ACE_Reactor, and unlinking it if necessary.
+int
+ACE_Service_Config::remove (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Config::remove");
+ return ACE_Service_Repository::instance ()->remove (svc_name);
+}
+
+// Suspend <svc_name>. Note that this will not unlink the service
+// from the daemon if it was dynamically linked, it will mark it as
+// being suspended in the Service Repository and call the <suspend>
+// member function on the appropriate <ACE_Service_Object>. A service
+// can be resumed later on by calling the <resume> method...
+
+int
+ACE_Service_Config::suspend (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Config::suspend");
+ return ACE_Service_Repository::instance ()->suspend (svc_name);
+}
+
+// Resume a SVC_NAME that was previously suspended or has not yet
+// been resumed (e.g., a static service).
+
+int
+ACE_Service_Config::resume (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Config::resume");
+ return ACE_Service_Repository::instance ()->resume (svc_name);
+}
+
+
+ACE_Service_Config::ACE_Service_Config (bool ignore_static_svcs,
+ size_t size,
+ int signum)
+ : ACE_Service_Gestalt (size, false, ignore_static_svcs)
+{
+ ACE_TRACE ("ACE_Service_Config::ACE_Service_Config");
+#if defined (ACE_HAS_TSS_EMULATION)
+ ACE_Object_Manager::init_tss ();
+#endif
+ this->tss_.ts_object (this);
+ ACE_Service_Config::signum_ = signum;
+}
+
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 0)
+ACE_Service_Type *
+ACE_Service_Config::create_service_type (const ACE_TCHAR *n,
+ ACE_Service_Type_Impl *o,
+ ACE_DLL &dll,
+ int active)
+{
+ ACE_Service_Type *sp = 0;
+ ACE_NEW_RETURN (sp,
+ ACE_Service_Type (n, o, dll, active),
+ 0);
+ return sp;
+}
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */
+
+ACE_Service_Type_Impl *
+ACE_Service_Config::create_service_type_impl (const ACE_TCHAR *name,
+ int type,
+ void *symbol,
+ u_int flags,
+ ACE_Service_Object_Exterminator gobbler)
+{
+ ACE_Service_Type_Impl *stp = 0;
+
+ // Note, the only place we need to put a case statement. This is
+ // also the place where we'd put the RTTI tests, if the compiler
+ // actually supported them!
+
+ switch (type)
+ {
+ case ACE_Service_Type::SERVICE_OBJECT:
+ ACE_NEW_RETURN (stp,
+ ACE_Service_Object_Type ((ACE_Service_Object *) symbol,
+ name, flags,
+ gobbler),
+ 0);
+ break;
+ case ACE_Service_Type::MODULE:
+ ACE_NEW_RETURN (stp,
+ ACE_Module_Type (symbol, name, flags),
+ 0);
+ break;
+ case ACE_Service_Type::STREAM:
+ ACE_NEW_RETURN (stp,
+ ACE_Stream_Type (symbol, name, flags),
+ 0);
+ break;
+ default:
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("unknown case\n")));
+ break;
+ }
+ return stp;
+
+}
+
+
+ACE_Service_Config::ACE_Service_Config (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key)
+ : ACE_Service_Gestalt (ACE_Service_Repository::DEFAULT_SIZE, false)
+{
+ ACE_TRACE ("ACE_Service_Config::ACE_Service_Config");
+#if defined (ACE_HAS_TSS_EMULATION)
+ ACE_Object_Manager::init_tss ();
+#endif
+ this->tss_.ts_object (this);
+ if (this->open (program_name,
+ logger_key) == -1 && errno != ENOENT)
+ {
+
+ // Only print out an error if it wasn't the svc.conf file that was
+ // missing.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) SC failed to open: %p\n"),
+ program_name));
+ }
+}
+
+// Signal handling API to trigger dynamic reconfiguration.
+
+void
+ACE_Service_Config::handle_signal (int sig,
+ siginfo_t *,
+ ucontext_t *)
+{
+#if defined (ACE_NDEBUG)
+ ACE_UNUSED_ARG (sig);
+#else /* ! ACE_NDEBUG */
+ ACE_ASSERT (ACE_Service_Config::signum_ == sig);
+#endif /* ! ACE_NDEBUG */
+
+ ACE_Service_Config::reconfig_occurred_ = 1;
+}
+
+// Trigger the reconfiguration process.
+
+void
+ACE_Service_Config::reconfigure (void)
+{
+ ACE_TRACE ("ACE_Service_Config::reconfigure");
+
+ ACE_Service_Config::reconfig_occurred_ = 0;
+
+ if (ACE::debug ())
+ {
+#if !defined (ACE_NLOGGING)
+ time_t t = ACE_OS::time (0);
+#endif /* ! ACE_NLOGGING */
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("beginning reconfiguration at %s"),
+ ACE_OS::ctime (&t)));
+ }
+ if (ACE_Service_Config::process_directives () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("process_directives")));
+}
+
+// Tidy up and perform last rites on a terminating ACE_Service_Config.
+int
+ACE_Service_Config::close (void)
+{
+ int const result1 = ACE_Service_Config::instance ()->close ();
+
+ // Delete the service repository. All the objects inside the
+ // service repository should already have been finalized.
+ int const result2 = ACE_Service_Config::close_svcs ();
+
+ // Do away with the Singleton
+ ACE_SERVICE_CONFIG_SINGLETON::close ();
+
+ return (result1 | result2);
+}
+
+int
+ACE_Service_Config::close_svcs (void)
+{
+ ACE_TRACE ("ACE_Service_Config::close_svcs");
+
+ ACE_Service_Repository::close_singleton ();
+ ACE_Service_Config::current (global ());
+ return 0;
+}
+
+int
+ACE_Service_Config::fini_svcs (void)
+{
+ ACE_TRACE ("ACE_Service_Config::fini_svcs");
+
+ // Clear the LM_DEBUG bit from log messages if appropriate
+ if (ACE::debug ())
+ ACE_Log_Msg::disable_debug_messages ();
+
+ int result = 0;
+ if (ACE_Service_Repository::instance () != 0)
+ result = ACE_Service_Repository::instance ()->fini ();
+
+ if (ACE::debug ())
+ ACE_Log_Msg::enable_debug_messages ();
+
+ return result;
+}
+
+// Perform user-specified close activities and remove dynamic memory.
+
+ACE_Service_Config::~ACE_Service_Config (void)
+{
+ ACE_TRACE ("ACE_Service_Config::~ACE_Service_Config");
+
+ // We do not want ~ACE_TSS<> to delete this again (single-thread
+ // builds)
+ this->tss_.ts_object (0);
+}
+
+// ************************************************************
+
+/* static */
+int
+ACE_Service_Config::reconfig_occurred (void)
+{
+ ACE_TRACE ("ACE_Service_Config::reconfig_occurred");
+ return ACE_Service_Config::reconfig_occurred_ != 0;
+}
+
+void
+ACE_Service_Config::reconfig_occurred (int config_occurred)
+{
+ ACE_TRACE ("ACE_Service_Config::reconfig_occurred");
+ ACE_Service_Config::reconfig_occurred_ = config_occurred;
+}
+
+// ************************************************************
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Config.h b/ACE/ace/Service_Config.h
new file mode 100644
index 00000000000..1c1c147af8f
--- /dev/null
+++ b/ACE/ace/Service_Config.h
@@ -0,0 +1,610 @@
+// -*- C++ -*-
+
+//====================================================================
+/**
+ * @file Service_Config.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//====================================================================
+
+#ifndef ACE_SERVICE_CONFIG_H
+#define ACE_SERVICE_CONFIG_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include "ace/Default_Constants.h"
+#include "ace/Service_Gestalt.h"
+#include "ace/TSS_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_signal.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl.
+class ACE_Service_Object;
+class ACE_Service_Type;
+class ACE_Service_Type_Impl;
+class ACE_Service_Repository;
+class ACE_Sig_Adapter;
+class ACE_Allocator;
+class ACE_Reactor;
+class ACE_Thread_Manager;
+class ACE_DLL;
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+#define ACE_STATIC_SERVICE_DIRECTIVE(ident, parameters) \
+ ACE_TEXT ("static ") \
+ ACE_TEXT (ident) \
+ ACE_TEXT (" \"") \
+ ACE_TEXT (parameters) \
+ ACE_TEXT ("\"")
+#define ACE_DYNAMIC_SERVICE_DIRECTIVE(ident, libpathname, objectclass, parameters) \
+ ACE_TEXT ("dynamic ") \
+ ACE_TEXT (ident) \
+ ACE_TEXT (" Service_Object * ") \
+ ACE_TEXT (libpathname) \
+ ACE_TEXT (":") \
+ ACE_TEXT (objectclass) \
+ ACE_TEXT ("() \"") \
+ ACE_TEXT (parameters) \
+ ACE_TEXT ("\"")
+#define ACE_REMOVE_SERVICE_DIRECTIVE(ident) \
+ ACE_TEXT ("remove ") \
+ ACE_TEXT (ident)
+class ACE_Svc_Conf_Param;
+#else
+#define ACE_STATIC_SERVICE_DIRECTIVE(ident, parameters) \
+ ACE_TEXT ("<ACE_Svc_Conf><static id=\"") \
+ ACE_TEXT (ident) \
+ ACE_TEXT ("\" params=\"") \
+ ACE_TEXT (parameters) \
+ ACE_TEXT ("\"/></ACE_Svc_Conf>")
+#define ACE_DYNAMIC_SERVICE_DIRECTIVE(ident, libpathname, objectclass, parameters) \
+ ACE_TEXT ("<ACE_Svc_Conf><dynamic id=\"") \
+ ACE_TEXT (ident) \
+ ACE_TEXT ("\" type=\"Service_Object\">") \
+ ACE_TEXT ("<initializer path=\"") \
+ ACE_TEXT (libpathname) \
+ ACE_TEXT ("\" init=\"") \
+ ACE_TEXT (objectclass) \
+ ACE_TEXT ("\"") \
+ ACE_TEXT (" params=\"") \
+ ACE_TEXT (parameters) \
+ ACE_TEXT ("\"/></dynamic></ACE_Svc_Conf>")
+#define ACE_REMOVE_SERVICE_DIRECTIVE(ident) \
+ ACE_TEXT ("<ACE_Svc_Conf><remove id=\"") \
+ ACE_TEXT (ident) \
+ ACE_TEXT ("\"></remove></ACE_Svc_Conf>")
+class ACE_XML_Svc_Conf;
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+extern "C"
+{
+ typedef ACE_Service_Object *(*ACE_SERVICE_ALLOCATOR) (ACE_Service_Object_Exterminator *);
+}
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Static_Svc_Descriptor
+ *
+ * @brief Holds the information necessary to describe a statically linked
+ * Svc.
+ */
+class ACE_Static_Svc_Descriptor
+{
+public:
+ /// Name of the service.
+ const ACE_TCHAR *name_;
+
+ /// Type of service.
+ int type_;
+
+ /// Factory function that allocates the service.
+ ACE_SERVICE_ALLOCATOR alloc_;
+
+ /// Bitmask flags indicating how the framework should delete memory.
+ u_int flags_;
+
+ /// Flag indicating whether the service starts out active.
+ int active_;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+public:
+ /// Compare two service descriptors for equality.
+ bool operator== (ACE_Static_Svc_Descriptor &) const;
+
+ /// Compare two service descriptors for inequality.
+ bool operator!= (ACE_Static_Svc_Descriptor &) const;
+};
+
+#define ACE_Component_Config ACE_Service_Config
+
+/**
+ * @class ACE_Service_Config
+ *
+ * @brief Supplies common server operations for dynamic and static
+ * configuration of service.
+ *
+ * The ACE_Service_Config uses the Monostate pattern. Therefore,
+ * you can only have one of these instantiated per-process. It
+ * represents the process-wide collection of services, which is
+ * typicaly shared among all other configurable entities. The only
+ * ACE_Service_Config instance is registered with and owned by the
+ * ACE_Object_Manager.
+ *
+ * By contrast, the ACE_Service_Gestalt represents the collection
+ * of services, pertaining to a configurable entity. Typicaly, a
+ * "configurable entity" is an instance, which owns an instance of
+ * ACE_Service_Gestalt in order to ensure full controll over the
+ * services it needs.
+ *
+ * Another facet of ACE_Service_Config is that for a given thread,
+ * it provides access to its current, process-global
+ * ACE_Service_Gestalt instance through its curent() method.
+ *
+ * @note The signal_handler_ static member is allocated by the
+ * ACE_Object_Manager. The ACE_Service_Config constructor
+ * uses signal_handler_. Therefore, if the program has any
+ * static ACE_Service_Config objects, there might be
+ * initialization order problems. They can be minimized, but
+ * not eliminated, by _not_ #defining
+ * ACE_HAS_NONSTATIC_OBJECT_MANAGER.
+ */
+class ACE_Export ACE_Service_Config: public ACE_Service_Gestalt
+{
+
+public:
+
+ // = Initialization and termination methods.
+
+ /**
+ * Initialize the Service Repository. Note that initialising @a
+ * signum to a negative number will prevent a signal handler being
+ * registered when the repository is opened.
+ */
+ ACE_Service_Config (bool ignore_static_svcs = true,
+ size_t size = ACE_Service_Gestalt::MAX_SERVICES,
+ int signum = SIGHUP);
+
+ /**
+ * Performs an open without parsing command-line arguments. The
+ * @a logger_key indicates where to write the logging output, which
+ * is typically either a STREAM pipe or a socket address.
+ */
+ ACE_Service_Config (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY);
+
+ /// Perform user-specified close activities and remove dynamic
+ /// memory.
+ virtual ~ACE_Service_Config (void);
+
+protected:
+
+ /**
+ * Performs an open without parsing command-line arguments.
+ * Implements whats different in the opening sequence
+ * for this class, as opposed to the base class.
+ *
+ * The @a logger_key indicates where to write the logging output, which
+ * is typically either a STREAM pipe or a socket address. If
+ * @a ignore_default_svc_conf_file is non-0 then the "svc.conf" file
+ * will be ignored. If @a ignore_debug_flag is non-0 then the
+ * application is responsible for setting the
+ * @c ACE_Log_Msg::priority_mask() appropriately. Returns number of
+ * errors that occurred on failure and 0 otherwise.
+ */
+ virtual int open_i (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key,
+ bool ignore_static_svcs,
+ bool ignore_default_svc_conf_file,
+ bool ignore_debug_flag);
+
+ /**
+ * Implements whats different in the command line parameter processing
+ * for this class, as opposed to the base class.
+ */
+ virtual int parse_args_i (int argc, ACE_TCHAR *argv[]);
+
+ /**
+ * A Wrapper for the TSS-stored pointer to the "current"
+ * configuration Gestalt. Static initializers from any DLL loaded
+ * through the SC will find the SC instance through the TSS pointer,
+ * instead of the global singleton. This makes it possible to ensure
+ * that the new services are loaded in the correct Gestalt,
+ * independent of which thread is actually using the SC at the time
+ * to do so.
+ */
+ ACE_TSS <ACE_Service_Gestalt> tss_;
+
+ /// = Static interfaces
+
+public:
+ /**
+ * Mutator to set the (TSS) global instance. Intended for use by
+ * helper classes like @see ACE_Service_Config_Guard. Stack-based
+ * instances of it can temporarily change which Gestalt is
+ * considered global by any static initializer (especially those in
+ * DLLs, loaded at run-time).
+ */
+ static ACE_Service_Gestalt* current (ACE_Service_Gestalt*);
+
+ /**
+ * Returns a process-wide global singleton instance in contrast with
+ * current (), which may return a different instance at different
+ * times, dependent on the context. Use of this method is
+ * discouraged as it allows circumvention of the mechanism for
+ * dynamically loading services. Use with extreme caution!
+ */
+ static ACE_Service_Config* global (void);
+
+ /// Accessor for the "current" service gestalt
+ static ACE_Service_Gestalt* current (void);
+
+ /**
+ * This is what the static service initializators are hard-wired to
+ * use, so in order to avoid interface changes this method merely
+ * forwards to @c ACE_Service_Config::current. This enables us to
+ * enforce which Service Gestalt is used for services registering
+ * through static initializers. Especially important for DLL-based
+ * dynamic services, which can contain their own static services and
+ * static initializers.
+ */
+ static ACE_Service_Gestalt* instance (void);
+
+ /**
+ * Performs an open without parsing command-line arguments. The
+ * @a logger_key indicates where to write the logging output, which
+ * is typically either a STREAM pipe or a socket address. If
+ * @a ignore_static_svcs is true then static services are not loaded,
+ * otherwise, they are loaded. If @a ignore_default_svc_conf_file is
+ * non-0 then the <svc.conf> configuration file will be ignored.
+ * Returns zero upon success, -1 if the file is not found or cannot
+ * be opened (errno is set accordingly), otherwise returns the
+ * number of errors encountered loading the services in the
+ * specified svc.conf configuration file. If @a ignore_debug_flag is
+ * non-0 then the application is responsible for setting the
+ * @c ACE_Log_Msg::priority_mask appropriately.
+ */
+ static int open (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
+ bool ignore_static_svcs = true,
+ bool ignore_default_svc_conf_file = false,
+ bool ignore_debug_flag = false);
+
+ /**
+ * This is the primary entry point into the ACE_Service_Config (the
+ * constructor just handles simple initializations). It parses
+ * arguments passed in from @a argc and @a argv parameters. The
+ * arguments that are valid in a call to this method include:
+ *
+ * - '-b' Option to indicate that we should be a daemon. Note that when
+ * this option is used, the process will be daemonized before the
+ * service configuration file(s) are read. During daemonization,
+ * (on POSIX systems) the current directory will be changed to "/"
+ * so the caller should either fully specify the file names, or
+ * execute a @c chroot() to the appropriate directory.
+ * @sa ACE::daemonize().
+ * - '-d' Turn on debugging mode
+ * - '-f' Specifies a configuration file name other than the default
+ * svc.conf. Can be specified multiple times to use multiple files.
+ * - '-k' Specifies the rendezvous point to use for the ACE distributed
+ * logger.
+ * - '-y' Explicitly enables the use of static services. This flag
+ * overrides the @a ignore_static_svcs parameter value.
+ * - '-n' Explicitly disables the use of static services. This flag
+ * overrides the @a ignore_static_svcs parameter value.
+ * - '-p' Specifies a pathname which is used to store the process id.
+ * - '-s' Specifies a signal number other than SIGHUP to trigger reprocessing
+ * of the configuration file(s). Ignored for platforms that do not
+ * have POSIX signals, such as Windows.
+ * - '-S' Specifies a service directive string. Enclose the string in quotes
+ * and escape any embedded quotes with a backslash. This option
+ * specifies service directives without the need for a configuration
+ * file.
+ *
+ * @param argc The number of commandline arguments.
+ * @param argv The array with commandline arguments
+ * @param logger_key Indicates where to write the logging output,
+ * which is typically either a STREAM pipe or a
+ * socket address.
+ * @param ignore_static_svcs If true then static services are not loaded,
+ * otherwise, they are loaded.
+ * @param ignore_default_svc_conf_file If non-0 then the @c svc.conf
+ * configuration file will be ignored.
+ * @param ignore_debug_flag If true then the application is responsible
+ * for setting the @c ACE_Log_Msg::priority_mask
+ * appropriately.
+ *
+ * @retval -1 The configuration file is not found or cannot
+ * be opened (errno is set accordingly).
+ * @retval 0 Success.
+ * @retval >0 The number of errors encountered while processing
+ * the service configuration file(s).
+ */
+ static int open (int argc,
+ ACE_TCHAR *argv[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
+ bool ignore_static_svcs = true,
+ bool ignore_default_svc_conf_file = false,
+ bool ignore_debug_flag = false);
+
+ /// Tidy up and perform last rites when ACE_Service_Config is shut
+ /// down. This method calls close_svcs(). Returns 0.
+ static int close (void);
+
+ /// Perform user-specified close hooks and possibly delete all of the
+ /// configured services in the <Service_Repository>.
+ static int fini_svcs (void);
+
+ /**
+ * Perform user-specified close hooks on all of the configured
+ * services in the Service_Repository, then delete the
+ * Service_Repository itself. Returns 0.
+ */
+ static int close_svcs (void);
+
+ /// True if reconfiguration occurred.
+ static int reconfig_occurred (void);
+
+ /// Indicate that reconfiguration occurred.
+ static void reconfig_occurred (int);
+
+ /// Perform the reconfiguration process.
+ static void reconfigure (void);
+
+ // = The following methods are static in order to enforce Singleton
+ // semantics for the Reactor, Service_Repository, Thread_Manager,
+ // and Acceptor/Connector Strategy factory. Other portions of the
+ // system may need to access them at some point or another...
+
+ // = This is not strictly needed, anymore since the service configurator
+ // has been refactored to allow multiple service configuration
+ // instances (called gestalts). The interfaces, however were retained in for
+ // the sake of maintaining source-code compatibility.
+
+
+ // = Accessors and mutators for process-wide Singletons.
+
+ /// Returns a pointer to the list of statically linked services.
+ ///
+ /// @deprecated - Same as instance(), but still useful in legacy code,
+ /// (notably, one that can not be easily modified) which uses the following
+ /// idiom for registering static services:
+ ///
+ /// ACE_Service_Config::static_svcs ()->insert (...);
+ static ACE_Service_Gestalt *static_svcs (void);
+
+ /// Insert a static service descriptor for processing on open_i(). The
+ /// corresponding ACE_STATIC_SVC_* macros were chaged to use this method
+ /// instead of obtaining a ptr to a container. See the note on static_svcs().
+ /// Added to prevent exposing the internal storage representation of the
+ /// services repository and provide a better way of debugging service
+ /// loading and registration problems.
+ static int insert (ACE_Static_Svc_Descriptor *svc);
+
+ // = Utility methods.
+ /// Dynamically link the shared object file and retrieve a pointer to
+ /// the designated shared object in this file.
+ static int initialize (const ACE_Service_Type *,
+ const ACE_TCHAR *parameters);
+
+ /// Initialize and activate a statically @a svc_name service.
+ static int initialize (const ACE_TCHAR *svc_name,
+ const ACE_TCHAR *parameters);
+
+ /// Resume a @a svc_name that was previously suspended or has not yet
+ /// been resumed (e.g., a static service).
+ static int resume (const ACE_TCHAR svc_name[]);
+
+ /**
+ * Suspend @a svc_name. Note that this will not unlink the service
+ * from the daemon if it was dynamically linked, it will mark it as
+ * being suspended in the Service Repository and call the <suspend>
+ * member function on the appropriate ACE_Service_Object. A
+ * service can be resumed later on by calling the <RESUME> member
+ * function...
+ */
+ static int suspend (const ACE_TCHAR svc_name[]);
+
+ /// Totally remove @a svc_name from the daemon by removing it
+ /// from the ACE_Reactor, and unlinking it if necessary.
+ static int remove (const ACE_TCHAR svc_name[]);
+
+#if defined (ACE_HAS_WINCE) && defined (ACE_USES_WCHAR)
+ // We must provide these function to bridge the Svc_Conf parser
+ // with ACE.
+ static int initialize (const ACE_Service_Type *, ACE_ANTI_TCHAR []);
+ static int initialize (const char svc_name[], ACE_ANTI_TCHAR parameters[]);
+ static int resume (const ACE_ANTI_TCHAR svc_name[]);
+ static int suspend (const ACE_ANTI_TCHAR svc_name[]);
+ static int remove (const ACE_ANTI_TCHAR svc_name[]);
+#endif /* ACE_HAS_WINCE */
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Set the signal_handler;for internal use by ACE_Object_Manager only.
+ static ACE_INLINE void signal_handler (ACE_Sig_Adapter *);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Process a file containing a list of service configuration
+ /// directives.
+ static int process_file (const ACE_TCHAR file[]);
+
+ /// Process one service configuration @a directive, which is passed as
+ /// a string. Returns the number of errors that occurred.
+ static int process_directive (const ACE_TCHAR directive[]);
+
+ /// Process one static service definition.
+ /**
+ * Load a new static service into the ACE_Service_Repository.
+ *
+ * @param ssd Service descriptor, see the document of
+ * ACE_Static_Svc_Descriptor for more details.
+ *
+ * @param force_replace If set the new service descriptor replaces
+ * any previous instance in the ACE_Service_Repository.
+ *
+ * @return Returns -1 if the service cannot be 'loaded'.
+ */
+ static int process_directive (const ACE_Static_Svc_Descriptor &ssd,
+ bool force_replace = false);
+
+ /**
+ * Process (or re-process) service configuration requests that are
+ * provided in the svc.conf file(s). Returns the number of errors
+ * that occurred.
+ */
+ static int process_directives (void);
+
+ /// Handles signals to trigger reconfigurations.
+ static void handle_signal (int sig, siginfo_t *, ucontext_t *);
+
+ /**
+ * Handle the command-line options intended for the
+ * ACE_Service_Config. Note that @c argv[0] is assumed to be the
+ * program name.
+ * The arguments that are valid in a call to this method are
+ * - '-b' Option to indicate that we should be a daemon
+ * - '-d' Turn on debugging mode
+ * - '-f' Option to read in the list of svc.conf file names
+ * - '-k' Option to read a wide string where in the logger output can
+ * be written
+ * - '-y' Turn on the flag for a repository of statically
+ * linked services
+ * - '-n' Need not have a repository of statically linked services
+ * - '-S' Option to read in the list of services on the command-line
+ * Please observe the difference between options '-f' that looks
+ * for a list of files and here a list of services.
+ */
+ static int parse_args (int, ACE_TCHAR *argv[]);
+#if (ACE_USES_CLASSIC_SVC_CONF == 0)
+ static ACE_Service_Type *create_service_type (const ACE_TCHAR *n,
+ ACE_Service_Type_Impl *o,
+ ACE_DLL &dll,
+ int active);
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */
+
+ static ACE_Service_Type_Impl *
+ create_service_type_impl (const ACE_TCHAR *name,
+ int type,
+ void *symbol,
+ u_int flags,
+ ACE_Service_Object_Exterminator gobbler);
+
+protected:
+
+ /// Process service configuration requests that were provided on the
+ /// command-line. Returns the number of errors that occurred.
+ static int process_commandline_directives (void);
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+ /// This is the implementation function that process_directives()
+ /// and process_directive() both call. Returns the number of errors
+ /// that occurred.
+ static int process_directives_i (ACE_Svc_Conf_Param *param);
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+ /// Become a daemon.
+ static int start_daemon (void);
+
+ /// Add the default statically-linked services to the
+ /// ACE_Service_Repository.
+ static int load_static_svcs (void);
+
+
+private:
+
+ /// True if reconfiguration occurred.
+ static sig_atomic_t reconfig_occurred_;
+
+ // = Set by command-line options.
+ /// Shall we become a daemon process?
+ static bool be_a_daemon_;
+
+ /// Pathname of file to write process id.
+ static ACE_TCHAR *pid_file_name_;
+
+ /// Number of the signal used to trigger reconfiguration.
+ static int signum_;
+
+ /// Handles the reconfiguration signals.
+ static ACE_Sig_Adapter *signal_handler_;
+
+ /// Pointer to the Singleton (ACE_Cleanup) Gestalt instance.
+ /// There is thread-specific global instance pointer, which is used to
+ /// temporarily change which Gestalt instance is used for static service
+ /// registrations.
+ ///
+ /// A specific use case is a thread, which loads a _dynamic_ service from
+ /// a DLL. If the said DLL also contains additional _static_ services,
+ /// those *must* be registered with the same configuration repository as
+ /// the dynamic service. Otherwise, the DLL's static services would be
+ /// registered with the global Gestalt and may outlive the DLL that
+ /// contains their code and perhaps the memory in which they are in.
+ /// This is a problem because if the DLL gets unloaded (as it will, if
+ /// it was loaded in an instance of Gestalt), the DLL's memory will be
+ /// deallocated, but the global service repository will still "think"
+ /// it must finalize the (DLL's) static services - with disastrous
+ /// consequences, occurring in the post-main code (at_exit()).
+
+ /// This class needs the intimate access to be able to swap the
+ /// current TSS pointer for the global Gestalt.
+ friend class ACE_Service_Config_Guard;
+};
+
+/**
+ * @class ACE_Service_Config_Guard
+ *
+ * @brief A guard class, designed to be instantiated on the stack.
+ *
+ * Instantiating it with a specific configuration ensures any references to
+ * ACE_Service_Config::instance(), even when occuring in static constructors,
+ * will allways access the designated configuration instance.
+ * This comes very handy when a dynamic service also registers any static
+ * services of its own and their static factories.
+ */
+class ACE_Export ACE_Service_Config_Guard
+{
+public:
+ ACE_Service_Config_Guard (ACE_Service_Gestalt * psg);
+ ~ACE_Service_Config_Guard (void);
+
+private:
+ // Private AND not implemented to disable copying
+ ACE_Service_Config_Guard(const ACE_Service_Config_Guard&);
+ ACE_Service_Config_Guard& operator= (const ACE_Service_Config_Guard&);
+
+private:
+ ACE_Service_Gestalt* saved_;
+};
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Service_Config.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SERVICE_CONFIG_H */
diff --git a/ACE/ace/Service_Config.inl b/ACE/ace/Service_Config.inl
new file mode 100644
index 00000000000..1cc6e35fe1d
--- /dev/null
+++ b/ACE/ace/Service_Config.inl
@@ -0,0 +1,190 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This is the primary entry point into the ACE_Service_Config (the
+// constructor just handles simple initializations).
+
+ACE_INLINE int
+ACE_Service_Config::open (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key,
+ bool ignore_static_svcs,
+ bool ignore_default_svc_conf,
+ bool ignore_debug_flag)
+{
+ ACE_TRACE ("ACE_Service_Config::open");
+ return ACE_Service_Config::current()->open (program_name,
+ logger_key,
+ ignore_static_svcs,
+ ignore_default_svc_conf,
+ ignore_debug_flag);
+}
+
+
+ACE_INLINE int
+ACE_Service_Config::open (int argc,
+ ACE_TCHAR *argv[],
+ const ACE_TCHAR *logger_key,
+ bool ignore_static_svcs,
+ bool ignore_default_svc_conf,
+ bool ignore_debug_flag)
+{
+ ACE_TRACE ("ACE_Service_Config::open");
+ return ACE_Service_Config::current()->open (argc,
+ argv,
+ logger_key,
+ ignore_static_svcs,
+ ignore_default_svc_conf,
+ ignore_debug_flag);
+}
+
+// Handle the command-line options intended for the
+// ACE_Service_Config.
+
+ACE_INLINE int
+ACE_Service_Config::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ return ACE_Service_Config::current ()->parse_args (argc, argv);
+}
+
+/// Return the configuration instance, considered "global" in the
+/// current thread. This may be the same as instance(), but on some
+/// occasions, it may be a different one. For example,
+/// ACE_Service_Config_Guard provides a way of temporarily replacing
+/// the "current" configuration instance in the context of a thread.
+ACE_INLINE ACE_Service_Gestalt *
+ACE_Service_Config::instance (void)
+{
+ return ACE_Service_Config::global ()->tss_;
+}
+
+/// Return the configuration instance, considered "global" in the
+/// current thread. This may be the same as instance(), but on some
+/// occasions, it may be a different one. For example,
+/// ACE_Service_Config_Guard provides a way of temporarily replacing
+/// the "current" configuration instance in the context of a thread.
+ACE_INLINE ACE_Service_Gestalt *
+ACE_Service_Config::current (void)
+{
+ return ACE_Service_Config::global ()->tss_;
+}
+
+/// A mutator to set the "current" (TSS) gestalt instance.
+ACE_INLINE ACE_Service_Gestalt*
+ACE_Service_Config::current (ACE_Service_Gestalt *newcurrent)
+{
+ return ACE_Service_Config::global ()->tss_.ts_object (newcurrent);
+}
+
+
+/// Compare two service descriptors for equality.
+ACE_INLINE bool
+ACE_Static_Svc_Descriptor::operator== (ACE_Static_Svc_Descriptor &d) const
+{
+ return ACE_OS::strcmp (name_, d.name_) == 0;
+}
+
+/// Compare two service descriptors for inequality.
+ACE_INLINE bool
+ACE_Static_Svc_Descriptor::operator!= (ACE_Static_Svc_Descriptor &d) const
+{
+ return !(*this == d);
+}
+
+ACE_INLINE void
+ACE_Service_Config::signal_handler (ACE_Sig_Adapter *signal_handler)
+{
+ signal_handler_ = signal_handler;
+}
+
+/// Initialize and activate a statically linked service.
+ACE_INLINE int
+ACE_Service_Config::initialize (const ACE_TCHAR *svc_name,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Config::initialize");
+ return ACE_Service_Config::current ()->initialize (svc_name,
+ parameters);
+}
+
+/// Dynamically link the shared object file and retrieve a pointer to
+/// the designated shared object in this file.
+ACE_INLINE int
+ACE_Service_Config::initialize (const ACE_Service_Type *sr,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Config::initialize");
+ return ACE_Service_Config::current ()->initialize (sr,
+ parameters);
+}
+
+/// Process a file containing a list of service configuration
+/// directives.
+ACE_INLINE int ACE_Service_Config::process_file (const ACE_TCHAR file[])
+{
+ return ACE_Service_Config::current ()->process_file (file);
+}
+
+///
+ACE_INLINE int
+ACE_Service_Config::process_directive (const ACE_TCHAR directive[])
+{
+ return ACE_Service_Config::current ()->process_directive (directive);
+}
+
+/// Process service configuration requests as indicated in the queue of
+/// svc.conf files.
+ACE_INLINE int
+ACE_Service_Config::process_directives (void)
+{
+ return ACE_Service_Config::current ()->process_directives ();
+}
+
+ACE_INLINE int
+ACE_Service_Config::process_directive (const ACE_Static_Svc_Descriptor &ssd,
+ bool force_replace)
+{
+ return ACE_Service_Config::current ()->process_directive (ssd, force_replace);
+}
+
+
+#if defined (ACE_HAS_WINCE) && defined (ACE_USES_WCHAR)
+// We must provide these function to bridge Svc_Conf parser with ACE.
+
+ACE_INLINE int
+ACE_Service_Config::initialize (const ACE_Service_Type *sp, ACE_ANTI_TCHAR parameters[])
+{
+ return ACE_Service_Config::initialize (sp, ACE_TEXT_ANTI_TO_TCHAR (parameters));
+}
+
+ACE_INLINE int
+ACE_Service_Config::initialize (const ACE_ANTI_TCHAR svc_name[], ACE_ANTI_TCHAR parameters[])
+{
+ return ACE_Service_Config::initialize (ACE_TEXT_ANTI_TO_TCHAR (svc_name),
+ ACE_TEXT_ANTI_TO_TCHAR (parameters));
+}
+
+ACE_INLINE int
+ACE_Service_Config::resume (const ACE_ANTI_TCHAR svc_name[])
+{
+ return ACE_Service_Config::resume (ACE_TEXT_ANTI_TO_TCHAR (svc_name));
+}
+
+ACE_INLINE int
+ACE_Service_Config::suspend (const ACE_ANTI_TCHAR svc_name[])
+{
+ return ACE_Service_Config::suspend (ACE_TEXT_ANTI_TO_TCHAR (svc_name));
+}
+
+ACE_INLINE int
+ACE_Service_Config::remove (const ACE_ANTI_TCHAR svc_name[])
+{
+ return ACE_Service_Config::remove (ACE_TEXT_ANTI_TO_TCHAR (svc_name));
+}
+#endif /* ACE_HAS_WINCE && !ACE_USES_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Gestalt.cpp b/ACE/ace/Service_Gestalt.cpp
new file mode 100644
index 00000000000..c644ec6ef72
--- /dev/null
+++ b/ACE/ace/Service_Gestalt.cpp
@@ -0,0 +1,1281 @@
+// $Id$
+
+#include "ace/Svc_Conf.h"
+#include "ace/Get_Opt.h"
+#include "ace/ARGV.h"
+#include "ace/Malloc.h"
+#include "ace/Service_Manager.h"
+#include "ace/Service_Types.h"
+#include "ace/Containers.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Reactor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/DLL.h"
+#include "ace/XML_Svc_Conf.h"
+#include "ace/SString.h"
+
+#ifndef ACE_LACKS_UNIX_SIGNALS
+# include "ace/Signal.h"
+#endif /* !ACE_LACKS_UNIX_SIGNALS */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_stat.h"
+
+#include "ace/TSS_T.h"
+#include "ace/Service_Gestalt.h"
+
+#include "ace/Svc_Conf_Param.h"
+
+ACE_RCSID (ace,
+ Service_Gestalt,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Service_Type_Dynamic_Guard::ACE_Service_Type_Dynamic_Guard
+ (ACE_Service_Repository &r, const ACE_TCHAR *name)
+ : repo_ (r)
+ , repo_begin_ (r.current_size ())
+ , name_ (name)
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ // On this thread (for the duration of the initialize() method),
+ // we're about to do two things that require locking: (1) fiddle
+ // with the repository and (2) load a DLL and hence lock the
+ // DLL_Manager.
+ //
+ // Now if we don't lock the repo here, it is possible that two
+ // threads may deadlock on initialization because they can acquire
+ // locks (1) and (2) in different order, for instance:
+ //
+ // T1: loads a DLL (2) and registers a service (1);
+ //
+ // T2: may be relocating a service (1), which could lead to a
+ // (re)opening or uping the ref count on a DLL (2);
+ //
+ // To prevent this, we lock the repo here, using the repo_monitor_
+ // member guard.
+ , repo_monitor_ (r.lock_)
+#endif
+{
+ ACE_ASSERT (this->name_ != 0); // No name?
+ ACE_NEW_NORETURN (this->dummy_, // Allocate the forward declaration ...
+ ACE_Service_Type (this->name_, // ... use the same name
+ 0, // ... inactive
+ ACE_DLL (), // ... bogus ACE_DLL
+ 0)); // ... no type_impl
+
+ ACE_ASSERT (this->dummy_ != 0); // No memory?
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) STDG::<ctor>, repo=%@ [%d], ")
+ ACE_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - inserting dummy forward\n"),
+ &this->repo_, this->repo_begin_, this->name_, this->dummy_,
+ this->dummy_->type (),
+ (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0,
+ this->dummy_->active ()));
+
+ // Note that the dummy_'s memory may be deallocated between invoking
+ // the ctor and dtor, if the expected ("real") dynamic service is
+ // inserted in the repository. See how this affects the destructor's
+ // behavior, below.
+ this->repo_.insert (this->dummy_);
+}
+
+
+/// Destructor
+
+ACE_Service_Type_Dynamic_Guard::~ACE_Service_Type_Dynamic_Guard (void)
+{
+ const ACE_Service_Type *tmp = 0;
+
+ // Lookup without ignoring suspended services. Making sure
+ // not to ignore any inactive services, since those may be forward
+ // declarations
+ size_t slot = 0;
+ int const ret = this->repo_.find_i (this->name_, slot, &tmp, false);
+
+ // We inserted it (as inactive), so we expect to find it, right?
+ if (ret < 0 && ret != -2)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_WARNING,
+ ACE_TEXT ("ACE (%P|%t) STDG::<dtor> - Failed (%d) to find %s\n"),
+ ret, this->name_));
+ return;
+ }
+
+ if (tmp != 0 && tmp->type () != 0)
+ {
+ // Something has registered a proper (non-forward-decl) service with
+ // the same name as our dummy.
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, name=%s - updating [%d - %d]\n"),
+ &this->repo_,
+ this->name_,
+ this->repo_begin_,
+ this->repo_.current_size ()));
+
+ // Relocate any static services. If any have been registered in
+ // the context of this guard, those really aren't static
+ // services because their code is in the DLL's code segment
+ this->repo_.relocate_i (this->repo_begin_, this->repo_.current_size (), tmp->dll());
+
+ // The ACE_Service_Gestalt::insert() modifies the memory for the
+ // original ACE_Service_Type instance. It deletes our dummy
+ // instance when replacing it with the actual implementation, so
+ // we are hereby simply giving up ownership.
+ this->dummy_ = 0;
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@ [%d], ")
+ ACE_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - loaded\n"),
+ &this->repo_, this->repo_begin_, this->name_, tmp, tmp->type (),
+ (tmp->type () != 0) ? tmp->type ()->object () : 0,
+ tmp->active ()));
+ }
+ else
+ {
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, ")
+ ACE_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - removing dummy forward\n"),
+ &this->repo_, this->name_, this->dummy_, this->dummy_->type (),
+ (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0,
+ this->dummy_->active ()));
+
+ // The (dummy) forward declaration is still there and is
+ // the same, which means that no actual declaration was
+ // provided inside the guarded scope. Therefore, the forward
+ // declaration is no longer necessary.
+ if (this->repo_.remove_i (this->name_,
+ const_cast< ACE_Service_Type**> (&this->dummy_)) == 0)
+ {
+ // If it is a dummy then deleting it while holding the repo lock is okay. There will be no
+ // call to service object's fini() and no possibility for deadlocks.
+ delete this->dummy_;
+ }
+ else
+ {
+ ACE_ERROR ((LM_WARNING,
+ ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, name=%s, ")
+ ACE_TEXT ("type=%@, impl=%@, object=%@, active=%d - dummy remove failed\n"),
+ &this->repo_, this->name_, this->dummy_, this->dummy_->type (),
+ (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0,
+ this->dummy_->active ()));
+ }
+ }
+
+ // Clean up
+ this->dummy_ = 0;
+}
+
+
+
+// ----------------------------------------
+
+ACE_Service_Gestalt::Processed_Static_Svc::
+Processed_Static_Svc (const ACE_Static_Svc_Descriptor *assd)
+ :name_(0),
+ assd_(assd)
+{
+ ACE_NEW_NORETURN (name_, ACE_TCHAR[ACE_OS::strlen(assd->name_)+1]);
+ ACE_OS::strcpy(name_,assd->name_);
+}
+
+ACE_Service_Gestalt::Processed_Static_Svc::~Processed_Static_Svc (void)
+{
+ delete [] name_;
+}
+
+// ----------------------------------------
+
+ACE_Service_Gestalt::~ACE_Service_Gestalt (void)
+{
+ if (this->svc_repo_is_owned_)
+ delete this->repo_;
+
+ this->repo_ =0;
+
+ delete this->static_svcs_;
+ this->static_svcs_ = 0;
+
+ // Delete the dynamically allocated static_svcs instance.
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::dtor - this=%@, pss = %@\n"),
+ this, this->processed_static_svcs_));
+#endif
+
+ if (this->processed_static_svcs_ &&
+ !this->processed_static_svcs_->is_empty())
+ {
+ Processed_Static_Svc **pss = 0;
+ for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
+ iter.next (pss) != 0;
+ iter.advance ())
+ {
+ delete *pss;
+ }
+ }
+ delete this->processed_static_svcs_;
+ this->processed_static_svcs_ = 0;
+}
+
+ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size,
+ bool svc_repo_is_owned,
+ bool no_static_svcs)
+ : svc_repo_is_owned_ (svc_repo_is_owned)
+ , svc_repo_size_ (size)
+ , is_opened_ (0)
+ , logger_key_ (ACE_DEFAULT_LOGGER_KEY)
+ , no_static_svcs_ (no_static_svcs)
+ , svc_queue_ (0)
+ , svc_conf_file_queue_ (0)
+ , repo_ (0)
+ , static_svcs_ (0)
+ , processed_static_svcs_ (0)
+{
+ (void)this->init_i ();
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::ctor - this = %@, pss = %@\n"),
+ this, this->processed_static_svcs_));
+#endif
+}
+
+/// Performs the common initialization tasks for a new or previously
+/// closed instance. Must not be virtual, as it is also called from
+/// the constructor.
+int
+ACE_Service_Gestalt::init_i (void)
+{
+ // Only initialize the repo_ if (a) we are being constructed, or;
+ // (b) we're being open()-ed, perhaps after previously having been
+ // close()-ed. In both cases: repo_ == 0 and we need a repository.
+ if (this->repo_ == 0)
+ {
+ if (this->svc_repo_is_owned_)
+ {
+ ACE_NEW_RETURN (this->repo_,
+ ACE_Service_Repository (this->svc_repo_size_),
+ -1);
+ }
+ else
+ {
+ this->repo_ =
+ ACE_Service_Repository::instance (this->svc_repo_size_);
+ }
+ }
+
+ return 0;
+}
+
+
+// Add the default statically-linked services to the Service
+// Repository.
+
+int
+ACE_Service_Gestalt::load_static_svcs (void)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::load_static_svcs");
+
+ if (this->static_svcs_ == 0)
+ return 0; // Nothing to do
+
+ ACE_Static_Svc_Descriptor **ssdp = 0;
+ for (ACE_STATIC_SVCS_ITERATOR iter (*this->static_svcs_);
+ iter.next (ssdp) != 0;
+ iter.advance ())
+ {
+ ACE_Static_Svc_Descriptor *ssd = *ssdp;
+
+ if (this->process_directive (*ssd, 1) == -1)
+ return -1;
+ }
+ return 0;
+
+} /* load_static_svcs () */
+
+
+
+/// Find a static service descriptor by name
+
+int
+ACE_Service_Gestalt::find_static_svc_descriptor (const ACE_TCHAR* name,
+ ACE_Static_Svc_Descriptor **ssd) const
+{
+ ACE_TRACE ("ACE_Service_Gestalt::find_static_svc_descriptor");
+
+ if (this->static_svcs_ == 0)
+ return -1;
+
+ ACE_Static_Svc_Descriptor **ssdp = 0;
+ for (ACE_STATIC_SVCS_ITERATOR iter ( *this->static_svcs_);
+ iter.next (ssdp) != 0;
+ iter.advance ())
+ {
+ if (ACE_OS::strcmp ((*ssdp)->name_, name) == 0)
+ {
+ if (ssd != 0)
+ *ssd = *ssdp;
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/// @brief
+
+const ACE_Static_Svc_Descriptor*
+ACE_Service_Gestalt::find_processed_static_svc (const ACE_TCHAR* name)
+{
+ if (this->processed_static_svcs_ == 0 || name == 0)
+ return 0;
+
+ Processed_Static_Svc **pss = 0;
+ for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
+ iter.next (pss) != 0;
+ iter.advance ())
+ {
+ if (ACE_OS::strcmp ((*pss)->name_, name) == 0)
+ return (*pss)->assd_;
+ }
+ return 0;
+}
+
+
+
+/// @brief Captures a list of the direcives processed (explicitely) for this
+/// Gestalt so that services can be replicated in other repositories
+/// upon their first initialization.
+///
+/// This is part of the mechanism ensuring distinct local instances
+/// for static service objects, loaded in another repository.
+
+void
+ACE_Service_Gestalt::add_processed_static_svc
+ (const ACE_Static_Svc_Descriptor *assd)
+{
+
+ /// When process_directive(Static_Svc_Descriptor&) is called, it
+ /// associates a service object with the Gestalt and makes the
+ /// resource (a Service Object) local to the repository. This is but
+ /// the first step in using such SO. The next is the
+ /// "initialization" step. It is typicaly done through a "static"
+ /// service configuration directive.
+ ///
+ /// In contrast a "dynamic" directive, when processed through the
+ /// overloaded process_directives(string) both creates the SO
+ /// locally and initializes it, where the statics directive must
+ /// first locate the SO and then calls the init() method. This means
+ /// that durig the "static" initialization there's no specific
+ /// information about the hosting repository and the gestalt must
+ /// employ some lookup strategy to find it elsewhere.
+
+ if (this->processed_static_svcs_ == 0)
+ ACE_NEW (this->processed_static_svcs_,
+ ACE_PROCESSED_STATIC_SVCS);
+
+ Processed_Static_Svc **pss = 0;
+ for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
+ iter.next (pss) != 0;
+ iter.advance ())
+ {
+ if (ACE_OS::strcmp ((*pss)->name_, assd->name_) == 0)
+ {
+ (*pss)->assd_ = assd;
+ return;
+ }
+ }
+ Processed_Static_Svc *tmp = 0;
+ ACE_NEW (tmp,Processed_Static_Svc(assd));
+ this->processed_static_svcs_->insert(tmp);
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::add_processed_static_svc, ")
+ ACE_TEXT ("repo=%@ - %s\n"),
+ this->repo_,
+ assd->name_));
+}
+
+
+/// Queues a static service object descriptor which, during open()
+/// will be given to process_directive() to create the Service
+/// Object. Normally, only called from static initializers, prior to
+/// calling open() but loading a service from a DLL can cause it too.
+
+int
+ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor *stsd)
+{
+ if (this->static_svcs_ == 0)
+ ACE_NEW_RETURN (this->static_svcs_,
+ ACE_STATIC_SVCS,
+ -1);
+
+ return this->static_svcs_->insert (stsd);
+}
+
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Service_Gestalt)
+
+
+void
+ACE_Service_Gestalt::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Service_Gestalt::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+
+
+///
+
+int
+ACE_Service_Gestalt::initialize (const ACE_TCHAR *svc_name,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Gestalt_Base::initialize (repo)");
+ ACE_ARGV args (parameters);
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::initialize - () repo=%@, ")
+ ACE_TEXT ("looking up static ")
+ ACE_TEXT ("service \'%s\' to initialize\n"),
+ this->repo_,
+ svc_name));
+ }
+#endif
+
+ const ACE_Service_Type *srp = 0;
+ for (int i = 0; this->find (svc_name, &srp) == -1 && i < 2; i++)
+ // if (this->repo_->find (svc_name, &srp) == -1)
+ {
+ const ACE_Static_Svc_Descriptor *assd =
+ ACE_Service_Config::global()->find_processed_static_svc(svc_name);
+ if (assd != 0)
+ {
+ this->process_directive_i(*assd, 0);
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - service \'%s\'")
+ ACE_TEXT (" was not located.\n"),
+ svc_name),
+ -1);
+ }
+ }
+ if (srp == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - service \'%s\'")
+ ACE_TEXT (" was not located.\n"),
+ svc_name),
+ -1);
+
+ /// If initialization fails ...
+ if (srp->type ()->init (args.argc (),
+ args.argv ()) == -1)
+ {
+ // ... report and remove this entry.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - static init of \'%s\'")
+ ACE_TEXT (" failed (%p)\n"),
+ svc_name, ACE_TEXT ("error")));
+ this->repo_->remove (svc_name);
+ return -1;
+ }
+
+ // If everything is ok, activate it
+ const_cast<ACE_Service_Type *>(srp)->active (1);
+ return 0;
+}
+
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+int
+ACE_Service_Gestalt::initialize (const ACE_Service_Type_Factory *stf,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::initialize");
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@, looking up dynamic ")
+ ACE_TEXT ("service \'%s\' to initialize\n"),
+ this->repo_,
+ stf->name ()));
+#endif
+
+ ACE_Service_Type *srp = 0;
+ int const retv = this->repo_->find (stf->name (),
+ (const ACE_Service_Type **) &srp);
+
+ // If there is an active service already, it must first be removed,
+ // before it could be re-installed.
+ // IJ: This used to be the behavior, before allowing multiple
+ // independent service repositories. Should that still be required?
+ if (retv >= 0)
+ {
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_ERROR_RETURN ((LM_WARNING,
+ ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@,")
+ ACE_TEXT (" %s is already initialized.")
+ ACE_TEXT (" Remove before re-initializing.\n"),
+ this->repo_,
+ stf->name ()),
+ 0);
+#endif
+ return 0;
+ }
+
+ // If there is an inactive service by that name it may have been
+ // either inactivated, or just a forward declaration for a service,
+ // that is in the process of being initialized. If it is the latter,
+ // then we have detected an attempt to initialize the same dynamic
+ // service while still processing previous attempt. This can lock up
+ // the process, because the ACE_DLL_Manager::open () is not
+ // re-entrant - it uses a Singleton lock to serialize concurent
+ // invocations. This use case must be handled here, because if the
+ // DLL_Manager was re-entrant we would have entered an infinite
+ // recursion here.
+ if (retv == -2 && srp->type () == 0)
+ ACE_ERROR_RETURN ((LM_WARNING,
+ ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@,")
+ ACE_TEXT (" %s is forward-declared.")
+ ACE_TEXT (" Recursive initialization requests are")
+ ACE_TEXT (" not supported.\n"),
+ this->repo_,
+ stf->name ()),
+ -1);
+
+ // Reserve a spot for the dynamic service by inserting an incomplete
+ // service declaration, i.e. one that can not produce a service
+ // object if asked (a forward declaration). This declaration
+ // ensures maintaining the proper partial ordering of the services
+ // with respect to their finalization. For example, dependent static
+ // services must be registered *after* the dynamic service that
+ // loads them, so that their finalization is complete *before*
+ // finalizing the dynamic service.
+ ACE_Service_Type_Dynamic_Guard dummy (*this->repo_,
+ stf->name ());
+
+ // make_service_type() is doing the dynamic loading and also runs
+ // any static initializers
+ ACE_Auto_Ptr<ACE_Service_Type> tmp (stf->make_service_type (this));
+
+ if (tmp.get () != 0 &&
+ this->initialize_i (tmp.get (), parameters) == 0)
+ {
+ // All good. Tthe ACE_Service_Type instance is now owned by the
+ // repository and we should make sure it is not destroyed upon
+ // exit from this method.
+ tmp.release ();
+ return 0;
+ }
+
+ return -1;
+}
+#endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
+
+
+// Dynamically link the shared object file and retrieve a pointer to
+// the designated shared object in this file.
+// @note This is obsolete (and error-prone) in the presense of dynamic
+// services with their own static services. This method will allow those
+// static services to register *before* the dynamic service that owns them.
+// Upon finalization of the static services the process may crash, because
+// the dynamic service's DLL may have been already released, together with
+// the memory in which the static services reside.
+// It may not crash, for instance, when the first static service to register
+// is the same as the dynamic service being loaded. You should be so lucky! ..
+
+int
+ACE_Service_Gestalt::initialize (const ACE_Service_Type *sr,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::initialize");
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::initialize - looking up dynamic ")
+ ACE_TEXT (" service %s to initialize, repo=%@\n"),
+ sr->name (), this->repo_));
+
+ ACE_Service_Type *srp = 0;
+ if (this->repo_->find (sr->name (),
+ (const ACE_Service_Type **) &srp) >= 0)
+ ACE_ERROR_RETURN ((LM_WARNING,
+ ACE_TEXT ("ACE (%P|%t) SG::initialize - \'%s\' ")
+ ACE_TEXT ("has already been installed. ")
+ ACE_TEXT ("Remove before reinstalling\n"),
+ sr->name ()),
+ 0);
+
+ return this->initialize_i (sr, parameters);
+
+}
+
+// Dynamically link the shared object file and retrieve a pointer to
+// the designated shared object in this file.
+int
+ACE_Service_Gestalt::initialize_i (const ACE_Service_Type *sr,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::initialize_i");
+ ACE_ARGV args (parameters);
+ if (sr->type ()->init (args.argc (),
+ args.argv ()) == -1)
+ {
+ // We just get ps to avoid having remove() delete it.
+ ACE_Service_Type *ps = 0;
+ this->repo_->remove (sr->name (), &ps);
+
+#ifndef ACE_NLOGGING
+ // Not using LM_ERROR here to avoid confusing the test harness
+ if (ACE::debug ())
+ ACE_ERROR_RETURN ((LM_WARNING,
+ ACE_TEXT ("ACE (%P|%t) SG::initialize_i ")
+ ACE_TEXT ("failed for %s: %m\n"),
+ sr->name ()),
+ -1);
+#endif
+ return -1;
+ }
+
+ if (this->repo_->insert (sr) == -1)
+ {
+#ifndef ACE_NLOGGING
+ // Not using LM_ERROR here to avoid confusing the test harness
+ if (ACE::debug ())
+ ACE_ERROR_RETURN ((LM_WARNING,
+ ACE_TEXT ("ACE (%P|%t) SG - repository insert ")
+ ACE_TEXT ("failed for %s: %m\n"),
+ sr->name ()),
+ -1);
+#endif
+ return -1;
+ }
+
+ return 0;
+}
+
+// Totally remove <svc_name> from the daemon by removing it from the
+// ACE_Reactor, and unlinking it if necessary.
+
+int
+ACE_Service_Gestalt::remove (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::remove");
+ if (this->repo_ == 0)
+ return -1;
+
+ return this->repo_->remove (svc_name);
+}
+
+// Suspend <svc_name>. Note that this will not unlink the service
+// from the daemon if it was dynamically linked, it will mark it as
+// being suspended in the Service Repository and call the <suspend>
+// member function on the appropriate <ACE_Service_Object>. A service
+// can be resumed later on by calling the <resume> method...
+
+int
+ACE_Service_Gestalt::suspend (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::suspend");
+ if (this->repo_ == 0)
+ return -1;
+
+ return this->repo_->suspend (svc_name);
+}
+
+// Resume a SVC_NAME that was previously suspended or has not yet
+// been resumed (e.g., a static service).
+
+int
+ACE_Service_Gestalt::resume (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::resume");
+ if (this->repo_ == 0)
+ return -1;
+
+ return this->repo_->resume (svc_name);
+}
+
+
+int
+ACE_Service_Gestalt::process_directive (const ACE_Static_Svc_Descriptor &ssd,
+ bool force_replace)
+{
+ int const result = process_directive_i (ssd, force_replace);
+ if (result == 0)
+ {
+ this->add_processed_static_svc(&ssd);
+ }
+ return result;
+}
+
+int
+ACE_Service_Gestalt::process_directive_i (const ACE_Static_Svc_Descriptor &ssd,
+ bool force_replace)
+{
+ if (this->repo_ == 0)
+ return -1;
+
+ if (!force_replace)
+ {
+ if (this->repo_->find (ssd.name_, 0, 0) >= 0)
+ {
+ // The service is already there, just return
+ return 0;
+ }
+ }
+
+
+ ACE_Service_Object_Exterminator gobbler;
+ void *sym = (ssd.alloc_)(&gobbler);
+
+ ACE_Service_Type_Impl *stp =
+ ACE_Service_Config::create_service_type_impl (ssd.name_,
+ ssd.type_,
+ sym,
+ ssd.flags_,
+ gobbler);
+ if (stp == 0)
+ return 0;
+
+ ACE_Service_Type *service_type = 0;
+
+ // This is just a temporary to force the compiler to use the right
+ // constructor in ACE_Service_Type. Note that, in cases where we are
+ // called from a static initializer which is part of a DLL, there is
+ // not enough information about the actuall DLL in this context.
+ ACE_DLL tmp_dll;
+
+ ACE_NEW_RETURN (service_type,
+ ACE_Service_Type (ssd.name_,
+ stp,
+ tmp_dll,
+ ssd.active_),
+ -1);
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::process_directive_i, ")
+ ACE_TEXT ("repo=%@ - %s, dll=%s, force=%d\n"),
+ this->repo_,
+ ssd.name_,
+ (tmp_dll.dll_name_ == 0) ? ACE_TEXT ("<null>") : tmp_dll.dll_name_,
+ force_replace));
+#endif
+
+ return this->repo_->insert (service_type);
+}
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+
+int
+ACE_Service_Gestalt::process_directives_i (ACE_Svc_Conf_Param *param)
+{
+ // AC 970827 Skip the heap check because yacc allocates a buffer
+ // here which will be reported as a memory leak for some reason.
+ ACE_NO_HEAP_CHECK
+
+ // Were we called in the context of the current instance?
+ ACE_ASSERT (this == param->config);
+
+ // Temporarily (for the duration of this call) make sure that *any* static
+ // service registrations will happen with this instance. Such registrations
+ // are possible as a side-effect of dynamically loading a DLL, which has
+ // other static services registered. Thus this instance will own both the
+ // DLL and those static services, which implies that their finalization
+ // will be performed in the correct order, i.e. prior to finalizing the DLL
+ ACE_Service_Config_Guard guard (this);
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::process_directives_i, ")
+ ACE_TEXT ("repo=%@ - %s\n"),
+ this->repo_,
+ (param->type == ACE_Svc_Conf_Param::SVC_CONF_FILE)
+ ? ACE_TEXT ("<from file>")
+ : param->source.directive));
+#endif
+
+ ::ace_yyparse (param);
+
+ // This is a hack, better errors should be provided...
+ if (param->yyerrno > 0)
+ {
+ // Always set the last error if ace_yyparse() fails.
+ // Other code may use errno to determine the type
+ // of problem that occurred from processing directives.
+ ACE_OS::last_error (EINVAL);
+ return param->yyerrno;
+ }
+ else
+ return 0;
+}
+
+#else
+
+ACE_XML_Svc_Conf *
+ACE_Service_Gestalt::get_xml_svc_conf (ACE_DLL &xmldll)
+{
+ if (xmldll.open (ACE_TEXT ("ACEXML_XML_Svc_Conf_Parser")) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) Failure to open ACEXML_XML_Svc_Conf_Parser: %p\n"),
+ "ACE_Service_Config::get_xml_svc_conf"),
+ 0);
+
+ void * foo =
+ xmldll.symbol (ACE_TEXT ("_ACEXML_create_XML_Svc_Conf_Object"));
+
+ ACE_XML_Svc_Conf::Factory factory =
+ reinterpret_cast<ACE_XML_Svc_Conf::Factory> (foo);
+ if (factory == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) Unable to resolve factory: %p\n"),
+ xmldll.error ()),
+ 0);
+
+ return factory ();
+}
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+int
+ACE_Service_Gestalt::process_file (const ACE_TCHAR file[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::process_file");
+
+ // To avoid recursive processing of the same file and the same repository
+ // we maintain an implicit stack of dummy "services" named after the file
+ // being processed. Anytime we have to open a new file, we then can check
+ // to see if it is not already being processed by searching for a dummy
+ // service with a matching name.
+ if (this->repo_->find (file, 0, 0) >=0)
+ {
+ ACE_DEBUG ((LM_WARNING,
+ ACE_TEXT ("ACE (%P|%t) Configuration file %s is currently")
+ ACE_TEXT (" being processed. Ignoring recursive process_file().\n"),
+ file));
+ return 0;
+ }
+
+ // Register a dummy service as a forward decl, using the file name as name.
+ // The entry will be automaticaly removed once the thread exits this block.
+ ACE_Service_Type_Dynamic_Guard recursion_guard (*this->repo_,
+ file);
+
+ /*
+ * @TODO: Test with ACE_USES_CLASSIC_SVC_CONF turned off!
+ */
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+ int result = 0;
+
+ FILE *fp = ACE_OS::fopen (file,
+ ACE_TEXT ("r"));
+
+ if (fp == 0)
+ {
+ // Invalid svc.conf file. We'll report it here and break out of
+ // the method.
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t): %p\n"),
+ file));
+
+ // Use stat to find out if the file exists. I didn't use access()
+ // because stat is better supported on most non-unix platforms.
+ ACE_stat exists;
+ if (ACE_OS::stat (file, &exists) == 0)
+ // If it exists, but we couldn't open it for reading then we
+ // must not have permission to read it.
+ errno = EPERM;
+ else
+ errno = ENOENT;
+ result = -1;
+ }
+ else
+ {
+ ACE_Svc_Conf_Param f (this, fp);
+
+ // Keep track of the number of errors.
+ result = this->process_directives_i (&f);
+
+ (void) ACE_OS::fclose (fp);
+ }
+ return result;
+#else
+ ACE_DLL dll;
+
+ auto_ptr<ACE_XML_Svc_Conf>
+ xml_svc_conf (this->get_xml_svc_conf (dll));
+
+ if (xml_svc_conf.get () == 0)
+ return -1;
+
+ return xml_svc_conf->parse_file (file);
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+}
+
+int
+ACE_Service_Gestalt::process_directive (const ACE_TCHAR directive[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::process_directive");
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::process_directive, repo=%@ - %s\n"),
+ this->repo_,
+ directive));
+#endif
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+ ACE_UNUSED_ARG (directive);
+
+ ACE_Svc_Conf_Param d (this, directive);
+
+ return this->process_directives_i (&d);
+#else
+ ACE_DLL dll;
+
+ auto_ptr<ACE_XML_Svc_Conf>
+ xml_svc_conf (this->get_xml_svc_conf (dll));
+
+ if (xml_svc_conf.get () == 0)
+ return -1;
+
+ // Temporarily (for the duration of this call) make sure that *any* static
+ // service registrations will happen with this instance. Such registrations
+ // are possible as a side-effect of dynamically loading a DLL, which has
+ // other static services registered. Thus this instance will own both the
+ // DLL and those static services, which implies that their finalization
+ // will be performed in the correct order, i.e. prior to finalizing the DLL
+ ACE_Service_Config_Guard guard (this);
+
+ return xml_svc_conf->parse_string (directive);
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+} /* process_directive () */
+
+
+int
+ACE_Service_Gestalt::init_svc_conf_file_queue (void)
+{
+ if (this->svc_conf_file_queue_ == 0)
+ {
+ ACE_SVC_QUEUE *tmp = 0;
+ ACE_NEW_RETURN (tmp,
+ ACE_SVC_QUEUE,
+ -1);
+ delete this->svc_conf_file_queue_;
+ this->svc_conf_file_queue_ = tmp;
+ }
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::init_svc_conf_file_queue ")
+ ACE_TEXT ("- this=%@, repo=%@\n"),
+ this, this->repo_));
+#endif
+
+ return 0;
+
+} /* init_svc_conf_file_queue () */
+
+
+int
+ACE_Service_Gestalt::open_i (const ACE_TCHAR /*program_name*/[],
+ const ACE_TCHAR* /*logger_key*/,
+ bool /*ignore_static_svcs*/,
+ bool /*ignore_default_svc_conf_file*/,
+ bool ignore_debug_flag)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::open_i");
+ int result = 0;
+ ACE_Log_Msg *log_msg = ACE_LOG_MSG;
+
+ // Record the current log setting upon entering this thread.
+ u_long old_process_mask = log_msg->priority_mask
+ (ACE_Log_Msg::PROCESS);
+
+ u_long old_thread_mask = log_msg->priority_mask
+ (ACE_Log_Msg::THREAD);
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::open_i - this=%@, ")
+ ACE_TEXT ("opened=%d, loadstatics=%d\n"),
+ this, this->is_opened_, this->no_static_svcs_));
+#endif
+
+ // Guard against reentrant processing. For example,
+ // if the singleton gestalt (ubergestalt) was already open,
+ // do not open it again...
+ if (this->is_opened_++ != 0)
+ return 0;
+
+ if (this->init_i () != 0)
+ return -1;
+
+ if (!ignore_debug_flag)
+ {
+ // If -d was included as a startup parameter, the user wants debug
+ // information printed during service initialization.
+ if (ACE::debug ())
+ ACE_Log_Msg::enable_debug_messages ();
+ else
+ // The user has requested no debugging info.
+ ACE_Log_Msg::disable_debug_messages ();
+ }
+
+ // See if we need to load the static services.
+ if (this->no_static_svcs_ == 0
+ && this->load_static_svcs () == -1)
+ result = -1;
+ else
+ {
+ if (this->process_commandline_directives () == -1)
+ result = -1;
+ else
+ result = this->process_directives ();
+ }
+
+
+ // Reset debugging back to the way it was when we came into
+ // into <open_i>.
+ {
+ // Make sure to save/restore errno properly.
+ ACE_Errno_Guard error (errno);
+
+ if (!ignore_debug_flag)
+ {
+ log_msg->priority_mask (old_process_mask, ACE_Log_Msg::PROCESS);
+ log_msg->priority_mask (old_thread_mask, ACE_Log_Msg::THREAD);
+ }
+ }
+
+ return result;
+} /* open_i () */
+
+
+int
+ACE_Service_Gestalt::is_opened (void)
+{
+ return this->is_opened_;
+}
+
+int
+ACE_Service_Gestalt::process_commandline_directives (void)
+{
+ int result = 0;
+ if (this->svc_queue_ != 0)
+ {
+ ACE_TString *sptr = 0;
+ for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_queue_);
+ iter.next (sptr) != 0;
+ iter.advance ())
+ {
+ // Process just a single directive.
+ if (this->process_directive ((sptr->fast_rep ())) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) %p\n"),
+ ACE_TEXT ("process_directive")));
+ result = -1;
+ }
+ }
+
+ delete this->svc_queue_;
+ this->svc_queue_ = 0;
+ }
+
+ return result;
+
+} /* process_commandline_directives () */
+
+
+int
+ACE_Service_Gestalt::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::parse_args");
+ return parse_args_i (argc, argv);
+}
+
+int
+ACE_Service_Gestalt::parse_args_i (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::parse_args_i");
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_Get_Opt getopt (argc,
+ argv,
+ ACE_TEXT ("df:k:nyS:"),
+ 1); // Start at argv[1].
+ //FUZZ: enable check_for_lack_ACE_OS
+
+ if (this->init_svc_conf_file_queue () == -1)
+ return -1;
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ for (int c; (argc != 0) && ((c = getopt ()) != -1); )
+ //FUZZ: enable check_for_lack_ACE_OS
+ switch (c)
+ {
+ case 'd':
+ ACE::debug (1);
+ break;
+ case 'f':
+ if (this->svc_conf_file_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("enqueue_tail")),
+ -1);
+ break;
+ case 'k':
+ /*
+ * @TODO: Is this always a static storage? Shouldn't we copy
+ * & gain ownership of the value?
+ */
+ this->logger_key_ = getopt.opt_arg ();
+ break;
+ case 'n':
+ this->no_static_svcs_ = 1;
+ break;
+ case 'y':
+ this->no_static_svcs_ = 0;
+ break;
+ case 'S':
+ if (this->svc_queue_ == 0)
+ {
+ ACE_NEW_RETURN (this->svc_queue_,
+ ACE_SVC_QUEUE,
+ -1);
+ }
+
+ if (this->svc_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("enqueue_tail")),
+ -1);
+ break;
+ default:
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) %c is not a ACE_Service_Config option\n"),
+ c));
+ }
+
+ return 0;
+} /* parse_args_i () */
+
+
+
+// Process service configuration requests as indicated in the queue of
+// svc.conf files.
+int
+ACE_Service_Gestalt::process_directives (void)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::process_directives");
+
+ int result = 0;
+
+ if (this->svc_conf_file_queue_ != 0)
+ {
+ ACE_TString *sptr = 0;
+
+ // Iterate through all the svc.conf files.
+ for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_conf_file_queue_);
+ iter.next (sptr) != 0;
+ iter.advance ())
+ {
+ int r = this->process_file (sptr->fast_rep ());
+
+ if (r < 0)
+ {
+ result = r;
+ break;
+ }
+
+ result += r;
+ }
+ }
+
+ return result;
+
+} /* process_directives () */
+
+// Tidy up and perform last rites on a terminating ACE_Service_Gestalt.
+int
+ACE_Service_Gestalt::close (void)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::close");
+
+ if (!this->is_opened_ || --this->is_opened_ != 0)
+ return 0;
+
+ // Delete the list fo svc.conf files
+ delete this->svc_conf_file_queue_;
+ this->svc_conf_file_queue_ = 0;
+
+ if (this->processed_static_svcs_ &&
+ !this->processed_static_svcs_->is_empty())
+ {
+ Processed_Static_Svc **pss = 0;
+ for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
+ iter.next (pss) != 0;
+ iter.advance ())
+ {
+ delete *pss;
+ }
+ }
+ delete this->processed_static_svcs_;
+ this->processed_static_svcs_ = 0;
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SG::close - complete this=%@, repo=%@, owned=%d\n"),
+ this, this->repo_, this->svc_repo_is_owned_));
+#endif
+
+ if (this->svc_repo_is_owned_)
+ delete this->repo_;
+
+ this->repo_ = 0;
+
+ return 0;
+} /* close () */
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Service_Gestalt.inl"
+#endif /* __ACE_INLINE__ */
+
+// Allocate a Service Manager.
+ACE_FACTORY_DEFINE (ACE, ACE_Service_Manager)
diff --git a/ACE/ace/Service_Gestalt.h b/ACE/ace/Service_Gestalt.h
new file mode 100644
index 00000000000..eee906f40c3
--- /dev/null
+++ b/ACE/ace/Service_Gestalt.h
@@ -0,0 +1,502 @@
+// -*- C++ -*-
+
+//====================================================================
+/**
+ * @file Service_Gestalt.h
+ *
+ * $Id$
+ *
+ * @author Iliyan Jeliazkov <iliyan@ociweb.com>
+ */
+//====================================================================
+
+#ifndef ACE_SERVICE_GESTALT_H
+#define ACE_SERVICE_GESTALT_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include "ace/Default_Constants.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Auto_Ptr.h"
+#include "ace/SString.h"
+#include "ace/Unbounded_Queue.h"
+#include "ace/Service_Repository.h"
+#include "ace/Singleton.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/Synch_Traits.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+class ACE_Service_Type_Factory;
+class ACE_Location_Node;
+#else
+class ACE_XML_Svc_Conf;
+class ACE_DLL;
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+class ACE_Static_Svc_Descriptor;
+class ACE_Svc_Conf_Param;
+class ACE_Service_Gestalt;
+
+/**
+ * @class ACE_Service_Gestalt
+ *
+ * @brief Supplies common server operations for dynamic and static
+ * configuration of services.
+ *
+ * The Gestalt embodies the concept of configuration context. On one
+ * hand, it is a flat namespace, where names correspond to a Service
+ * Object instance. A Gestalt owns the Service Repository instance,
+ * which in turn owns the Service Object instances.
+ *
+ * Another aspect of a Gestalt is its responsibility for
+ * record-keeping and accounting for the meta-data, necessary for
+ * locating, removing or instantiating a service.
+ *
+ * A repository underlies an instance of a gestalt and its lifetime
+ * may or may not be bounded by the lifetime of the gestalt, that owns
+ * it. This feature is important for the derived classes and the
+ * Service Config in particular.
+
+ */
+class ACE_Export ACE_Service_Gestalt
+{
+private:
+ /**
+ * Not implemented to enforce no copying
+ */
+ ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt(const ACE_Service_Gestalt&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt& operator=(const ACE_Service_Gestalt&))
+
+public:
+ enum
+ {
+ MAX_SERVICES = ACE_DEFAULT_SERVICE_REPOSITORY_SIZE
+ };
+
+ /// Constructor either associates the instance with the process-wide
+ /// singleton instance of ACE_Service_Repository, or creates and
+ /// manages its own instance of the specified size.
+ ACE_Service_Gestalt (size_t size = 1024,
+ bool svc_repo_is_owned = true,
+ bool no_static_svcs = true);
+
+ /// Perform user-specified close activities and remove dynamic
+ /// memory.
+ virtual ~ACE_Service_Gestalt (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /**
+ * Performs an open without parsing command-line arguments. The
+ * @a logger_key indicates where to write the logging output, which
+ * is typically either a STREAM pipe or a socket address. If
+ * @a ignore_static_svcs is true then static services are not loaded,
+ * otherwise, they are loaded. If @a ignore_default_svc_conf_file is
+ * true then the <svc.conf> configuration file will be ignored.
+ * Returns zero upon success, -1 if the file is not found or cannot
+ * be opened (errno is set accordingly), otherwise returns the
+ * number of errors encountered loading the services in the
+ * specified svc.conf configuration file. If @a ignore_debug_flag is
+ * true then the application is responsible for setting the
+ * <ACE_Log_Msg::priority_mask> appropriately.
+ */
+ int open (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
+ bool ignore_static_svcs = true,
+ bool ignore_default_svc_conf_file = false,
+ bool ignore_debug_flag = false);
+
+ /**
+ * This is the primary entry point into the ACE_Service_Config (the
+ * constructor just handles simple initializations). It parses
+ * arguments passed in from @a argc and @a argv parameters. The
+ * arguments that are valid in a call to this method include:
+ *
+ * - '-b' Option to indicate that we should be a daemon. Note that when
+ * this option is used, the process will be daemonized before the
+ * service configuration file(s) are read. During daemonization,
+ * (on POSIX systems) the current directory will be changed to "/"
+ * so the caller should either fully specify the file names, or
+ * execute a @c chroot() to the appropriate directory.
+ * @sa ACE::daemonize().
+ * - '-d' Turn on debugging mode
+ * - '-f' Specifies a configuration file name other than the default
+ * svc.conf. Can be specified multiple times to use multiple files.
+ * - '-k' Specifies the rendezvous point to use for the ACE distributed
+ * logger.
+ * - '-y' Explicitly enables the use of static services. This flag
+ * overrides the @a ignore_static_svcs parameter value.
+ * - '-n' Explicitly disables the use of static services. This flag
+ * overrides the @a ignore_static_svcs parameter value.
+ * - '-p' Specifies a pathname which is used to store the process id.
+ * - '-s' Specifies a signal number other than SIGHUP to trigger reprocessing
+ * of the configuration file(s). Ignored for platforms that do not
+ * have POSIX signals, such as Windows.
+ * - '-S' Specifies a service directive string. Enclose the string in quotes
+ * and escape any embedded quotes with a backslash. This option
+ * specifies service directives without the need for a configuration
+ * file.
+ *
+ * @param argc The number of commandline arguments.
+ * @param argv The array with commandline arguments
+ * @param logger_key Indicates where to write the logging output,
+ * which is typically either a STREAM pipe or a
+ * socket address.
+ * @param ignore_static_svcs If true then static services are not loaded,
+ * otherwise, they are loaded.
+ * @param ignore_default_svc_conf_file If false then the @c svc.conf
+ * configuration file will be ignored.
+ * @param ignore_debug_flag If false then the application is responsible
+ * for setting the @c ACE_Log_Msg::priority_mask
+ * appropriately.
+ *
+ * @retval -1 The configuration file is not found or cannot
+ * be opened (errno is set accordingly).
+ * @retval 0 Success.
+ * @retval >0 The number of errors encountered while processing
+ * the service configuration file(s).
+ */
+ int open (int argc,
+ ACE_TCHAR *argv[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
+ bool ignore_static_svcs = true,
+ bool ignore_default_svc_conf_file = false,
+ bool ignore_debug_flag = false);
+
+ /// Has it been opened? Returns the difference between the times
+ /// open and close have been called on this instance
+ int is_opened (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Process one service configuration @a directive, which is passed as
+ /// a string. Returns the number of errors that occurred.
+ int process_directive (const ACE_TCHAR directive[]);
+
+ /// Process one static service definition.
+ /**
+ * Load a new static service.
+ *
+ * @param ssd Service descriptor, see the document of
+ * ACE_Static_Svc_Descriptor for more details.
+ *
+ * @param force_replace If set the new service descriptor replaces
+ * any previous instance in the repository.
+ *
+ * @return Returns -1 if the service cannot be 'loaded'.
+ */
+ int process_directive (const ACE_Static_Svc_Descriptor &ssd,
+ bool force_replace = false);
+
+ /// Process a file containing a list of service configuration
+ /// directives.
+ int process_file (const ACE_TCHAR file[]);
+
+ /**
+ * Locate an entry with @a name in the table. If <ignore_suspended>
+ * is set then only consider services marked as resumed. If the
+ * caller wants the located entry, pass back a pointer to the
+ * located entry via <srp>. If @a name is not found, -1 is returned.
+ * If @a name is found, but it is suspended and the caller wants to
+ * ignore suspended services a -2 is returned.
+ */
+ int find (const ACE_TCHAR name[],
+ const ACE_Service_Type **srp = 0,
+ int ignore_suspended = 1) const;
+
+ /**
+ * Handle the command-line options intended for the
+ * <ACE_Service_Gestalt>. Note that <argv[0]> is assumed to be the
+ * program name.
+ *
+ * The arguments that are valid in a call to this method are
+ * - '-d' Turn on debugging mode
+ * - '-f' Option to read in the list of svc.conf file names
+ * - '-k' Option to read a wide string where in the logger output can
+ * be written
+ * - '-y' Turn on the flag for a repository of statically
+ * linked services
+ * - '-n' Need not have a repository of statically linked services
+ * - '-S' Option to read in the list of services on the command-line
+ * Please observe the difference between options '-f' that looks
+ * for a list of files and here a list of services.
+ */
+ int parse_args (int, ACE_TCHAR *argv[]);
+
+ /**
+ * Process (or re-process) service configuration requests that are
+ * provided in the svc.conf file(s). Returns the number of errors
+ * that occurred.
+ */
+ int process_directives (void);
+
+ /// Tidy up and perform last rites when ACE_Service_Config is shut
+ /// down. This method calls <close_svcs>. Returns 0.
+ int close (void);
+
+
+ // Registers a service descriptor for a static service object
+ int insert (ACE_Static_Svc_Descriptor *stsd);
+
+ // = Utility methods.
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+ /// Dynamically link the shared object file and retrieve a pointer to
+ /// the designated shared object in this file. Also account for the
+ /// possiblity to have static services registered when loading the DLL, by
+ /// ensuring that the dynamic sevice is registered before any of its
+ /// subordibnate static services. Thus avoiding any finalization order
+ /// problems.
+ int initialize (const ACE_Service_Type_Factory *,
+ const ACE_TCHAR *parameters);
+#endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
+
+ // Dynamically link the shared object file and retrieve a pointer to
+ // the designated shared object in this file.
+ // @obsolete
+ // @note This is error-prone in the presense of dynamic services,
+ // which in turn initialize their own static services. This method
+ // will allow those static services to register *before* the dynamic
+ // service that owns them. Upon finalization of the static services
+ // the process will typically crash, because the dynamic service's
+ // DLL may have been already released, together with the memory in
+ // which the static services reside. It may not crash, for
+ // instance, when the first static service to register is the same
+ // as the dynamic service being loaded. You should be so lucky!
+ int initialize (const ACE_Service_Type *,
+ const ACE_TCHAR *parameters);
+
+ /// Initialize and activate a statically @a svc_name service.
+ int initialize (const ACE_TCHAR *svc_name,
+ const ACE_TCHAR *parameters);
+
+ /// Resume a @a svc_name that was previously suspended or has not yet
+ /// been resumed (e.g., a static service).
+ int resume (const ACE_TCHAR svc_name[]);
+
+ /**
+ * Suspend @a svc_name. Note that this will not unlink the service
+ * from the daemon if it was dynamically linked, it will mark it as
+ * being suspended in the Service Repository and call the <suspend>
+ * member function on the appropriate <ACE_Service_Object>. A
+ * service can be resumed later on by calling the <RESUME> member
+ * function...
+ */
+ int suspend (const ACE_TCHAR svc_name[]);
+
+ /// Totally remove @a svc_name from the daemon by removing it
+ /// from the ACE_Reactor, and unlinking it if necessary.
+ int remove (const ACE_TCHAR svc_name[]);
+
+ /**
+ * Using the supplied name, finds and (if needed) returns a pointer to a
+ * static service descriptor. Returns 0 for success and -1 for failure
+ */
+ int find_static_svc_descriptor (const ACE_TCHAR* name,
+ ACE_Static_Svc_Descriptor **ssd = 0) const;
+
+ struct Processed_Static_Svc
+ {
+ Processed_Static_Svc (const ACE_Static_Svc_Descriptor *);
+ ~Processed_Static_Svc (void);
+ ACE_TCHAR * name_;
+ const ACE_Static_Svc_Descriptor *assd_;
+ };
+
+ /// Get the current ACE_Service_Repository held by this object.
+ ACE_Service_Repository* current_service_repository (void);
+
+protected:
+
+ /**
+ *
+ */
+ virtual int parse_args_i (int, ACE_TCHAR *argv[]);
+
+ /**
+ * Performs an open without parsing command-line arguments. The
+ * @a logger_key indicates where to write the logging output, which
+ * is typically either a STREAM pipe or a socket address. If
+ * @a ignore_default_svc_conf_file is non-0 then the "svc.conf" file
+ * will be ignored. If @a ignore_debug_flag is non-0 then the
+ * application is responsible for setting the
+ * @c ACE_Log_Msg::priority_mask() appropriately. Returns number of
+ * errors that occurred on failure and 0 otherwise.
+ */
+ virtual int open_i (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
+ bool ignore_static_svcs = true,
+ bool ignore_default_svc_conf_file = false,
+ bool ignore_debug_flag = false);
+
+ /// Initialize the <svc_conf_file_queue_> if necessary.
+ int init_svc_conf_file_queue (void);
+
+ /// Add the default statically-linked services to the
+ /// ACE_Service_Repository.
+ int load_static_svcs (void);
+
+ /// Process service configuration requests that were provided on the
+ /// command-line. Returns the number of errors that occurred.
+ int process_commandline_directives (void);
+
+ /// Process a static directive without also inserting its descriptor
+ /// the global table. This avoids multiple additions when processing
+ /// directives in non-global gestalts.
+ int process_directive_i (const ACE_Static_Svc_Descriptor &ssd,
+ bool force_replace = false);
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+ /// This is the implementation function that process_directives()
+ /// and process_directive() both call. Returns the number of errors
+ /// that occurred.
+ int process_directives_i (ACE_Svc_Conf_Param *param);
+#else
+ /// Helper function to dynamically link in the XML Service Configurator
+ /// parser.
+ ACE_XML_Svc_Conf* get_xml_svc_conf (ACE_DLL &d);
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+ // Dynamically link the shared object file and retrieve a pointer to
+ // the designated shared object in this file.
+ int initialize_i (const ACE_Service_Type *sr, const ACE_TCHAR *parameters);
+
+ const ACE_Static_Svc_Descriptor* find_processed_static_svc (const ACE_TCHAR*);
+ void add_processed_static_svc (const ACE_Static_Svc_Descriptor *);
+
+ /// Performs the common initialization tasks for a new or previously
+ /// closed instance. Must not be virtual, as it is called from the
+ /// constructor.
+ int init_i (void);
+
+
+protected:
+
+ // Maintain a queue of services to be configured from the
+ // command-line.
+ typedef ACE_Unbounded_Queue<ACE_TString> ACE_SVC_QUEUE;
+ typedef ACE_Unbounded_Queue_Iterator<ACE_TString> ACE_SVC_QUEUE_ITERATOR;
+
+ // Maintain a set of the statically linked service descriptors.
+ typedef ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *>
+ ACE_STATIC_SVCS;
+
+ typedef ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *>
+ ACE_STATIC_SVCS_ITERATOR;
+
+ typedef ACE_Unbounded_Set<Processed_Static_Svc *>
+ ACE_PROCESSED_STATIC_SVCS;
+
+ typedef ACE_Unbounded_Set_Iterator<Processed_Static_Svc *>
+ ACE_PROCESSED_STATIC_SVCS_ITERATOR;
+
+ friend class ACE_Dynamic_Service_Base;
+ friend class ACE_Service_Object;
+ friend class ACE_Service_Config_Guard;
+
+protected:
+
+ /// Do we own the service repository instance, or have only been
+ /// given a ptr to the singleton?
+ bool svc_repo_is_owned_;
+
+ /// Repository size is necessary, so that we can close (which may
+ /// destroy the repository instance), and then re-open again.
+ size_t svc_repo_size_;
+
+ /// Keep track of the number of times the instance has been
+ /// initialized (opened). "If so, we can't allow <yyparse> to be called since
+ /// it's not reentrant" is the original motivation, but that does not seem
+ /// to be the case anymore. This variable is incremented by the
+ /// <ACE_Service_Gestalt::open> method and decremented by the
+ /// <ACE_Service_Gestalt::close> method.
+ int is_opened_;
+
+ /// Indicates where to write the logging output. This is typically
+ /// either a STREAM pipe or a socket
+ const ACE_TCHAR *logger_key_;
+
+ /// Should we avoid loading the static services?
+ bool no_static_svcs_;
+
+ /// Queue of services specified on the command-line.
+ ACE_SVC_QUEUE* svc_queue_;
+
+ /** Queue of svc.conf files specified on the command-line.
+ * @@ This should probably be made to handle unicode filenames...
+ */
+ ACE_SVC_QUEUE* svc_conf_file_queue_;
+
+ /// The service repository to hold the services.
+ ACE_Service_Repository* repo_;
+
+ /// Repository of statically linked services.
+ ACE_STATIC_SVCS* static_svcs_;
+
+ /// Repository of statically linked services for which process
+ /// directive was called, but the service is not already a member of
+ /// the static_svcs_ list.
+ ACE_PROCESSED_STATIC_SVCS* processed_static_svcs_;
+
+}; /* class ACE_Service_Gestalt */
+
+
+/**
+ * @class ACE_Service_Type_Dynamic_Guard
+ *
+ * @brief A forward service declaration guard.
+ *
+ * Helps to resolve an issue with hybrid services, i.e. dynamic
+ * services, accompanied by static services in the same DLL. Only
+ * automatic instances of SDG are supposed to exist. Those are
+ * created during (dynamic) service initialization and serve to:
+ *
+ * (a) Ensure the service we are loading is ordered last in the
+ * repository, following any other services it may cause to register,
+ * as part of its own registration. This is a common case when
+ * loading dynamic services from DLLs - there are often static
+ * initializers, which register static services.
+ *
+ * (b) The SDG instance destructor detects if the dynamic service
+ * initialized successfully and "fixes-up" all the newly registered
+ * static services to hold a reference to the DLL, from which they
+ * have originated.
+ */
+class ACE_Export ACE_Service_Type_Dynamic_Guard
+{
+public:
+ ACE_Service_Type_Dynamic_Guard (ACE_Service_Repository &r,
+ ACE_TCHAR const *name);
+
+ ~ACE_Service_Type_Dynamic_Guard (void);
+
+private:
+ ACE_Service_Repository & repo_;
+ size_t repo_begin_;
+ ACE_TCHAR const * const name_;
+ ACE_Service_Type const * dummy_;
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_Guard< ACE_Recursive_Thread_Mutex > repo_monitor_;
+#endif
+};
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Service_Gestalt.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SERVICE_GESTALT_H */
diff --git a/ACE/ace/Service_Gestalt.inl b/ACE/ace/Service_Gestalt.inl
new file mode 100644
index 00000000000..2f1c88e7db3
--- /dev/null
+++ b/ACE/ace/Service_Gestalt.inl
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+
+// This is the primary entry point into the ACE_Service_Config (the
+// constructor just handles simple initializations).
+
+ACE_INLINE int
+ACE_Service_Gestalt::open (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key,
+ bool ignore_static_svcs,
+ bool ignore_default_svc_conf,
+ bool ignore_debug_flag)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::open");
+ this->no_static_svcs_ = ignore_static_svcs;
+
+ return this->open_i (program_name,
+ logger_key,
+ ignore_static_svcs,
+ ignore_default_svc_conf,
+ ignore_debug_flag);
+}
+
+ACE_INLINE int
+ACE_Service_Gestalt::open (int argc,
+ ACE_TCHAR *argv[],
+ const ACE_TCHAR *logger_key,
+ bool ignore_static_svcs,
+ bool ignore_default_svc_conf,
+ bool ignore_debug_flag)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::open");
+ this->no_static_svcs_ = ignore_static_svcs;
+
+ if (this->parse_args_i (argc,
+ argv) == -1)
+ return -1;
+ else
+ return this->open_i (argv == 0 ? 0 : argv[0],
+ logger_key,
+ ignore_static_svcs,
+ ignore_default_svc_conf,
+ ignore_debug_flag);
+}
+
+/// Searches for a service object declaration in the local repo, only
+
+ACE_INLINE int
+ACE_Service_Gestalt::find (const ACE_TCHAR name[],
+ const ACE_Service_Type **srp,
+ int ignore_suspended) const
+{
+ // Closing the gestalt will have disassociated it from the
+ // repository. If the repository used to be owned by the gestalt, it
+ // will also have been destroyed - so just check for repo_ before
+ // doing anything with it.
+ if (this->repo_ != 0)
+ return this->repo_->find (name, srp, ignore_suspended);
+
+ return 0;
+}
+
+ACE_INLINE ACE_Service_Repository*
+ACE_Service_Gestalt::current_service_repository (void)
+{
+ return this->repo_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Manager.cpp b/ACE/ace/Service_Manager.cpp
new file mode 100644
index 00000000000..979187be847
--- /dev/null
+++ b/ACE/ace/Service_Manager.cpp
@@ -0,0 +1,387 @@
+// $Id$
+
+#include "ace/Service_Manager.h"
+
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/Service_Repository.h"
+#include "ace/Service_Config.h"
+#include "ace/Service_Types.h"
+#include "ace/Reactor.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ Service_Manager,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Service_Manager)
+
+void
+ACE_Service_Manager::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Service_Manager::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+// Static variables.
+
+u_short ACE_Service_Manager::DEFAULT_PORT_ = 10000;
+
+ACE_Service_Manager::ACE_Service_Manager (void)
+ : debug_ (false),
+ signum_ (SIGHUP)
+{
+ ACE_TRACE ("ACE_Service_Manager::ACE_Service_Manager");
+}
+
+ACE_Service_Manager::~ACE_Service_Manager (void)
+{
+ ACE_TRACE ("ACE_Service_Manager::~ACE_Service_Manager");
+}
+
+int
+ACE_Service_Manager::suspend (void)
+{
+ ACE_TRACE ("ACE_Service_Manager::suspend");
+ return ACE_Reactor::instance ()->suspend_handler (this);
+}
+
+int
+ACE_Service_Manager::resume (void)
+{
+ ACE_TRACE ("ACE_Service_Manager::resume");
+ return ACE_Reactor::instance ()->resume_handler (this);
+}
+
+int
+ACE_Service_Manager::open (const ACE_INET_Addr &sia)
+{
+ ACE_TRACE ("ACE_Service_Manager::open");
+
+ // Reuse the listening address, even if it's already in use!
+ if (this->acceptor_.open (sia, 1) == -1)
+ return -1;
+ return 0;
+}
+
+int
+ACE_Service_Manager::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TRACE ("ACE_Service_Manager::info");
+ ACE_INET_Addr sa;
+ ACE_TCHAR buf[BUFSIZ];
+
+ if (this->acceptor_.get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("%d/%s %s"),
+ sa.get_port_number (),
+ ACE_TEXT ("tcp"),
+ ACE_TEXT ("# lists all services in the daemon\n"));
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return static_cast<int> (ACE_OS::strlen (buf));
+}
+
+int
+ACE_Service_Manager::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Service_Manager::init");
+ ACE_INET_Addr local_addr (ACE_Service_Manager::DEFAULT_PORT_);
+
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("dp:s:"), 0); // Start at argv[0]
+
+ for (int c; (c = getopt ()) != -1; )
+ //FUZZ: enable check_for_lack_ACE_OS
+ switch (c)
+ {
+ case 'd':
+ this->debug_ = true;
+ break;
+ case 'p':
+ local_addr.set ((u_short) ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ case 's':
+ this->signum_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ default:
+ break;
+ }
+
+ if (this->get_handle () == ACE_INVALID_HANDLE &&
+ this->open (local_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler
+ (this,
+ ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("registering service with ACE_Reactor\n")),
+ -1);
+ return 0;
+}
+
+int
+ACE_Service_Manager::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_Service_Manager::handle_close");
+ return this->acceptor_.close ();
+}
+
+int
+ACE_Service_Manager::fini (void)
+{
+ ACE_TRACE ("ACE_Service_Manager::fini");
+
+ int retv = 0;
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ {
+ retv = ACE_Reactor::instance ()->remove_handler
+ (this,
+ ACE_Event_Handler::ACCEPT_MASK |
+ ACE_Event_Handler::DONT_CALL);
+ this->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::NULL_MASK);
+ }
+ return retv;
+}
+
+ACE_HANDLE
+ACE_Service_Manager::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Service_Manager::get_handle");
+ return this->acceptor_.get_handle ();
+}
+
+int
+ACE_Service_Manager::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ return 0;
+}
+
+// Determine all the services offered by this daemon and return the
+// information back to the client.
+
+int
+ACE_Service_Manager::list_services (void)
+{
+ ACE_TRACE ("ACE_Service_Manager::list_services");
+ ACE_Service_Repository_Iterator sri (*ACE_Service_Repository::instance (), 0);
+
+ for (const ACE_Service_Type *sr;
+ sri.next (sr) != 0;
+ sri.advance ())
+ {
+ ssize_t len = static_cast<ssize_t> (ACE_OS::strlen (sr->name ())) + 11;
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_TCHAR *p = buf + len;
+
+ ACE_OS::strcpy (buf, sr->name ());
+ ACE_OS::strcat (buf, (sr->active ()) ?
+ ACE_TEXT (" (active) ") :
+ ACE_TEXT (" (paused) "));
+
+ p[-1] = ' ';
+ p[0] = '\0';
+
+ len += sr->type ()->info (&p, sizeof buf - len);
+
+ if (this->debug_)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("len = %d, info = %s%s"),
+ len,
+ buf,
+ buf[len - 1] == '\n' ? ACE_TEXT ("") : ACE_TEXT ("\n")));
+
+ if (len > 0)
+ {
+ ssize_t n = this->client_stream_.send_n (buf, len);
+ if (n <= 0 && errno != EPIPE)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")));
+ }
+ }
+
+ return 0;
+}
+
+// Trigger a reconfiguration of the Service Configurator via its
+// svc.conf file.
+
+int
+ACE_Service_Manager::reconfigure_services (void)
+{
+ ACE_TRACE ("ACE_Service_Manager::reconfigure_services");
+
+#if 0
+// Send ourselves a signal! ACE_OS::kill (ACE_OS::getpid (),
+// this->signum_);
+#endif /* 0 */
+
+ // Flag the main event loop that a reconfiguration should occur.
+ // The next trip through the <ACE_Reactor::run_event_loop> should
+ // pick this up and cause a reconfiguration. Note that we can't
+ // trigger the reconfiguration automatically since that might "pull
+ // the rug" out from underneath the existing services in a
+ // problematic way.
+ ACE_Service_Config::reconfig_occurred ((sig_atomic_t) 1);
+ return static_cast<int> (this->client_stream_.send_n ("done\n",
+ sizeof ("done\n")));
+}
+
+// isolate the request-processing code
+void
+ACE_Service_Manager::process_request (ACE_TCHAR *request)
+{
+ ACE_TRACE("ACE_Service_Manager::process_request");
+ ACE_TCHAR *p;
+
+ // Kill trailing newlines.
+ for (p = request;
+ (*p != '\0') && (*p != '\r') && (*p != '\n');
+ p++)
+ continue;
+
+ *p = '\0';
+
+ if (ACE_OS::strcmp (request, ACE_TEXT ("help")) == 0)
+ // Return a list of the configured services.
+ this->list_services ();
+ else if (ACE_OS::strcmp (request, ACE_TEXT ("reconfigure") )== 0)
+ // Trigger a reconfiguration by re-reading the local <svc.conf> file.
+ this->reconfigure_services ();
+ else
+ // Just process a single request passed in via the socket
+ // remotely.
+ ACE_Service_Config::process_directive (request);
+
+ // Additional management services may be handled here...
+}
+
+// Accept new connection from client and carry out the service they
+// request.
+
+int
+ACE_Service_Manager::handle_input (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Service_Manager::handle_input");
+
+ // 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 =
+ ACE_Reactor::instance ()->uses_event_associations ();
+
+ if (this->acceptor_.accept (this->client_stream_, // stream
+ 0, // remote address
+ 0, // timeout
+ 1, // restart
+ reset_new_handle // reset new handler
+ ) == -1)
+ return -1;
+
+ if (this->debug_)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("client_stream fd = %d\n"),
+ this->client_stream_.get_handle ()));
+ ACE_INET_Addr sa;
+ if (this->client_stream_.get_remote_addr (sa) == -1)
+ return -1;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("accepted from host %s at port %d\n"),
+ ACE_TEXT_CHAR_TO_TCHAR (sa.get_host_name ()),
+ sa.get_port_number ()));
+ }
+
+ ACE_TCHAR request[BUFSIZ];
+ ACE_TCHAR* offset = request;
+ ssize_t remaining = sizeof (request);
+
+ // Read service request from client.
+
+ ssize_t result;
+
+ // Keep looping until we actually get the request. Note that Win32
+ // sets the socket into non-blocking mode, so we may need to loop if
+ // the system is heavily loaded. Read bytes into the buffer until a
+ // '\n' or '\r' is found in the buffer, otherwise the buffer
+ // contains an incomplete string.
+
+ int error;
+ do
+ {
+ result = client_stream_.recv (offset, remaining);
+ error = errno;
+ if (result == 0 && error != EWOULDBLOCK)
+ remaining = 0;
+
+ if (result >= 0)
+ {
+ if ((remaining -= result) <= 0)
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("Request buffer overflow.\n")));
+ result = 0;
+ break;
+ }
+
+ offset += result;
+ *offset = 0;
+
+ if (ACE_OS::strchr (request, '\r') != 0
+ || ACE_OS::strchr (request, '\n') != 0)
+ remaining = 0;
+ }
+ }
+ while (result == -1 && error == EWOULDBLOCK || remaining > 0);
+
+ switch (result)
+ {
+ case -1:
+ if (this->debug_)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv")));
+ break;
+ case 0:
+ return 0;
+ /* NOTREACHED */
+ default:
+ {
+ ACE_Event_Handler *old_signal_handler = 0;
+ ACE_Reactor::instance ()->register_handler (SIGPIPE,
+ this,
+ 0,
+ &old_signal_handler);
+
+ this->process_request (request);
+
+ // Restore existing SIGPIPE handler
+ ACE_Reactor::instance ()->register_handler (SIGPIPE,
+ old_signal_handler);
+ }
+ }
+
+ if (this->client_stream_.close () == -1 && this->debug_)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")));
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Manager.h b/ACE/ace/Service_Manager.h
new file mode 100644
index 00000000000..c0d0c7e0fa7
--- /dev/null
+++ b/ACE/ace/Service_Manager.h
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Service_Manager.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SERVICE_MANAGER_H
+#define ACE_SERVICE_MANAGER_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/SOCK_Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/Service_Object.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Service_Manager
+ *
+ * @brief Provide a standard ACE service for managing all the services
+ * configured in an ACE_Service_Repository.
+ *
+ * This implementation is simple and just handles each client
+ * request one at a time. There are currently 3 types of requests:
+ * - List services: If the string "help" is sent, return a list of all
+ * the services supported by the Service Configurator.
+ * - Reconfigure: If the string "reconfigure" is sent trigger a
+ * reconfiguration, which will re-read the local <svc.conf> file.
+ * - Process directive: If neither "help" nor "reconfigure" is sent,
+ * simply treat the incoming string as a process directive and pass
+ * it along to <ACE_Service_Config::process_directive>. This allows
+ * remote configuration via command-line instructions like
+ * % echo suspend My_Remote_Service | telnet hostname 3911
+ *
+ * Each request is associated with a new connection, which is closed
+ * when the request is processed. In addition, you must be using the
+ * singleton <ACE_Reactor::instance> in order to trigger
+ * reconfigurations.
+ */
+class ACE_Export ACE_Service_Manager : public ACE_Service_Object
+{
+public:
+ // = Initialization and termination hooks.
+ /// Constructor.
+ ACE_Service_Manager (void);
+
+ /// Destructor.
+ ~ACE_Service_Manager (void);
+
+protected:
+ // = Perform the various meta-services.
+
+ /// Trigger a reconfiguration of the Service Configurator by
+ /// re-reading its local <svc.conf> file.
+ virtual int reconfigure_services (void);
+
+ /// Determine all the services offered by this daemon and return the
+ /// information back to the client.
+ virtual int list_services (void);
+
+ // = Dynamic linking hooks.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+ virtual int fini (void);
+
+ // = Scheduling hooks.
+ virtual int suspend (void);
+ virtual int resume (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ int open (const ACE_INET_Addr &sia);
+
+ // = Demultiplexing hooks.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask);
+ virtual int handle_signal (int signum, siginfo_t *, ucontext_t *);
+
+ /// Handle one request.
+ virtual void process_request (ACE_TCHAR *request);
+
+ /// Connection to the client (we only support one client connection
+ /// at a time).
+ ACE_SOCK_Stream client_stream_;
+
+ /// Acceptor instance.
+ ACE_SOCK_Acceptor acceptor_;
+
+ /// Keep track whether we debug or not.
+ bool debug_;
+
+ /// The signal used to trigger reconfiguration.
+ int signum_;
+
+ /// Default port for the Acceptor to listen on.
+ static u_short DEFAULT_PORT_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* _SERVICE_MANAGER_H */
diff --git a/ACE/ace/Service_Object.cpp b/ACE/ace/Service_Object.cpp
new file mode 100644
index 00000000000..cc2a1605a39
--- /dev/null
+++ b/ACE/ace/Service_Object.cpp
@@ -0,0 +1,173 @@
+// $Id$
+
+#include "ace/config-all.h"
+
+#include "ace/Service_Object.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Service_Object.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/Service_Types.h"
+#include "ace/DLL.h"
+#include "ace/ACE.h"
+#if defined (ACE_OPENVMS)
+# include "ace/Lib_Find.h"
+#endif
+
+ACE_RCSID (ace,
+ Service_Object,
+ "$Id$")
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Service_Object)
+ ACE_ALLOC_HOOK_DEFINE(ACE_Service_Type)
+
+ void
+ACE_Service_Type::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Service_Type::dump");
+#endif /* ACE_HAS_DUMP */
+
+
+ // Using printf, since the log facility may not have been
+ // initialized yet. Using a "//" prefix, in case the executable
+ // happens to be a code generator and the output gets embedded in
+ // the generated C++ code.
+ ACE_OS::fprintf(stderr,
+ "// [ST] dump, this=%p, name=%s, type=%p, so=%p, active=%d\n",
+ this,
+ this->name_,
+ this->type_,
+ (this->type_ != 0) ? this->type_->object () : 0,
+ this->active_);
+
+}
+
+ACE_Service_Type::ACE_Service_Type (const ACE_TCHAR *n,
+ ACE_Service_Type_Impl *t,
+ const ACE_DLL &dll,
+ int active)
+ : name_ (0),
+ type_ (t),
+ dll_ (dll),
+ active_ (active),
+ fini_already_called_ (0)
+{
+ ACE_TRACE ("ACE_Service_Type::ACE_Service_Type");
+ this->name (n);
+}
+
+ACE_Service_Type::ACE_Service_Type (const ACE_TCHAR *n,
+ ACE_Service_Type_Impl *t,
+ ACE_SHLIB_HANDLE handle,
+ int active)
+ : name_ (0),
+ type_ (t),
+ active_ (active),
+ fini_already_called_ (0)
+{
+ ACE_TRACE ("ACE_Service_Type::ACE_Service_Type");
+ this->dll_.set_handle (handle);
+ this->name (n);
+}
+
+ACE_Service_Type::~ACE_Service_Type (void)
+{
+ ACE_TRACE ("ACE_Service_Type::~ACE_Service_Type");
+ this->fini ();
+
+ delete [] const_cast <ACE_TCHAR *> (this->name_);
+}
+
+int
+ACE_Service_Type::fini (void)
+{
+ if (this->fini_already_called_)
+ return 0;
+
+ this->fini_already_called_ = 1;
+
+ if (this->type_ == 0)
+ {
+ // Returning 1 currently only makes sense for dummy instances, used
+ // to "reserve" a spot (kind of like forward-declarations) for a
+ // dynamic service. This is necessary to help enforce the correct
+ // finalization order, when such service also has any (dependent)
+ // static services
+
+ return 1; // No implementation was found.
+ }
+
+ int ret = this->type_->fini ();
+
+ // Ensure that closing the DLL is done after type_->fini() as it may
+ // require access to the code for the service object destructor,
+ // which resides in the DLL
+ return (ret | this->dll_.close());
+
+}
+
+int
+ACE_Service_Type::suspend (void) const
+{
+ ACE_TRACE ("ACE_Service_Type::suspend");
+ (const_cast<ACE_Service_Type *> (this))->active_ = 0;
+ return this->type_->suspend ();
+}
+
+int
+ACE_Service_Type::resume (void) const
+{
+ ACE_TRACE ("ACE_Service_Type::resume");
+ (const_cast<ACE_Service_Type *> (this))->active_ = 1;
+ return this->type_->resume ();
+}
+
+ACE_Service_Object::ACE_Service_Object (ACE_Reactor *r)
+ : ACE_Event_Handler (r)
+{
+ ACE_TRACE ("ACE_Service_Object::ACE_Service_Object");
+}
+
+ACE_Service_Object::~ACE_Service_Object (void)
+{
+ ACE_TRACE ("ACE_Service_Object::~ACE_Service_Object");
+}
+
+int
+ACE_Service_Object::suspend (void)
+{
+ ACE_TRACE ("ACE_Service_Object::suspend");
+ return 0;
+}
+
+int
+ACE_Service_Object::resume (void)
+{
+ ACE_TRACE ("ACE_Service_Object::resume");
+ return 0;
+}
+
+void
+ACE_Service_Type::name (const ACE_TCHAR *n)
+{
+ ACE_TRACE ("ACE_Service_Type::name");
+
+ delete [] const_cast <ACE_TCHAR *> (this->name_);
+ this->name_ = ACE::strnew (n);
+}
+
+#if defined (ACE_OPENVMS)
+ACE_Dynamic_Svc_Registrar::ACE_Dynamic_Svc_Registrar (const ACE_TCHAR* alloc_name,
+ void* svc_allocator)
+{
+ // register service allocator function by full name in ACE singleton registry
+ ACE::ldregister (alloc_name, svc_allocator);
+}
+#endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Object.h b/ACE/ace/Service_Object.h
new file mode 100644
index 00000000000..abc4781d9c8
--- /dev/null
+++ b/ACE/ace/Service_Object.h
@@ -0,0 +1,207 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Service_Object.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SERVICE_OBJECT_H
+#define ACE_SERVICE_OBJECT_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Shared_Object.h"
+#include "ace/Svc_Conf_Tokens.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event_Handler.h"
+#include "ace/DLL.h"
+
+#include "ace/Service_Gestalt.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#define ACE_Component ACE_Service_Object
+
+/**
+ * @class ACE_Service_Object
+ *
+ * @brief Provide the abstract base class common to all service
+ * implementations.
+ *
+ * Classes that inherit from <ACE_Service_Objects> are capable
+ * of being registered with the ACE_Reactor (due to the
+ * ACE_Event_Handler, as well as being dynamically linked by
+ * the ACE_Service_Config (due to the <ACE_Shared_Object>).
+ */
+class ACE_Export ACE_Service_Object
+ : public ACE_Event_Handler,
+ public ACE_Shared_Object
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Service_Object (ACE_Reactor * = 0);
+
+ /// Destructor.
+ virtual ~ACE_Service_Object (void);
+
+ /// Temporarily disable a service without removing it completely.
+ virtual int suspend (void);
+
+ /// Re-enable a previously suspended service.
+ virtual int resume (void);
+};
+
+// Forward decl.
+class ACE_Service_Type_Impl;
+
+/**
+ * @class ACE_Service_Type
+ *
+ * @brief Keeps track of information related to the various
+ * ACE_Service_Type_Impl subclasses.
+ *
+ * This class acts as the interface of the "Bridge" pattern.
+ */
+class ACE_Export ACE_Service_Type
+{
+public:
+ enum
+ {
+ /// Delete the payload object.
+ DELETE_OBJ = 1,
+
+ /// Delete the enclosing object.
+ DELETE_THIS = 2
+ };
+
+ enum
+ {
+ SERVICE_OBJECT = ACE_SVC_OBJ_T,
+ MODULE = ACE_MODULE_T,
+ STREAM = ACE_STREAM_T,
+ INVALID_TYPE = -1
+ };
+
+ // = Initialization and termination methods.
+ ACE_Service_Type (const ACE_TCHAR *n,
+ ACE_Service_Type_Impl *o,
+ const ACE_DLL &dll,
+ int active);
+ ACE_Service_Type (const ACE_TCHAR *n,
+ ACE_Service_Type_Impl *o,
+ ACE_SHLIB_HANDLE handle,
+ int active);
+ ~ACE_Service_Type (void);
+
+ const ACE_TCHAR *name (void) const;
+ void name (const ACE_TCHAR *);
+
+ const ACE_Service_Type_Impl *type (void) const;
+ void type (const ACE_Service_Type_Impl *, int active = 1);
+
+ // Is this just a stub for the real thing?
+ bool is_forward_declaration (void) const;
+
+ int suspend (void) const;
+ int resume (void) const;
+ int active (void) const;
+ void active (int);
+
+ /// Calls <fini> on <type_>
+ int fini (void);
+
+ /// Check if the service has been fini'ed.
+ int fini_called (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Get to the DLL's implentation
+ const ACE_DLL & dll (void) const;
+
+ /// Sets the DLL
+ void dll (const ACE_DLL&);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Humanly readible name of svc.
+ const ACE_TCHAR *name_;
+
+ /// Pointer to C++ object that implements the svc.
+ const ACE_Service_Type_Impl *type_;
+
+ /// ACE_DLL representing the shared object file (non-zero if
+ /// dynamically linked).
+ mutable ACE_DLL dll_;
+
+ /// 1 if svc is currently active, otherwise 0.
+ int active_;
+
+ /// 1 if <fini> on <type_> has already been called, otherwise 0.
+ int fini_already_called_;
+};
+
+/**
+ * @class ACE_Service_Object_Ptr
+ *
+ * @brief This is a smart pointer that holds onto the associated
+ * ACE_Service_Object * until the current scope is left, at
+ * which point the object's <fini> hook is called and the
+ * service_object_ gets deleted.
+ *
+ * This class is similar to the Standard C++ Library class
+ * <auto_ptr>. It is used in conjunction with statically linked
+ * <ACE_Service_Objects>, as shown in the
+ * ./netsvcs/server/main.cpp example.
+ */
+class ACE_Export ACE_Service_Object_Ptr
+{
+public:
+ // = Initialization and termination methods.
+ /// Acquire ownership of the @a so.
+ ACE_Service_Object_Ptr (ACE_Service_Object *so);
+
+ /// Release the held ACE_Service_Object by calling its <fini> hook.
+ ~ACE_Service_Object_Ptr (void);
+
+ /// Smart pointer to access the underlying ACE_Service_Object.
+ ACE_Service_Object *operator-> ();
+
+private:
+ /// Holds the service object until we're done.
+ ACE_Service_Object *service_object_;
+};
+
+#if defined (ACE_OPENVMS)
+/**
+ * @class ACE_Dynamic_Svc_Registrar
+ *
+ * @brief Used to register Service allocator function by its full name.
+ */
+class ACE_Dynamic_Svc_Registrar
+{
+public:
+ ACE_Dynamic_Svc_Registrar (const ACE_TCHAR* alloc_name,
+ void* svc_allocator);
+};
+#endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Service_Object.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SERVICE_OBJECT_H */
diff --git a/ACE/ace/Service_Object.inl b/ACE/ace/Service_Object.inl
new file mode 100644
index 00000000000..5e58bc57588
--- /dev/null
+++ b/ACE/ace/Service_Object.inl
@@ -0,0 +1,79 @@
+// -*- C++ -*-
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_Service_Object_Ptr::ACE_Service_Object_Ptr (ACE_Service_Object *so)
+ : service_object_ (so)
+{
+}
+
+ACE_INLINE ACE_Service_Object_Ptr::~ACE_Service_Object_Ptr (void)
+{
+ this->service_object_->fini ();
+ delete this->service_object_;
+}
+
+ACE_INLINE ACE_Service_Object *
+ACE_Service_Object_Ptr::operator-> ()
+{
+ return this->service_object_;
+}
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Service_Type::name (void) const
+{
+ ACE_TRACE ("ACE_Service_Type::name");
+ return this->name_;
+}
+
+ACE_INLINE const ACE_Service_Type_Impl *
+ACE_Service_Type::type (void) const
+{
+ ACE_TRACE ("ACE_Service_Type::type");
+ return this->type_;
+}
+
+ACE_INLINE void
+ACE_Service_Type::type (const ACE_Service_Type_Impl *o, int enabled)
+{
+ ACE_TRACE ("ACE_Service_Type::type");
+ this->type_ = o;
+ ((ACE_Service_Type *) this)->active_ = enabled;
+}
+
+ACE_INLINE int
+ACE_Service_Type::active (void) const
+{
+ ACE_TRACE ("ACE_Service_Type::active");
+ return this->active_ != 0;
+}
+
+ACE_INLINE void
+ACE_Service_Type::active (int turnon)
+{
+ ACE_TRACE ("ACE_Service_Type::active");
+ this->active_ = turnon;
+}
+
+ACE_INLINE int
+ACE_Service_Type::fini_called (void) const
+{
+ ACE_TRACE ("ACE_Service_Type::fini_called");
+ return this->fini_already_called_;
+}
+
+ACE_INLINE const ACE_DLL & ACE_Service_Type::dll () const
+{
+ ACE_TRACE ("ACE_Service_Type::dll");
+ return this->dll_;
+}
+
+ACE_INLINE void ACE_Service_Type::dll (const ACE_DLL &adll)
+{
+ ACE_TRACE ("ACE_Service_Type::dll");
+ this->dll_ = adll;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
diff --git a/ACE/ace/Service_Repository.cpp b/ACE/ace/Service_Repository.cpp
new file mode 100644
index 00000000000..582f3a2729f
--- /dev/null
+++ b/ACE/ace/Service_Repository.cpp
@@ -0,0 +1,577 @@
+// $Id$
+
+#include "ace/Service_Repository.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Service_Repository.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Service_Types.h"
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ Service_Repository,
+ "$Id$")
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Service_Repository)
+
+// Process-wide Service Repository.
+ACE_Service_Repository *ACE_Service_Repository::svc_rep_ = 0;
+
+// Controls whether the Service_Repository is deleted when we shut
+// down (we can only delete it safely if we created it)!
+bool ACE_Service_Repository::delete_svc_rep_ = false;
+
+void
+ACE_Service_Repository::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Service_Repository::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Service_Repository::ACE_Service_Repository (void)
+ : service_vector_ (0),
+ current_size_ (0),
+ total_size_ (0)
+{
+ ACE_TRACE ("ACE_Service_Repository::ACE_Service_Repository");
+}
+
+ACE_Service_Repository *
+ACE_Service_Repository::instance (size_t size /* = ACE_Service_Repository::DEFAULT_SIZE */)
+{
+ ACE_TRACE ("ACE_Service_Repository::instance");
+
+ if (ACE_Service_Repository::svc_rep_ == 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_Service_Repository::svc_rep_ == 0)
+ {
+ if (ACE_Object_Manager::starting_up () ||
+ !ACE_Object_Manager::shutting_down ())
+ {
+ ACE_NEW_RETURN (ACE_Service_Repository::svc_rep_,
+ ACE_Service_Repository (size),
+ 0);
+ ACE_Service_Repository::delete_svc_rep_ = true;
+ }
+ }
+ }
+
+ return ACE_Service_Repository::svc_rep_;
+}
+
+ACE_Service_Repository *
+ACE_Service_Repository::instance (ACE_Service_Repository *s)
+{
+ ACE_TRACE ("ACE_Service_Repository::instance");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ ACE_Service_Repository *t = ACE_Service_Repository::svc_rep_;
+ // We can't safely delete it since we don't know who created it!
+ ACE_Service_Repository::delete_svc_rep_ = false;
+
+ ACE_Service_Repository::svc_rep_ = s;
+ return t;
+}
+
+void
+ACE_Service_Repository::close_singleton (void)
+{
+ ACE_TRACE ("ACE_Service_Repository::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ if (ACE_Service_Repository::delete_svc_rep_)
+ {
+ delete ACE_Service_Repository::svc_rep_;
+ ACE_Service_Repository::svc_rep_ = 0;
+ ACE_Service_Repository::delete_svc_rep_ = false;
+ }
+}
+
+// Initialize the Repository to a clean slate.
+
+int
+ACE_Service_Repository::open (size_t size)
+{
+ ACE_TRACE ("ACE_Service_Repository::open");
+
+ ACE_Service_Type **temp = 0;
+
+ ACE_NEW_RETURN (temp,
+ ACE_Service_Type *[size],
+ -1);
+
+ this->service_vector_ = const_cast<const ACE_Service_Type **> (temp);
+ this->total_size_ = size;
+ return 0;
+}
+
+ACE_Service_Repository::ACE_Service_Repository (size_t size)
+ : current_size_ (0)
+{
+ ACE_TRACE ("ACE_Service_Repository::ACE_Service_Repository");
+
+ if (this->open (size) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Service_Repository")));
+}
+
+// Finalize (call <fini> and possibly delete) all the services.
+
+int
+ACE_Service_Repository::fini (void)
+{
+ ACE_TRACE ("ACE_Service_Repository::fini");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+ int retval = 0;
+
+ if (this->service_vector_ != 0)
+ {
+ // <fini> the services in reverse order. Note that if services
+ // were removed from the middle of the repository the order
+ // won't necessarily be maintained since the <remove> method
+ // performs compaction. However, the common case is not to
+ // remove services, so typically they are deleted in reverse
+ // order.
+
+ // Do not be tempted to use the prefix decrement operator. We
+ // need to use the postfix decrement operator in this case since
+ // the index is unsigned.
+ for (size_t i = this->current_size_; i-- != 0; )
+ {
+ ACE_Service_Type *s =
+ const_cast<ACE_Service_Type *> (this->service_vector_[i]);
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SR::fini, repo=%@ [%d] (%d), ")
+ ACE_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d\n"),
+ this, i, this->total_size_, s->name(), s->type (),
+ (s->type () != 0) ? s->type ()->object () : 0,
+ s->active ()));
+#endif
+
+ // Collect any errors.
+ int ret = s->fini ();
+ retval += ret;
+ }
+ }
+
+ return (retval == 0) ? 0 : -1;
+}
+
+// Close down all the services.
+
+int
+ACE_Service_Repository::close (void)
+{
+ ACE_TRACE ("ACE_Service_Repository::close");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (this->service_vector_ != 0)
+ {
+ // Delete services in reverse order. Note that if services were
+ // removed from the middle of the repository the order won't
+ // necessarily be maintained since the <remove> method performs
+ // compaction. However, the common case is not to remove
+ // services, so typically they are deleted in reverse order.
+
+#ifndef ACE_NLOGGING
+ if(ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) SR::close, this=%@, size=%d\n"),
+ this,
+ this->current_size_));
+#endif
+
+ // Do not be tempted to use the prefix decrement operator. We
+ // need to use the postfix decrement operator in this case since
+ // the index is unsigned.
+ for (size_t i = this->current_size_; i-- != 0; )
+ {
+
+#ifndef ACE_NLOGGING
+ if(ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) SR::close, this=%@, delete so[%d]=%@ (%s)\n"),
+ this, i,
+ this->service_vector_[i],
+ this->service_vector_[i]->name ()));
+#endif
+
+ ACE_Service_Type *s = const_cast<ACE_Service_Type *> (this->service_vector_[i]);
+ --this->current_size_;
+ delete s;
+ }
+
+ delete [] this->service_vector_;
+ this->service_vector_ = 0;
+ this->current_size_ = 0;
+ }
+
+ return 0;
+}
+
+ACE_Service_Repository::~ACE_Service_Repository (void)
+{
+ ACE_TRACE ("ACE_Service_Repository::~ACE_Service_Repository");
+#ifndef ACE_NLOGGING
+ if(ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) SR::<dtor>, this=%@\n", this));
+#endif
+ this->close ();
+}
+
+// Locate an entry with <name> in the table. If <ignore_suspended> is
+// set then only consider services marked as resumed. If the caller
+// wants the located entry, pass back a pointer to the located entry
+// via <srp>. If <name> is not found -1 is returned. If <name> is
+// found, but it is suspended and the caller wants to ignore suspended
+// services a -2 is returned. Must be called with locks held.
+
+int
+ACE_Service_Repository::find_i (const ACE_TCHAR name[],
+ size_t &slot,
+ const ACE_Service_Type **srp,
+ bool ignore_suspended) const
+{
+ ACE_TRACE ("ACE_Service_Repository::find_i");
+ size_t i;
+
+ for (i = 0; i < this->current_size_; i++)
+ if (ACE_OS::strcmp (name,
+ this->service_vector_[i]->name ()) == 0)
+ break;
+
+ if (i < this->current_size_)
+ {
+ slot = i;
+ if (this->service_vector_[i]->fini_called ())
+ {
+ if (srp != 0)
+ *srp = 0;
+ return -1;
+ }
+
+ if (srp != 0)
+ *srp = this->service_vector_[i];
+ if (ignore_suspended
+ && this->service_vector_[i]->active () == 0)
+ return -2;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+/// @brief Relocate (a static) service to another DLL.
+///
+/// Works by having the service type keep a reference to a specific
+/// DLL. No locking, caller makes sure calling it is safe. You can
+/// forcefully relocate any DLLs in the given range, not only the
+/// static ones - but that will cause Very Bad Things (tm) to happen.
+
+int
+ACE_Service_Repository::relocate_i (size_t begin,
+ size_t end,
+ const ACE_DLL& adll,
+ bool static_only)
+{
+ ACE_SHLIB_HANDLE new_handle = adll.get_handle (0);
+
+ for (size_t i = begin; i < end; i++)
+ {
+ ACE_Service_Type *type =
+ const_cast<ACE_Service_Type *> (this->service_vector_[i]);
+
+ ACE_SHLIB_HANDLE old_handle = type->dll ().get_handle (0);
+ if (static_only && old_handle != ACE_SHLIB_INVALID_HANDLE)
+ continue;
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SR::relocate, repo=%@ [%d] (size=%d): name=%s - DLL from=%d to=%d\n"),
+ this, i, this->total_size_, type->name (),
+ old_handle,
+ new_handle));
+#else
+ ACE_UNUSED_ARG (new_handle);
+#endif
+ type->dll (adll);
+ }
+
+ return 0;
+}
+
+int
+ACE_Service_Repository::find (const ACE_TCHAR name[],
+ const ACE_Service_Type **srp,
+ bool ignore_suspended) const
+{
+ ACE_TRACE ("ACE_Service_Repository::find");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+ size_t ignore_location = 0;
+ return this->find_i (name, ignore_location, srp, ignore_suspended);
+}
+
+
+// Insert the ACE_Service_Type SR into the repository. Note that
+// services may be inserted either resumed or suspended. Using same name
+// as in an existing service causes the delete () to be called for the old one,
+// i.e. make sure @code sr is allocated on the heap!
+
+int
+ACE_Service_Repository::insert (const ACE_Service_Type *sr)
+{
+ ACE_TRACE ("ACE_Service_Repository::insert");
+
+ int return_value = -1;
+ ACE_Service_Type *s = 0;
+ size_t i = 0;
+
+ {
+ // @TODO: Do we need a recursive mutex here?
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ // Check to see if this is a duplicate.
+ for (i = 0; i < this->current_size_; i++)
+ if (ACE_OS::strcmp (sr->name (),
+ this->service_vector_[i]->name ()) == 0)
+ break;
+
+ // Replacing an existing entry
+ if (i < this->current_size_)
+ {
+ return_value = 0;
+ // Check for self-assignment...
+ if (sr != this->service_vector_[i])
+ {
+ s = const_cast<ACE_Service_Type *> (this->service_vector_[i]);
+ this->service_vector_[i] = sr;
+ }
+ }
+ // Adding a new entry.
+ else if (i < this->total_size_)
+ {
+ this->service_vector_[i] = sr;
+ this->current_size_++;
+ return_value = 0;
+ }
+
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SR::insert")
+ ACE_TEXT (" - repo=%@ [%d] (%d), name=%s")
+ ACE_TEXT (", type=%@, object=%@, active=%d\n"),
+ this, i, this->total_size_, sr->name(), sr->type (),
+ (sr->type () != 0) ? sr->type ()->object () : 0,
+ sr->active ()));
+#endif
+ }
+
+ // Delete outside the lock
+ if (s != 0)
+ {
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SR::insert")
+ ACE_TEXT (" - destroying (replacing), repo=%@ [%d] (%d), name=%s")
+ ACE_TEXT (", type=%@, object=%@, active=%d\n"),
+ this, i, this->total_size_, s->name(), s->type (),
+ (s->type () != 0) ? s->type ()->object () : 0,
+ s->active ()));
+#endif
+ delete s;
+ }
+
+ if (return_value == -1)
+ ACE_OS::last_error (ENOSPC);
+
+ return return_value;
+}
+
+// Re-resume a service that was previously suspended.
+
+int
+ACE_Service_Repository::resume (const ACE_TCHAR name[],
+ const ACE_Service_Type **srp)
+{
+ ACE_TRACE ("ACE_Service_Repository::resume");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ size_t i = 0;
+ if (-1 == this->find_i (name, i, srp, 0))
+ return -1;
+
+ return this->service_vector_[i]->resume ();
+}
+
+// Suspend a service so that it will not be considered active under
+// most circumstances by other portions of the ACE_Service_Repository.
+
+int
+ACE_Service_Repository::suspend (const ACE_TCHAR name[],
+ const ACE_Service_Type **srp)
+{
+ ACE_TRACE ("ACE_Service_Repository::suspend");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+ size_t i = 0;
+ if (-1 == this->find_i (name, i, srp, 0))
+ return -1;
+
+ return this->service_vector_[i]->suspend ();
+}
+
+
+/**
+ * @brief Completely remove a <name> entry from the Repository and
+ * dynamically unlink it if it was originally dynamically linked.
+ */
+
+int
+ACE_Service_Repository::remove (const ACE_TCHAR name[], ACE_Service_Type **ps)
+{
+ ACE_TRACE ("ACE_Service_Repository::remove");
+ ACE_Service_Type *s = 0;
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ // Not found!?
+ if (this->remove_i (name, &s) == -1)
+ return -1;
+ }
+
+ if (ps != 0)
+ *ps = s;
+ else
+ delete s;
+ return 0;
+}
+
+/**
+ * @brief Completely remove a <name> entry from the Repository and
+ * dynamically unlink it if it was originally dynamically linked.
+ *
+ * Return a ptr to the entry in @code ps. There is no locking so make
+ * sure you hold the repo lock when calling.
+ *
+ * Since the order of services in the Respository matters, we can't
+ * simply overwrite the entry being deleted with the last and
+ * decrement the <current_size> by 1 - we must "pack" the array. A
+ * good example of why the order matters is a dynamic service, in
+ * whose DLL there is at least one static service. In order to prevent
+ * SEGV during finalization, those static services must be finalized
+ * _before_the dynamic service that owns them. Otherwice the TEXT
+ * segment, containing the code for the static service's desructor may
+ * be unloaded with the DLL.
+ *
+ * @note: (IJ) The above is not entirely true, since the introduction
+ * of the ACE_Service_Dynamic_Guard, which fixes-up any stray static
+ * services to hold a reference to the DLL. This allows out-of order
+ * removals and perhaps allows to skip packing the repo. I left it in
+ * because a packed repo is a lot easier to debug.
+ */
+int
+ACE_Service_Repository::remove_i (const ACE_TCHAR name[], ACE_Service_Type **ps)
+{
+ size_t i = 0;
+ if (-1 == this->find_i (name, i, 0, false))
+ return -1; // Not found
+
+ // We may need the old ptr - to be delete outside the lock!
+ *ps = const_cast<ACE_Service_Type *> (this->service_vector_[i]);
+
+ // Pack the array
+ --this->current_size_;
+ for (size_t j = i; j < this->current_size_; j++)
+ this->service_vector_[j] = this->service_vector_[j+1];
+
+ return 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Service_Repository_Iterator)
+
+void
+ACE_Service_Repository_Iterator::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Service_Repository_Iterator::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+
+// Initializes the iterator and skips over any suspended entries at
+// the beginning of the table, if necessary. Note, you must not
+// perform destructive operations on elements during this iteration...
+
+ACE_Service_Repository_Iterator::ACE_Service_Repository_Iterator
+ (ACE_Service_Repository &sr, int ignr_suspended)
+ : svc_rep_ (sr),
+ next_ (0),
+ ignore_suspended_ (ignr_suspended)
+{
+ while (!(done() || valid()))
+ this->next_++;
+}
+
+// Obtains a pointer to the next valid service in the table. If there
+// are no more entries, returns 0, else 1.
+
+int
+ACE_Service_Repository_Iterator::next (const ACE_Service_Type *&sr)
+{
+ ACE_TRACE ("ACE_Service_Repository_Iterator::next");
+
+ if (done ())
+ return 0;
+
+ sr = this->svc_rep_.service_vector_[this->next_];
+ return 1;
+}
+
+// Advance the iterator by the proper amount. If we are ignoring
+// suspended entries and the current entry is suspended, then we must
+// skip over this entry. Otherwise, we must advance the NEXT index to
+// reference the next valid service entry.
+
+int
+ACE_Service_Repository_Iterator::advance (void)
+{
+ ACE_TRACE ("ACE_Service_Repository_Iterator::advance");
+
+ if (done()) return 0;
+
+ do this->next_++; while (!(done () || valid ()));
+
+ return !done();
+}
+
+bool
+ACE_Service_Repository_Iterator::valid (void) const
+{
+ ACE_TRACE ("ACE_Service_Repository_Iterator::valid");
+ return (this->ignore_suspended_ == 0
+ || this->svc_rep_.service_vector_[this->next_]->active ());
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Repository.h b/ACE/ace/Service_Repository.h
new file mode 100644
index 00000000000..ad2b442819b
--- /dev/null
+++ b/ACE/ace/Service_Repository.h
@@ -0,0 +1,281 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Service_Repository.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SERVICE_REPOSITORY_H
+#define ACE_SERVICE_REPOSITORY_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Default_Constants.h"
+#include "ace/Recursive_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Service_Type;
+class ACE_DLL;
+
+#define ACE_Component_Repository ACE_Service_Repository
+/**
+ * @class ACE_Service_Repository
+ *
+ * @brief Contains all the services offered by a Service
+ * Configurator-based application.
+ *
+ * This class contains a vector of <ACE_Service_Types> *'s and
+ * allows an administrative entity to centrally manage and
+ * control the behavior of application services. Note that if
+ * services are removed from the middle of the repository the
+ * order won't necessarily be maintained since the <remove>
+ * method performs compaction. However, the common case is not
+ * to remove services, so typically they are deleted in the
+ * reverse order that they were added originally.
+ */
+class ACE_Export ACE_Service_Repository
+{
+public:
+ friend class ACE_Service_Repository_Iterator;
+
+ enum
+ {
+ DEFAULT_SIZE = ACE_DEFAULT_SERVICE_REPOSITORY_SIZE
+ };
+
+ // = Initialization and termination methods.
+ /// Initialize the repository.
+ ACE_Service_Repository (void);
+
+ /// Initialize the repository.
+ ACE_Service_Repository (size_t size);
+
+ /// Initialize the repository.
+ int open (size_t size = DEFAULT_SIZE);
+
+ /// Close down the repository and free up dynamically allocated
+ /// resources.
+ ~ACE_Service_Repository (void);
+
+ /// Close down the repository and free up dynamically allocated
+ /// resources.
+ int close (void);
+
+ /// Finalize all the services by calling <fini> and deleting
+ /// dynamically allocated services.
+ int fini (void);
+
+ /// Get pointer to a process-wide ACE_Service_Repository.
+ static ACE_Service_Repository * instance
+ (size_t size = ACE_Service_Repository::DEFAULT_SIZE);
+
+ /// Set pointer to a process-wide ACE_Service_Repository and return
+ /// existing pointer.
+ static ACE_Service_Repository *instance (ACE_Service_Repository *);
+
+ /// Delete the dynamically allocated Singleton.
+ static void close_singleton (void);
+
+ // = Search structure operations (all acquire locks as necessary).
+
+ /// Insert a new service record. Returns -1 when the service repository
+ /// is full and 0 on success.
+ int insert (const ACE_Service_Type *);
+
+ /**
+ * Locate a named entry in the service table, optionally ignoring
+ * suspended entries.
+ *
+ * @param service_name The name of the service to search for.
+ * @param srp Optional; if not 0, it is a pointer to a location
+ * to receive the ACE_Service_Type pointer for the
+ * located service. Meaningless if this method
+ * returns -1.
+ * @param ignore_suspended If true, the search ignores suspended services.
+ *
+ * @retval 0 Named service was located.
+ * @retval -1 Named service was not found.
+ * @retval -2 Named service was found, but is suspended and
+ * @a ignore_suspended is true.
+ */
+ int find (const ACE_TCHAR name[],
+ const ACE_Service_Type **srp = 0,
+ bool ignore_suspended = true) const;
+
+ /// Remove an existing service record. If @a sr == 0, the service record
+ /// is deleted before control is returned to the caller. If @a sr != 0,
+ /// the service's record is removed from the repository, but not deleted;
+ /// *sr receives the service record pointer and the caller is responsible
+ /// for properly disposing of it.
+ int remove (const ACE_TCHAR[], ACE_Service_Type **sr = 0);
+
+ // = Liveness control
+ /// Resume a service record.
+ int resume (const ACE_TCHAR[], const ACE_Service_Type ** = 0);
+
+ /// Suspend a service record.
+ int suspend (const ACE_TCHAR[], const ACE_Service_Type ** = 0);
+
+ /// Return the current size of the repository.
+ size_t current_size (void) const;
+
+ /// Return the total size of the repository.
+ size_t total_size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ friend class ACE_Service_Type_Dynamic_Guard;
+
+ /// Remove an existing service record. It requires @a sr != 0, which
+ /// receives the service record pointer and the caller is
+ /// responsible for properly disposing of it.
+ int remove_i (const ACE_TCHAR[], ACE_Service_Type **sr);
+
+ /**
+ * Locate a named entry in the service table, optionally ignoring
+ * suspended entries.
+ *
+ * @param service_name The name of the service to search for.
+ * @param slot Receives the position index of the service if it
+ * is found. Contents are meaningless if this method
+ * returns -1.
+ * @param srp Optional; if not 0, it is a pointer to a location
+ * to receive the ACE_Service_Type pointer for the
+ * located service. Meaningless if this method
+ * returns -1.
+ * @param ignore_suspended If true, the search ignores suspended services.
+ *
+ * @retval 0 Named service was located; index in the table is set in
+ * @a slot.
+ * @retval -1 Named service was not found.
+ * @retval -2 Named service was found, but is suspended and
+ * @a ignore_suspended is true.
+ */
+ int find_i (const ACE_TCHAR service_name[],
+ size_t &slot,
+ const ACE_Service_Type **srp = 0,
+ bool ignore_suspended = true) const;
+
+ /// @brief Relocate (static) services to another DLL.
+ ///
+ /// If any have been registered in the context of a "forward
+ /// declaration" guard, those really aren't static services. Their
+ /// code is in the DLL's code segment, or in one of the dependent
+ /// DLLs. Therefore, such services need to be associated with the
+ /// proper DLL in order to prevent failures upon finalization. The
+ /// method locks the repo.
+ ///
+ /// Works by having the service type keep a reference to a specific
+ /// DLL. No locking, caller makes sure calling it is safe. You can
+ /// forcefully relocate any DLLs in the given range, not only the
+ /// static ones - but that will cause Very Bad Things (tm) to happen.
+
+ int relocate_i (size_t begin,
+ size_t end,
+ const ACE_DLL &adll,
+ bool static_only = true);
+
+ /// Contains all the configured services.
+ const ACE_Service_Type **service_vector_;
+
+ /// Current number of services.
+ size_t current_size_;
+
+ /// Maximum number of services.
+ size_t total_size_;
+
+ /// Pointer to a process-wide ACE_Service_Repository.
+ static ACE_Service_Repository *svc_rep_;
+
+ /// Must delete the <svc_rep_> if true.
+ static bool delete_svc_rep_;
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ /// Synchronization variable for the MT_SAFE Repository
+ mutable ACE_Recursive_Thread_Mutex lock_;
+#endif /* ACE_MT_SAFE */
+};
+
+/**
+ * @class ACE_Service_Repository_Iterator
+ *
+ * @brief Iterate through the ACE_Service_Repository.
+ *
+ * Make sure not to delete entries as the iteration is going on
+ * since this class is not designed as a robust iterator.
+ */
+class ACE_Export ACE_Service_Repository_Iterator
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor initializes the iterator.
+ ACE_Service_Repository_Iterator (ACE_Service_Repository &sr,
+ int ignored_suspended = 1);
+
+ /// Destructor.
+ ~ACE_Service_Repository_Iterator (void);
+
+
+public:
+ // = Iteration methods.
+
+ /// Pass back the <next_item> that hasn't been seen in the repository.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (const ACE_Service_Type *&next_item);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Move forward by one element in the repository. 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:
+ bool valid (void) const;
+
+private:
+ ACE_Service_Repository_Iterator (const ACE_Service_Repository_Iterator&);
+
+ /// Reference to the Service Repository we are iterating over.
+ ACE_Service_Repository &svc_rep_;
+
+ /// Next index location that we haven't yet seen.
+ size_t next_;
+
+ /// Are we ignoring suspended services?
+ int ignore_suspended_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Service_Repository.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* _SERVICE_REPOSITORY_H */
diff --git a/ACE/ace/Service_Repository.inl b/ACE/ace/Service_Repository.inl
new file mode 100644
index 00000000000..a042a0f9a1d
--- /dev/null
+++ b/ACE/ace/Service_Repository.inl
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// Returns a count of the number of currently valid entries (counting
+// both resumed and suspended entries).
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+#include "ace/Guard_T.h"
+#include "ace/Thread_Mutex.h"
+#endif /* ACE_MT_SAFE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE size_t
+ACE_Service_Repository::current_size (void) const
+{
+ ACE_TRACE ("ACE_Service_Repository::current_size");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon,
+ (ACE_Recursive_Thread_Mutex &) this->lock_, 0));
+ return this->current_size_;
+}
+
+// Returns a count of the total number of possible entries in the
+// table.
+
+ACE_INLINE size_t
+ACE_Service_Repository::total_size (void) const
+{
+ ACE_TRACE ("ACE_Service_Repository::total_size");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
+ ace_mon,
+ (ACE_Recursive_Thread_Mutex &) this->lock_, 0));
+ return this->total_size_;
+}
+
+ACE_INLINE int
+ACE_Service_Repository_Iterator::done (void) const
+{
+ ACE_TRACE ("ACE_Service_Repository_Iterator::done");
+
+ return this->next_ >= this->svc_rep_.current_size_;
+}
+
+ACE_INLINE
+ACE_Service_Repository_Iterator::~ACE_Service_Repository_Iterator (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Templates.h b/ACE/ace/Service_Templates.h
new file mode 100644
index 00000000000..d41f16e6cbb
--- /dev/null
+++ b/ACE/ace/Service_Templates.h
@@ -0,0 +1,29 @@
+
+//=============================================================================
+/**
+ * @file Service_Templates.h
+ *
+ * $Id$
+ *
+ * @author Priyanka Gontla <pgontla@ece.uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SERVICE_TEMPLATES_H
+#define ACE_SERVICE_TEMPLATES_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Svc_Conf.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Stream_Modules.h"
+#include "ace/Stream.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SERVICE_TEMPLATES_H */
diff --git a/ACE/ace/Service_Types.cpp b/ACE/ace/Service_Types.cpp
new file mode 100644
index 00000000000..7cf3c4ef643
--- /dev/null
+++ b/ACE/ace/Service_Types.cpp
@@ -0,0 +1,458 @@
+// $Id$
+
+#include "ace/Service_Types.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Service_Types.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Stream_Modules.h"
+#include "ace/Stream.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+
+
+ACE_RCSID (ace,
+ Service_Types,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+typedef ACE_Stream<ACE_SYNCH> MT_Stream;
+typedef ACE_Module<ACE_SYNCH> MT_Module;
+typedef ACE_Task<ACE_SYNCH> MT_Task;
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Service_Type_Impl)
+
+void
+ACE_Service_Type_Impl::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Service_Type_Impl::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Service_Type_Impl::ACE_Service_Type_Impl (void *so,
+ const ACE_TCHAR *s_name,
+ u_int f,
+ ACE_Service_Object_Exterminator gobbler)
+ : name_ (0),
+ obj_ (so),
+ gobbler_ (gobbler),
+ flags_ (f)
+{
+ ACE_TRACE ("ACE_Service_Type_Impl::ACE_Service_Type_Impl");
+ this->name (s_name);
+}
+
+ACE_Service_Type_Impl::~ACE_Service_Type_Impl (void)
+{
+ ACE_TRACE ("ACE_Service_Type_Impl::~ACE_Service_Type_Impl");
+
+ // It's ok to call this, even though we may have already deleted it
+ // in the fini() method since it would then be NULL.
+ delete [] const_cast <ACE_TCHAR *> (this->name_);
+}
+
+int
+ACE_Service_Type_Impl::fini (void) const
+{
+ ACE_TRACE ("ACE_Service_Type_Impl::fini");
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) ST::fini - destroying %s, flags = %d\n"),
+ this->name_,
+ this->flags_));
+
+ delete [] const_cast <ACE_TCHAR *> (this->name_);
+ (const_cast <ACE_Service_Type_Impl *> (this))->name_ = 0;
+
+ if (ACE_BIT_ENABLED (this->flags_,
+ ACE_Service_Type::DELETE_OBJ))
+ {
+ if (gobbler_ != 0)
+ gobbler_ (this->object ());
+ else
+ // Cast to remove const-ness.
+ operator delete ((void *) this->object ());
+ }
+
+ if (ACE_BIT_ENABLED (this->flags_,
+ ACE_Service_Type::DELETE_THIS))
+ delete const_cast <ACE_Service_Type_Impl *> (this);
+
+ return 0;
+}
+
+ACE_Service_Object_Type::ACE_Service_Object_Type (void *so,
+ const ACE_TCHAR *s_name,
+ u_int f,
+ ACE_Service_Object_Exterminator gobbler)
+ : ACE_Service_Type_Impl (so, s_name, f, gobbler)
+ , initialized_ (-1)
+{
+ ACE_TRACE ("ACE_Service_Object_Type::ACE_Service_Object_Type");
+}
+
+int
+ACE_Service_Object_Type::init (int argc, ACE_TCHAR *argv[]) const
+{
+ ACE_TRACE ("ACE_Service_Object_Type::init");
+
+ void * const obj = this->object ();
+
+ ACE_Service_Object * const so =
+ static_cast<ACE_Service_Object *> (obj);
+
+ if (so == 0)
+ return -1;
+
+ this->initialized_ = so->init (argc, argv);
+
+ return this->initialized_;
+}
+
+int
+ACE_Service_Object_Type::fini (void) const
+{
+ ACE_TRACE ("ACE_Service_Object_Type::fini");
+
+ void * const obj = this->object ();
+
+ ACE_Service_Object * const so =
+ static_cast<ACE_Service_Object *> (obj);
+
+ // Call fini() if an only if, the object was successfuly
+ // initialized, i.e. init() returned 0. This is necessary to
+ // maintain the ctor/dtor-like semantics for init/fini.
+ if (so && initialized_ == 0)
+ so->fini ();
+
+ return ACE_Service_Type_Impl::fini ();
+}
+
+ACE_Service_Object_Type::~ACE_Service_Object_Type (void)
+{
+ ACE_TRACE ("ACE_Service_Object_Type::~ACE_Service_Object_Type");
+}
+
+int
+ACE_Service_Object_Type::suspend (void) const
+{
+ ACE_TRACE ("ACE_Service_Object_Type::suspend");
+ return static_cast<ACE_Service_Object *> (this->object ())->suspend ();
+}
+
+int
+ACE_Service_Object_Type::resume (void) const
+{
+ ACE_TRACE ("ACE_Service_Object_Type::resume");
+ return static_cast<ACE_Service_Object *> (this->object ())->resume ();
+}
+
+int
+ACE_Service_Object_Type::info (ACE_TCHAR **str, size_t len) const
+{
+ ACE_TRACE ("ACE_Service_Object_Type::info");
+ return static_cast<ACE_Service_Object *> (this->object ())->info (str, len);
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Module_Type)
+
+void
+ACE_Module_Type::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Module_Type::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Module_Type::ACE_Module_Type (void *m,
+ const ACE_TCHAR *m_name,
+ u_int f)
+ : ACE_Service_Type_Impl (m, m_name, f)
+{
+ ACE_TRACE ("ACE_Module_Type::ACE_Module_Type");
+}
+
+ACE_Module_Type::~ACE_Module_Type (void)
+{
+ ACE_TRACE ("ACE_Module_Type::~ACE_Module_Type");
+}
+
+int
+ACE_Module_Type::init (int argc, ACE_TCHAR *argv[]) const
+{
+ ACE_TRACE ("ACE_Module_Type::init");
+ void *obj = this->object ();
+ MT_Module *mod = (MT_Module *) obj;
+ MT_Task *reader = mod->reader ();
+ MT_Task *writer = mod->writer ();
+
+ if (reader->init (argc, argv) == -1
+ || writer->init (argc, argv) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_Module_Type::suspend (void) const
+{
+ ACE_TRACE ("ACE_Module_Type::suspend");
+ void *obj = this->object ();
+ MT_Module *mod = (MT_Module *) obj;
+ MT_Task *reader = mod->reader ();
+ MT_Task *writer = mod->writer ();
+
+ if (reader->suspend () == -1
+ || writer->suspend () == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_Module_Type::resume (void) const
+{
+ ACE_TRACE ("ACE_Module_Type::resume");
+ void *obj = this->object ();
+ MT_Module *mod = (MT_Module *) obj;
+ MT_Task *reader = mod->reader ();
+ MT_Task *writer = mod->writer ();
+
+ if (reader->resume () == -1
+ || writer->resume () == -1)
+ return -1;
+ else
+ return 0;
+}
+
+// Note, these operations are somewhat too familiar with the
+// implementation of ACE_Module and ACE_Module::close...
+
+int
+ACE_Module_Type::fini (void) const
+{
+ ACE_TRACE ("ACE_Module_Type::fini");
+
+ void *obj = this->object ();
+ MT_Module *mod = (MT_Module *) obj;
+ MT_Task *reader = mod->reader ();
+ MT_Task *writer = mod->writer ();
+
+ if (reader != 0)
+ reader->fini ();
+
+ if (writer != 0)
+ writer->fini ();
+
+ // Close the module and delete the memory.
+ mod->close (MT_Module::M_DELETE);
+ return ACE_Service_Type_Impl::fini ();
+}
+
+int
+ACE_Module_Type::info (ACE_TCHAR **str, size_t len) const
+{
+ ACE_TRACE ("ACE_Module_Type::info");
+ ACE_TCHAR buf[BUFSIZ];
+
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("%s\t %s"),
+ this->name (),
+ ACE_TEXT ("# ACE_Module\n"));
+
+ if (*str == 0 && (*str = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*str, buf, len);
+ return static_cast<int> (ACE_OS::strlen (buf));
+}
+
+void
+ACE_Module_Type::link (ACE_Module_Type *n)
+{
+ ACE_TRACE ("ACE_Module_Type::link");
+ this->link_ = n;
+}
+
+ACE_Module_Type *
+ACE_Module_Type::link (void) const
+{
+ ACE_TRACE ("ACE_Module_Type::link");
+ return this->link_;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Stream_Type)
+
+void
+ACE_Stream_Type::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Stream_Type::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Stream_Type::init (int, ACE_TCHAR *[]) const
+{
+ ACE_TRACE ("ACE_Stream_Type::init");
+ return 0;
+}
+
+int
+ACE_Stream_Type::suspend (void) const
+{
+ ACE_TRACE ("ACE_Stream_Type::suspend");
+
+ for (ACE_Module_Type *m = this->head_;
+ m != 0;
+ m = m->link ())
+ m->suspend ();
+
+ return 0;
+}
+
+int
+ACE_Stream_Type::resume (void) const
+{
+ ACE_TRACE ("ACE_Stream_Type::resume");
+
+ for (ACE_Module_Type *m = this->head_;
+ m != 0;
+ m = m->link ())
+ m->resume ();
+
+ return 0;
+}
+
+ACE_Stream_Type::ACE_Stream_Type (void *s,
+ const ACE_TCHAR *s_name,
+ u_int f)
+ : ACE_Service_Type_Impl (s, s_name, f),
+ head_ (0)
+{
+ ACE_TRACE ("ACE_Stream_Type::ACE_Stream_Type");
+}
+
+ACE_Stream_Type::~ACE_Stream_Type (void)
+{
+ ACE_TRACE ("ACE_Stream_Type::~ACE_Stream_Type");
+}
+
+int
+ACE_Stream_Type::info (ACE_TCHAR **str, size_t len) const
+{
+ ACE_TRACE ("ACE_Stream_Type::info");
+ ACE_TCHAR buf[BUFSIZ];
+
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("%s\t %s"),
+ this->name (),
+ ACE_TEXT ("# STREAM\n"));
+
+ if (*str == 0 && (*str = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*str, buf, len);
+ return static_cast<int> (ACE_OS::strlen (buf));
+}
+
+int
+ACE_Stream_Type::fini (void) const
+{
+ ACE_TRACE ("ACE_Stream_Type::fini");
+ void *obj = this->object ();
+ MT_Stream *str = (MT_Stream *) obj;
+
+ for (ACE_Module_Type *m = this->head_; m != 0; )
+ {
+ ACE_Module_Type *t = m->link ();
+
+ // Final arg is an indication to *not* delete the Module.
+ str->remove (m->name (),
+ MT_Module::M_DELETE_NONE);
+
+ // Finalize the Module (this may delete it, but we don't really
+ // care since we don't access it again).
+ m->fini ();
+ m = t;
+ }
+
+ str->close ();
+ return ACE_Service_Type_Impl::fini ();
+}
+
+// Locate and remove <mod_name> from the ACE_Stream.
+
+int
+ACE_Stream_Type::remove (ACE_Module_Type *mod)
+{
+ ACE_TRACE ("ACE_Stream_Type::remove");
+
+ ACE_Module_Type *prev = 0;
+ void *obj = this->object ();
+ MT_Stream *str = (MT_Stream *) obj;
+ int result = 0;
+
+ for (ACE_Module_Type *m = this->head_; m != 0; )
+ {
+ // We need to do this first so we don't bomb out if we delete m!
+ ACE_Module_Type *link = m->link ();
+
+ if (m == mod)
+ {
+ if (prev == 0)
+ this->head_ = link;
+ else
+ prev->link (link);
+
+ // Final arg is an indication to *not* delete the Module.
+ if (str->remove (m->name (),
+ MT_Module::M_DELETE_NONE) == -1)
+ result = -1;
+
+ // This call may end up deleting m, which is ok since we
+ // don't access it again!
+ m->fini ();
+ }
+ else
+ prev = m;
+
+ m = link;
+ }
+
+ return result;
+}
+
+int
+ACE_Stream_Type::push (ACE_Module_Type *new_module)
+{
+ ACE_TRACE ("ACE_Stream_Type::push");
+ void *obj = this->object ();
+ MT_Stream *str = (MT_Stream *) obj;
+
+ new_module->link (this->head_);
+ this->head_ = new_module;
+ obj = new_module->object ();
+ return str->push ((MT_Module *) obj);
+}
+
+ACE_Module_Type *
+ACE_Stream_Type::find (const ACE_TCHAR *mod_name) const
+{
+ ACE_TRACE ("ACE_Stream_Type::find");
+
+ for (ACE_Module_Type *m = this->head_;
+ m != 0;
+ m = m->link ())
+ if (ACE_OS::strcmp (m->name (), mod_name) == 0)
+ return m;
+
+ return 0;
+}
+
+// @@@ Eliminated ommented out explicit template instantiation code
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Service_Types.h b/ACE/ace/Service_Types.h
new file mode 100644
index 00000000000..fccf76b5f02
--- /dev/null
+++ b/ACE/ace/Service_Types.h
@@ -0,0 +1,206 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Service_Types.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_SERVICE_TYPE_H
+#define ACE_SERVICE_TYPE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Service_Object.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Service_Type_Impl
+ *
+ * @brief The abstract base class of the hierarchy that defines the
+ * contents of the ACE_Service_Repository. The subclasses of
+ * this class allow the configuration of ACE_Service_Objects,
+ * ACE_Modules, and ACE_Streams.
+ *
+ * This class provides the root of the implementation hierarchy
+ * of the "Bridge" pattern. It maintains a pointer to the
+ * appropriate type of service implementation, i.e.,
+ * ACE_Service_Object, ACE_Module, or ACE_Stream.
+ */
+class ACE_Export ACE_Service_Type_Impl
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Service_Type_Impl (void *object,
+ const ACE_TCHAR *s_name,
+ u_int flags = 0,
+ ACE_Service_Object_Exterminator gobbler = 0);
+ virtual ~ACE_Service_Type_Impl (void);
+
+ // = Pure virtual interface (must be defined by the subclass).
+ virtual int suspend (void) const = 0;
+ virtual int resume (void) const = 0;
+ virtual int init (int argc, ACE_TCHAR *argv[]) const = 0;
+ virtual int fini (void) const;
+ virtual int info (ACE_TCHAR **str, size_t len) const = 0;
+
+ /// The pointer to the service.
+ void *object (void) const;
+
+ /// Get the name of the service.
+ const ACE_TCHAR *name (void) const;
+
+ /// Set the name of the service.
+ void name (const ACE_TCHAR *);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Name of the service.
+ const ACE_TCHAR *name_;
+
+ /// Pointer to object that implements the service. This actually
+ /// points to an ACE_Service_Object, ACE_Module, or ACE_Stream.
+ void *obj_;
+
+ /// Destroy function to deallocate obj_.
+ ACE_Service_Object_Exterminator gobbler_;
+
+ /// Flags that control serivce behavior (particularly deletion).
+ u_int flags_;
+};
+
+/**
+ * @class ACE_Service_Object_Type
+ *
+ * @brief Define the methods for handling the configuration of
+ * ACE_Service_Objects.
+ */
+class ACE_Export ACE_Service_Object_Type : public ACE_Service_Type_Impl
+{
+public:
+ // = Initialization method.
+ ACE_Service_Object_Type (void *so,
+ const ACE_TCHAR *name,
+ u_int flags = 0,
+ ACE_Service_Object_Exterminator gobbler = 0);
+
+ ~ACE_Service_Object_Type (void);
+
+ // = Implement the hooks for <ACE_Service_Objects>.
+ virtual int suspend (void) const;
+ virtual int resume (void) const;
+ virtual int init (int argc, ACE_TCHAR *argv[]) const;
+ virtual int fini (void) const;
+ virtual int info (ACE_TCHAR **str, size_t len) const;
+
+private:
+ /// Holds the initialization status (result of object->init())
+ mutable int initialized_;
+};
+
+/**
+ * @class ACE_Module_Type
+ *
+ * @brief Define the methods for handling the configuration of
+ * ACE_Modules.
+ */
+class ACE_Export ACE_Module_Type : public ACE_Service_Type_Impl
+{
+public:
+ // = Initialization method.
+ ACE_Module_Type (void *m, // Really an ACE_Module *.
+ const ACE_TCHAR *identifier,
+ u_int flags = 0);
+
+ ~ACE_Module_Type (void);
+
+ // = Implement the hooks for <ACE_Modules>.
+ virtual int suspend (void) const;
+ virtual int resume (void) const;
+ virtual int init (int argc, ACE_TCHAR *argv[]) const;
+ virtual int fini (void) const;
+ virtual int info (ACE_TCHAR **str, size_t len) const;
+
+ /// Get the link pointer.
+ ACE_Module_Type *link (void) const;
+
+ /// Set the link pointer.
+ void link (ACE_Module_Type *);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to the next ACE_Module_Type in an ACE_Stream_Type.
+ ACE_Module_Type *link_;
+};
+
+/**
+ * @class ACE_Stream_Type
+ *
+ * @brief Define the methods for handling the configuration of
+ * ACE_Streams.
+ */
+class ACE_Export ACE_Stream_Type : public ACE_Service_Type_Impl
+{
+public:
+ // = Initialization method.
+ ACE_Stream_Type (void *s, // Really an ACE_Stream *.
+ const ACE_TCHAR *identifier,
+ u_int flags = 0);
+
+ ~ACE_Stream_Type (void);
+
+ // = Implement the hooks for <ACE_Streams>.
+ virtual int suspend (void) const;
+ virtual int resume (void) const;
+ virtual int init (int argc, ACE_TCHAR *argv[]) const;
+ virtual int fini (void) const;
+ virtual int info (ACE_TCHAR **str, size_t len) const;
+
+ /// Add a new ACE_Module to the top of the ACE_Stream.
+ int push (ACE_Module_Type *new_module);
+
+ /// Search for @a module and remove it from the ACE_Stream.
+ int remove (ACE_Module_Type *module);
+
+ /// Locate the ACE_Module with @a mod_name.
+ ACE_Module_Type *find (const ACE_TCHAR *mod_name) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to the head of the ACE_Module list.
+ ACE_Module_Type *head_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Service_Types.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* _SERVICE_TYPE_H */
diff --git a/ACE/ace/Service_Types.inl b/ACE/ace/Service_Types.inl
new file mode 100644
index 00000000000..9ebfd705ced
--- /dev/null
+++ b/ACE/ace/Service_Types.inl
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/ACE.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE void *
+ACE_Service_Type_Impl::object (void) const
+{
+ ACE_TRACE ("ACE_Service_Type_Impl::object");
+ return this->obj_;
+}
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Service_Type_Impl::name (void) const
+{
+ ACE_TRACE ("ACE_Service_Type_Impl::name");
+ return this->name_;
+}
+
+ACE_INLINE void
+ACE_Service_Type_Impl::name (const ACE_TCHAR *n)
+{
+ ACE_TRACE ("ACE_Service_Type_Impl::name");
+
+ ACE::strdelete (const_cast<ACE_TCHAR*> (this->name_));
+ this->name_ = ACE::strnew (n);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Shared_Memory.cpp b/ACE/ace/Shared_Memory.cpp
new file mode 100644
index 00000000000..90a9a7ed93e
--- /dev/null
+++ b/ACE/ace/Shared_Memory.cpp
@@ -0,0 +1,13 @@
+// $Id$
+
+#include "ace/Shared_Memory.h"
+
+ACE_RCSID(ace, Shared_Memory, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Shared_Memory::~ACE_Shared_Memory (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Shared_Memory.h b/ACE/ace/Shared_Memory.h
new file mode 100644
index 00000000000..9fc64a23036
--- /dev/null
+++ b/ACE/ace/Shared_Memory.h
@@ -0,0 +1,58 @@
+// -*- 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_export.h"
+
+#include "ace/os_include/os_stddef.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 size_t get_segment_size (void) const = 0;
+ virtual ACE_HANDLE get_id (void) const = 0;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SHARED_MEMORY_H */
diff --git a/ACE/ace/Shared_Memory_MM.cpp b/ACE/ace/Shared_Memory_MM.cpp
new file mode 100644
index 00000000000..ae3285939d1
--- /dev/null
+++ b/ACE/ace/Shared_Memory_MM.cpp
@@ -0,0 +1,111 @@
+// $Id$
+
+#include "ace/Shared_Memory_MM.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Shared_Memory_MM.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Shared_Memory_MM,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_MM)
+
+void
+ACE_Shared_Memory_MM::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Shared_Memory_MM::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+// Creates a shared memory segment of SIZE bytes.
+
+ACE_Shared_Memory_MM::ACE_Shared_Memory_MM (ACE_HANDLE handle,
+ size_t length,
+ int prot,
+ int share,
+ char *addr,
+ ACE_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,
+ size_t len,
+ int flags,
+ int mode,
+ int prot,
+ int share,
+ char *addr,
+ ACE_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");
+}
+
+// The overall size of the segment.
+
+size_t
+ACE_Shared_Memory_MM::get_segment_size (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::get_segment_size");
+ // This cast is legit since the original length in open() is an int.
+ return this->shared_memory_.size ();
+}
+
+// Unmaps the shared memory segment.
+
+int
+ACE_Shared_Memory_MM::remove (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::remove");
+ return shared_memory_.remove ();
+}
+
+// Closes (unmaps) the shared memory segment.
+
+int
+ACE_Shared_Memory_MM::close (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::close");
+ return shared_memory_.unmap ();
+}
+
+void *
+ACE_Shared_Memory_MM::malloc (size_t)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::malloc");
+ void *addr = 0;
+
+ return this->shared_memory_ (addr) == -1 ? 0 : addr;
+}
+
+ACE_HANDLE
+ACE_Shared_Memory_MM::get_id (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::get_id");
+ return this->shared_memory_.handle ();
+}
+
+int
+ACE_Shared_Memory_MM::free (void *p)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::free");
+ return p != 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Shared_Memory_MM.h b/ACE/ace/Shared_Memory_MM.h
new file mode 100644
index 00000000000..e23ac00cdbf
--- /dev/null
+++ b/ACE/ace/Shared_Memory_MM.h
@@ -0,0 +1,120 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Shared_Memory_MM.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#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"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Shared_Memory_MM
+ *
+ * @brief Shared memory wrapper based on MMAP.
+ *
+ * This class provides a very simple-minded shared memory manager. We
+ * strongly recommend that you do NOT use this class. Instead, please
+ * use @c ACE_Malloc, which has much more powerful capabilities.
+ */
+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,
+ size_t length = static_cast<size_t> (-1),
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ char *addr = 0,
+ ACE_OFF_T pos = 0);
+
+ /// Constructor.
+ ACE_Shared_Memory_MM (const ACE_TCHAR *file_name,
+ size_t length = static_cast<size_t> (-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, ACE_OFF_T pos = 0);
+
+ /// Open method.
+ int open (ACE_HANDLE handle,
+ size_t length = static_cast<size_t> (-1),
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ char *addr = 0,
+ ACE_OFF_T pos = 0);
+
+ /// Open method.
+ int open (const ACE_TCHAR *file_name,
+ size_t length = static_cast<size_t> (-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,
+ ACE_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 @a 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 size_t 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Shared_Memory_MM.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SHARED_MALLOC_MM_H */
diff --git a/ACE/ace/Shared_Memory_MM.inl b/ACE/ace/Shared_Memory_MM.inl
new file mode 100644
index 00000000000..4f6890d9270
--- /dev/null
+++ b/ACE/ace/Shared_Memory_MM.inl
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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,
+ size_t length,
+ int prot,
+ int share,
+ char *addr,
+ ACE_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,
+ size_t len,
+ int flags,
+ int mode,
+ int prot,
+ int share,
+ char *addr,
+ ACE_OFF_T pos)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::open");
+ return shared_memory_.map (file_name, len, flags, mode,
+ prot, share, addr, pos);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Shared_Memory_Pool.cpp b/ACE/ace/Shared_Memory_Pool.cpp
new file mode 100644
index 00000000000..44c346ea389
--- /dev/null
+++ b/ACE/ace/Shared_Memory_Pool.cpp
@@ -0,0 +1,461 @@
+// $Id$
+
+// Shared_Memory_Pool.cpp
+#include "ace/Shared_Memory_Pool.h"
+#include "ace/OS_NS_sys_shm.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Shared_Memory_Pool, "$Id$")
+
+#if !defined (ACE_LACKS_SYSV_SHMEM)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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,
+ ACE_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");
+}
+
+void
+ACE_Shared_Memory_Pool::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Shared_Memory_Pool::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Shared_Memory_Pool::in_use (ACE_OFF_T &offset,
+ size_t &counter)
+{
+ offset = 0;
+ SHM_TABLE *st = 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_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("shmctl")),
+ -1);
+ offset += buf.shm_segsz;
+ // ACE_DEBUG ((LM_DEBUG, ACE_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,
+ ACE_OFF_T &offset,
+ size_t &counter)
+{
+ offset = 0;
+ SHM_TABLE *st = 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_TEXT ("(%P|%t) %p\n"),
+ ACE_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 (((ptrdiff_t) offset + (ptrdiff_t) (this->base_addr_)) > (ptrdiff_t) searchPtr)
+ {
+ --counter;
+ offset -= buf.shm_segsz;
+ return 0;
+ }
+ // ACE_DEBUG ((LM_DEBUG, ACE_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,
+ ACE_OFF_T &offset)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::commit_backing_store_name");
+
+ size_t counter;
+ SHM_TABLE *st = 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_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("shmget")),
+ -1);
+ 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),
+ -1);
+ }
+ 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_TEXT ("signal %S occurred\n"), signum));
+
+ // While FreeBSD 5.X has a siginfo_t struct with a si_addr field,
+ // it does not define SEGV_MAPERR.
+#if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR) && \
+ (defined (SEGV_MAPERR) || defined (SEGV_MEMERR))
+ ACE_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_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_TEXT ("(%P|%t) %p\n"),
+ ACE_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_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("in_use")),
+ -1);
+
+ void *address = (void *) (((char *) this->base_addr_) + offset);
+ SHM_TABLE *st = 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),
+ -1);
+
+ // 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_ =
+ reinterpret_cast<void *> (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 (ACE_TEXT_ALWAYS_CHAR (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 (ACE_TEXT_ALWAYS_CHAR (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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Sig_Handler::register_handler")));
+}
+
+ACE_Shared_Memory_Pool::~ACE_Shared_Memory_Pool (void)
+{
+}
+
+// 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_TEXT ("(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes));
+
+ ACE_OFF_T offset;
+
+ if (this->commit_backing_store_name (rounded_bytes, offset) == -1)
+ return 0;
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_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");
+
+ ACE_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_TEXT ("(%P|%t) %p\n"),
+ ACE_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_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("shmget")),
+ 0);
+
+ // This implementation doesn't care if we don't get the key we
+ // want...
+ this->base_addr_ =
+ ACE_OS::shmat (shmid,
+ reinterpret_cast<char *> (this->base_addr_),
+ 0);
+ if (this->base_addr_ == 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,
+ reinterpret_cast<char *> (this->base_addr_),
+ 0);
+ if (this->base_addr_ == reinterpret_cast<char *> (-1))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p, base_addr = %u\n",
+ "shmat",
+ this->base_addr_), 0);
+
+ SHM_TABLE *st = 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 (int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::release");
+
+ int result = 0;
+ SHM_TABLE *st = 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;
+}
+
+int
+ACE_Shared_Memory_Pool::sync (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::sync");
+ return 0;
+}
+
+int
+ACE_Shared_Memory_Pool::sync (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::sync");
+ return 0;
+}
+
+int
+ACE_Shared_Memory_Pool::protect (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::protect");
+ return 0;
+}
+
+int
+ACE_Shared_Memory_Pool::protect (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::protect");
+ return 0;
+}
+
+void *
+ACE_Shared_Memory_Pool::base_addr (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::base_addr");
+ return this->base_addr_;
+}
+
+// Implement the algorithm for rounding up the request to an
+// appropriate chunksize.
+
+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_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_LACKS_SYSV_SHMEM */
diff --git a/ACE/ace/Shared_Memory_Pool.h b/ACE/ace/Shared_Memory_Pool.h
new file mode 100644
index 00000000000..27c113b1c0f
--- /dev/null
+++ b/ACE/ace/Shared_Memory_Pool.h
@@ -0,0 +1,210 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Shared_Memory_Pool.h
+ *
+ * $Id$
+ *
+ * @author Dougls C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SHARED_MEMORY_POOL_H
+#define ACE_SHARED_MEMORY_POOL_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_SYSV_SHMEM)
+
+#include "ace/ACE.h"
+#include "ace/Event_Handler.h"
+#include "ace/Sig_Handler.h"
+#include "ace/os_include/sys/os_mman.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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,
+ ACE_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.
+ ACE_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 @a nbytes from the memory pool. @a rounded_byes 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 (int destroy = 1);
+
+ /// Sync the memory region to the backing store starting at
+ /// @c this->base_addr_.
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync the memory region to the backing store starting at @a addr.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to @a prot
+ * starting at @c this->base_addr_ up to @a len bytes. If @a 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 @a prot
+ /// starting at @a addr up to @a len bytes.
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
+
+ /// Return the base address of this memory pool, 0 if base_addr
+ /// never changes.
+ 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);
+
+ /**
+ * Commits a new shared memory segment if necessary after an
+ * <acquire> or a signal. @a offset is set to the new offset into
+ * the backing store.
+ */
+ virtual int commit_backing_store_name (size_t rounded_bytes,
+ ACE_OFF_T &offset);
+
+ /// Keeps track of all the segments being used.
+ struct SHM_TABLE
+ {
+ /// Shared memory segment key.
+ key_t key_;
+
+ /// Shared memory segment internal id.
+ int shmid_;
+
+ /// Is the segment currently used.;
+ int 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.
+ ACE_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 @a searchPtr
+ virtual int find_seg (const void *const searchPtr,
+ ACE_OFF_T &offset,
+ size_t &counter);
+
+ /// Determine how much memory is currently in use.
+ virtual int in_use (ACE_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 *);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* !ACE_LACKS_SYSV_SHMEM */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SHARED_MEMORY_POOL_H */
diff --git a/ACE/ace/Shared_Memory_SV.cpp b/ACE/ace/Shared_Memory_SV.cpp
new file mode 100644
index 00000000000..e16b181408e
--- /dev/null
+++ b/ACE/ace/Shared_Memory_SV.cpp
@@ -0,0 +1,88 @@
+// $Id$
+
+#include "ace/Shared_Memory_SV.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Shared_Memory_SV.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Shared_Memory_SV,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_SV)
+
+void
+ACE_Shared_Memory_SV::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Shared_Memory_SV::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Shared_Memory_SV::ACE_Shared_Memory_SV (key_t id,
+ size_t 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");
+}
+
+// The overall size of the segment.
+
+size_t
+ACE_Shared_Memory_SV::get_segment_size (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::get_segment_size");
+ // This cast is ok since the 'open' method for this class allows only
+ // an 'int' size. Therefore, this case should not lose information.
+ return this->shared_memory_.get_segment_size ();
+}
+
+// Removes the shared memory segment.
+
+int
+ACE_Shared_Memory_SV::remove (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::remove");
+ return shared_memory_.remove ();
+}
+
+// Closes (detaches) the shared memory segment.
+
+int
+ACE_Shared_Memory_SV::close (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::close");
+ return shared_memory_.detach ();
+}
+
+void *
+ACE_Shared_Memory_SV::malloc (size_t)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::malloc");
+ return this->shared_memory_.get_segment_ptr ();
+}
+
+ACE_HANDLE
+ACE_Shared_Memory_SV::get_id (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::get_id");
+ return this->shared_memory_.get_id ();
+}
+
+int
+ACE_Shared_Memory_SV::free (void *p)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::free");
+ return p != 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Shared_Memory_SV.h b/ACE/ace/Shared_Memory_SV.h
new file mode 100644
index 00000000000..517d72c33dc
--- /dev/null
+++ b/ACE/ace/Shared_Memory_SV.h
@@ -0,0 +1,101 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Shared_Memory_SV.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#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"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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. We
+ * strongly recommend that you do NOT use this class. Instead, please
+ * use @c ACE_Malloc, which has much more powerful capabilities.
+ */
+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,
+ size_t 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,
+ size_t 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 @a 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 size_t 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Shared_Memory_SV.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SHARED_MALLOC_SV_H */
diff --git a/ACE/ace/Shared_Memory_SV.inl b/ACE/ace/Shared_Memory_SV.inl
new file mode 100644
index 00000000000..71f417f8848
--- /dev/null
+++ b/ACE/ace/Shared_Memory_SV.inl
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Shared_Memory_SV::open (key_t id,
+ size_t 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 "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_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Shared_Object.cpp b/ACE/ace/Shared_Object.cpp
new file mode 100644
index 00000000000..ca2d554035c
--- /dev/null
+++ b/ACE/ace/Shared_Object.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+#include "ace/Shared_Object.h"
+#include "ace/Global_Macros.h"
+#include "ace/config-all.h"
+
+/* Provide the abstract base class used to access dynamic linking
+ facilities */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Shared_Object.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Shared_Object,
+ "$Id$")
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Initializes object when dynamic linking occurs.
+
+int
+ACE_Shared_Object::init (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("ACE_Shared_Object::init");
+ return 0;
+}
+
+// Terminates object when dynamic unlinking occurs.
+
+int
+ACE_Shared_Object::fini (void)
+{
+ ACE_TRACE ("ACE_Shared_Object::fini");
+ return 0;
+}
+
+// Returns information on active object.
+
+int
+ACE_Shared_Object::info (ACE_TCHAR **, size_t) const
+{
+ ACE_TRACE ("ACE_Shared_Object::info");
+ return 0;
+}
+
+// Need to give a default implementation.
+
+ACE_Shared_Object::~ACE_Shared_Object (void)
+{
+ ACE_TRACE ("ACE_Shared_Object::~ACE_Shared_Object");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Shared_Object.h b/ACE/ace/Shared_Object.h
new file mode 100644
index 00000000000..a1d25f0f7bb
--- /dev/null
+++ b/ACE/ace/Shared_Object.h
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Shared_Object.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_SHARED_OBJECT_H
+#define ACE_SHARED_OBJECT_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Shared_Object
+ *
+ * @brief Provide the abstract base class used to access dynamic
+ * linking facilities.
+ */
+class ACE_Export ACE_Shared_Object
+{
+public:
+ ACE_Shared_Object (void);
+
+ /// Initializes object when dynamic linking occurs.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ /// Terminates object when dynamic unlinking occurs.
+ virtual int fini (void);
+
+ /// Returns information on a service object.
+ virtual int info (ACE_TCHAR **info_string, size_t length = 0) const;
+
+ virtual ~ACE_Shared_Object (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Shared_Object.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SHARED_OBJECT_H */
diff --git a/ACE/ace/Shared_Object.inl b/ACE/ace/Shared_Object.inl
new file mode 100644
index 00000000000..cd76cb6a267
--- /dev/null
+++ b/ACE/ace/Shared_Object.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Shared_Object::ACE_Shared_Object (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Sig_Adapter.cpp b/ACE/ace/Sig_Adapter.cpp
new file mode 100644
index 00000000000..24788efa0cc
--- /dev/null
+++ b/ACE/ace/Sig_Adapter.cpp
@@ -0,0 +1,80 @@
+// $Id$
+
+#include "ace/Sig_Adapter.h"
+
+ACE_RCSID(ace, Sig_Adapter, "$Id$")
+
+
+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");
+}
+
+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;
+}
diff --git a/ACE/ace/Sig_Adapter.h b/ACE/ace/Sig_Adapter.h
new file mode 100644
index 00000000000..5e8369b2ad8
--- /dev/null
+++ b/ACE/ace/Sig_Adapter.h
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Sig_Adapter.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SIG_ADAPTER_H
+#define ACE_SIG_ADAPTER_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event_Handler.h"
+#include "ace/Signal.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SIG_ADAPTER_H */
diff --git a/ACE/ace/Sig_Handler.cpp b/ACE/ace/Sig_Handler.cpp
new file mode 100644
index 00000000000..37d8de90bc6
--- /dev/null
+++ b/ACE/ace/Sig_Handler.cpp
@@ -0,0 +1,614 @@
+// $Id$
+
+#include "ace/Sig_Handler.h"
+#include "ace/Sig_Adapter.h"
+#include "ace/Signal.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Managed_Object.h"
+#include "ace/Containers.h"
+#include "ace/Guard_T.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Sig_Handler.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Sig_Handler, "$Id$")
+
+#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)
+
+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)
+
+#else
+#define ace_signal_handler_dispatcher ACE_SignalHandler(ACE_Sig_Handler::dispatch)
+
+#define ace_signal_handlers_dispatcher ACE_SignalHandler(ACE_Sig_Handlers::dispatch)
+#endif /* ACE_HAS_SIG_C_FUNC */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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_Handler)
+
+ACE_Sig_Handler::~ACE_Sig_Handler (void)
+{
+}
+
+void
+ACE_Sig_Handler::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Sig_Handler::dump");
+#endif /* ACE_HAS_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);
+ }
+
+ 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 ((ACE_SignalHandler) 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*/
+ }
+}
+
+// ----------------------------------------
+// The following classes are local to this file.
+
+// There are bugs with HP/UX's C++ compiler that prevents this stuff
+// from compiling...
+#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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Sig_Handlers::dump");
+#endif /* ACE_HAS_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 ();
+ }
+ }
+
+ 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 = 0;
+
+ ACE_NEW_RETURN (temp,
+ ACE_Sig_Adapter (new_sh,
+ ++ACE_Sig_Handlers::sigkey_),
+ 0);
+ handler_set->insert (temp);
+ return *eh;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Sig_Handler.h b/ACE/ace/Sig_Handler.h
new file mode 100644
index 00000000000..0d99bf81341
--- /dev/null
+++ b/ACE/ace/Sig_Handler.h
@@ -0,0 +1,236 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Sig_Handler.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SIGNAL_HANDLER_H
+#define ACE_SIGNAL_HANDLER_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event_Handler.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Sig_Action;
+
+/**
+ * @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
+ * @a signum. When a signal occurs that corresponds to this
+ * @a signum, the @c handle_signal method of the registered
+ * ACE_Event_Handler is invoked automatically.
+ */
+class ACE_Export ACE_Sig_Handler
+{
+public:
+ /// Default ctor/dtor.
+ ACE_Sig_Handler (void);
+ virtual ~ACE_Sig_Handler (void);
+
+ // = Registration and removal methods.
+ /**
+ * Add a new ACE_Event_Handler and a new sigaction associated with
+ * @a 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
+ * @a signum. @a 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 @a 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 @a signum.
+ virtual ACE_Event_Handler *handler (int signum);
+
+ /// Set a new ACE_Event_Handler that is associated with @a 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 @a 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
+ * @c dispatch. It doesn't do any locking so that it can be called
+ * within a signal handler, such as @c dispatch. It adds a new
+ * ACE_Event_Handler and a new sigaction associated with @a 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_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 @a signum. When a signal occurs that
+ * corresponds to this @a 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
+ * @a 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 @a signum.
+ * We remove the handler if (1) its sigkey> matches the @a 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 @a 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 @a 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Sig_Handler.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SIG_HANDLER_H */
diff --git a/ACE/ace/Sig_Handler.inl b/ACE/ace/Sig_Handler.inl
new file mode 100644
index 00000000000..89427780d98
--- /dev/null
+++ b/ACE/ace/Sig_Handler.inl
@@ -0,0 +1,15 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_INLINE
+ACE_Sig_Handler::ACE_Sig_Handler (void)
+{
+}
+
+ACE_INLINE int
+ACE_Sig_Handler::in_range (int signum)
+{
+ ACE_TRACE ("ACE_Sig_Handler::in_range");
+ return signum > 0 && signum < ACE_NSIG;
+}
diff --git a/ACE/ace/Signal.cpp b/ACE/ace/Signal.cpp
new file mode 100644
index 00000000000..4148f33a959
--- /dev/null
+++ b/ACE/ace/Signal.cpp
@@ -0,0 +1,221 @@
+// $Id$
+
+#include "ace/Signal.h"
+// #include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Signal.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Signal, "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Action)
+
+void
+ACE_Sig_Action::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Sig_Action::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Set)
+
+ACE_Sig_Set::~ACE_Sig_Set (void)
+{
+ ACE_TRACE ("ACE_Sig_Set::~ACE_Sig_Set");
+ ACE_OS::sigemptyset (&this->sigset_);
+}
+
+ACE_Sig_Action::~ACE_Sig_Action (void)
+{
+ ACE_TRACE ("ACE_Sig_Action::~ACE_Sig_Action");
+}
+
+// Restore the signal mask.
+
+ACE_Sig_Guard::~ACE_Sig_Guard (void)
+{
+ //ACE_TRACE ("ACE_Sig_Guard::~ACE_Sig_Guard");
+ if (!this->condition_)
+ return;
+
+#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 */
+}
+
+void
+ACE_Sig_Set::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Sig_Set::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Guard)
+
+void
+ACE_Sig_Guard::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Sig_Guard::dump");
+#endif /* ACE_HAS_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)
+ for (int s = 1; s < ACE_NSIG; s++)
+ if ((signals.is_member (s)) == 1)
+ ACE_OS::sigaction (s, &this->sa_, 0);
+#else /* ACE_NSIG <= 0 */
+ ACE_UNUSED_ARG (signals);
+#endif /* ACE_NSIG <= 0 */
+}
+
+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)
+ for (int s = 1; s < ACE_NSIG; s++)
+ if ((signals.is_member (s)) == 1)
+ ACE_OS::sigaction (s, &this->sa_, 0);
+#else /* ACE_NSIG <= 0 */
+ ACE_UNUSED_ARG (signals);
+#endif /* ACE_NSIG <= 0 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Signal.h b/ACE/ace/Signal.h
new file mode 100644
index 00000000000..fd82d3a7247
--- /dev/null
+++ b/ACE/ace/Signal.h
@@ -0,0 +1,267 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Signal.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SIGNAL_H
+#define ACE_SIGNAL_H
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if defined (ACE_DONT_INCLUDE_ACE_SIGNAL_H)
+# error ace/Signal.h was #included instead of signal.h by ace/OS_NS_signal.h: fix!!!!
+#endif /* ACE_DONT_INCLUDE_ACE_SIGNAL_H */
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_signal.h"
+
+// Type of the extended signal handler.
+typedef void (*ACE_Sig_Handler_Ex) (int, siginfo_t *siginfo, ucontext_t *ucontext);
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a sigset. If @a sigset == 0 then fill
+ /// the set.
+ ACE_Sig_Set (sigset_t *sigset);
+
+ /// Initialize <sigset_> with @a sigset. If @a sigset == 0 then fill
+ /// the set.
+ ACE_Sig_Set (ACE_Sig_Set *sigset);
+
+ /// If @a 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 @a signo to the set.
+ int sig_add (int signo);
+
+ /// Deletes the individual signal specified by @a signo from the set.
+ int sig_del (int signo);
+
+ /// Checks whether the signal specified by @a signo is in the set.
+ int is_member (int signo) const;
+
+ /// Returns a pointer to the underlying @c sigset_t.
+ operator sigset_t *();
+
+ /// Returns a copy of the underlying @c 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 @c 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 @c sigaction struct but doesn't
+ /// register for signal handling via the @c sigaction function.
+ ACE_Sig_Action (ACE_SignalHandler handler,
+ sigset_t *sigmask = 0,
+ int flags = 0);
+
+ /// Assigns the various fields of a @c sigaction struct but doesn't
+ /// register for signal handling via the @c sigaction function.
+ ACE_Sig_Action (ACE_SignalHandler handler,
+ const ACE_Sig_Set &sigmask,
+ int flags = 0);
+
+ /**
+ * Assigns the various fields of a @c sigaction struct and registers
+ * the @a handler to process signal @a signum via the @c sigaction
+ * function.
+ */
+ ACE_Sig_Action (ACE_SignalHandler handler,
+ int signum,
+ sigset_t *sigmask = 0,
+ int flags = 0);
+
+ /**
+ * Assigns the various fields of a @c sigaction struct and registers
+ * the @a handler to process signal @a signum via the @c 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 @c sigaction struct and registers
+ * the @a handler to process all @a signalss via the @c 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 @c sigaction struct and registers
+ * the @a handler to process all @a signalss via the @c 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 @c this as the current disposition and store old
+ /// disposition into @a oaction if it is non-NULL.
+ int register_action (int signum,
+ ACE_Sig_Action *oaction = 0);
+
+ /// Assign the value of @a oaction to @c this and make it become the
+ /// new signal disposition.
+ int restore_action (int signum,
+ ACE_Sig_Action &oaction);
+
+ /// Retrieve the current disposition into @c this.
+ int retrieve_action (int signum);
+
+ /// Set current signal action.
+ void set (struct sigaction *);
+
+ /// Get current signal action.
+ struct sigaction *get (void);
+ operator struct sigaction *();
+
+ /// Set current signal flags.
+ void flags (int);
+
+ /// Get current signal flags.
+ int flags (void);
+
+ /// Set current signal mask.
+ void mask (sigset_t *);
+ void mask (ACE_Sig_Set &);
+
+ /// Get current signal mask.
+ sigset_t *mask (void);
+
+ /// Set current signal handler (pointer to function).
+ void handler (ACE_SignalHandler);
+
+ /// Get current signal handler (pointer to function).
+ 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.
+ /// This is kind of conditional Guard, needed when guard should be
+ /// activated only when a spcific condition met. When condition ==
+ /// true (default), Guard is activated
+ ACE_Sig_Guard (ACE_Sig_Set *mask = 0, bool condition = true);
+
+ /// 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_;
+
+ /// Guard Condition
+ bool condition_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Signal.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SIGNAL_HANDLER_H */
diff --git a/ACE/ace/Signal.inl b/ACE/ace/Signal.inl
new file mode 100644
index 00000000000..04ecfbfb49f
--- /dev/null
+++ b/ACE/ace/Signal.inl
@@ -0,0 +1,265 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_signal.h"
+#include "ace/config-all.h"
+#include "ace/Trace.h"
+#include "ace/Object_Manager_Base.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 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 (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 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 struct sigaction * ()
+{
+ ACE_TRACE ("ACE_Sig_Action::operator struct 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,
+ bool condition)
+ : omask_ ()
+ , condition_ (condition)
+{
+ //ACE_TRACE ("ACE_Sig_Guard::ACE_Sig_Guard");
+ if (!this->condition_)
+ return;
+
+#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 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Singleton.cpp b/ACE/ace/Singleton.cpp
new file mode 100644
index 00000000000..b59213eaf1b
--- /dev/null
+++ b/ACE/ace/Singleton.cpp
@@ -0,0 +1,534 @@
+// $Id$
+
+#ifndef ACE_SINGLETON_CPP
+#define ACE_SINGLETON_CPP
+
+#include "ace/Singleton.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Singleton.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+#include "ace/Framework_Component.h"
+#include "ace/Guard_T.h"
+
+ACE_RCSID (ace,
+ Singleton,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TYPE, class ACE_LOCK> void
+ACE_Singleton<TYPE, ACE_LOCK>::dump (void)
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Singleton<TYPE, ACE_LOCK>::dump");
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("instance_ = %x"),
+ ACE_Singleton<TYPE, ACE_LOCK>::instance_i ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class TYPE, class ACE_LOCK> ACE_Singleton<TYPE, ACE_LOCK> *&
+ACE_Singleton<TYPE, ACE_LOCK>::instance_i (void)
+{
+#if defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ // Pointer to the Singleton instance. This works around a bug with
+ // G++ and it's (mis-)handling of templates and statics...
+ static ACE_Singleton<TYPE, ACE_LOCK> *singleton_ = 0;
+
+ return singleton_;
+#else
+ return ACE_Singleton<TYPE, ACE_LOCK>::singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+}
+
+template <class TYPE, class ACE_LOCK> TYPE *
+ACE_Singleton<TYPE, ACE_LOCK>::instance (void)
+{
+ ACE_TRACE ("ACE_Singleton<TYPE, ACE_LOCK>::instance");
+
+ ACE_Singleton<TYPE, ACE_LOCK> *&singleton =
+ ACE_Singleton<TYPE, ACE_LOCK>::instance_i ();
+
+ // Perform the Double-Check pattern...
+ if (singleton == 0)
+ {
+ if (ACE_Object_Manager::starting_up () ||
+ ACE_Object_Manager::shutting_down ())
+ {
+ // The program is still starting up, and therefore assumed
+ // to be single threaded. There's no need to double-check.
+ // Or, the ACE_Object_Manager instance has been destroyed,
+ // so the preallocated lock is not available. Either way,
+ // don't register for destruction with the
+ // ACE_Object_Manager: we'll have to leak this instance.
+
+ ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0);
+ }
+ else
+ {
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ // Obtain a lock from the ACE_Object_Manager. The pointer
+ // is static, so we only obtain one per ACE_Singleton
+ // instantiation.
+ static ACE_LOCK *lock = 0;
+ if (ACE_Object_Manager::get_singleton_lock (lock) != 0)
+ // Failed to acquire the lock!
+ return 0;
+
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0);
+
+ if (singleton == 0)
+ {
+#endif /* ACE_MT_SAFE */
+ ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0);
+
+ // Register for destruction with ACE_Object_Manager.
+ ACE_Object_Manager::at_exit (singleton);
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ }
+#endif /* ACE_MT_SAFE */
+ }
+ }
+
+ return &singleton->instance_;
+}
+
+template <class TYPE, class ACE_LOCK> void
+ACE_Singleton<TYPE, ACE_LOCK>::cleanup (void *)
+{
+ delete this;
+ ACE_Singleton<TYPE, ACE_LOCK>::instance_i () = 0;
+}
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+// Pointer to the Singleton instance.
+template <class TYPE, class ACE_LOCK> ACE_Singleton<TYPE, ACE_LOCK> *
+ACE_Singleton<TYPE, ACE_LOCK>::singleton_ = 0;
+
+template <class TYPE, class ACE_LOCK> ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *
+ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::singleton_ = 0;
+#endif /* !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */
+
+template <class TYPE, class ACE_LOCK> void
+ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::dump (void)
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::dump");
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("instance_ = %x"),
+ ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class TYPE, class ACE_LOCK>
+ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *&
+ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i (void)
+{
+#if defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ // Pointer to the Singleton instance. This works around a bug with
+ // G++ and it's (mis-)handling of templates and statics...
+ static ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *singleton_ = 0;
+
+ return singleton_;
+#else
+ return ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+}
+
+template <class TYPE, class ACE_LOCK> TYPE *
+ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance (void)
+{
+ ACE_TRACE ("ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance");
+
+ ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *&singleton =
+ ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i ();
+
+ // Perform the Double-Check pattern...
+ if (singleton == 0)
+ {
+ if (ACE_Object_Manager::starting_up () ||
+ ACE_Object_Manager::shutting_down ())
+ {
+ // The program is still starting up, and therefore assumed
+ // to be single threaded. There's no need to double-check.
+ // Or, the ACE_Object_Manager instance has been destroyed,
+ // so the preallocated lock is not available. Either way,
+ // don't register for destruction with the
+ // ACE_Object_Manager: we'll have to leak this instance.
+
+ ACE_NEW_RETURN (singleton, (ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>),
+ 0);
+ }
+ else
+ {
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ // Obtain a lock from the ACE_Object_Manager. The pointer
+ // is static, so we only obtain one per
+ // ACE_Unmanaged_Singleton instantiation.
+ static ACE_LOCK *lock = 0;
+ if (ACE_Object_Manager::get_singleton_lock (lock) != 0)
+ // Failed to acquire the lock!
+ return 0;
+
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0);
+#endif /* ACE_MT_SAFE */
+
+ if (singleton == 0)
+ ACE_NEW_RETURN (singleton,
+ (ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>),
+ 0);
+ }
+ }
+
+ return &singleton->instance_;
+}
+
+template <class TYPE, class ACE_LOCK> void
+ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::close (void)
+{
+ ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *&singleton =
+ ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i ();
+
+ if (singleton)
+ {
+ singleton->cleanup ();
+ ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i () = 0;
+ }
+}
+
+template <class TYPE, class ACE_LOCK> void
+ACE_TSS_Singleton<TYPE, ACE_LOCK>::dump (void)
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TSS_Singleton<TYPE, ACE_LOCK>::dump");
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("instance_ = %x"),
+ ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance_i ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class TYPE, class ACE_LOCK> ACE_TSS_Singleton<TYPE, ACE_LOCK> *&
+ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance_i (void)
+{
+#if defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ // Pointer to the Singleton instance. This works around a bug with
+ // G++ and it's (mis-)handling of templates and statics...
+ static ACE_TSS_Singleton<TYPE, ACE_LOCK> *singleton_ = 0;
+
+ return singleton_;
+#else
+ return ACE_TSS_Singleton<TYPE, ACE_LOCK>::singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+}
+
+template <class TYPE, class ACE_LOCK> TYPE *
+ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance (void)
+{
+ ACE_TRACE ("ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance");
+
+ ACE_TSS_Singleton<TYPE, ACE_LOCK> *&singleton =
+ ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance_i ();
+
+ // Perform the Double-Check pattern...
+ if (singleton == 0)
+ {
+ if (ACE_Object_Manager::starting_up () ||
+ ACE_Object_Manager::shutting_down ())
+ {
+ // The program is still starting up, and therefore assumed
+ // to be single threaded. There's no need to double-check.
+ // Or, the ACE_Object_Manager instance has been destroyed,
+ // so the preallocated lock is not available. Either way,
+ // don't register for destruction with the
+ // ACE_Object_Manager: we'll have to leak this instance.
+
+ ACE_NEW_RETURN (singleton, (ACE_TSS_Singleton<TYPE, ACE_LOCK>), 0);
+ }
+ else
+ {
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ // Obtain a lock from the ACE_Object_Manager. The pointer
+ // is static, so we only obtain one per ACE_Singleton instantiation.
+ static ACE_LOCK *lock = 0;
+ if (ACE_Object_Manager::get_singleton_lock (lock) != 0)
+ // Failed to acquire the lock!
+ return 0;
+
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0);
+
+ if (singleton == 0)
+ {
+#endif /* ACE_MT_SAFE */
+ ACE_NEW_RETURN (singleton, (ACE_TSS_Singleton<TYPE, ACE_LOCK>),
+ 0);
+
+ // Register for destruction with ACE_Object_Manager.
+ ACE_Object_Manager::at_exit (singleton);
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ }
+#endif /* ACE_MT_SAFE */
+ }
+ }
+
+ return ACE_TSS_GET (&singleton->instance_, TYPE);
+}
+
+template <class TYPE, class ACE_LOCK> void
+ACE_TSS_Singleton<TYPE, ACE_LOCK>::cleanup (void *)
+{
+ delete this;
+ ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance_i () = 0;
+}
+
+template <class TYPE, class ACE_LOCK> void
+ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::dump (void)
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::dump");
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("instance_ = %x"),
+ ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance_i ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class TYPE, class ACE_LOCK>
+ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *&
+ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance_i (void)
+{
+#if defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ // Pointer to the Singleton instance. This works around a bug with
+ // G++ and it's (mis-)handling of templates and statics...
+ static ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *singleton_ = 0;
+
+ return singleton_;
+#else
+ return ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+}
+
+template <class TYPE, class ACE_LOCK> TYPE *
+ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance (void)
+{
+ ACE_TRACE ("ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance");
+
+ ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *&singleton =
+ ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance_i ();
+
+ // Perform the Double-Check pattern...
+ if (singleton == 0)
+ {
+ if (ACE_Object_Manager::starting_up () ||
+ ACE_Object_Manager::shutting_down ())
+ {
+ // The program is still starting up, and therefore assumed
+ // to be single threaded. There's no need to double-check.
+ // Or, the ACE_Object_Manager instance has been destroyed,
+ // so the preallocated lock is not available. Either way,
+ // don't register for destruction with the
+ // ACE_Object_Manager: we'll have to leak this instance.
+
+ ACE_NEW_RETURN (singleton,
+ (ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>),
+ 0);
+ }
+ else
+ {
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ // Obtain a lock from the ACE_Object_Manager. The pointer
+ // is static, so we only obtain one per
+ // ACE_Unmanaged_Singleton instantiation.
+ static ACE_LOCK *lock = 0;
+ if (ACE_Object_Manager::get_singleton_lock (lock) != 0)
+ // Failed to acquire the lock!
+ return 0;
+
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0);
+#endif /* ACE_MT_SAFE */
+
+ if (singleton == 0)
+ ACE_NEW_RETURN (singleton,
+ (ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>),
+ 0);
+ }
+ }
+
+ return ACE_TSS_GET (&singleton->instance_, TYPE);
+}
+
+template <class TYPE, class ACE_LOCK> void
+ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::close (void)
+{
+ ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *&singleton =
+ ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance_i ();
+
+ if (singleton)
+ singleton->cleanup ();
+}
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+// Pointer to the Singleton instance.
+template <class TYPE, class ACE_LOCK> ACE_TSS_Singleton <TYPE, ACE_LOCK> *
+ACE_TSS_Singleton<TYPE, ACE_LOCK>::singleton_ = 0;
+
+template <class TYPE, class ACE_LOCK>
+ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *
+ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::singleton_ = 0;
+#endif /* !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */
+
+/*************************************************************************/
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+// Pointer to the Singleton instance.
+template <class TYPE, class ACE_LOCK> ACE_DLL_Singleton_T<TYPE, ACE_LOCK> *
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::singleton_ = 0;
+#endif /* !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */
+
+template <class TYPE, class ACE_LOCK> void
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::dump (void)
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::dump");
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("instance_ = %x"),
+ ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::instance_i ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class TYPE, class ACE_LOCK>
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK> *&
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::instance_i (void)
+{
+ ACE_TRACE ("ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::instance_i");
+
+#if defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ // Pointer to the Singleton instance. This works around a bug with
+ // G++ and it's (mis-)handling of templates and statics...
+ static ACE_DLL_Singleton_T<TYPE, ACE_LOCK> *singleton_ = 0;
+
+ return singleton_;
+#else
+ return ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+}
+
+template <class TYPE, class ACE_LOCK> TYPE *
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::instance (void)
+{
+ ACE_TRACE ("ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::instance");
+
+ ACE_DLL_Singleton_T<TYPE, ACE_LOCK> *&singleton =
+ ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::instance_i ();
+
+ // Perform the Double-Check pattern...
+ if (singleton == 0)
+ {
+ if (ACE_Object_Manager::starting_up () ||
+ ACE_Object_Manager::shutting_down ())
+ {
+ // The program is still starting up, and therefore assumed
+ // to be single threaded. There's no need to double-check.
+ // Or, the ACE_Object_Manager instance has been destroyed,
+ // so the preallocated lock is not available. Either way,
+ // don't register for destruction with the
+ // ACE_Object_Manager: we'll have to leak this instance.
+
+ ACE_NEW_RETURN (singleton, (ACE_DLL_Singleton_T<TYPE, ACE_LOCK>),
+ 0);
+ }
+ else
+ {
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ // Obtain a lock from the ACE_Object_Manager. The pointer
+ // is static, so we only obtain one per
+ // ACE_Unmanaged_Singleton instantiation.
+ static ACE_LOCK *lock = 0;
+ if (ACE_Object_Manager::get_singleton_lock (lock) != 0)
+ // Failed to acquire the lock!
+ return 0;
+
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0);
+#endif /* ACE_MT_SAFE */
+
+ if (singleton == 0)
+ ACE_NEW_RETURN (singleton,
+ (ACE_DLL_Singleton_T<TYPE, ACE_LOCK>),
+ 0);
+ }
+ //ACE_REGISTER_FRAMEWORK_COMPONENT(ACE_DLL_Singleton<TYPE,ACE_LOCK>, singleton);
+ ACE_Framework_Repository::instance ()->register_component
+ (new ACE_Framework_Component_T<ACE_DLL_Singleton_T<TYPE, ACE_LOCK> > (singleton));
+ }
+
+ return &singleton->instance_;
+}
+
+template <class TYPE, class ACE_LOCK> void
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::close (void)
+{
+ ACE_TRACE ("ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::close");
+
+ ACE_DLL_Singleton_T<TYPE, ACE_LOCK> *&singleton =
+ ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::instance_i ();
+
+ delete singleton;
+ singleton = 0;
+}
+
+template <class TYPE, class ACE_LOCK> void
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::close_singleton (void)
+{
+ ACE_TRACE ("ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::close_singleton");
+ ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::close ();
+}
+
+template <class TYPE, class ACE_LOCK> const ACE_TCHAR *
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::dll_name (void)
+{
+ return this->instance ()->dll_name ();
+}
+
+template <class TYPE, class ACE_LOCK> const ACE_TCHAR *
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::name (void)
+{
+ return this->instance ()->name ();
+}
+
+
+/**********************************************************************/
+
+template <class TYPE> const ACE_TCHAR*
+ACE_DLL_Singleton_Adapter_T<TYPE>::dll_name (void)
+{
+ // @todo make this a constant somewhere (or it there already is one
+ // then use it.
+ return ACE_TEXT("ACE");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_SINGLETON_CPP */
diff --git a/ACE/ace/Singleton.h b/ACE/ace/Singleton.h
new file mode 100644
index 00000000000..032f26740f4
--- /dev/null
+++ b/ACE/ace/Singleton.h
@@ -0,0 +1,327 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Singleton.h
+ *
+ * $Id$
+ *
+ * @brief
+ *
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Chris Lahey
+ * @author Rich Christy
+ * @author David Levine <levine@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SINGLETON_H
+#define ACE_SINGLETON_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+#include "ace/TSS_T.h"
+#include "ace/Cleanup.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Singleton
+ *
+ * @brief A Singleton Adapter uses the Adapter pattern to turn ordinary
+ * classes into Singletons optimized with the Double-Checked
+ * Locking optimization pattern.
+ *
+ * This implementation is a slight variation on the GoF
+ * Singleton pattern. In particular, a single
+ * <ACE_Singleton<TYPE, ACE_LOCK> > instance is allocated here,
+ * not a <TYPE> instance. The reason for this is to allow
+ * registration with the ACE_Object_Manager, so that the
+ * Singleton can be cleaned up when the process exits. For this
+ * scheme to work, a (static) cleanup() function must be
+ * provided. ACE_Singleton provides one so that TYPE doesn't
+ * need to.
+ * If you want to make sure that only the singleton instance of
+ * <T> is created, and that users cannot create their own
+ * instances of <T>, do the following to class <T>:
+ * (a) Make the constructor of <T> private (or protected)
+ * (b) Make Singleton a friend of <T>
+ * Here is an example:
+ * @verbatim
+ * class foo
+ * {
+ * friend class ACE_Singleton<foo, ACE_Null_Mutex>;
+ * private:
+ * foo () { cout << "foo constructed" << endl; }
+ * ~foo () { cout << "foo destroyed" << endl; }
+ * };
+ * typedef ACE_Singleton<foo, ACE_Null_Mutex> FOO;
+ * @endverbatim
+ *
+ * @note The best types to use for ACE_LOCK are
+ * ACE_Recursive_Thread_Mutex and ACE_Null_Mutex.
+ * ACE_Recursive_Thread_Mutex should be used in multi-threaded
+ * programs in which it is possible for more than one thread to
+ * access the <ACE_Singleton<TYPE, ACE_LOCK>> instance.
+ * ACE_Null_Mutex can be used otherwise. The reason that these
+ * types of locks are best has to do with their allocation by
+ * the ACE_Object_Manager. Single ACE_Recursive_Thread_Mutex
+ * and ACE_Null_Mutex instances are used for all ACE_Singleton
+ * instantiations. However, other types of locks are allocated
+ * per ACE_Singleton instantiation.
+ */
+template <class TYPE, class ACE_LOCK>
+class ACE_Singleton : public ACE_Cleanup
+{
+public:
+ /// Global access point to the Singleton.
+ static TYPE *instance (void);
+
+ /// Cleanup method, used by <ace_cleanup_destroyer> to destroy the
+ /// ACE_Singleton.
+ virtual void cleanup (void *param = 0);
+
+ /// Dump the state of the object.
+ static void dump (void);
+
+protected:
+ /// Default constructor.
+ ACE_Singleton (void);
+
+ /// Contained instance.
+ TYPE instance_;
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ /// Pointer to the Singleton (ACE_Cleanup) instance.
+ static ACE_Singleton<TYPE, ACE_LOCK> *singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+
+ /// Get pointer to the Singleton instance.
+ static ACE_Singleton<TYPE, ACE_LOCK> *&instance_i (void);
+};
+
+/**
+ * @class ACE_Unmanaged_Singleton
+ *
+ * @brief Same as ACE_Singleton, except does _not_ register with
+ * ACE_Object_Manager for destruction.
+ *
+ * This version of ACE_Singleton can be used if, for example,
+ * its DLL will be unloaded before the ACE_Object_Manager
+ * destroys the instance. Unlike with ACE_Singleton, the
+ * application is responsible for explicitly destroying the
+ * instance after it is no longer needed (if it wants to avoid
+ * memory leaks, at least). The close() static member function
+ * must be used to explicitly destroy the Singleton.
+ * Usage is the same as for ACE_Singleton, but note that if you
+ * you declare a friend, the friend class must still be an
+ * *ACE_Singleton*<T, [ACE_LOCK]>, not an ACE_Unmanaged_Singleton.
+ */
+template <class TYPE, class ACE_LOCK>
+class ACE_Unmanaged_Singleton : public ACE_Singleton <TYPE, ACE_LOCK>
+{
+public:
+ /// Global access point to the Singleton.
+ static TYPE *instance (void);
+
+ /// Explicitly delete the Singleton instance.
+ static void close (void);
+
+ /// Dump the state of the object.
+ static void dump (void);
+
+protected:
+ /// Default constructor.
+ ACE_Unmanaged_Singleton (void);
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ /// Pointer to the Singleton (ACE_Cleanup) instance.
+ static ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+
+ /// Get pointer to the Singleton instance.
+ static ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *&instance_i (void);
+};
+
+/**
+ * @class ACE_TSS_Singleton
+ *
+ * @brief This class uses the Adapter pattern to turn ordinary classes
+ * into Thread-specific Singletons optimized with the
+ * Double-Checked Locking optimization pattern.
+ *
+ * This implementation is another variation on the GoF Singleton
+ * pattern. In this case, a single <ACE_TSS_Singleton<TYPE,
+ * LOCK> > instance is allocated here, not a <TYPE> instance.
+ * Each call to the <instance> static method returns a Singleton
+ * whose pointer resides in thread-specific storage. As with
+ * ACE_Singleton, we use the ACE_Object_Manager so that the
+ * Singleton can be cleaned up when the process exits. For this
+ * scheme to work, a (static) cleanup() function must be
+ * provided. ACE_Singleton provides one so that TYPE doesn't
+ * need to.
+ */
+template <class TYPE, class ACE_LOCK>
+class ACE_TSS_Singleton : public ACE_Cleanup
+{
+public:
+ /// Global access point to the singleton.
+ static TYPE *instance (void);
+
+ /// Cleanup method, used by <ace_cleanup_destroyer> to destroy the
+ /// singleton.
+ virtual void cleanup (void *param = 0);
+
+ /// Dump the state of the object.
+ static void dump (void);
+
+protected:
+ /// Default constructor.
+ ACE_TSS_Singleton (void);
+
+ /// Contained instance.
+ ACE_TSS_TYPE (TYPE) instance_;
+
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS_Singleton<TYPE,ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_TSS_Singleton (const ACE_TSS_Singleton<TYPE,ACE_LOCK> &))
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ /// Pointer to the Singleton (ACE_Cleanup) instance.
+ static ACE_TSS_Singleton<TYPE, ACE_LOCK> *singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+
+ /// Get pointer to the TSS Singleton instance.
+ static ACE_TSS_Singleton<TYPE, ACE_LOCK> *&instance_i (void);
+};
+
+/**
+ * @class ACE_Unmanaged_TSS_Singleton
+ *
+ * @brief Same as ACE_TSS_Singleton, except does _not_ register with
+ * ACE_Object_Manager for destruction.
+ *
+ * This version of ACE_TSS_Singleton can be used if, for example, its DLL will
+ * be unloaded before the ACE_Object_Manager destroys the instance. Unlike with
+ * ACE_Singleton, the application is responsible for explicitly destroying the
+ * instance after it is no longer needed (if it wants to avoid memory leaks,
+ * at least). The close() static member function must be used to explicitly
+ * destroy the Singleton.
+ */
+template <class TYPE, class ACE_LOCK>
+class ACE_Unmanaged_TSS_Singleton : public ACE_TSS_Singleton <TYPE, ACE_LOCK>
+{
+public:
+ /// Global access point to the singleton.
+ static TYPE *instance (void);
+
+ /// Explicitly delete the singleton instance.
+ static void close (void);
+
+ /// Dump the state of the object.
+ static void dump (void);
+
+protected:
+ /// Default constructor.
+ ACE_Unmanaged_TSS_Singleton (void);
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ /// Pointer to the Singleton (ACE_Cleanup) instance.
+ static ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+
+ /// Get pointer to the Singleton instance.
+ static ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *&instance_i (void);
+};
+
+/**
+ * @class ACE_DLL_Singleton_T
+ *
+ * @brief Same as ACE_Singleton, except that it registers for
+ * destruction with the ACE_Framework_Repository instead of
+ * with the ACE_Object_Manager directly.
+ *
+ * This version of ACE_Singleton should be used for singletons
+ * that live in a dll loaded either directly by ACE_DLL or indirectly
+ * by the ACE Service Configuration framework. Whenever ACE_DLL is ready
+ * to actually unload the dll, ACE_DLL_Singleton based dlls associated
+ * with that dll will be destroyed first. In fact, any singleton can
+ * safely use ACE_DLL_Singleton, even those that don't live in dlls. In
+ * that case, the singleton will be destroyed at normal program shutdown.
+ *
+ * The only additional requirement is that the contained class
+ * export name() and dll_name() methods. See ACE_DLL_Singleton_Adapter_T
+ * below for a convenient example of how to satisfy this
+ * requirement for the dll_name().
+ *
+ * Usage is the same as for ACE_Singleton, but note that if you
+ * you declare a friend, the friend class must still be an
+ * *ACE_Singleton*<T, [ACE_LOCK]>, not an ACE_Unmanaged_Singleton.
+ */
+template <class TYPE, class ACE_LOCK>
+class ACE_DLL_Singleton_T
+{
+public:
+ //void cleanup (void *param = 0);
+
+ /// Global access point to the Singleton.
+ static TYPE *instance (void);
+
+ /// Explicitly delete the Singleton instance.
+ static void close (void);
+
+ static void close_singleton (void);
+
+ /// Dump the state of the object.
+ static void dump (void);
+
+ const ACE_TCHAR *dll_name (void);
+
+ const ACE_TCHAR *name (void);
+
+protected:
+ /// Default constructor.
+ ACE_DLL_Singleton_T (void);
+
+ /// Destructor.
+ ~ACE_DLL_Singleton_T (void);
+
+ /// Contained instance.
+ TYPE instance_;
+
+#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
+ /// Pointer to the Singleton instance.
+ static ACE_DLL_Singleton_T<TYPE, ACE_LOCK> *singleton_;
+#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */
+
+ /// Get pointer to the singleton instance.
+ static ACE_DLL_Singleton_T<TYPE, ACE_LOCK> *&instance_i (void);
+};
+
+template <class TYPE>
+class ACE_DLL_Singleton_Adapter_T : public TYPE
+{
+public:
+ const ACE_TCHAR *dll_name (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Singleton.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Singleton.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Singleton.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SINGLETON_H */
diff --git a/ACE/ace/Singleton.inl b/ACE/ace/Singleton.inl
new file mode 100644
index 00000000000..4351a59a5f6
--- /dev/null
+++ b/ACE/ace/Singleton.inl
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Default constructors.
+//
+// Note: don't explicitly initialize "instance_", because TYPE may not
+// have a default constructor. Let the compiler figure it out . . .
+
+template <class TYPE, class ACE_LOCK> ACE_INLINE
+ACE_Singleton<TYPE, ACE_LOCK>::ACE_Singleton (void)
+{
+}
+
+template <class TYPE, class ACE_LOCK> ACE_INLINE
+ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::ACE_Unmanaged_Singleton (void)
+{
+}
+
+template <class TYPE, class ACE_LOCK> ACE_INLINE
+ACE_TSS_Singleton<TYPE, ACE_LOCK>::ACE_TSS_Singleton (void)
+{
+}
+
+template <class TYPE, class ACE_LOCK> ACE_INLINE
+ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::ACE_Unmanaged_TSS_Singleton (void)
+{
+}
+
+template <class TYPE, class ACE_LOCK> ACE_INLINE
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::ACE_DLL_Singleton_T (void)
+{
+}
+
+template <class TYPE, class ACE_LOCK>
+ACE_DLL_Singleton_T<TYPE, ACE_LOCK>::~ACE_DLL_Singleton_T (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Sock_Connect.cpp b/ACE/ace/Sock_Connect.cpp
new file mode 100644
index 00000000000..3046cfc1a50
--- /dev/null
+++ b/ACE/ace/Sock_Connect.cpp
@@ -0,0 +1,1642 @@
+// $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"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_stdio.h"
+
+#if defined (sparc)
+# include "ace/OS_NS_fcntl.h"
+#endif // sparc
+
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/os_include/net/os_if.h"
+
+#if defined (ACE_HAS_IPV6)
+# include "ace/Guard_T.h"
+# include "ace/Recursive_Thread_Mutex.h"
+# if defined (_AIX)
+# include /**/ <netinet/in6_var.h>
+# endif /* _AIX */
+#endif /* ACE_HAS_IPV6 */
+
+# if defined (ACE_HAS_GETIFADDRS)
+# if defined (ACE_VXWORKS)
+# include /**/ <net/ifaddrs.h>
+# else
+# include /**/ <ifaddrs.h>
+# endif /*ACE_VXWORKS */
+# endif /* ACE_HAS_GETIFADDRS */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
+#include /**/ <inetLib.h>
+#include /**/ <netinet/in_var.h>
+#if defined (ACE_HAS_IPV6)
+#include /**/ <ifLib.h>
+extern "C" {
+ extern struct in_ifaddr* in_ifaddr;
+ extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl;
+}
+#endif /* ACE_HAS_IPV6 */
+#include "ace/OS_NS_stdio.h"
+#endif /* ACE_VXWORKS < 0x600 */
+
+#if defined (ACE_VXWORKS) && ((ACE_VXWORKS == 0x630) || (ACE_VXWORKS == 0x640)) && defined (__RTP__) && defined (ACE_HAS_IPV6)
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
+#endif /* ACE_VXWORKS == 0x630 && __RTP__ && ACE_HAS_IPV6 */
+
+#if defined (ACE_HAS_WINCE)
+#include /**/ <Iphlpapi.h>
+// The following code is suggested by microsoft as a workaround to the fact
+// that on Windows CE, these constants are exported as function addresses
+// rather than simply values.
+# include /**/ <ws2tcpip.h>
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+#endif // ACE_HAS_WINCE
+
+#if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
+# include "ace/OS_NS_stdio.h"
+#endif
+
+#if defined (ACE_HAS_IPV6)
+
+// These defines support a generic usage based on
+// the various SIGCF*IF ioctl implementations
+
+# if defined (SIOCGLIFCONF)
+# define SIOCGIFCONF_CMD SIOCGLIFCONF
+# if defined (__hpux)
+# define IFREQ if_laddrreq
+# define IFCONF if_laddrconf
+# define IFC_REQ iflc_req
+# define IFC_LEN iflc_len
+# define IFC_BUF iflc_buf
+# define IFR_ADDR iflr_addr
+# define IFR_NAME iflr_name
+# define IFR_FLAGS iflr_flags
+# undef SETFAMILY
+# define SA_FAMILY sa_family
+# else
+# define IFREQ lifreq
+# define IFCONF lifconf
+# define IFC_REQ lifc_req
+# define IFC_LEN lifc_len
+# define IFC_BUF lifc_buf
+# define IFR_ADDR lifr_addr
+# define IFR_NAME lifr_name
+# define IFR_FLAGS lifr_flags
+# define SETFAMILY
+# define IFC_FAMILY lifc_family
+# define IFC_FLAGS lifc_flags
+# define SA_FAMILY ss_family
+# endif
+# else
+# define SIOCGIFCONF_CMD SIOCGIFCONF
+# define IFREQ ifreq
+# define IFCONF ifconf
+# define IFC_REQ ifc_req
+# define IFC_LEN ifc_len
+# define IFC_BUF ifc_buf
+# define IFR_ADDR ifr_addr
+# define IFR_NAME ifr_name
+# define IFR_FLAGS ifr_flags
+# undef SETFAMILY
+# define SA_FAMILY sa_family
+# endif /* SIOCGLIFCONF */
+
+# if defined (ACE_HAS_THREADS)
+# include "ace/Object_Manager.h"
+# endif /* ACE_HAS_THREADS */
+
+namespace
+{
+ // private:
+ // Used internally so not exported.
+
+ // Does this box have ipv4 turned on?
+ int ace_ipv4_enabled = -1;
+
+ // Does this box have ipv6 turned on?
+ int ace_ipv6_enabled = -1;
+
+}
+#else /* ACE_HAS_IPV6 */
+# define SIOCGIFCONF_CMD SIOCGIFCONF
+# define IFREQ ifreq
+# define IFCONF ifconf
+# define IFC_REQ ifc_req
+# define IFC_LEN ifc_len
+# define IFC_BUF ifc_buf
+# define IFR_ADDR ifr_addr
+# define IFR_NAME ifr_name
+# define IFR_FLAGS ifr_flags
+# undef SETFAMILY
+# define SA_FAMILY sa_family
+#endif /* ACE_HAS_IPV6 */
+
+// This is a hack to work around a problem with Visual Age C++ 5 and 6 on AIX.
+// Without this, the compiler auto-instantiates the ACE_Auto_Array_Ptr for
+// ifreq (contained in this module) but only adds the #include for <net/if.h>
+// and not the one for <sys/socket.h> which is also needed. Although we
+// don't need the template defined here, it makes the compiler pull in
+// <sys/socket.h> and the build runs clean.
+#if defined (AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 500) && (__IBMCPP__ < 700)
+static ACE_Auto_Array_Ptr<sockaddr> force_compiler_to_include_socket_h;
+#endif /* AIX && __IBMCPP__ >= 500 */
+
+
+ACE_RCSID (ace,
+ Sock_Connect,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Bind socket to an unused port.
+
+int
+ACE::bind_port (ACE_HANDLE handle, ACE_UINT32 ip_addr, int address_family)
+{
+ ACE_TRACE ("ACE::bind_port");
+
+ ACE_INET_Addr addr;
+
+#if defined (ACE_HAS_IPV6)
+ if (address_family != PF_INET6)
+ // What do we do if it is PF_"INET6? Since it's 4 bytes, it must be an
+ // IPV4 address. Is there a difference? Why is this test done? dhinton
+#else /* ACE_HAS_IPV6 */
+ ACE_UNUSED_ARG (address_family);
+#endif /* !ACE_HAS_IPV6 */
+ addr = ACE_INET_Addr ((u_short)0, ip_addr);
+#if defined (ACE_HAS_IPV6)
+ else if (ip_addr != INADDR_ANY)
+ // address_family == PF_INET6 and a non default IP address means to bind
+ // to the IPv4-mapped IPv6 address
+ addr.set ((u_short)0, ip_addr, 1, 1);
+#endif /* ACE_HAS_IPV6 */
+
+#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::get_bcast_addr (ACE_UINT32 &bcast_addr,
+ const ACE_TCHAR *host_name,
+ ACE_UINT32 host_addr,
+ ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE::get_bcast_addr");
+
+#if defined (ACE_LACKS_GET_BCAST_ADDR)
+ ACE_UNUSED_ARG (bcast_addr);
+ ACE_UNUSED_ARG (host_name);
+ ACE_UNUSED_ARG (host_addr);
+ ACE_UNUSED_ARG (handle);
+ ACE_NOTSUP_RETURN (-1);
+#elif !defined(ACE_WIN32) && !defined(__INTERIX)
+ 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_TEXT ("%p\n"),
+ ACE_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 (ACE_OS::ioctl (s, SIOCGIFCONF_CMD, (char *) &ifc) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_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 (ACE_TEXT_ALWAYS_CHAR (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 */
+ }
+
+#if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
+ for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
+ n--, ifr++)
+#else
+ // see mk_broadcast@SOCK_Dgram_Bcast.cpp
+ for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
+ ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
+ (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
+ ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
+ (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
+ ifr = (struct ifreq *)
+ ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
+ (nbytes -= sizeof (struct ifreq), ifr++)))
+#endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
+ {
+ 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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_TEXT (" ioctl (get interface flags)")));
+ continue;
+ }
+
+ if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_TEXT ("ioctl (get broadaddr)")));
+ else
+ {
+ ACE_OS::memcpy (&ip_addr,
+ &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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_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 && !__INTERIX */
+}
+
+int
+ACE::get_fqdn (ACE_INET_Addr const & addr,
+ char hostname[],
+ size_t len)
+{
+ int h_error; // Not the same as errno!
+ hostent hentry;
+ ACE_HOSTENT_DATA buf;
+
+ char * ip_addr = 0;
+ int ip_addr_size = 0;
+ if (addr.get_type () == AF_INET)
+ {
+ sockaddr_in * const sock_addr =
+ reinterpret_cast<sockaddr_in *> (addr.get_addr ());
+ ip_addr_size = sizeof sock_addr->sin_addr;
+ ip_addr = (char*) &sock_addr->sin_addr;
+ }
+#ifdef ACE_HAS_IPV6
+ else
+ {
+ sockaddr_in6 * sock_addr =
+ reinterpret_cast<sockaddr_in6 *> (addr.get_addr ());
+
+ ip_addr_size = sizeof sock_addr->sin6_addr;
+ ip_addr = (char*) &sock_addr->sin6_addr;
+ }
+#endif /* ACE_HAS_IPV6 */
+
+ // get the host entry for the address in question
+ hostent * const hp = ACE_OS::gethostbyaddr_r (ip_addr,
+ ip_addr_size,
+ addr.get_type (),
+ &hentry,
+ buf,
+ &h_error);
+
+ // if it's not found in the host file or the DNS datase, there is nothing
+ // much we can do. embed the IP address
+ if (hp == 0 || hp->h_name == 0)
+ return -1;
+
+ if (ACE::debug())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
+ ACE_TEXT ("canonical host name is %s\n"),
+ ACE_TEXT_CHAR_TO_TCHAR (hp->h_name)));
+
+ // check if the canonical name is the FQDN
+ if (!ACE_OS::strchr(hp->h_name, '.'))
+ {
+ // list of address
+ char** p;
+ // list of aliases
+ char** q;
+
+ // for every address and for every alias within the address, check and
+ // see if we can locate a FQDN
+ for (p = hp->h_addr_list; *p != 0; ++p)
+ {
+ for (q = hp->h_aliases; *q != 0; ++q)
+ {
+ if (ACE_OS::strchr(*q, '.'))
+ {
+ // we got an FQDN from an alias. use this
+ if (ACE_OS::strlen (*q) >= len)
+ // the hostname is too huge to fit into a
+ // buffer of size MAXHOSTNAMELEN
+ // should we check other aliases as well
+ // before bailing out prematurely?
+ // for right now, let's do it. this (short name)
+ // is atleast better than embedding the IP
+ // address in the profile
+ continue;
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
+ ACE_TEXT ("found fqdn within alias as %s\n"),
+ ACE_TEXT_CHAR_TO_TCHAR(*q)));
+ ACE_OS::strcpy (hostname, *q);
+
+ return 0;
+ }
+ }
+ }
+ }
+
+ // The canonical name may be an FQDN when we reach here.
+ // Alternatively, the canonical name (a non FQDN) may be the best
+ // we can do.
+ if (ACE_OS::strlen (hp->h_name) >= len)
+ {
+ // The hostname is too large to fit into a buffer of size
+ // MAXHOSTNAMELEN.
+ return -2;
+ }
+ else
+ {
+ ACE_OS::strcpy (hostname, hp->h_name);
+ }
+
+ return 0;
+}
+
+#if defined (ACE_WIN32)
+
+static int
+get_ip_interfaces_win32 (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+# if defined (ACE_HAS_WINCE)
+ // moved the ACE_HAS_WINCE impl ahaid of ACE_HAS_WINSOCK2 because
+ // WINCE in fact has winsock2, but doesn't properly support the
+ // WSAIoctl for obtaining IPv6 address info.
+ PIP_ADAPTER_ADDRESSES AdapterAddresses = 0;
+ ULONG OutBufferLength = 0;
+ ULONG RetVal = 0;
+ unsigned char *octet_buffer = 0;
+
+ RetVal =
+ GetAdaptersAddresses(AF_UNSPEC,
+ 0,
+ 0,
+ AdapterAddresses,
+ &OutBufferLength);
+
+ if (RetVal != ERROR_BUFFER_OVERFLOW)
+ {
+ return -1;
+ }
+
+ ACE_NEW_RETURN (octet_buffer, unsigned char[OutBufferLength],-1);
+ AdapterAddresses = (IP_ADAPTER_ADDRESSES *)octet_buffer;
+
+ RetVal =
+ GetAdaptersAddresses(AF_UNSPEC,
+ 0,
+ 0,
+ AdapterAddresses,
+ &OutBufferLength);
+
+ if (RetVal != NO_ERROR)
+ {
+ delete [] octet_buffer;
+ return -1;
+ }
+
+ // If successful, output some information from the data we received
+ PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses;
+ while (AdapterList)
+ {
+ if (AdapterList->OperStatus == IfOperStatusUp)
+ {
+ if (AdapterList->IfIndex != 0)
+ ++count;
+ if (AdapterList->Ipv6IfIndex != 0)
+ ++count;
+ }
+ AdapterList = AdapterList->Next;
+ }
+
+ AdapterList = AdapterAddresses;
+
+ ACE_NEW_RETURN (addrs, ACE_INET_Addr[count],-1);
+ count = 0;
+ for (AdapterList = AdapterAddresses;
+ AdapterList != 0;
+ AdapterList = AdapterList->Next)
+ {
+ if (AdapterList->OperStatus != IfOperStatusUp)
+ continue;
+
+ IP_ADAPTER_UNICAST_ADDRESS *uni = 0;
+ if (AdapterList->IfIndex != 0)
+ for (uni = AdapterList->FirstUnicastAddress;
+ uni != 0;
+ uni = uni->Next)
+ {
+ SOCKET_ADDRESS *sa_addr = &uni->Address;
+ if (sa_addr->lpSockaddr->sa_family == AF_INET)
+ {
+ sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
+ addrs[count].set(sin,sa_addr->iSockaddrLength);
+ ++count;
+ break;
+ }
+ }
+ if (AdapterList->Ipv6IfIndex != 0)
+ {
+ for (uni = AdapterList->FirstUnicastAddress;
+ uni != 0;
+ uni = uni->Next)
+ {
+ SOCKET_ADDRESS *sa_addr = &uni->Address;
+ if (sa_addr->lpSockaddr->sa_family == AF_INET6)
+ {
+ sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
+ addrs[count].set(sin,sa_addr->iSockaddrLength);
+ ++count;
+ break;
+ }
+ }
+ }
+ }
+
+ delete [] octet_buffer;
+ return 0;
+
+# elif defined (ACE_HAS_PHARLAP)
+ // PharLap ETS has its own kernel routines to rummage through the device
+ // configs and extract the interface info, but only for Pharlap RT.
+# 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
+ // All non-CE, non-Pharlap Windows. Must support Winsock2.
+
+ 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);
+
+ // SIO_GET_INTERFACE_LIST does not work for IPv6
+ // Instead recent versions of Winsock2 add the new opcode
+ // SIO_ADDRESS_LIST_QUERY.
+ // If this is not available forget about IPv6 local interfaces:-/
+ int n_v6_interfaces = 0;
+
+# if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
+
+ LPSOCKET_ADDRESS_LIST v6info;
+ char *buffer;
+ DWORD buflen = sizeof (SOCKET_ADDRESS_LIST) + (63 * sizeof (SOCKET_ADDRESS));
+ ACE_NEW_RETURN (buffer,
+ char[buflen],
+ -1);
+ v6info = reinterpret_cast<LPSOCKET_ADDRESS_LIST> (buffer);
+
+ // Get an (overlapped) DGRAM socket to test with.
+ // If it fails only return IPv4 interfaces.
+ sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock != INVALID_SOCKET)
+ {
+ status = WSAIoctl(sock,
+ SIO_ADDRESS_LIST_QUERY,
+ 0,
+ 0,
+ v6info,
+ buflen,
+ &bytes,
+ 0,
+ 0);
+ closesocket (sock);
+ if (status != SOCKET_ERROR)
+ n_v6_interfaces = v6info->iAddressCount;
+ }
+# endif /* ACE_HAS_IPV6 */
+
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[n_interfaces + n_v6_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 = 0;
+
+ lpii = &info[i];
+ if (!(lpii->iiFlags & IFF_UP))
+ continue;
+
+ // We assume IPv4 addresses here
+ addrp = reinterpret_cast<struct sockaddr_in *> (&lpii->iiAddress.AddressIn);
+ if (addrp->sin_addr.s_addr == INADDR_ANY)
+ continue;
+
+ // Set the address for the caller.
+ addrs[count].set(addrp, sizeof(sockaddr_in));
+ ++count;
+ }
+
+# if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
+ // 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 (i = 0; i < n_v6_interfaces; i++)
+ {
+ struct sockaddr_in6 *addr6p;
+
+ if (v6info->Address[i].lpSockaddr->sa_family != AF_INET6)
+ continue;
+
+ addr6p = reinterpret_cast<struct sockaddr_in6 *> (v6info->Address[i].lpSockaddr);
+ if (IN6_IS_ADDR_UNSPECIFIED(&addr6p->sin6_addr)) // IN6ADDR_ANY?
+ continue;
+
+ // Set the address for the caller.
+ addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr6p), sizeof(sockaddr_in6));
+ ++count;
+ }
+
+ delete [] buffer; // Clean up
+# endif /* ACE_HAS_IPV6 */
+
+ if (count == 0)
+ {
+ delete [] addrs;
+ addrs = 0;
+ }
+
+ return 0;
+
+# endif /* ACE_HAS_WINCE */
+}
+#elif defined (ACE_HAS_GETIFADDRS)
+static int
+get_ip_interfaces_getifaddrs (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ // Take advantage of the BSD getifaddrs function that simplifies
+ // access to connected interfaces.
+ struct ifaddrs *ifap = 0;
+ struct ifaddrs *p_if = 0;
+
+ if (::getifaddrs (&ifap) != 0)
+ return -1;
+
+ // Count number of interfaces.
+ size_t num_ifs = 0;
+ for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
+ ++num_ifs;
+
+ // Now create and initialize output array.
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[num_ifs],
+ -1); // caller must free
+
+ // 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 (p_if = ifap;
+ p_if != 0;
+ p_if = p_if->ifa_next)
+ {
+ if (p_if->ifa_addr &&
+ p_if->ifa_addr->sa_family == AF_INET)
+ {
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
+
+ // Sometimes the kernel returns 0.0.0.0 as the interface
+ // address, skip those...
+ if (addr->sin_addr.s_addr != INADDR_ANY)
+ {
+ addrs[count].set ((u_short) 0,
+ addr->sin_addr.s_addr,
+ 0);
+ ++count;
+ }
+ }
+# if defined (ACE_HAS_IPV6)
+ else if (p_if->ifa_addr &&
+ p_if->ifa_addr->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *addr =
+ reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
+
+ // Skip the ANY address
+ if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr))
+ {
+ addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr),
+ sizeof(sockaddr_in6));
+ ++count;
+ }
+ }
+# endif /* ACE_HAS_IPV6 */
+ }
+
+ ::freeifaddrs (ifap);
+
+ return 0;
+}
+#elif defined (__hpux)
+static int
+get_ip_interfaces_hpux (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ size_t num_ifs = 0;
+ size_t num_ifs_found = 0;
+
+ // Call specific routine as necessary.
+ ACE_HANDLE handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
+ ACE_HANDLE handle_ipv6 = ACE_INVALID_HANDLE;
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:open")),
+ -1);
+
+ int result = 0;
+ int tmp_how_many = 0;
+
+ result = ACE_OS::ioctl (handle,
+ SIOCGIFNUM,
+ (caddr_t) &tmp_how_many);
+ if (result != -1)
+ num_ifs = (size_t)tmp_how_many;
+
+# if defined (ACE_HAS_IPV6)
+ tmp_how_many = 0;
+ handle_ipv6 = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
+ result = ACE_OS::ioctl (handle_ipv6,
+ SIOCGLIFNUM,
+ (caddr_t) &tmp_how_many);
+ if (result != -1)
+ num_ifs += (size_t)tmp_how_many;
+# endif
+
+ if (num_ifs == 0)
+ {
+ ACE_OS::close (handle);
+ ACE_OS::close (handle_ipv6);
+ 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;
+
+ //HPUX requires two passes, First for IPv4, then for IPv6
+
+ 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);
+ ACE_OS::close (handle_ipv6);
+ 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 (ACE_OS::ioctl (handle,
+ SIOCGIFCONF,
+ (char *) &ifcfg) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:")
+ ACE_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 ();
+ num_ifs_found = ifcfg.ifc_len / sizeof (struct ifreq); // get the number of returned ifs
+
+ for (size_t i = 0;
+ i < num_ifs_found;
+ i++)
+ {
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr);
+ if (addr->sin_addr.s_addr != 0)
+ {
+ addrs[count].set ((u_short) 0,
+ addr->sin_addr.s_addr,
+ 0);
+ ++count;
+ }
+ ++pcur;
+ }
+
+# if defined (ACE_HAS_IPV6)
+
+ if (handle_ipv6 != ACE_INVALID_HANDLE)
+ {
+ struct if_laddrreq *lifs = 0;
+ ACE_NEW_RETURN (lifs,
+ struct if_laddrreq[num_ifs],
+ -1);
+ ACE_OS::memset (lifs, 0, num_ifs * sizeof (struct if_laddrreq));
+
+ ACE_Auto_Array_Ptr<struct if_laddrreq> p_lifs (lifs);
+
+ if (p_lifs.get() == 0)
+ {
+ ACE_OS::close (handle);
+ ACE_OS::close (handle_ipv6);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ struct if_laddrconf lifcfg;
+ ACE_OS::memset (&lifcfg, 0, sizeof (struct if_laddrconf));
+
+ lifcfg.iflc_req = p_lifs.get ();
+ lifcfg.iflc_len = num_ifs * sizeof (struct if_laddrreq);
+
+ if (ACE_OS::ioctl (handle_ipv6,
+ SIOCGLIFCONF,
+ (char *) &lifcfg) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:")
+ ACE_TEXT ("ioctl - SIOCGLIFCONF failed")),
+ -1);
+ }
+
+ ACE_OS::close (handle_ipv6);
+
+ struct if_laddrreq *plcur = p_lifs.get ();
+ num_ifs_found = lifcfg.iflc_len / sizeof (struct if_laddrreq);
+
+ for (size_t i = 0;
+ i < num_ifs_found;
+ i++)
+ {
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (&plcur->iflr_addr);
+ if (!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
+ {
+ addrs[count].set(addr, sizeof(struct sockaddr_in6));
+ ++count;
+ }
+ ++plcur;
+ }
+ }
+# endif /* ACE_HAS_IPV6 */
+ return 0;
+}
+#elif defined (_AIX)
+static int
+get_ip_interfaces_aix (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ ACE_HANDLE handle = ACE::get_handle();
+ size_t num_ifs = 0;
+ struct ifconf ifc;
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces_aix:")),
+ -1);
+
+ if (ACE_OS::ioctl (handle,
+ SIOCGSIZIFCONF,
+ (caddr_t)&ifc.ifc_len) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get ifconf size")),
+ -1);
+ }
+
+ ACE_NEW_RETURN (ifc.ifc_buf,char [ifc.ifc_len], -1);
+
+ ACE_Auto_Array_Ptr<char> safe_buf (ifc.ifc_buf);
+ ACE_OS::memset (safe_buf.get(), 0, ifc.ifc_len);
+
+ if (ACE_OS::ioctl(handle, SIOCGIFCONF, (caddr_t)&ifc) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get ifconf")),
+ -1);
+ }
+
+ ACE_OS::close (handle);
+
+ char *buf_start = safe_buf.get();
+ char *buf_end = buf_start + ifc.ifc_len;
+
+ num_ifs = 0;
+ for (char *ptr = buf_start; ptr < buf_end; )
+ {
+ struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
+ ptr += IFNAMSIZ;
+ ptr += req->ifr_addr.sa_len;
+ if (req->ifr_addr.sa_family == AF_INET
+# if defined (ACE_HAS_IPV6)
+ || req->ifr_addr.sa_family == AF_INET6
+# endif
+ )
+ ++num_ifs;
+ }
+ ACE_NEW_RETURN (addrs,ACE_INET_Addr[num_ifs], -1);
+
+ for (char * ptr = buf_start; ptr < buf_end; )
+ {
+ struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
+ // skip the interface name
+ ptr += IFNAMSIZ;
+ if (req->ifr_addr.sa_family == AF_INET
+# if defined (ACE_HAS_IPV6)
+ || req->ifr_addr.sa_family == AF_INET6
+# endif
+ )
+ {
+ sockaddr_in *addr = (sockaddr_in*)&req->ifr_addr;
+ addrs[count++].set(addr, addr->sin_len);
+ }
+ ptr += req->ifr_addr.sa_len;
+ }
+
+ return 0;
+}
+
+#elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
+int
+get_ip_interfaces_vxworks_lt600 (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ count = 0;
+ // Loop through each address structure
+
+# if defined (ACE_HAS_IPV6) && defined (TAILQ_ENTRY)
+# define ia_next ia_link.tqe_next
+# endif /* TAILQ_ENTRY */
+
+ 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_TEXT ("ACE::get_ip_interface failed\n")
+ ACE_TEXT ("Couldnt get the IP Address\n")),
+ -1);
+ }
+ ++count;
+ }
+ }
+ return 0;
+}
+#endif // ACE_WIN32 || ACE_HAS_GETIFADDRS || __hpux || _AIX || ACE_VXWORKS < 0x600
+
+
+// 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::get_ip_interfaces (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ ACE_TRACE ("ACE::get_ip_interfaces");
+
+ count = 0;
+ addrs = 0;
+
+#if defined (ACE_WIN32)
+ return get_ip_interfaces_win32 (count, addrs);
+#elif defined (ACE_HAS_GETIFADDRS)
+ return get_ip_interfaces_getifaddrs (count, addrs);
+#elif defined (__hpux)
+ return get_ip_interfaces_hpux (count, addrs);
+#elif defined (_AIX)
+ return get_ip_interfaces_aix (count, addrs);
+#elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
+ return get_ip_interfaces_vxworks_lt600 (count, addrs);
+#elif (defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (ACE_OPENVMS) || (defined (ACE_VXWORKS) && (ACE_VXWORKS == 0x650)) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
+ // COMMON (SVR4 and BSD) UNIX CODE
+
+ // Call specific routine as necessary.
+ ACE_HANDLE handle = ACE::get_handle();
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:open")),
+ -1);
+
+ size_t num_ifs, num_ifs_found;
+
+ if (ACE::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));
+
+# ifdef SETFAMILY
+ ifcfg.IFC_FAMILY = AF_UNSPEC; // request all families be returned
+ ifcfg.IFC_FLAGS = 0;
+# endif
+
+ ifcfg.IFC_REQ = p_ifs.get ();
+ ifcfg.IFC_LEN = num_ifs * sizeof (struct IFREQ);
+
+ if (ACE_OS::ioctl (handle,
+ SIOCGIFCONF_CMD,
+ (caddr_t) &ifcfg) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:")
+ ACE_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 ();
+ num_ifs_found = ifcfg.IFC_LEN / sizeof (struct IFREQ); // get the number of returned ifs
+
+ // 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_found;
+ i++)
+ {
+ if (pcur->IFR_ADDR.SA_FAMILY == AF_INET
+# if defined (ACE_HAS_IPV6)
+ || pcur->IFR_ADDR.SA_FAMILY == AF_INET6
+# endif
+ )
+
+ {
+# if !defined(_UNICOS)
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (&pcur->IFR_ADDR);
+
+ // Sometimes the kernel returns 0.0.0.0 as an IPv4 interface
+ // address; skip those...
+ if (addr->sin_addr.s_addr != 0
+# if defined (ACE_HAS_IPV6)
+ || (addr->sin_family == AF_INET6 &&
+ !IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
+# endif
+ )
+ {
+ int addrlen = static_cast<int> (sizeof (struct sockaddr_in));
+# if defined (ACE_HAS_IPV6)
+ if (addr->sin_family == AF_INET6)
+ addrlen = static_cast<int> (sizeof (struct sockaddr_in6));
+# endif
+ addrs[count].set (addr, addrlen);
+ ++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 (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS)
+ ++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 /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
+ }
+
+# if defined (ACE_HAS_IPV6)
+ // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if
+ // it exists. If we cannot open it then ignore possible IPv6
+ // interfaces, we did our best;-)
+ FILE* fp;
+ char addr_p[8][5];
+ char s_ipaddr[64];
+ int scopeid;
+ struct addrinfo hints, *res0;
+ int error;
+
+ ACE_OS::memset (&hints, 0, sizeof (hints));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF_INET6;
+
+ if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
+ {
+ while (fscanf (fp,
+ "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
+ addr_p[0], addr_p[1], addr_p[2], addr_p[3],
+ addr_p[4], addr_p[5], addr_p[6], addr_p[7], &scopeid) != EOF)
+ {
+ // Format the address intoa proper IPv6 decimal address specification and
+ // resolve the resulting text using getaddrinfo().
+
+ const char* ip_fmt = "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
+ ACE_OS::sprintf (s_ipaddr,
+ ip_fmt,
+ addr_p[0], addr_p[1], addr_p[2], addr_p[3],
+ addr_p[4], addr_p[5], addr_p[6], addr_p[7], scopeid);
+
+ error = getaddrinfo (s_ipaddr, 0, &hints, &res0);
+ if (error)
+ continue;
+
+ if (res0->ai_family == AF_INET6 &&
+ !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6 *> (res0->ai_addr)->sin6_addr))
+ {
+ addrs[count].set(reinterpret_cast<sockaddr_in *> (res0->ai_addr), res0->ai_addrlen);
+ ++count;
+ }
+ freeaddrinfo (res0);
+
+ }
+ ACE_OS::fclose (fp);
+ }
+# endif /* ACE_HAS_IPV6 */
+
+ 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::count_interfaces (ACE_HANDLE handle,
+ size_t &how_many)
+{
+#if defined (ACE_WIN32) || defined (ACE_HAS_GETIFADDRS) || defined (__hpux) || defined (_AIX) || (defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600))
+ // none of these platforms make use of count_interfaces
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (how_many);
+ ACE_NOTSUP_RETURN (-1); // no implementation
+
+#elif defined (SIOCGIFNUM)
+# if defined (SIOCGLIFNUM)
+ int cmd = SIOCGLIFNUM;
+ struct lifnum if_num = {AF_UNSPEC,0,0};
+# else
+ int cmd = SIOCGIFNUM;
+ int if_num = 0;
+# endif /* SIOCGLIFNUM */
+ if (ACE_OS::ioctl (handle, cmd, (caddr_t)&if_num) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::count_interfaces:")
+ ACE_TEXT ("ioctl - SIOCGLIFNUM failed")),
+ -1);
+# if defined (SIOCGLIFNUM)
+ how_many = if_num.lifn_count;
+# else
+ how_many = if_num;
+# endif /* SIOCGLIFNUM */
+return 0;
+
+#elif (defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
+ // 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 (ACE_OS::ioctl (handle,
+ SIOCGIFCONF_CMD,
+ (caddr_t) &ifcfg) == -1)
+ {
+ ACE_OS::free (ifcfg.ifc_req);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::count_interfaces:")
+ ACE_TEXT ("ioctl - 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++)
+ {
+ /* In OpenBSD, the length of the list is returned. */
+ ifcfg.ifc_len -= sizeof (struct ifreq);
+ if (ifcfg.ifc_len < 0)
+ break;
+
+ ++if_count;
+#if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS)
+ ++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 /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
+ }
+
+ ACE_OS::free (ifcfg.ifc_req);
+
+# if defined (ACE_HAS_IPV6)
+ FILE* fp = 0;
+
+ if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
+ {
+ // Scan the lines according to the expected format but don't really read any input
+ while (fscanf (fp, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF)
+ {
+ ++if_count;
+ }
+ ACE_OS::fclose (fp);
+ }
+# endif /* ACE_HAS_IPV6 */
+
+ how_many = if_count;
+ return 0;
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (how_many);
+ ACE_NOTSUP_RETURN (-1); // no implementation
+#endif /* sparc && SIOCGIFNUM */
+}
+
+// Routine to return a handle from which ioctl() requests can be made.
+
+ACE_HANDLE
+ACE::get_handle (void)
+{
+ // Solaris 2.x
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+#if defined (sparc)
+ handle = ACE_OS::open ("/dev/udp", O_RDONLY);
+#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (__hpux) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)
+ // 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;
+}
+
+
+#if defined (ACE_HAS_IPV6)
+static int
+ip_check (int &ipvn_enabled, int pf)
+{
+ // We only get to this point if ipvn_enabled was -1 in the caller.
+ // Perform Double-Checked Locking Optimization.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ if (ipvn_enabled == -1)
+ {
+ // Determine if the kernel has IPv6 support by attempting to
+ // create a PF_INET socket and see if it fails.
+ ACE_HANDLE const s = ACE_OS::socket (pf, SOCK_DGRAM, 0);
+ if (s == ACE_INVALID_HANDLE)
+ {
+ ipvn_enabled = 0;
+ }
+ else
+ {
+ ipvn_enabled = 1;
+ ACE_OS::closesocket (s);
+ }
+ }
+ return ipvn_enabled;
+}
+#endif /* ACE_HAS_IPV6 */
+
+bool
+ACE::ipv4_enabled (void)
+{
+#if defined (ACE_HAS_IPV6)
+ return static_cast<bool> (ace_ipv4_enabled == -1 ?
+ ::ip_check (ace_ipv4_enabled, PF_INET) :
+ ace_ipv4_enabled);
+#else
+ // Assume it's always enabled since ACE requires some version of
+ // TCP/IP to exist.
+ return true;
+#endif /* ACE_HAS_IPV6*/
+}
+
+int
+ACE::ipv6_enabled (void)
+{
+#if defined (ACE_HAS_IPV6)
+ return ace_ipv6_enabled == -1 ?
+ ::ip_check (ace_ipv6_enabled, PF_INET6) :
+ ace_ipv6_enabled;
+#else /* ACE_HAS_IPV6 */
+ return 0;
+#endif /* !ACE_HAS_IPV6 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Sock_Connect.h b/ACE/ace/Sock_Connect.h
new file mode 100644
index 00000000000..33ae2dad6bb
--- /dev/null
+++ b/ACE/ace/Sock_Connect.h
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Sock_Connect.h
+ *
+ * $Id$
+ *
+ * @author Priyanka Gontla <pgontla@ece.uci.edu>
+ * @author Based on code that existed formerly in ACE.h.
+ */
+//==========================================================================
+
+#ifndef ACE_SOCK_CONNECT_H
+#define ACE_SOCK_CONNECT_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Basic_Types.h"
+#include "ace/os_include/netinet/os_in.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward Declarations
+class ACE_INET_Addr;
+
+namespace ACE
+{
+ // = Socket connection establishment calls.
+
+ /// Bind a new unused port to @a handle.
+ extern ACE_Export int bind_port (ACE_HANDLE handle,
+ ACE_UINT32 ip_addr = INADDR_ANY,
+ int address_family = AF_UNSPEC);
+
+ /**
+ * Get our broadcast address based on our @a host_addr. If
+ * @a hostname is non-0 we'll use it to determine our IP address. If
+ * @a 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.
+ */
+ extern ACE_Export int get_bcast_addr (
+ ACE_UINT32 &bcast_addr,
+ const ACE_TCHAR *hostname = 0,
+ ACE_UINT32 host_addr = 0,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE);
+
+ /// Get fully qualified host/domain name.
+ extern ACE_Export int get_fqdn (ACE_INET_Addr const & addr,
+ char hostname[],
+ size_t len);
+
+ /**
+ * 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 @a addr_array.
+ */
+ extern ACE_Export 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.
+ */
+ extern ACE_Export int count_interfaces (ACE_HANDLE handle,
+ size_t &how_many);
+
+ /// Routine to return a handle from which @c ioctl requests can be
+ /// made. Caller must close the handle.
+ extern ACE_Export ACE_HANDLE get_handle (void);
+
+ /// Returns @c true if IPv4 is enabled on the current host; @c false
+ /// if not.
+ /**
+ * This is an execution-time check. If ACE has not been compiled
+ * with @c ACE_HAS_IPV6, it always returns @c true. This function
+ * tries to create a @c PF_INET socket, returning @c true if it
+ * succeeds, and @c false if it fails. Caches the result so it only
+ gets checked once.
+ */
+ extern ACE_Export bool ipv4_enabled (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.
+ */
+ extern ACE_Export int ipv6_enabled (void);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SOCK_CONNECT_H */
diff --git a/ACE/ace/Static_Object_Lock.h b/ACE/ace/Static_Object_Lock.h
new file mode 100644
index 00000000000..b6a7e4acfc9
--- /dev/null
+++ b/ACE/ace/Static_Object_Lock.h
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Static_Object_Lock.h
+ *
+ * $Id$
+ *
+ * @author David L. Levine <levine@cs.wustl.edu>
+ * @author Matthias Kerkhoff
+ * @author Per Andersson
+ */
+//=============================================================================
+
+#ifndef ACE_STATIC_OBJECT_LOCK_H
+#define ACE_STATIC_OBJECT_LOCK_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_THREADS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Recursive_Thread_Mutex;
+
+/**
+ * @class ACE_Static_Object_Lock
+ *
+ * @brief Provide an interface to access a global lock.
+ *
+ * This class is used to serialize the creation of static
+ * singleton objects. It really isn't needed any more, because
+ * anyone can access ACE_STATIC_OBJECT_LOCK directly. But, it
+ * is retained for backward compatibility.
+ */
+class ACE_Export ACE_Static_Object_Lock
+{
+public:
+ /// Static lock access point.
+ static ACE_Recursive_Thread_Mutex *instance (void);
+
+ /// For use only by ACE_Object_Manager to clean up lock if it
+ /// what dynamically allocated.
+ static void cleanup_lock (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
+
+// hack to get around errors while compiling using split-cpp
+#if defined (ACE_HAS_THREADS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_IS_SPLITTING)
+typedef ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex> ACE_Static_Object_Lock_Type;
+
+# if defined (__GNUC__)
+// With g++, suppress the warning that this is unused.
+static ACE_Static_Object_Lock_Type *ACE_Static_Object_Lock_lock __attribute__ ((unused)) = 0;
+# else
+static ACE_Static_Object_Lock_Type *ACE_Static_Object_Lock_lock = 0;
+# endif /* __GNUC__ */
+
+# endif /* ACE_IS_SPLITTING */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_STATIC_OBJECT_LOCK_H */
diff --git a/ACE/ace/Stats.cpp b/ACE/ace/Stats.cpp
new file mode 100644
index 00000000000..57f20799cc4
--- /dev/null
+++ b/ACE/ace/Stats.cpp
@@ -0,0 +1,426 @@
+// $Id$
+
+#include "ace/Stats.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Stats.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(ace, Stats, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_UINT32
+ACE_Stats_Value::fractional_field (void) const
+{
+ if (precision () == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ ACE_UINT32 field = 10;
+ for (u_int i = 0; i < precision () - 1; ++i)
+ {
+ field *= 10;
+ }
+
+ return field;
+ }
+}
+
+int
+ACE_Stats::sample (const ACE_INT32 value)
+{
+ if (samples_.enqueue_tail (value) == 0)
+ {
+ ++number_of_samples_;
+ if (number_of_samples_ == 0)
+ {
+ // That's a lot of samples :-)
+ overflow_ = EFAULT;
+ return -1;
+ }
+
+ if (value < min_)
+ min_ = value;
+
+ if (value > max_)
+ max_ = value;
+
+ return 0;
+ }
+ else
+ {
+ // Probably failed due to running out of memory when trying to
+ // enqueue the new value.
+ overflow_ = errno;
+ return -1;
+ }
+}
+
+void
+ACE_Stats::mean (ACE_Stats_Value &m,
+ const ACE_UINT32 scale_factor)
+{
+ if (number_of_samples_ > 0)
+ {
+#if defined ACE_LACKS_LONGLONG_T
+ // If ACE_LACKS_LONGLONG_T, then ACE_UINT64 is a user-defined class.
+ // To prevent having to construct a static of that class, declare it
+ // on the stack, and construct it, in each function that needs it.
+ const ACE_U_LongLong ACE_STATS_INTERNAL_OFFSET (0, 8);
+#else /* ! ACE_LACKS_LONGLONG_T */
+ const ACE_UINT64 ACE_STATS_INTERNAL_OFFSET =
+ ACE_UINT64_LITERAL (0x100000000);
+#endif /* ! ACE_LACKS_LONGLONG_T */
+
+ ACE_UINT64 sum = ACE_STATS_INTERNAL_OFFSET;
+ ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
+ while (! i.done ())
+ {
+ ACE_INT32 *sample;
+ if (i.next (sample))
+ {
+ sum += *sample;
+ i.advance ();
+ }
+ }
+
+ // sum_ was initialized with ACE_STATS_INTERNAL_OFFSET, so
+ // subtract that off here.
+ quotient (sum - ACE_STATS_INTERNAL_OFFSET,
+ number_of_samples_ * scale_factor,
+ m);
+ }
+ else
+ {
+ m.whole (0);
+ m.fractional (0);
+ }
+}
+
+int
+ACE_Stats::std_dev (ACE_Stats_Value &std_dev,
+ const ACE_UINT32 scale_factor)
+{
+ if (number_of_samples_ <= 1)
+ {
+ std_dev.whole (0);
+ std_dev.fractional (0);
+ }
+ else
+ {
+ const ACE_UINT32 field = std_dev.fractional_field ();
+
+ // The sample standard deviation is:
+ //
+ // sqrt (sum (sample_i - mean)^2 / (number_of_samples_ - 1))
+
+ ACE_UINT64 mean_scaled;
+ // Calculate the mean, scaled, so that we don't lose its
+ // precision.
+ ACE_Stats_Value avg (std_dev.precision ());
+ mean (avg, 1u);
+ avg.scaled_value (mean_scaled);
+
+ // Calculate the summation term, of squared differences from the
+ // mean.
+ ACE_UINT64 sum_of_squares = 0;
+ ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
+ while (! i.done ())
+ {
+ ACE_INT32 *sample;
+ if (i.next (sample))
+ {
+ const ACE_UINT64 original_sum_of_squares = sum_of_squares;
+
+ // Scale up by field width so that we don't lose the
+ // precision of the mean. Carefully . . .
+ const ACE_UINT64 product (*sample * field);
+
+ ACE_UINT64 difference;
+ // NOTE: please do not reformat this code! It //
+ // works with the Diab compiler the way it is! //
+ if (product >= mean_scaled) //
+ { //
+ difference = product - mean_scaled; //
+ } //
+ else //
+ { //
+ difference = mean_scaled - product; //
+ } //
+ // NOTE: please do not reformat this code! It //
+ // works with the Diab compiler the way it is! //
+
+ // Square using 64-bit arithmetic.
+ sum_of_squares += difference * ACE_U64_TO_U32 (difference);
+ i.advance ();
+
+ if (sum_of_squares < original_sum_of_squares)
+ {
+ overflow_ = ENOSPC;
+ return -1;
+ }
+ }
+ }
+
+ // Divide the summation by (number_of_samples_ - 1), to get the
+ // variance. In addition, scale the variance down to undo the
+ // mean scaling above. Otherwise, it can get too big.
+ ACE_Stats_Value variance (std_dev.precision ());
+ quotient (sum_of_squares,
+ (number_of_samples_ - 1) * field * field,
+ variance);
+
+ // Take the square root of the variance to get the standard
+ // deviation. First, scale up . . .
+ ACE_UINT64 scaled_variance;
+ variance.scaled_value (scaled_variance);
+
+ // And scale up, once more, because we'll be taking the square
+ // root.
+ scaled_variance *= field;
+ ACE_Stats_Value unscaled_standard_deviation (std_dev.precision ());
+ square_root (scaled_variance,
+ unscaled_standard_deviation);
+
+ // Unscale.
+ quotient (unscaled_standard_deviation,
+ scale_factor * field,
+ std_dev);
+ }
+
+ return 0;
+}
+
+
+void
+ACE_Stats::reset (void)
+{
+ overflow_ = 0u;
+ number_of_samples_ = 0u;
+ min_ = 0x7FFFFFFF;
+ max_ = -0x8000 * 0x10000;
+ samples_.reset ();
+}
+
+int
+ACE_Stats::print_summary (const u_int precision,
+ const ACE_UINT32 scale_factor,
+ FILE *file) const
+{
+ ACE_TCHAR mean_string [128];
+ ACE_TCHAR std_dev_string [128];
+ ACE_TCHAR min_string [128];
+ ACE_TCHAR max_string [128];
+ int success = 0;
+
+ for (int tmp_precision = precision;
+ ! overflow_ && ! success && tmp_precision >= 0;
+ --tmp_precision)
+ {
+ // Build a format string, in case the C library doesn't support %*u.
+ ACE_TCHAR format[32];
+ if (tmp_precision == 0)
+ ACE_OS::sprintf (format, ACE_TEXT ("%%%d"), tmp_precision);
+ else
+ ACE_OS::sprintf (format, ACE_TEXT ("%%d.%%0%du"), tmp_precision);
+
+ ACE_Stats_Value u (tmp_precision);
+ ((ACE_Stats *) this)->mean (u, scale_factor);
+ ACE_OS::sprintf (mean_string, format, u.whole (), u.fractional ());
+
+ ACE_Stats_Value sd (tmp_precision);
+ if (((ACE_Stats *) this)->std_dev (sd, scale_factor))
+ {
+ success = 0;
+ continue;
+ }
+ else
+ {
+ success = 1;
+ }
+ ACE_OS::sprintf (std_dev_string, format, sd.whole (), sd.fractional ());
+
+ ACE_Stats_Value minimum (tmp_precision), maximum (tmp_precision);
+ if (min_ != 0)
+ {
+ const ACE_UINT64 m (min_);
+ quotient (m, scale_factor, minimum);
+ }
+ if (max_ != 0)
+ {
+ const ACE_UINT64 m (max_);
+ quotient (m, scale_factor, maximum);
+ }
+ ACE_OS::sprintf (min_string, format,
+ minimum.whole (), minimum.fractional ());
+ ACE_OS::sprintf (max_string, format,
+ maximum.whole (), maximum.fractional ());
+ }
+
+ if (success == 1)
+ {
+ ACE_OS::fprintf (file, ACE_TEXT ("samples: %u (%s - %s); mean: ")
+ ACE_TEXT ("%s; std dev: %s\n"),
+ samples (), min_string, max_string,
+ mean_string, std_dev_string);
+ return 0;
+ }
+ else
+ {
+#if !defined (ACE_HAS_WINCE)
+ ACE_OS::fprintf (file,
+ ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW: %s\n"),
+ ACE_OS::strerror (overflow_));
+#else
+ // WinCE doesn't have strerror ;(
+ ACE_OS::fprintf (file,
+ ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW\n"));
+#endif /* ACE_HAS_WINCE */
+ return -1;
+ }
+}
+
+void
+ACE_Stats::quotient (const ACE_UINT64 dividend,
+ const ACE_UINT32 divisor,
+ ACE_Stats_Value &quotient)
+{
+ // The whole part of the division comes from simple integer division.
+ quotient.whole (static_cast<ACE_UINT32> (divisor == 0
+ ? 0 : dividend / divisor));
+
+ if (quotient.precision () > 0 || divisor == 0)
+ {
+ const ACE_UINT32 field = quotient.fractional_field ();
+
+ // Fractional = (dividend % divisor) * 10^precision / divisor
+
+ // It would be nice to add round-up term:
+ // Fractional = (dividend % divisor) * 10^precision / divisor +
+ // 10^precision/2 / 10^precision
+ // = ((dividend % divisor) * 10^precision + divisor) /
+ // divisor
+ quotient.fractional (static_cast<ACE_UINT32> (
+ dividend % divisor * field / divisor));
+ }
+ else
+ {
+ // No fractional portion is requested, so don't bother
+ // calculating it.
+ quotient.fractional (0);
+ }
+}
+
+void
+ACE_Stats::quotient (const ACE_Stats_Value &dividend,
+ const ACE_UINT32 divisor,
+ ACE_Stats_Value &quotient)
+{
+ // The whole part of the division comes from simple integer division.
+ quotient.whole (divisor == 0 ? 0 : dividend.whole () / divisor);
+
+ if (quotient.precision () > 0 || divisor == 0)
+ {
+ const ACE_UINT32 field = quotient.fractional_field ();
+
+ // Fractional = (dividend % divisor) * 10^precision / divisor.
+ quotient.fractional (dividend.whole () % divisor * field / divisor +
+ dividend.fractional () / divisor);
+ }
+ else
+ {
+ // No fractional portion is requested, so don't bother
+ // calculating it.
+ quotient.fractional (0);
+ }
+}
+
+void
+ACE_Stats::square_root (const ACE_UINT64 n,
+ ACE_Stats_Value &square_root)
+{
+ ACE_UINT32 floor = 0;
+ ACE_UINT32 ceiling = 0xFFFFFFFFu;
+ ACE_UINT32 mid = 0;
+ u_int i;
+
+ // The maximum number of iterations is log_2 (2^64) == 64.
+ for (i = 0; i < 64; ++i)
+ {
+ mid = (ceiling - floor) / 2 + floor;
+ if (floor == mid)
+ // Can't divide the interval any further.
+ break;
+ else
+ {
+ // Multiply carefully to avoid overflow.
+ ACE_UINT64 mid_squared = mid; mid_squared *= mid;
+ if (mid_squared == n)
+ break;
+ else if (mid_squared < n)
+ floor = mid;
+ else
+ ceiling = mid;
+ }
+ }
+
+ square_root.whole (mid);
+ ACE_UINT64 mid_squared = mid; mid_squared *= mid;
+
+ if (square_root.precision () && mid_squared < n)
+ {
+ // (mid * 10^precision + fractional)^2 ==
+ // n^2 * 10^(precision * 2)
+
+ const ACE_UINT32 field = square_root.fractional_field ();
+
+ floor = 0;
+ ceiling = field;
+ mid = 0;
+
+ // Do the 64-bit arithmetic carefully to avoid overflow.
+ ACE_UINT64 target = n;
+ target *= field;
+ target *= field;
+
+ ACE_UINT64 difference = 0;
+
+ for (i = 0; i < square_root.precision (); ++i)
+ {
+ mid = (ceiling - floor) / 2 + floor;
+
+ ACE_UINT64 current = square_root.whole () * field + mid;
+ current *= square_root.whole () * field + mid;
+
+ if (floor == mid)
+ {
+ difference = target - current;
+ break;
+ }
+ else if (current <= target)
+ floor = mid;
+ else
+ ceiling = mid;
+ }
+
+ // Check to see if the fractional part should be one greater.
+ ACE_UINT64 next = square_root.whole () * field + mid + 1;
+ next *= square_root.whole () * field + mid + 1;
+
+ square_root.fractional (next - target < difference ? mid + 1 : mid);
+ }
+ else
+ {
+ // No fractional portion is requested, so don't bother
+ // calculating it.
+ square_root.fractional (0);
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Stats.h b/ACE/ace/Stats.h
new file mode 100644
index 00000000000..35cdde1a3d3
--- /dev/null
+++ b/ACE/ace/Stats.h
@@ -0,0 +1,222 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Stats.h
+ *
+ * $Id$
+ *
+ * @author David L. Levine
+ */
+//==========================================================================
+
+
+#ifndef ACE_STATS_H
+#define ACE_STATS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Unbounded_Queue.h"
+#include "ace/Log_Msg.h"
+#include "ace/Basic_Stats.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Stats_Value
+ *
+ * @brief Helper class for ACE_Stats.
+ *
+ * Container struct for 64-bit signed quantity and its
+ * precision. It would be nicer to use a fixed-point class, but
+ * this is sufficient. Users typically don't need to use this
+ * class directly; see ACE_Stats below.
+ */
+class ACE_Export ACE_Stats_Value
+{
+public:
+ /**
+ * Constructor, which requires precision in terms of number of
+ * decimal digits. The more variation in the data, and the greater
+ * the data values, the smaller the precision must be to avoid
+ * overflow in the standard deviation calculation. 3 might be a
+ * good value, or maybe 4. 5 will probably be too large for
+ * non-trivial data sets.
+ */
+ ACE_Stats_Value (const u_int precision);
+
+ /// Accessor for precision.
+ u_int precision (void) const;
+
+ /// Set the whole_ field.
+ void whole (const ACE_UINT32);
+
+ /// Accessor for the whole_ field.
+ ACE_UINT32 whole (void) const;
+
+ /// Set the fractional_ field.
+ void fractional (const ACE_UINT32);
+
+ /// Accessor for the fractional_ field.
+ ACE_UINT32 fractional (void) const;
+
+ /// Calculates the maximum value of the fractional portion, given its
+ /// precision.
+ ACE_UINT32 fractional_field (void) const;
+
+ /**
+ * Access the value as an _unsigned_ 64 bit quantity. It scales the
+ * value up by {precision} decimal digits, so that no precision will
+ * be lost. It assumes that {whole_} is >= 0.
+ */
+ void scaled_value (ACE_UINT64 &) const;
+
+ /// Print to stdout.
+ void dump (void) const;
+
+private:
+
+ ACE_Stats_Value (void) {}
+
+private:
+ /// The integer portion of the value.
+ ACE_UINT32 whole_;
+
+ /// The fractional portion of the value.
+ ACE_UINT32 fractional_;
+
+ /**
+ * The number of decimal digits of precision represented by
+ * {fractional_}. Not declared const, so the only way to change it
+ * is via the assignment operator.
+ */
+ u_int precision_;
+
+};
+
+/**
+ * @class ACE_Stats
+ *
+ * @brief Provides simple statistical analysis.
+ *
+ * Simple statistical analysis package. Prominent features are:
+ * -# It does not use any floating point arithmetic.
+ * -# It handles positive and/or negative sample values. The
+ * sample value type is ACE_INT32.
+ * -# It uses 64 bit unsigned, but not 64 bit signed, quantities
+ * internally.
+ * -# It checks for overflow of internal state.
+ * -# It has no static variables of other than built-in types.
+ *
+ * Example usage:
+ *
+ * @verbatim
+ * ACE_Stats stats;
+ * for (u_int i = 0; i < n; ++i)
+ * {
+ * const ACE_UINT32 sample = ...;
+ * stats.sample (sample);
+ * }
+ * stats.print_summary (3);
+ * @endverbatim
+ */
+class ACE_Export ACE_Stats
+{
+public:
+ /// Default constructor.
+ ACE_Stats (void);
+
+ /// Provide a new sample. Returns 0 on success, -1 if it fails due
+ /// to running out of memory, or to rolling over of the sample count.
+ int sample (const ACE_INT32 value);
+
+ /// Access the number of samples provided so far.
+ ACE_UINT32 samples (void) const;
+
+ /// Value of the minimum sample provided so far.
+ ACE_INT32 min_value (void) const;
+
+ /// Value of the maximum sample provided so far.
+ ACE_INT32 max_value (void) const;
+
+ /**
+ * Access the mean of all samples provided so far. The fractional
+ * part is to the specified number of digits. E.g., 3 fractional
+ * digits specifies that the fractional part is in thousandths.
+ */
+ void mean (ACE_Stats_Value &mean,
+ const ACE_UINT32 scale_factor = 1);
+
+ /// Access the standard deviation, whole and fractional parts. See
+ /// description of {mean} method for argument descriptions.
+ int std_dev (ACE_Stats_Value &std_dev,
+ const ACE_UINT32 scale_factor = 1);
+
+ /**
+ * Print summary statistics. If scale_factor is not 1, then the
+ * results are divided by it, i.e., each of the samples is scaled
+ * down by it. If internal overflow is reached with the specified
+ * scale factor, it successively tries to reduce it. Returns -1 if
+ * there is overflow even with a 0 scale factor.
+ */
+ int print_summary (const u_int precision,
+ const ACE_UINT32 scale_factor = 1,
+ FILE * = stdout) const;
+
+ /// Initialize internal state.
+ void reset (void);
+
+ /// Utility division function, for ACE_UINT64 dividend.
+ static void quotient (const ACE_UINT64 dividend,
+ const ACE_UINT32 divisor,
+ ACE_Stats_Value &quotient);
+
+ /// Utility division function, for ACE_Stats_Value dividend.
+ static void quotient (const ACE_Stats_Value &dividend,
+ const ACE_UINT32 divisor,
+ ACE_Stats_Value &quotient);
+
+ /**
+ * Sqrt function, which uses an oversimplified version of Newton's
+ * method. It's not fast, but it doesn't require floating point
+ * support.
+ */
+ static void square_root (const ACE_UINT64 n,
+ ACE_Stats_Value &square_root);
+
+ /// Print summary statistics to stdout.
+ void dump (void) const;
+
+protected:
+ /// Internal indication of whether there has been overflow. Contains
+ /// the errno corresponding to the cause of overflow.
+ u_int overflow_;
+
+ /// Number of samples.
+ ACE_UINT32 number_of_samples_;
+
+ /// Minimum sample value.
+ ACE_INT32 min_;
+
+ /// Maximum sample value.
+ ACE_INT32 max_;
+
+ /// The samples.
+ ACE_Unbounded_Queue <ACE_INT32> samples_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Stats.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ! ACE_STATS_H */
diff --git a/ACE/ace/Stats.inl b/ACE/ace/Stats.inl
new file mode 100644
index 00000000000..621dd16841e
--- /dev/null
+++ b/ACE/ace/Stats.inl
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Stats_Value::ACE_Stats_Value (const u_int precision)
+ : whole_ (0),
+ fractional_ (0),
+ precision_ (precision)
+{
+}
+
+ACE_INLINE
+u_int
+ACE_Stats_Value::precision (void) const
+{
+ return precision_;
+}
+
+ACE_INLINE
+void
+ACE_Stats_Value::whole (const ACE_UINT32 value)
+{
+ whole_ = value;
+}
+
+ACE_INLINE
+ACE_UINT32
+ACE_Stats_Value::whole (void) const
+{
+ return whole_;
+}
+
+ACE_INLINE
+void
+ACE_Stats_Value::fractional (const ACE_UINT32 value)
+{
+ fractional_ = value;
+}
+
+ACE_INLINE
+ACE_UINT32
+ACE_Stats_Value::fractional (void) const
+{
+ return fractional_;
+}
+
+ACE_INLINE
+void
+ACE_Stats_Value::scaled_value (ACE_UINT64 &sv) const
+{
+ sv = whole () * fractional_field () + fractional ();
+}
+
+ACE_INLINE
+void
+ACE_Stats_Value::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("precision: %u digits; whole: %u, fractional: %u\n"),
+ precision_, whole_, fractional_));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_INLINE
+ACE_Stats::ACE_Stats (void)
+{
+ reset ();
+}
+
+ACE_INLINE
+ACE_UINT32
+ACE_Stats::samples (void) const
+{
+ return number_of_samples_;
+}
+
+ACE_INLINE
+ACE_INT32
+ACE_Stats::min_value (void) const
+{
+ return min_;
+}
+
+ACE_INLINE
+ACE_INT32
+ACE_Stats::max_value (void) const
+{
+ return max_;
+}
+
+ACE_INLINE
+void
+ACE_Stats::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ print_summary (3u);
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Strategies.h b/ACE/ace/Strategies.h
new file mode 100644
index 00000000000..ae4c0479833
--- /dev/null
+++ b/ACE/ace/Strategies.h
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Strategies.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_STRATEGIES_H
+#define ACE_STRATEGIES_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/// Place holder for backward compatibility..
+#include "ace/Connection_Recycling_Strategy.h"
+#include "ace/Hashable.h"
+#include "ace/Notification_Strategy.h"
+#include "ace/Reactor_Notification_Strategy.h"
+#include "ace/Recyclable.h"
+#include "ace/Refcountable.h"
+
+
+#include /**/ "ace/post.h"
+#endif /*ACE_STRATEGIES_H*/
diff --git a/ACE/ace/Strategies_T.cpp b/ACE/ace/Strategies_T.cpp
new file mode 100644
index 00000000000..aa3b607d52e
--- /dev/null
+++ b/ACE/ace/Strategies_T.cpp
@@ -0,0 +1,1498 @@
+// $Id$
+
+#ifndef ACE_STRATEGIES_T_CPP
+#define ACE_STRATEGIES_T_CPP
+
+#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/Service_Types.h"
+#include "ace/Thread_Manager.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_dlfcn.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Errno.h"
+#if defined (ACE_OPENVMS)
+# include "ace/Lib_Find.h"
+#endif
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Strategies_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class SVC_HANDLER>
+ACE_Recycling_Strategy<SVC_HANDLER>::~ACE_Recycling_Strategy (void)
+{
+}
+
+template<class SVC_HANDLER> 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> int
+ACE_Recycling_Strategy<SVC_HANDLER>::prepare_for_recycling (SVC_HANDLER *svc_handler)
+{
+ return svc_handler->recycle ();
+}
+
+template <class SVC_HANDLER>
+ACE_Singleton_Strategy<SVC_HANDLER>::~ACE_Singleton_Strategy (void)
+{
+ ACE_TRACE ("ACE_Singleton_Strategy<SVC_HANDLER>::~ACE_Singleton_Strategy");
+ if (this->delete_svc_handler_)
+ delete this->svc_handler_;
+}
+
+// Create a Singleton SVC_HANDLER by always returning the same
+// SVC_HANDLER.
+
+template <class SVC_HANDLER> 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> 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_)
+ 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_ = true;
+ }
+ else
+ {
+ this->svc_handler_ = sh;
+ this->delete_svc_handler_ = false;
+ }
+
+ return 0;
+}
+
+template <class SVC_HANDLER> int
+ACE_DLL_Strategy<SVC_HANDLER>::open (const ACE_TCHAR dll_name[],
+ const ACE_TCHAR factory_function[],
+ const ACE_TCHAR 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->dll_name_);
+
+ // Extract the factory function.
+#if defined (ACE_OPENVMS)
+ SVC_HANDLER *(*factory)(void) =
+ (SVC_HANDLER *(*)(void)) ACE::ldsymbol (handle,
+ this->factory_function_);
+#else
+ SVC_HANDLER *(*factory)(void) =
+ (SVC_HANDLER *(*)(void)) ACE_OS::dlsym (handle,
+ this->factory_function_);
+#endif
+
+ // Call the factory function to obtain the new SVC_Handler (should
+ // use RTTI here when it becomes available...)
+ SVC_HANDLER *svc_handler = 0;
+
+ 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 = 0;
+ 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,
+ int 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_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_TEXT ("%p\n"),
+ ACE_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)
+ {
+ // Ensure that errno is preserved in case the svc_handler
+ // close() method resets it
+ ACE_Errno_Guard error(errno);
+
+ // 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 const 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_TEXT ("child"), this->flags_))
+ {
+ case -1:
+ {
+ ACE_Errno_Guard error (errno);
+ svc_handler->destroy ();
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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
+(creation_strategy_type *cre_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ ACE_Recycling_Strategy<SVC_HANDLER> *rec_s,
+ MUTEX *lock,
+ bool delete_lock)
+ : lock_ (lock),
+ delete_lock_ (delete_lock),
+ reverse_lock_ (0),
+ creation_strategy_ (0),
+ delete_creation_strategy_ (false),
+ concurrency_strategy_ (0),
+ delete_concurrency_strategy_ (false),
+ recycling_strategy_ (0),
+ delete_recycling_strategy_ (false)
+{
+ // Create a new lock if necessary.
+ if (this->lock_ == 0)
+ {
+ ACE_NEW (this->lock_,
+ MUTEX);
+
+ this->delete_lock_ = true;
+ }
+
+ ACE_NEW (this->reverse_lock_,
+ REVERSE_MUTEX (*this->lock_));
+
+ if (this->open (cre_s,
+ con_s,
+ rec_s) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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_ = false;
+ this->creation_strategy_ = 0;
+
+ if (this->delete_concurrency_strategy_)
+ delete this->concurrency_strategy_;
+ this->delete_concurrency_strategy_ = false;
+ this->concurrency_strategy_ = 0;
+
+ if (this->delete_recycling_strategy_)
+ delete this->recycling_strategy_;
+ this->delete_recycling_strategy_ = false;
+ this->recycling_strategy_ = 0;
+
+ // Close down all cached service handlers.
+ CONNECTION_MAP_ENTRY *entry = 0;
+ 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
+(creation_strategy_type *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_ &&
+ cre_s != 0)
+ {
+ delete this->creation_strategy_;
+ this->creation_strategy_ = 0;
+ this->delete_creation_strategy_ = false;
+ }
+
+ 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_ = true;
+ }
+
+ // Initialize the concurrency strategy.
+
+ if (this->concurrency_strategy_ != 0 &&
+ this->delete_concurrency_strategy_ &&
+ con_s != 0)
+ {
+ delete this->concurrency_strategy_;
+ this->concurrency_strategy_ = 0;
+ this->delete_concurrency_strategy_ = false;
+ }
+
+ 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_ = true;
+ }
+
+ // Initialize the recycling strategy.
+
+ if (this->recycling_strategy_ != 0 &&
+ this->delete_recycling_strategy_ &&
+ rec_s != 0)
+ {
+ delete this->recycling_strategy_;
+ this->recycling_strategy_ = 0;
+ this->delete_recycling_strategy_ = false;
+ }
+
+ 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_ = true;
+ }
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> 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> 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> 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> 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);
+}
+
+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,
+ CONNECTION_MAP_ENTRY *&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,
+ CONNECTION_MAP_ENTRY *&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 = 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 (
+ REFCOUNTED_HASH_RECYCLABLE_ADDRESS &search_addr,
+ CONNECTION_MAP_ENTRY *&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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER>
+ACE_Concurrency_Strategy<SVC_HANDLER>::~ACE_Concurrency_Strategy (void)
+{
+ ACE_TRACE ("ACE_Concurrency_Strategy<SVC_HANDLER>::~ACE_Concurrency_Strategy");
+}
+
+
+template <class SVC_HANDLER> void
+ACE_Concurrency_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Concurrency_Strategy<SVC_HANDLER>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER>
+ACE_Reactive_Strategy<SVC_HANDLER>::~ACE_Reactive_Strategy (void)
+{
+ ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::~ACE_Reactive_Strategy");
+}
+
+
+template <class SVC_HANDLER> void
+ACE_Reactive_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER>
+ACE_Thread_Strategy<SVC_HANDLER>::~ACE_Thread_Strategy (void)
+{
+ ACE_TRACE ("ACE_Thread_Strategy<SVC_HANDLER>::~ACE_Thread_Strategy");
+}
+
+template <class SVC_HANDLER> void
+ACE_Thread_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Thread_Strategy<SVC_HANDLER>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+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_ACCEPTOR_1> 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> 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> void
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+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> 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> void
+ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER>
+ACE_Process_Strategy<SVC_HANDLER>::~ACE_Process_Strategy (void)
+{
+ ACE_TRACE ("ACE_Process_Strategy<SVC_HANDLER>::~ACE_Process_Strategy");
+}
+
+template <class SVC_HANDLER> void
+ACE_Process_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Process_Strategy<SVC_HANDLER>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER>
+ACE_Scheduling_Strategy<SVC_HANDLER>::~ACE_Scheduling_Strategy (void)
+{
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::~ACE_Scheduling_Strategy");
+}
+
+template <class SVC_HANDLER> int
+ACE_Scheduling_Strategy<SVC_HANDLER>::suspend (void)
+{
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::suspend");
+ return -1;
+}
+
+template <class SVC_HANDLER> int
+ACE_Scheduling_Strategy<SVC_HANDLER>::resume (void)
+{
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::resume");
+ return -1;
+}
+
+template <class SVC_HANDLER> void
+ACE_Scheduling_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER> 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> 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> void
+ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::dump");
+
+ ACE_Scheduling_Strategy<SVC_HANDLER>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER> 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> 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 SVC_HANDLER> void
+ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::dump");
+
+ ACE_Scheduling_Strategy<SVC_HANDLER>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Refcounted_Hash_Recyclable<T>::~ACE_Refcounted_Hash_Recyclable (void)
+{
+}
+
+template <class SVC_HANDLER> void
+ACE_Singleton_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Singleton_Strategy<SVC_HANDLER>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER>
+ACE_Creation_Strategy<SVC_HANDLER>::~ACE_Creation_Strategy (void)
+{
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::~ACE_Creation_Strategy");
+}
+
+// Default behavior is to make a new SVC_HANDLER, passing in the
+// Thread_Manager (if any).
+
+template <class SVC_HANDLER> 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);
+ sh->reactor (this->reactor_);
+ return 0;
+}
+
+template <class SVC_HANDLER> void
+ACE_Creation_Strategy<SVC_HANDLER>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class SVC_HANDLER> 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> 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;
+}
+
+
+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)
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_STRATEGIES_T_CPP */
diff --git a/ACE/ace/Strategies_T.h b/ACE/ace/Strategies_T.h
new file mode 100644
index 00000000000..1ab517d4b7b
--- /dev/null
+++ b/ACE/ace/Strategies_T.h
@@ -0,0 +1,1076 @@
+// -*- 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_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Reactor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Connection_Recycling_Strategy.h"
+#include "ace/Refcountable.h"
+#include "ace/Hashable.h"
+#include "ace/Recyclable.h"
+#include "ace/Reverse_Lock_T.h"
+
+// Needed for broken linkers that can't grok long symbols.
+#define ACE_Refcounted_Hash_Recyclable ARHR
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Service_Repository;
+
+/**
+ * @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:
+
+ // Useful STL-style traits.
+ typedef typename SVC_HANDLER::addr_type addr_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+
+ /// 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:
+
+ // Useful STL-style traits.
+ typedef typename SVC_HANDLER::addr_type addr_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+
+ // = Initialization and termination methods.
+
+ /// Default constructor.
+ ACE_Creation_Strategy (ACE_Thread_Manager * = 0,
+ ACE_Reactor * = ACE_Reactor::instance ());
+
+ /// An ACE_Thread_Manager is useful when creating active objects and
+ /// the ACE_Reactor is used to initialize the service handler's reactor.
+ int open (ACE_Thread_Manager * = 0,
+ ACE_Reactor * = ACE_Reactor::instance ());
+
+ 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
+ * @a sh == 0 (passing in the <Thread_Manager>), else @a 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_;
+
+ /// Pointer to an ACE_Reactor.
+ ACE_Reactor *reactor_;
+};
+
+/**
+ * @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:
+
+ // Useful STL-style traits.
+ typedef ACE_Creation_Strategy<SVC_HANDLER> base_type;
+
+ // = 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.
+ bool 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:
+
+ // Useful STL-style traits.
+ typedef ACE_Creation_Strategy<SVC_HANDLER> base_type;
+
+ // = 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 ACE_TCHAR dll_name[],
+ const ACE_TCHAR factory_function[],
+ const ACE_TCHAR 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 ACE_TCHAR dll_name[],
+ const ACE_TCHAR factory_function[],
+ const ACE_TCHAR 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.
+ ACE_TCHAR dll_name_[MAXPATHLEN + 1];
+
+ /// Name of the factory function in the shared library to use to
+ /// obtain a pointer to the new SVC_HANDLER.
+ ACE_TCHAR factory_function_[MAXPATHLEN + 1];
+
+ /// Name of the service.
+ ACE_TCHAR 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:
+
+ // Useful STL-style traits.
+ typedef typename SVC_HANDLER::addr_type addr_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+
+ /// 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, where all upcalls to @c handle_*()
+ * methods run in the reactor's thread of control.
+ *
+ * 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:
+
+ // Useful STL-style traits.
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER> base_type;
+
+ // = 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 via a
+ * thread-per-connection model. 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:
+
+ // Useful STL-style traits.
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER> base_type;
+
+ // = 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,
+ int n_threads = 1,
+ int flags = 0);
+
+ /// Initialize the strategy.
+ virtual int open (ACE_Thread_Manager *tm,
+ long thr_flags,
+ int 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.
+ int n_threads_;
+};
+
+/**
+ * @class ACE_Process_Strategy
+ *
+ * @brief Defines the interface for specifying a concurrency strategy
+ * for a @c SVC_HANDLER based on multiprocessing.
+ *
+ * This class provides a strategy that manages the creation of
+ * processes to handle requests from clients concurrently using a
+ * process-per-connection model. It behaves as a "process factory",
+ * using @c ACE::fork() to fork threads "on-demand" to run the service
+ * specified by a user-supplied @c SVC_HANDLER in a separate process.
+ */
+template <class SVC_HANDLER>
+class ACE_Process_Strategy : public ACE_Concurrency_Strategy<SVC_HANDLER>
+{
+public:
+
+ // Useful STL-style traits.
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER> base_type;
+
+ // = Intialization and termination methods.
+
+ /// Initialize the strategy. If @a 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 @a 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 @a svc_handler with an appropriate concurrency
+ * strategy. This method activates the SVC_HANDLER by first forking
+ * and then calling the @c 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 @c 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:
+
+ // Useful STL-style traits.
+ typedef ACE_PEER_ACCEPTOR_ADDR addr_type;
+ typedef ACE_PEER_ACCEPTOR acceptor_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_Accept_Strategy (ACE_Reactor *reactor = ACE_Reactor::instance ());
+
+ /// Initialize the @c peer_acceptor_ with @a 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 @a local_addr, indicating
+ /// whether to @a 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:
+
+ // Useful STL-style traits.
+ typedef ACE_PEER_CONNECTOR_ADDR addr_type;
+ typedef ACE_PEER_CONNECTOR connector_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+
+ // = 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:
+
+ // Useful STL-style traits.
+ typedef typename SVC_HANDLER::addr_type addr_type;
+ typedef SVC_HANDLER handler_type;
+ typedef typename SVC_HANDLER::stream_type stream_type;
+
+ // = 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:
+
+ // Useful STL-style traits.
+ typedef ACE_Scheduling_Strategy<SVC_HANDLER> base_type;
+
+ // = 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:
+
+ /// Reactor
+ 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:
+
+ // Useful STL-style traits.
+ typedef ACE_Scheduling_Strategy<SVC_HANDLER> base_type;
+
+ // = 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:
+
+ // Useful STL-style traits.
+ typedef ACE_Creation_Strategy<SVC_HANDLER> base_type;
+
+ /// 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:
+
+ // Useful STL-style traits.
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER> base_type;
+
+ // = 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.
+ bool operator== (const ACE_Refcounted_Hash_Recyclable<T> &rhs) const;
+ bool 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:
+
+ // Useful STL-style traits.
+ typedef ACE_Creation_Strategy<SVC_HANDLER>
+ creation_strategy_type;
+ typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+ connect_strategy_type;
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER>
+ concurrency_strategy_type;
+ typedef ACE_Recycling_Strategy<SVC_HANDLER> recycling_strategy_type;
+
+ // = Define some useful (old style) traits.
+ 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;
+
+
+ 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,
+ bool delete_lock = false);
+
+ /// 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);
+
+ // = Traits for managing the map
+ typedef ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>
+ REFCOUNTED_HASH_RECYCLABLE_ADDRESS;
+ typedef ACE_Hash_Map_Manager_Ex<REFCOUNTED_HASH_RECYCLABLE_ADDRESS, SVC_HANDLER *, ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>, ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>, ACE_Null_Mutex>
+ CONNECTION_MAP;
+
+ typedef typename CONNECTION_MAP::ITERATOR CONNECTION_MAP_ITERATOR;
+ typedef typename CONNECTION_MAP::ENTRY 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 (REFCOUNTED_HASH_RECYCLABLE_ADDRESS &search_addr,
+ CONNECTION_MAP_ENTRY *&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);
+
+ /// Set <recycle_state> (non-locking version).
+ virtual int recycle_state_i (const void *recycling_act,
+ ACE_Recyclable_State new_state);
+
+ /// Get <recycle_state> (non-locking version).
+ 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,
+ CONNECTION_MAP_ENTRY *&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,
+ CONNECTION_MAP_ENTRY *&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_HANDLERs.
+ CONNECTION_MAP connection_map_;
+
+ /// Mutual exclusion for this object.
+ MUTEX *lock_;
+
+ /// Mutual exclusion for this object.
+ bool delete_lock_;
+
+ /// Reverse lock.
+ REVERSE_MUTEX *reverse_lock_;
+
+ // = Strategy objects.
+
+ /// Creation strategy for an <Connector>.
+ CREATION_STRATEGY *creation_strategy_;
+
+ /// true if <Connector> created the creation strategy and thus should
+ /// delete it, else false.
+ bool delete_creation_strategy_;
+
+ /// Concurrency strategy for an <Connector>.
+ CONCURRENCY_STRATEGY *concurrency_strategy_;
+
+ /// true if <Connector> created the concurrency strategy and thus should
+ /// delete it, else false.
+ bool delete_concurrency_strategy_;
+
+ /// Recycling strategy for an <Connector>.
+ RECYCLING_STRATEGY *recycling_strategy_;
+
+ /// true if <Connector> created the recycling strategy and thus should
+ /// delete it, else false.
+ bool delete_recycling_strategy_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Strategies_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#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/ace/Strategies_T.inl b/ACE/ace/Strategies_T.inl
new file mode 100644
index 00000000000..bf5f43fe4b2
--- /dev/null
+++ b/ACE/ace/Strategies_T.inl
@@ -0,0 +1,230 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class SVC_HANDLER> ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Singleton_Strategy")));
+}
+
+template <class SVC_HANDLER> ACE_INLINE int
+ACE_Creation_Strategy<SVC_HANDLER>::open (ACE_Thread_Manager *thr_mgr,
+ ACE_Reactor *reactor)
+{
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::open");
+ this->thr_mgr_ = thr_mgr;
+ this->reactor_ = reactor;
+ return 0;
+}
+
+template <class SVC_HANDLER> ACE_INLINE
+ACE_Creation_Strategy<SVC_HANDLER>::ACE_Creation_Strategy (ACE_Thread_Manager *thr_mgr,
+ ACE_Reactor *reactor)
+{
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::ACE_Creation_Strategy");
+ if (this->open (thr_mgr, reactor) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Creation_Strategy")));
+}
+
+template <class SVC_HANDLER> ACE_INLINE
+ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy (const ACE_TCHAR dll_name[],
+ const ACE_TCHAR factory_function[],
+ const ACE_TCHAR 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_TEXT ("%p\n"),
+ ACE_TEXT ("open")));
+}
+
+template <class SVC_HANDLER> ACE_INLINE
+ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy (void)
+{
+ ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy");
+}
+
+template <class SVC_HANDLER> ACE_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> ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Reactive_Strategy<SVC_HANDLER>::ACE_Reactive_Strategy")));
+}
+
+template <class SVC_HANDLER> ACE_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> ACE_INLINE
+ACE_Thread_Strategy<SVC_HANDLER>::ACE_Thread_Strategy (ACE_Thread_Manager *thr_mgr,
+ long thr_flags,
+ int 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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Thread_Strategy<SVC_HANDLER>::ACE_Thread_Strategy")));
+}
+
+template <class SVC_HANDLER> ACE_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, ACE_PEER_ACCEPTOR_1> ACE_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_CONNECTOR_1> ACE_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_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Process_Strategy")));
+}
+
+template <class SVC_HANDLER> ACE_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> ACE_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> ACE_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 T> ACE_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> ACE_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> ACE_INLINE u_long
+ACE_Refcounted_Hash_Recyclable<T>::hash_i (void) const
+{
+ return this->t_.hash ();
+}
+
+template <class T> ACE_INLINE T &
+ACE_Refcounted_Hash_Recyclable<T>::subject (void)
+{
+ return this->t_;
+}
+
+template <class T> ACE_INLINE bool
+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> ACE_INLINE bool
+ACE_Refcounted_Hash_Recyclable<T>::operator!= (const ACE_Refcounted_Hash_Recyclable<T> &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Stream.cpp b/ACE/ace/Stream.cpp
new file mode 100644
index 00000000000..a83e6cbd942
--- /dev/null
+++ b/ACE/ace/Stream.cpp
@@ -0,0 +1,619 @@
+// Stream.cpp
+// $Id$
+
+#ifndef ACE_STREAM_CPP
+#define ACE_STREAM_CPP
+
+//#include "ace/Module.h"
+#include "ace/Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Stream_Modules.h"
+#include "ace/OS_NS_string.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Stream)
+
+// Give some idea of what the heck is going on in a stream!
+
+template <ACE_SYNCH_DECL> void
+ACE_Stream<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("-------- module links --------\n")));
+
+ for (ACE_Module<ACE_SYNCH_USE> *mp = this->stream_head_;
+ ;
+ mp = mp->next ())
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("module name = %s\n"), mp->name ()));
+ if (mp == this->stream_tail_)
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("-------- writer links --------\n")));
+
+ ACE_Task<ACE_SYNCH_USE> *tp;
+
+ for (tp = this->stream_head_->writer ();
+ ;
+ tp = tp->next ())
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("writer queue name = %s\n"), tp->name ()));
+ tp->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("-------\n")));
+ if (tp == this->stream_tail_->writer ()
+ || (this->linked_us_
+ && tp == this->linked_us_->stream_head_->reader ()))
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("-------- reader links --------\n")));
+ for (tp = this->stream_tail_->reader (); ; tp = tp->next ())
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("reader queue name = %s\n"), tp->name ()));
+ tp->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("-------\n")));
+ if (tp == this->stream_head_->reader ()
+ || (this->linked_us_
+ && tp == this->linked_us_->stream_head_->writer ()))
+ break;
+ }
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::push (ACE_Module<ACE_SYNCH_USE> *new_top)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::push");
+ if (this->push_module (new_top,
+ this->stream_head_->next (),
+ this->stream_head_) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::put (ACE_Message_Block *mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::put");
+ return this->stream_head_->writer ()->put (mb, tv);
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::get (ACE_Message_Block *&mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::get");
+ return this->stream_head_->reader ()->getq (mb, tv);
+}
+
+// Return the "top" ACE_Module in a ACE_Stream, skipping over the
+// stream_head.
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::top (ACE_Module<ACE_SYNCH_USE> *&m)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::top");
+ if (this->stream_head_->next () == this->stream_tail_)
+ return -1;
+ else
+ {
+ m = this->stream_head_->next ();
+ return 0;
+ }
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::insert (const ACE_TCHAR *prev_name,
+ ACE_Module<ACE_SYNCH_USE> *mod)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::insert");
+
+ for (ACE_Module<ACE_SYNCH_USE> *prev_mod = this->stream_head_;
+ prev_mod != 0;
+ prev_mod = prev_mod->next ())
+ if (ACE_OS::strcmp (prev_mod->name (), prev_name) == 0)
+ {
+ ACE_Module<ACE_SYNCH_USE> *next_mod = prev_mod->next ();
+
+ // We can't insert a module below <stream_tail_>.
+ if (next_mod == 0)
+ return -1;
+
+ mod->link (next_mod);
+ prev_mod->link (mod);
+
+ if (mod->reader ()->open (mod->arg ()) == -1)
+ return -1;
+
+ if (mod->writer ()->open (mod->arg ()) == -1)
+ return -1;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::replace (const ACE_TCHAR *replace_name,
+ ACE_Module<ACE_SYNCH_USE> *mod,
+ int flags)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::replace");
+ ACE_Module<ACE_SYNCH_USE> *prev_mod = 0;
+
+ for (ACE_Module<ACE_SYNCH_USE> *rep_mod = this->stream_head_;
+ rep_mod != 0;
+ rep_mod = rep_mod->next ())
+ if (ACE_OS::strcmp (rep_mod->name (), replace_name) == 0)
+ {
+ ACE_Module<ACE_SYNCH_USE> *next_mod = rep_mod->next ();
+
+ if (next_mod)
+ mod->link (next_mod);
+ else // In case the <next_mod> is <stream_tail_>.
+ {
+ mod->writer ()->next (0);
+ mod->next (0);
+ this->stream_tail_ = mod;
+ }
+
+ if (prev_mod)
+ prev_mod->link (mod);
+ else // In case the <rep_mod> is <stream_head_>.
+ {
+ mod->reader ()->next (0);
+ this->stream_head_ = mod;
+ }
+
+ if (mod->reader ()->open (mod->arg ()) == -1)
+ return -1;
+
+ if (mod->writer ()->open (mod->arg ()) == -1)
+ return -1;
+
+ if (flags != ACE_Module<ACE_SYNCH_USE>::M_DELETE_NONE)
+ {
+ rep_mod->close (flags);
+ delete rep_mod;
+ }
+
+ return 0;
+ }
+ else
+ prev_mod = rep_mod;
+
+ return -1;
+}
+
+// Remove the "top" ACE_Module in a ACE_Stream, skipping over the
+// stream_head.
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::pop (int flags)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::pop");
+ if (this->stream_head_->next () == this->stream_tail_)
+ return -1;
+ else
+ {
+ // Skip over the ACE_Stream head.
+ ACE_Module<ACE_SYNCH_USE> *top_mod = this->stream_head_->next ();
+ ACE_Module<ACE_SYNCH_USE> *new_top = top_mod->next ();
+
+ this->stream_head_->next (new_top);
+
+ // Close the top ACE_Module.
+
+ top_mod->close (flags);
+
+ // Don't delete the Module unless the flags request this.
+ if (flags != ACE_Module<ACE_SYNCH_USE>::M_DELETE_NONE)
+ delete top_mod;
+
+ this->stream_head_->writer ()->next (new_top->writer ());
+ new_top->reader ()->next (this->stream_head_->reader ());
+ return 0;
+ }
+}
+
+// Remove a named ACE_Module from an arbitrary place in the
+// ACE_Stream.
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::remove (const ACE_TCHAR *name,
+ int flags)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::remove");
+ ACE_Module<ACE_SYNCH_USE> *prev = 0;
+
+ for (ACE_Module<ACE_SYNCH_USE> *mod = this->stream_head_;
+ mod != 0;
+ mod = mod->next ())
+ if (ACE_OS::strcmp (mod->name (), name) == 0)
+ {
+ if (prev == 0) // Deleting ACE_Stream Head
+ this->stream_head_->link (mod->next ());
+ else
+ prev->link (mod->next ());
+
+ // Don't delete the Module unless the flags request this.
+ if (flags != ACE_Module<ACE_SYNCH_USE>::M_DELETE_NONE)
+ {
+ // Close down the module and release the memory.
+ mod->close (flags);
+ delete mod;
+ }
+
+ return 0;
+ }
+ else
+ prev = mod;
+
+ return -1;
+}
+
+template <ACE_SYNCH_DECL> ACE_Module<ACE_SYNCH_USE> *
+ACE_Stream<ACE_SYNCH_USE>::find (const ACE_TCHAR *name)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::find");
+ for (ACE_Module<ACE_SYNCH_USE> *mod = this->stream_head_;
+ mod != 0;
+ mod = mod->next ())
+ if (ACE_OS::strcmp (mod->name (), name) == 0)
+ return mod;
+
+ return 0;
+}
+
+// Actually push a module onto the stack...
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::push_module (ACE_Module<ACE_SYNCH_USE> *new_top,
+ ACE_Module<ACE_SYNCH_USE> *current_top,
+ ACE_Module<ACE_SYNCH_USE> *head)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::push_module");
+ ACE_Task<ACE_SYNCH_USE> *nt_reader = new_top->reader ();
+ ACE_Task<ACE_SYNCH_USE> *nt_writer = new_top->writer ();
+ ACE_Task<ACE_SYNCH_USE> *ct_reader = 0;
+ ACE_Task<ACE_SYNCH_USE> *ct_writer = 0;
+
+ if (current_top)
+ {
+ ct_reader = current_top->reader ();
+ ct_writer = current_top->writer ();
+ ct_reader->next (nt_reader);
+ }
+
+ nt_writer->next (ct_writer);
+
+ if (head)
+ {
+ if (head != new_top)
+ head->link (new_top);
+ }
+ else
+ nt_reader->next (0);
+
+ new_top->next (current_top);
+
+ if (nt_reader->open (new_top->arg ()) == -1)
+ return -1;
+
+ if (nt_writer->open (new_top->arg ()) == -1)
+ return -1;
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::open (void *a,
+ ACE_Module<ACE_SYNCH_USE> *head,
+ ACE_Module<ACE_SYNCH_USE> *tail)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::open");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ ACE_Task<ACE_SYNCH_USE> *h1 = 0, *h2 = 0;
+ ACE_Task<ACE_SYNCH_USE> *t1 = 0, *t2 = 0;
+
+ if (head == 0)
+ {
+ ACE_NEW_RETURN (h1,
+ ACE_Stream_Head<ACE_SYNCH_USE>,
+ -1);
+ ACE_NEW_RETURN (h2,
+ ACE_Stream_Head<ACE_SYNCH_USE>,
+ -1);
+ ACE_NEW_RETURN (head,
+ ACE_Module<ACE_SYNCH_USE> (ACE_TEXT ("ACE_Stream_Head"),
+ h1, h2,
+ a,
+ M_DELETE),
+ -1);
+ }
+
+ if (tail == 0)
+ {
+ ACE_NEW_RETURN (t1,
+ ACE_Stream_Tail<ACE_SYNCH_USE>,
+ -1);
+ ACE_NEW_RETURN (t2,
+ ACE_Stream_Tail<ACE_SYNCH_USE>,
+ -1);
+ ACE_NEW_RETURN (tail,
+ ACE_Module<ACE_SYNCH_USE> (ACE_TEXT ("ACE_Stream_Tail"),
+ t1, t2,
+ a,
+ M_DELETE),
+ -1);
+ }
+
+ // Make sure *all* the allocation succeeded!
+ if (head == 0 && (h1 == 0 || h2 == 0)
+ || tail == 0 && (t1 == 0 || t2 == 0))
+ {
+ delete h1;
+ delete h2;
+ delete t1;
+ delete t2;
+ delete head;
+ delete tail;
+ errno = ENOMEM;
+ return -1;
+ }
+
+ this->stream_head_ = head;
+ this->stream_tail_ = tail;
+
+ if (this->push_module (this->stream_tail_) == -1)
+ return -1;
+ else if (this->push_module (this->stream_head_,
+ this->stream_tail_,
+ this->stream_head_) == -1)
+ return -1;
+
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::close (int flags)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::close");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ if (this->stream_head_ != 0
+ && this->stream_tail_ != 0)
+ {
+ // Don't bother checking return value here.
+ this->unlink_i ();
+
+ int result = 0;
+
+ // Remove and cleanup all the intermediate modules.
+
+ while (this->stream_head_->next () != this->stream_tail_)
+ if (this->pop (flags) == -1)
+ result = -1;
+
+ // Clean up the head and tail of the stream.
+ if (this->stream_head_->close (flags) == -1)
+ result = -1;
+ if (this->stream_tail_->close (flags) == -1)
+ result = -1;
+
+ // Cleanup the memory.
+ delete this->stream_head_;
+ delete this->stream_tail_;
+
+ this->stream_head_ = 0;
+ this->stream_tail_ = 0;
+
+ // Tell all threads waiting on the close that we are done.
+ this->final_close_.broadcast ();
+ return result;
+ }
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::control (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd,
+ void *a)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::control");
+ ACE_IO_Cntl_Msg ioc (cmd);
+
+ ACE_Message_Block *db;
+
+ // Try to create a data block that contains the user-supplied data.
+ ACE_NEW_RETURN (db,
+ ACE_Message_Block (sizeof (int),
+ ACE_Message_Block::MB_IOCTL,
+ 0,
+ (char *) a),
+ -1);
+ // Try to create a control block <cb> that contains the control
+ // field and a pointer to the data block <db> in <cb>'s continuation
+ // field.
+ ACE_Message_Block *cb = 0;
+
+ ACE_NEW_RETURN (cb,
+ ACE_Message_Block (sizeof ioc,
+ ACE_Message_Block::MB_IOCTL,
+ db,
+ (char *) &ioc),
+ -1);
+ // @@ Michael: The old semantic assumed that cb returns == 0
+ // if no memory was available. We will now return immediately
+ // without release (errno is set to ENOMEM by the macro).
+
+ // If we can't allocate <cb> then we need to delete db and return
+ // -1.
+ if (cb == 0)
+ {
+ db->release ();
+ errno = ENOMEM;
+ return -1;
+ }
+
+ int result;
+
+ if (this->stream_head_->writer ()->put (cb) == -1)
+ result = -1;
+ else if (this->stream_head_->reader ()->getq (cb) == -1)
+ result = -1;
+ else
+ result = ((ACE_IO_Cntl_Msg *) cb->rd_ptr ())->rval ();
+
+ // This will also release db if it's reference count == 0.
+ cb->release ();
+
+ return result;
+}
+
+// Link two streams together at their bottom-most Modules (i.e., the
+// one just above the Stream tail). Note that all of this is premised
+// on the fact that the Stream head and Stream tail are non-NULL...
+// This must be called with locks held.
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::link_i (ACE_Stream<ACE_SYNCH_USE> &us)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::link_i");
+ this->linked_us_ = &us;
+ // Make sure the other side is also linked to us!
+ us.linked_us_ = this;
+
+ ACE_Module<ACE_SYNCH_USE> *my_tail = this->stream_head_;
+
+ if (my_tail == 0)
+ return -1;
+
+ // Locate the module just above our Stream tail.
+ while (my_tail->next () != this->stream_tail_)
+ my_tail = my_tail->next ();
+
+ ACE_Module<ACE_SYNCH_USE> *other_tail = us.stream_head_;
+
+ if (other_tail == 0)
+ return -1;
+
+ // Locate the module just above the other Stream's tail.
+ while (other_tail->next () != us.stream_tail_)
+ other_tail = other_tail->next ();
+
+ // Reattach the pointers so that the two streams are linked!
+ my_tail->writer ()->next (other_tail->reader ());
+ other_tail->writer ()->next (my_tail->reader ());
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::link (ACE_Stream<ACE_SYNCH_USE> &us)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::link");
+
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+
+ return this->link_i (us);
+}
+
+// Must be called with locks held...
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::unlink_i (void)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::unlink_i");
+
+ // Only try to unlink if we are in fact still linked!
+
+ if (this->linked_us_ != 0)
+ {
+ ACE_Module<ACE_SYNCH_USE> *my_tail = this->stream_head_;
+
+ // Only relink if we still exist!
+ if (my_tail)
+ {
+ // Find the module that's just before our stream tail.
+ while (my_tail->next () != this->stream_tail_)
+ my_tail = my_tail->next ();
+
+ // Restore the writer's next() link to our tail.
+ my_tail->writer ()->next (this->stream_tail_->writer ());
+ }
+
+ ACE_Module<ACE_SYNCH_USE> *other_tail =
+ this->linked_us_->stream_head_;
+
+ // Only fiddle with the other side if it in fact still remains.
+ if (other_tail != 0)
+ {
+ while (other_tail->next () != this->linked_us_->stream_tail_)
+ other_tail = other_tail->next ();
+
+ other_tail->writer ()->next (this->linked_us_->stream_tail_->writer ());
+
+ }
+
+ // Make sure the other side is also aware that it's been unlinked!
+ this->linked_us_->linked_us_ = 0;
+
+ this->linked_us_ = 0;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream<ACE_SYNCH_USE>::unlink (void)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::unlink");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->lock_, -1);
+ return this->unlink_i ();
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Stream<ACE_SYNCH_USE>::ACE_Stream (void * a,
+ ACE_Module<ACE_SYNCH_USE> *head,
+ ACE_Module<ACE_SYNCH_USE> *tail)
+ : linked_us_ (0),
+ final_close_ (lock_)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::ACE_Stream");
+ if (this->open (a, head, tail) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_Stream<ACE_SYNCH_USE>::open (%s, %s)\n"),
+ head->name (), tail->name ()));
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Stream<ACE_SYNCH_USE>::~ACE_Stream (void)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::~ACE_Stream");
+
+ if (this->stream_head_ != 0)
+ this->close ();
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Stream_Iterator<ACE_SYNCH_USE>::ACE_Stream_Iterator (const ACE_Stream<ACE_SYNCH_USE> &sr)
+ : next_ (sr.stream_head_)
+{
+ ACE_TRACE ("ACE_Stream_Iterator<ACE_SYNCH_USE>::ACE_Stream_Iterator");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_STREAM_CPP */
diff --git a/ACE/ace/Stream.h b/ACE/ace/Stream.h
new file mode 100644
index 00000000000..da558b89d4b
--- /dev/null
+++ b/ACE/ace/Stream.h
@@ -0,0 +1,241 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Stream.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@uci.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_STREAM_H
+#define ACE_STREAM_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/IO_Cntl_Msg.h"
+#include "ace/Message_Block.h"
+#include "ace/Module.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls.
+template<ACE_SYNCH_DECL> class ACE_Stream_Iterator;
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Stream
+ *
+ * @brief This class is the primary abstraction for the ASX framework.
+ * It is moduled after System V Stream.
+ *
+ * A Stream consists of a stack of <ACE_Modules>, each of which
+ * contains two <ACE_Tasks>. Even though the methods in this
+ * class are virtual, this class isn't really intended for
+ * subclassing unless you know what you are doing. In
+ * particular, the ACE_Stream destructor calls <close>, which
+ * won't be overridden properly unless you call it in a subclass
+ * destructor.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Stream
+{
+public:
+ friend class ACE_Stream_Iterator<ACE_SYNCH_USE>;
+
+ enum
+ {
+ /// Indicates that <close> deletes the Tasks. Don't change this
+ /// value without updating the same enum in class ACE_Module...
+ M_DELETE = 3
+ };
+
+ // = Initializatation and termination methods.
+ /**
+ * Create a Stream consisting of <head> and <tail> as the Stream
+ * head and Stream tail, respectively. If these are 0 then the
+ * <ACE_Stream_Head> and <ACE_Stream_Tail> are used, respectively.
+ * <arg> is the value past in to the <open> methods of the tasks.
+ */
+ ACE_Stream (void *arg = 0,
+ ACE_Module<ACE_SYNCH_USE> *head = 0,
+ ACE_Module<ACE_SYNCH_USE> *tail = 0);
+
+ /**
+ * Create a Stream consisting of <head> and <tail> as the Stream
+ * head and Stream tail, respectively. If these are 0 then the
+ * <ACE_Stream_Head> and <ACE_Stream_Tail> are used, respectively.
+ * <arg> is the value past in to the <open> methods of the tasks.
+ */
+ virtual int open (void *arg,
+ ACE_Module<ACE_SYNCH_USE> *head = 0,
+ ACE_Module<ACE_SYNCH_USE> *tail = 0);
+
+ /// Close down the stream and release all the resources.
+ virtual int close (int flags = M_DELETE);
+
+ /// Close down the stream and release all the resources.
+ virtual ~ACE_Stream (void);
+
+ // = ACE_Stream plumbing operations
+
+ /// Add a new module <mod> right below the Stream head. The
+ /// <open()> hook methods of the <ACE_Tasks> in this ACE_Module
+ /// are invoked to initialize the tasks.
+ virtual int push (ACE_Module<ACE_SYNCH_USE> *mod);
+
+ /// Remove the <mod> right below the Stream head and close it down.
+ // The <close()> hook methods of the <ACE_Tasks> in this ACE_Module
+ /// are invoked to cleanup the tasks.
+ virtual int pop (int flags = M_DELETE);
+
+ /// Return the top module on the stream (right below the stream
+ /// head).
+ virtual int top (ACE_Module<ACE_SYNCH_USE> *&mod);
+
+ /// Insert a new module <mod> below the named module <prev_name>.
+ virtual int insert (const ACE_TCHAR *prev_name,
+ ACE_Module<ACE_SYNCH_USE> *mod);
+
+ /// Replace the named module <replace_name> with a new module <mod>.
+ virtual int replace (const ACE_TCHAR *replace_name,
+ ACE_Module<ACE_SYNCH_USE> *mod,
+ int flags = M_DELETE);
+
+ /// Remove the named module <mod> from the stream. This bypasses the
+ /// strict LIFO ordering of <push> and <pop>.
+ virtual int remove (const ACE_TCHAR *mod,
+ int flags = M_DELETE);
+
+ /// Return current stream head.
+ virtual ACE_Module<ACE_SYNCH_USE> *head (void);
+
+ /// Return current stream tail.
+ virtual ACE_Module<ACE_SYNCH_USE> *tail (void);
+
+ /// Find a particular ACE_Module.
+ virtual ACE_Module<ACE_SYNCH_USE> *find (const ACE_TCHAR *mod);
+
+ /// Create a pipe between two Streams.
+ virtual int link (ACE_Stream<ACE_SYNCH_USE> &);
+
+ /// Remove a pipe formed between two Streams.
+ virtual int unlink (void);
+
+ // = Blocking data transfer operations
+ /**
+ * Send the message @a mb down the stream, starting at the Module
+ * below the Stream head. Wait for upto @a timeout amount of
+ * absolute time for the operation to complete (or block forever if
+ * @a timeout == 0).
+ */
+ virtual int put (ACE_Message_Block *mb,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Read the message @a mb that is stored in the stream head.
+ * Wait for upto @a timeout amount of absolute time for the operation
+ * to complete (or block forever if @a timeout == 0).
+ */
+ virtual int get (ACE_Message_Block *&mb,
+ ACE_Time_Value *timeout = 0);
+
+ /// Send control message down the stream.
+ virtual int control (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd,
+ void *args);
+
+ /// Synchronize with the final close of the stream.
+ virtual int wait (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Actually perform the unlinking of two Streams (must be called
+ /// with locks held).
+ int unlink_i (void);
+
+ /// Actually perform the linking of two Streams (must be called with
+ /// locks held).
+ int link_i (ACE_Stream<ACE_SYNCH_USE> &);
+
+ /// Must a new module onto the Stream.
+ int push_module (ACE_Module<ACE_SYNCH_USE> *,
+ ACE_Module<ACE_SYNCH_USE> * = 0,
+ ACE_Module<ACE_SYNCH_USE> * = 0);
+
+ /// Pointer to the head of the stream.
+ ACE_Module<ACE_SYNCH_USE> *stream_head_;
+
+ /// Pointer to the tail of the stream.
+ ACE_Module<ACE_SYNCH_USE> *stream_tail_;
+
+ /// Pointer to an adjoining linked stream.
+ ACE_Stream<ACE_SYNCH_USE> *linked_us_;
+
+ // = Synchronization objects used for thread-safe streams.
+ /// Protect the stream against race conditions.
+ ACE_SYNCH_MUTEX_T lock_;
+
+ /// Use to tell all threads waiting on the close that we are done.
+ ACE_SYNCH_CONDITION_T final_close_;
+};
+
+/**
+ * @class ACE_Stream_Iterator
+ *
+ * @brief Iterate through an ACE_Stream.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Stream_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Stream_Iterator (const ACE_Stream<ACE_SYNCH_USE> &sr);
+
+ // = 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 (const ACE_Module<ACE_SYNCH_USE> *&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);
+
+private:
+ /// Next <Module> that we haven't yet seen.
+ ACE_Module<ACE_SYNCH_USE> *next_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Stream.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Stream.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_STREAM_H */
diff --git a/ACE/ace/Stream.inl b/ACE/ace/Stream.inl
new file mode 100644
index 00000000000..24ff6840431
--- /dev/null
+++ b/ACE/ace/Stream.inl
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <ACE_SYNCH_DECL> ACE_INLINE ACE_Module<ACE_SYNCH_USE> *
+ACE_Stream<ACE_SYNCH_USE>::head (void)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::head");
+ return this->stream_head_;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE ACE_Module<ACE_SYNCH_USE> *
+ACE_Stream<ACE_SYNCH_USE>::tail (void)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::tail");
+ return this->stream_tail_;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Stream<ACE_SYNCH_USE>::wait (void)
+{
+ ACE_TRACE ("ACE_Stream<ACE_SYNCH_USE>::wait");
+ return this->final_close_.wait ();
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Stream_Iterator<ACE_SYNCH_USE>::next (const ACE_Module<ACE_SYNCH_USE> *&mod)
+{
+ ACE_TRACE ("ACE_Stream_Iterator<ACE_SYNCH_USE>::next");
+ mod = this->next_;
+ return this->next_ != 0;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Stream_Iterator<ACE_SYNCH_USE>::done (void) const
+{
+ ACE_TRACE ("ACE_Stream_Iterator<ACE_SYNCH_USE>::done");
+ return this->next_ == 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Iterator<ACE_SYNCH_USE>::advance (void)
+{
+ ACE_TRACE ("ACE_Stream_Iterator<ACE_SYNCH_USE>::advance");
+ this->next_ = this->next_->next ();
+ return this->next_ != 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Stream_Modules.cpp b/ACE/ace/Stream_Modules.cpp
new file mode 100644
index 00000000000..69163951323
--- /dev/null
+++ b/ACE/ace/Stream_Modules.cpp
@@ -0,0 +1,380 @@
+// $Id$
+
+#ifndef ACE_STREAM_MODULES_CPP
+#define ACE_STREAM_MODULES_CPP
+
+#include "ace/Stream_Modules.h"
+#include "ace/OS_NS_string.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Stream_Head)
+
+template <ACE_SYNCH_DECL>
+ACE_Stream_Head<ACE_SYNCH_USE>::ACE_Stream_Head (void)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::ACE_Stream_Head");
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Stream_Head<ACE_SYNCH_USE>::~ACE_Stream_Head (void)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::~ACE_Stream_Head");
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Stream_Head<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+// ACE_Module that act as the head and tail of a Stream.
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::open (void *)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::open");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::close (u_long)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::close");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::svc (void)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::svc");
+ return -1;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::control (ACE_Message_Block *mb)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::control");
+ ACE_IO_Cntl_Msg *ioc = (ACE_IO_Cntl_Msg *) mb->rd_ptr ();
+ ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd;
+
+ switch (cmd = ioc->cmd ())
+ {
+ case ACE_IO_Cntl_Msg::SET_LWM:
+ case ACE_IO_Cntl_Msg::SET_HWM:
+ this->water_marks (cmd, *(size_t *) mb->cont ()->rd_ptr ());
+ ioc->rval (0);
+ break;
+ default:
+ return 0;
+ }
+ return ioc->rval ();
+}
+
+// Performs canonical flushing at the ACE_Stream Head.
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::canonical_flush (ACE_Message_Block *mb)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::canonical_flush");
+ char *cp = mb->rd_ptr ();
+
+ if (ACE_BIT_ENABLED (*cp, ACE_Task_Flags::ACE_FLUSHR))
+ {
+ this->flush (ACE_Task_Flags::ACE_FLUSHALL);
+ ACE_CLR_BITS (*cp, ACE_Task_Flags::ACE_FLUSHR);
+ }
+
+ if (ACE_BIT_ENABLED (*cp, ACE_Task_Flags::ACE_FLUSHW))
+ return this->reply (mb);
+ else
+ mb->release ();
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::put");
+ int res = 0;
+
+ if (mb->msg_type () == ACE_Message_Block::MB_IOCTL
+ && (res = this->control (mb)) == -1)
+ return res;
+
+ if (this->is_writer ())
+ return this->put_next (mb, tv);
+ else // this->is_reader ()
+ {
+ switch (mb->msg_type ())
+ {
+ case ACE_Message_Block::MB_FLUSH:
+ return this->canonical_flush (mb);
+ default:
+ break;
+ }
+
+ return this->putq (mb, tv);
+ }
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::init (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::init");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::info");
+ const ACE_TCHAR *name = this->name ();
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (name)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, name, length);
+ return static_cast<int> (ACE_OS::strlen (name));
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Head<ACE_SYNCH_USE>::fini (void)
+{
+ ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_USE>::fini");
+ return 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Stream_Tail)
+
+template <ACE_SYNCH_DECL>
+ACE_Stream_Tail<ACE_SYNCH_USE>::ACE_Stream_Tail (void)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::ACE_Stream_Tail");
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Stream_Tail<ACE_SYNCH_USE>::~ACE_Stream_Tail (void)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::~ACE_Stream_Tail");
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Stream_Tail<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::open (void *)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::open");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::close (u_long)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::close");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::svc (void)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::svc");
+ return -1;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::control (ACE_Message_Block *mb)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::control");
+ ACE_IO_Cntl_Msg *ioc = (ACE_IO_Cntl_Msg *) mb->rd_ptr ();
+ ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd;
+
+ switch (cmd = ioc->cmd ())
+ {
+ case ACE_IO_Cntl_Msg::SET_LWM:
+ case ACE_IO_Cntl_Msg::SET_HWM:
+ {
+ size_t wm_size = *(size_t *) mb->cont ()->rd_ptr ();
+
+ this->water_marks (cmd, wm_size);
+ this->sibling ()->water_marks (cmd, wm_size);
+ ioc->rval (0);
+ break;
+ }
+ default:
+ mb->msg_type (ACE_Message_Block::MB_IOCNAK);
+ }
+ return this->reply (mb);
+}
+
+// Perform flush algorithm as though we were the driver.
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::canonical_flush (ACE_Message_Block *mb)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::canonical_flush");
+ char *cp = mb->rd_ptr ();
+
+ if (ACE_BIT_ENABLED (*cp, ACE_Task_Flags::ACE_FLUSHW))
+ {
+ this->flush (ACE_Task_Flags::ACE_FLUSHALL);
+ ACE_CLR_BITS (*cp, ACE_Task_Flags::ACE_FLUSHW);
+ }
+
+ if (ACE_BIT_ENABLED (*cp, ACE_Task_Flags::ACE_FLUSHR))
+ {
+ this->sibling ()->flush (ACE_Task_Flags::ACE_FLUSHALL);
+ return this->reply (mb);
+ }
+ else
+ mb->release ();
+
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::put (ACE_Message_Block *mb,
+ ACE_Time_Value *)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::put");
+
+ if (this->is_writer ())
+ {
+ switch (mb->msg_type ())
+ {
+ case ACE_Message_Block::MB_IOCTL:
+ return this->control (mb);
+ /* NOTREACHED */
+ default:
+ mb->release ();
+ return 0;
+ /* NOTREACHED */
+ }
+ }
+
+ return -1;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::init (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::init");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::info");
+ const ACE_TCHAR *name = this->name ();
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (name)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, name, length);
+ return static_cast<int> (ACE_OS::strlen (name));
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Stream_Tail<ACE_SYNCH_USE>::fini (void)
+{
+ ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_USE>::fini");
+ return 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Thru_Task)
+
+template <ACE_SYNCH_DECL>
+ACE_Thru_Task<ACE_SYNCH_USE>::ACE_Thru_Task (void)
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::ACE_Thru_Task");
+}
+
+template <ACE_SYNCH_DECL>
+ACE_Thru_Task<ACE_SYNCH_USE>::~ACE_Thru_Task (void)
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::~ACE_Thru_Task");
+}
+
+template <ACE_SYNCH_DECL> void
+ACE_Thru_Task<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Thru_Task<ACE_SYNCH_USE>::open (void *)
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::open");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Thru_Task<ACE_SYNCH_USE>::close (u_long)
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::close");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Thru_Task<ACE_SYNCH_USE>::svc (void)
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::svc");
+ return -1;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Thru_Task<ACE_SYNCH_USE>::put (ACE_Message_Block *msg,
+ ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::put");
+ return this->put_next (msg, tv);
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Thru_Task<ACE_SYNCH_USE>::init (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::init");
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Thru_Task<ACE_SYNCH_USE>::info (ACE_TCHAR **strp,
+ size_t length) const
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::info");
+ const ACE_TCHAR *name = this->name ();
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (name)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, name, length);
+ return static_cast<int> (ACE_OS::strlen (name));
+}
+
+template <ACE_SYNCH_DECL> int
+ACE_Thru_Task<ACE_SYNCH_USE>::fini (void)
+{
+ ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_USE>::fini");
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_STREAM_MODULES_CPP */
diff --git a/ACE/ace/Stream_Modules.h b/ACE/ace/Stream_Modules.h
new file mode 100644
index 00000000000..10d396c95f5
--- /dev/null
+++ b/ACE/ace/Stream_Modules.h
@@ -0,0 +1,166 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Stream_Modules.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+// This needs to go outside of the #if !defined() block. Don't ask...
+#include "ace/Task.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#ifndef ACE_STREAM_MODULES
+#define ACE_STREAM_MODULES
+#include /**/ "ace/pre.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Stream_Head
+ *
+ * @brief Standard task that acts as reader or writer at the head of
+ * an ACE_Stream.
+ *
+ * A ACE_Message_Block sent to this task (via its put() hook) triggers
+ * actions depending on the block type and whether the task is acting as
+ * a reader or a writer. If the block is of type ACE_Message_Block::MB_IOCTL,
+ * the block's is assumed to contain (beginning at its rd_ptr()) an
+ * ACE_IO_Cntl_Msg object and is processed accordingly. This is usually
+ * used to set the task's message queue high water and/or low water marks.
+ *
+ * When the block is not ACE_Message_Block::MB_IOCTL, processing depends on
+ * the ACE_Stream_Head's role in the module:
+ *
+ * - Reader: If the block is of type ACE_Message_Block::MB_FLUSH, the
+ * canonical_flush() method is called.
+ * (@see ACE_Stream::canonical_flush().) If the block is any other
+ * type, it is queued on this task's message queue. It would thus
+ * be available to caller's reading blocks from the containing
+ * stream.
+ * - Writer: The block is passed to the next module in the stream.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Stream_Head : public ACE_Task<ACE_SYNCH_USE>
+{
+public:
+ /// Construction
+ ACE_Stream_Head (void);
+
+ /// Destruction
+ ~ACE_Stream_Head (void);
+
+ // = ACE_Task hooks
+ virtual int open (void *a = 0);
+ virtual int close (u_long flags = 0);
+ virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0);
+ virtual int svc (void);
+
+ // = Dynamic linking hooks
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+ virtual int fini (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Performs canonical flushing at the ACE_Stream Head.
+ int control (ACE_Message_Block *);
+ int canonical_flush (ACE_Message_Block *);
+};
+
+/**
+ * @class ACE_Stream_Tail
+ *
+ * @brief Standard module that acts as the head of a stream.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Stream_Tail : public ACE_Task<ACE_SYNCH_USE>
+{
+public:
+ /// Construction
+ ACE_Stream_Tail (void);
+
+ /// Destruction
+ ~ACE_Stream_Tail (void);
+
+ // = ACE_Task hooks
+ virtual int open (void *a = 0);
+ virtual int close (u_long flags = 0);
+ virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0);
+ virtual int svc (void);
+
+ // = Dynamic linking hooks
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+ virtual int fini (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Performs canonical flushing at the ACE_Stream tail.
+ int control (ACE_Message_Block *);
+ int canonical_flush (ACE_Message_Block *);
+};
+
+/**
+ * @class ACE_Thru_Task
+ *
+ * @brief Standard module that acts as a "no op", simply passing on all
+ * data to its adjacent neighbor.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Thru_Task : public ACE_Task<ACE_SYNCH_USE>
+{
+public:
+ /// Construction
+ ACE_Thru_Task (void);
+
+ /// Destruction
+ ~ACE_Thru_Task (void);
+
+ // = ACE_Task hooks
+ virtual int open (void *a = 0);
+ virtual int close (u_long flags = 0);
+ virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0);
+ virtual int svc (void);
+
+ // = Dynamic linking hooks
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+ virtual int fini (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Stream_Modules.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Stream_Modules.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_STREAM_MODULES */
diff --git a/ACE/ace/String_Base.cpp b/ACE/ace/String_Base.cpp
new file mode 100644
index 00000000000..12850c9c29a
--- /dev/null
+++ b/ACE/ace/String_Base.cpp
@@ -0,0 +1,563 @@
+// $Id$
+
+#ifndef ACE_STRING_BASE_CPP
+#define ACE_STRING_BASE_CPP
+
+#include "ace/ACE.h"
+#include "ace/Malloc_Base.h"
+#include "ace/String_Base.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/OS_NS_string.h"
+
+#include <algorithm> // For std::swap<>
+
+#if !defined (__ACE_INLINE__)
+#include "ace/String_Base.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_String_Base)
+
+template <class CHAR>
+CHAR ACE_String_Base<CHAR>::NULL_String_ = 0;
+
+// Default constructor.
+
+template <class CHAR>
+ACE_String_Base<CHAR>::ACE_String_Base (ACE_Allocator *the_allocator)
+ : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
+ len_ (0),
+ buf_len_ (0),
+ rep_ (&ACE_String_Base<CHAR>::NULL_String_),
+ release_ (false)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
+}
+
+// Constructor that actually copies memory.
+
+template <class CHAR>
+ACE_String_Base<CHAR>::ACE_String_Base (const CHAR *s,
+ ACE_Allocator *the_allocator,
+ bool release)
+ : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
+ len_ (0),
+ buf_len_ (0),
+ rep_ (0),
+ release_ (false)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
+ this->set (s, release);
+}
+
+template <class CHAR>
+ACE_String_Base<CHAR>::ACE_String_Base (CHAR c,
+ ACE_Allocator *the_allocator)
+ : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
+ len_ (0),
+ buf_len_ (0),
+ rep_ (0),
+ release_ (false)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
+
+ this->set (&c, 1, true);
+}
+
+// Constructor that actually copies memory.
+
+template <class CHAR>
+ACE_String_Base<CHAR>::ACE_String_Base (
+ const CHAR *s,
+ typename ACE_String_Base<CHAR>::size_type len,
+ ACE_Allocator *the_allocator,
+ bool release)
+ : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
+ len_ (0),
+ buf_len_ (0),
+ rep_ (0),
+ release_ (false)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
+
+ this->set (s, len, release);
+}
+
+// Copy constructor.
+
+template <class CHAR>
+ACE_String_Base<CHAR>::ACE_String_Base (const ACE_String_Base<CHAR> &s)
+ : allocator_ (s.allocator_ ? s.allocator_ : ACE_Allocator::instance ()),
+ len_ (0),
+ buf_len_ (0),
+ rep_ (0),
+ release_ (false)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
+
+ this->set (s.rep_, s.len_, true);
+}
+
+template <class CHAR>
+ACE_String_Base<CHAR>::ACE_String_Base (
+ typename ACE_String_Base<CHAR>::size_type len,
+ CHAR c,
+ ACE_Allocator *the_allocator)
+ : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
+ len_ (0),
+ buf_len_ (0),
+ rep_ (0),
+ release_ (false)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
+
+ this->resize (len, c);
+}
+
+template <class CHAR>
+ACE_String_Base<CHAR>::~ACE_String_Base (void)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::~ACE_String_Base");
+
+ if (this->buf_len_ != 0 && this->release_)
+ this->allocator_->free (this->rep_);
+}
+
+// this method might benefit from a little restructuring.
+template <class CHAR> void
+ACE_String_Base<CHAR>::set (const CHAR *s,
+ typename ACE_String_Base<CHAR>::size_type len,
+ bool release)
+{
+ // Case 1. Going from memory to more memory
+ size_type new_buf_len = len + 1;
+ if (s != 0 && len != 0 && release && this->buf_len_ < new_buf_len)
+ {
+ CHAR *temp;
+ ACE_ALLOCATOR (temp,
+ (CHAR *) this->allocator_->malloc (new_buf_len * sizeof (CHAR)));
+
+ if (this->buf_len_ != 0 && this->release_)
+ this->allocator_->free (this->rep_);
+
+ this->rep_ = temp;
+ this->buf_len_ = new_buf_len;
+ this->release_ = true;
+ this->len_ = len;
+ ACE_OS::memcpy (this->rep_, s, len * sizeof (CHAR));
+ this->rep_[len] = 0;
+ }
+ else // Case 2. No memory allocation is necessary.
+ {
+ // Free memory if necessary and figure out future ownership
+ if (!release || s == 0 || len == 0)
+ {
+ if (this->buf_len_ != 0 && this->release_)
+ {
+ this->allocator_->free (this->rep_);
+ this->release_ = false;
+ }
+ }
+ // Populate data.
+ if (s == 0 || len == 0)
+ {
+ this->buf_len_ = 0;
+ this->len_ = 0;
+ this->rep_ = &ACE_String_Base<CHAR>::NULL_String_;
+ this->release_ = false;
+ }
+ else if (!release) // Note: No guarantee that rep_ is null terminated.
+ {
+ this->buf_len_ = len;
+ this->len_ = len;
+ this->rep_ = const_cast <CHAR *> (s);
+ this->release_ = false;
+ }
+ else
+ {
+ ACE_OS::memcpy (this->rep_, s, len * sizeof (CHAR));
+ this->rep_[len] = 0;
+ this->len_ = len;
+ }
+ }
+}
+
+// Return substring.
+template <class CHAR> ACE_String_Base<CHAR>
+ACE_String_Base<CHAR>::substring (
+ typename ACE_String_Base<CHAR>::size_type offset,
+ typename ACE_String_Base<CHAR>::size_type length) const
+{
+ ACE_String_Base<CHAR> nill;
+ size_type count = length;
+
+ // case 1. empty string
+ if (this->len_ == 0)
+ return nill;
+
+ // case 2. start pos past our end
+ if (offset >= this->len_)
+ return nill;
+ // No length == empty string.
+ else if (length == 0)
+ return nill;
+ // Get all remaining bytes.
+ else if (length == npos || count > (this->len_ - offset))
+ count = this->len_ - offset;
+
+ return ACE_String_Base<CHAR> (&this->rep_[offset], count, this->allocator_);
+}
+
+template <class CHAR> ACE_String_Base<CHAR> &
+ACE_String_Base<CHAR>::append (const CHAR* s,
+ typename ACE_String_Base<CHAR>::size_type slen)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::append(const CHAR*, size_type)");
+ if (slen > 0 && slen != npos)
+ {
+ // case 1. No memory allocation needed.
+ if (this->buf_len_ >= this->len_ + slen + 1)
+ {
+ // Copy in data from new string.
+ ACE_OS::memcpy (this->rep_ + this->len_, s, slen * sizeof (CHAR));
+ }
+ else // case 2. Memory reallocation is needed
+ {
+ const size_type new_buf_len =
+ ace_max(this->len_ + slen + 1, this->buf_len_ + this->buf_len_ / 2);
+
+ CHAR *t = 0;
+
+ ACE_ALLOCATOR_RETURN (t,
+ (CHAR *) this->allocator_->malloc (new_buf_len * sizeof (CHAR)), *this);
+
+ // Copy memory from old string into new string.
+ ACE_OS::memcpy (t, this->rep_, this->len_ * sizeof (CHAR));
+
+ ACE_OS::memcpy (t + this->len_, s, slen * sizeof (CHAR));
+
+ if (this->buf_len_ != 0 && this->release_)
+ this->allocator_->free (this->rep_);
+
+ this->release_ = true;
+ this->rep_ = t;
+ this->buf_len_ = new_buf_len;
+ }
+
+ this->len_ += slen;
+ this->rep_[this->len_] = 0;
+ }
+
+ return *this;
+}
+
+template <class CHAR> u_long
+ACE_String_Base<CHAR>::hash (void) const
+{
+ return
+ ACE::hash_pjw (reinterpret_cast<char *> (
+ const_cast<CHAR *> (this->rep_)),
+ this->len_ * sizeof (CHAR));
+}
+
+template <class CHAR> void
+ACE_String_Base<CHAR>::resize (typename ACE_String_Base<CHAR>::size_type len,
+ CHAR c)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::resize");
+
+ fast_resize(len);
+ ACE_OS::memset (this->rep_, c, this->buf_len_ * sizeof (CHAR));
+}
+
+template <class CHAR> void
+ACE_String_Base<CHAR>::fast_resize (size_t len)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::fast_resize");
+
+ // Only reallocate if we don't have enough space...
+ if (this->buf_len_ <= len)
+ {
+ if (this->buf_len_ != 0 && this->release_)
+ this->allocator_->free (this->rep_);
+
+ this->rep_ = static_cast<CHAR*>
+ (this->allocator_->malloc ((len + 1) * sizeof (CHAR)));
+ this->buf_len_ = len + 1;
+ this->release_ = true;
+ }
+ this->len_ = 0;
+ if (len > 0)
+ this->rep_[0] = 0;
+}
+
+template <class CHAR> void
+ACE_String_Base<CHAR>::clear (bool release)
+{
+ // This can't use set(), because that would free memory if release=false
+ if (release)
+ {
+ if (this->buf_len_ != 0 && this->release_)
+ this->allocator_->free (this->rep_);
+
+ this->rep_ = &ACE_String_Base<CHAR>::NULL_String_;
+ this->len_ = 0;
+ this->buf_len_ = 0;
+ this->release_ = false;
+ }
+ else
+ {
+ this->fast_clear ();
+ }
+}
+
+// Assignment operator (does copy memory).
+template <class CHAR> ACE_String_Base<CHAR> &
+ACE_String_Base<CHAR>::operator= (const CHAR *s)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator=");
+ if (s != 0)
+ this->set (s, true);
+ return *this;
+}
+
+// Assignment operator (does copy memory).
+template <class CHAR> ACE_String_Base<CHAR> &
+ACE_String_Base<CHAR>::operator= (const ACE_String_Base<CHAR> &s)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator=");
+
+ // Check for self-assignment.
+ if (this != &s)
+ {
+ this->set (s.rep_, s.len_, true);
+ }
+
+ return *this;
+}
+
+template <class CHAR> void
+ACE_String_Base<CHAR>::set (const CHAR *s, bool release)
+{
+ size_t length = 0;
+ if (s != 0)
+ length = ACE_OS::strlen (s);
+
+ this->set (s, length, release);
+}
+
+template <class CHAR> void
+ACE_String_Base<CHAR>::fast_clear (void)
+{
+ this->len_ = 0;
+ if (this->release_)
+ {
+ // String retains the original buffer.
+ if (this->rep_ != &ACE_String_Base<CHAR>::NULL_String_)
+ this->rep_[0] = 0;
+ }
+ else
+ {
+ // External buffer: string relinquishes control of it.
+ this->buf_len_ = 0;
+ this->rep_ = &ACE_String_Base<CHAR>::NULL_String_;
+ }
+}
+
+// Get a copy of the underlying representation.
+
+template <class CHAR> CHAR *
+ACE_String_Base<CHAR>::rep (void) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::rep");
+
+ CHAR *new_string;
+ ACE_NEW_RETURN (new_string, CHAR[this->len_ + 1], 0);
+ ACE_OS::strsncpy (new_string, this->rep_, this->len_+1);
+
+ return new_string;
+}
+
+template <class CHAR> int
+ACE_String_Base<CHAR>::compare (const ACE_String_Base<CHAR> &s) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::compare");
+
+ if (this->rep_ == s.rep_)
+ return 0;
+
+ // Pick smaller of the two lengths and perform the comparison.
+ size_type smaller_length = ace_min (this->len_, s.len_);
+
+ int result = ACE_OS::memcmp (this->rep_,
+ s.rep_,
+ smaller_length * sizeof (CHAR));
+
+ if (!result)
+ result = static_cast<int> (this->len_ - s.len_);
+ return result;
+}
+
+// Comparison operator.
+
+template <class CHAR> bool
+ACE_String_Base<CHAR>::operator== (const ACE_String_Base<CHAR> &s) const
+{
+ return this->len_ == s.len_ &&
+ ACE_OS::memcmp (this->rep_,
+ s.rep_,
+ this->len_ * sizeof (CHAR)) == 0;
+}
+
+template <class CHAR> bool
+ACE_String_Base<CHAR>::operator== (const CHAR *s) const
+{
+ size_t len = ACE_OS::strlen (s);
+ return this->len_ == len &&
+ ACE_OS::memcmp (this->rep_,
+ s,
+ len * sizeof (CHAR)) == 0;
+}
+
+template <class CHAR> typename ACE_String_Base<CHAR>::size_type
+ACE_String_Base<CHAR>::find (
+ const CHAR *s,
+ typename ACE_String_Base<CHAR>::size_type pos) const
+{
+ CHAR *substr = this->rep_ + pos;
+ size_t len = ACE_OS::strlen (s);
+ CHAR *pointer = ACE_OS::strnstr (substr, s, len);
+ if (pointer == 0)
+ return ACE_String_Base<CHAR>::npos;
+ else
+ return pointer - this->rep_;
+}
+
+template <class CHAR> typename ACE_String_Base<CHAR>::size_type
+ACE_String_Base<CHAR>::find (
+ CHAR c,
+ typename ACE_String_Base<CHAR>::size_type pos) const
+{
+ CHAR *substr = this->rep_ + pos;
+ CHAR *pointer = ACE_OS::strnchr (substr, c, this->len_ - pos);
+ if (pointer == 0)
+ return ACE_String_Base<CHAR>::npos;
+ else
+ return pointer - this->rep_;
+}
+
+template <class CHAR> typename ACE_String_Base<CHAR>::size_type
+ACE_String_Base<CHAR>::rfind (
+ CHAR c,
+ typename ACE_String_Base<CHAR>::size_type pos) const
+{
+ if (pos == npos || pos > this->len_)
+ pos = this->len_;
+
+ // Do not change to prefix operator! Proper operation of this loop
+ // depends on postfix decrement behavior.
+ for (size_type i = pos; i-- != 0; )
+ if (this->rep_[i] == c)
+ return i;
+
+ return ACE_String_Base<CHAR>::npos;
+}
+
+template <class CHAR> void
+ACE_String_Base<CHAR>::swap (ACE_String_Base<CHAR> & str)
+{
+ std::swap (this->allocator_ , str.allocator_);
+ std::swap (this->len_ , str.len_);
+ std::swap (this->buf_len_ , str.buf_len_);
+ std::swap (this->rep_ , str.rep_);
+ std::swap (this->release_ , str.release_);
+}
+
+// ----------------------------------------------
+
+template <class CHAR> ACE_String_Base<CHAR>
+operator+ (const ACE_String_Base<CHAR> &s, const ACE_String_Base<CHAR> &t)
+{
+ ACE_String_Base<CHAR> temp (s.length () + t.length ());
+ temp += s;
+ temp += t;
+ return temp;
+}
+
+template <class CHAR> ACE_String_Base<CHAR>
+operator+ (const CHAR *s, const ACE_String_Base<CHAR> &t)
+{
+ size_t slen = 0;
+ if (s != 0)
+ slen = ACE_OS::strlen (s);
+ ACE_String_Base<CHAR> temp (slen + t.length ());
+ if (slen > 0)
+ temp.append (s, slen);
+ temp += t;
+ return temp;
+}
+
+template <class CHAR> ACE_String_Base<CHAR>
+operator+ (const ACE_String_Base<CHAR> &s, const CHAR *t)
+{
+ size_t tlen = 0;
+ if (t != 0)
+ tlen = ACE_OS::strlen (t);
+ ACE_String_Base<CHAR> temp (s.length () + tlen);
+ temp += s;
+ if (tlen > 0)
+ temp.append (t, tlen);
+ return temp;
+}
+
+template <class CHAR> ACE_String_Base<CHAR>
+operator + (const ACE_String_Base<CHAR> &t,
+ const CHAR c)
+{
+ ACE_String_Base<CHAR> temp (t.length () + 1);
+ temp += t;
+ temp += c;
+ return temp;
+}
+
+template <class CHAR> ACE_String_Base<CHAR>
+operator + (const CHAR c,
+ const ACE_String_Base<CHAR> &t)
+{
+ ACE_String_Base<CHAR> temp (t.length () + 1);
+ temp += c;
+ temp += t;
+ return temp;
+}
+
+template <class CHAR>
+ACE_String_Base<CHAR> &
+ACE_String_Base<CHAR>::operator+= (const CHAR* s)
+{
+ size_t slen = 0;
+ if (s != 0)
+ slen = ACE_OS::strlen (s);
+ return this->append (s, slen);
+}
+
+template <class CHAR>
+ACE_String_Base<CHAR> &
+ACE_String_Base<CHAR>::operator+= (const ACE_String_Base<CHAR> &s)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator+=(const ACE_String_Base<CHAR> &)");
+ return this->append (s.rep_, s.len_);
+}
+
+template <class CHAR>
+ACE_String_Base<CHAR> &
+ACE_String_Base<CHAR>::operator+= (const CHAR c)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator+=(const CHAR)");
+ const size_type slen = 1;
+ return this->append (&c, slen);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_STRING_BASE_CPP */
diff --git a/ACE/ace/String_Base.h b/ACE/ace/String_Base.h
new file mode 100644
index 00000000000..85ef2755407
--- /dev/null
+++ b/ACE/ace/String_Base.h
@@ -0,0 +1,612 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file String_Base.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt (schmidt@cs.wustl.edu)
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_STRING_BASE_H
+#define ACE_STRING_BASE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Global_Macros.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/String_Base_Const.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_String_Base
+ *
+ * @brief This class provides a wrapper facade for C strings.
+ *
+ * This class uses an ACE_Allocator to allocate memory. The
+ * user can make this a persistant class by providing an
+ * ACE_Allocator with a persistable memory pool. This class is
+ * optimized for efficiency, so it doesn't provide any internal
+ * locking.
+ * @note If an instance of this class is constructed from or
+ * assigned an empty string (with first element of '\0'), then it
+ * is not allocated new space. Instead, its internal
+ * representation is set equal to a global empty string.
+ * CAUTION: in cases when ACE_String_Base is constructed from a
+ * provided buffer with the release parameter set to false,
+ * ACE_String_Base is not guaranteed to be '\0' terminated.
+ *
+ * \li Do not use a "@c -1" magic number to refer to the "no position"
+ * condition. This was never the right thing to do. The "@c npos"
+ * constant should be used in such cases.
+ * \li Do not assign or pass string positions to or from signed types.
+ * Use the "@c size_type" @c typedef found in all ACE string
+ * classes. This typedef is analogous to the "@c size_type"
+ * @c typedef found in the standard C++ string class as well as
+ * many STL class templates. If you find yourself casting you're
+ * probably doing something wrong.
+ */
+template <class CHAR>
+class ACE_String_Base : public ACE_String_Base_Const
+{
+public:
+
+ using ACE_String_Base_Const::size_type;
+
+ /**
+ * Default constructor.
+ *
+ * @param the_allocator ACE_Allocator associated with string
+ * @return Default ACE_String_Base string.
+ */
+ ACE_String_Base (ACE_Allocator *the_allocator = 0);
+
+ /**
+ * Constructor that copies @a s into dynamically allocated memory.
+ *
+ * if release == true then a new buffer is allocated internally, and
+ * s is copied to the internal buffer.
+ * if release == false then the s buffer is used directly. If s == 0
+ * then it will _not_ be used, and instead the internal buffer
+ * is set to NULL_String_.
+ *
+ * @param s Zero terminated input string
+ * @param the_allocator ACE_Allocator associated with string
+ * @param release Allocator responsible(true)/not reponsible(false) for
+ * freeing memory.
+ * @return ACE_String_Base containing const CHAR *s
+ */
+ ACE_String_Base (const CHAR *s,
+ ACE_Allocator *the_allocator = 0,
+ bool release = true);
+
+ /**
+ * Constructor that copies @a len CHARs of @a s into dynamically
+ * allocated memory (will zero terminate the result).
+ *
+ * if release == true then a new buffer is allocated internally.
+ * s is copied to the internal buffer.
+ * if release == false then the s buffer is used directly. If s == 0
+ * then it will _not_ be used, and instead the internal buffer
+ * is set to NULL_String_.
+ *
+ * @param s Non-zero terminated input string
+ * @param len Length of non-zero terminated input string
+ * @param the_allocator ACE_Allocator associated with string
+ * @param release Allocator responsible(true)/not reponsible(false) for
+ * freeing memory.
+ * @return ACE_String_Base containing const CHAR *s
+ */
+ ACE_String_Base (const CHAR *s,
+ size_type len,
+ ACE_Allocator *the_allocator = 0,
+ bool release = true);
+
+ /**
+ * Copy constructor.
+ *
+ * @param s Input ACE_String_Base string to copy
+ * @return Copy of input string @a s
+ */
+ ACE_String_Base (const ACE_String_Base < CHAR > &s);
+
+ /**
+ * Constructor that copies @a c into dynamically allocated memory.
+ *
+ * @param c Single input character.
+ * @param the_allocator ACE_Allocator associated with string
+ * @return ACE_String_Base containing CHAR 'c'
+ */
+ ACE_String_Base (CHAR c, ACE_Allocator *the_allocator = 0);
+
+ /**
+ * Constructor that allocates a len long string.
+ *
+ * Warning : This constructor was incorrectly documented in the past.
+ * It simply calls resize(len, c).
+ * It is probably not advisable to use the second parameter. See
+ * resize() for more information.
+ *
+ * @param len Amount of space to reserve for the string.
+ * @param c The array is filled with c's
+ * @param the_allocator ACE_Allocator associated with string
+ * @return Empty ACE_String_Base with room for len CHARs
+ */
+ ACE_String_Base (size_type len,
+ CHAR c = 0,
+ ACE_Allocator *the_allocator = 0);
+
+ /**
+ * Deletes the memory...
+ */
+ ~ACE_String_Base (void);
+
+ /**
+ * Return the <slot'th> character in the string (doesn't perform
+ * bounds checking).
+ *
+ * @param slot Index of the desired character
+ * @return The character at index @a slot
+ */
+ const CHAR & operator[] (size_type slot) const;
+
+ /**
+ * Return the <slot'th> character by reference in the string
+ * (doesn't perform bounds checking).
+ *
+ * @param slot Index of the desired character
+ * @return The character at index @a slot
+ */
+ CHAR & operator[] (size_type slot);
+
+ /**
+ * Assignment operator (does copy memory).
+ *
+ * @param s Input null-terminated CHAR string to assign to this object.
+ * @return Return a copy of the this string.
+ */
+ ACE_String_Base < CHAR > &operator = (const CHAR * s);
+
+ /**
+ * Assignment operator (does copy memory).
+ *
+ * @param s Input ACE_String_Base string to assign to this object.
+ * @return Return a copy of the this string.
+ */
+ ACE_String_Base < CHAR > &operator = (const ACE_String_Base < CHAR > &s);
+
+ /**
+ * Assignment alternative method (does not copy memory).
+ *
+ * @param s Input ACE_String_Base string to assign to this object.
+ * @return Return this string.
+ */
+ ACE_String_Base < CHAR > &assign_nocopy (const ACE_String_Base < CHAR > &s);
+
+ /**
+ * Copy @a s into this @a ACE_String_Base.
+ *
+ * If release == true then a new buffer is allocated internally if the
+ * existing one is not big enough to hold s. If the existing
+ * buffer is big enough, then it will be used. This means that
+ * set(*, 1) can be illegal when the string is constructed with a
+ * const char*. (e.g. ACE_String_Base("test", 0, false)).
+ *
+ * if release == false then the s buffer is used directly, and any
+ * existing buffer is destroyed. If s == 0 then it will _not_ be
+ * used, and instead the internal buffer is set to NULL_String_.
+ *
+ * @param s Null terminated input string
+ * @param release Allocator responsible(true)/not reponsible(false) for
+ * freeing memory.
+ */
+ void set (const CHAR * s, bool release = true);
+
+ /**
+ * Copy @a len bytes of @a s (will zero terminate the result).
+ *
+ * If release == true then a new buffer is allocated internally if the
+ * existing one is not big enough to hold s. If the existing
+ * buffer is big enough, then it will be used. This means that
+ * set(*, *, 1) is illegal when the string is constructed with a
+ * non-owned const char*. (e.g. ACE_String_Base("test", 0, 0))
+ *
+ * If release == false then the s buffer is used directly, and any
+ * existing buffer is destroyed. If s == 0 then it will _not_ be
+ * used, and instead the internal buffer is set to NULL_String_.
+ *
+ * @param s Non-zero terminated input string
+ * @param len Length of input string 's'
+ * @param release Allocator responsible(true)/not reponsible(false) for
+ * freeing memory.
+ */
+ void set (const CHAR * s, size_type len, bool release);
+
+ /**
+ * Clear this string. Memory is _not_ freed if @a release is false.
+ *
+ * Warning: This method was incorrectly documented in the past, but
+ * the current implementation has been changed to match the documented
+ * behavior.
+ *
+ * Warning: clear(false) behaves like fast_clear() below.
+ *
+ * @param release Memory is freed if true, and not freed if false.
+ */
+ void clear (bool release = false);
+
+ /**
+ * A more specialized version of clear(): "fast clear". fast_clear()
+ * resets the string to 0 length. If the string owns the buffer
+ * (@arg release_== true):
+ * - the string buffer is not freed
+ * - the first character of the buffer is set to 0.
+ *
+ * If @arg release_ is false (this object does not own the buffer):
+ * - the buffer pointer is reset to the NULL_String_ and does not
+ * maintain a pointer to the caller-supplied buffer on return
+ * - the maximum string length is reset to 0.
+ *
+ * Warning : Calling clear(false) or fast_clear() can have unintended
+ * side-effects if the string was constructed (or set()) with an
+ * external buffer. The string will be disassociated with the buffer
+ * and the next append() or +=() will cause a new buffer to be
+ * allocated internally.
+ */
+ void fast_clear (void);
+
+ /**
+ * Return a substring given an offset and length.
+ * If length == @c npos use rest of str. Return empty substring if
+ * offset or offset/length are invalid.
+ *
+ * @param offset Index of first desired character of the substring.
+ * @param length How many characters to return starting at the offset.
+ * @return The string containing the desired substring
+ */
+ ACE_String_Base < CHAR > substring (size_type offset,
+ size_type length = npos) const;
+
+ /**
+ * Same as <substring>.
+ *
+ * @param offset Index of first desired character of the substring.
+ * @param length How many characters to return starting at the offset.
+ * @return The string containing the desired substring
+ */
+ ACE_String_Base < CHAR > substr (size_type offset,
+ size_type length = npos) const;
+
+ /**
+ * Concat operator (copies memory).
+ *
+ * @param s Input ACE_String_Base string to concatenate to this string.
+ * @return The combined string (input append to the end of the old). New
+ * string is zero terminated.
+ */
+ ACE_String_Base < CHAR > &operator += (const ACE_String_Base < CHAR > &s);
+
+ /**
+ * Concat operator (copies memory).
+ *
+ * @param s Input C string to concatenate to this string.
+ * @return The combined string (input append to the end of the old). New
+ * string is zero terminated.
+ */
+ ACE_String_Base < CHAR >& operator += (const CHAR* s);
+
+ /**
+ * Concat operator (copies memory).
+ *
+ * @param c Input CHAR to concatenate to this string.
+ * @return The combined string (input append to the end of the old). New
+ * string is zero terminated.
+ */
+ ACE_String_Base < CHAR >& operator += (const CHAR c);
+
+ /**
+ * Append function (copies memory).
+ *
+ * @param s Input CHAR array to concatenate to this string.
+ * @param slen The length of the array.
+ * @return The combined string (input append to the end of the old). New
+ * string is zero terminated.
+ */
+ ACE_String_Base < CHAR >& append (const CHAR* s, size_type slen);
+
+ /**
+ * Returns a hash value for this string.
+ *
+ * @return Hash value of string
+ */
+ u_long hash (void) const;
+
+ /**
+ * Return the length of the string.
+ *
+ * @return Length of stored string
+ */
+ size_type length (void) const;
+
+ /**
+ * Return the number of allocated CHARs in the string object.
+ * This may be greater than the current length of the string.
+ *
+ * @return Maximum number of CHAR units that can be stored, including
+ * any terminating nul that may be needed.
+ */
+ size_t capacity (void) const;
+
+ /**
+ * Return @c true if the length of the string is zero, else @c false.
+ */
+ bool is_empty (void) const;
+
+ /**
+ * Return @c true if the length of the string is zero, else @c
+ * false. We recommend using @c is_empty() instead since it's more
+ * consistent with the ACE container naming conventions.
+ */
+ bool empty (void) const;
+
+ /**
+ * Get a copy of the underlying representation.
+ *
+ * This method allocates memory for a copy of the string and returns
+ * a pointer to the new area. The caller is responsible for freeing
+ * the memory when finished; use delete []
+ *
+ * @return Pointer reference to the string data. Returned string is
+ * zero terminated.
+ */
+ CHAR *rep (void) const;
+
+ /**
+ * Get at the underlying representation directly!
+ * _Don't_ even think about casting the result to (char *) and modifying it,
+ * if it has length 0!
+ *
+ * @return Pointer reference to the stored string data. No guarantee is
+ * that the string is zero terminated.
+ *
+ */
+ const CHAR *fast_rep (void) const;
+
+ /**
+ * Same as STL String's <c_str> and <fast_rep>.
+ */
+ const CHAR *c_str (void) const;
+
+ /**
+ * Comparison operator that will match substrings. Returns the
+ * slot of the first location that matches, else @c npos.
+ *
+ * @param s Input ACE_String_Base string
+ * @return Integer index value of the first location of string @a s or
+ * @c npos (not found).
+ */
+ size_type strstr (const ACE_String_Base<CHAR> &s) const;
+
+ /**
+ * Find <str> starting at pos. Returns the slot of the first
+ * location that matches (will be >= pos), else @c npos.
+ *
+ * @param str Input ACE_String_Base string to search for in stored string.
+ * @param pos Starting index position to start searching for string @a str.
+ * @return Index value of the first location of string @a str else
+ * @c npos.
+ */
+ size_type find (const ACE_String_Base<CHAR> &str, size_type pos = 0) const;
+
+ /**
+ * Find @a s starting at pos. Returns the slot of the first
+ * location that matches (will be >= pos), else @c npos.
+ *
+ * @param s non-zero input string to search for in stored string.
+ * @param pos Starting index position to start searching for string @a str.
+ * @return Index value of the first location of string @a str else
+ * @c npos.
+ */
+ size_type find (const CHAR *s, size_type pos = 0) const;
+
+ /**
+ * Find @a c starting at pos. Returns the slot of the first
+ * location that matches (will be >= pos), else @c npos.
+ *
+ * @param c Input character to search for in stored string.
+ * @param pos Starting index position to start searching for string @a str.
+ * @return Index value of the first location of string @a str else
+ * @c npos.
+ */
+ size_type find (CHAR c, size_type pos = 0) const;
+
+ /**
+ * Find @a c starting at pos (counting from the end). Returns the
+ * slot of the first location that matches, else @c npos.
+ *
+ * @param c Input character to search for in stored string.
+ * @param pos Starting index position to start searching for string @a str.
+ * @return Index value of the first location of string @a str else
+ * @c npos.
+ */
+ size_type rfind (CHAR c, size_type pos = npos) const;
+
+ /**
+ * Equality comparison operator (must match entire string).
+ *
+ * @param s Input ACE_String_Base string to compare against stored string.
+ * @return @c true if equal, @c false otherwise.
+ */
+ bool operator == (const ACE_String_Base<CHAR> &s) const;
+
+ /**
+ * Equality comparison operator (must match entire string).
+ *
+ * @param s Null terminated string to compare against stored string.
+ * @return @c true if equal, @c false otherwise.
+ */
+ bool operator == (const CHAR *s) const;
+
+ /**
+ * Less than comparison operator.
+ *
+ * @param s Input ACE_String_Base string to compare against stored string.
+ * @return @c true if less than, @c false otherwise.
+ */
+ bool operator < (const ACE_String_Base<CHAR> &s) const;
+
+ /**
+ * Greater than comparison operator.
+ *
+ * @param s Input ACE_String_Base string to compare against stored string.
+ * @return @c true if greater than, @c false otherwise.
+ */
+ bool operator > (const ACE_String_Base<CHAR> &s) const;
+
+ /**
+ * Inequality comparison operator.
+ *
+ * @param s String to compare against stored string.
+ * @return @c true if not equal, @c false otherwise.
+ */
+ bool operator != (const ACE_String_Base<CHAR> &s) const;
+
+ /**
+ * Inequality comparison operator.
+ *
+ * @param s Null terminated string to compare against stored string.
+ * @return @c true if not equal, @c false otherwise.
+ */
+ bool operator != (const CHAR *s) const;
+
+ /**
+ * Performs a strncmp comparison.
+ *
+ * @param s Input ACE_String_Base string to compare against stored string.
+ * @return Integer value of result (less than 0, 0, greater than 0)
+ * depending on how input string @a s is to the stored string.
+ */
+ int compare (const ACE_String_Base<CHAR> &s) const;
+
+ /**
+ * Dump the state of an object.
+ */
+ void dump (void) const;
+
+ /**
+ * This method is designed for high-performance. Please use with
+ * care ;-)
+ *
+ * Warning : This method was documented incorrectly in the past.
+ * The original intention was to change the length of the string to
+ * len, and to fill the whole thing with c CHARs.
+ * However, what was actually done was to set the length of the
+ * string to zero, and fill the buffer with c's. The buffer was
+ * also not null-terminated unless c happened to be zero.
+ * Rather than fix the method to work as documented, the code is
+ * left as is, but the second parameter should probably not be used.
+ *
+ * fast_resize just adjusts the buffer if needed and sets the length,
+ * it doesn't fill the buffer, so is much faster.
+ *
+ * @param len The number of CHARs to reserve
+ * @param c The CHAR to use when filling the string.
+ */
+ void resize (size_type len, CHAR c = 0);
+ void fast_resize (size_t len);
+
+ /// Swap the contents of this @c ACE_String_Base with @a str.
+ /**
+ * @note This is non-throwing operation.
+ */
+ void swap (ACE_String_Base<CHAR> & str);
+
+ /**
+ * Declare the dynamic allocation hooks.
+ */
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /**
+ * Pointer to a memory allocator.
+ */
+ ACE_Allocator *allocator_;
+
+ /**
+ * Length of the ACE_String_Base data (not counting the trailing '\0').
+ */
+ size_type len_;
+
+ /**
+ * Length of the ACE_String_Base data buffer. Keeping track of the
+ * length allows to avoid unnecessary dynamic allocations.
+ */
+ size_type buf_len_;
+
+ /**
+ * Pointer to data.
+ */
+ CHAR *rep_;
+
+ /**
+ * Flag that indicates if we own the memory
+ */
+ bool release_;
+
+ /**
+ * Represents the "NULL" string to simplify the internal logic.
+ */
+ static CHAR NULL_String_;
+};
+
+template < class CHAR >
+ ACE_String_Base < CHAR > operator + (const ACE_String_Base < CHAR > &,
+ const ACE_String_Base < CHAR > &);
+template < class CHAR >
+ ACE_String_Base < CHAR > operator + (const ACE_String_Base < CHAR > &,
+ const CHAR *);
+template < class CHAR >
+ ACE_String_Base < CHAR > operator + (const CHAR *,
+ const ACE_String_Base < CHAR > &);
+
+template < class CHAR >
+ ACE_String_Base < CHAR > operator + (const ACE_String_Base < CHAR > &t,
+ const CHAR c);
+
+template < class CHAR >
+ ACE_String_Base < CHAR > operator + (const CHAR c,
+ const ACE_String_Base < CHAR > &t);
+
+template <class CHAR>
+ bool operator == (const CHAR *s,
+ const ACE_String_Base<CHAR> &t);
+
+template <class CHAR>
+ bool operator != (const CHAR *s,
+ const ACE_String_Base<CHAR> &t);
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/String_Base.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/String_Base.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("String_Base.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_STRING_BASE_H */
diff --git a/ACE/ace/String_Base.inl b/ACE/ace/String_Base.inl
new file mode 100644
index 00000000000..28b5e824aa7
--- /dev/null
+++ b/ACE/ace/String_Base.inl
@@ -0,0 +1,159 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Malloc_Base.h"
+#include "ace/Min_Max.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Memory.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class CHAR> ACE_INLINE void
+ACE_String_Base<CHAR>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_String_Base<CHAR>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+// Assignment method (does not copy memory)
+template <class CHAR> ACE_INLINE ACE_String_Base<CHAR> &
+ACE_String_Base<CHAR>::assign_nocopy (const ACE_String_Base<CHAR> &s)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::assign_nocopy");
+ this->set (s.rep_, s.len_, false);
+ return *this;
+}
+
+template <class CHAR> ACE_INLINE typename ACE_String_Base<CHAR>::size_type
+ACE_String_Base<CHAR>::length (void) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::length");
+ return this->len_;
+}
+
+template <class CHAR> ACE_INLINE size_t
+ACE_String_Base<CHAR>::capacity (void) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::capacity");
+ return this->buf_len_;
+}
+
+template <class CHAR> ACE_INLINE bool
+ACE_String_Base<CHAR>::is_empty (void) const
+{
+ return this->len_ == 0;
+}
+
+template <class CHAR> ACE_INLINE bool
+ACE_String_Base<CHAR>::empty (void) const
+{
+ return this->is_empty ();
+}
+
+template <class CHAR> ACE_INLINE ACE_String_Base<CHAR>
+ACE_String_Base<CHAR>::substr (
+ typename ACE_String_Base<CHAR>::size_type offset,
+ typename ACE_String_Base<CHAR>::size_type length) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::substr");
+ return this->substring (offset, length);
+}
+
+// Return the <slot'th> character in the string.
+
+template <class CHAR> ACE_INLINE const CHAR &
+ACE_String_Base<CHAR>::operator[] (
+ typename ACE_String_Base<CHAR>::size_type slot) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator[]");
+ return this->rep_[slot];
+}
+
+// Return the <slot'th> character in the string by reference.
+
+template <class CHAR> ACE_INLINE CHAR &
+ACE_String_Base<CHAR>::operator[] (
+ typename ACE_String_Base<CHAR>::size_type slot)
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator[]");
+ return this->rep_[slot];
+}
+
+template <class CHAR> ACE_INLINE const CHAR *
+ACE_String_Base<CHAR>::fast_rep (void) const
+{
+ return this->rep_;
+}
+
+template <class CHAR> ACE_INLINE const CHAR *
+ACE_String_Base<CHAR>::c_str (void) const
+{
+ return this->rep_;
+}
+
+// Less than comparison operator.
+
+template <class CHAR> ACE_INLINE bool
+ACE_String_Base<CHAR>::operator < (const ACE_String_Base<CHAR> &s) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator <");
+ return compare (s) < 0;
+}
+
+// Greater than comparison operator.
+
+template <class CHAR> ACE_INLINE bool
+ACE_String_Base<CHAR>::operator > (const ACE_String_Base &s) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator >");
+ return compare (s) > 0;
+}
+
+
+// Comparison operator.
+
+template <class CHAR> ACE_INLINE bool
+ACE_String_Base<CHAR>::operator!= (const ACE_String_Base<CHAR> &s) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::operator!=");
+ return !(*this == s);
+}
+
+template <class CHAR> ACE_INLINE bool
+ACE_String_Base<CHAR>::operator!= (const CHAR *s) const
+{
+ return !(*this == s);
+}
+
+template <class CHAR> ACE_INLINE typename ACE_String_Base<CHAR>::size_type
+ACE_String_Base<CHAR>::find (const ACE_String_Base<CHAR>&str,
+ typename ACE_String_Base<CHAR>::size_type pos) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::find");
+ return this->find (str.rep_, pos);
+}
+
+template <class CHAR> ACE_INLINE typename ACE_String_Base<CHAR>::size_type
+ACE_String_Base<CHAR>::strstr (const ACE_String_Base<CHAR> &s) const
+{
+ ACE_TRACE ("ACE_String_Base<CHAR>::strstr");
+ return this->find (s.rep_);
+}
+
+template <class CHAR> ACE_INLINE bool
+operator== (const CHAR *s,
+ const ACE_String_Base<CHAR> &t)
+{
+ return t == s;
+}
+
+template <class CHAR> ACE_INLINE bool
+operator!= (const CHAR *s,
+ const ACE_String_Base<CHAR> &t)
+{
+ return !(t == s);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/String_Base_Const.cpp b/ACE/ace/String_Base_Const.cpp
new file mode 100644
index 00000000000..7e431a7cb8a
--- /dev/null
+++ b/ACE/ace/String_Base_Const.cpp
@@ -0,0 +1,20 @@
+// $Id$
+
+#include "ace/String_Base_Const.h"
+#include "ace/Numeric_Limits.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_String_Base_Const::size_type const ACE_String_Base_Const::npos =
+#if defined (AIX) //&& (defined (__xlC__) || defined (__IBMCPP__))
+ // Under some mixed shared/static linking conditions, this constant
+ // will not be initialized at run-time if the
+ // std::numeric_limits<>::max() trait is used on AIX/XLC++.
+ // Workaround that problem by making it easier for the compiler to
+ // realize it can set the constant at compile-time.
+ static_cast<ACE_String_Base_Const::size_type> (-1);
+#else
+ ACE_Numeric_Limits<ACE_String_Base_Const::size_type>::max ();
+#endif /* AIX */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/String_Base_Const.h b/ACE/ace/String_Base_Const.h
new file mode 100644
index 00000000000..2684e3dff8e
--- /dev/null
+++ b/ACE/ace/String_Base_Const.h
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file String_Base_Const.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_STRING_BASE_CONST_H
+#define ACE_STRING_BASE_CONST_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/Malloc_Base.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_String_Base_Const
+ *
+ * @brief This class defines a constant for ACE_String_Base
+ * which originally was there to circumvent a bug in SunCC 6.0.
+ * This could be moved to ACE_String_Base but that
+ * adds a lot of footprint to the user applications which
+ * is not something we want.
+ */
+class ACE_Export ACE_String_Base_Const
+{
+public:
+
+ typedef ACE_Allocator::size_type size_type;
+
+ /// Constant that denotes case where no such character position
+ /// exists.
+ static size_type const npos;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_STRING_BASE_CONST_H */
diff --git a/ACE/ace/Svc_Conf.h b/ACE/ace/Svc_Conf.h
new file mode 100644
index 00000000000..2038519c6f7
--- /dev/null
+++ b/ACE/ace/Svc_Conf.h
@@ -0,0 +1,100 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Svc_Conf.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SVC_CONF_H
+#define ACE_SVC_CONF_H
+
+#include /**/ "ace/pre.h"
+
+// Globally visible macros, type decls, and extern var decls for
+// Service Configurator utility.
+
+#include "ace/Obstack.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Config.h"
+#include "ace/Parse_Node.h"
+
+#include "ace/Svc_Conf_Param.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+
+// The following yylex() declarations require support for reentrant
+// parser generation (e.g. from GNU Bison).
+#define ACE_YY_DECL extern "C" int ace_yylex (ACE_YYSTYPE *ace_yylval, void *ACE_YYLEX_PARAM)
+
+// Forward declarations
+class ACE_Location_Node;
+class ACE_Parse_Node;
+class ACE_Static_Node;
+class ACE_Service_Type_Factory;
+
+// The following definition for the ACE_YYSTYPE must occur before
+// ACE_YY_DECL is declared since ACE_YY_DECL expands to function
+// prototypes that use ACE_YYSTYPE.
+typedef union
+{
+ int type_;
+ ACE_Location_Node *location_node_;
+ ACE_Parse_Node *parse_node_;
+ ACE_Static_Node *static_node_;
+ ACE_Service_Type_Factory *svc_record_;
+ ACE_TCHAR *ident_;
+} ACE_YYSTYPE;
+
+// Forward declaration
+struct ace_yy_buffer_state;
+
+/// Performs the parsing
+#ifdef ACE_YYPARSE_PARAM
+int ace_yyparse (void *);
+#else
+int ace_yyparse (void);
+#endif
+
+/// Performs the lexical analysis
+ACE_YY_DECL;
+
+/// Name of input stream
+extern FILE *ace_yyin;
+
+/// Error handling routine required by YACC or BISON
+void ace_yyerror (int yyerrno, int yylineno, char const *);
+
+/// Holds the lexeme for the current token
+extern ACE_TCHAR *ace_yytext;
+
+/// Holds the length of the lexeme for the current token
+extern int ace_yyleng;
+
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+/// Factory that creates a new ACE_Service_Type_Impl.
+extern ACE_Service_Type_Impl *
+ace_create_service_type (const ACE_TCHAR *,
+ int,
+ void *,
+ unsigned int,
+ ACE_Service_Object_Exterminator = 0);
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SVC_CONF_H */
diff --git a/ACE/ace/Svc_Conf.y b/ACE/ace/Svc_Conf.y
new file mode 100644
index 00000000000..6b8ee2a1ad7
--- /dev/null
+++ b/ACE/ace/Svc_Conf.y
@@ -0,0 +1,425 @@
+%{
+// $Id$
+
+#include "ace/Svc_Conf.h"
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+
+#include "ace/ARGV.h"
+#include "ace/Module.h"
+#include "ace/Stream.h"
+#include "ace/Service_Types.h"
+#include "ace/OS_NS_string.h"
+
+
+#include "ace/ace_wchar.h"
+
+ACE_RCSID (ace,
+ Svc_Conf_y,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Prototypes.
+
+static ACE_Module_Type *ace_get_module (ACE_Service_Type const * sr,
+ ACE_Service_Type const * sv,
+ int & ace_yyerrno);
+
+static ACE_Module_Type *ace_get_module (ACE_Service_Type const * sr,
+ ACE_TCHAR const * svc_name,
+ int & ace_yyerrno);
+
+#define YYDEBUG_LEXER_TEXT (yytext[yyleng] = '\0', yytext)
+
+// Force the pretty debugging code to compile.
+// #define YYDEBUG 1
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+%}
+
+%token ACE_DYNAMIC ACE_STATIC ACE_SUSPEND ACE_RESUME ACE_REMOVE ACE_USTREAM
+%token ACE_MODULE_T ACE_STREAM_T ACE_SVC_OBJ_T ACE_ACTIVE ACE_INACTIVE
+%token ACE_PATHNAME ACE_IDENT ACE_STRING
+
+%start svc_config_entries
+
+%type <ident_> ACE_IDENT ACE_STRING ACE_PATHNAME pathname parameters_opt
+%type <type_> type status
+%type <parse_node_> dynamic static suspend resume remove module_list stream
+%type <parse_node_> stream_modules module svc_config_entry
+%type <static_node_> stream_ops
+%type <svc_record_> svc_location
+%type <location_node_> svc_initializer
+
+// Generate a pure (reentrant) parser -- GNU Bison only
+%pure_parser
+
+%%
+
+svc_config_entries
+ : svc_config_entries svc_config_entry
+ {
+ if ($2 != 0)
+ {
+ $2->apply (ACE_SVC_CONF_PARAM->config, ACE_SVC_CONF_PARAM->yyerrno);
+ delete $2;
+ }
+ ACE_SVC_CONF_PARAM->obstack.release ();
+ }
+ | svc_config_entries error
+ {
+ ACE_SVC_CONF_PARAM->obstack.release ();
+ }
+ | /* EMPTY */
+ ;
+
+svc_config_entry
+ : dynamic
+ | static
+ | suspend
+ | resume
+ | remove
+ | stream
+ ;
+
+dynamic
+ : ACE_DYNAMIC svc_location parameters_opt
+ {
+ if ($2 != 0)
+ $$ = new ACE_Dynamic_Node ($2, $3);
+ else
+ $$ = 0;
+ }
+ ;
+
+static
+ : ACE_STATIC ACE_IDENT parameters_opt
+ {
+ $$ = new ACE_Static_Node ($2, $3);
+ }
+ ;
+
+suspend
+ : ACE_SUSPEND ACE_IDENT
+ {
+ $$ = new ACE_Suspend_Node ($2);
+ }
+ ;
+
+resume
+ : ACE_RESUME ACE_IDENT
+ {
+ $$ = new ACE_Resume_Node ($2);
+ }
+ ;
+
+remove
+ : ACE_REMOVE ACE_IDENT
+ {
+ $$ = new ACE_Remove_Node ($2);
+ }
+ ;
+
+stream
+ : ACE_USTREAM stream_ops stream_modules
+ {
+ $$ = new ACE_Stream_Node ($2, $3);
+ }
+ | ACE_USTREAM ACE_IDENT { $<static_node_>$ = new ACE_Static_Node ($2); } stream_modules
+ {
+ $$ = new ACE_Dummy_Node ($<static_node_>3, $4);
+ }
+ ;
+
+stream_ops
+ : dynamic
+ {
+ }
+ | static
+ {
+ }
+ ;
+
+stream_modules
+ : '{'
+ {
+ // Initialize left context...
+ $<static_node_>$ = $<static_node_>0;
+ }
+ module_list '}'
+ {
+ $$ = $3;
+ }
+ | /* EMPTY */ { $$ = 0; }
+ ;
+
+module_list
+ : module_list module
+ {
+ if ($2 != 0)
+ {
+ $2->link ($1);
+ $$ = $2;
+ }
+ }
+ | /* EMPTY */ { $$ = 0; }
+ ;
+
+module
+ : dynamic
+ {
+ ACE_Static_Node *svc_type = $<static_node_>1;
+
+ if (svc_type != 0)
+ {
+ ACE_Static_Node *module = $<static_node_>-1;
+
+ ACE_ARGV args (svc_type->parameters ());
+ ACE_Module_Type *mt = ace_get_module (module->record (ACE_SVC_CONF_PARAM->config),
+ svc_type->record (ACE_SVC_CONF_PARAM->config),
+ ACE_SVC_CONF_PARAM->yyerrno);
+ ACE_Stream_Type *st =
+ dynamic_cast<ACE_Stream_Type *> (const_cast<ACE_Service_Type_Impl *> (module->record (ACE_SVC_CONF_PARAM->config)->type ()));
+
+ if (!st
+ || !mt
+ || mt->init (args.argc (), args.argv ()) == -1
+ || st->push (mt) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("dynamic initialization failed for Module %s\n"),
+ svc_type->name ()));
+ ACE_SVC_CONF_PARAM->yyerrno++;
+ }
+ }
+ }
+ | static
+ {
+ ACE_Static_Node *sn = $<static_node_>-1;
+ ACE_Module_Type *mt = ace_get_module (sn->record (ACE_SVC_CONF_PARAM->config),
+ $<static_node_>1->name (),
+ ACE_SVC_CONF_PARAM->yyerrno);
+
+ if (((ACE_Stream_Type *) sn->record (ACE_SVC_CONF_PARAM->config)->type ())->push (mt) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Problem with static\n")));
+ ACE_SVC_CONF_PARAM->yyerrno++;
+ }
+ }
+ | suspend
+ {
+ ACE_Static_Node *sn = $<static_node_>-1;
+ ACE_Module_Type *mt = ace_get_module (sn->record (ACE_SVC_CONF_PARAM->config),
+ sn->name (),
+ ACE_SVC_CONF_PARAM->yyerrno);
+ if (mt != 0)
+ mt->suspend ();
+ }
+ | resume
+ {
+ ACE_Static_Node *sn = $<static_node_>-1;
+ ACE_Module_Type *mt = ace_get_module (sn->record (ACE_SVC_CONF_PARAM->config),
+ $<static_node_>1->name (),
+ ACE_SVC_CONF_PARAM->yyerrno);
+ if (mt != 0)
+ mt->resume ();
+ }
+ | remove
+ {
+ ACE_Static_Node *stream = $<static_node_>-1;
+ ACE_Static_Node *module = $<static_node_>1;
+ ACE_Module_Type *mt = ace_get_module (stream->record (ACE_SVC_CONF_PARAM->config),
+ module->name (),
+ ACE_SVC_CONF_PARAM->yyerrno);
+
+ ACE_Stream_Type *st =
+ dynamic_cast<ACE_Stream_Type *> (const_cast<ACE_Service_Type_Impl *> (stream->record (ACE_SVC_CONF_PARAM->config)->type ()));
+ if (!st || (mt != 0 && st->remove (mt) == -1))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("cannot remove Module_Type %s from STREAM_Type %s\n"),
+ module->name (),
+ stream->name ()));
+ ACE_SVC_CONF_PARAM->yyerrno++;
+ }
+ }
+ ;
+
+svc_location
+ : ACE_IDENT type svc_initializer status
+ {
+ $$ = new ACE_Service_Type_Factory ($1, $2, $3, $4);
+ }
+ ;
+
+status
+ : ACE_ACTIVE
+ {
+ $$ = 1;
+ }
+ | ACE_INACTIVE
+ {
+ $$ = 0;
+ }
+ | /* EMPTY */
+ {
+ $$ = 1;
+ }
+ ;
+
+svc_initializer
+ : pathname ':' ACE_IDENT
+ {
+ $$ = new ACE_Object_Node ($1, $3);
+ }
+ | pathname ':' ACE_IDENT '(' ')'
+ {
+ $$ = new ACE_Function_Node ($1, $3);
+ }
+ | ':' ACE_IDENT '(' ')'
+ {
+ $$ = new ACE_Static_Function_Node ($2);
+ }
+ ;
+
+type
+ : ACE_MODULE_T '*'
+ {
+ $$ = ACE_MODULE_T;
+ }
+ | ACE_SVC_OBJ_T '*'
+ {
+ $$ = ACE_SVC_OBJ_T;
+ }
+ | ACE_STREAM_T '*'
+ {
+ $$ = ACE_STREAM_T;
+ }
+ ;
+
+parameters_opt
+ : ACE_STRING
+ | /* EMPTY */ { $$ = 0; }
+ ;
+
+pathname
+ : ACE_PATHNAME
+ | ACE_IDENT
+ | ACE_STRING
+ ;
+
+%%
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Prints the error string to standard output. Cleans up the error
+// messages.
+
+void
+yyerror (int yyerrno, int yylineno, char const * s)
+{
+#if defined (ACE_NLOGGING)
+ ACE_UNUSED_ARG (yyerrno);
+ ACE_UNUSED_ARG (yylineno);
+ ACE_UNUSED_ARG (s);
+#endif /* ACE_NLOGGING */
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE (%P|%t) [error %d] on line %d: %s\n"),
+ yyerrno,
+ yylineno,
+ ACE_TEXT_CHAR_TO_TCHAR (s)));
+}
+
+// Note that SRC_REC represents left context, which is the STREAM *
+// record.
+
+static ACE_Module_Type *
+ace_get_module (ACE_Service_Type const * sr,
+ ACE_TCHAR const * svc_name,
+ int & yyerrno)
+{
+ ACE_Service_Type_Impl const * const type = sr->type ();
+ ACE_Stream_Type const * const st =
+ (sr == 0
+ ? 0
+ : dynamic_cast<ACE_Stream_Type const *> (type));
+ ACE_Module_Type const * const mt = (st == 0 ? 0 : st->find (svc_name));
+
+ if (sr == 0 || st == 0 || mt == 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("cannot locate Module_Type %s ")
+ ACE_LIB_TEXT ("in STREAM_Type %s\n"),
+ svc_name,
+ (sr ? sr->name () : ACE_LIB_TEXT ("(nil)"))));
+ ++yyerrno;
+ }
+
+ return const_cast<ACE_Module_Type *> (mt);
+}
+
+static ACE_Module_Type *
+ace_get_module (ACE_Service_Type const * sr,
+ ACE_Service_Type const * sv,
+ int & yyerrno)
+{
+ ACE_Stream_Type const * const st =
+ (sr == 0
+ ? 0
+ : static_cast<ACE_Stream_Type const *> (sr->type ()));
+
+ ACE_Module_Type const * const mt =
+ static_cast <ACE_Module_Type const *> (sv->type ());
+
+ ACE_TCHAR const * const module_type_name =
+ (mt ? mt->name () : ACE_LIB_TEXT ("(nil)"));
+
+ if (sr == 0 || st == 0 || mt == 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("cannot locate Module_Type %s or STREAM_Type %s\n"),
+ module_type_name,
+ (sr ? sr->name () : ACE_LIB_TEXT ("(nil)"))));
+ ++yyerrno;
+ }
+
+ // Make sure that the Module has the same name as the
+ // Module_Type object from the svc.conf file.
+ ACE_Module<ACE_SYNCH> * const mp =
+ static_cast<ACE_Module<ACE_SYNCH> *> (mt ? mt->object () : 0);
+
+ if (mp && ACE_OS::strcmp (mp->name (), module_type_name) != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("warning: assigning Module_Type name %s to Module %s since names differ\n"),
+ module_type_name,
+ mp->name ()));
+ mp->name (module_type_name);
+ }
+
+ return const_cast<ACE_Module_Type *> (mt);
+}
+
+#if defined (SVC_CONF_Y_DEBUGGING)
+// Main driver program.
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Svc_Conf_Param param (0, stdin);
+
+ // Try to reopen any filename argument to use YYIN.
+ if (argc > 1 && (yyin = freopen (argv[1], "r", stdin)) == 0)
+ (void) ACE_OS::fprintf (stderr, ACE_LIB_TEXT ("usage: %s [file]\n"), argv[0]), ACE_OS::exit (1);
+
+ return ::yyparse (&param);
+}
+#endif /* SVC_CONF_Y_DEBUGGING */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
diff --git a/ACE/ace/Svc_Conf_Lexer.cpp b/ACE/ace/Svc_Conf_Lexer.cpp
new file mode 100644
index 00000000000..3bcd8d6d559
--- /dev/null
+++ b/ACE/ace/Svc_Conf_Lexer.cpp
@@ -0,0 +1,676 @@
+// $Id$
+#include "ace/Svc_Conf_Lexer.h"
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+
+#if defined (ACE_USES_WCHAR)
+#include "ace/Encoding_Converter.h"
+#include "ace/Encoding_Converter_Factory.h"
+#endif /* ACE_USES_WCHAR */
+
+#include "ace/Svc_Conf_Tokens.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Static_Object_Lock.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Guard_T.h"
+#include "ace/Synch_Traits.h"
+#include "ace/os_include/os_ctype.h"
+
+#if !defined (__GNUG__)
+# include "ace/Auto_Ptr.h"
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#define ACE_YY_BUF_SIZE 4096
+#define ACE_MAX_BYTES_PER_CHAR 4
+#define ACE_YY_CONVERSION_SPACE ACE_YY_BUF_SIZE * ACE_MAX_BYTES_PER_CHAR
+
+#if defined (__GNUG__)
+# define ACE_TEMPORARY_STRING(X,SIZE) \
+ __extension__ char X[SIZE]
+#else
+# define ACE_TEMPORARY_STRING(X,SIZE) \
+ char* X = 0; \
+ char X ## buf[ACE_YY_BUF_SIZE]; \
+ ACE_Auto_Ptr<char> X ## bufp (0); \
+ if (SIZE > ACE_YY_BUF_SIZE) { \
+ X ## bufp.reset (new char[SIZE]); \
+ X = X ## bufp.get (); \
+ } \
+ else { \
+ X = X ## buf; \
+ }
+#endif /* __GNUG__ */
+
+// These are states not covered by the tokens in Svc_Conf_Tokens.h
+#define ACE_NO_STATE -1
+#define ACE_COMMENT 0
+
+#if defined (_MSC_VER) && (_MSC_VER >= 1400)
+// Visual Studio .NET 2005 (VC8) issues warning C4351 for input_ in the
+// constructor initializer list below. Since we like the warned-of new
+// behavior (input_ elements will be default-initialized), squash the
+// warning here.
+# pragma warning (push)
+# pragma warning (disable:4351)
+#endif /* VC8 */
+
+struct ace_yy_buffer_state
+{
+ ace_yy_buffer_state (void)
+ : input_ (),
+ index_ (0),
+ size_ (0),
+ start_ (0),
+ need_more_ (true),
+ eof_ (false),
+ state_ (ACE_NO_STATE),
+ string_start_ (0)
+#if defined (ACE_USES_WCHAR)
+ , converter_ (0)
+#endif /* ACE_USES_WCHAR */
+ {
+ }
+#if defined (_MSC_VER) && (_MSC_VER >= 1400)
+# pragma warning (pop)
+#endif /* VC8 */
+
+ ~ace_yy_buffer_state (void)
+ {
+#if defined (ACE_USES_WCHAR)
+ delete converter_;
+#endif /* ACE_USES_WCHAR */
+ }
+
+ // Input related
+ char input_[ACE_YY_CONVERSION_SPACE];
+ size_t index_;
+ size_t size_;
+ size_t start_;
+ bool need_more_;
+ bool eof_;
+
+ // Parsing related
+ int state_;
+ char string_start_;
+
+#if defined (ACE_USES_WCHAR)
+ // Code set conversion related
+ ACE_Encoding_Converter* converter_;
+#endif /* ACE_USES_WCHAR */
+};
+
+// ******************************************************************
+// Global functions
+// ******************************************************************
+
+int
+ace_yylex (ACE_YYSTYPE *ace_yylval, void *ACE_YYLEX_PARAM)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX,
+ ace_mon,
+ *ACE_Static_Object_Lock::instance (),
+ -1));
+
+ return ACE_Svc_Conf_Lexer::yylex (ace_yylval, ACE_SVC_CONF_PARAM);
+
+}
+
+void
+ace_yy_delete_buffer (ace_yy_buffer_state *buffer)
+{
+ delete buffer;
+}
+
+// ******************************************************************
+// Inline methods
+// ******************************************************************
+
+inline size_t
+normalize (size_t length)
+{
+ return (length >= ACE_MAX_BYTES_PER_CHAR ?
+ (length / ACE_MAX_BYTES_PER_CHAR) * ACE_MAX_BYTES_PER_CHAR :
+ length);
+}
+
+// ******************************************************************
+// Static class methods
+// ******************************************************************
+
+int
+ACE_Svc_Conf_Lexer::yylex (ACE_YYSTYPE* ace_yylval,
+ ACE_Svc_Conf_Param* param)
+{
+#if defined (ACE_USES_WCHAR)
+ bool look_for_bom = false;
+ ACE_Encoding_Converter_Factory::Encoding_Hint hint =
+ ACE_Encoding_Converter_Factory::ACE_NONE;
+#endif /* ACE_USES_WCHAR */
+ if (param->buffer == 0)
+ {
+#if defined (ACE_USES_WCHAR)
+ look_for_bom = true;
+#endif /* ACE_USES_WCHAR */
+ ACE_NEW_RETURN (param->buffer,
+ ace_yy_buffer_state,
+ -1);
+ }
+
+ int token = ACE_NO_STATE;
+ do {
+ if (param->buffer->need_more_)
+ {
+#if defined (ACE_USES_WCHAR)
+ size_t skip_bytes = 0;
+#endif /* ACE_USES_WCHAR */
+ param->buffer->need_more_ = false;
+ size_t amount =
+ input (param,
+ param->buffer->input_ + param->buffer->size_,
+ normalize (ACE_YY_BUF_SIZE -
+ param->buffer->size_));
+ if (amount == 0)
+ {
+ param->buffer->eof_ = true;
+#if defined (ACE_USES_WCHAR)
+ skip_bytes = param->buffer->size_;
+#endif /* ACE_USES_WCHAR */
+ }
+ else
+ {
+#if defined (ACE_USES_WCHAR)
+ if (look_for_bom)
+ {
+ size_t read_more = 0;
+
+ look_for_bom = false;
+ hint = locate_bom (param->buffer->input_, amount, read_more);
+
+ if (read_more != 0)
+ {
+ input (param,
+ param->buffer->input_ + amount,
+ read_more);
+ ACE_OS::memmove (param->buffer->input_,
+ param->buffer->input_ + read_more,
+ amount);
+ }
+ }
+ skip_bytes = param->buffer->size_;
+#endif /* ACE_USES_WCHAR */
+ param->buffer->size_ += amount;
+ }
+
+#if defined (ACE_USES_WCHAR)
+ if (!convert_to_utf8 (param, skip_bytes, hint))
+ {
+ ace_yyerror (++param->yyerrno,
+ param->yylineno,
+ "Unable to convert input stream to UTF-8");
+ return ACE_NO_STATE;
+ }
+#endif /* ACE_USES_WCHAR */
+ }
+
+ token = scan (ace_yylval, param);
+ } while (token == ACE_NO_STATE && param->buffer->need_more_);
+
+ return token;
+}
+
+size_t
+ACE_Svc_Conf_Lexer::input (ACE_Svc_Conf_Param* param,
+ char* buf, size_t max_size)
+{
+ size_t result = 0;
+
+ switch (param->type)
+ {
+ case ACE_Svc_Conf_Param::SVC_CONF_FILE:
+ errno = 0;
+ while ((result = ACE_OS::fread (buf, 1,
+ max_size, param->source.file)) == 0 &&
+ ferror (param->source.file))
+ {
+ if (errno == EINTR)
+ {
+ errno = 0;
+#if !defined (ACE_LACKS_CLEARERR)
+ ACE_OS::clearerr (param->source.file);
+#endif /* !ACE_LACKS_CLEARERR */
+ }
+ else
+ {
+ ACE_OS::fprintf (stderr, "ERROR: input in scanner failed\n");
+ ACE_OS::exit (2);
+ }
+ }
+ break;
+ case ACE_Svc_Conf_Param::SVC_CONF_DIRECTIVE:
+ result = ACE_OS::strlen (param->source.directive +
+ param->buffer->start_) * sizeof (ACE_TCHAR);
+ if (result != 0)
+ {
+ // Make sure that the amount we are going to copy
+ // fits in the buffer
+ if (result > max_size)
+ {
+ result = max_size;
+ }
+ ACE_OS::memcpy (buf,
+ param->source.directive + param->buffer->start_,
+ result);
+ param->buffer->start_ += (result / sizeof (ACE_TCHAR));
+ }
+ break;
+ default:
+ ace_yyerror (++param->yyerrno,
+ param->yylineno,
+ "Invalid Service Configurator type in "
+ "ACE_Svc_Conf_Lexer::input");
+ }
+
+ return result;
+}
+
+int
+ACE_Svc_Conf_Lexer::scan (ACE_YYSTYPE* ace_yylval,
+ ACE_Svc_Conf_Param* param)
+
+{
+ ace_yy_buffer_state* buffer = param->buffer;
+
+ // If we are not currently in any state, skip over whitespace
+ if (buffer->state_ == ACE_NO_STATE)
+ {
+ while (buffer->index_ < buffer->size_ &&
+ isspace (buffer->input_[buffer->index_]))
+ {
+ // Make sure that we count all of the new lines
+ if (buffer->input_[buffer->index_] == '\n')
+ {
+ ++param->yylineno;
+ }
+ ++buffer->index_;
+ }
+ }
+
+ size_t current;
+ size_t last = buffer->size_ + (buffer->eof_ ? 1 : 0);
+ for (current = buffer->index_; current < last; current++)
+ {
+ static const char* separators = " \t\r\n:*(){}";
+ char c = (buffer->eof_ && current == buffer->size_ ?
+ '\n' : buffer->input_[current]);
+ switch (buffer->state_)
+ {
+ case ACE_COMMENT:
+ if (c == '\n')
+ {
+ buffer->state_ = ACE_NO_STATE;
+ buffer->index_ = current + 1;
+ ++param->yylineno;
+ }
+ break;
+ case ACE_STRING:
+ if (!(c >= ' ' && c <= '~'))
+ {
+ // The character at currrent is definitely not part of
+ // the string so we need to move current back one.
+ --current;
+
+ // Get the starting point of our string (skipping the quote)
+ char* source = buffer->input_ + buffer->index_ + 1;
+
+ // Now, we need to move back in the string until we find the
+ // same character that started the string
+ bool string_end_found = false;
+ if (current > buffer->index_)
+ {
+ for (size_t i = current - buffer->index_; i-- != 0; )
+ {
+ if (source[i] == buffer->string_start_)
+ {
+ current = buffer->index_ + i + 1;
+ string_end_found = true;
+ break;
+ }
+ }
+ }
+
+ if (!string_end_found)
+ {
+ ace_yyerror (++param->yyerrno,
+ param->yylineno,
+ "Unable to find the end of the string");
+ return ACE_NO_STATE;
+ }
+
+ size_t amount = (current - buffer->index_) - 1;
+#if defined (ACE_USES_WCHAR)
+ ACE_TCHAR target[ACE_YY_CONVERSION_SPACE] = ACE_TEXT ("");
+ size_t length = 0;
+ if (!convert_from_utf8 (buffer->converter_,
+ source,
+ amount,
+ target,
+ ACE_YY_CONVERSION_SPACE,
+ length))
+ {
+ ace_yyerror (++param->yyerrno,
+ param->yylineno,
+ "Unable to convert string from UTF-8");
+ return ACE_NO_STATE;
+ }
+ amount = length;
+#else
+ char* target = source;
+#endif /* ACE_USES_WCHAR */
+ ace_yylval->ident_ = param->obstack.copy (target, amount);
+ buffer->state_ = ACE_NO_STATE;
+ buffer->index_ = current + 1;
+ return ACE_STRING;
+ }
+ break;
+ case ACE_NO_STATE:
+ if (c == '"' || c == '\'')
+ {
+ buffer->string_start_ = c;
+ buffer->state_ = ACE_STRING;
+ }
+ else if (c == '#')
+ {
+ buffer->state_ = ACE_COMMENT;
+ }
+ else if (ACE_OS::strchr (separators, c) != 0)
+ {
+ if (c == '\n')
+ {
+ ++param->yylineno;
+ }
+
+ if (current == buffer->index_ + 1)
+ {
+ int lower = ACE_OS::ace_tolower (
+ buffer->input_[current - 1]);
+ if (c == ':' &&
+ (buffer->input_[current - 1] == '%' ||
+ (lower >= 'a' && lower <= 'z')))
+ {
+ // This is considered a path, so we need to
+ // skip over the ':' and go around the loop
+ // again
+ break;
+ }
+ }
+
+ if (current == buffer->index_)
+ {
+ buffer->index_ = current + 1;
+ if (isspace (c))
+ {
+ // This is an empty line.
+ // Let's look for something else.
+ break;
+ }
+ else
+ {
+ return c;
+ }
+ }
+
+ // String from buffer->index_ to current (inclusive)
+ size_t size = (current - buffer->index_) + 1;
+ ACE_TEMPORARY_STRING (str, size);
+ ACE_OS::strncpy (str, buffer->input_ + buffer->index_,
+ size - 1);
+ str[size - 1] = '\0';
+
+
+ if (ACE_OS::strcmp (str, "dynamic") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_DYNAMIC;
+ }
+ else if (ACE_OS::strcmp (str, "static") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_STATIC;
+ }
+ else if (ACE_OS::strcmp (str, "suspend") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_SUSPEND;
+ }
+ else if (ACE_OS::strcmp (str, "resume") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_RESUME;
+ }
+ else if (ACE_OS::strcmp (str, "remove") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_REMOVE;
+ }
+ else if (ACE_OS::strcmp (str, "stream") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_USTREAM;
+ }
+ else if (ACE_OS::strcmp (str, "Module") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_MODULE_T;
+ }
+ else if (ACE_OS::strcmp (str, "Service_Object") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_SVC_OBJ_T;
+ }
+ else if (ACE_OS::strcmp (str, "STREAM") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_STREAM_T;
+ }
+ else if (ACE_OS::strcmp (str, "active") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_ACTIVE;
+ }
+ else if (ACE_OS::strcmp (str, "inactive") == 0)
+ {
+ buffer->index_ = current;
+ return ACE_INACTIVE;
+ }
+ else
+ {
+ // Get the string and save it in ace_yylval
+ int token = ACE_IDENT;
+ size_t amount = size - 1;
+#if defined (ACE_USES_WCHAR)
+ ACE_TCHAR target[ACE_YY_CONVERSION_SPACE] = ACE_TEXT ("");
+ size_t length = 0;
+ if (!convert_from_utf8 (buffer->converter_,
+ str,
+ amount,
+ target,
+ ACE_YY_CONVERSION_SPACE,
+ length))
+ {
+ ace_yyerror (++param->yyerrno,
+ param->yylineno,
+ "Unable to convert "
+ "identifier from UTF-8");
+ return ACE_NO_STATE;
+ }
+ amount = length;
+#else
+ char* target = str;
+#endif /* ACE_USES_WCHAR */
+ ace_yylval->ident_ = param->obstack.copy (target, amount);
+
+ // Determine the difference between pathname and ident
+ if (ACE_OS::ace_isdigit (ace_yylval->ident_[0]))
+ {
+ token = ACE_PATHNAME;
+ }
+ else
+ {
+ static const ACE_TCHAR* path_parts =
+ ACE_TEXT ("/\\:%.~-");
+ for (const ACE_TCHAR* p = path_parts; *p != '\0'; p++)
+ {
+ if (ACE_OS::strchr (ace_yylval->ident_, *p) != 0)
+ {
+ token = ACE_PATHNAME;
+ break;
+ }
+ }
+ }
+
+ buffer->state_ = ACE_NO_STATE;
+ buffer->index_ = current;
+ return token;
+ }
+ }
+ break;
+ default:
+ ace_yyerror (++param->yyerrno,
+ param->yylineno,
+ "Unexpected state in ACE_Svc_Conf_Lexer::scan");
+ return ACE_NO_STATE;
+ }
+ }
+
+ // We need more from the input source so, we will move the remainder of
+ // the buffer to the front and signal that we need more
+ if (!buffer->eof_)
+ {
+ buffer->need_more_ = true;
+ if (buffer->state_ == ACE_COMMENT)
+ {
+ buffer->index_ = 0;
+ buffer->size_ = 0;
+ }
+ else
+ {
+ buffer->size_ = current - buffer->index_;
+ if (buffer->size_ != 0 && buffer->index_ != 0)
+ ACE_OS::memmove (buffer->input_,
+ buffer->input_ + buffer->index_, buffer->size_);
+ buffer->index_ = 0;
+ buffer->state_ = ACE_NO_STATE;
+ }
+ }
+ return ACE_NO_STATE;
+}
+
+#if defined (ACE_USES_WCHAR)
+
+bool
+ACE_Svc_Conf_Lexer::convert_to_utf8 (
+ ACE_Svc_Conf_Param* param,
+ size_t skip_bytes,
+ ACE_Encoding_Converter_Factory::Encoding_Hint hint)
+{
+ bool status = false;
+ if (param->buffer->converter_ == 0)
+ {
+ param->buffer->converter_ =
+ ACE_Encoding_Converter_Factory::create (
+ reinterpret_cast<ACE_Byte*> (param->buffer->input_ + skip_bytes),
+ param->buffer->size_ - skip_bytes,
+ hint);
+ }
+
+ if (param->buffer->converter_ != 0)
+ {
+ char target[ACE_YY_CONVERSION_SPACE] = "";
+ if (param->buffer->converter_->to_utf8 (
+ param->buffer->input_ + skip_bytes,
+ param->buffer->size_ - skip_bytes,
+ reinterpret_cast<ACE_Byte*> (target),
+ ACE_YY_CONVERSION_SPACE) == ACE_Encoding_Converter::CONVERSION_OK)
+ {
+ ACE_OS::strcpy (param->buffer->input_ + skip_bytes, target);
+ param->buffer->size_ = ACE_OS::strlen (target) + skip_bytes;
+ status = true;
+ }
+ }
+
+ return status;
+}
+
+bool
+ACE_Svc_Conf_Lexer::convert_from_utf8 (ACE_Encoding_Converter* converter,
+ const char* source,
+ size_t source_size,
+ ACE_TCHAR* target,
+ size_t target_size,
+ size_t& length)
+{
+ if (converter != 0)
+ {
+ if (converter->from_utf8 (
+ reinterpret_cast <const ACE_Byte*> (source),
+ source_size,
+ target,
+ target_size) != ACE_Encoding_Converter::CONVERSION_OK)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ ACE_OS::strncpy (target, ACE_TEXT_CHAR_TO_TCHAR (source), source_size);
+ target[source_size] = 0;
+ }
+
+ length = ACE_OS::strlen (target);
+ return true;
+}
+
+ACE_Encoding_Converter_Factory::Encoding_Hint
+ACE_Svc_Conf_Lexer::locate_bom (char* source,
+ size_t source_size,
+ size_t& bytes_used)
+{
+ struct bom {
+ size_t length_;
+ const char* data_;
+ ACE_Encoding_Converter_Factory::Encoding_Hint hint_;
+ };
+ static const bom boms[] = {
+ { 4, "\x00\x00\xfe\xff", ACE_Encoding_Converter_Factory::ACE_UTF_32BE },
+ { 4, "\xff\xfe\x00\x00", ACE_Encoding_Converter_Factory::ACE_UTF_32LE },
+ { 2, "\xfe\xff", ACE_Encoding_Converter_Factory::ACE_UTF_16BE },
+ { 2, "\xff\xfe", ACE_Encoding_Converter_Factory::ACE_UTF_16LE },
+ { 3, "\xef\xbb\xbf", ACE_Encoding_Converter_Factory::ACE_UTF_8 },
+ };
+
+ for (size_t i = 0; i < sizeof (boms) / sizeof (bom); i++)
+ {
+ if (source_size >= boms[i].length_)
+ {
+ if (ACE_OS::memcmp (source,
+ boms[i].data_, boms[i].length_) == 0)
+ {
+ bytes_used = boms[i].length_;
+ return boms[i].hint_;
+ }
+ }
+ }
+
+ // No BOM was found
+ bytes_used = 0;
+ return ACE_Encoding_Converter_Factory::ACE_NONE;
+}
+
+#endif /* ACE_USES_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_CLASSIC_SVC_CONF = 1 */
diff --git a/ACE/ace/Svc_Conf_Lexer.h b/ACE/ace/Svc_Conf_Lexer.h
new file mode 100644
index 00000000000..387e7b7611f
--- /dev/null
+++ b/ACE/ace/Svc_Conf_Lexer.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+
+//=========================================================================
+/**
+ * @file Svc_Conf_Lexer.h
+ *
+ * $Id$
+ *
+ * This class is a hand-coded replacement for the lexer generated from
+ * Svc_Conf.l that correctly supports Unicode.
+ *
+ * @author Chad Elliott <elliott_c@ociweb.com>
+ */
+//=========================================================================
+
+#ifndef SVC_CONF_LEXER_H
+#define SVC_CONF_LEXER_H
+
+#include /**/ "ace/pre.h"
+#include "ace/Svc_Conf.h"
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+#include "ace/Encoding_Converter_Factory.h"
+
+class ACE_Encoding_Converter;
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/** This class lexes the classic ACE Service Configurator language.
+ * The entry point is similar to what flex would generate. However, it
+ * is a static method in this class (which is really just name space).
+ */
+class ACE_Svc_Conf_Lexer
+{
+public:
+ /// This is similar to the C function, ace_yylex, which a bison
+ /// generated parser expects. It returns information in the ace_yylval
+ /// parameter and uses input stored in the param parameter.
+ static int yylex (ACE_YYSTYPE* ace_yylval,
+ ACE_Svc_Conf_Param* param);
+
+private:
+ static size_t input(ACE_Svc_Conf_Param* param, char* buf, size_t max_size);
+
+ static int scan (ACE_YYSTYPE* ace_yylval, ACE_Svc_Conf_Param* param);
+
+#if defined (ACE_USES_WCHAR)
+ static bool convert_to_utf8 (
+ ACE_Svc_Conf_Param* param,
+ size_t skip_bytes,
+ ACE_Encoding_Converter_Factory::Encoding_Hint hint);
+ static bool convert_from_utf8 (ACE_Encoding_Converter* converter,
+ const char* source,
+ size_t source_size,
+ ACE_TCHAR* target,
+ size_t target_size,
+ size_t& length);
+ static ACE_Encoding_Converter_Factory::Encoding_Hint
+ locate_bom (char* source,
+ size_t source_size,
+ size_t& bytes_used);
+#endif /* ACE_USES_WCHAR */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_CLASSIC_SVC_CONF = 1 */
+
+#include /**/ "ace/post.h"
+
+#endif /* SVC_CONF_LEXER_H */
diff --git a/ACE/ace/Svc_Conf_Param.h b/ACE/ace/Svc_Conf_Param.h
new file mode 100644
index 00000000000..f1d31d13d9e
--- /dev/null
+++ b/ACE/ace/Svc_Conf_Param.h
@@ -0,0 +1,142 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Svc_Conf_Param.h
+ *
+ * $Id$
+ *
+ * @author Iliyan Jeliazkov <iliyan@ociweb.com>
+ * @author Based on code originally found in Svc_Conf.h by Doug
+ Schmidt and Ossama Othman.
+ */
+//=============================================================================
+
+
+#ifndef ACE_SVC_CONF_PARAM_H
+#define ACE_SVC_CONF_PARAM_H
+
+#include /**/ "ace/pre.h"
+
+// Globally visible macros, type decls, and extern var decls for
+// Service Configurator utility.
+
+#include "ace/Obstack.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+struct ace_yy_buffer_state;
+class ACE_Service_Gestalt;
+
+extern void ace_yy_delete_buffer (ace_yy_buffer_state *buffer);
+
+/**
+ * @class ACE_Svc_Conf_Param
+ *
+ * @brief An instance of this object will be passed down to the
+ * yyparse() and yylex() functions.
+ *
+ * This is intended for internal use within ACE service configuration
+ * framework only.
+ *
+ * This class retains the state for a given parse/scan. It primarily
+ * makes it possible to hold the static object lock in the scanner
+ * for as short a period of time as possible. The resulting finer
+ * grained locking prevents deadlocks from occuring when scanning a
+ * `svc.conf' file and activating an ACE_Task, for example, as a
+ * result of processing the directives in that file.
+ */
+class ACE_Svc_Conf_Param
+{
+public:
+
+ enum SVC_CONF_PARAM_TYPE
+ {
+ /// The lexer will scan a file containing one or more directives.
+ SVC_CONF_FILE,
+
+ /// The lexer will scan a string containing a directive.
+ SVC_CONF_DIRECTIVE
+ };
+
+ /// Constructor
+ ACE_Svc_Conf_Param (ACE_Service_Gestalt* config, FILE *file)
+ : type (SVC_CONF_FILE),
+ yyerrno (0),
+ yylineno (1),
+ buffer (0),
+ obstack (),
+ config (config)
+ {
+ source.file = file;
+ }
+
+ /// Constructor
+ ACE_Svc_Conf_Param (ACE_Service_Gestalt* config, const ACE_TCHAR *directive)
+ : type (SVC_CONF_DIRECTIVE),
+ yyerrno (0),
+ yylineno (1),
+ buffer (0),
+ obstack (),
+ config (config)
+ {
+ source.directive = directive;
+ }
+
+ ~ACE_Svc_Conf_Param (void)
+ {
+ ace_yy_delete_buffer (this->buffer);
+ }
+
+public:
+
+ union
+ {
+ /// FILE stream from which directives will be scanned and parsed.
+ FILE *file;
+
+ /// String containing directive that will be scanned and parsed.
+ const ACE_TCHAR *directive;
+
+ } source;
+
+ /// Discriminant use to determine which union member to use.
+ SVC_CONF_PARAM_TYPE type;
+
+ /// Keeps track of the number of errors encountered so far.
+ int yyerrno;
+
+ /// Keeps track of the current line number for error-handling routine.
+ int yylineno;
+
+ /// Lexer buffer that corresponds to the current Service
+ /// Configurator file/direct scan.
+ ace_yy_buffer_state *buffer;
+
+ /// Obstack used for efficient memory allocation when
+ /// parsing/scanning a service configurator directive.
+ ACE_Obstack_T<ACE_TCHAR> obstack;
+
+ /// A reference to the configuration
+ ACE_Service_Gestalt *config;
+};
+
+
+// Parameter that is passed down to the yyparse() function, and
+// eventually to yylex().
+#define ACE_YYPARSE_PARAM ace_svc_conf_parameter
+
+#define ACE_YYLEX_PARAM ACE_YYPARSE_PARAM
+
+#define ACE_SVC_CONF_PARAM (static_cast<ACE_Svc_Conf_Param *> (ACE_YYLEX_PARAM))
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SVC_CONF_PARAM_H */
diff --git a/ACE/ace/Svc_Conf_Tokens.h b/ACE/ace/Svc_Conf_Tokens.h
new file mode 100644
index 00000000000..8c514a0a582
--- /dev/null
+++ b/ACE/ace/Svc_Conf_Tokens.h
@@ -0,0 +1,81 @@
+// $Id$
+#ifndef BISON_SVC_CONF_TAB_H
+# define BISON_SVC_CONF_TAB_H
+# define ACE_YYSTYPE_IS_DECLARED 1
+/* A Bison parser, made by GNU Bison 2.0. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Tokens. */
+#ifndef ACE_YYTOKENTYPE
+# define ACE_YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum ace_yytokentype {
+ ACE_DYNAMIC = 258,
+ ACE_STATIC = 259,
+ ACE_SUSPEND = 260,
+ ACE_RESUME = 261,
+ ACE_REMOVE = 262,
+ ACE_USTREAM = 263,
+ ACE_MODULE_T = 264,
+ ACE_STREAM_T = 265,
+ ACE_SVC_OBJ_T = 266,
+ ACE_ACTIVE = 267,
+ ACE_INACTIVE = 268,
+ ACE_PATHNAME = 269,
+ ACE_IDENT = 270,
+ ACE_STRING = 271
+ };
+#endif
+#define ACE_DYNAMIC 258
+#define ACE_STATIC 259
+#define ACE_SUSPEND 260
+#define ACE_RESUME 261
+#define ACE_REMOVE 262
+#define ACE_USTREAM 263
+#define ACE_MODULE_T 264
+#define ACE_STREAM_T 265
+#define ACE_SVC_OBJ_T 266
+#define ACE_ACTIVE 267
+#define ACE_INACTIVE 268
+#define ACE_PATHNAME 269
+#define ACE_IDENT 270
+#define ACE_STRING 271
+
+
+
+
+#if ! defined (ACE_YYSTYPE) && ! defined (ACE_YYSTYPE_IS_DECLARED)
+typedef int ACE_YYSTYPE;
+# define ace_yystype ACE_YYSTYPE /* obsolescent; will be withdrawn */
+# define ACE_YYSTYPE_IS_DECLARED 1
+# define ACE_YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+
+
+#endif /* ifndef BISON_SVC_CONF_TAB_H */
diff --git a/ACE/ace/Svc_Conf_y.cpp b/ACE/ace/Svc_Conf_y.cpp
new file mode 100644
index 00000000000..cc303d98d31
--- /dev/null
+++ b/ACE/ace/Svc_Conf_y.cpp
@@ -0,0 +1,1759 @@
+/* A Bison parser, made by GNU Bison 2.0. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with ace_yy or ACE_YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define ACE_YYBISON 1
+
+/* Skeleton name. */
+#define ACE_YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define ACE_YYPURE 1
+
+/* Using locations. */
+#define ACE_YYLSP_NEEDED 0
+
+/* On HP-UX aC++ on Itanium, disable warning 2111, statement is unreachable. */
+#if defined (__HP_aCC) && defined (__ia64)
+# pragma diag_suppress 2111
+#endif
+
+/* Tokens. */
+#ifndef ACE_YYTOKENTYPE
+# define ACE_YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum ace_yytokentype {
+ ACE_DYNAMIC = 258,
+ ACE_STATIC = 259,
+ ACE_SUSPEND = 260,
+ ACE_RESUME = 261,
+ ACE_REMOVE = 262,
+ ACE_USTREAM = 263,
+ ACE_MODULE_T = 264,
+ ACE_STREAM_T = 265,
+ ACE_SVC_OBJ_T = 266,
+ ACE_ACTIVE = 267,
+ ACE_INACTIVE = 268,
+ ACE_PATHNAME = 269,
+ ACE_IDENT = 270,
+ ACE_STRING = 271
+ };
+#endif
+#define ACE_DYNAMIC 258
+#define ACE_STATIC 259
+#define ACE_SUSPEND 260
+#define ACE_RESUME 261
+#define ACE_REMOVE 262
+#define ACE_USTREAM 263
+#define ACE_MODULE_T 264
+#define ACE_STREAM_T 265
+#define ACE_SVC_OBJ_T 266
+#define ACE_ACTIVE 267
+#define ACE_INACTIVE 268
+#define ACE_PATHNAME 269
+#define ACE_IDENT 270
+#define ACE_STRING 271
+
+
+
+
+/* Copy the first part of user declarations. */
+
+
+// $Id$
+
+#include "ace/Svc_Conf.h"
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+
+#include "ace/ARGV.h"
+#include "ace/Module.h"
+#include "ace/Stream.h"
+#include "ace/Service_Types.h"
+#include "ace/OS_NS_string.h"
+
+
+#include "ace/ace_wchar.h"
+
+ACE_RCSID (ace,
+ Svc_Conf_y,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Prototypes.
+
+static ACE_Module_Type *ace_get_module (const ACE_Service_Type *sr,
+ const ACE_Service_Type *sv,
+ int & ace_ace_yyerrno);
+
+static ACE_Module_Type *ace_get_module (const ACE_Service_Type *sr,
+ const ACE_TCHAR *svc_name,
+ int & ace_ace_yyerrno);
+
+#define ACE_YYDEBUG_LEXER_TEXT (ace_yytext[ace_yyleng] = '\0', ace_yytext)
+
+// Force the pretty debugging code to compile.
+// #define ACE_YYDEBUG 1
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+/* Enabling traces. */
+#ifndef ACE_YYDEBUG
+# define ACE_YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef ACE_YYERROR_VERBOSE
+# undef ACE_YYERROR_VERBOSE
+# define ACE_YYERROR_VERBOSE 1
+#else
+# define ACE_YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (ACE_YYSTYPE) && ! defined (ACE_YYSTYPE_IS_DECLARED)
+typedef int ACE_YYSTYPE;
+# define ace_yystype ACE_YYSTYPE /* obsolescent; will be withdrawn */
+# define ACE_YYSTYPE_IS_DECLARED 1
+# define ACE_YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 213 of yacc.c. */
+
+
+#if ! defined (ace_yyoverflow) || ACE_YYERROR_VERBOSE
+
+# ifndef ACE_YYFREE
+# define ACE_YYFREE free
+# endif
+# ifndef ACE_YYMALLOC
+# define ACE_YYMALLOC malloc
+# endif
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef ACE_YYSTACK_USE_ALLOCA
+# if ACE_YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define ACE_YYSTACK_ALLOC __builtin_alloca
+# else
+# define ACE_YYSTACK_ALLOC alloca
+# endif
+# endif
+# endif
+
+# ifdef ACE_YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define ACE_YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define ACE_YYSIZE_T size_t
+# endif
+# define ACE_YYSTACK_ALLOC ACE_YYMALLOC
+# define ACE_YYSTACK_FREE ACE_YYFREE
+# endif
+#endif /* ! defined (ace_yyoverflow) || ACE_YYERROR_VERBOSE */
+
+
+#if (! defined (ace_yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (defined (ACE_YYSTYPE_IS_TRIVIAL) && ACE_YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union ace_yyalloc
+{
+ short int ace_yyss;
+ ACE_YYSTYPE ace_yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define ACE_YYSTACK_GAP_MAXIMUM (sizeof (union ace_yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define ACE_YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short int) + sizeof (ACE_YYSTYPE)) \
+ + ACE_YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef ACE_YYCOPY
+# if defined (__GNUC__) && 1 < __GNUC__
+# define ACE_YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define ACE_YYCOPY(To, From, Count) \
+ do \
+ { \
+ register ACE_YYSIZE_T ace_yyi; \
+ for (ace_yyi = 0; ace_yyi < (Count); ace_yyi++) \
+ (To)[ace_yyi] = (From)[ace_yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables ACE_YYSIZE and ACE_YYSTACKSIZE give the old and new number of
+ elements in the stack, and ACE_YYPTR gives the new location of the
+ stack. Advance ACE_YYPTR to a properly aligned location for the next
+ stack. */
+# define ACE_YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ ACE_YYSIZE_T ace_yynewbytes; \
+ ACE_YYCOPY (&ace_yyptr->Stack, Stack, ace_yysize); \
+ Stack = &ace_yyptr->Stack; \
+ ace_yynewbytes = ace_yystacksize * sizeof (*Stack) + ACE_YYSTACK_GAP_MAXIMUM; \
+ ace_yyptr += ace_yynewbytes / sizeof (*ace_yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char ace_yysigned_char;
+#else
+ typedef short int ace_yysigned_char;
+#endif
+
+/* ACE_YYFINAL -- State number of the termination state. */
+#define ACE_YYFINAL 2
+/* ACE_YYLAST -- Last index in ACE_YYTABLE. */
+#define ACE_YYLAST 62
+
+/* ACE_YYNTOKENS -- Number of terminals. */
+#define ACE_YYNTOKENS 23
+/* ACE_YYNNTS -- Number of nonterminals. */
+#define ACE_YYNNTS 21
+/* ACE_YYNRULES -- Number of rules. */
+#define ACE_YYNRULES 45
+/* ACE_YYNRULES -- Number of states. */
+#define ACE_YYNSTATES 66
+
+/* ACE_YYTRANSLATE(ACE_YYLEX) -- Bison symbol number corresponding to ACE_YYLEX. */
+#define ACE_YYUNDEFTOK 2
+#define ACE_YYMAXUTOK 271
+
+#define ACE_YYTRANSLATE(ACE_YYX) \
+ ((unsigned int) (ACE_YYX) <= ACE_YYMAXUTOK ? ace_yytranslate[ACE_YYX] : ACE_YYUNDEFTOK)
+
+/* ACE_YYTRANSLATE[ACE_YYLEX] -- Bison symbol number corresponding to ACE_YYLEX. */
+static const unsigned char ace_yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 20, 21, 22, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 19, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 17, 2, 18, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16
+};
+
+#if ACE_YYDEBUG
+/* ACE_YYPRHS[ACE_YYN] -- Index of the first RHS symbol of rule number ACE_YYN in
+ ACE_YYRHS. */
+static const unsigned char ace_yyprhs[] =
+{
+ 0, 0, 3, 6, 9, 10, 12, 14, 16, 18,
+ 20, 22, 26, 30, 33, 36, 39, 43, 44, 49,
+ 51, 53, 54, 59, 60, 63, 64, 66, 68, 70,
+ 72, 74, 79, 81, 83, 84, 88, 94, 99, 102,
+ 105, 108, 110, 111, 113, 115
+};
+
+/* ACE_YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const ace_yysigned_char ace_yyrhs[] =
+{
+ 24, 0, -1, 24, 25, -1, 24, 1, -1, -1,
+ 26, -1, 27, -1, 28, -1, 29, -1, 30, -1,
+ 31, -1, 3, 38, 42, -1, 4, 15, 42, -1,
+ 5, 15, -1, 6, 15, -1, 7, 15, -1, 8,
+ 33, 34, -1, -1, 8, 15, 32, 34, -1, 26,
+ -1, 27, -1, -1, 17, 35, 36, 18, -1, -1,
+ 36, 37, -1, -1, 26, -1, 27, -1, 28, -1,
+ 29, -1, 30, -1, 15, 41, 40, 39, -1, 12,
+ -1, 13, -1, -1, 43, 19, 15, -1, 43, 19,
+ 15, 20, 21, -1, 19, 15, 20, 21, -1, 9,
+ 22, -1, 11, 22, -1, 10, 22, -1, 16, -1,
+ -1, 14, -1, 15, -1, 16, -1
+};
+
+/* ACE_YYRLINE[ACE_YYN] -- source line where rule number ACE_YYN was defined. */
+static const unsigned short int ace_yyrline[] =
+{
+ 0, 62, 62, 71, 75, 79, 80, 81, 82, 83,
+ 84, 88, 98, 105, 112, 119, 126, 130, 130, 137,
+ 140, 147, 146, 155, 159, 167, 171, 196, 210, 219,
+ 228, 250, 257, 261, 266, 272, 276, 280, 287, 291,
+ 295, 302, 303, 307, 308, 309
+};
+#endif
+
+#if ACE_YYDEBUG || ACE_YYERROR_VERBOSE
+/* ACE_YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at ACE_YYNTOKENS, nonterminals. */
+static const char *const ace_yytname[] =
+{
+ "$end", "error", "$undefined", "ACE_DYNAMIC", "ACE_STATIC",
+ "ACE_SUSPEND", "ACE_RESUME", "ACE_REMOVE", "ACE_USTREAM", "ACE_MODULE_T",
+ "ACE_STREAM_T", "ACE_SVC_OBJ_T", "ACE_ACTIVE", "ACE_INACTIVE",
+ "ACE_PATHNAME", "ACE_IDENT", "ACE_STRING", "'{'", "'}'", "':'", "'('",
+ "')'", "'*'", "$accept", "svc_config_entries", "svc_config_entry",
+ "dynamic", "static", "suspend", "resume", "remove", "stream", "@1",
+ "stream_ops", "stream_modules", "@2", "module_list", "module",
+ "svc_location", "status", "svc_initializer", "type", "parameters_opt",
+ "pathname", 0
+};
+#endif
+
+# ifdef ACE_YYPRINT
+/* ACE_YYTOKNUM[ACE_YYLEX-NUM] -- Internal token number corresponding to
+ token ACE_YYLEX-NUM. */
+static const unsigned short int ace_yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 123, 125, 58,
+ 40, 41, 42
+};
+# endif
+
+/* ACE_YYR1[ACE_YYN] -- Symbol number of symbol that rule ACE_YYN derives. */
+static const unsigned char ace_yyr1[] =
+{
+ 0, 23, 24, 24, 24, 25, 25, 25, 25, 25,
+ 25, 26, 27, 28, 29, 30, 31, 32, 31, 33,
+ 33, 35, 34, 34, 36, 36, 37, 37, 37, 37,
+ 37, 38, 39, 39, 39, 40, 40, 40, 41, 41,
+ 41, 42, 42, 43, 43, 43
+};
+
+/* ACE_YYR2[ACE_YYN] -- Number of symbols composing right hand side of rule ACE_YYN. */
+static const unsigned char ace_yyr2[] =
+{
+ 0, 2, 2, 2, 0, 1, 1, 1, 1, 1,
+ 1, 3, 3, 2, 2, 2, 3, 0, 4, 1,
+ 1, 0, 4, 0, 2, 0, 1, 1, 1, 1,
+ 1, 4, 1, 1, 0, 3, 5, 4, 2, 2,
+ 2, 1, 0, 1, 1, 1
+};
+
+/* ACE_YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when ACE_YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char ace_yydefact[] =
+{
+ 4, 0, 1, 3, 0, 0, 0, 0, 0, 0,
+ 2, 5, 6, 7, 8, 9, 10, 0, 42, 42,
+ 13, 14, 15, 17, 19, 20, 23, 0, 0, 0,
+ 0, 41, 11, 12, 23, 21, 16, 38, 40, 39,
+ 43, 44, 45, 0, 34, 0, 18, 25, 0, 32,
+ 33, 31, 0, 0, 0, 35, 22, 26, 27, 28,
+ 29, 30, 24, 37, 0, 36
+};
+
+/* ACE_YYDEFGOTO[NTERM-NUM]. */
+static const ace_yysigned_char ace_yydefgoto[] =
+{
+ -1, 1, 10, 11, 12, 13, 14, 15, 16, 34,
+ 26, 36, 47, 53, 62, 18, 51, 44, 30, 32,
+ 45
+};
+
+/* ACE_YYPACT[STATE-NUM] -- Index in ACE_YYTABLE of the portion describing
+ STATE-NUM. */
+#define ACE_YYPACT_NINF -13
+static const ace_yysigned_char ace_yypact[] =
+{
+ -13, 20, -13, -13, 1, 3, 7, 14, 18, 4,
+ -13, -13, -13, -13, -13, -13, -13, 21, 19, 19,
+ -13, -13, -13, -13, -13, -13, -2, 12, 15, 16,
+ -5, -13, -13, -13, -2, -13, -13, -13, -13, -13,
+ -13, -13, -13, 24, 0, 17, -13, -13, 22, -13,
+ -13, -13, 25, -1, 26, 23, -13, -13, -13, -13,
+ -13, -13, -13, -13, 27, -13
+};
+
+/* ACE_YYPGOTO[NTERM-NUM]. */
+static const ace_yysigned_char ace_yypgoto[] =
+{
+ -13, -13, -13, -9, -8, -12, -7, -4, -13, -13,
+ -13, 28, -13, -13, -13, -13, -13, -13, -13, 31,
+ -13
+};
+
+/* ACE_YYTABLE[ACE_YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what ACE_YYDEFACT says.
+ If ACE_YYTABLE_NINF, syntax error. */
+#define ACE_YYTABLE_NINF -1
+static const unsigned char ace_yytable[] =
+{
+ 24, 25, 4, 5, 6, 7, 8, 4, 5, 40,
+ 41, 42, 49, 50, 43, 35, 17, 56, 19, 23,
+ 2, 3, 20, 4, 5, 6, 7, 8, 9, 21,
+ 27, 28, 29, 22, 37, 31, 52, 38, 39, 48,
+ 55, 59, 54, 64, 57, 58, 60, 63, 65, 61,
+ 33, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 46
+};
+
+static const ace_yysigned_char ace_yycheck[] =
+{
+ 9, 9, 3, 4, 5, 6, 7, 3, 4, 14,
+ 15, 16, 12, 13, 19, 17, 15, 18, 15, 15,
+ 0, 1, 15, 3, 4, 5, 6, 7, 8, 15,
+ 9, 10, 11, 15, 22, 16, 19, 22, 22, 15,
+ 15, 53, 20, 20, 53, 53, 53, 21, 21, 53,
+ 19, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 34
+};
+
+/* ACE_YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char ace_yystos[] =
+{
+ 0, 24, 0, 1, 3, 4, 5, 6, 7, 8,
+ 25, 26, 27, 28, 29, 30, 31, 15, 38, 15,
+ 15, 15, 15, 15, 26, 27, 33, 9, 10, 11,
+ 41, 16, 42, 42, 32, 17, 34, 22, 22, 22,
+ 14, 15, 16, 19, 40, 43, 34, 35, 15, 12,
+ 13, 39, 19, 36, 20, 15, 18, 26, 27, 28,
+ 29, 30, 37, 21, 20, 21
+};
+
+#if ! defined (ACE_YYSIZE_T) && defined (__SIZE_TYPE__)
+# define ACE_YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (ACE_YYSIZE_T) && defined (size_t)
+# define ACE_YYSIZE_T size_t
+#endif
+#if ! defined (ACE_YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define ACE_YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (ACE_YYSIZE_T)
+# define ACE_YYSIZE_T unsigned int
+#endif
+
+#define ace_yyerrok (ace_yyerrstatus = 0)
+#define ace_yyclearin (ace_yychar = ACE_YYEMPTY)
+#define ACE_YYEMPTY (-2)
+#define ACE_YYEOF 0
+
+#define ACE_YYACCEPT goto ace_yyacceptlab
+#define ACE_YYABORT goto ace_yyabortlab
+#define ACE_YYERROR goto ace_yyerrorlab
+
+
+/* Like ACE_YYERROR except do call ace_yyerror. This remains here temporarily
+ to ease the transition to the new meaning of ACE_YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define ACE_YYFAIL goto ace_yyerrlab
+
+#define ACE_YYRECOVERING() (!!ace_yyerrstatus)
+
+#define ACE_YYBACKUP(Token, Value) \
+ do \
+ if (ace_yychar == ACE_YYEMPTY && ace_yylen == 1) \
+ { \
+ ace_yychar = (Token); \
+ ace_yylval = (Value); \
+ ace_yytoken = ACE_YYTRANSLATE (ace_yychar); \
+ ACE_YYPOPSTACK; \
+ goto ace_yybackup; \
+ } \
+ else \
+ { \
+ ace_yyerror (ACE_SVC_CONF_PARAM->yyerrno, ACE_SVC_CONF_PARAM->yylineno, "syntax error: cannot back up");\
+ ACE_YYERROR; \
+ } \
+ while (0)
+
+
+#define ACE_YYTERROR 1
+#define ACE_YYERRCODE 256
+
+
+/* ACE_YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define ACE_YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef ACE_YYLLOC_DEFAULT
+# define ACE_YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (N) \
+ { \
+ (Current).first_line = ACE_YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = ACE_YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = ACE_YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = ACE_YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ ACE_YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ ACE_YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (0)
+#endif
+
+
+/* ACE_YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef ACE_YY_LOCATION_PRINT
+# if ACE_YYLTYPE_IS_TRIVIAL
+# define ACE_YY_LOCATION_PRINT(File, Loc) \
+ ACE_OS::fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define ACE_YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* ACE_YYLEX -- calling `ace_yylex' with the right arguments. */
+
+#ifdef ACE_YYLEX_PARAM
+# define ACE_YYLEX ace_yylex (&ace_yylval, ACE_YYLEX_PARAM)
+#else
+# define ACE_YYLEX ace_yylex (&ace_yylval)
+#endif
+
+/* Enable debugging if requested. */
+#if ACE_YYDEBUG
+
+# ifndef ACE_YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define ACE_YYFPRINTF ACE_OS::fprintf
+# endif
+
+# define ACE_YYDPRINTF(Args) \
+ do \
+ { \
+ if (ace_yydebug) \
+ ACE_YYFPRINTF Args; \
+ } \
+ while (0)
+
+# define ACE_YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+ do \
+ { \
+ if (ace_yydebug) \
+ { \
+ ACE_YYFPRINTF (stderr, "%s ", Title); \
+ ace_yysymprint (stderr, \
+ Type, Value); \
+ ACE_YYFPRINTF (stderr, "\n"); \
+ } \
+ } \
+ while (0)
+
+/*------------------------------------------------------------------.
+| ace_yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+ace_yy_stack_print (short int *bottom, short int *top)
+#else
+static void
+ace_yy_stack_print (bottom, top)
+ short int *bottom;
+ short int *top;
+#endif
+{
+ ACE_YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ ACE_YYFPRINTF (stderr, " %d", *bottom);
+ ACE_YYFPRINTF (stderr, "\n");
+}
+
+# define ACE_YY_STACK_PRINT(Bottom, Top) \
+ do \
+ { \
+ if (ace_yydebug) \
+ ace_yy_stack_print ((Bottom), (Top)); \
+ } \
+ while (0)
+
+
+/*------------------------------------------------.
+| Report that the ACE_YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+ace_yy_reduce_print (int ace_yyrule)
+#else
+static void
+ace_yy_reduce_print (ace_yyrule)
+ int ace_yyrule;
+#endif
+{
+ int ace_yyi;
+ unsigned int ace_yylno = ace_yyrline[ace_yyrule];
+ ACE_YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ ace_yyrule - 1, ace_yylno);
+ /* Print the symbols being reduced, and their result. */
+ for (ace_yyi = ace_yyprhs[ace_yyrule]; 0 <= ace_yyrhs[ace_yyi]; ace_yyi++)
+ ACE_YYFPRINTF (stderr, "%s ", ace_yytname [ace_yyrhs[ace_yyi]]);
+ ACE_YYFPRINTF (stderr, "-> %s\n", ace_yytname [ace_yyr1[ace_yyrule]]);
+}
+
+# define ACE_YY_REDUCE_PRINT(Rule) \
+ do \
+ { \
+ if (ace_yydebug) \
+ ace_yy_reduce_print (Rule); \
+ } \
+ while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int ace_yydebug;
+#else /* !ACE_YYDEBUG */
+# define ACE_YYDPRINTF(Args)
+# define ACE_YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define ACE_YY_STACK_PRINT(Bottom, Top)
+# define ACE_YY_REDUCE_PRINT(Rule)
+#endif /* !ACE_YYDEBUG */
+
+
+/* ACE_YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef ACE_YYINITDEPTH
+# define ACE_YYINITDEPTH 200
+#endif
+
+/* ACE_YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < ACE_YYSTACK_BYTES (ACE_YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef ACE_YYMAXDEPTH
+# define ACE_YYMAXDEPTH 10000
+#endif
+
+
+
+#if ACE_YYERROR_VERBOSE
+
+# ifndef ace_yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define ace_yystrlen strlen
+# else
+/* Return the length of ACE_YYSTR. */
+static ACE_YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+ace_yystrlen (const char *ace_yystr)
+# else
+ace_yystrlen (ace_yystr)
+ const char *ace_yystr;
+# endif
+{
+ register const char *ace_yys = ace_yystr;
+
+ while (*ace_yys++ != '\0')
+ continue;
+
+ return ace_yys - ace_yystr - 1;
+}
+# endif
+# endif
+
+# ifndef ace_yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define ace_yystpcpy stpcpy
+# else
+/* Copy ACE_YYSRC to ACE_YYDEST, returning the address of the terminating '\0' in
+ ACE_YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+ace_yystpcpy (ACE_TCHAR *ace_yydest, const char *ace_yysrc)
+# else
+ace_yystpcpy (ace_yydest, ace_yysrc)
+ char *ace_yydest;
+ const char *ace_yysrc;
+# endif
+{
+ register char *ace_yyd = ace_yydest;
+ register const char *ace_yys = ace_yysrc;
+
+ while ((*ace_yyd++ = *ace_yys++) != '\0')
+ continue;
+
+ return ace_yyd - 1;
+}
+# endif
+# endif
+
+#endif /* !ACE_YYERROR_VERBOSE */
+
+
+
+#if ACE_YYDEBUG
+/*--------------------------------.
+| Print this symbol on ACE_YYOUTPUT. |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+ace_yysymprint (FILE *ace_yyoutput, int ace_yytype, ACE_YYSTYPE *ace_yyvaluep)
+#else
+static void
+ace_yysymprint (ace_yyoutput, ace_yytype, ace_yyvaluep)
+ FILE *ace_yyoutput;
+ int ace_yytype;
+ ACE_YYSTYPE *ace_yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) ace_yyvaluep;
+
+ if (ace_yytype < ACE_YYNTOKENS)
+ ACE_YYFPRINTF (ace_yyoutput, "token %s (", ace_yytname[ace_yytype]);
+ else
+ ACE_YYFPRINTF (ace_yyoutput, "nterm %s (", ace_yytname[ace_yytype]);
+
+
+# ifdef ACE_YYPRINT
+ if (ace_yytype < ACE_YYNTOKENS)
+ ACE_YYPRINT (ace_yyoutput, ace_yytoknum[ace_yytype], *ace_yyvaluep);
+# endif
+ switch (ace_yytype)
+ {
+ default:
+ break;
+ }
+ ACE_YYFPRINTF (ace_yyoutput, ")");
+}
+
+#endif /* ! ACE_YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+ace_yydestruct (const char *ace_yymsg, int ace_yytype, ACE_YYSTYPE *ace_yyvaluep)
+#else
+static void
+ace_yydestruct (ace_yymsg, ace_yytype, ace_yyvaluep)
+ const char *ace_yymsg;
+ int ace_yytype;
+ ACE_YYSTYPE *ace_yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) ace_yyvaluep;
+ (void) ace_yytype;
+
+ if (!ace_yymsg)
+ ace_yymsg = "Deleting";
+ ACE_YY_SYMBOL_PRINT (ace_yymsg, ace_yytype, ace_yyvaluep, ace_yylocationp);
+}
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef ACE_YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int ace_yyparse (void *ACE_YYPARSE_PARAM);
+# else
+int ace_yyparse ();
+# endif
+#else /* ! ACE_YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int ace_yyparse (void);
+#else
+int ace_yyparse ();
+#endif
+#endif /* ! ACE_YYPARSE_PARAM */
+
+
+/*----------.
+| ace_yyparse. |
+`----------*/
+
+#ifdef ACE_YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int ace_yyparse (void *ACE_YYPARSE_PARAM)
+# else
+int ace_yyparse (ACE_YYPARSE_PARAM)
+ void *ACE_YYPARSE_PARAM;
+# endif
+#else /* ! ACE_YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+ace_yyparse (void)
+#else
+int
+ace_yyparse ()
+
+#endif
+#endif
+{
+ /* The look-ahead symbol. */
+int ace_yychar;
+
+/* The semantic value of the look-ahead symbol. */
+ACE_YYSTYPE ace_yylval;
+
+#if defined (ACE_YYSTYPE_IS_TRIVIAL)
+ ace_yylval = 0;
+#else
+ ace_yylval.type_ = 0;
+#endif /* ACE_YYSTYPE_IS_TRIVIAL */
+
+/* Number of syntax errors so far. */
+int ace_yynerrs;
+
+ register int ace_yystate;
+ register int ace_yyn;
+ int ace_yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int ace_yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int ace_yytoken = 0;
+
+ /* Three stacks and their tools:
+ `ace_yyss': related to states,
+ `ace_yyvs': related to semantic values,
+ `ace_yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow ace_yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short int ace_yyssa[ACE_YYINITDEPTH];
+ short int *ace_yyss = ace_yyssa;
+ register short int *ace_yyssp;
+
+ /* The semantic value stack. */
+ ACE_YYSTYPE ace_yyvsa[ACE_YYINITDEPTH];
+ ACE_YYSTYPE *ace_yyvs = ace_yyvsa;
+ register ACE_YYSTYPE *ace_yyvsp;
+
+
+
+#define ACE_YYPOPSTACK (ace_yyvsp--, ace_yyssp--)
+
+ ACE_YYSIZE_T ace_yystacksize = ACE_YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ ACE_YYSTYPE ace_yyval;
+
+
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
+ int ace_yylen;
+
+ ACE_YYDPRINTF ((stderr, "Starting parse\n"));
+
+ ace_yystate = 0;
+ ace_yyerrstatus = 0;
+ ace_yynerrs = 0;
+ ace_yychar = ACE_YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ ace_yyssp = ace_yyss;
+ ace_yyvsp = ace_yyvs;
+
+
+ ace_yyvsp[0] = ace_yylval;
+
+ goto ace_yysetstate;
+
+/*------------------------------------------------------------.
+| ace_yynewstate -- Push a new state, which is found in ace_yystate. |
+`------------------------------------------------------------*/
+ ace_yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ ace_yyssp++;
+
+ ace_yysetstate:
+ *ace_yyssp = ace_yystate;
+
+ if (ace_yyss + ace_yystacksize - 1 <= ace_yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ ACE_YYSIZE_T ace_yysize = ace_yyssp - ace_yyss + 1;
+
+#ifdef ace_yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ ACE_YYSTYPE *ace_yyvs1 = ace_yyvs;
+ short int *ace_yyss1 = ace_yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if ace_yyoverflow is a macro. */
+ ace_yyoverflow ("parser stack overflow",
+ &ace_yyss1, ace_yysize * sizeof (*ace_yyssp),
+ &ace_yyvs1, ace_yysize * sizeof (*ace_yyvsp),
+
+ &ace_yystacksize);
+
+ ace_yyss = ace_yyss1;
+ ace_yyvs = ace_yyvs1;
+ }
+#else /* no ace_yyoverflow */
+# ifndef ACE_YYSTACK_RELOCATE
+ goto ace_yyoverflowlab;
+# else
+ /* Extend the stack our own way. */
+ if (ACE_YYMAXDEPTH <= ace_yystacksize)
+ goto ace_yyoverflowlab;
+ ace_yystacksize *= 2;
+ if (ACE_YYMAXDEPTH < ace_yystacksize)
+ ace_yystacksize = ACE_YYMAXDEPTH;
+
+ {
+ short int *ace_yyss1 = ace_yyss;
+ union ace_yyalloc *ace_yyptr =
+ (union ace_yyalloc *) ACE_YYSTACK_ALLOC (ACE_YYSTACK_BYTES (ace_yystacksize));
+ if (! ace_yyptr)
+ goto ace_yyoverflowlab;
+ ACE_YYSTACK_RELOCATE (ace_yyss);
+ ACE_YYSTACK_RELOCATE (ace_yyvs);
+
+# undef ACE_YYSTACK_RELOCATE
+ if (ace_yyss1 != ace_yyssa)
+ ACE_YYSTACK_FREE (ace_yyss1);
+ }
+# endif
+#endif /* no ace_yyoverflow */
+
+ ace_yyssp = ace_yyss + ace_yysize - 1;
+ ace_yyvsp = ace_yyvs + ace_yysize - 1;
+
+
+ ACE_YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) ace_yystacksize));
+
+ if (ace_yyss + ace_yystacksize - 1 <= ace_yyssp)
+ ACE_YYABORT;
+ }
+
+ ACE_YYDPRINTF ((stderr, "Entering state %d\n", ace_yystate));
+
+ goto ace_yybackup;
+
+/*-----------.
+| ace_yybackup. |
+`-----------*/
+ace_yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a look-ahead token if we need one and don't already have one. */
+/* ace_yyresume: */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+
+ ace_yyn = ace_yypact[ace_yystate];
+ if (ace_yyn == ACE_YYPACT_NINF)
+ goto ace_yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* ACE_YYCHAR is either ACE_YYEMPTY or ACE_YYEOF or a valid look-ahead symbol. */
+ if (ace_yychar == ACE_YYEMPTY)
+ {
+ ACE_YYDPRINTF ((stderr, "Reading a token: "));
+ ace_yychar = ACE_YYLEX;
+ }
+
+ if (ace_yychar <= ACE_YYEOF)
+ {
+ ace_yychar = ace_yytoken = ACE_YYEOF;
+ ACE_YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ ace_yytoken = ACE_YYTRANSLATE (ace_yychar);
+ ACE_YY_SYMBOL_PRINT ("Next token is", ace_yytoken, &ace_yylval, &ace_yylloc);
+ }
+
+ /* If the proper action on seeing token ACE_YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ ace_yyn += ace_yytoken;
+ if (ace_yyn < 0 || ACE_YYLAST < ace_yyn || ace_yycheck[ace_yyn] != ace_yytoken)
+ goto ace_yydefault;
+ ace_yyn = ace_yytable[ace_yyn];
+ if (ace_yyn <= 0)
+ {
+ if (ace_yyn == 0 || ace_yyn == ACE_YYTABLE_NINF)
+ goto ace_yyerrlab;
+ ace_yyn = -ace_yyn;
+ goto ace_yyreduce;
+ }
+
+ if (ace_yyn == ACE_YYFINAL)
+ ACE_YYACCEPT;
+
+ /* Shift the look-ahead token. */
+ ACE_YY_SYMBOL_PRINT ("Shifting", ace_yytoken, &ace_yylval, &ace_yylloc);
+
+ /* Discard the token being shifted unless it is eof. */
+ if (ace_yychar != ACE_YYEOF)
+ ace_yychar = ACE_YYEMPTY;
+
+ *++ace_yyvsp = ace_yylval;
+
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (ace_yyerrstatus)
+ ace_yyerrstatus--;
+
+ ace_yystate = ace_yyn;
+ goto ace_yynewstate;
+
+
+/*-----------------------------------------------------------.
+| ace_yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+ace_yydefault:
+ ace_yyn = ace_yydefact[ace_yystate];
+ if (ace_yyn == 0)
+ goto ace_yyerrlab;
+ goto ace_yyreduce;
+
+
+/*-----------------------------.
+| ace_yyreduce -- Do a reduction. |
+`-----------------------------*/
+ace_yyreduce:
+ /* ace_yyn is the number of a rule to reduce with. */
+ ace_yylen = ace_yyr2[ace_yyn];
+
+ /* If ACE_YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets ACE_YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to ACE_YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that ACE_YYVAL may be used uninitialized. */
+ ace_yyval = ace_yyvsp[1-ace_yylen];
+
+
+ ACE_YY_REDUCE_PRINT (ace_yyn);
+ switch (ace_yyn)
+ {
+ case 2:
+
+ {
+ if ((ace_yyvsp[0].parse_node_) != 0)
+ {
+ (ace_yyvsp[0].parse_node_)->apply (ACE_SVC_CONF_PARAM->config, ACE_SVC_CONF_PARAM->yyerrno);
+ delete (ace_yyvsp[0].parse_node_);
+ }
+ ACE_SVC_CONF_PARAM->obstack.release ();
+ ;}
+ break;
+
+ case 3:
+
+ {
+ ACE_SVC_CONF_PARAM->obstack.release ();
+ ;}
+ break;
+
+ case 11:
+
+ {
+ if ((ace_yyvsp[-1].svc_record_) != 0)
+ (ace_yyval.parse_node_) = new ACE_Dynamic_Node ((ace_yyvsp[-1].svc_record_), (ace_yyvsp[0].ident_));
+ else
+ (ace_yyval.parse_node_) = 0;
+ ;}
+ break;
+
+ case 12:
+
+ {
+ (ace_yyval.parse_node_) = new ACE_Static_Node ((ace_yyvsp[-1].ident_), (ace_yyvsp[0].ident_));
+ ;}
+ break;
+
+ case 13:
+
+ {
+ (ace_yyval.parse_node_) = new ACE_Suspend_Node ((ace_yyvsp[0].ident_));
+ ;}
+ break;
+
+ case 14:
+
+ {
+ (ace_yyval.parse_node_) = new ACE_Resume_Node ((ace_yyvsp[0].ident_));
+ ;}
+ break;
+
+ case 15:
+
+ {
+ (ace_yyval.parse_node_) = new ACE_Remove_Node ((ace_yyvsp[0].ident_));
+ ;}
+ break;
+
+ case 16:
+
+ {
+ (ace_yyval.parse_node_) = new ACE_Stream_Node ((ace_yyvsp[-1].static_node_), (ace_yyvsp[0].parse_node_));
+ ;}
+ break;
+
+ case 17:
+
+ { (ace_yyval.static_node_) = new ACE_Static_Node ((ace_yyvsp[0].ident_)); ;}
+ break;
+
+ case 18:
+
+ {
+ (ace_yyval.parse_node_) = new ACE_Dummy_Node ((ace_yyvsp[-1].static_node_), (ace_yyvsp[0].parse_node_));
+ ;}
+ break;
+
+ case 19:
+
+ {
+ ;}
+ break;
+
+ case 20:
+
+ {
+ ;}
+ break;
+
+ case 21:
+
+ {
+ // Initialize left context...
+ (ace_yyval.static_node_) = (ace_yyvsp[-1].static_node_);
+ ;}
+ break;
+
+ case 22:
+
+ {
+ (ace_yyval.parse_node_) = (ace_yyvsp[-1].parse_node_);
+ ;}
+ break;
+
+ case 23:
+
+ { (ace_yyval.parse_node_) = 0; ;}
+ break;
+
+ case 24:
+
+ {
+ if ((ace_yyvsp[0].parse_node_) != 0)
+ {
+ (ace_yyvsp[0].parse_node_)->link ((ace_yyvsp[-1].parse_node_));
+ (ace_yyval.parse_node_) = (ace_yyvsp[0].parse_node_);
+ }
+ ;}
+ break;
+
+ case 25:
+
+ { (ace_yyval.parse_node_) = 0; ;}
+ break;
+
+ case 26:
+
+ {
+ ACE_Static_Node *svc_type = (ace_yyvsp[0].static_node_);
+
+ if (svc_type != 0)
+ {
+ ACE_Static_Node *module = (ace_yyvsp[-2].static_node_);
+
+ ACE_ARGV args (svc_type->parameters ());
+ ACE_Module_Type *mt = ace_get_module (module->record (ACE_SVC_CONF_PARAM->config),
+ svc_type->record (ACE_SVC_CONF_PARAM->config),
+ ACE_SVC_CONF_PARAM->yyerrno);
+ ACE_Stream_Type *st =
+ dynamic_cast<ACE_Stream_Type *> (const_cast<ACE_Service_Type_Impl *> (module->record (ACE_SVC_CONF_PARAM->config)->type ()));
+
+ if (!st
+ || !mt
+ || mt->init (args.argc (), args.argv ()) == -1
+ || st->push (mt) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("dynamic initialization failed for Module %s\n"),
+ svc_type->name ()));
+ ACE_SVC_CONF_PARAM->yyerrno++;
+ }
+ }
+ ;}
+ break;
+
+ case 27:
+
+ {
+ ACE_Static_Node *sn = (ace_yyvsp[-2].static_node_);
+ ACE_Module_Type *mt = ace_get_module (sn->record (ACE_SVC_CONF_PARAM->config),
+ (ace_yyvsp[0].static_node_)->name (),
+ ACE_SVC_CONF_PARAM->yyerrno);
+
+ if (((ACE_Stream_Type *) sn->record (ACE_SVC_CONF_PARAM->config)->type ())->push (mt) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Problem with static\n")));
+ ACE_SVC_CONF_PARAM->yyerrno++;
+ }
+ ;}
+ break;
+
+ case 28:
+
+ {
+ ACE_Static_Node *sn = (ace_yyvsp[-2].static_node_);
+ ACE_Module_Type *mt = ace_get_module (sn->record (ACE_SVC_CONF_PARAM->config),
+ sn->name (),
+ ACE_SVC_CONF_PARAM->yyerrno);
+ if (mt != 0)
+ mt->suspend ();
+ ;}
+ break;
+
+ case 29:
+
+ {
+ ACE_Static_Node *sn = (ace_yyvsp[-2].static_node_);
+ ACE_Module_Type *mt = ace_get_module (sn->record (ACE_SVC_CONF_PARAM->config),
+ (ace_yyvsp[0].static_node_)->name (),
+ ACE_SVC_CONF_PARAM->yyerrno);
+ if (mt != 0)
+ mt->resume ();
+ ;}
+ break;
+
+ case 30:
+
+ {
+ ACE_Static_Node *stream = (ace_yyvsp[-2].static_node_);
+ ACE_Static_Node *module = (ace_yyvsp[0].static_node_);
+ ACE_Module_Type *mt = ace_get_module (stream->record (ACE_SVC_CONF_PARAM->config),
+ module->name (),
+ ACE_SVC_CONF_PARAM->yyerrno);
+
+ ACE_Stream_Type *st =
+ dynamic_cast<ACE_Stream_Type *> (const_cast<ACE_Service_Type_Impl *> (stream->record (ACE_SVC_CONF_PARAM->config)->type ()));
+ if (!st || (mt != 0 && st->remove (mt) == -1))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("cannot remove Module_Type %s from STREAM_Type %s\n"),
+ module->name (),
+ stream->name ()));
+ ACE_SVC_CONF_PARAM->yyerrno++;
+ }
+ ;}
+ break;
+
+ case 31:
+
+ {
+ (ace_yyval.svc_record_) = new ACE_Service_Type_Factory ((ace_yyvsp[-3].ident_), (ace_yyvsp[-2].type_), (ace_yyvsp[-1].location_node_), (ace_yyvsp[0].type_));
+ ;}
+ break;
+
+ case 32:
+
+ {
+ (ace_yyval.type_) = 1;
+ ;}
+ break;
+
+ case 33:
+
+ {
+ (ace_yyval.type_) = 0;
+ ;}
+ break;
+
+ case 34:
+
+ {
+ (ace_yyval.type_) = 1;
+ ;}
+ break;
+
+ case 35:
+
+ {
+ (ace_yyval.location_node_) = new ACE_Object_Node ((ace_yyvsp[-2].ident_), (ace_yyvsp[0].ident_));
+ ;}
+ break;
+
+ case 36:
+
+ {
+ (ace_yyval.location_node_) = new ACE_Function_Node ((ace_yyvsp[-4].ident_), (ace_yyvsp[-2].ident_));
+ ;}
+ break;
+
+ case 37:
+
+ {
+ (ace_yyval.location_node_) = new ACE_Static_Function_Node ((ace_yyvsp[-2].ident_));
+ ;}
+ break;
+
+ case 38:
+
+ {
+ (ace_yyval.type_) = ACE_MODULE_T;
+ ;}
+ break;
+
+ case 39:
+
+ {
+ (ace_yyval.type_) = ACE_SVC_OBJ_T;
+ ;}
+ break;
+
+ case 40:
+
+ {
+ (ace_yyval.type_) = ACE_STREAM_T;
+ ;}
+ break;
+
+ case 42:
+
+ { (ace_yyval.ident_) = 0; ;}
+ break;
+
+
+ }
+
+/* Line 1037 of yacc.c. */
+
+
+ ace_yyvsp -= ace_yylen;
+ ace_yyssp -= ace_yylen;
+
+
+ ACE_YY_STACK_PRINT (ace_yyss, ace_yyssp);
+
+ *++ace_yyvsp = ace_yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ ace_yyn = ace_yyr1[ace_yyn];
+
+ ace_yystate = ace_yypgoto[ace_yyn - ACE_YYNTOKENS] + *ace_yyssp;
+ if (0 <= ace_yystate && ace_yystate <= ACE_YYLAST && ace_yycheck[ace_yystate] == *ace_yyssp)
+ ace_yystate = ace_yytable[ace_yystate];
+ else
+ ace_yystate = ace_yydefgoto[ace_yyn - ACE_YYNTOKENS];
+
+ goto ace_yynewstate;
+
+
+/*------------------------------------.
+| ace_yyerrlab -- here on detecting error |
+`------------------------------------*/
+ace_yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!ace_yyerrstatus)
+ {
+ ++ace_yynerrs;
+#if ACE_YYERROR_VERBOSE
+ ace_yyn = ace_yypact[ace_yystate];
+
+ if (ACE_YYPACT_NINF < ace_yyn && ace_yyn < ACE_YYLAST)
+ {
+ ACE_YYSIZE_T ace_yysize = 0;
+ int ace_yytype = ACE_YYTRANSLATE (ace_yychar);
+ const char* ace_yyprefix;
+ char *ace_yymsg;
+ int ace_yyx;
+
+ /* Start ACE_YYX at -ACE_YYN if negative to avoid negative indexes in
+ ACE_YYCHECK. */
+ int ace_yyxbegin = ace_yyn < 0 ? -ace_yyn : 0;
+
+ /* Stay within bounds of both ace_yycheck and ace_yytname. */
+ int ace_yychecklim = ACE_YYLAST - ace_yyn;
+ int ace_yyxend = ace_yychecklim < ACE_YYNTOKENS ? ace_yychecklim : ACE_YYNTOKENS;
+ int ace_yycount = 0;
+
+ ace_yyprefix = ", expecting ";
+ for (ace_yyx = ace_yyxbegin; ace_yyx < ace_yyxend; ++ace_yyx)
+ if (ace_yycheck[ace_yyx + ace_yyn] == ace_yyx && ace_yyx != ACE_YYTERROR)
+ {
+ ace_yysize += ace_yystrlen (ace_yyprefix) + ace_yystrlen (ace_yytname [ace_yyx]);
+ ace_yycount += 1;
+ if (ace_yycount == 5)
+ {
+ ace_yysize = 0;
+ break;
+ }
+ }
+ ace_yysize += (sizeof ("syntax error, unexpected ")
+ + ace_yystrlen (ace_yytname[ace_yytype]));
+ ace_yymsg = (ACE_TCHAR *) ACE_YYSTACK_ALLOC (ace_yysize);
+ if (ace_yymsg != 0)
+ {
+ char *ace_yyp = ace_yystpcpy (ace_yymsg, "syntax error, unexpected ");
+ ace_yyp = ace_yystpcpy (ace_yyp, ace_yytname[ace_yytype]);
+
+ if (ace_yycount < 5)
+ {
+ ace_yyprefix = ", expecting ";
+ for (ace_yyx = ace_yyxbegin; ace_yyx < ace_yyxend; ++ace_yyx)
+ if (ace_yycheck[ace_yyx + ace_yyn] == ace_yyx && ace_yyx != ACE_YYTERROR)
+ {
+ ace_yyp = ace_yystpcpy (ace_yyp, ace_yyprefix);
+ ace_yyp = ace_yystpcpy (ace_yyp, ace_yytname[ace_yyx]);
+ ace_yyprefix = " or ";
+ }
+ }
+ ace_yyerror (ACE_SVC_CONF_PARAM->yyerrno, ACE_SVC_CONF_PARAM->yylineno, ace_yymsg);
+ ACE_YYSTACK_FREE (ace_yymsg);
+ }
+ else
+ ace_yyerror (ACE_SVC_CONF_PARAM->yyerrno, ACE_SVC_CONF_PARAM->yylineno, "syntax error; also virtual memory exhausted");
+ }
+ else
+#endif /* ACE_YYERROR_VERBOSE */
+ ace_yyerror (ACE_SVC_CONF_PARAM->yyerrno, ACE_SVC_CONF_PARAM->yylineno, "syntax error");
+ }
+
+
+
+ if (ace_yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (ace_yychar <= ACE_YYEOF)
+ {
+ /* If at end of input, pop the error token,
+ then the rest of the stack, then return failure. */
+ if (ace_yychar == ACE_YYEOF)
+ for (;;)
+ {
+
+ ACE_YYPOPSTACK;
+ if (ace_yyssp == ace_yyss)
+ ACE_YYABORT;
+ ace_yydestruct ("Error: popping",
+ ace_yystos[*ace_yyssp], ace_yyvsp);
+ }
+ }
+ else
+ {
+ ace_yydestruct ("Error: discarding", ace_yytoken, &ace_yylval);
+ ace_yychar = ACE_YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto ace_yyerrlab1;
+
+
+/*---------------------------------------------------.
+| ace_yyerrorlab -- error raised explicitly by ACE_YYERROR. |
+`---------------------------------------------------*/
+ace_yyerrorlab:
+
+#if defined (__GNUC__) || defined (ACE_WIN32) || defined (__HP_aCC) || defined (__DECCXX)
+ /* Pacify GCC when the user code never invokes ACE_YYERROR and the label
+ ace_yyerrorlab therefore never appears in user code. */
+ if (0)
+ goto ace_yyerrorlab;
+#endif
+
+ace_yyvsp -= ace_yylen;
+ ace_yyssp -= ace_yylen;
+ ace_yystate = *ace_yyssp;
+ goto ace_yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| ace_yyerrlab1 -- common code for both syntax error and ACE_YYERROR. |
+`-------------------------------------------------------------*/
+ace_yyerrlab1:
+ ace_yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ ace_yyn = ace_yypact[ace_yystate];
+ if (ace_yyn != ACE_YYPACT_NINF)
+ {
+ ace_yyn += ACE_YYTERROR;
+ if (0 <= ace_yyn && ace_yyn <= ACE_YYLAST && ace_yycheck[ace_yyn] == ACE_YYTERROR)
+ {
+ ace_yyn = ace_yytable[ace_yyn];
+ if (0 < ace_yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (ace_yyssp == ace_yyss)
+ ACE_YYABORT;
+
+
+ ace_yydestruct ("Error: popping", ace_yystos[ace_yystate], ace_yyvsp);
+ ACE_YYPOPSTACK;
+ ace_yystate = *ace_yyssp;
+ ACE_YY_STACK_PRINT (ace_yyss, ace_yyssp);
+ }
+
+ if (ace_yyn == ACE_YYFINAL)
+ ACE_YYACCEPT;
+
+ *++ace_yyvsp = ace_yylval;
+
+
+ /* Shift the error token. */
+ ACE_YY_SYMBOL_PRINT ("Shifting", ace_yystos[ace_yyn], ace_yyvsp, ace_yylsp);
+
+ ace_yystate = ace_yyn;
+ goto ace_yynewstate;
+
+
+/*-------------------------------------.
+| ace_yyacceptlab -- ACE_YYACCEPT comes here. |
+`-------------------------------------*/
+ace_yyacceptlab:
+ ace_yyresult = 0;
+ goto ace_yyreturn;
+
+/*-----------------------------------.
+| ace_yyabortlab -- ACE_YYABORT comes here. |
+`-----------------------------------*/
+ace_yyabortlab:
+ ace_yydestruct ("Error: discarding lookahead",
+ ace_yytoken, &ace_yylval);
+ ace_yychar = ACE_YYEMPTY;
+ ace_yyresult = 1;
+ goto ace_yyreturn;
+
+#ifndef ace_yyoverflow
+/*----------------------------------------------.
+| ace_yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+ace_yyoverflowlab:
+ ace_yyerror (ACE_SVC_CONF_PARAM->yyerrno, ACE_SVC_CONF_PARAM->yylineno, "parser stack overflow");
+ ace_yyresult = 2;
+ /* Fall through. */
+#endif
+
+ace_yyreturn:
+#ifndef ace_yyoverflow
+ if (ace_yyss != ace_yyssa)
+ ACE_YYSTACK_FREE (ace_yyss);
+#endif
+ return ace_yyresult;
+}
+
+// Prints the error string to standard output. Cleans up the error
+// messages.
+
+void
+ace_yyerror (int ace_yyerrno, int ace_yylineno, char const *s)
+{
+#if defined (ACE_NLOGGING)
+ ACE_UNUSED_ARG (ace_yyerrno);
+ ACE_UNUSED_ARG (ace_yylineno);
+ ACE_UNUSED_ARG (s);
+#endif /* ACE_NLOGGING */
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE (%P|%t) [error %d] on line %d: %s\n"),
+ ace_yyerrno,
+ ace_yylineno,
+ ACE_TEXT_CHAR_TO_TCHAR (s)));
+}
+
+// Note that SRC_REC represents left context, which is the STREAM *
+// record.
+
+static ACE_Module_Type *
+ace_get_module (ACE_Service_Type const * sr,
+ ACE_TCHAR const * svc_name,
+ int & ace_yyerrno)
+{
+ ACE_Service_Type_Impl const * const type = sr->type ();
+ ACE_Stream_Type const * const st =
+ (sr == 0
+ ? 0
+ : dynamic_cast<ACE_Stream_Type const *> (type));
+ ACE_Module_Type const * const mt = (st == 0 ? 0 : st->find (svc_name));
+
+ if (sr == 0 || st == 0 || mt == 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("cannot locate Module_Type %s ")
+ ACE_TEXT ("in STREAM_Type %s\n"),
+ svc_name,
+ (sr ? sr->name () : ACE_TEXT ("(nil)"))));
+ ++ace_yyerrno;
+ }
+
+ return const_cast<ACE_Module_Type *> (mt);
+}
+
+static ACE_Module_Type *
+ace_get_module (ACE_Service_Type const * sr,
+ ACE_Service_Type const * sv,
+ int & ace_yyerrno)
+{
+ ACE_Stream_Type const * const st =
+ (sr == 0
+ ? 0
+ : static_cast<ACE_Stream_Type const *> (sr->type ()));
+
+ ACE_Module_Type const * const mt =
+ static_cast <ACE_Module_Type const *> (sv->type ());
+
+ ACE_TCHAR const * const module_type_name =
+ (mt ? mt->name () : ACE_TEXT ("(nil)"));
+
+ if (sr == 0 || st == 0 || mt == 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("cannot locate Module_Type %s or STREAM_Type %s\n"),
+ module_type_name,
+ (sr ? sr->name () : ACE_TEXT ("(nil)"))));
+ ++ace_yyerrno;
+ }
+
+ // Make sure that the Module has the same name as the
+ // Module_Type object from the svc.conf file.
+ ACE_Module<ACE_SYNCH> * const mp =
+ static_cast<ACE_Module<ACE_SYNCH> *> (mt ? mt->object () : 0);
+
+ if (mp && ACE_OS::strcmp (mp->name (), module_type_name) != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("warning: assigning Module_Type name %s to Module %s since names differ\n"),
+ module_type_name,
+ mp->name ()));
+ mp->name (module_type_name);
+ }
+
+ return const_cast<ACE_Module_Type *> (mt);
+}
+
+#if defined (SVC_CONF_Y_DEBUGGING)
+// Main driver program.
+
+int
+ACE_TMAIN(int argc, ACE_TCHAR *argv[])
+{
+ ACE_Svc_Conf_Param param (0, stdin);
+
+ // Try to reopen any filename argument to use ACE_YYIN.
+ if (argc > 1 && (ace_yyin = freopen (argv[1], "r", stdin)) == 0)
+ (void) ACE_OS::fprintf (stderr, ACE_TEXT ("usage: %s [file]\n"), argv[0]), ACE_OS::exit (1);
+
+ return ::ace_yyparse (&param);
+}
+#endif /* SVC_CONF_Y_DEBUGGING */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
diff --git a/ACE/ace/Svc_Handler.cpp b/ACE/ace/Svc_Handler.cpp
new file mode 100644
index 00000000000..7941c34238c
--- /dev/null
+++ b/ACE/ace/Svc_Handler.cpp
@@ -0,0 +1,525 @@
+// $Id$
+
+#ifndef ACE_SVC_HANDLER_CPP
+#define ACE_SVC_HANDLER_CPP
+
+#include "ace/Svc_Handler.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Object_Manager.h"
+#include "ace/Connection_Recycling_Strategy.h"
+
+#include "ace/Dynamic.h"
+
+#define PR_ST_1 ACE_PEER_STREAM_1
+#define PR_ST_2 ACE_PEER_STREAM_2
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <PR_ST_1, ACE_SYNCH_DECL> void *
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator new (size_t, void *p)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator new (NOOP, 2 parameters)");
+ return p;
+}
+
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator delete (void *, void *)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator delete (NOOP, 2 parameters)");
+ return;
+}
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+
+template <PR_ST_1, ACE_SYNCH_DECL> void *
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator new (size_t n)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator new");
+
+ ACE_Dynamic *const dynamic_instance = ACE_Dynamic::instance ();
+
+ if (dynamic_instance == 0)
+ {
+ // If this ACE_ASSERT fails, it may be due to running of out TSS
+ // keys. Try using ACE_HAS_TSS_EMULATION, or increasing
+ // ACE_DEFAULT_THREAD_KEYS if already using TSS emulation.
+ ACE_ASSERT (dynamic_instance != 0);
+
+ ACE_throw_bad_alloc;
+ }
+ else
+ {
+ // Allocate the memory and store it (usually in thread-specific
+ // storage, depending on config flags).
+ dynamic_instance->set ();
+
+ return ::new char[n];
+ }
+}
+
+#if defined (ACE_HAS_NEW_NOTHROW)
+template <PR_ST_1, ACE_SYNCH_DECL> void *
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator new (size_t n,
+ const ACE_nothrow_t&) throw()
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator new(nothrow)");
+
+ ACE_Dynamic *const dynamic_instance = ACE_Dynamic::instance ();
+
+ if (dynamic_instance == 0)
+ {
+ // If this ACE_ASSERT fails, it may be due to running of out TSS
+ // keys. Try using ACE_HAS_TSS_EMULATION, or increasing
+ // ACE_DEFAULT_THREAD_KEYS if already using TSS emulation.
+ ACE_ASSERT (dynamic_instance != 0);
+
+ return 0;
+ }
+ else
+ {
+ // Allocate the memory and store it (usually in thread-specific
+ // storage, depending on config flags).
+ dynamic_instance->set ();
+
+ return ::new(ACE_nothrow) char[n];
+ }
+}
+
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator delete (void *p,
+ const ACE_nothrow_t&) throw()
+{
+ ACE_TRACE
+ ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator delete(nothrow)");
+ ::delete [] static_cast <char *> (p);
+}
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+
+#endif /* ACE_HAS_NEW_NOTHROW */
+
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::destroy (void)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::destroy");
+
+ // Only delete ourselves if we're not owned by a module and have
+ // been allocated dynamically.
+ if (this->mod_ == 0 && this->dynamic_ && this->closing_ == false)
+ // Will call the destructor, which automatically calls <shutdown>.
+ // Note that if we are *not* allocated dynamically then the
+ // destructor will call <shutdown> automatically when it gets run
+ // during cleanup.
+ delete this;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator delete (void *obj)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::operator delete");
+ // You cannot delete a 'void*' (X3J16/95-0087 5.3.5.3), but we know
+ // the pointer was created using new char[] (see operator new code),
+ // so we use a cast:
+ ::delete [] static_cast <char *> (obj);
+}
+
+// Default constructor.
+
+template <PR_ST_1, ACE_SYNCH_DECL>
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::ACE_Svc_Handler (ACE_Thread_Manager *tm,
+ ACE_Message_Queue<ACE_SYNCH_USE> *mq,
+ ACE_Reactor *reactor)
+ : ACE_Task<ACE_SYNCH_USE> (tm, mq),
+ closing_ (false),
+ recycler_ (0),
+ recycling_act_ (0)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::ACE_Svc_Handler");
+
+ this->reactor (reactor);
+
+ // This clever idiom transparently checks if we were allocated
+ // dynamically. This information is used by the <destroy> method to
+ // decide if we need to delete <this>... The idiom is based on a
+ // paper by Michael van Rooyen (mrooyen@cellnet.co.uk) that appeared
+ // in the April '96 issue of the C++ Report. We've spruced it up to
+ // work correctly in multi-threaded programs by using our ACE_TSS
+ // class.
+ this->dynamic_ = ACE_Dynamic::instance ()->is_dynamic ();
+
+ if (this->dynamic_)
+ // Make sure to reset the flag.
+ ACE_Dynamic::instance ()->reset ();
+}
+
+// Default behavior for a ACE_Svc_Handler object is to be registered
+// with the ACE_Reactor (thereby ensuring single threading).
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::open (void *)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::open");
+#if defined (ACE_DEBUGGING)
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_PEER_STREAM_ADDR client_addr;
+
+ if (this->peer_.get_remote_addr (client_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_remote_addr")),
+ -1);
+ else if (client_addr.addr_to_string (buf, sizeof buf) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("can't obtain peer's address")),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("connected to %s on fd %d\n"),
+ buf,
+ this->peer_.get_handle ()));
+#endif /* ACE_DEBUGGING */
+ if (this->reactor ()
+ && this->reactor ()->register_handler
+ (this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("unable to register client handler")),
+ -1);
+ return 0;
+}
+
+// Perform termination activities.
+
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::shutdown (void)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::shutdown");
+
+ // Deregister this handler with the ACE_Reactor.
+ if (this->reactor ())
+ {
+ ACE_Reactor_Mask mask = ACE_Event_Handler::ALL_EVENTS_MASK |
+ ACE_Event_Handler::DONT_CALL;
+
+ // Make sure there are no timers.
+ this->reactor ()->cancel_timer (this);
+
+ if (this->peer ().get_handle () != ACE_INVALID_HANDLE)
+ // Remove self from reactor.
+ this->reactor ()->remove_handler (this, mask);
+ }
+
+ // Remove self from the recycler.
+ if (this->recycler ())
+ this->recycler ()->purge (this->recycling_act_);
+
+ this->peer ().close ();
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::cleanup_hint (void **act_holder)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::cleanup_hint");
+
+ // Remove as hint.
+ if (this->recycler ())
+ this->recycler ()->cleanup_hint (this->recycling_act_,
+ act_holder);
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::dump");
+
+ this->peer_.dump ();
+ ACE_DEBUG ((LM_DEBUG,
+ "dynamic_ = %d\n",
+ this->dynamic_));
+ ACE_DEBUG ((LM_DEBUG,
+ "closing_ = %d\n",
+ this->closing_));
+ ACE_DEBUG ((LM_DEBUG,
+ "recycler_ = %d\n",
+ this->recycler_));
+ ACE_DEBUG ((LM_DEBUG,
+ "recycling_act_ = %d\n",
+ this->recycling_act_));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> ACE_PEER_STREAM &
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::peer (void) const
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::peer");
+ return (ACE_PEER_STREAM &) this->peer_;
+}
+
+// Extract the underlying I/O descriptor.
+
+template <PR_ST_1, ACE_SYNCH_DECL> ACE_HANDLE
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::get_handle");
+ return this->peer_.get_handle ();
+}
+
+// Set the underlying I/O descriptor.
+
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::set_handle (ACE_HANDLE h)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::set_handle");
+ this->peer_.set_handle (h);
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL>
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::~ACE_Svc_Handler (void)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::~ACE_Svc_Handler");
+
+ if (this->closing_ == false)
+ {
+ // 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_ = true;
+
+ this->shutdown ();
+ }
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::handle_close");
+
+ this->destroy ();
+
+ return 0;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::handle_timeout");
+ return this->handle_close ();
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::close (u_long)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::close");
+ return this->handle_close ();
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::init (int /* argc */,
+ ACE_TCHAR * /* argv */[])
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::init");
+ return -1;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::fini (void)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::fini");
+ return -1;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::info (ACE_TCHAR **, size_t) const
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::info");
+ return -1;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::idle (u_long flags)
+{
+ if (this->recycler ())
+ return this->recycler ()->cache (this->recycling_act_);
+ else
+ return this->close (flags);
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycle_state (ACE_Recyclable_State new_state)
+{
+ if (this->recycler ())
+ return this->recycler ()->recycle_state (this->recycling_act_,
+ new_state);
+
+ return 0;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> ACE_Recyclable_State
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycle_state (void) const
+{
+ if (this->recycler ())
+ return this->recycler ()->recycle_state (this->recycling_act_);
+
+ return ACE_RECYCLABLE_UNKNOWN;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycler (ACE_Connection_Recycling_Strategy *recycler,
+ const void *recycling_act)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycler");
+ this->recycler_ = recycler;
+ this->recycling_act_ = recycling_act;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> ACE_Connection_Recycling_Strategy *
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycler (void) const
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycler");
+ return this->recycler_;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> const void *
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycling_act (void) const
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycling_act");
+ return this->recycling_act_;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycle (void *)
+{
+ ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::recycle");
+ // By default, the object is ready and willing to be recycled.
+ return 0;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL>
+ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::~ACE_Buffered_Svc_Handler (void)
+{
+ this->flush ();
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL>
+ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::ACE_Buffered_Svc_Handler (ACE_Thread_Manager *tm,
+ ACE_Message_Queue<ACE_SYNCH_USE> *mq,
+ ACE_Reactor *reactor,
+ size_t maximum_buffer_size,
+ ACE_Time_Value *timeout)
+ : ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE> (tm, mq, reactor),
+ maximum_buffer_size_ (maximum_buffer_size),
+ current_buffer_size_ (0),
+ timeoutp_ (timeout)
+{
+ ACE_TRACE ("ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::ACE_Buffered_Svc_Handler");
+
+ if (this->timeoutp_ != 0)
+ {
+ this->interval_ = *timeout;
+ this->next_timeout_ = ACE_OS::gettimeofday () + this->interval_;
+ }
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv)
+{
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, m, this->msg_queue ()->lock (), -1);
+
+ // Enqueue <mb> onto the message queue.
+ if (this->putq (mb, tv) == -1)
+ return -1;
+ else
+ {
+ // Update the current number of bytes on the queue.
+ this->current_buffer_size_ += mb->total_size ();
+
+ // Flush the buffer when the number of bytes exceeds the maximum
+ // buffer size or when the timeout period has elapsed.
+ if (this->current_buffer_size_ >= this->maximum_buffer_size_
+ || (this->timeoutp_ != 0
+ && this->next_timeout_ <= ACE_OS::gettimeofday ()))
+ return this->flush_i ();
+ else
+ return 0;
+ }
+}
+
+// Flush the buffer.
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::flush (void)
+{
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, m, this->msg_queue ()->lock (), -1);
+
+ return this->flush_i ();
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::flush_i (void)
+{
+ ACE_Message_Queue_Iterator<ACE_SYNCH_USE> iterator (*this->msg_queue ());
+ ACE_Message_Block *mblk = 0;
+ ssize_t result = 0;
+
+ // Get the first <ACE_Message_Block> so that we can write everything
+ // out via the <send_n>.
+ if (iterator.next (mblk) != 0)
+ result = this->peer ().send_n (mblk);
+
+ // This method assumes the caller holds the queue's lock!
+ if (result != -1)
+ this->msg_queue ()->flush_i ();
+
+ if (this->timeoutp_ != 0)
+ // Update the next timeout period by adding the interval.
+ this->next_timeout_ += this->interval_;
+
+ this->current_buffer_size_ = 0;
+
+ return result;
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> void
+ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::dump");
+
+ ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::dump ();
+ ACE_DEBUG ((LM_DEBUG,
+ "maximum_buffer_size_ = %d\n",
+ this->maximum_buffer_size_));
+ ACE_DEBUG ((LM_DEBUG,
+ "current_buffer_size_ = %d\n",
+ this->current_buffer_size_));
+ if (this->timeoutp_ != 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "next_timeout_.sec = %d, next_timeout_.usec = %d\n",
+ this->next_timeout_.sec (),
+ this->next_timeout_.usec ()));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <PR_ST_1, ACE_SYNCH_DECL> int
+ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ ACE_TRACE ("ACE_Buffered_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::handle_timeout");
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#undef PR_ST_1
+#undef PR_ST_2
+#endif /* ACE_SVC_HANDLER_CPP */
diff --git a/ACE/ace/Svc_Handler.h b/ACE/ace/Svc_Handler.h
new file mode 100644
index 00000000000..c366a30b2f7
--- /dev/null
+++ b/ACE/ace/Svc_Handler.h
@@ -0,0 +1,339 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Svc_Handler.h
+ *
+ * $Id$
+ *
+ * @author Douglas Schmidt <schmidt@uci.edu>
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SVC_HANDLER_H
+#define ACE_SVC_HANDLER_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Synch_Options.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Task.h"
+#include "ace/Recyclable.h"
+#include "ace/Reactor.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls.
+class ACE_Connection_Recycling_Strategy;
+
+/**
+ * @class ACE_Svc_Handler
+ *
+ * @brief Defines the interface for a service that exchanges data with
+ * its connected peer.
+ *
+ * This class provides a well-defined interface that the
+ * Acceptor and Connector pattern factories use as their target.
+ * Typically, client applications will subclass ACE_Svc_Handler
+ * and do all the interesting work in the subclass. One thing
+ * that the ACE_Svc_Handler does contain is a PEER_STREAM
+ * endpoint that is initialized by an ACE_Acceptor or
+ * ACE_Connector when a connection is established successfully.
+ * This endpoint is used to exchange data between a
+ * ACE_Svc_Handler and the peer it is connected with.
+ */
+template <ACE_PEER_STREAM_1, ACE_SYNCH_DECL>
+class ACE_Svc_Handler : public ACE_Task<ACE_SYNCH_USE>
+{
+public:
+
+ // Useful STL-style traits.
+ typedef ACE_PEER_STREAM_ADDR addr_type;
+ typedef ACE_PEER_STREAM stream_type;
+
+ /**
+ * Constructor initializes the @a thr_mgr and @a mq by passing them
+ * down to the ACE_Task base class. The @a reactor is passed to
+ * the ACE_Event_Handler.
+ */
+ ACE_Svc_Handler (ACE_Thread_Manager *thr_mgr = 0,
+ ACE_Message_Queue<ACE_SYNCH_USE> *mq = 0,
+ ACE_Reactor *reactor = ACE_Reactor::instance ());
+
+ /// Destructor.
+ virtual ~ACE_Svc_Handler (void);
+
+ /// Activate the client handler. This is typically called by the
+ /// ACE_Acceptor or ACE_Connector.
+ virtual int open (void * = 0);
+
+ /**
+ * Object termination hook -- application-specific cleanup code goes
+ * here. This function is called by the idle() function if the object
+ * does not have a ACE_Connection_Recycling_Strategy associated with it.
+ * Also, due to this class's derivation from ACE_Task, close() is
+ * also called when a thread activated with this object exits. See
+ * ACE_Task::close() for further details. The default action of this
+ * function is to call handle_close() with the default arguments.
+ */
+ virtual int close (u_long flags = 0);
+
+ /**
+ * Call this method if you want to recycling the @c Svc_Handler
+ * instead of closing it. If the object does not have a recycler,
+ * it will be closed.
+ */
+ virtual int idle (u_long flags = 0);
+
+ /**
+ * Call this method if you want to get/set the state of the
+ * @c Svc_Handler. If the object does not have a recycler, this call
+ * will have no effect (and the accessor will return
+ * ACE_RECYCLABLE_UNKNOWN).
+ */
+ virtual ACE_Recyclable_State recycle_state (void) const;
+ virtual int recycle_state (ACE_Recyclable_State new_state);
+
+ /**
+ * When the svc_handle is no longer needed around as a hint, call
+ * this method. In addition, reset @c *act_holder to zero if
+ * @a act_holder != 0.
+ */
+ virtual void cleanup_hint (void **act_holder = 0);
+
+ // = 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 does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+
+ // = Demultiplexing hooks.
+
+ /**
+ * Perform termination activities on the SVC_HANDLER. The default
+ * behavior is to close down the <peer_> (to avoid descriptor leaks)
+ * and to <destroy> this object (to avoid memory leaks)! If you
+ * don't want this behavior make sure you override this method...
+ */
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ /// Default behavior when timeouts occur is to close down the
+ /// <Svc_Handler> by calling <handle_close>.
+ virtual int handle_timeout (const ACE_Time_Value &time,
+ const void *);
+
+ /// Get the underlying handle associated with the <peer_>.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Set the underlying handle associated with the <peer_>.
+ virtual void set_handle (ACE_HANDLE);
+
+ /// Returns the underlying PEER_STREAM. Used by
+ /// <ACE_Acceptor::accept> and <ACE_Connector::connect> factories
+ ACE_PEER_STREAM &peer (void) const;
+
+ /// Overloaded new operator. This method unobtrusively records if a
+ /// <Svc_Handler> is allocated dynamically, which allows it to clean
+ /// itself up correctly whether or not it's allocated statically or
+ /// dynamically.
+ void *operator new (size_t n);
+
+#if defined (ACE_HAS_NEW_NOTHROW)
+ /// Overloaded new operator, nothrow_t variant. Unobtrusively records if a
+ /// <Svc_Handler> is allocated dynamically, which allows it to clean
+ /// itself up correctly whether or not it's allocated statically or
+ /// dynamically.
+ void *operator new (size_t n, const ACE_nothrow_t&) throw();
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+ void operator delete (void *p, const ACE_nothrow_t&) throw ();
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+#endif
+
+ /// This operator permits "placement new" on a per-object basis.
+ void * operator new (size_t n, void *p);
+
+ /**
+ * Call this to free up dynamically allocated <Svc_Handlers>
+ * (otherwise you will get memory leaks). In general, you should
+ * call this method rather than <delete> since this method knows
+ * whether or not the object was allocated dynamically, and can act
+ * accordingly (i.e., deleting it if it was allocated dynamically).
+ */
+ virtual void destroy (void);
+
+ /**
+ * This really should be private so that users are forced to call
+ * <destroy>. Unfortunately, the C++ standard doesn't allow there
+ * to be a public new and a private delete. It is a bad idea to
+ * call this method directly, so use <destroy> instead, unless you
+ * know for sure that you've allocated the object dynamically.
+ */
+ void operator delete (void *);
+
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+ /**
+ * This operator is necessary to complement the class-specific
+ * operator new above. Unfortunately, it's not portable to all C++
+ * compilers...
+ */
+ void operator delete (void *, void *);
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+
+ /// Close down the descriptor and unregister from the Reactor
+ void shutdown (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+public:
+
+ // = The following methods are not suppose to be public.
+
+ // Because friendship is *not* inherited in C++, these methods have
+ // to be public.
+
+ // = Accessors to set/get the connection recycler.
+
+ /// Set the recycler and the @a recycling_act that is used during
+ /// purging and caching.
+ virtual void recycler (ACE_Connection_Recycling_Strategy *recycler,
+ const void *recycling_act);
+
+ /// Get the recycler.
+ virtual ACE_Connection_Recycling_Strategy *recycler (void) const;
+
+ /// Get the recycling act.
+ virtual const void *recycling_act (void) const;
+
+ /**
+ * Upcall made by the recycler when it is about to recycle the
+ * connection. This gives the object a chance to prepare itself for
+ * recycling. Return 0 if the object is ready for recycling, -1 on
+ * failures.
+ */
+ virtual int recycle (void * = 0);
+
+protected:
+ /// Maintain connection with client.
+ ACE_PEER_STREAM peer_;
+
+ /// Have we been dynamically created?
+ bool dynamic_;
+
+ /// Keeps track of whether we are in the process of closing (required
+ /// to avoid circular calls to <handle_close>).
+ bool closing_;
+
+ /// Pointer to the connection recycler.
+ ACE_Connection_Recycling_Strategy *recycler_;
+
+ /// Asynchronous Completion Token (ACT) to be used to when talking to
+ /// the recycler.
+ const void *recycling_act_;
+};
+
+/**
+ * @class ACE_Buffered_Svc_Handler
+ *
+ * @brief Defines the interface for a service that exchanges data with
+ * its connected peer and supports buffering.
+ *
+ * The buffering feature makes it possible to queue up
+ * ACE_Message_Blocks in an ACE_Message_Queue until (1) the
+ * queue is "full" or (2) a period of time elapses, at which
+ * point the queue is "flushed" via <sendv_n> to the peer.
+ */
+template <ACE_PEER_STREAM_1, ACE_SYNCH_DECL>
+class ACE_Buffered_Svc_Handler : public ACE_Svc_Handler<ACE_PEER_STREAM_2, ACE_SYNCH_USE>
+{
+public:
+ // = Initialization and termination methods.
+ /**
+ * Constructor initializes the @a thr_mgr and @a mq by passing them
+ * down to the ACE_Task base class. The @a reactor is passed to
+ * the ACE_Event_Handler. The @a max_buffer_size and
+ * @a relative_timeout are used to determine at what point to flush
+ * the @a mq. By default, there's no buffering at all. The
+ * @a relative_timeout value is interpreted to be in a unit that's
+ * relative to the current time returned by <ACE_OS::gettimeofday>.
+ */
+ ACE_Buffered_Svc_Handler (ACE_Thread_Manager *thr_mgr = 0,
+ ACE_Message_Queue<ACE_SYNCH_USE> *mq = 0,
+ ACE_Reactor *reactor = ACE_Reactor::instance (),
+ size_t max_buffer_size = 0,
+ ACE_Time_Value *relative_timeout = 0);
+
+ /// Destructor, which calls <flush>.
+ virtual ~ACE_Buffered_Svc_Handler (void);
+
+ /**
+ * Insert the ACE_Message_Block chain rooted at @a message_block
+ * into the ACE_Message_Queue with the designated @a timeout. The
+ * <flush> method will be called if this <put> causes the number of
+ * bytes to exceed the maximum buffer size or if the timeout period
+ * has elapsed.
+ */
+ virtual int put (ACE_Message_Block *message_block,
+ ACE_Time_Value *timeout = 0);
+
+ /// Flush the ACE_Message_Queue, which writes all the queued
+ /// ACE_Message_Blocks to the <PEER_STREAM>.
+ virtual int flush (void);
+
+ /// This method is not currently implemented -- this is where the
+ /// integration with the <Reactor> would occur.
+ virtual int handle_timeout (const ACE_Time_Value &time,
+ const void *);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+protected:
+ /// Implement the flush operation on the ACE_Message_Queue, which
+ /// writes all the queued ACE_Message_Blocks to the <PEER_STREAM>.
+ /// Assumes that the caller holds the lock.
+ virtual int flush_i (void);
+
+ /// Maximum size the <Message_Queue> can be before we have to flush
+ /// the buffer.
+ size_t maximum_buffer_size_;
+
+ /// Current size in bytes of the <Message_Queue> contents.
+ size_t current_buffer_size_;
+
+ /// Timeout value used to control when the buffer is flushed.
+ ACE_Time_Value next_timeout_;
+
+ /// Interval of the timeout.
+ ACE_Time_Value interval_;
+
+ /// Timeout pointer.
+ ACE_Time_Value *timeoutp_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Svc_Handler.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Svc_Handler.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SVC_HANDLER_H */
diff --git a/ACE/ace/Synch.h b/ACE/ace/Synch.h
new file mode 100644
index 00000000000..8a8b98dd342
--- /dev/null
+++ b/ACE/ace/Synch.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Synch.h
+ *
+ * $Id$
+ *
+ * Wrapper Facades for various synchronization mechanisms.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_SYNCH_H
+#define ACE_SYNCH_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 (DO_NOT_INCLUDE_SYNCH_H)
+
+/* All the classes have been moved out into their own headers as part of
+ the compile-time and footprint reduction effort. */
+
+#include "ace/Auto_Event.h"
+#include "ace/Barrier.h"
+#include "ace/Condition_Thread_Mutex.h"
+#include "ace/Condition_Recursive_Thread_Mutex.h"
+#include "ace/Event.h"
+#include "ace/Lock.h"
+#include "ace/Manual_Event.h"
+#include "ace/Mutex.h"
+#include "ace/Null_Barrier.h"
+#include "ace/Null_Condition.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Null_Semaphore.h"
+#include "ace/RW_Mutex.h"
+#include "ace/RW_Thread_Mutex.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Semaphore.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Thread_Semaphore.h"
+#include "ace/TSS_Adapter.h"
+
+// Include the templates here.
+// FUZZ: disable check_for_synch_include
+#include "ace/Synch_T.h"
+
+#if defined (ACE_LEGACY_MODE)
+# include "ace/File_Lock.h"
+# include "ace/Process_Semaphore.h"
+# include "ace/Process_Mutex.h"
+# include "ace/RW_Process_Mutex.h"
+# include "ace/Test_and_Set.h"
+#endif /* ACE_LEGACY_MODE */
+
+#endif /* DO_NOT_INCLUDE_SYNCH_H */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SYNCH_H */
diff --git a/ACE/ace/Synch_Options.cpp b/ACE/ace/Synch_Options.cpp
new file mode 100644
index 00000000000..07bfb8debc0
--- /dev/null
+++ b/ACE/ace/Synch_Options.cpp
@@ -0,0 +1,110 @@
+#include "ace/Synch_Options.h"
+
+#include "ace/Global_Macros.h"
+#include "ace/config-all.h"
+
+ACE_RCSID (ace,
+ Synch_Options,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Synch_Options)
+
+void
+ACE_Synch_Options::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Synch_Options::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+// Static initialization.
+// Note: these three objects require static construction and destruction.
+
+/* static */
+ACE_Synch_Options ACE_Synch_Options::defaults;
+
+/* static */
+ACE_Synch_Options ACE_Synch_Options::synch;
+
+/* static */
+ACE_Synch_Options ACE_Synch_Options::asynch (ACE_Synch_Options::USE_REACTOR);
+
+ACE_Synch_Options::ACE_Synch_Options (unsigned long options,
+ const ACE_Time_Value &timeout,
+ const void *arg)
+{
+ // ACE_TRACE ("ACE_Synch_Options::ACE_Synch_Options");
+ this->set (options, timeout, arg);
+}
+
+void
+ACE_Synch_Options::set (unsigned long options,
+ const ACE_Time_Value &timeout,
+ const void *arg)
+{
+ // ACE_TRACE ("ACE_Synch_Options::set");
+ this->options_ = options;
+ this->timeout_ = timeout;
+
+ // Whoa, possible dependence on static initialization here. This
+ // function is called during initialization of the statics above.
+ // But, ACE_Time_Value::zero is a static object. Very fortunately,
+ // its bits have a value of 0.
+ if (this->timeout_ != ACE_Time_Value::zero)
+ ACE_SET_BITS (this->options_, ACE_Synch_Options::USE_TIMEOUT);
+
+ this->arg_ = arg;
+}
+
+bool
+ACE_Synch_Options::operator[] (unsigned long option) const
+{
+ ACE_TRACE ("ACE_Synch_Options::operator[]");
+ return (this->options_ & option) != 0;
+}
+
+void
+ACE_Synch_Options::operator= (unsigned long option)
+{
+ ACE_TRACE ("ACE_Synch_Options::operator=");
+ this->options_ |= option;
+}
+
+const ACE_Time_Value &
+ACE_Synch_Options::timeout (void) const
+{
+ ACE_TRACE ("ACE_Synch_Options::timeout");
+ return this->timeout_;
+}
+
+void
+ACE_Synch_Options::timeout (const ACE_Time_Value &tv)
+{
+ ACE_TRACE ("ACE_Synch_Options::timeout");
+ this->timeout_ = tv;
+}
+
+const ACE_Time_Value *
+ACE_Synch_Options::time_value (void) const
+{
+ ACE_TRACE ("ACE_Synch_Options::time_value");
+ return (*this)[USE_TIMEOUT] ? &this->timeout_ : 0;
+}
+
+const void *
+ACE_Synch_Options::arg (void) const
+{
+ ACE_TRACE ("ACE_Synch_Options::arg");
+ return this->arg_;
+}
+
+void
+ACE_Synch_Options::arg (const void *a)
+{
+ ACE_TRACE ("ACE_Synch_Options::arg");
+ this->arg_ = a;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Synch_Options.h b/ACE/ace/Synch_Options.h
new file mode 100644
index 00000000000..308991cd9e8
--- /dev/null
+++ b/ACE/ace/Synch_Options.h
@@ -0,0 +1,163 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Synch_Options.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@uci.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_SYNCH_OPTIONS_H
+#define ACE_SYNCH_OPTIONS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Synch_Options
+ *
+ * @brief Contains the values of options used to determine the
+ * synchronous and asynchronous behavior.
+ *
+ * The supported set of options is depicted in the following table.
+ * The Reactor column indicates whether or not the USE_REACTOR option is
+ * supplied.
+ * The Timeout column specifies the period of time specified by the object;
+ * Unused implies that USE_TIMEOUT is not included in the options and the
+ * default timeout value, ACE_Time_Value::zero, is specified, either
+ * explicitly or by default.
+ *
+ * <TABLE>
+ * <TR><TD align="center"><B>Reactor</B></TD><TD align="center"><B>Timeout</B></TD><TD><B>Behavior</B></TD></TR>
+ * <TR><TD>yes</TD><TD>Unused</TD><TD>Infinite timeout (using Reactor);
+ * this is the default.</TD></TR>
+ * <TR><TD>yes</TD><TD>time</TD><TD>Try asynch transaction for the
+ * specified time (using Reactor)</TD></TR>
+ * <TR><TD>yes</TD><TD>0,0</TD><TD>Poll; try, if EWOULDBLOCK, return
+ * immediately (using Reactor)</TD></TR>
+ * <TR><TD>no</TD><TD>Unused</TD><TD>Block until completion (don't use Reactor)</TD></TR>
+ * <TR><TD>no</TD><TD>time</TD><TD>Wait up to specified amount of time for
+ * completion (don't use Reactor)</TD></TR>
+ * <TR><TD>no</TD><TD>0,0</TD><TD>Poll and return immediately</TD></TR>
+ * </TABLE>
+ */
+class ACE_Export ACE_Synch_Options
+{
+public:
+ /// Options flags for controlling synchronization.
+ /**
+ * Note that these flags can be bit-wise "or'd" together if both
+ * options are desired.
+ */
+ enum
+ {
+ /// Use the Reactor.
+ USE_REACTOR = 01,
+ /// Use the supplied timeout value.
+ USE_TIMEOUT = 02
+ };
+
+ /**
+ * Initialize the object to default values unless specified otherwise.
+ *
+ * @param options Specifies the options to use; default is neither option
+ * (no reactor, no timeout).
+ * @param timeout Specifies the period of time to use for the operation's
+ * timeout. The default is ACE_Time_Value::zero, noted as
+ * 0,0 in the behavior options table. If a non-zero timeout
+ * is specified, the USE_TIMEOUT option is added to
+ * @a options.
+ * To use a zero timeout, USE_TIMEOUT must be explicitly
+ * specified in @a options.
+ * @param arg A completion tag that can be passed through the options;
+ * the class using ACE_Synch_Options can access this.
+ * ACE_Synch_Options makes no use of it internally.
+ */
+ ACE_Synch_Options (unsigned long options = 0,
+ const ACE_Time_Value &timeout = ACE_Time_Value::zero,
+ const void *arg = 0);
+
+ /// Initialize the object; arguments are the same as for the
+ /// constructor.
+ void set (unsigned long options = 0,
+ const ACE_Time_Value &timeout = ACE_Time_Value::zero,
+ const void *arg = 0);
+
+ /// Returns true if the specified option(s) are enabled, false otherwise.
+ bool operator[] (unsigned long option) const;
+
+ /// Adds the specified option(s) to the object; does not replace them.
+ void operator= (unsigned long option);
+
+ /// Returns the "magic cookie" argument.
+ const void *arg (void) const;
+
+ /// Set the "magic cookie" argument.
+ void arg (const void *);
+
+ /// Returns a reference to the ACE_Time_Value. This value only makes
+ /// sense if (*this)[USE_TIMEOUT] is true.
+ const ACE_Time_Value &timeout (void) const;
+
+ /// Set the timeout value. This method does not alter the options; in
+ /// particular, it doesn't add USE_TIMEOUT to the options when a non-zero
+ /// timeout is specified as the constructor and set() do.
+ void timeout (const ACE_Time_Value &tv);
+
+ /**
+ * Returns a timeout pointer if (*this)[USE_TIMEOUT] is true, else 0.
+ * This should be used with care, e.g., the timeout pointer should not
+ * be stored in a manner that will lead to dangling pointers.
+ */
+ const ACE_Time_Value *time_value (void) const;
+
+ // = Static data members (singletons)
+
+ /// This is the default setting for options, which will block
+ /// synchronously.
+ static ACE_Synch_Options defaults;
+
+ /// This is the default synchronous setting.
+ static ACE_Synch_Options synch;
+
+ /// This is the default asynchronous setting.
+ static ACE_Synch_Options asynch;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Keeps track of the enabled options.
+ unsigned long options_;
+
+ /// Amount of time to wait for timeouts.
+ ACE_Time_Value timeout_;
+
+ /**
+ * "Magic cookie" always passed in as an argument to the ACE_Reactor's
+ * schedule_timer() method. Used to communicate values for
+ * asynchronous programming.
+ */
+ const void *arg_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SYNCH_OPTIONS_H */
diff --git a/ACE/ace/Synch_T.cpp b/ACE/ace/Synch_T.cpp
new file mode 100644
index 00000000000..22ee08d4e0b
--- /dev/null
+++ b/ACE/ace/Synch_T.cpp
@@ -0,0 +1,22 @@
+// $Id$
+
+#ifndef ACE_SYNCH_T_CPP
+#define ACE_SYNCH_T_CPP
+
+#include "ace/Thread.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// FUZZ: disable check_for_synch_include
+#include "ace/Synch_T.h"
+#include "ace/Log_Msg.h"
+
+#include "ace/Lock_Adapter_T.cpp"
+#include "ace/Reverse_Lock_T.cpp"
+#include "ace/Guard_T.cpp"
+#include "ace/TSS_T.cpp"
+#include "ace/Condition_T.cpp"
+
+#endif /* ACE_SYNCH_T_CPP */
diff --git a/ACE/ace/Synch_T.h b/ACE/ace/Synch_T.h
new file mode 100644
index 00000000000..edd7c6ba77e
--- /dev/null
+++ b/ACE/ace/Synch_T.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Synch_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SYNCH_T_H
+#define ACE_SYNCH_T_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// FUZZ: disable check_for_synch_include
+#include "ace/Synch.h"
+
+#include "ace/Lock_Adapter_T.h"
+#include "ace/Reverse_Lock_T.h"
+#include "ace/Guard_T.h"
+#include "ace/TSS_T.h"
+#include "ace/Condition_T.h"
+#include "ace/Synch_Traits.h"
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Synch_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Synch_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SYNCH_T_H */
diff --git a/ACE/ace/Synch_Traits.h b/ACE/ace/Synch_Traits.h
new file mode 100644
index 00000000000..086e29b1e63
--- /dev/null
+++ b/ACE/ace/Synch_Traits.h
@@ -0,0 +1,152 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Synch_Traits.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_SYNCH_TRAITS_H
+#define ACE_SYNCH_TRAITS_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h" /* Need to know threads, template settings */
+#include "ace/Lock.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl
+class ACE_Null_Mutex;
+class ACE_Null_Condition;
+class ACE_Null_Semaphore;
+class ACE_Null_Mutex;
+class ACE_Thread_Mutex;
+class ACE_Process_Mutex;
+class ACE_Recursive_Thread_Mutex;
+class ACE_RW_Thread_Mutex;
+class ACE_Condition_Thread_Mutex;
+class ACE_Condition_Recursive_Thread_Mutex;
+class ACE_Thread_Semaphore;
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+
+/**
+ * @class ACE_NULL_SYNCH
+ *
+ * @brief Implement a do nothing Synchronization wrapper that
+ * typedefs the @c ACE_Condition and @c ACE_Mutex to the
+ * @c Null* versions.
+ */
+class ACE_Export ACE_NULL_SYNCH
+{
+public:
+ typedef ACE_Null_Mutex MUTEX;
+ typedef ACE_Null_Mutex NULL_MUTEX;
+ typedef ACE_Null_Mutex PROCESS_MUTEX;
+ typedef ACE_Null_Mutex RECURSIVE_MUTEX;
+ typedef ACE_Null_Mutex RW_MUTEX;
+ typedef ACE_Null_Condition CONDITION;
+ typedef ACE_Null_Condition RECURSIVE_CONDITION;
+ typedef ACE_Null_Semaphore SEMAPHORE;
+ typedef ACE_Null_Mutex NULL_SEMAPHORE;
+};
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Process_Mutex;
+class ACE_Condition_Recursive_Thread_Mutex;
+
+/**
+ * @class ACE_MT_SYNCH
+ *
+ * @brief Implement a default thread safe synchronization wrapper that
+ * typedefs the @c ACE_Condition and @c ACE_Mutex to the
+ * @c ACE_Condition and @c ACE_Mutex versions.
+ *
+ * @todo This should be a template, but SunC++ 4.0.1 complains about
+ * this.
+ */
+class ACE_Export ACE_MT_SYNCH
+{
+public:
+ typedef ACE_Thread_Mutex MUTEX;
+ typedef ACE_Null_Mutex NULL_MUTEX;
+ typedef ACE_Process_Mutex PROCESS_MUTEX;
+ typedef ACE_Recursive_Thread_Mutex RECURSIVE_MUTEX;
+ typedef ACE_RW_Thread_Mutex RW_MUTEX;
+ typedef ACE_Condition_Thread_Mutex CONDITION;
+ typedef ACE_Condition_Recursive_Thread_Mutex RECURSIVE_CONDITION;
+ typedef ACE_Thread_Semaphore SEMAPHORE;
+ typedef ACE_Null_Semaphore NULL_SEMAPHORE;
+};
+
+#endif /* ACE_HAS_THREADS */
+
+#define ACE_SYNCH_MUTEX ACE_SYNCH::MUTEX
+#define ACE_SYNCH_NULL_MUTEX ACE_SYNCH::NULL_MUTEX
+#define ACE_SYNCH_RECURSIVE_MUTEX ACE_SYNCH::RECURSIVE_MUTEX
+#define ACE_SYNCH_RW_MUTEX ACE_SYNCH::RW_MUTEX
+#define ACE_SYNCH_CONDITION ACE_SYNCH::CONDITION
+#define ACE_SYNCH_RECURSIVE_CONDITION ACE_SYNCH::RECURSIVE_CONDITION
+#define ACE_SYNCH_NULL_SEMAPHORE ACE_SYNCH::NULL_SEMAPHORE
+#define ACE_SYNCH_SEMAPHORE ACE_SYNCH::SEMAPHORE
+
+#else /* !ACE_HAS_TEMPLATE_TYPEDEFS */
+
+#if defined (ACE_HAS_OPTIMIZED_MESSAGE_QUEUE)
+#define ACE_NULL_SYNCH ACE_Null_Mutex, ACE_Null_Condition, ACE_Null_Mutex
+#define ACE_MT_SYNCH ACE_Thread_Mutex, ACE_Condition_Thread_Mutex, ACE_Thread_Semaphore
+#else
+#define ACE_NULL_SYNCH ACE_Null_Mutex, ACE_Null_Condition
+#define ACE_MT_SYNCH ACE_Thread_Mutex, ACE_Condition_Thread_Mutex
+#endif /* ACE_HAS_OPTIMIZED_MESSAGE_QUEUE */
+
+#if defined (ACE_HAS_THREADS)
+
+#define ACE_SYNCH_MUTEX ACE_Thread_Mutex
+#define ACE_SYNCH_NULL_MUTEX ACE_Null_Mutex
+#define ACE_SYNCH_RECURSIVE_MUTEX ACE_Recursive_Thread_Mutex
+#define ACE_SYNCH_RW_MUTEX ACE_RW_Thread_Mutex
+#define ACE_SYNCH_CONDITION ACE_Condition_Thread_Mutex
+#define ACE_SYNCH_RECURSIVE_CONDITION ACE_Condition_Recursive_Thread_Mutex
+#define ACE_SYNCH_SEMAPHORE ACE_Thread_Semaphore
+#define ACE_SYNCH_NULL_SEMAPHORE ACE_Null_Semaphore
+
+#else /* ACE_HAS_THREADS */
+
+#define ACE_SYNCH_MUTEX ACE_Null_Mutex
+#define ACE_SYNCH_NULL_MUTEX ACE_Null_Mutex
+#define ACE_SYNCH_RECURSIVE_MUTEX ACE_Null_Mutex
+#define ACE_SYNCH_RW_MUTEX ACE_Null_Mutex
+#define ACE_SYNCH_CONDITION ACE_Null_Condition
+#define ACE_SYNCH_RECURSIVE_CONDITION ACE_Null_Condition
+#define ACE_SYNCH_SEMAPHORE ACE_Null_Semaphore
+#define ACE_SYNCH_NULL_SEMAPHORE ACE_Null_Mutex
+
+#endif /* ACE_HAS_THREADS */
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+// These are available on *all* platforms
+#define ACE_SYNCH_PROCESS_SEMAPHORE ACE_Process_Semaphore
+#define ACE_SYNCH_PROCESS_MUTEX ACE_Process_Mutex
+
+#if defined (ACE_HAS_THREADS)
+#define ACE_SYNCH ACE_MT_SYNCH
+#else /* ACE_HAS_THREADS */
+#define ACE_SYNCH ACE_NULL_SYNCH
+#endif /* ACE_HAS_THREADS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SYNCH_TRAITS_H */
diff --git a/ACE/ace/System_Time.cpp b/ACE/ace/System_Time.cpp
new file mode 100644
index 00000000000..d1ae525b8d6
--- /dev/null
+++ b/ACE/ace/System_Time.cpp
@@ -0,0 +1,140 @@
+// $Id$
+
+#include "ace/System_Time.h"
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Malloc_T.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+
+ACE_RCSID(ace, System_Time, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_System_Time::ACE_System_Time (const ACE_TCHAR *poolname)
+ : shmem_ (0)
+ , delta_time_ (0)
+{
+ ACE_TRACE ("ACE_System_Time::ACE_System_Time");
+
+ // Only create a new unique filename for the memory pool file
+ // if the user didn't supply one...
+ if (poolname == 0)
+ {
+#if defined (ACE_DEFAULT_BACKING_STORE)
+ // Create a temporary file.
+ ACE_OS::strcpy (this->poolname_,
+ ACE_DEFAULT_BACKING_STORE);
+#else /* ACE_DEFAULT_BACKING_STORE */
+ if (ACE::get_temp_dir (this->poolname_,
+ MAXPATHLEN - 17) == -1)
+ // -17 for ace-malloc-XXXXXX
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Temporary path too long, ")
+ ACE_TEXT ("defaulting to current directory\n")));
+ this->poolname_[0] = 0;
+ }
+
+ // Add the filename to the end
+ ACE_OS::strcat (this->poolname_, ACE_TEXT ("ace-malloc-XXXXXX"));
+
+#endif /* ACE_DEFAULT_BACKING_STORE */
+ }
+ else
+ ACE_OS::strsncpy (this->poolname_,
+ poolname,
+ (sizeof this->poolname_ / sizeof (ACE_TCHAR)));
+
+ ACE_NEW (this->shmem_,
+ ALLOCATOR (this->poolname_));
+}
+
+ACE_System_Time::~ACE_System_Time (void)
+{
+ ACE_TRACE ("ACE_System_Time::~ACE_System_Time");
+ delete this->shmem_;
+}
+
+// Get the local system time.
+
+int
+ACE_System_Time::get_local_system_time (time_t & time_out)
+{
+ ACE_TRACE ("ACE_System_Time::get_local_system_time");
+ time_out = ACE_OS::time (0);
+ return 0;
+}
+
+int
+ACE_System_Time::get_local_system_time (ACE_Time_Value &time_out)
+{
+ ACE_TRACE ("ACE_System_Time::get_local_system_time");
+ time_out.set (ACE_OS::time (0), 0);
+ return 0;
+}
+
+// Get the system time of the central time server.
+
+int
+ACE_System_Time::get_master_system_time (time_t &time_out)
+{
+ ACE_TRACE ("ACE_System_Time::get_master_system_time");
+
+ if (this->delta_time_ == 0)
+ {
+ // Try to find it
+ void * temp;
+ if (this->shmem_->find (ACE_DEFAULT_TIME_SERVER_STR, temp) == -1)
+ {
+ // No time entry in shared memory (meaning no Clerk exists)
+ // so return the local time of the host.
+ return this->get_local_system_time (time_out);
+ }
+ else
+ // Extract the delta time.
+ this->delta_time_ = static_cast<long *> (temp);
+ }
+
+ time_t local_time;
+
+ // If delta_time is positive, it means that the system clock is
+ // ahead of our local clock so add delta to the local time to get an
+ // approximation of the system time. Else if delta time is negative,
+ // it means that our local clock is ahead of the system clock, so
+ // return the last local time stored (to avoid time conflicts).
+ if (*this->delta_time_ >= 0 )
+ {
+ this->get_local_system_time (local_time);
+ time_out = local_time + static_cast<ACE_UINT32> (*this->delta_time_);
+ }
+ else
+ // Return the last local time. Note that this is stored as the
+ // second field in shared memory.
+ time_out = *(this->delta_time_ + 1);
+ return 0;
+}
+
+int
+ACE_System_Time::get_master_system_time (ACE_Time_Value &time_out)
+{
+ ACE_TRACE ("ACE_System_Time::get_master_system_time");
+ time_t to;
+ if (this->get_master_system_time (to) == -1)
+ return -1;
+ time_out.sec (to);
+ return 0;
+}
+
+// Synchronize local system time with the central time server using
+// specified mode (currently unimplemented).
+
+int
+ACE_System_Time::sync_local_system_time (ACE_System_Time::Sync_Mode)
+{
+ ACE_TRACE ("ACE_System_Time::sync_local_system_time");
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/System_Time.h b/ACE/ace/System_Time.h
new file mode 100644
index 00000000000..e40b21299f5
--- /dev/null
+++ b/ACE/ace/System_Time.h
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file System_Time.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain
+ * @author Tim H. Harrison
+ * @author Douglas C. Schmidt
+ */
+//=============================================================================
+
+#ifndef ACE_SYSTEM_TIME_H
+#define ACE_SYSTEM_TIME_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/Global_Macros.h"
+#include "ace/os_include/os_time.h" /* For time_t. */
+#include "ace/os_include/os_limits.h" /* For MAXPATHLEN. */
+#include "ace/MMAP_Memory_Pool.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<ACE_MEM_POOL_1, class ACE_LOCK> class ACE_Malloc;
+template<class MALLOC> class ACE_Allocator_Adapter;
+
+class ACE_Null_Mutex;
+class ACE_Time_Value;
+class ACE_MMAP_Memory_Pool;
+
+/**
+ * @class ACE_System_Time
+ *
+ * @brief Defines the timer services of the OS interface to access the
+ * system time either on the local host or on the central time
+ * server in the network.
+ */
+class ACE_Export ACE_System_Time
+{
+public:
+ /**
+ * Enumeration types to specify mode of synchronization with master
+ * clock. Jump will set local system time directly (thus possibly
+ * producing time gaps or ambiguous local system times. Adjust will
+ * smoothly slow down or speed up the local system clock to reach
+ * the system time of the master clock.
+ */
+ enum Sync_Mode { Jump, Adjust };
+
+ /// Default constructor.
+ ACE_System_Time (const ACE_TCHAR *poolname = 0);
+
+ /// Default destructor.
+ ~ACE_System_Time (void);
+
+ /// Get the local system time, i.e., the value returned by
+ /// ACE_OS::time().
+ static int get_local_system_time (time_t & time_out);
+
+ /// Get the local system time, i.e., the value returned by
+ /// ACE_OS::time().
+ static int get_local_system_time (ACE_Time_Value &time_out);
+
+ /// Get the system time of the central time server.
+ int get_master_system_time (time_t & time_out);
+
+ /// Get the system time of the central time server.
+ int get_master_system_time (ACE_Time_Value &time_out);
+
+ /// Synchronize local system time with the central time server using
+ /// specified mode.
+ int sync_local_system_time (ACE_System_Time::Sync_Mode mode);
+
+private:
+ typedef ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_Null_Mutex> MALLOC;
+ typedef ACE_Allocator_Adapter<MALLOC> ALLOCATOR;
+
+ /// Our allocator (used for obtaining system time from shared memory).
+ ALLOCATOR * shmem_;
+
+ /// The name of the pool used by the allocator.
+ ACE_TCHAR poolname_[MAXPATHLEN + 1];
+
+ /// Pointer to delta time kept in shared memory.
+ long * delta_time_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SYSTEM_TIME_H */
diff --git a/ACE/ace/TLI.cpp b/ACE/ace/TLI.cpp
new file mode 100644
index 00000000000..7dde750931c
--- /dev/null
+++ b/ACE/ace/TLI.cpp
@@ -0,0 +1,273 @@
+// $Id$
+
+// Defines the member functions for the base class of the ACE_TLI
+// abstraction.
+
+#include "ace/TLI.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_TLI.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/Auto_Ptr.h"
+
+ACE_RCSID(ace, TLI, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TLI.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TLI)
+
+void
+ACE_TLI::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TLI::dump");
+#endif /* ACE_HAS_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_TLI::ACE_TLI")));
+}
+
+int
+ACE_TLI::get_local_addr (ACE_Addr &sa) const
+{
+ ACE_TRACE ("ACE_TLI::get_local_addr");
+ struct netbuf name;
+
+ name.maxlen = sa.get_size ();
+ name.buf = (char *) sa.get_addr ();
+
+ if (ACE_OS::t_getname (this->get_handle (), &name, LOCALNAME) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+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)
+{
+ /* Set up options for ACE_TLI */
+ ACE_TRACE ("ACE_TLI::set_option");
+
+#if defined (ACE_HAS_XTI)
+ // ret will get the negotiated option back after attempting to set it.
+ // Assume this will fit in the requested size.
+ struct t_optmgmt req, ret;
+ ACE_NEW_RETURN (req.opt.buf, char[sizeof (struct t_opthdr) + optlen], -1);
+# if (_XOPEN_SOURCE - 0 >= 500)
+ auto_ptr<char> req_opt_buf_p (reinterpret_cast<char*> (req.opt.buf));
+# else
+ ACE_Auto_Array_Ptr<char> req_opt_buf_p (req.opt.buf);
+# endif /* XPG5 vs XPG4 */
+ struct t_opthdr *opthdr =
+ reinterpret_cast<struct t_opthdr *> (req.opt.buf);
+ ACE_NEW_RETURN (ret.opt.buf, char[sizeof (struct t_opthdr) + optlen], -1);
+# if (_XOPEN_SOURCE - 0 >= 500)
+ auto_ptr<char> ret_opt_buf_p (reinterpret_cast<char*> (ret.opt.buf));
+# else
+ ACE_Auto_Array_Ptr<char> ret_opt_buf_p (ret.opt.buf);
+# endif /* XPG5 vs XPG4 */
+
+ req.flags = T_NEGOTIATE;
+ req.opt.len = sizeof *opthdr + optlen;
+ ret.opt.maxlen = req.opt.len;
+ opthdr->level = level;
+ opthdr->name = option;
+ opthdr->len = req.opt.len; // We only request one option at a time.
+ ACE_OS::memcpy (&opthdr[1], optval, optlen);
+ return ACE_OS::t_optmgmt (this->get_handle (), &req, &ret);
+
+#elif defined (ACE_HAS_SVR4_TLI)
+ struct opthdr *opthdr = 0; /* See <sys/socket.h> for info 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 = reinterpret_cast<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_XTI, else 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_XTI)
+ // ret will get the option requested in req.
+ struct t_optmgmt req, ret;
+ ACE_NEW_RETURN (req.opt.buf, char[sizeof (struct t_opthdr)], -1);
+# if (_XOPEN_SOURCE - 0 >= 500)
+ auto_ptr<char> req_opt_buf_p (reinterpret_cast<char*> (req.opt.buf));
+# else
+ ACE_Auto_Array_Ptr<char> req_opt_buf_p (req.opt.buf);
+# endif /* XPG5 vs XPG4 */
+ struct t_opthdr *opthdr =
+ reinterpret_cast<struct t_opthdr *> (req.opt.buf);
+ ACE_NEW_RETURN (ret.opt.buf, char[sizeof (struct t_opthdr) + optlen], -1);
+# if (_XOPEN_SOURCE - 0 >= 500)
+ auto_ptr<char> ret_opt_buf_p (reinterpret_cast<char*> (ret.opt.buf));
+# else
+ ACE_Auto_Array_Ptr<char> ret_opt_buf_p (ret.opt.buf);
+# endif /* XPG5 vs XPG4 */
+
+ req.flags = T_CURRENT;
+ req.opt.len = sizeof *opthdr;
+ ret.opt.maxlen = sizeof (struct t_opthdr) + optlen;
+ opthdr->level = level;
+ opthdr->name = option;
+ opthdr->len = sizeof (*opthdr); // Just the header on the request
+ if (ACE_OS::t_optmgmt (this->get_handle (), &req, &ret) == -1)
+ return -1;
+ else
+ {
+ opthdr = reinterpret_cast<struct t_opthdr *> (ret.opt.buf);
+ if (opthdr->status == T_NOTSUPPORT)
+ {
+ errno = ENOTSUP;
+ return -1;
+ }
+ else
+ {
+ ACE_OS::memcpy (optval, &opthdr[1], optlen);
+ return 0;
+ }
+ }
+
+#elif 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 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/ace/TLI.h b/ACE/ace/TLI.h
new file mode 100644
index 00000000000..20fcec2841a
--- /dev/null
+++ b/ACE/ace/TLI.h
@@ -0,0 +1,116 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file TLI.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_TLI_H
+#define ACE_TLI_H
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_TLI.h"
+
+#if defined (ACE_HAS_TLI)
+
+#include "ace/IPC_SAP.h"
+#include "ace/Addr.h"
+#include "ace/os_include/os_fcntl.h"
+
+// 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
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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.
+ ACE_TLI (void);
+
+ /// Destructor.
+ ~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)
+ // XTI/TLI option management.
+ struct t_optmgmt so_opt_req;
+ struct t_optmgmt so_opt_ret;
+#endif /* ACE_HAS_SVR4_TLI */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/TLI.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TLI */
+#include /**/ "ace/post.h"
+#endif /* ACE_TLI_H */
diff --git a/ACE/ace/TLI.inl b/ACE/ace/TLI.inl
new file mode 100644
index 00000000000..2485cdc5557
--- /dev/null
+++ b/ACE/ace/TLI.inl
@@ -0,0 +1,50 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/TLI.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 ());
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/TLI_Acceptor.cpp b/ACE/ace/TLI_Acceptor.cpp
new file mode 100644
index 00000000000..b6820c5db4e
--- /dev/null
+++ b/ACE/ace/TLI_Acceptor.cpp
@@ -0,0 +1,553 @@
+// $Id$
+
+#include "ace/TLI_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Memory.h"
+
+ACE_RCSID(ace, TLI_Acceptor, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TLI_Request_Queue::dump");
+#endif /* ACE_HAS_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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TLI_Acceptor::dump");
+#endif /* ACE_HAS_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");
+ ACE_HANDLE fd = ACE_OS::t_open ((char *) dev,
+ O_RDWR,
+ 0);
+
+ 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,
+ const_cast<char *> ("tirdwr"))
+ == ACE_INVALID_HANDLE)
+ fd = ACE_INVALID_HANDLE;
+#else
+ ACE_UNUSED_ARG(rwf);
+#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_TEXT ("%p\n"),
+ ACE_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/ace/TLI_Acceptor.h b/ACE/ace/TLI_Acceptor.h
new file mode 100644
index 00000000000..7a6577800ad
--- /dev/null
+++ b/ACE/ace/TLI_Acceptor.h
@@ -0,0 +1,123 @@
+// -*- 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/TLI_Stream.h"
+#include "ace/Default_Constants.h"
+
+#if defined (ACE_HAS_TLI)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward reference...
+class ACE_TLI_Request_Queue;
+class ACE_Time_Value;
+
+/**
+ * @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 @a timeout of 0 means
+ * block forever, a @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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TLI */
+#include /**/ "ace/post.h"
+#endif /* ACE_TLI_ACCEPTOR_H */
diff --git a/ACE/ace/TLI_Connector.cpp b/ACE/ace/TLI_Connector.cpp
new file mode 100644
index 00000000000..9a11d2c880b
--- /dev/null
+++ b/ACE/ace/TLI_Connector.cpp
@@ -0,0 +1,256 @@
+// $Id$
+
+#include "ace/TLI_Connector.h"
+
+ACE_RCSID(ace, TLI_Connector, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TLI_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Handle_Set.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Connector)
+
+void
+ACE_TLI_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TLI_Connector::dump");
+#endif /* ACE_HAS_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,
+ struct netbuf *udata,
+ struct 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,
+ 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_XTI) || defined (ACE_HAS_SVR4_TLI)
+ struct netbuf name;
+
+ name.maxlen = remote_sap->get_size ();
+ name.buf = (char *) remote_sap->get_addr ();
+
+ if (ACE_OS::t_getname (new_stream.get_handle (),
+ &name,
+ REMOTENAME) == -1)
+#else /* SunOS4 */
+ if (0)
+#endif /* ACE_HAS_XTI || 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 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/ace/TLI_Connector.h b/ACE/ace/TLI_Connector.h
new file mode 100644
index 00000000000..971b9c82b92
--- /dev/null
+++ b/ACE/ace/TLI_Connector.h
@@ -0,0 +1,130 @@
+// -*- 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)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a remote_sap is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a 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 @a remote_sap is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a 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 @a new_stream contains
+ * the connected ACE_SOCK_Stream. If @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/TLI_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TLI */
+#include /**/ "ace/post.h"
+#endif /* ACE_TLI_CONNECTOR_H */
diff --git a/ACE/ace/TLI_Connector.inl b/ACE/ace/TLI_Connector.inl
new file mode 100644
index 00000000000..8dc40b1eaa6
--- /dev/null
+++ b/ACE/ace/TLI_Connector.inl
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 rw_flag,
+ struct netbuf *udata,
+ struct 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,
+ rw_flag,
+ udata,
+ opt) == -1
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/TLI_Stream.cpp b/ACE/ace/TLI_Stream.cpp
new file mode 100644
index 00000000000..7b7e41fa42d
--- /dev/null
+++ b/ACE/ace/TLI_Stream.cpp
@@ -0,0 +1,229 @@
+// $Id$
+
+/* Defines the member functions for the base class of the ACE_TLI_Stream
+ abstraction. */
+
+#include "ace/TLI_Stream.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(ace, TLI_Stream, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TLI_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Stream)
+
+void
+ACE_TLI_Stream::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_TLI_Stream::dump");
+#endif /* ACE_HAS_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");
+
+ 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)
+ return -1;
+ else
+ return 0;
+}
+
+// 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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/ace/TLI_Stream.h b/ACE/ace/TLI_Stream.h
new file mode 100644
index 00000000000..fe54f76f30b
--- /dev/null
+++ b/ACE/ace/TLI_Stream.h
@@ -0,0 +1,141 @@
+// -*- 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/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/TLI.h"
+
+#include "ace/INET_Addr.h"
+
+#if defined (ACE_HAS_TLI)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @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)).
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Recv an n byte buffer from the connected socket (uses t_rcv(3)).
+ 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)).
+ ssize_t send_n (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Recv exactly n bytes from the connected socket (uses t_rcv(3)).
+ 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 rwflag
+ int get_rwflag (void) const;
+
+ /// Set rwflag
+ void set_rwflag (int value);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/TLI_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TLI */
+#include /**/ "ace/post.h"
+#endif /* ACE_TLI_STREAM_H */
diff --git a/ACE/ace/TLI_Stream.inl b/ACE/ace/TLI_Stream.inl
new file mode 100644
index 00000000000..8ef7265f8cd
--- /dev/null
+++ b/ACE/ace/TLI_Stream.inl
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/TLI_Stream.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::get_rwflag");
+ return this->rwflag_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/TP_Reactor.cpp b/ACE/ace/TP_Reactor.cpp
new file mode 100644
index 00000000000..4216fa3db15
--- /dev/null
+++ b/ACE/ace/TP_Reactor.cpp
@@ -0,0 +1,686 @@
+// $Id$
+
+#include "ace/TP_Reactor.h"
+#include "ace/Thread.h"
+#include "ace/Timer_Queue.h"
+#include "ace/Sig_Handler.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_time.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TP_Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ TP_Reactor,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE (ACE_TP_Reactor)
+
+int
+ACE_TP_Token_Guard::acquire_read_token (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_TP_Token_Guard::acquire_read_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));
+ }
+
+ // 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 ourselves 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 ());
+ }
+
+ // 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 ourselves as owner
+ this->owner_ = 1;
+
+ return result;
+}
+
+
+ACE_TP_Reactor::ACE_TP_Reactor (ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int mask_signals,
+ int s_queue)
+ : ACE_Select_Reactor (sh, tq, ACE_DISABLE_NOTIFY_PIPE_DEFAULT, 0, mask_signals, s_queue)
+{
+ ACE_TRACE ("ACE_TP_Reactor::ACE_TP_Reactor");
+ this->supress_notify_renew (1);
+}
+
+ACE_TP_Reactor::ACE_TP_Reactor (size_t max_number_of_handles,
+ int restart,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int mask_signals,
+ int s_queue)
+ : ACE_Select_Reactor (max_number_of_handles, restart, sh, tq, ACE_DISABLE_NOTIFY_PIPE_DEFAULT, 0, mask_signals, s_queue)
+{
+ 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 elapsed 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 const result = guard.acquire_read_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::dispatch_i (ACE_Time_Value *max_wait_time,
+ ACE_TP_Token_Guard &guard)
+{
+ int event_count = this->get_event_for_dispatching (max_wait_time);
+
+ // We use this count to detect potential infinite loops as described
+ // in bug 2540.
+ int const initial_event_count = event_count;
+
+ 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.
+
+#if 0
+ // @Ciju
+ // signal handling isn't in a production state yet.
+ // Commenting it out for now.
+
+ // 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);
+ }
+#endif // #if 0
+
+ // 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 just go 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
+ result = this->handle_socket_events (event_count, guard);
+ }
+
+ if (event_count != 0 && event_count == initial_event_count)
+ {
+ this->state_changed_ = true;
+ }
+
+ return result;
+}
+
+
+#if 0
+ // @Ciju
+ // signal handling isn't in a production state yet.
+ // Commenting it out for now.
+
+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;
+}
+#endif // #if 0
+
+
+int
+ACE_TP_Reactor::handle_timer_events (int & /*event_count*/,
+ ACE_TP_Token_Guard &guard)
+{
+ if (this->timer_queue_ == 0 || this->timer_queue_->is_empty())
+ { // Empty timer queue so cannot have any expired timers.
+ return 0;
+ }
+
+ // 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))
+ {
+ const void *upcall_act = 0;
+
+ // Preinvoke.
+ this->timer_queue_->preinvoke (info, cur_time, upcall_act);
+
+ // Release the token before dispatching notifies...
+ guard.release_token ();
+
+ // call the functor
+ this->timer_queue_->upcall (info, cur_time);
+
+ // Postinvoke
+ this->timer_queue_->postinvoke (info, cur_time, upcall_act);
+
+ // 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 some 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 I/O events.
+ 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 ())
+ {
+ // Check for removed handlers.
+ if (dispatch_info.event_handler_ == 0)
+ {
+ this->handler_rep_.unbind(dispatch_info.handle_,
+ dispatch_info.mask_);
+ }
+
+
+ return 0;
+ }
+
+ // Suspend the handler so that other threads don't start dispatching
+ // it, if we can't suspend then return directly
+ //
+ // 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_)
+ if (this->suspend_i (dispatch_info.handle_) == -1)
+ return 0;
+
+ // Call add_reference() if needed.
+ if (dispatch_info.reference_counting_required_)
+ dispatch_info.event_handler_->add_reference ();
+
+ // Release the lock. Others threads can start waiting.
+ guard.release_token ();
+
+ int result = 0;
+
+ // If there was an event handler ready, dispatch it.
+ // Decrement the event left
+ --event_count;
+
+ // Dispatched an event
+ if (this->dispatch_socket_event (dispatch_info) == 0)
+ ++result;
+
+ 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_ = false;
+ }
+ 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.
+
+ 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 ());
+ }
+
+ 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)
+{
+ // 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->clear_handle_read_set (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->clear_handle_read_set (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->clear_handle_read_set (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_Event_Handler * const event_handler = dispatch_info.event_handler_;
+ ACE_EH_PTMF const 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) (dispatch_info.handle_);
+
+ // Post process socket event
+ return this->post_process_socket_event (dispatch_info, status);
+}
+
+int
+ACE_TP_Reactor::post_process_socket_event (ACE_EH_Dispatch_Info &dispatch_info,
+ int status)
+{
+ int result = 0;
+
+ // First check if we really have to post process something, if not, then
+ // we don't acquire the token which saves us a lot of time.
+ if (status < 0 ||
+ (dispatch_info.event_handler_ != this->notify_handler_ &&
+ dispatch_info.resume_flag_ ==
+ ACE_Event_Handler::ACE_REACTOR_RESUMES_HANDLER))
+ {
+ // Get the reactor token and with this token acquired remove first the
+ // handler and resume it at the same time. This must be atomic, see also
+ // bugzilla 2395. When this is not atomic it can be that we resume the
+ // handle after it is reused by the OS.
+ ACE_TP_Token_Guard guard (this->token_);
+
+ result = guard.acquire_token ();
+
+ // If the guard is NOT the owner just return the retval
+ if (!guard.is_owner ())
+ return result;
+
+ // A different event handler may have been registered during the
+ // upcall if the handle was closed and then reopened, for
+ // example. Make sure we're removing and/or resuming the event
+ // handler used during the upcall.
+ ACE_Event_Handler const * const eh =
+ this->handler_rep_.find (dispatch_info.handle_);
+
+ // Only remove or resume the event handler used during the
+ // upcall.
+ if (eh == dispatch_info.event_handler_)
+ {
+ if (status < 0)
+ {
+ result =
+ this->remove_handler_i (dispatch_info.handle_,
+ dispatch_info.mask_);
+ }
+
+ // Resume handler if required.
+ if (dispatch_info.event_handler_ != this->notify_handler_ &&
+ dispatch_info.resume_flag_ ==
+ ACE_Event_Handler::ACE_REACTOR_RESUMES_HANDLER)
+ this->resume_i (dispatch_info.handle_);
+ }
+ }
+
+ // Call remove_reference() if needed.
+ if (dispatch_info.reference_counting_required_)
+ dispatch_info.event_handler_->remove_reference ();
+
+ return result;
+}
+
+int
+ACE_TP_Reactor::resumable_handler (void)
+{
+ return 1;
+}
+
+int
+ACE_TP_Reactor::handle_events (ACE_Time_Value &max_wait_time)
+{
+ return this->handle_events (&max_wait_time);
+}
+
+void
+ACE_TP_Reactor::notify_handle (ACE_HANDLE,
+ ACE_Reactor_Mask,
+ ACE_Handle_Set &,
+ ACE_Event_Handler *eh,
+ ACE_EH_PTMF)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_TP_Reactor::notify_handle: ")
+ ACE_TEXT ("Wrong version of notify_handle() got called \n")));
+
+ ACE_ASSERT (eh == 0);
+ ACE_UNUSED_ARG (eh);
+}
+
+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 const 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))
+ {
+ return read_handle;
+ }
+
+ // None found..
+ return ACE_INVALID_HANDLE;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/TP_Reactor.h b/ACE/ace/TP_Reactor.h
new file mode 100644
index 00000000000..d8bbf111dd2
--- /dev/null
+++ b/ACE/ace/TP_Reactor.h
@@ -0,0 +1,320 @@
+// -*- 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 create threads. The context switching cost
+ * will also reduce. Moreover, 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/Timer_Queue.h" /* Simple forward decl won't work... */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_EH_Dispatch_Info
+ *
+ * @brief This structure contains information of the activated event
+ * handler.
+ */
+class 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);
+
+ bool dispatch (void) const;
+
+ ACE_HANDLE handle_;
+ ACE_Event_Handler *event_handler_;
+ ACE_Reactor_Mask mask_;
+ ACE_EH_PTMF callback_;
+ int resume_flag_;
+ bool reference_counting_required_;
+
+private:
+ bool dispatch_;
+
+ // Disallow copying and assignment.
+ ACE_EH_Dispatch_Info (const ACE_EH_Dispatch_Info &);
+ 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_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.
+ bool is_owner (void);
+
+ /// A helper method that grabs the token for us, after which the
+ /// thread that owns that can do some actual work.
+ int acquire_read_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
+ * acquire_read_token() as it uses acquire () to get the token instead of
+ * acquire_read ()
+ */
+ int acquire_token (ACE_Time_Value *max_wait_time = 0);
+
+private:
+
+ // Disallow default construction.
+ ACE_TP_Token_Guard (void);
+
+ // Disallow copying and assignment.
+ ACE_TP_Token_Guard (const ACE_TP_Token_Guard &);
+ ACE_TP_Token_Guard &operator= (const ACE_TP_Token_Guard &);
+
+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 false indicates that this class
+ /// hasnt got the token (and hence the thread) and a value of true
+ /// vice-versa.
+ bool owner_;
+
+};
+
+/**
+ * @class ACE_TP_Reactor
+ *
+ * @brief Specialization of ACE_Select_Reactor to support thread-pool
+ * based event dispatching.
+ *
+ * One of the shortcomings of the ACE_Select_Reactor is that it
+ * does not support a thread pool-based event dispatching model,
+ * similar to the one in ACE_WFMO_Reactor. In ACE_Select_Reactor, only
+ * thread can call handle_events() at any given time. ACE_TP_Reactor
+ * removes this short-coming.
+ *
+ * ACE_TP_Reactor is a specialization of ACE_Select_Reactor to support
+ * thread pool-based event dispatching. This reactor takes advantage
+ * of the fact that events reported by @c select() are persistent if not
+ * acted upon immediately. It works by remembering the event handler
+ * which was just activated, suspending it for further I/O activities,
+ * releasing the internal lock (so that another thread can start waiting
+ * in the event loop) and then dispatching the event's handler outside the
+ * scope of the reactor lock. After the event handler has been dispatched
+ * the event handler is resumed for further I/O activity.
+ *
+ * This reactor implementation 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 loop. Note that I/O-processing
+ * callback code in event handlers (e.g. handle_input()) does not have to
+ * be modified or made thread-safe for this reactor. This is because
+ * before an I/O event is dispatched to an event handler, the handler is
+ * suspended; it is resumed by the reactor after the upcall completes.
+ * Therefore, multiple I/O events will not be made to one event handler
+ * multiple threads simultaneously. This suspend/resume protection does not
+ * apply to either timers scheduled with the reactor or to notifications
+ * requested via the reactor. When using timers and/or notifications you
+ * must provide proper protection for your class in the context of multiple
+ * threads.
+ */
+class ACE_Export ACE_TP_Reactor : public ACE_Select_Reactor
+{
+public:
+
+ /// Initialize ACE_TP_Reactor with the default size.
+ ACE_TP_Reactor (ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int mask_signals = 1,
+ int s_queue = ACE_Select_Reactor_Token::FIFO);
+
+ /**
+ * Initialize the ACE_TP_Reactor to manage
+ * @a max_number_of_handles. If @a restart is non-0 then the
+ * ACE_Reactor's @c handle_events() method will be restarted
+ * automatically when @c EINTR occurs. If @a sh or
+ * @a tq 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 *sh = 0,
+ ACE_Timer_Queue *tq = 0,
+ int mask_signals = 1,
+ int s_queue = ACE_Select_Reactor_Token::FIFO);
+
+ /**
+ * This event loop driver that blocks for @a max_wait_time before
+ * returning. It will return earlier if timer events, I/O events,
+ * or signal events occur. Note that @a max_wait_time can be 0, in
+ * which case this method blocks indefinitely until events occur.
+ *
+ * @a 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,
+ * @a max_wait_time will equal 1 second. This can be used if an
+ * application wishes to handle events for some fixed amount of
+ * time.
+ *
+ * @return The total number of events that were dispatched; 0 if the
+ * @a max_wait_time elapsed without dispatching any handlers, or -1
+ * if an error occurs (check @c errno for more information).
+ */
+ virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
+
+ virtual int handle_events (ACE_Time_Value &max_wait_time);
+
+ /// 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 positive value.
+ virtual int resumable_handler (void);
+
+ /// Called from handle events
+ static void no_op_sleep_hook (void *);
+
+ /// The ACE_TP_Reactor implementation does not have a single owner thread.
+ /// Attempts to set the owner explicitly are ignored. The reported owner
+ /// thread is the current Leader in the pattern.
+ virtual int owner (ACE_thread_t n_id, ACE_thread_t *o_id = 0);
+
+ /// Return the thread ID of the current Leader.
+ virtual int owner (ACE_thread_t *t_id);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Internal methods that do the actual work.
+
+ /// Template method from the base class.
+ virtual void clear_dispatch_mask (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /// 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);
+
+#if 0
+ // @Ciju
+ // signal handling isn't in a production state yet.
+ // Commenting it out for now.
+
+ /// 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);
+#endif // #if 0
+
+ /// 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);
+
+ /// Clear the @a handle from the read_set
+ void clear_handle_read_set (ACE_HANDLE handle);
+
+ int post_process_socket_event (ACE_EH_Dispatch_Info &dispatch_info,int status);
+
+private:
+ /// Deny access since member-wise won't work...
+ ACE_TP_Reactor (const ACE_TP_Reactor &);
+ ACE_TP_Reactor &operator = (const ACE_TP_Reactor &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/TP_Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_TP_REACTOR_H */
diff --git a/ACE/ace/TP_Reactor.inl b/ACE/ace/TP_Reactor.inl
new file mode 100644
index 00000000000..33f3fbe2a4c
--- /dev/null
+++ b/ACE/ace/TP_Reactor.inl
@@ -0,0 +1,119 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/************************************************************************/
+// Methods for ACE_EH_Dispatch_Info
+/************************************************************************/
+
+ACE_INLINE
+ACE_EH_Dispatch_Info::ACE_EH_Dispatch_Info (void) :
+ handle_ (ACE_INVALID_HANDLE),
+ event_handler_ (0),
+ mask_ (ACE_Event_Handler::NULL_MASK),
+ callback_ (0),
+ resume_flag_ (ACE_Event_Handler::ACE_REACTOR_RESUMES_HANDLER),
+ reference_counting_required_ (false),
+ dispatch_ (false)
+{
+}
+
+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_ = true;
+
+ this->handle_ = handle;
+ this->event_handler_ = event_handler;
+ this->mask_ = mask;
+ this->callback_ = callback;
+ if (event_handler_)
+ {
+ this->resume_flag_ = event_handler->resume_handler ();
+ this->reference_counting_required_ =
+ (event_handler_->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
+ }
+ else
+ this->dispatch_ = false;
+}
+
+ACE_INLINE bool
+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_ (false)
+{
+}
+
+ACE_INLINE
+ACE_TP_Token_Guard::~ACE_TP_Token_Guard (void)
+{
+ if (this->owner_)
+ {
+ ACE_MT (this->token_.release ());
+ this->owner_ = false;
+ }
+}
+
+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_ = false;
+ }
+}
+
+ACE_INLINE bool
+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 *)
+{
+}
+
+ACE_INLINE void
+ACE_TP_Reactor::clear_handle_read_set (ACE_HANDLE handle)
+{
+ this->ready_set_.wr_mask_.clr_bit (handle);
+ this->ready_set_.ex_mask_.clr_bit (handle);
+ this->ready_set_.rd_mask_.clr_bit (handle);
+}
+
+ACE_INLINE void
+ACE_TP_Reactor::clear_dispatch_mask (ACE_HANDLE ,
+ ACE_Reactor_Mask )
+{
+ this->ready_set_.rd_mask_.reset ();
+ this->ready_set_.wr_mask_.reset ();
+ this->ready_set_.ex_mask_.reset ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/TSS_Adapter.cpp b/ACE/ace/TSS_Adapter.cpp
new file mode 100644
index 00000000000..ddca0236d4f
--- /dev/null
+++ b/ACE/ace/TSS_Adapter.cpp
@@ -0,0 +1,45 @@
+/**
+ * @file TSS_Adapter.cpp
+ *
+ * $Id$
+ *
+ * Originally in Synch.cpp
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+
+#include "ace/TSS_Adapter.h"
+
+ACE_RCSID(ace, TSS_Adapter, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_TSS_Adapter::ACE_TSS_Adapter (void *object, ACE_THR_DEST f)
+ : ts_obj_ (object),
+ func_ (f)
+{
+ // ACE_TRACE ("ACE_TSS_Adapter::ACE_TSS_Adapter");
+}
+
+void
+ACE_TSS_Adapter::cleanup (void)
+{
+ // ACE_TRACE ("ACE_TSS_Adapter::cleanup");
+ (*this->func_)(this->ts_obj_); // call cleanup routine for ts_obj_
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+extern "C" void
+ACE_TSS_C_cleanup (void *object)
+{
+ // ACE_TRACE ("ACE_TSS_C_cleanup");
+ if (object != 0)
+ {
+ ACE_TSS_Adapter * const tss_adapter = (ACE_TSS_Adapter *) object;
+ // Perform cleanup on the real TS object.
+ tss_adapter->cleanup ();
+ // Delete the adapter object.
+ delete tss_adapter;
+ }
+}
diff --git a/ACE/ace/TSS_Adapter.h b/ACE/ace/TSS_Adapter.h
new file mode 100644
index 00000000000..b5405e5b6b9
--- /dev/null
+++ b/ACE/ace/TSS_Adapter.h
@@ -0,0 +1,61 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file TSS_Adapter.h
+ *
+ * $Id$
+ *
+ * Originally in Synch.h
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_TSS_ADAPTER_H
+#define ACE_TSS_ADAPTER_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_TSS_Adapter
+ *
+ * @brief This class encapsulates a TSS object and its associated
+ * C++ destructor function. It is used by the ACE_TSS...
+ * methods (in Synch_T.cpp) in order to allow an extern
+ * "C" cleanup routine to be used. Needed by the "frigging"
+ * MVS C++ compiler.
+ *
+ * Objects of this class are stored in thread specific
+ * storage. ts_obj_ points to the "real" object and
+ * func_ is a pointer to the C++ cleanup function for ts_obj_.
+ */
+class ACE_Export ACE_TSS_Adapter
+{
+public:
+ /// Initialize the adapter.
+ ACE_TSS_Adapter (void *object, ACE_THR_DEST f);
+
+ /// Perform the cleanup operation.
+ void cleanup (void);
+
+//private:
+
+ /// The real TS object.
+ void * const ts_obj_;
+
+ /// The real cleanup routine for ts_obj;
+ ACE_THR_DEST func_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TSS_ADAPTER_H */
diff --git a/ACE/ace/TSS_T.cpp b/ACE/ace/TSS_T.cpp
new file mode 100644
index 00000000000..516ade82501
--- /dev/null
+++ b/ACE/ace/TSS_T.cpp
@@ -0,0 +1,725 @@
+// $Id$
+
+#ifndef ACE_TSS_T_CPP
+#define ACE_TSS_T_CPP
+
+#include "ace/TSS_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TSS_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Thread.h"
+#include "ace/Log_Msg.h"
+#include "ace/Guard_T.h"
+#include "ace/OS_NS_stdio.h"
+
+#if defined (ACE_HAS_THR_C_DEST)
+# include "ace/TSS_Adapter.h"
+#endif /* ACE_HAS_THR_C_DEST */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TSS)
+
+template <class TYPE>
+ACE_TSS<TYPE>::~ACE_TSS (void)
+{
+#if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
+ if (this->once_)
+ {
+ ACE_OS::thr_key_detach (this->key_, this);
+ ACE_OS::thr_keyfree (this->key_);
+ }
+#else // defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
+ // We own it, we need to delete it.
+ delete type_;
+#endif // defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
+}
+
+template <class TYPE> TYPE *
+ACE_TSS<TYPE>::operator-> () const
+{
+ return this->ts_get ();
+}
+
+template <class TYPE>
+ACE_TSS<TYPE>::operator TYPE *(void) const
+{
+ return this->ts_get ();
+}
+
+template <class TYPE> TYPE *
+ACE_TSS<TYPE>::make_TSS_TYPE (void) const
+{
+ TYPE *temp = 0;
+ ACE_NEW_RETURN (temp,
+ TYPE,
+ 0);
+ return temp;
+}
+
+template <class TYPE> void
+ACE_TSS<TYPE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_TSS<TYPE>::dump");
+#if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->keylock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %d\n"), this->key_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nonce_ = %d"), this->once_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
+#endif /* ACE_HAS_DUMP */
+}
+
+#if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
+#if defined (ACE_HAS_THR_C_DEST)
+extern "C" void ACE_TSS_C_cleanup (void *); // defined in Synch.cpp
+#endif /* ACE_HAS_THR_C_DEST */
+
+template <class TYPE> void
+ACE_TSS<TYPE>::cleanup (void *ptr)
+{
+ // Cast this to the concrete TYPE * so the destructor gets called.
+ delete (TYPE *) ptr;
+}
+
+template <class TYPE> int
+ACE_TSS<TYPE>::ts_init (void)
+{
+ // Ensure that we are serialized!
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->keylock_, 0);
+
+ // Use the Double-Check pattern to make sure we only create the key
+ // once!
+ if (!this->once_)
+ {
+ if (ACE_Thread::keycreate (&this->key_,
+#if defined (ACE_HAS_THR_C_DEST)
+ &ACE_TSS_C_cleanup,
+#else
+ &ACE_TSS<TYPE>::cleanup,
+#endif /* ACE_HAS_THR_C_DEST */
+ (void *) this) != 0)
+ return -1; // Major problems, this should *never* happen!
+ else
+ {
+ // This *must* come last to avoid race conditions!
+ this->once_ = true;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+template <class TYPE>
+ACE_TSS<TYPE>::ACE_TSS (TYPE *ts_obj)
+ : once_ (false),
+ key_ (ACE_OS::NULL_key)
+{
+ // If caller has passed us a non-NULL TYPE *, then we'll just use
+ // this to initialize the thread-specific value. Thus, subsequent
+ // calls to operator->() will return this value. This is useful
+ // since it enables us to assign objects to thread-specific data
+ // that have arbitrarily complex constructors!
+
+ if (ts_obj != 0)
+ {
+ if (this->ts_init () == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ // What should we do if this call fails?!
+#if defined (ACE_HAS_WINCE)
+ ::MessageBox (0,
+ ACE_TEXT ("ACE_Thread::keycreate() failed!"),
+ ACE_TEXT ("ACE_TSS::ACE_TSS"),
+ MB_OK);
+#else
+ ACE_OS::fprintf (stderr,
+ "ACE_Thread::keycreate() failed!");
+#endif /* ACE_HAS_WINCE */
+ return;
+ }
+
+#if defined (ACE_HAS_THR_C_DEST)
+ // Encapsulate a ts_obj and it's destructor in an
+ // ACE_TSS_Adapter.
+ ACE_TSS_Adapter *tss_adapter = 0;
+ ACE_NEW (tss_adapter,
+ ACE_TSS_Adapter ((void *) ts_obj,
+ ACE_TSS<TYPE>::cleanup));
+
+ // Put the adapter in thread specific storage
+ if (ACE_Thread::setspecific (this->key_,
+ (void *) tss_adapter) != 0)
+ {
+ delete tss_adapter;
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Thread::setspecific() failed!")));
+ }
+#else
+ if (ACE_Thread::setspecific (this->key_,
+ (void *) ts_obj) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Thread::setspecific() failed!")));
+#endif /* ACE_HAS_THR_C_DEST */
+ }
+}
+
+template <class TYPE> TYPE *
+ACE_TSS<TYPE>::ts_get (void) const
+{
+ if (!this->once_)
+ {
+ // Create and initialize thread-specific ts_obj.
+ if (const_cast< ACE_TSS < TYPE > * >(this)->ts_init () == -1)
+ // Seriously wrong..
+ return 0;
+ }
+
+ TYPE *ts_obj = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+
+ // Get the adapter from thread-specific storage
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ if (ACE_Thread::getspecific (this->key_, &temp) == -1)
+ return 0; // This should not happen!
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+
+ // Check to see if this is the first time in for this thread.
+ if (tss_adapter == 0)
+#else
+ // Get the ts_obj from thread-specific storage. Note that no locks
+ // are required here...
+ void *temp = ts_obj; // Need this temp to keep G++ from complaining.
+ if (ACE_Thread::getspecific (this->key_, &temp) == -1)
+ return 0; // This should not happen!
+ ts_obj = static_cast <TYPE *> (temp);
+
+ // Check to see if this is the first time in for this thread.
+ if (ts_obj == 0)
+#endif /* ACE_HAS_THR_C_DEST */
+ {
+ // Allocate memory off the heap and store it in a pointer in
+ // thread-specific storage (on the stack...).
+
+ ts_obj = this->make_TSS_TYPE ();
+
+ if (ts_obj == 0)
+ return 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ // Encapsulate a ts_obj and it's destructor in an
+ // ACE_TSS_Adapter.
+ ACE_NEW_RETURN (tss_adapter,
+ ACE_TSS_Adapter (ts_obj,
+ ACE_TSS<TYPE>::cleanup), 0);
+
+ // Put the adapter in thread specific storage
+ if (ACE_Thread::setspecific (this->key_,
+ (void *) tss_adapter) != 0)
+ {
+ delete tss_adapter;
+ delete ts_obj;
+ return 0; // Major problems, this should *never* happen!
+ }
+#else
+ // Store the dynamically allocated pointer in thread-specific
+ // storage.
+ if (ACE_Thread::setspecific (this->key_,
+ (void *) ts_obj) != 0)
+ {
+ delete ts_obj;
+ return 0; // Major problems, this should *never* happen!
+ }
+#endif /* ACE_HAS_THR_C_DEST */
+ }
+
+#if defined (ACE_HAS_THR_C_DEST)
+ // Return the underlying ts object.
+ return static_cast <TYPE *> (tss_adapter->ts_obj_);
+#else
+ return ts_obj;
+#endif /* ACE_HAS_THR_C_DEST */
+}
+
+// Get the thread-specific object for the key associated with this
+// object. Returns 0 if the ts_obj has never been initialized,
+// otherwise returns a pointer to the ts_obj.
+
+template <class TYPE> TYPE *
+ACE_TSS<TYPE>::ts_object (void) const
+{
+ if (!this->once_) // Return 0 if we've never been initialized.
+ return 0;
+
+ TYPE *ts_obj = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+
+ // Get the tss adapter from thread-specific storage
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ if (ACE_Thread::getspecific (this->key_, &temp) == -1)
+ {
+ return 0; // This should not happen!
+ }
+ else
+ {
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ {
+ if (tss_adapter != 0)
+ // Extract the real TS object.
+ ts_obj = static_cast <TYPE *> (tss_adapter->ts_obj_);
+ }
+ }
+#else
+ void *temp = ts_obj; // Need this temp to keep G++ from complaining.
+ if (ACE_Thread::getspecific (this->key_, &temp) == -1)
+ return 0; // This should not happen!
+ ts_obj = static_cast <TYPE *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return ts_obj;
+}
+
+template <class TYPE> TYPE *
+ACE_TSS<TYPE>::ts_object (TYPE *new_ts_obj)
+{
+ // Note, we shouldn't hold the keylock at this point because
+ // <ts_init> does it for us and we'll end up with deadlock
+ // otherwise...
+ if (!this->once_)
+ {
+ // Create and initialize thread-specific ts_obj.
+ if (this->ts_init () == -1)
+ return 0;
+ }
+
+ TYPE *ts_obj = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ if (ACE_Thread::getspecific (this->key_, &temp) == -1)
+ return 0; // This should not happen!
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+
+ if (tss_adapter != 0)
+ {
+ ts_obj = static_cast <TYPE *> (tss_adapter->ts_obj_);
+ delete tss_adapter; // don't need this anymore
+ }
+
+ ACE_NEW_RETURN (tss_adapter,
+ ACE_TSS_Adapter ((void *) new_ts_obj,
+ ACE_TSS<TYPE>::cleanup),
+ 0);
+
+ if (ACE_Thread::setspecific (this->key_,
+ (void *) tss_adapter) == -1)
+ {
+ delete tss_adapter;
+ return ts_obj; // This should not happen!
+ }
+#else
+ void *temp = ts_obj; // Need this temp to keep G++ from complaining.
+ if (ACE_Thread::getspecific (this->key_, &temp) == -1)
+ return 0; // This should not happen!
+ ts_obj = static_cast <TYPE *> (temp);
+ if (ACE_Thread::setspecific (this->key_, (void *) new_ts_obj) == -1)
+ return ts_obj; // This should not happen!
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return ts_obj;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TSS_Guard)
+
+template <class ACE_LOCK> void
+ACE_TSS_Guard<ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %d"), this->key_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class ACE_LOCK> void
+ACE_TSS_Guard<ACE_LOCK>::init_key (void)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::init_key");
+
+ this->key_ = ACE_OS::NULL_key;
+ ACE_Thread::keycreate (&this->key_,
+#if defined (ACE_HAS_THR_C_DEST)
+ &ACE_TSS_C_cleanup,
+#else
+ &ACE_TSS_Guard<ACE_LOCK>::cleanup,
+#endif /* ACE_HAS_THR_C_DEST */
+ (void *) this);
+}
+
+template <class ACE_LOCK>
+ACE_TSS_Guard<ACE_LOCK>::ACE_TSS_Guard (void)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::ACE_TSS_Guard");
+ this->init_key ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Guard<ACE_LOCK>::release (void)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::release");
+
+ ACE_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return guard->release ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Guard<ACE_LOCK>::remove (void)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::remove");
+
+ ACE_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return guard->remove ();
+}
+
+template <class ACE_LOCK>
+ACE_TSS_Guard<ACE_LOCK>::~ACE_TSS_Guard (void)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::~ACE_TSS_Guard");
+
+ ACE_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ // Make sure that this pointer is NULL when we shut down...
+ ACE_Thread::setspecific (this->key_, 0);
+ ACE_Thread::keyfree (this->key_);
+ // Destructor releases lock.
+ delete guard;
+}
+
+template <class ACE_LOCK> void
+ACE_TSS_Guard<ACE_LOCK>::cleanup (void *ptr)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::cleanup");
+
+ // Destructor releases lock.
+ delete (ACE_Guard<ACE_LOCK> *) ptr;
+}
+
+template <class ACE_LOCK>
+ACE_TSS_Guard<ACE_LOCK>::ACE_TSS_Guard (ACE_LOCK &lock, int block)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::ACE_TSS_Guard");
+
+ this->init_key ();
+ ACE_Guard<ACE_LOCK> *guard = 0;
+ ACE_NEW (guard,
+ ACE_Guard<ACE_LOCK> (lock,
+ block));
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ ACE_NEW (tss_adapter,
+ ACE_TSS_Adapter ((void *) guard,
+ ACE_TSS_Guard<ACE_LOCK>::cleanup));
+ ACE_Thread::setspecific (this->key_,
+ (void *) tss_adapter);
+#else
+ ACE_Thread::setspecific (this->key_,
+ (void *) guard);
+#endif /* ACE_HAS_THR_C_DEST */
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Guard<ACE_LOCK>::acquire (void)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::acquire");
+
+ ACE_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return guard->acquire ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Guard<ACE_LOCK>::tryacquire (void)
+{
+// ACE_TRACE ("ACE_TSS_Guard<ACE_LOCK>::tryacquire");
+
+ ACE_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return guard->tryacquire ();
+}
+
+template <class ACE_LOCK>
+ACE_TSS_Write_Guard<ACE_LOCK>::ACE_TSS_Write_Guard (ACE_LOCK &lock,
+ int block)
+{
+// ACE_TRACE ("ACE_TSS_Write_Guard<ACE_LOCK>::ACE_TSS_Write_Guard");
+
+ this->init_key ();
+ ACE_Guard<ACE_LOCK> *guard;
+ ACE_NEW (guard,
+ ACE_Write_Guard<ACE_LOCK> (lock,
+ block));
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ ACE_NEW (tss_adapter,
+ ACE_TSS_Adapter ((void *) guard,
+ ACE_TSS_Guard<ACE_LOCK>::cleanup));
+ ACE_Thread::setspecific (this->key_,
+ (void *) tss_adapter);
+#else
+ ACE_Thread::setspecific (this->key_,
+ (void *) guard);
+#endif /* ACE_HAS_THR_C_DEST */
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Write_Guard<ACE_LOCK>::acquire (void)
+{
+// ACE_TRACE ("ACE_TSS_Write_Guard<ACE_LOCK>::acquire");
+
+ ACE_Write_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Write_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Write_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return guard->acquire_write ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire (void)
+{
+// ACE_TRACE ("ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire");
+
+ ACE_Write_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Write_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Write_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return guard->tryacquire_write ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Write_Guard<ACE_LOCK>::acquire_write (void)
+{
+// ACE_TRACE ("ACE_TSS_Write_Guard<ACE_LOCK>::acquire_write");
+
+ return this->acquire ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire_write (void)
+{
+// ACE_TRACE ("ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire_write");
+
+ return this->tryacquire ();
+}
+
+template <class ACE_LOCK> void
+ACE_TSS_Write_Guard<ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_TSS_Write_Guard<ACE_LOCK>::dump");
+ ACE_TSS_Guard<ACE_LOCK>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class ACE_LOCK>
+ACE_TSS_Read_Guard<ACE_LOCK>::ACE_TSS_Read_Guard (ACE_LOCK &lock, int block)
+{
+// ACE_TRACE ("ACE_TSS_Read_Guard<ACE_LOCK>::ACE_TSS_Read_Guard");
+
+ this->init_key ();
+ ACE_Guard<ACE_LOCK> *guard;
+ ACE_NEW (guard,
+ ACE_Read_Guard<ACE_LOCK> (lock,
+ block));
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter;
+ ACE_NEW (tss_adapter,
+ ACE_TSS_Adapter ((void *)guard,
+ ACE_TSS_Guard<ACE_LOCK>::cleanup));
+ ACE_Thread::setspecific (this->key_,
+ (void *) tss_adapter);
+#else
+ ACE_Thread::setspecific (this->key_,
+ (void *) guard);
+#endif /* ACE_HAS_THR_C_DEST */
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Read_Guard<ACE_LOCK>::acquire (void)
+{
+// ACE_TRACE ("ACE_TSS_Read_Guard<ACE_LOCK>::acquire");
+
+ ACE_Read_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Read_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Read_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return guard->acquire_read ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Read_Guard<ACE_LOCK>::tryacquire (void)
+{
+// ACE_TRACE ("ACE_TSS_Read_Guard<ACE_LOCK>::tryacquire");
+
+ ACE_Read_Guard<ACE_LOCK> *guard = 0;
+
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_TSS_Adapter *tss_adapter = 0;
+ void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
+ guard = static_cast <ACE_Read_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
+#else
+ void *temp = guard; // Need this temp to keep G++ from complaining.
+ ACE_Thread::getspecific (this->key_, &temp);
+ guard = static_cast <ACE_Read_Guard<ACE_LOCK> *> (temp);
+#endif /* ACE_HAS_THR_C_DEST */
+
+ return guard->tryacquire_read ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Read_Guard<ACE_LOCK>::acquire_read (void)
+{
+// ACE_TRACE ("ACE_TSS_Read_Guard<ACE_LOCK>::acquire_read");
+
+ return this->acquire ();
+}
+
+template <class ACE_LOCK> int
+ACE_TSS_Read_Guard<ACE_LOCK>::tryacquire_read (void)
+{
+// ACE_TRACE ("ACE_TSS_Read_Guard<ACE_LOCK>::tryacquire_read");
+
+ return this->tryacquire ();
+}
+
+template <class ACE_LOCK> void
+ACE_TSS_Read_Guard<ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_TSS_Read_Guard<ACE_LOCK>::dump");
+ ACE_TSS_Guard<ACE_LOCK>::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+#endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TSS_T_CPP */
diff --git a/ACE/ace/TSS_T.h b/ACE/ace/TSS_T.h
new file mode 100644
index 00000000000..d0ed0a7b472
--- /dev/null
+++ b/ACE/ace/TSS_T.h
@@ -0,0 +1,253 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file TSS_T.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_TSS_T_H
+#define ACE_TSS_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Lock.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// This should probably go somewhere else, but it's only used here and
+// in Thread_Manager.
+// Note there is no ACE_TSS_SET because one would typicaly do
+// 'ACE_TSS_GET()->xyz_ = value', so the macro would have been too
+// complicated.
+# if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
+# define ACE_TSS_TYPE(T) ACE_TSS< T >
+# define ACE_TSS_GET(I, T) ((I)->operator T * ())
+# else
+# define ACE_TSS_TYPE(T) T
+# define ACE_TSS_GET(I, T) (I)
+# endif /* ACE_HAS_THREADS && (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) */
+
+#include "ace/Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_TSS
+ *
+ * @brief Allows objects that are "physically" in thread specific
+ * storage (i.e., private to a thread) to be accessed as though
+ * they were "logically" global to a program.
+ *
+ * This class helps to maintain a separate copy of an object for each thread
+ * that needs access to it. All threads access a single instance of ACE_TSS
+ * to obtain a pointer to a thread-specific copy of a TYPE object. Using
+ * a pointer to TYPE in TSS instead of TYPE itself is useful because,
+ * in addition to avoiding copies on what may be a complex class, it allows
+ * assignment of objects to thread-specific data that have arbitrarily
+ * complex constructors.
+ *
+ * When the ACE_TSS object is destroyed, all threads's instances of the
+ * data are deleted.
+ *
+ * Modern compilers have no problem using a built-in type for @c TYPE.
+ * However, if you must use an older compiler that won't work with a built-in
+ * type, the ACE_TSS_Type_Adapter class template, below, can be used for
+ * adapting built-in types to work with ACE_TSS.
+ *
+ * @note Beware when creating static instances of this type
+ * (as with any other, btw). The unpredictable order of initialization
+ * across different platforms may cause a situation where one uses
+ * the instance before it is fully initialized. That's why typically
+ * instances of this type are dynamicaly allocated. On the stack it is
+ * typically allocated inside the ACE_Thread::svc() method which
+ * limits its lifetime appropriately.
+ *
+ */
+template <class TYPE>
+class ACE_TSS
+{
+public:
+ /**
+ * Default constructor. Can also initialize this ACE_TSS instance,
+ * readying it for use by the calling thread as well as all other
+ * threads in the process. If the constructor does not initialize this
+ * object, the first access to it will perform the initialization, which
+ * could possibly (under odd error conditions) fail.
+ *
+ * @param ts_obj If non-zero, this object is initialized for use by
+ * all threads and @a ts_obj is used to set the
+ * thread-specific value for the calling thread. Other
+ * threads use the ts_object (TYPE *) method to set
+ * a specific value.
+ */
+ ACE_TSS (TYPE *ts_obj = 0);
+
+ /// Deregister this object from thread-specific storage administration.
+ /// Will cause all threads' copies of TYPE to be destroyed.
+ virtual ~ACE_TSS (void);
+
+ /**
+ * Set the thread-specific object for the calling thread.
+ * If this object has not been initialized yet, this method performs the
+ * initialization.
+ *
+ * @param new_ts_obj The new value for the calling thread's copy of
+ * this object.
+ *
+ * @return The previous value of the calling thread's copy of this
+ * object; 0 if there was no previous value. This method also
+ * returns 0 on errors. To tell the difference between an error
+ * and a returned 0 pointer, it's recommended that one set errno
+ * to 0 prior to calling ts_object() and check for a new errno
+ * value if ts_object() returns 0.
+ */
+ TYPE *ts_object (TYPE *new_ts_obj);
+
+ /** @name Accessors
+ *
+ * All accessors return a pointer to the calling thread's copy of the
+ * TYPE data. The pointer may be 0 on error conditions or if the calling
+ * thread's copy of the data has not yet been set. See specific method
+ * descriptions for complete details.
+ */
+ //@{
+ /**
+ * Get the thread-specific object for this object.
+ *
+ * @return 0 if the object has never been initialized, otherwise returns
+ * the calling thread's copy of the data. The returned pointer
+ * may be 0 under odd error conditions; check errno for further
+ * information.
+ */
+ TYPE *ts_object (void) const;
+
+ /**
+ * Use a "smart pointer" to get the thread-specific data associated
+ * with this object.
+ * If this ACE_TSS object hasn't been initialized, this method
+ * will initialize it as a side-affect. If the calling thread has not
+ * set a value, a default-constructed instance of TYPE is allocated and it
+ * becomes the thread's instance.
+ *
+ * @return The calling thread's copy of the data. The returned pointer
+ * may be 0 under odd error conditions; check errno for further
+ * information.
+ */
+ TYPE *operator-> () const;
+
+ /**
+ * Obtain a pointer to the calling thread's TYPE object.
+ * If this ACE_TSS object hasn't been initialized, this method
+ * will initialize it as a side-affect. If the calling thread has not
+ * set a value, a default-constructed instance of TYPE is allocated and it
+ * becomes the thread's instance.
+ *
+ * @return The calling thread's copy of the data. The returned pointer
+ * may be 0 under odd error conditions; check errno for further
+ * information.
+ */
+ operator TYPE *(void) const;
+
+ //@}
+
+ /// Hook for construction parameters.
+ virtual TYPE *make_TSS_TYPE (void) const;
+
+ // = Utility methods.
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+protected:
+ /// Actually implements the code that retrieves the object from
+ /// thread-specific storage.
+ TYPE *ts_get (void) const;
+
+ /// Factors out common code for initializing TSS. This must NOT be
+ /// called with the lock held...
+ int ts_init (void);
+
+#if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)))
+ /// This implementation only works for non-threading systems...
+ TYPE *type_;
+#else
+ /// Avoid race conditions during initialization.
+ ACE_Thread_Mutex keylock_;
+
+ /// "First time in" flag.
+ volatile bool once_;
+
+ /// Key for the thread-specific error data.
+ ACE_thread_key_t key_;
+
+ /// "Destructor" that deletes internal TYPE * when thread exits.
+ static void cleanup (void *ptr);
+#endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
+ // = Disallow copying...
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS<TYPE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS<TYPE> &))
+};
+
+/**
+ * @class ACE_TSS_Type_Adapter
+ *
+ * @brief Adapter that allows built-in types to be used with ACE_TSS.
+ *
+ * Wraps a value of a built-in type, providing conversions to
+ * and from the type. Example use with ACE_TSS:
+ * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
+ * *i = 37;
+ * ACE_OS::fprintf (stderr, "%d\n", *i);
+ * Unfortunately, though, some compilers have trouble with the
+ * implicit type conversions. This seems to work better:
+ * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
+ * i->operator int & () = 37;
+ * ACE_OS::fprintf (stderr, "%d\n", i->operator int ());
+ */
+template <class TYPE>
+class ACE_TSS_Type_Adapter
+{
+public:
+ /// Constructor. Inlined here so that it should _always_ be inlined.
+ ACE_TSS_Type_Adapter (const TYPE value = 0): value_ (value) {}
+
+ /// TYPE conversion. Inlined here so that it should _always_ be
+ /// inlined.
+ operator TYPE () const { return value_; };
+
+ /// TYPE & conversion. Inlined here so that it should _always_ be
+ /// inlined.
+ operator TYPE &() { return value_; };
+
+private:
+ /// The wrapped value.
+ TYPE value_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/TSS_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/TSS_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("TSS_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TSS_T_H */
diff --git a/ACE/ace/TSS_T.inl b/ACE/ace/TSS_T.inl
new file mode 100644
index 00000000000..1d74573c658
--- /dev/null
+++ b/ACE/ace/TSS_T.inl
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)))
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TYPE> ACE_INLINE
+ACE_TSS<TYPE>::ACE_TSS (TYPE *type)
+ : type_ (type)
+{
+}
+
+template <class TYPE> ACE_INLINE int
+ACE_TSS<TYPE>::ts_init (void)
+{
+ return 0;
+}
+
+template <class TYPE> ACE_INLINE TYPE *
+ACE_TSS<TYPE>::ts_object (void) const
+{
+ return this->type_;
+}
+
+template <class TYPE> ACE_INLINE TYPE *
+ACE_TSS<TYPE>::ts_object (TYPE *type)
+{
+ this->type_ = type;
+ return this->type_;
+}
+
+template <class TYPE> ACE_INLINE TYPE *
+ACE_TSS<TYPE>::ts_get (void) const
+{
+ return this->type_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ! (defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))) */
diff --git a/ACE/ace/TTY_IO.cpp b/ACE/ace/TTY_IO.cpp
new file mode 100644
index 00000000000..5989f8f6375
--- /dev/null
+++ b/ACE/ace/TTY_IO.cpp
@@ -0,0 +1,583 @@
+// $Id$
+
+#include "ace/TTY_IO.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_strings.h"
+
+#if defined (ACE_HAS_TERMIOS)
+# include "ace/os_include/os_termios.h"
+#elif defined (ACE_HAS_TERMIO)
+# include <termio.h>
+#endif
+
+ACE_RCSID (ace,
+ TTY_IO,
+ "$Id$")
+
+namespace
+{
+ const char ACE_TTY_IO_NONE[] = "none";
+#if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO) || defined (ACE_WIN32)
+ const char ACE_TTY_IO_ODD[] = "odd";
+ const char ACE_TTY_IO_EVEN[] = "even";
+#endif
+#if defined (ACE_WIN32)
+ const char ACE_TTY_IO_MARK[] = "mark";
+ const char ACE_TTY_IO_SPACE[] = "space";
+#endif /* ACE_WIN32 */
+}
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_TTY_IO::Serial_Params::Serial_Params (void)
+{
+ baudrate = 9600;
+ xonlim = 0;
+ xofflim = 0;
+ readmincharacters = 0;
+ readtimeoutmsec = 10000;
+ parityenb = true;
+ paritymode = ACE_TTY_IO_NONE;
+ ctsenb = false;
+ rtsenb = 0;
+ xinenb = false;
+ xoutenb = false;
+ modem = false;
+ rcvenb = true;
+ dsrenb = false;
+ dtrdisable = false;
+ databits = 8;
+ stopbits = 1;
+}
+
+// Interface for reading/writing serial device parameters
+
+int ACE_TTY_IO::control (Control_Mode cmd, Serial_Params *arg) const
+{
+#if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO)
+
+#if defined (ACE_HAS_TERMIOS)
+ struct termios devpar;
+ speed_t newbaudrate = 0;
+ if (tcgetattr (get_handle () , &devpar) == -1)
+#elif defined (TCGETS)
+ struct termios devpar;
+ unsigned int newbaudrate = 0;
+ if (this->ACE_IO_SAP::control (TCGETS, static_cast<void*>(&devpar)) == -1)
+#elif defined (TCGETA)
+ struct termio devpar;
+ unsigned int newbaudrate = 0;
+ if (this->ACE_IO_SAP::control (TCGETA, static_cast<void*>(&devpar)) == -1)
+#else
+ errno = ENOSYS;
+#endif /* ACE_HAS_TERMIOS */
+ return -1;
+
+ switch (cmd)
+ {
+ case SETPARAMS:
+ switch (arg->baudrate)
+ {
+#if defined (B0)
+ case 0: newbaudrate = B0; break;
+#endif /* B0 */
+#if defined (B50)
+ case 50: newbaudrate = B50; break;
+#endif /* B50 */
+#if defined (B75)
+ case 75: newbaudrate = B75; break;
+#endif /* B75 */
+#if defined (B110)
+ case 110: newbaudrate = B110; break;
+#endif /* B110 */
+#if defined (B134)
+ case 134: newbaudrate = B134; break;
+#endif /* B134 */
+#if defined (B150)
+ case 150: newbaudrate = B150; break;
+#endif /* B150 */
+#if defined (B200)
+ case 200: newbaudrate = B200; break;
+#endif /* B200 */
+#if defined (B300)
+ case 300: newbaudrate = B300; break;
+#endif /* B300 */
+#if defined (B600)
+ case 600: newbaudrate = B600; break;
+#endif /* B600 */
+#if defined (B1200)
+ case 1200: newbaudrate = B1200; break;
+#endif /* B1200 */
+#if defined (B1800)
+ case 1800: newbaudrate = B1800; break;
+#endif /* B1800 */
+#if defined (B2400)
+ case 2400: newbaudrate = B2400; break;
+#endif /* B2400 */
+#if defined (B4800)
+ case 4800: newbaudrate = B4800; break;
+#endif /* B4800 */
+#if defined (B9600)
+ case 9600: newbaudrate = B9600; break;
+#endif /* B9600 */
+#if defined (B19200)
+ case 19200: newbaudrate = B19200; break;
+#endif /* B19200 */
+#if defined (B38400)
+ case 38400: newbaudrate = B38400; break;
+#endif /* B38400 */
+#if defined (B56000)
+ case 56000: newbaudrate = B56000; break;
+#endif /* B56000 */
+#if defined (B57600)
+ case 57600: newbaudrate = B57600; break;
+#endif /* B57600 */
+#if defined (B76800)
+ case 76800: newbaudrate = B76800; break;
+#endif /* B76800 */
+#if defined (B115200)
+ case 115200: newbaudrate = B115200; break;
+#endif /* B115200 */
+#if defined (B128000)
+ case 128000: newbaudrate = B128000; break;
+#endif /* B128000 */
+#if defined (B153600)
+ case 153600: newbaudrate = B153600; break;
+#endif /* B153600 */
+#if defined (B230400)
+ case 230400: newbaudrate = B230400; break;
+#endif /* B230400 */
+#if defined (B307200)
+ case 307200: newbaudrate = B307200; break;
+#endif /* B307200 */
+#if defined (B256000)
+ case 256000: newbaudrate = B256000; break;
+#endif /* B256000 */
+#if defined (B460800)
+ case 460800: newbaudrate = B460800; break;
+#endif /* B460800 */
+#if defined (B500000)
+ case 500000: newbaudrate = B500000; break;
+#endif /* B500000 */
+#if defined (B576000)
+ case 576000: newbaudrate = B576000; break;
+#endif /* B576000 */
+#if defined (B921600)
+ case 921600: newbaudrate = B921600; break;
+#endif /* B921600 */
+#if defined (B1000000)
+ case 1000000: newbaudrate = B1000000; break;
+#endif /* B1000000 */
+#if defined (B1152000)
+ case 1152000: newbaudrate = B1152000; break;
+#endif /* B1152000 */
+#if defined (B1500000)
+ case 1500000: newbaudrate = B1500000; break;
+#endif /* B1500000 */
+#if defined (B2000000)
+ case 2000000: newbaudrate = B2000000; break;
+#endif /* B2000000 */
+#if defined (B2500000)
+ case 2500000: newbaudrate = B2500000; break;
+#endif /* B2500000 */
+#if defined (B3000000)
+ case 3000000: newbaudrate = B3000000; break;
+#endif /* B3000000 */
+#if defined (B3500000)
+ case 3500000: newbaudrate = B3500000; break;
+#endif /* B3500000 */
+#if defined (B4000000)
+ case 4000000: newbaudrate = B4000000; break;
+#endif /* B4000000 */
+ default:
+ return -1;
+ }
+
+#if defined (ACE_HAS_TERMIOS)
+ // Can you really have different input and output baud rates?!
+ if (cfsetospeed (&devpar, newbaudrate) == -1)
+ return -1;
+ if (cfsetispeed (&devpar, newbaudrate) == -1)
+ return -1;
+#else
+ devpar.c_cflag &= ~CBAUD;
+# if defined (CBAUDEX)
+ devpar.c_cflag &= ~CBAUDEX;
+# endif /* CBAUDEX */
+ devpar.c_cflag |= newbaudrate;
+#endif /* ACE_HAS_TERMIOS */
+
+ devpar.c_cflag &= ~CSIZE;
+ switch (arg->databits)
+ {
+ case 5:
+ devpar.c_cflag |= CS5;
+ break;
+ case 6:
+ devpar.c_cflag |= CS6;
+ break;
+ case 7:
+ devpar.c_cflag |= CS7;
+ break;
+ case 8:
+ devpar.c_cflag |= CS8;
+ break;
+ default:
+ return -1;
+ }
+
+ switch (arg->stopbits)
+ {
+ case 1:
+ devpar.c_cflag &= ~CSTOPB;
+ break;
+ case 2:
+ devpar.c_cflag |= CSTOPB;
+ break;
+ default:
+ return -1;
+ }
+
+ if (arg->parityenb && arg->paritymode)
+ {
+ if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_ODD) == 0)
+ {
+ devpar.c_cflag |= PARENB;
+ devpar.c_cflag |= PARODD;
+ }
+ else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_EVEN) == 0)
+ {
+ devpar.c_cflag |= PARENB;
+ devpar.c_cflag &= ~PARODD;
+ }
+ else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_NONE) == 0)
+ devpar.c_cflag &= ~PARENB;
+ else
+ return -1;
+ }
+ else
+ {
+ devpar.c_cflag &= ~PARENB;
+ }
+
+#if defined (CNEW_RTSCTS)
+ if ((arg->ctsenb) || (arg->rtsenb)) // Enable RTS/CTS protocol
+ devpar.c_cflag |= CNEW_RTSCTS;
+ else
+ devpar.c_cflag &= ~CNEW_RTSCTS;
+#elif defined (CRTSCTS)
+ if ((arg->ctsenb) || (arg->rtsenb)) // Enable RTS/CTS protocol
+ devpar.c_cflag |= CRTSCTS;
+ else
+ devpar.c_cflag &= ~CRTSCTS;
+#endif /* NEW_RTSCTS || CRTSCTS */
+
+#if defined (CREAD)
+ // Enable/disable receiver
+ if (arg->rcvenb)
+ devpar.c_cflag |= CREAD;
+ else
+ devpar.c_cflag &= ~CREAD;
+#endif /* CREAD */
+
+#if defined (HUPCL)
+ // Cause DTR to drop after port close.
+ devpar.c_cflag |= HUPCL;
+#endif /* HUPCL */
+
+#if defined (CLOCAL)
+ // If device is not a modem set to local device.
+ if (arg->modem)
+ devpar.c_cflag &= ~CLOCAL;
+ else
+ devpar.c_cflag |= CLOCAL;
+#endif /* CLOCAL */
+
+ devpar.c_iflag = IGNPAR | INPCK;
+ if (arg->databits < 8)
+ devpar.c_iflag |= ISTRIP;
+
+#if defined (IGNBRK)
+ // If device is not a modem set to ignore break points
+ if(arg->modem)
+ devpar.c_iflag &= ~IGNBRK;
+ else
+ devpar.c_iflag |= IGNBRK;
+#endif /* IGNBRK */
+
+#if defined (IXOFF)
+ // Enable/disable software flow control on input
+ if (arg->xinenb)
+ devpar.c_iflag |= IXOFF;
+ else
+ devpar.c_iflag &= ~IXOFF;
+#endif /* IXOFF */
+
+#if defined (IXON)
+ // Enable/disable software flow control on output
+ if (arg->xoutenb)
+ devpar.c_iflag |= IXON;
+ else
+ devpar.c_iflag &= ~IXON;
+#endif /* IXON */
+
+#if defined (ICANON)
+ // Enable noncanonical input processing mode
+ devpar.c_lflag &= ~ICANON;
+#endif /* ICANON */
+
+#if defined (ECHO)
+ // Disable echoing of input characters
+ devpar.c_lflag &= ~ECHO;
+#endif /* ECHO */
+
+#if defined (ECHOE)
+ // Disable echoing erase chareacter as BS-SP-BS
+ devpar.c_lflag &= ~ECHOE;
+#endif /* ECHOE */
+
+#if defined (ISIG)
+ // Disable SIGINTR, SIGSUSP, SIGDSUSP and SIGQUIT signals
+ devpar.c_lflag &= ~ISIG;
+#endif /* ISIG */
+
+#if defined (OPOST)
+ // Disable post-processing of output data
+ devpar.c_oflag &= ~OPOST;
+#endif /* OPOST */
+
+ if (arg->readtimeoutmsec < 0)
+ {
+ // Settings for infinite timeout.
+ devpar.c_cc[VTIME] = 0;
+ // In case of infinite timeout [VMIN] must be at least 1.
+ if (arg->readmincharacters > UCHAR_MAX)
+ devpar.c_cc[VMIN] = UCHAR_MAX;
+ else if (arg->readmincharacters < 1)
+ devpar.c_cc[VMIN] = 1;
+ else
+ devpar.c_cc[VMIN] = static_cast<unsigned char>(arg->readmincharacters);
+ }
+ else
+ {
+ devpar.c_cc[VTIME] = static_cast<unsigned char>(arg->readtimeoutmsec / 100);
+
+ if (arg->readmincharacters > UCHAR_MAX)
+ devpar.c_cc[VMIN] = UCHAR_MAX;
+ else if (arg->readmincharacters < 1)
+ devpar.c_cc[VMIN] = 0;
+ else
+ devpar.c_cc[VMIN] = static_cast<unsigned char>(arg->readmincharacters);
+ }
+
+#if defined (TIOCMGET)
+ int status;
+ this->ACE_IO_SAP::control (TIOCMGET, &status);
+
+ if (arg->dtrdisable)
+ status &= ~TIOCM_DTR;
+ else
+ status |= TIOCM_DTR;
+
+ this->ACE_IO_SAP::control (TIOCMSET, &status);
+#endif /* definded (TIOCMGET) */
+
+#if defined (ACE_HAS_TERMIOS)
+ return tcsetattr (get_handle (), TCSANOW, &devpar);
+#elif defined (TCSETS)
+ return this->ACE_IO_SAP::control (TCSETS, static_cast<void*>(&devpar));
+#elif defined (TCSETA)
+ return this->ACE_IO_SAP::control (TCSETA, static_cast<void*>(&devpar));
+#else
+ errno = ENOSYS;
+ return -1;
+#endif /* ACE_HAS_TERMIOS */
+
+ 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;
+ }
+
+ dcb.BaudRate = arg->baudrate;
+
+ switch (arg->databits)
+ {
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ dcb.ByteSize = arg->databits;
+ break;
+ default:
+ return -1;
+ }
+
+ switch (arg->stopbits)
+ {
+ case 1:
+ dcb.StopBits = ONESTOPBIT;
+ break;
+ case 2:
+ dcb.StopBits = TWOSTOPBITS;
+ break;
+ default:
+ return -1;
+ }
+
+ if (arg->parityenb && arg->paritymode)
+ {
+ dcb.fParity = TRUE;
+ if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_ODD) == 0)
+ dcb.Parity = ODDPARITY;
+ else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_EVEN) == 0)
+ dcb.Parity = EVENPARITY;
+ else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_NONE) == 0)
+ dcb.Parity = NOPARITY;
+ else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_MARK) == 0)
+ dcb.Parity = MARKPARITY;
+ else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_SPACE) == 0)
+ dcb.Parity = SPACEPARITY;
+ else
+ return -1;
+ }
+ else
+ {
+ dcb.fParity = FALSE;
+ dcb.Parity = NOPARITY;
+ }
+
+ // Enable/disable RTS protocol.
+ switch (arg->rtsenb)
+ {
+ 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;
+ }
+
+ // Enable/disable CTS protocol.
+ if (arg->ctsenb)
+ dcb.fOutxCtsFlow = TRUE;
+ else
+ dcb.fOutxCtsFlow = FALSE;
+
+ // Enable/disable DSR protocol.
+ if (arg->dsrenb)
+ dcb.fOutxDsrFlow = TRUE;
+ else
+ dcb.fOutxDsrFlow = FALSE;
+
+ // Disable/enable DTR protocol
+ if (arg->dtrdisable)
+ dcb.fDtrControl = DTR_CONTROL_DISABLE;
+ else
+ dcb.fDtrControl = DTR_CONTROL_ENABLE;
+
+ // Enable/disable software flow control on input
+ if (arg->xinenb)
+ dcb.fInX = TRUE;
+ else
+ dcb.fInX = FALSE;
+
+ // Enable/disable software flow control on output
+ if (arg->xoutenb)
+ dcb.fOutX = TRUE;
+ else
+ dcb.fOutX = FALSE;
+
+ // Always set limits unless set to negative to use default.
+ if (arg->xonlim >= 0)
+ dcb.XonLim = static_cast<WORD>(arg->xonlim);
+ if (arg->xofflim >= 0)
+ dcb.XoffLim = static_cast<WORD>(arg->xofflim);
+
+ 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;
+ }
+
+ COMMTIMEOUTS timeouts;
+ if (!::GetCommTimeouts (this->get_handle(), &timeouts))
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+
+ if (arg->readtimeoutmsec < 0)
+ {
+ // Settings for infinite timeout.
+ timeouts.ReadIntervalTimeout = 0;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = 0;
+ }
+ else 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 timeout for char to arrive before returning.
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = arg->readtimeoutmsec;
+ }
+
+ 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_TERMIOS || ACE_HAS_TERMIO */
+}
+
+#if defined (ACE_NEEDS_DEV_IO_CONVERSION)
+ACE_TTY_IO::operator ACE_DEV_IO &()
+{
+ return static_cast<ACE_DEV_IO &>(*this);
+}
+#endif /* ACE_NEEDS_DEV_IO_CONVERSION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/TTY_IO.h b/ACE/ace/TTY_IO.h
new file mode 100644
index 00000000000..f4f3d12b54d
--- /dev/null
+++ b/ACE/ace/TTY_IO.h
@@ -0,0 +1,122 @@
+// -*- 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/DEV_IO.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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
+ {
+ SETPARAMS, ///< Set control parameters.
+ GETPARAMS ///< Get control parameters.
+ };
+
+ struct ACE_Export Serial_Params
+ {
+ Serial_Params (void);
+
+ /** Specifies the baudrate at which the communnication port operates. */
+ int baudrate;
+ /** Specifies the minimum number of bytes in input buffer before XON char
+ is sent. Negative value indicates that default value should
+ be used (Win32). */
+ int xonlim;
+ /** Specifies the maximum number of bytes in input buffer before XOFF char
+ is sent. Negative value indicates that default value should
+ be used (Win32). */
+ int xofflim;
+ /** Specifies the minimum number of characters for non-canonical
+ read (POSIX). */
+ unsigned int readmincharacters;
+ /** Specifies the time to wait before returning from read. Negative value
+ means infinite timeout. */
+ int readtimeoutmsec;
+ /**
+ * @deprecated
+ * Note that this member is going away in a subsequent
+ * release. Use <code>paritymode = "none"</code> to disable parity
+ * checking.
+ *
+ * Enable/disable parity checking.
+ */
+ bool parityenb;
+ /** Specifies the parity mode. POSIX supports "none", "even" and
+ "odd" parity. Additionally Win32 supports "mark" and "space"
+ parity modes. */
+ const char *paritymode;
+ /** Enable & set CTS mode. Note that RTS & CTS are enabled/disabled
+ together on some systems (RTS/CTS is enabled if either
+ <code>ctsenb</code> or <code>rtsenb</code> is set). */
+ bool ctsenb;
+ /** Enable & set RTS mode. Note that RTS & CTS are enabled/disabled
+ together on some systems (RTS/CTS is enabled if either
+ <code>ctsenb</code> or <code>rtsenb</code> is set).
+ - 0 = Disable RTS.
+ - 1 = Enable RTS.
+ - 2 = Enable RTS flow-control handshaking (Win32).
+ - 3 = Specifies that RTS line will be high if bytes are available
+ for transmission. After transmission RTS will be low (Win32). */
+ unsigned char rtsenb;
+ /** Enable/disable software flow control on input. */
+ bool xinenb;
+ /** Enable/disable software flow control on output. */
+ bool xoutenb;
+ /** Specifies if device is a modem (POSIX). If not set modem status
+ lines are ignored. */
+ bool modem;
+ /** Enable/disable receiver (POSIX). */
+ bool rcvenb;
+ /** Controls whether DSR is disabled or enabled (Win32). */
+ bool dsrenb;
+ /** Controls whether DTR is disabled or enabled. */
+ bool dtrdisable;
+ /** Data bits. Valid values 5, 6, 7 and 8 data bits.
+ Additionally Win32 supports 4 data bits. */
+ unsigned char databits;
+ /** Stop bits. Valid values are 1 and 2. */
+ unsigned char stopbits;
+ };
+
+ /** 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 */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TTY_IO_H */
diff --git a/ACE/ace/Task.cpp b/ACE/ace/Task.cpp
new file mode 100644
index 00000000000..d928bced6f4
--- /dev/null
+++ b/ACE/ace/Task.cpp
@@ -0,0 +1,299 @@
+// $Id$
+
+#include "ace/Task.h"
+#include "ace/Module.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Task.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Task,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Task_Base::ACE_Task_Base (ACE_Thread_Manager *thr_man)
+ : thr_count_ (0),
+ thr_mgr_ (thr_man),
+ flags_ (0),
+ grp_id_ (-1)
+#if !(defined (ACE_MVS) || defined(__TANDEM))
+ ,last_thread_id_ (0)
+#endif /* !defined (ACE_MVS) */
+{
+#if (defined (ACE_MVS) || defined(__TANDEM))
+ ACE_OS::memset( &this->last_thread_id_, '\0', sizeof( this->last_thread_id_ ));
+#endif /* defined (ACE_MVS) */
+}
+
+ACE_Task_Base::~ACE_Task_Base (void)
+{
+}
+
+// Default ACE_Task service routine
+
+int
+ACE_Task_Base::svc (void)
+{
+ ACE_TRACE ("ACE_Task_Base::svc");
+ return 0;
+}
+
+// Default ACE_Task open routine
+
+int
+ACE_Task_Base::open (void *)
+{
+ ACE_TRACE ("ACE_Task_Base::open");
+ return 0;
+}
+
+// Default ACE_Task close routine
+
+int
+ACE_Task_Base::close (u_long)
+{
+ ACE_TRACE ("ACE_Task_Base::close");
+ return 0;
+}
+
+// Forward the call to close() so that existing applications don't
+// break.
+
+int
+ACE_Task_Base::module_closed (void)
+{
+ return this->close (1);
+}
+
+// Default ACE_Task put routine.
+
+int
+ACE_Task_Base::put (ACE_Message_Block *, ACE_Time_Value *)
+{
+ ACE_TRACE ("ACE_Task_Base::put");
+ return 0;
+}
+
+// Wait for all threads running in a task to exit.
+
+int
+ACE_Task_Base::wait (void)
+{
+ ACE_TRACE ("ACE_Task_Base::wait");
+
+ // If we don't have a thread manager, we probably were never
+ // activated.
+ if (this->thr_mgr () != 0)
+ return this->thr_mgr ()->wait_task (this);
+ else
+ return 0;
+}
+
+// Suspend a task.
+int
+ACE_Task_Base::suspend (void)
+{
+ ACE_TRACE ("ACE_Task_Base::suspend");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+ if (this->thr_count_ > 0)
+ return this->thr_mgr_->suspend_task (this);
+
+ return 0;
+}
+
+// Resume a suspended task.
+int
+ACE_Task_Base::resume (void)
+{
+ ACE_TRACE ("ACE_Task_Base::resume");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+ if (this->thr_count_ > 0)
+ return this->thr_mgr_->resume_task (this);
+
+ return 0;
+}
+
+int
+ACE_Task_Base::activate (long flags,
+ int n_threads,
+ int force_active,
+ long priority,
+ int grp_id,
+ ACE_Task_Base *task,
+ ACE_hthread_t thread_handles[],
+ void *stack[],
+ size_t stack_size[],
+ ACE_thread_t thread_ids[],
+ const char* thr_name[])
+{
+ ACE_TRACE ("ACE_Task_Base::activate");
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
+
+ // If the task passed in is zero, we will use <this>
+ if (task == 0)
+ task = this;
+
+ if (this->thr_count_ > 0 && force_active == 0)
+ return 1; // Already active.
+ else
+ {
+ if (this->thr_count_ > 0 && this->grp_id_ != -1)
+ // If we're joining an existing group of threads then make
+ // sure to use its group id.
+ grp_id = this->grp_id_;
+ this->thr_count_ += n_threads;
+ }
+
+ // Use the ACE_Thread_Manager singleton if we're running as an
+ // active object and the caller didn't supply us with a
+ // Thread_Manager.
+ if (this->thr_mgr_ == 0)
+# if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
+ this->thr_mgr_ = ACE_THREAD_MANAGER_SINGLETON::instance ();
+# else /* ! ACE_THREAD_MANAGER_LACKS_STATICS */
+ this->thr_mgr_ = ACE_Thread_Manager::instance ();
+# endif /* ACE_THREAD_MANAGER_LACKS_STATICS */
+
+ int grp_spawned = -1;
+ if (thread_ids == 0)
+ // Thread Ids were not specified
+ grp_spawned =
+ this->thr_mgr_->spawn_n (n_threads,
+ &ACE_Task_Base::svc_run,
+ (void *) this,
+ flags,
+ priority,
+ grp_id,
+ task,
+ thread_handles,
+ stack,
+ stack_size,
+ thr_name);
+ else
+ // thread names were specified
+ grp_spawned =
+ this->thr_mgr_->spawn_n (thread_ids,
+ n_threads,
+ &ACE_Task_Base::svc_run,
+ (void *) this,
+ flags,
+ priority,
+ grp_id,
+ stack,
+ stack_size,
+ thread_handles,
+ task,
+ thr_name);
+ if (grp_spawned == -1)
+ {
+ // If spawn_n fails, restore original thread count.
+ this->thr_count_ -= n_threads;
+ return -1;
+ }
+
+ if (this->grp_id_ == -1)
+ this->grp_id_ = grp_spawned;
+
+#if defined (ACE_MVS) || defined(__TANDEM)
+ ACE_OS::memcpy( &this->last_thread_id_, '\0', sizeof(this->last_thread_id_));
+#else
+ this->last_thread_id_ = 0; // Reset to prevent inadvertant match on ID
+#endif /* defined (ACE_MVS) */
+
+ return 0;
+
+#else
+ {
+ // Keep the compiler from complaining.
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (n_threads);
+ ACE_UNUSED_ARG (force_active);
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (grp_id);
+ ACE_UNUSED_ARG (task);
+ ACE_UNUSED_ARG (thread_handles);
+ ACE_UNUSED_ARG (stack);
+ ACE_UNUSED_ARG (stack_size);
+ ACE_UNUSED_ARG (thread_ids);
+ ACE_UNUSED_ARG (thr_name);
+ ACE_NOTSUP_RETURN (-1);
+ }
+#endif /* ACE_MT_SAFE */
+}
+
+void
+ACE_Task_Base::cleanup (void *object, void *)
+{
+ ACE_Task_Base *t = (ACE_Task_Base *) object;
+
+ // The thread count must be decremented first in case the <close>
+ // hook does something crazy like "delete this".
+ {
+ ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, t->lock_));
+ t->thr_count_--;
+ if (0 == t->thr_count_)
+ t->last_thread_id_ = ACE_Thread::self ();
+ }
+
+ // @@ Is it possible to pass in the exit status somehow?
+ t->close ();
+ // t is undefined here. close() could have deleted it.
+}
+
+
+#if defined (ACE_HAS_SIG_C_FUNC)
+extern "C" void
+ACE_Task_Base_cleanup (void *object, void *)
+{
+ ACE_Task_Base::cleanup (object, 0);
+}
+#endif /* ACE_HAS_SIG_C_FUNC */
+
+ACE_THR_FUNC_RETURN
+ACE_Task_Base::svc_run (void *args)
+{
+ ACE_TRACE ("ACE_Task_Base::svc_run");
+
+ ACE_Task_Base *t = (ACE_Task_Base *) args;
+
+ // Register ourself with our <Thread_Manager>'s thread exit hook
+ // mechanism so that our close() hook will be sure to get invoked
+ // when this thread exits.
+
+#if defined ACE_HAS_SIG_C_FUNC
+ t->thr_mgr ()->at_exit (t, ACE_Task_Base_cleanup, 0);
+#else
+ t->thr_mgr ()->at_exit (t, ACE_Task_Base::cleanup, 0);
+#endif /* ACE_HAS_SIG_C_FUNC */
+
+ // Call the Task's svc() hook method.
+ int const svc_status = t->svc ();
+ ACE_THR_FUNC_RETURN status;
+#if defined (ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN)
+ // Reinterpret case between integral types is not mentioned in the C++ spec
+ status = static_cast<ACE_THR_FUNC_RETURN> (svc_status);
+#else
+ status = reinterpret_cast<ACE_THR_FUNC_RETURN> (svc_status);
+#endif /* ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN */
+
+// If we changed this zero change the other if in OS.cpp Thread_Adapter::invoke
+#if 1
+ // Call the <Task->close> hook.
+ ACE_Thread_Manager *thr_mgr_ptr = t->thr_mgr ();
+
+ // This calls the Task->close () hook.
+ t->cleanup (t, 0);
+
+ // This prevents a second invocation of the cleanup code
+ // (called later by <ACE_Thread_Manager::exit>.
+ thr_mgr_ptr->at_exit (t, 0, 0);
+#endif
+ return status;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Task.h b/ACE/ace/Task.h
new file mode 100644
index 00000000000..757cf651323
--- /dev/null
+++ b/ACE/ace/Task.h
@@ -0,0 +1,307 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Task.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TASK_H
+#define ACE_TASK_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Service_Object.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Thread_Manager.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Task_Flags
+ *
+ * @brief These flags are used within the ACE_Task.
+ *
+ * These flags should be hidden within ACE_Task. Unfortunately, the
+ * HP/UX C++ compiler can't grok this... Fortunately, there's no
+ * code defined here, so we don't have to worry about multiple
+ * definitions.
+ */
+namespace ACE_Task_Flags
+{
+ enum
+ {
+ /// Identifies a Task as being the "reader" in a Module.
+ ACE_READER = 01,
+ /// Just flush data messages in the queue.
+ ACE_FLUSHDATA = 02,
+ /// Flush all messages in the Queue.
+ ACE_FLUSHALL = 04,
+ /// Flush read queue
+ ACE_FLUSHR = 010,
+ /// Flush write queue
+ ACE_FLUSHW = 020,
+ /// Flush both queues
+ ACE_FLUSHRW = 030
+ };
+}
+
+/**
+ * @class ACE_Task_Base
+ *
+ * @brief Direct base class for the ACE_Task template.
+ *
+ * This class factors out the non-template code in order to
+ * reduce template bloat, as well as to make it possible for the
+ * ACE_Thread_Manager to store ACE_Task_Base *'s
+ * polymorphically.
+ */
+class ACE_Export ACE_Task_Base : public ACE_Service_Object
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Task_Base (ACE_Thread_Manager * = 0);
+
+ /// Destructor.
+ virtual ~ACE_Task_Base (void);
+
+ // = Initialization and termination hooks.
+
+ // These methods should be overridden by subclasses if you'd like to
+ // provide <Task>-specific initialization and termination behavior.
+
+ /// Hook called to initialize a task and prepare it for execution.
+ /// @a args can be used to pass arbitrary information into <open>.
+ virtual int open (void *args = 0);
+
+ /**
+ * Hook called from ACE_Thread_Exit when during thread exit and from
+ * the default implementation of <module_closed>. In general, this
+ * method shouldn't be called directly by an application,
+ * particularly if the <Task> is running as an Active Object.
+ * Instead, a special message should be passed into the <Task> via
+ * the <put> method defined below, and the <svc> method should
+ * interpret this as a flag to shut down the <Task>.
+ */
+ virtual int close (u_long flags = 0);
+
+ /**
+ * Hook called during <ACE_Module::close>. The default
+ * implementation calls forwards the call to close(1). Please
+ * notice the changed value of the default argument of <close>.
+ * This allows tasks to differ between the call has been originated
+ * from <ACE_Thread_Exit> or from <module_closed>. Be aware that
+ * close(0) will be also called when a thread associated with the
+ * ACE_Task instance exits.
+ */
+ virtual int module_closed (void);
+
+ // = Immediate and deferred processing methods, respectively.
+
+ // These methods should be overridden by subclasses if you'd like to
+ // provide <Task>-specific message processing behavior.
+
+ /// A hook method that can be used to pass a message to a
+ /// task, where it can be processed immediately or queued for subsequent
+ /// processing in the <svc> hook method.
+ virtual int put (ACE_Message_Block *, ACE_Time_Value * = 0);
+
+ /// Run by a daemon thread to handle deferred processing.
+ virtual int svc (void);
+
+ // = Active object activation method.
+ /**
+ * Turn the task into an active object, i.e., having @a n_threads of
+ * control, all running at the @a priority level (see below) with the
+ * same @a grp_id, all of which invoke <Task::svc>. Returns -1 if
+ * failure occurs, returns 1 if Task is already an active object and
+ * @a force_active is false (i.e., do *not* create a new thread in
+ * this case), and returns 0 if Task was not already an active
+ * object and a thread is created successfully or thread is an
+ * active object and @a force_active is true. Note that if
+ * @a force_active is true and there are already threads spawned in
+ * this <Task>, the @a grp_id parameter is ignored and the @a grp_id
+ * of any newly activated thread(s) will inherit the existing
+ * @a grp_id of the existing thread(s) in the <Task>.
+ *
+ * The <{flags}> are a bitwise-OR of the following:
+ * = BEGIN<INDENT>
+ * THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED,
+ * THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED,
+ * THR_SUSPENDED, THR_DAEMON, THR_JOINABLE, THR_SCHED_FIFO,
+ * THR_SCHED_RR, THR_SCHED_DEFAULT, THR_EXPLICIT_SCHED,
+ * THR_SCOPE_SYSTEM, THR_SCOPE_PROCESS
+ * = END<INDENT>
+ * If THR_SCHED_INHERIT is not desirable, applications should
+ * specifically pass in THR_EXPLICIT_SCHED.
+ *
+ *
+ * By default, or if <{priority}> is set to
+ * ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for
+ * the given scheduling policy (specified in <{flags}>, e.g.,
+ * <THR_SCHED_DEFAULT>) is used. This value is calculated
+ * dynamically, and is the median value between the minimum and
+ * maximum priority values for the given policy. If an explicit
+ * value is given, it is used. Note that actual priority values are
+ * EXTREMEMLY implementation-dependent, and are probably best
+ * avoided.
+ *
+ * If @a thread_handles != 0 it is assumed to be an array of @a n
+ * thread_handles that will be assigned the values of the thread
+ * handles being spawned. Returns -1 on failure (@c errno will
+ * explain...), otherwise returns the group id of the threads.
+ *
+ * Assigning @a task allows you to associate the newly spawned
+ * threads with an instance of ACE_Task_Base. If @a task == 0, then
+ * the new threads are associated automatically with @c this
+ * ACE_Task_Base. Setting the @a task argument to value other than
+ * @c this makes the thread manipulating methods, such as wait(),
+ * suspend(), resume(), useless. Threads spawned with user
+ * specified @a task value must therefore be manipulated thru
+ * ACE_Thread_Manager directly.
+ *
+ * If @a stack != 0 it is assumed to be an array of @a n pointers to
+ * the base of the stacks to use for the threads being spawned.
+ * Likewise, if @a stack_size != 0 it is assumed to be an array of
+ * @a n values indicating how big each of the corresponding @a stacks
+ * are.
+ *
+ *
+ */
+ virtual int activate (long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED,
+ int n_threads = 1,
+ int force_active = 0,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ int grp_id = -1,
+ ACE_Task_Base *task = 0,
+ ACE_hthread_t thread_handles[] = 0,
+ void *stack[] = 0,
+ size_t stack_size[] = 0,
+ ACE_thread_t thread_ids[] = 0,
+ const char* thr_name[] = 0);
+
+ /**
+ * Block until there are no more threads running in this task.
+ * This method will not wait for either detached or daemon threads;
+ * the threads must have been spawned with the @c THR_JOINABLE flag.
+ * Upon successful completion, the threads have been joined, so further
+ * attempts to join with any of the waited-for threads will fail.
+ *
+ * @retval 0 Success.
+ * @retval -1 Failure (consult errno for further information).
+ */
+ virtual int wait (void);
+
+ // = Suspend/resume a Task.
+
+ // Note that these methods are not portable and should be avoided
+ // since they are inherently error-prone to use. They are only here
+ // for (the rare) applications that know how to use them correctly.
+ /// Suspend a task.
+ virtual int suspend (void);
+ /// Resume a suspended task.
+ virtual int resume (void);
+
+ /// Get the current group id.
+ int grp_id (void) const;
+
+ /// Set the current group id.
+ void grp_id (int);
+
+ /// Get the thread manager associated with this Task.
+ ACE_Thread_Manager *thr_mgr (void) const;
+
+ /// Set the thread manager associated with this Task.
+ void thr_mgr (ACE_Thread_Manager *);
+
+ /// True if queue is a reader, else false.
+ int is_reader (void) const;
+
+ /// True if queue is a writer, else false.
+ int is_writer (void) const;
+
+ /**
+ * Returns the number of threads currently running within a task.
+ * If we're a passive object this value is 0, else it's greater than
+ * 0.
+ */
+ size_t thr_count (void) const;
+
+ /**
+ * Returns the thread ID of the thread whose exit caused this object's
+ * thread count to be decremented to 0.
+ *
+ * When a thread spawned in the context of this object (using activate())
+ * returns from its svc() method ACE calls the close() hook. Before it does
+ * so, it decrements the number of active threads. If the number of threads
+ * is decremented to 0, the thread ID of the current thread is stored for
+ * access by this method. If the returned thread ID matches the calling
+ * thread's ID, the calling thread knows that there are no other threads
+ * still active in the ACE_Task.
+ *
+ * @retval ACE_thread_t of the last thread to close. 0 if the last thread
+ * is not yet known; for example, if no threads are active, or if
+ * multiple threads are active.
+ */
+ ACE_thread_t last_thread (void) const;
+
+ /// Routine that runs the service routine as a daemon thread.
+ static ACE_THR_FUNC_RETURN svc_run (void *);
+
+ /// Cleanup hook that is called when a thread exits to gracefully
+ /// shutdown an ACE_Task.
+ static void cleanup (void *object, void *params);
+
+protected:
+ /**
+ * Count of the number of threads running within the task. If this
+ * value is greater than 0 then we're an active object and the value
+ * of <thr_count_> is the number of active threads at this instant.
+ * If the value == 0, then we're a passive object.
+ */
+ size_t thr_count_;
+
+ /// Multi-threading manager.
+ ACE_Thread_Manager *thr_mgr_;
+
+ /// ACE_Task flags.
+ u_long flags_;
+
+ /// This maintains the group id of the Task.
+ int grp_id_;
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ /// Protect the state of a Task during concurrent operations, but
+ /// only if we're configured as MT safe...
+ ACE_Thread_Mutex lock_;
+#endif /* ACE_MT_SAFE */
+
+ /// Holds the thread ID of the last thread to exit svc() in this object.
+ ACE_thread_t last_thread_id_;
+
+private:
+
+ // = Disallow these operations.
+ ACE_Task_Base &operator= (const ACE_Task_Base &);
+ ACE_Task_Base (const ACE_Task_Base &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Task.inl"
+#endif /* __ACE_INLINE__ */
+
+// Include the ACE_Task templates classes at this point.
+#include "ace/Task_T.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TASK_H */
diff --git a/ACE/ace/Task.inl b/ACE/ace/Task.inl
new file mode 100644
index 00000000000..2430651ccc5
--- /dev/null
+++ b/ACE/ace/Task.inl
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Get the current group id.
+ACE_INLINE int
+ACE_Task_Base::grp_id (void) const
+{
+ ACE_TRACE ("ACE_Task_Base::grp_id");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, const_cast <ACE_Thread_Mutex&>(this->lock_), -1));
+ return this->grp_id_;
+}
+
+// Set the current group id.
+
+ACE_INLINE void
+ACE_Task_Base::grp_id (int identifier)
+{
+ ACE_TRACE ("ACE_Task_Base::grp_id");
+ ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_));
+
+ // Cache the group id in the task and then set it in the
+ // Thread_Manager, if there is one.
+ this->grp_id_ = identifier;
+ if (this->thr_mgr ())
+ this->thr_mgr ()->set_grp (this, identifier);
+}
+
+ACE_INLINE ACE_Thread_Manager *
+ACE_Task_Base::thr_mgr (void) const
+{
+ ACE_TRACE ("ACE_Task_Base::thr_mgr");
+ return this->thr_mgr_;
+}
+
+ACE_INLINE void
+ACE_Task_Base::thr_mgr (ACE_Thread_Manager *thr_mgr)
+{
+ ACE_TRACE ("ACE_Task_Base::thr_mgr");
+ this->thr_mgr_ = thr_mgr;
+}
+
+ACE_INLINE int
+ACE_Task_Base::is_reader (void) const
+{
+ ACE_TRACE ("ACE_Task_Base::is_reader");
+ return (ACE_BIT_ENABLED (this->flags_, ACE_Task_Flags::ACE_READER));
+}
+
+ACE_INLINE int
+ACE_Task_Base::is_writer (void) const
+{
+ ACE_TRACE ("ACE_Task_Base::is_writer");
+ return (ACE_BIT_DISABLED (this->flags_, ACE_Task_Flags::ACE_READER));
+}
+
+// Return the count of the current number of threads.
+ACE_INLINE size_t
+ACE_Task_Base::thr_count (void) const
+{
+ ACE_TRACE ("ACE_Task_Base::thr_count");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, const_cast <ACE_Thread_Mutex&>(this->lock_), 0));
+
+ return this->thr_count_;
+}
+
+// Return the thread ID of the last thread to exit svc().
+ACE_INLINE ACE_thread_t
+ACE_Task_Base::last_thread (void) const
+{
+ ACE_TRACE ("ACE_Task_Base::last_thread");
+ return this->last_thread_id_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Task_Ex_T.cpp b/ACE/ace/Task_Ex_T.cpp
new file mode 100644
index 00000000000..1a3848d6ccb
--- /dev/null
+++ b/ACE/ace/Task_Ex_T.cpp
@@ -0,0 +1,114 @@
+// $Id$
+
+#ifndef ACE_TASK_EX_T_CPP
+#define ACE_TASK_EX_T_CPP
+
+#include "ace/Task_Ex_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Module.h"
+#include "ace/Null_Condition.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Task_Ex_T.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> void
+ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_mgr_ = %x"), this->thr_mgr_));
+ this->msg_queue_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_msg_queue_ = %d\n"), this->delete_msg_queue_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags = %x"), this->flags_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmod_ = %x"), this->mod_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnext_ = %x"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ngrp_id_ = %d"), this->grp_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_count_ = %d"), this->thr_count_));
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ this->lock_.dump ();
+#endif /* ACE_MT_SAFE */
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// If the user doesn't supply a ACE_Message_Queue_Ex pointer then we'll
+// allocate one dynamically. Otherwise, we'll use the one they give.
+
+template<ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE>
+ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::ACE_Task_Ex (ACE_Thread_Manager *thr_man,
+ ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE> *mq)
+ : ACE_Task_Base (thr_man),
+ msg_queue_ (0),
+ delete_msg_queue_ (false),
+ mod_ (0),
+ next_ (0)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::ACE_Task_Ex");
+
+ if (mq == 0)
+ {
+ ACE_NEW (mq,
+ (ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>));
+ this->delete_msg_queue_ = true;
+ }
+
+ this->msg_queue_ = mq;
+}
+
+template<ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE>
+ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::~ACE_Task_Ex (void)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::~ACE_Task_Ex");
+ if (this->delete_msg_queue_)
+ delete this->msg_queue_;
+
+ // These assignments aren't strickly necessary but they help guard
+ // against odd race conditions...
+ this->delete_msg_queue_ = false;
+}
+
+template<ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_Task<ACE_SYNCH_USE> *
+ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::sibling (void)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::sibling");
+ /// @todo FIXME Need to impl ACE_Moudle to support ACE_Task as well.
+ /// Now always return 0 for sibling
+ return 0;
+/*
+ if (this->mod_ == 0)
+ return 0;
+ else
+ return this->mod_->sibling (this);
+*/
+}
+
+template<ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> const ACE_TCHAR *
+ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::name (void) const
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::name");
+ if (this->mod_ == 0)
+ return 0;
+ else
+ return this->mod_->name ();
+}
+
+template<ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_Module<ACE_SYNCH_USE> *
+ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::module (void) const
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE>::module");
+ return this->mod_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TASK_EX_T_CPP */
diff --git a/ACE/ace/Task_Ex_T.h b/ACE/ace/Task_Ex_T.h
new file mode 100644
index 00000000000..090ac7a18a0
--- /dev/null
+++ b/ACE/ace/Task_Ex_T.h
@@ -0,0 +1,205 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Task_Ex_T.h
+ *
+ * $Id$
+ *
+ * @author Kobi Cohen-Arazi <kobi-co@barak-online.net>
+ */
+//=============================================================================
+
+#ifndef ACE_TASK_EX_T_H
+#define ACE_TASK_EX_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Service_Object.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch_Traits.h"
+#include "ace/Task.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls...
+template <ACE_SYNCH_DECL> class ACE_Module;
+
+/**
+ * @class ACE_Task_Ex
+ *
+ * @brief Primary interface for application message processing, as well
+ * as input and output message queueing.
+ *
+ * Unlike ACE_Task, these class doesn't have the ability to be a part of
+ * a Stream chain. I.e. You cannot (yet) chain modules based on ACE_Task_Ex.
+ *
+ * @todo: We can merge ACE_Task and ACE_Task_Ex to be one class.
+ * something like that:
+ * template <ACE_SYNCH_DECL, ACE_MESSAGE_TYPE = ACE_Message_Block>
+ * class ACE_Task : public ACE_Task_Base
+ * {
+ * // use here the code from ACE_Task_Ex using ACE_Message_Queue_Ex
+ * };
+ *
+ * Now specialized version of ACE_Task with ACE_Message_Block as its
+ * ACE_MESSAGE_TYPE...
+ *
+ * template <ACE_SYNCH_DECL>
+ * class ACE_Task <ACE_SYNCH_USE, ACE_Message_Block> : public ACE_Task_Base
+ * {
+ * // put here the good old ACE_Task code
+ * };
+ *
+ * When User (and legacy code) write ACE_Task<ACE_MT_SYNCH>, specialized ACE_Task
+ * code is in action.
+ */
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE>
+class ACE_Task_Ex : public ACE_Task_Base
+{
+public:
+ friend class ACE_Module<ACE_SYNCH_USE>;
+ friend class ACE_Module_Type;
+ typedef ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE> MESSAGE_QUEUE_EX;
+
+ // = Initialization/termination methods.
+ /**
+ * Initialize a Task, supplying a thread manager and a message
+ * queue. If the user doesn't supply a ACE_Message_Queue pointer
+ * then we'll allocate one dynamically. Otherwise, we'll use the
+ * one passed as a parameter.
+ */
+ ACE_Task_Ex (ACE_Thread_Manager *thr_mgr = 0,
+ MESSAGE_QUEUE_EX *mq = 0);
+
+ /// Destructor.
+ virtual ~ACE_Task_Ex (void);
+
+ /// Gets the message queue associated with this task.
+ MESSAGE_QUEUE_EX *msg_queue (void);
+
+ /// Sets the message queue associated with this task.
+ void msg_queue (MESSAGE_QUEUE_EX *);
+
+public: // Should be protected:
+ // = Message queue manipulation methods.
+
+ // = Enqueue and dequeue methods.
+
+ // For the following five method if @a timeout == 0, the caller will
+ // block until action is possible, else will wait until the
+ // <{absolute}> time specified in *@a timeout elapses). These calls
+ // will return, however, when queue is closed, deactivated, when a
+ // signal occurs, or if the time specified in timeout elapses, (in
+ // which case errno = EWOULDBLOCK).
+
+ /// Insert message into the message queue. Note that @a timeout uses
+ /// <{absolute}> time rather than <{relative}> time.
+ int putq (ACE_MESSAGE_TYPE *, ACE_Time_Value *timeout = 0);
+
+ /**
+ * Extract the first message from the queue (blocking). Note that
+ * @a timeout uses <{absolute}> time rather than <{relative}> time.
+ * Returns number of items in queue if the call succeeds or -1 otherwise.
+ */
+ int getq (ACE_MESSAGE_TYPE *&mb, ACE_Time_Value *timeout = 0);
+
+ /// Return a message to the queue. Note that @a timeout uses
+ /// <{absolute}> time rather than <{relative}> time.
+ int ungetq (ACE_MESSAGE_TYPE *, ACE_Time_Value *timeout = 0);
+
+ /**
+ * Turn the message around and send it back down the Stream. Note
+ * that @a timeout uses <{absolute}> time rather than <{relative}>
+ * time.
+ */
+ int reply (ACE_MESSAGE_TYPE *, ACE_Time_Value *timeout = 0);
+
+ /**
+ * Transfer message to the adjacent ACE_Task_Ex in a ACE_Stream. Note
+ * that @a timeout uses <{absolute}> time rather than <{relative}>
+ * time.
+ */
+ int put_next (ACE_MESSAGE_TYPE *msg, ACE_Time_Value *timeout = 0);
+
+ /**
+ * Tests whether we can enqueue a message without blocking.
+ * @deprecated This method is deprecated and will go away in the future.
+ */
+ int can_put (ACE_MESSAGE_TYPE *);
+
+ // = ACE_Task utility routines to identify names et al.
+ /// Return the name of the enclosing Module if there's one associated
+ /// with the Task, else returns 0.
+ const ACE_TCHAR *name (void) const;
+
+ // = Pointers to next ACE_Task_Base (if ACE is part of an ACE_Stream).
+ /// Get next Task pointer.
+ ACE_Task<ACE_SYNCH_USE> *next (void);
+
+ /// Set next Task pointer.
+ void next (ACE_Task<ACE_SYNCH_USE> *);
+
+ /// Alwasy return 0. @todo FIXME
+ ACE_Task<ACE_SYNCH_USE> *sibling (void);
+
+ /// Return the Task's Module if there is one, else returns 0.
+ ACE_Module<ACE_SYNCH_USE> *module (void) const;
+
+ /**
+ * Flush the task's queue, i.e., free all of the enqueued
+ * message blocks and releases any threads blocked on the queue.
+ * Note that if this conflicts with the C++ iostream <flush>
+ * function, just rewrite the iostream function as ::<flush>.
+ */
+ int flush (u_long flag = ACE_Task_Flags::ACE_FLUSHALL);
+
+ // = Special routines corresponding to certain message types.
+
+ /// Manipulate watermarks.
+ void water_marks (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds, size_t);
+
+ /// Queue of messages on the ACE_Task..
+ MESSAGE_QUEUE_EX *msg_queue_;
+
+ /// true if should delete Message_Queue, false otherwise.
+ bool delete_msg_queue_;
+
+ /// Back-pointer to the enclosing module.
+ ACE_Module<ACE_SYNCH_USE> *mod_;
+
+ /// Pointer to adjacent ACE_Task.
+ ACE_Task<ACE_SYNCH_USE> *next_;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Task_Ex (const ACE_Task_Ex<ACE_SYNCH_USE, ACE_MESSAGE_TYPE> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Task_Ex_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Task_Ex_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Task_Ex_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TASK_EX_H */
diff --git a/ACE/ace/Task_Ex_T.inl b/ACE/ace/Task_Ex_T.inl
new file mode 100644
index 00000000000..ee0843978b3
--- /dev/null
+++ b/ACE/ace/Task_Ex_T.inl
@@ -0,0 +1,109 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE void
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::water_marks (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd,
+ size_t wm_size)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::water_marks");
+ if (cmd == ACE_IO_Cntl_Msg::SET_LWM)
+ this->msg_queue_->low_water_mark (wm_size);
+ else /* cmd == ACE_IO_Cntl_Msg::SET_HWM */
+ this->msg_queue_->high_water_mark (wm_size);
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE int
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::getq (ACE_MESSAGE_TYPE *&mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::getq");
+ return this->msg_queue_->dequeue_head (mb, tv);
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE int
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::can_put (ACE_MESSAGE_TYPE *)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::can_put");
+ ACE_NOTSUP_RETURN (-1);
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE int
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::putq (ACE_MESSAGE_TYPE *mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::putq");
+ return this->msg_queue_->enqueue_tail (mb, tv);
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE int
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::ungetq (ACE_MESSAGE_TYPE *mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::ungetq");
+ return this->msg_queue_->enqueue_head (mb, tv);
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE int
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::flush (u_long flag)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::flush");
+ if (ACE_BIT_ENABLED (flag, ACE_Task_Flags::ACE_FLUSHALL))
+ return this->msg_queue_ != 0 && this->msg_queue_->close ();
+ else
+ return -1; // Note, need to be more careful about what we free...
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE void
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::msg_queue (ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE> *mq)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::msg_queue");
+ if (this->delete_msg_queue_)
+ {
+ delete this->msg_queue_;
+ this->delete_msg_queue_ = false;
+ }
+ this->msg_queue_ = mq;
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE> *
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::msg_queue (void)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::msg_queue");
+ return this->msg_queue_;
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE int
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::reply (ACE_MESSAGE_TYPE *mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::reply");
+ ACE_UNUSED_ARG (mb);
+ ACE_UNUSED_ARG (tv);
+ return -1 ; // this->sibling ()->put_next (mb, tv);
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE ACE_Task<ACE_SYNCH_USE> *
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::next (void)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::next");
+ return this->next_;
+}
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE void
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::next (ACE_Task<ACE_SYNCH_USE> *q)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::next");
+ this->next_ = q;
+}
+
+// Transfer msg to the next ACE_Task_Ex.
+
+template <ACE_SYNCH_DECL, class ACE_MESSAGE_TYPE> ACE_INLINE int
+ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::put_next (
+ ACE_MESSAGE_TYPE * /* msg */,
+ ACE_Time_Value * /* tv */)
+{
+ ACE_TRACE ("ACE_Task_Ex<ACE_SYNCH_USE,ACE_MESSAGE_TYPE>::put_next");
+ return -1; // this->next_ == 0 ? -1 : this->next_->put (msg, tv);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Task_T.cpp b/ACE/ace/Task_T.cpp
new file mode 100644
index 00000000000..cb7010d0bda
--- /dev/null
+++ b/ACE/ace/Task_T.cpp
@@ -0,0 +1,108 @@
+// $Id$
+
+#ifndef ACE_TASK_T_CPP
+#define ACE_TASK_T_CPP
+
+#include "ace/Task_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Module.h"
+#include "ace/Null_Condition.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Task_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <ACE_SYNCH_DECL> void
+ACE_Task<ACE_SYNCH_USE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_mgr_ = %x"), this->thr_mgr_));
+ this->msg_queue_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_msg_queue_ = %d\n"), this->delete_msg_queue_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags = %x"), this->flags_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmod_ = %x"), this->mod_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnext_ = %x"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ngrp_id_ = %d"), this->grp_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_count_ = %d"), this->thr_count_));
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ this->lock_.dump ();
+#endif /* ACE_MT_SAFE */
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// If the user doesn't supply a ACE_Message_Queue pointer then we'll
+// allocate one dynamically. Otherwise, we'll use the one they give.
+
+template<ACE_SYNCH_DECL>
+ACE_Task<ACE_SYNCH_USE>::ACE_Task (ACE_Thread_Manager *thr_man,
+ ACE_Message_Queue<ACE_SYNCH_USE> *mq)
+ : ACE_Task_Base (thr_man),
+ msg_queue_ (0),
+ delete_msg_queue_ (false),
+ mod_ (0),
+ next_ (0)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::ACE_Task");
+
+ if (mq == 0)
+ {
+ ACE_NEW (mq,
+ ACE_Message_Queue<ACE_SYNCH_USE>);
+ this->delete_msg_queue_ = true;
+ }
+
+ this->msg_queue_ = mq;
+}
+
+template<ACE_SYNCH_DECL>
+ACE_Task<ACE_SYNCH_USE>::~ACE_Task (void)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::~ACE_Task");
+ if (this->delete_msg_queue_)
+ delete this->msg_queue_;
+
+ // These assignments aren't strickly necessary but they help guard
+ // against odd race conditions...
+ this->delete_msg_queue_ = false;
+}
+
+template<ACE_SYNCH_DECL> ACE_Task<ACE_SYNCH_USE> *
+ACE_Task<ACE_SYNCH_USE>::sibling (void)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::sibling");
+ if (this->mod_ == 0)
+ return 0;
+ else
+ return this->mod_->sibling (this);
+}
+
+template<ACE_SYNCH_DECL> const ACE_TCHAR *
+ACE_Task<ACE_SYNCH_USE>::name (void) const
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::name");
+ if (this->mod_ == 0)
+ return 0;
+ else
+ return this->mod_->name ();
+}
+
+template<ACE_SYNCH_DECL> ACE_Module<ACE_SYNCH_USE> *
+ACE_Task<ACE_SYNCH_USE>::module (void) const
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::module");
+ return this->mod_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TASK_T_CPP */
diff --git a/ACE/ace/Task_T.h b/ACE/ace/Task_T.h
new file mode 100644
index 00000000000..26b5fc252f4
--- /dev/null
+++ b/ACE/ace/Task_T.h
@@ -0,0 +1,198 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Task_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TASK_T_H
+#define ACE_TASK_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Message_Queue.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch_Traits.h"
+#include "ace/Task.h"
+#include "ace/IO_Cntl_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls...
+template <ACE_SYNCH_DECL> class ACE_Module;
+
+/**
+ * @class ACE_Task
+ *
+ * @brief Primary interface for application message processing, as well
+ * as input and output message queueing.
+ *
+ * This class serves as the basis for passive and active objects
+ * in ACE.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Task : public ACE_Task_Base
+{
+public:
+ friend class ACE_Module<ACE_SYNCH_USE>;
+ friend class ACE_Module_Type;
+
+ // = Initialization/termination methods.
+ /**
+ * Initialize a Task, supplying a thread manager and a message
+ * queue. If the user doesn't supply a ACE_Message_Queue pointer
+ * then we'll allocate one dynamically. Otherwise, we'll use the
+ * one passed as a parameter.
+ */
+ ACE_Task (ACE_Thread_Manager *thr_mgr = 0,
+ ACE_Message_Queue<ACE_SYNCH_USE> *mq = 0);
+
+ /// Destructor.
+ virtual ~ACE_Task (void);
+
+ /// Gets the message queue associated with this task.
+ ACE_Message_Queue<ACE_SYNCH_USE> *msg_queue (void);
+
+ /// Sets the message queue associated with this task.
+ void msg_queue (ACE_Message_Queue<ACE_SYNCH_USE> *);
+
+public: // Should be protected:
+ // = Message queue manipulation methods.
+
+ // = Enqueue and dequeue methods.
+
+ // For the following five method if @a timeout == 0, the caller will
+ // block until action is possible, else will wait until the
+ // <{absolute}> time specified in *@a timeout elapses). These calls
+ // will return, however, when queue is closed, deactivated, when a
+ // signal occurs, or if the time specified in timeout elapses, (in
+ // which case errno = EWOULDBLOCK).
+
+ /// Insert message into the message queue. Note that @a timeout uses
+ /// <{absolute}> time rather than <{relative}> time.
+ int putq (ACE_Message_Block *, ACE_Time_Value *timeout = 0);
+
+ /**
+ * Extract the first message from the queue (blocking). Note that
+ * @a timeout uses <{absolute}> time rather than <{relative}> time.
+ * Returns number of items in queue if the call succeeds or -1 otherwise.
+ */
+ int getq (ACE_Message_Block *&mb, ACE_Time_Value *timeout = 0);
+
+ /// Return a message to the queue. Note that @a timeout uses
+ /// <{absolute}> time rather than <{relative}> time.
+ int ungetq (ACE_Message_Block *, ACE_Time_Value *timeout = 0);
+
+ /**
+ * Turn the message around, sending it in the opposite direction in
+ * the stream. To do this, the message is put onto the task next in
+ * the stream after this task's sibling.
+ *
+ * @param ACE_Message_Block Pointer to the block that is used in the reply.
+ * @param timeout The absolute time at which the put operation used to
+ * send the message block to the next module in the stream
+ * will time out. If 0, this call blocks until it can be
+ * completed.
+ */
+ int reply (ACE_Message_Block *, ACE_Time_Value *timeout = 0);
+
+ /**
+ * Transfer message to the adjacent ACE_Task in a ACE_Stream. Note
+ * that @a timeout uses <{absolute}> time rather than <{relative}>
+ * time.
+ */
+ int put_next (ACE_Message_Block *msg, ACE_Time_Value *timeout = 0);
+
+ /**
+ * Tests whether we can enqueue a message without blocking.
+ *
+ * @deprecated This method is deprecated and will go away in the future.
+ */
+ int can_put (ACE_Message_Block *);
+
+ // = ACE_Task utility routines to identify names et al.
+ /// Return the name of the enclosing Module if there's one associated
+ /// with the Task, else returns 0.
+ const ACE_TCHAR *name (void) const;
+
+ // = Pointers to next ACE_Task_Base (if ACE is part of an ACE_Stream).
+ /// Get next Task pointer.
+ ACE_Task<ACE_SYNCH_USE> *next (void);
+
+ /// Set next Task pointer.
+ void next (ACE_Task<ACE_SYNCH_USE> *);
+
+ /// Return the Task's sibling if there's one associated with the
+ /// Task's Module, else returns 0.
+ ACE_Task<ACE_SYNCH_USE> *sibling (void);
+
+ /// Return the Task's Module if there is one, else returns 0.
+ ACE_Module<ACE_SYNCH_USE> *module (void) const;
+
+ /**
+ * Flush the task's queue, i.e., free all of the enqueued
+ * message blocks and unblocks any threads waiting on the queue.
+ * Note that if this conflicts with the C++ iostream <flush>
+ * function, just rewrite the iostream function as ::<flush>.
+ */
+ int flush (u_long flag = ACE_Task_Flags::ACE_FLUSHALL);
+
+ // = Special routines corresponding to certain message types.
+
+ /// Manipulate watermarks.
+ void water_marks (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds, size_t);
+
+ /// Queue of messages on the ACE_Task..
+ ACE_Message_Queue<ACE_SYNCH_USE> *msg_queue_;
+
+ /// true if should delete Message_Queue, false otherwise.
+ bool delete_msg_queue_;
+
+ /// Back-pointer to the enclosing module.
+ ACE_Module<ACE_SYNCH_USE> *mod_;
+
+ /// Pointer to adjacent ACE_Task.
+ ACE_Task<ACE_SYNCH_USE> *next_;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Task<ACE_SYNCH_USE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Task (const ACE_Task<ACE_SYNCH_USE> &))
+};
+
+#if defined ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT
+template class ACE_Export ACE_Task<ACE_MT_SYNCH>;
+template class ACE_Export ACE_Task<ACE_NULL_SYNCH>;
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Task_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Task_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Task_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TASK_T_H */
diff --git a/ACE/ace/Task_T.inl b/ACE/ace/Task_T.inl
new file mode 100644
index 00000000000..c3ab9cdfe99
--- /dev/null
+++ b/ACE/ace/Task_T.inl
@@ -0,0 +1,105 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <ACE_SYNCH_DECL> ACE_INLINE void
+ACE_Task<ACE_SYNCH_USE>::water_marks (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd,
+ size_t wm_size)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::water_marks");
+ if (cmd == ACE_IO_Cntl_Msg::SET_LWM)
+ this->msg_queue_->low_water_mark (wm_size);
+ else /* cmd == ACE_IO_Cntl_Msg::SET_HWM */
+ this->msg_queue_->high_water_mark (wm_size);
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Task<ACE_SYNCH_USE>::getq (ACE_Message_Block *&mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::getq");
+ return this->msg_queue_->dequeue_head (mb, tv);
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Task<ACE_SYNCH_USE>::can_put (ACE_Message_Block *)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::can_put");
+ ACE_NOTSUP_RETURN (-1);
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Task<ACE_SYNCH_USE>::putq (ACE_Message_Block *mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::putq");
+ return this->msg_queue_->enqueue_tail (mb, tv);
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Task<ACE_SYNCH_USE>::ungetq (ACE_Message_Block *mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::ungetq");
+ return this->msg_queue_->enqueue_head (mb, tv);
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Task<ACE_SYNCH_USE>::flush (u_long flag)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::flush");
+ if (ACE_BIT_ENABLED (flag, ACE_Task_Flags::ACE_FLUSHALL))
+ return this->msg_queue_ != 0 && this->msg_queue_->close ();
+ else
+ return -1; // Note, need to be more careful about what we free...
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE void
+ACE_Task<ACE_SYNCH_USE>::msg_queue (ACE_Message_Queue<ACE_SYNCH_USE> *mq)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::msg_queue");
+ if (this->delete_msg_queue_)
+ {
+ delete this->msg_queue_;
+ this->delete_msg_queue_ = false;
+ }
+ this->msg_queue_ = mq;
+}
+
+template <ACE_SYNCH_DECL> ACE_Message_Queue<ACE_SYNCH_USE> *
+ACE_Task<ACE_SYNCH_USE>::msg_queue (void)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::msg_queue");
+ return this->msg_queue_;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Task<ACE_SYNCH_USE>::reply (ACE_Message_Block *mb, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::reply");
+ return this->sibling ()->put_next (mb, tv);
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE ACE_Task<ACE_SYNCH_USE> *
+ACE_Task<ACE_SYNCH_USE>::next (void)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::next");
+ return this->next_;
+}
+
+template <ACE_SYNCH_DECL> ACE_INLINE void
+ACE_Task<ACE_SYNCH_USE>::next (ACE_Task<ACE_SYNCH_USE> *q)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::next");
+ this->next_ = q;
+}
+
+// Transfer msg to the next ACE_Task.
+
+template <ACE_SYNCH_DECL> ACE_INLINE int
+ACE_Task<ACE_SYNCH_USE>::put_next (ACE_Message_Block *msg, ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::put_next");
+ return this->next_ == 0 ? -1 : this->next_->put (msg, tv);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Test_and_Set.cpp b/ACE/ace/Test_and_Set.cpp
new file mode 100644
index 00000000000..ea420bbe508
--- /dev/null
+++ b/ACE/ace/Test_and_Set.cpp
@@ -0,0 +1,51 @@
+// $Id$
+
+#ifndef ACE_TEST_AND_SET_CPP
+#define ACE_TEST_AND_SET_CPP
+
+#include "ace/Test_and_Set.h"
+#include "ace/Guard_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_LOCK, class TYPE>
+ACE_Test_and_Set<ACE_LOCK, TYPE>::ACE_Test_and_Set (TYPE initial_value)
+ : is_set_ (initial_value)
+{
+}
+
+// Returns true if we are done, else false.
+template <class ACE_LOCK, class TYPE> TYPE
+ACE_Test_and_Set<ACE_LOCK, TYPE>::is_set (void) const
+{
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, (ACE_LOCK &) this->lock_, this->is_set_);
+ return this->is_set_;
+}
+
+// Sets the <is_set_> status.
+template <class ACE_LOCK, class TYPE> TYPE
+ACE_Test_and_Set<ACE_LOCK, TYPE>::set (TYPE status)
+{
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, this->is_set_);
+ TYPE o_status = this->is_set_;
+ this->is_set_ = status;
+ return o_status;
+}
+
+template <class ACE_LOCK, class TYPE> int
+ACE_Test_and_Set<ACE_LOCK, TYPE>::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ // By setting this to 1, we are "signaling" to anyone calling
+ // <is_set> or or <set> that the "test and set" object is in the
+ // "signaled" state, i.e., it's "available" to be set back to 0.
+ this->set (1);
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TEST_AND_SET_CPP */
diff --git a/ACE/ace/Test_and_Set.h b/ACE/ace/Test_and_Set.h
new file mode 100644
index 00000000000..d72c3d474b0
--- /dev/null
+++ b/ACE/ace/Test_and_Set.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Test_and_Set.h
+ *
+ * $Id$
+ */
+//=============================================================================
+
+
+#ifndef ACE_TEST_AND_SET_H
+#define ACE_TEST_AND_SET_H
+
+#include /**/ "ace/pre.h"
+#include "ace/Event_Handler.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Test_and_Set
+ *
+ * @brief Implements the classic ``test and set'' operation.
+ *
+ *
+ * This class keeps track of the status of <is_set_>, which can
+ * be set based on various events (such as receipt of a
+ * signal). This class is derived from ACE_Event_Handler so
+ * that it can be "signaled" by a Reactor when a signal occurs.
+ * We assume that <TYPE> is a data type that can be assigned the
+ * value 0 or 1.
+ */
+template <class ACE_LOCK, class TYPE>
+class ACE_Test_and_Set : public ACE_Event_Handler
+{
+public:
+ ACE_Test_and_Set (TYPE initial_value = 0);
+
+ /// Returns true if we are set, else false.
+ TYPE is_set (void) const;
+
+ /// Sets the <is_set_> status, returning the original value of
+ /// <is_set_>.
+ TYPE set (TYPE);
+
+ /// 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);
+
+private:
+ /// Keeps track of our state.
+ TYPE is_set_;
+
+ /// Protect the state from race conditions.
+ ACE_LOCK lock_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Test_and_Set.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Test_and_Set.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TEST_AND_SET_H */
diff --git a/ACE/ace/Thread.cpp b/ACE/ace/Thread.cpp
new file mode 100644
index 00000000000..fab00ea5e6b
--- /dev/null
+++ b/ACE/ace/Thread.cpp
@@ -0,0 +1,99 @@
+// $Id$
+
+#include "ace/Thread.h"
+
+ACE_RCSID(ace,
+ Thread,
+ "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Thread.inl"
+#endif /* !defined (__ACE_INLINE__) */
+
+#if defined (ACE_HAS_THREADS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+size_t
+ACE_Thread::spawn_n (size_t n,
+ ACE_THR_FUNC func,
+ void *arg,
+ long flags,
+ long priority,
+ void *stack[],
+ size_t stack_size[],
+ ACE_Thread_Adapter *thread_adapter,
+ const char* thr_name[])
+{
+ ACE_TRACE ("ACE_Thread::spawn_n");
+ ACE_thread_t t_id;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ // Bail out if error occurs.
+ if (ACE_OS::thr_create (func,
+ arg,
+ flags,
+ &t_id,
+ 0,
+ priority,
+ stack == 0 ? 0 : stack[i],
+ stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
+ thread_adapter,
+ thr_name == 0 ? 0 : &thr_name[i]) != 0)
+ break;
+
+ return i;
+}
+
+size_t
+ACE_Thread::spawn_n (ACE_thread_t thread_ids[],
+ size_t n,
+ ACE_THR_FUNC func,
+ void *arg,
+ long flags,
+ long priority,
+ void *stack[],
+ size_t stack_size[],
+ ACE_hthread_t thread_handles[],
+ ACE_Thread_Adapter *thread_adapter,
+ const char* thr_name[])
+{
+ ACE_TRACE ("ACE_Thread::spawn_n");
+ size_t i = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ ACE_thread_t t_id;
+ ACE_hthread_t t_handle;
+
+ int const result =
+ ACE_OS::thr_create (func,
+ arg,
+ flags,
+ &t_id,
+ &t_handle,
+ priority,
+ stack == 0 ? 0 : stack[i],
+ stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
+ thread_adapter,
+ thr_name == 0 ? 0 : &thr_name[i]);
+
+ if (result == 0)
+ {
+ if (thread_ids != 0)
+ thread_ids[i] = t_id;
+ if (thread_handles != 0)
+ thread_handles[i] = t_handle;
+ }
+ else
+ // Bail out if error occurs.
+ break;
+ }
+
+ return i;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/Thread.h b/ACE/ace/Thread.h
new file mode 100644
index 00000000000..9800997df16
--- /dev/null
+++ b/ACE/ace/Thread.h
@@ -0,0 +1,282 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Thread.h
+ *
+ * $Id$
+ *
+ * @author Douglas Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_THREAD_H
+#define ACE_THREAD_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_Thread.h"
+#include "ace/Thread_Adapter.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+struct cancel_state
+{
+ /// e.g., PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE,
+ /// PTHREAD_CANCELED.
+ int cancelstate;
+
+ /// e.g., PTHREAD_CANCEL_DEFERRED and PTHREAD_CANCEL_ASYNCHRONOUS.
+ int canceltype;
+};
+
+/**
+ * @class ACE_Thread
+ *
+ * @brief Provides a wrapper for threads.
+ *
+ * This class provides a common interface that is mapped onto
+ * POSIX Pthreads, Solaris threads, Win32 threads, VxWorks
+ * threads, or pSoS threads. Note, however, that it is
+ * generally a better idea to use the ACE_Thread_Manager
+ * programming API rather than the <ACE_Thread> API since the
+ * thread manager is more powerful.
+ */
+class ACE_Export ACE_Thread
+{
+public:
+ /**
+ * Creates a new thread having @a flags attributes and running @a func
+ * with <args> (if <thread_adapter> is non-0 then @a func and <args>
+ * are ignored and are obtained from <thread_adapter>). <thr_id>
+ * and <t_handle> are set to the thread's ID and handle (?),
+ * respectively. The thread runs at @a priority priority (see
+ * below).
+ *
+ * The @a flags are a bitwise-OR of the following:
+ * = BEGIN<INDENT>
+ * THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED,
+ * THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED,
+ * THR_SUSPENDED, THR_DAEMON, THR_JOINABLE, THR_SCHED_FIFO,
+ * THR_SCHED_RR, THR_SCHED_DEFAULT, THR_EXPLICIT_SCHED,
+ * THR_SCOPE_SYSTEM, THR_SCOPE_PROCESS
+ * = END<INDENT>
+ *
+ * By default, or if @a priority is set to
+ * ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for
+ * the given scheduling policy (specified in <flags}>, e.g.,
+ * <THR_SCHED_DEFAULT>) is used. This value is calculated
+ * dynamically, and is the median value between the minimum and
+ * maximum priority values for the given policy. If an explicit
+ * value is given, it is used. Note that actual priority values are
+ * EXTREMEMLY implementation-dependent, and are probably best
+ * avoided.
+ *
+ * Note that <thread_adapter> is always deleted when <spawn>
+ * is called, so it must be allocated with global operator new.
+ */
+ static int spawn (ACE_THR_FUNC func,
+ void *arg = 0,
+ long flags = THR_NEW_LWP | THR_JOINABLE,
+ ACE_thread_t *t_id = 0,
+ ACE_hthread_t *t_handle = 0,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ void *stack = 0,
+ size_t stack_size = ACE_DEFAULT_THREAD_STACKSIZE,
+ ACE_Thread_Adapter *thread_adapter = 0,
+ const char** thr_name = 0);
+
+ /**
+ * Spawn N new threads, which execute @a func with argument @a arg (if
+ * @a thread_adapter is non-0 then @a func and @a args are ignored and
+ * are obtained from @a thread_adapter). If @a stack != 0 it is
+ * assumed to be an array of @a n pointers to the base of the stacks
+ * to use for the threads being spawned. Likewise, if @a stack_size
+ * != 0 it is assumed to be an array of @a n values indicating how
+ * big each of the corresponding @a stacks are. Returns the number
+ * of threads actually spawned (if this doesn't equal the number
+ * requested then something has gone wrong and @c errno will
+ * explain...).
+ *
+ * @see spawn()
+ */
+ static size_t spawn_n (size_t n,
+ ACE_THR_FUNC func,
+ void *arg = 0,
+ long flags = THR_NEW_LWP | THR_JOINABLE,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ void *stack[] = 0,
+ size_t stack_size[] = 0,
+ ACE_Thread_Adapter *thread_adapter = 0,
+ const char* thr_name[] = 0);
+
+ /**
+ * Spawn @a n new threads, which execute @a func with argument @a arg
+ * (if @a thread_adapter is non-0 then @a func and @a args are ignored
+ * and are obtained from @a thread_adapter). The thread_ids of
+ * successfully spawned threads will be placed into the <thread_ids>
+ * buffer (which must be the same size as @a n). If @a stack != 0 it
+ * is assumed to be an array of @a n pointers to the base of the
+ * stacks to use for the threads being spawned. If @a stack_size !=
+ * 0 it is assumed to be an array of @a n values indicating how big
+ * each of the corresponding @a stacks are. If @a thread_handles != 0
+ * it is assumed to be an array of @a n thread_handles that will be
+ * assigned the values of the thread handles being spawned. Returns
+ * the number of threads actually spawned (if this doesn't equal the
+ * number requested then something has gone wrong and @c errno will
+ * explain...).
+ *
+ * @see spawn()
+ */
+ static size_t spawn_n (ACE_thread_t thread_ids[],
+ size_t n,
+ ACE_THR_FUNC func,
+ void *arg,
+ long flags,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ void *stack[] = 0,
+ size_t stack_size[] = 0,
+ ACE_hthread_t thread_handles[] = 0,
+ ACE_Thread_Adapter *thread_adapter = 0,
+ const char* thr_name[] = 0);
+
+ /**
+ * Wait for one or more threads to exit and reap their exit status.
+ * thr_join() returns successfully when the target thread terminates.
+ *
+ * @param thread_id is the ACE_thread_t ID of the thread to wait for.
+ * If @a thread_id is 0, join() waits for any
+ * undetached thread in the process to terminate
+ * on platforms that support this capability
+ * (for example, Solaris).
+ * @param departed points to a location that is set to the ID of the
+ * terminated thread if join() returns successfully.
+ * If @a departed is 0, it is ignored.
+ * @param status Points to the location that receives the joined
+ * thread's exit value. If @a status is 0, it is ignored.
+ *
+ * @retval 0 for success
+ * @retval -1 (with errno set) for failure.
+ */
+ static int join (ACE_thread_t thread_id,
+ ACE_thread_t *departed,
+ ACE_THR_FUNC_RETURN *status);
+
+ /// Wait for one thread to exit and reap its exit status.
+ static int join (ACE_hthread_t,
+ ACE_THR_FUNC_RETURN * = 0);
+
+ /// Continue the execution of a previously suspended thread.
+ static int resume (ACE_hthread_t);
+
+ /// Suspend the execution of a particular thread.
+ static int suspend (ACE_hthread_t);
+
+ /// Get the priority of a particular thread.
+ static int getprio (ACE_hthread_t ht_id, int &priority);
+
+ /// Get the priority and policy of a particular thread.
+ static int getprio (ACE_hthread_t ht_id, int &priority, int &policy);
+
+ /// Set the priority of a particular thread.
+ static int setprio (ACE_hthread_t ht_id, int priority, int policy = -1);
+
+ /// Send a signal to the thread.
+ static int kill (ACE_thread_t, int signum);
+
+ /// Yield the thread to another.
+ static void yield (void);
+
+ /**
+ * Return the unique kernel handle of the thread. Note that on
+ * Win32 this is actually a pseudohandle, which cannot be shared
+ * with other processes or waited on by threads. To locate the real
+ * handle, please use the ACE_Thread_Manager::thr_self() method.
+ */
+ static void self (ACE_hthread_t &t_handle);
+
+ /// Return the unique ID of the thread.
+ static ACE_thread_t self (void);
+
+ /// Exit the current thread and return "status".
+ /// Should _not_ be called by main thread.
+ static void exit (ACE_THR_FUNC_RETURN status = 0);
+
+ /// Get the LWP concurrency level of the process.
+ static int getconcurrency (void);
+
+ /// Set the LWP concurrency level of the process.
+ static int setconcurrency (int new_level);
+
+ /// Change and/or examine calling thread's signal mask.
+ static int sigsetmask (int how,
+ const sigset_t *sigset,
+ sigset_t *osigset = 0);
+
+ /**
+ * Allocates a @a keyp that is used to identify data that is specific
+ * to each thread in the process. The key is global to all threads
+ * in the process.
+ */
+ static int keycreate (ACE_thread_key_t *keyp,
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_THR_C_DEST destructor,
+#else
+ ACE_THR_DEST destructor,
+#endif /* ACE_HAS_THR_C_DEST */
+ void * = 0);
+
+ /// Free up the key so that other threads can reuse it.
+ static int keyfree (ACE_thread_key_t key);
+
+ /// Bind value to the thread-specific data key, @a key, for the calling
+ /// thread.
+ static int setspecific (ACE_thread_key_t key,
+ void *value);
+
+ /// Stores the current value bound to @a key for the calling thread
+ /// into the location pointed to by @a valuep.
+ static int getspecific (ACE_thread_key_t key,
+ void **valuep);
+
+ /// Disable thread cancellation.
+ static int disablecancel (struct cancel_state *old_state);
+
+ /// Enable thread cancellation.
+ static int enablecancel (struct cancel_state *old_state,
+ int flag);
+
+ /// Set the cancellation state.
+ static int setcancelstate (struct cancel_state &new_state,
+ struct cancel_state *old_state);
+
+ /**
+ * Cancel a thread.
+ * @note This method is only portable on platforms, such as POSIX pthreads,
+ * that support thread cancellation.
+ */
+ static int cancel (ACE_thread_t t_id);
+
+ /// Test the cancel.
+ static void testcancel (void);
+
+private:
+ /// Ensure that we don't get instantiated.
+ ACE_Thread (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Thread.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_THREAD_H */
diff --git a/ACE/ace/Thread.inl b/ACE/ace/Thread.inl
new file mode 100644
index 00000000000..6c292ab27cd
--- /dev/null
+++ b/ACE/ace/Thread.inl
@@ -0,0 +1,286 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Allocates a <keyp> that is used to identify data that is specific
+// to each thread in the process. The key is global to all threads in
+// the process.
+
+ACE_INLINE int
+ACE_Thread::keycreate (ACE_thread_key_t *keyp,
+#if defined (ACE_HAS_THR_C_DEST)
+ ACE_THR_C_DEST destructor,
+#else
+ ACE_THR_DEST destructor,
+#endif /* ACE_HAS_THR_C_DEST */
+ void *inst)
+{
+ // ACE_TRACE ("ACE_Thread::keycreate");
+ return ACE_OS::thr_keycreate (keyp, destructor, inst);
+}
+
+// Free up the key so that other threads can reuse it.
+
+ACE_INLINE int
+ACE_Thread::keyfree (ACE_thread_key_t key)
+{
+ ACE_TRACE ("ACE_Thread::keyfree");
+ return ACE_OS::thr_keyfree (key);
+}
+
+// Bind value to the thread-specific data key, <key>, for the calling
+// thread.
+
+ACE_INLINE int
+ACE_Thread::setspecific (ACE_thread_key_t key, void *value)
+{
+ // ACE_TRACE ("ACE_Thread::setspecific");
+ return ACE_OS::thr_setspecific (key, value);
+}
+
+// Stores the current value bound to <key> for the calling thread
+// into the location pointed to by <valuep>.
+
+ACE_INLINE int
+ACE_Thread::getspecific (ACE_thread_key_t key, void **valuep)
+{
+ // ACE_TRACE ("ACE_Thread::getspecific");
+ return ACE_OS::thr_getspecific (key, valuep);
+}
+
+ACE_INLINE ACE_thread_t
+ACE_Thread::self (void)
+{
+// ACE_TRACE ("ACE_Thread::self");
+ return ACE_OS::thr_self ();
+}
+
+ACE_INLINE void
+ACE_Thread::exit (ACE_THR_FUNC_RETURN status)
+{
+ ACE_TRACE ("ACE_Thread::exit");
+ ACE_OS::thr_exit (status);
+}
+
+ACE_INLINE void
+ACE_Thread::yield (void)
+{
+ ACE_TRACE ("ACE_Thread::yield");
+ ACE_OS::thr_yield ();
+}
+
+ACE_INLINE int
+ACE_Thread::spawn (ACE_THR_FUNC func,
+ void *arg,
+ long flags,
+ ACE_thread_t *t_id,
+ ACE_hthread_t *t_handle,
+ long priority,
+ void *thr_stack,
+ size_t thr_stack_size,
+ ACE_Thread_Adapter *thread_adapter,
+ const char** thr_name)
+{
+ ACE_TRACE ("ACE_Thread::spawn");
+
+ return ACE_OS::thr_create (func,
+ arg,
+ flags,
+ t_id,
+ t_handle,
+ priority,
+ thr_stack,
+ thr_stack_size,
+ thread_adapter,
+ thr_name);
+}
+
+ACE_INLINE int
+ACE_Thread::resume (ACE_hthread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread::resume");
+ return ACE_OS::thr_continue (t_id);
+}
+
+ACE_INLINE int
+ACE_Thread::suspend (ACE_hthread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread::suspend");
+ return ACE_OS::thr_suspend (t_id);
+}
+
+ACE_INLINE int
+ACE_Thread::kill (ACE_thread_t t_id, int signum)
+{
+ ACE_TRACE ("ACE_Thread::kill");
+ return ACE_OS::thr_kill (t_id, signum);
+}
+
+ACE_INLINE int
+ACE_Thread::join (ACE_thread_t wait_for,
+ ACE_thread_t *departed,
+ ACE_THR_FUNC_RETURN *status)
+{
+ ACE_TRACE ("ACE_Thread::join");
+ return ACE_OS::thr_join (wait_for, departed, status);
+}
+
+ACE_INLINE int
+ACE_Thread::join (ACE_hthread_t wait_for,
+ ACE_THR_FUNC_RETURN *status)
+{
+ ACE_TRACE ("ACE_Thread::join");
+ return ACE_OS::thr_join (wait_for, status);
+}
+
+ACE_INLINE int
+ACE_Thread::getconcurrency (void)
+{
+ ACE_TRACE ("ACE_Thread::getconcurrency");
+ return ACE_OS::thr_getconcurrency ();
+}
+
+ACE_INLINE int
+ACE_Thread::setconcurrency (int new_level)
+{
+ ACE_TRACE ("ACE_Thread::setconcurrency");
+ return ACE_OS::thr_setconcurrency (new_level);
+}
+
+ACE_INLINE int
+ACE_Thread::sigsetmask (int how,
+ const sigset_t *sigset,
+ sigset_t *osigset)
+{
+ ACE_TRACE ("ACE_Thread::sigsetmask");
+ return ACE_OS::thr_sigsetmask (how, sigset, osigset);
+}
+
+ACE_INLINE int
+ACE_Thread::disablecancel (struct cancel_state *old_state)
+{
+ ACE_TRACE ("ACE_Thread::disablecancel");
+ int old_cstate = 0;
+ int result = ACE_OS::thr_setcancelstate (THR_CANCEL_DISABLE,
+ &old_cstate);
+ if (result == 0 && old_state != 0)
+ {
+ ACE_OS::memset (old_state,
+ 0,
+ sizeof (old_state));
+ old_state->cancelstate = old_cstate;
+ }
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_Thread::enablecancel (struct cancel_state *old_state,
+ int flag)
+{
+ ACE_TRACE ("ACE_Thread::enablecancel");
+ int old_cstate = 0;
+ int old_ctype = 0;
+ int result;
+
+ result = ACE_OS::thr_setcancelstate (THR_CANCEL_ENABLE,
+ &old_cstate);
+ if (result != 0)
+ return result;
+
+ result = ACE_OS::thr_setcanceltype (flag,
+ &old_ctype);
+ if (result != 0)
+ return result;
+
+ if (old_state != 0)
+ {
+ old_state->cancelstate = old_cstate;
+ old_state->canceltype = old_ctype;
+ }
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Thread::setcancelstate (struct cancel_state &new_state,
+ struct cancel_state *old_state)
+{
+ ACE_TRACE ("ACE_Thread::setcancelstate");
+ int old_cstate = 0;
+ int old_ctype = 0;
+
+ if (new_state.cancelstate != 0
+ && ACE_OS::thr_setcancelstate (new_state.cancelstate,
+ &old_cstate) != 0)
+ return -1;
+
+ if (new_state.canceltype != 0
+ && ACE_OS::thr_setcanceltype (new_state.canceltype,
+ &old_ctype) != 0)
+ {
+ int o_cstate;
+
+ ACE_OS::thr_setcancelstate (old_cstate,
+ &o_cstate);
+ return -1;
+ }
+
+ if (old_state != 0)
+ {
+ old_state->cancelstate = old_cstate;
+ old_state->canceltype = old_ctype;
+ }
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Thread::cancel (ACE_thread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread::cancel");
+
+ return ACE_OS::thr_cancel (t_id);
+}
+
+ACE_INLINE void
+ACE_Thread::testcancel (void)
+{
+ ACE_TRACE ("ACE_Thread::testcancel");
+
+ ACE_OS::thr_testcancel ();
+}
+
+ACE_INLINE void
+ACE_Thread::self (ACE_hthread_t &t_id)
+{
+// ACE_TRACE ("ACE_Thread::self");
+ ACE_OS::thr_self (t_id);
+}
+
+ACE_INLINE int
+ACE_Thread::getprio (ACE_hthread_t ht_id, int &priority)
+{
+ ACE_TRACE ("ACE_Thread::getprio");
+ return ACE_OS::thr_getprio (ht_id, priority);
+}
+
+ACE_INLINE int
+ACE_Thread::getprio (ACE_hthread_t ht_id, int &priority, int &policy)
+{
+ ACE_TRACE ("ACE_Thread::getprio");
+ return ACE_OS::thr_getprio (ht_id, priority, policy);
+}
+
+ACE_INLINE int
+ACE_Thread::setprio (ACE_hthread_t ht_id, int priority, int policy)
+{
+ ACE_TRACE ("ACE_Thread::setprio");
+ return ACE_OS::thr_setprio (ht_id, priority, policy);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Adapter.cpp b/ACE/ace/Thread_Adapter.cpp
new file mode 100644
index 00000000000..d68dc6c8061
--- /dev/null
+++ b/ACE/ace/Thread_Adapter.cpp
@@ -0,0 +1,225 @@
+// $Id$
+
+#include "ace/Thread_Adapter.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Thread_Exit.h"
+#include "ace/Thread_Hook.h"
+#include "ace/Object_Manager_Base.h"
+
+ACE_RCSID (ace,
+ Thread_Adapter,
+ "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/Thread_Adapter.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC user_func,
+ void *arg,
+ ACE_THR_C_FUNC entry_point,
+ ACE_Thread_Manager *tm,
+ ACE_Thread_Descriptor *td
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , ACE_SEH_EXCEPT_HANDLER selector,
+ ACE_SEH_EXCEPT_HANDLER handler
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ )
+ : ACE_Base_Thread_Adapter (
+ user_func
+ , arg
+ , entry_point
+ , td
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , selector
+ , handler
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ )
+ , thr_mgr_ (tm)
+{
+ ACE_OS_TRACE ("ACE_Thread_Adapter::ACE_Thread_Adapter");
+}
+
+ACE_Thread_Adapter::~ACE_Thread_Adapter (void)
+{
+}
+
+ACE_THR_FUNC_RETURN
+ACE_Thread_Adapter::invoke (void)
+{
+ // Inherit the logging features if the parent thread has an
+ // ACE_Log_Msg instance in thread-specific storage.
+ this->inherit_log_msg ();
+
+#if !defined(ACE_USE_THREAD_MANAGER_ADAPTER)
+ // NOTE: this preprocessor directive should match the one in above
+ // ACE_Thread_Exit::instance (). With the Xavier Pthreads package,
+ // the exit_hook in TSS causes a seg fault. So, this works around
+ // that by creating exit_hook on the stack.
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)
+ // Obtain our thread-specific exit hook and make sure that it knows
+ // how to clean us up! Note that we never use this pointer directly
+ // (it's stored in thread-specific storage), so it's ok to
+ // dereference it here and only store it as a reference.
+
+ // Except if it is null, then the thr_mgr() method crashes.
+ // -jxh
+
+ ACE_Thread_Exit *exit_hook_instance = ACE_Thread_Exit::instance ();
+ ACE_Thread_Exit_Maybe exit_hook_maybe (exit_hook_instance == 0);
+ ACE_Thread_Exit *exit_hook_ptr = exit_hook_instance
+ ? exit_hook_instance
+ : exit_hook_maybe.instance ();
+ ACE_Thread_Exit &exit_hook = *exit_hook_ptr;
+
+ if (this->thr_mgr () != 0)
+ {
+ // Keep track of the <Thread_Manager> that's associated with this
+ // <exit_hook>.
+ exit_hook.thr_mgr (this->thr_mgr ());
+ }
+# else
+ // Without TSS, create an <ACE_Thread_Exit> instance. When this
+ // function returns, its destructor will be called because the
+ // object goes out of scope. The drawback with this appraoch is
+ // that the destructor _won't_ get called if <thr_exit> is called.
+ // So, threads shouldn't exit that way. Instead, they should return
+ // from <svc>.
+ ACE_Thread_Exit exit_hook;
+ exit_hook.thr_mgr (this->thr_mgr ());
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+
+#endif /* ! ACE_USE_THREAD_MANAGER_ADAPTER */
+
+ return this->invoke_i ();
+}
+
+ACE_THR_FUNC_RETURN
+ACE_Thread_Adapter::invoke_i (void)
+{
+ // Extract the arguments.
+ ACE_THR_FUNC func = reinterpret_cast<ACE_THR_FUNC> (this->user_func_);
+ void *arg = this->arg_;
+
+#if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+ ACE_OS_Thread_Descriptor *thr_desc = this->thr_desc_;
+#endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
+
+ // Delete ourselves since we don't need <this> anymore. Make sure
+ // not to access <this> anywhere below this point.
+ delete this;
+
+#if defined (ACE_NEEDS_LWP_PRIO_SET)
+ // On SunOS, the LWP priority needs to be set in order to get
+ // preemption when running in the RT class. This is the ACE way to
+ // do that . . .
+ ACE_hthread_t thr_handle;
+ ACE_OS::thr_self (thr_handle);
+ int prio;
+
+ // thr_getprio () on the current thread should never fail.
+ ACE_OS::thr_getprio (thr_handle, prio);
+
+ // ACE_OS::thr_setprio () has the special logic to set the LWP priority,
+ // if running in the RT class.
+ ACE_OS::thr_setprio (prio);
+
+#endif /* ACE_NEEDS_LWP_PRIO_SET */
+
+ ACE_THR_FUNC_RETURN status = 0;
+
+ ACE_SEH_TRY
+ {
+ ACE_SEH_TRY
+ {
+ ACE_Thread_Hook *hook =
+ ACE_OS_Object_Manager::thread_hook ();
+
+ if (hook)
+ // Invoke the start hook to give the user a chance to
+ // perform some initialization processing before the
+ // <func> is invoked.
+ status = hook->start (func, arg);
+ else
+ // Call thread entry point.
+ status = (*func) (arg);
+ }
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_SEH_EXCEPT (ACE_OS_Object_Manager::seh_except_selector ()(
+ (void *) GetExceptionInformation ()))
+ {
+ ACE_OS_Object_Manager::seh_except_handler ()(0);
+ }
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ }
+
+ ACE_SEH_FINALLY
+ {
+ // If we changed this to 1, change the respective if in
+ // Task::svc_run to 0.
+#if 0
+ // Call the <Task->close> hook.
+ if (func == reinterpret_cast<ACE_THR_FUNC_INTERNAL> (
+ ACE_Task_Base::svc_run))
+ {
+ ACE_Task_Base *task_ptr = (ACE_Task_Base *) arg;
+ ACE_Thread_Manager *thr_mgr_ptr = task_ptr->thr_mgr ();
+
+ // This calls the Task->close () hook.
+ task_ptr->cleanup (task_ptr, 0);
+
+ // This prevents a second invocation of the cleanup code
+ // (called later by <ACE_Thread_Manager::exit>.
+ thr_mgr_ptr->at_exit (task_ptr, 0, 0);
+ }
+#endif /* 0 */
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
+# if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+ int using_afx = -1;
+ if (thr_desc)
+ using_afx = ACE_BIT_ENABLED (thr_desc->flags (), THR_USE_AFX);
+# endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
+ // Call TSS destructors.
+ ACE_OS::cleanup_tss (0 /* not main thread */);
+
+# if defined (ACE_WIN32)
+ // Exit the thread. Allow CWinThread-destructor to be invoked
+ // from AfxEndThread. _endthreadex will be called from
+ // AfxEndThread so don't exit the thread now if we are running
+ // an MFC thread.
+# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+ if (using_afx != -1)
+ {
+ if (using_afx)
+ ::AfxEndThread ((DWORD) status);
+ else
+ ACE_ENDTHREADEX (status);
+ }
+ else
+ {
+ // Not spawned by ACE_Thread_Manager, use the old buggy
+ // version. You should seriously consider using
+ // ACE_Thread_Manager to spawn threads. The following code
+ // is know to cause some problem.
+ CWinThread *pThread = ::AfxGetThread ();
+
+ if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
+ ACE_ENDTHREADEX (status);
+ else
+ ::AfxEndThread ((DWORD)status);
+ }
+# else
+
+ ACE_ENDTHREADEX (status);
+# endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
+# endif /* ACE_WIN32 */
+#endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
+ }
+
+ return status;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Adapter.h b/ACE/ace/Thread_Adapter.h
new file mode 100644
index 00000000000..9b2c8dd22a1
--- /dev/null
+++ b/ACE/ace/Thread_Adapter.h
@@ -0,0 +1,100 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Thread_Adapter.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_THREAD_ADAPTER_H
+#define ACE_THREAD_ADAPTER_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Base_Thread_Adapter.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decl.
+class ACE_Thread_Manager;
+class ACE_Thread_Descriptor;
+
+/**
+ * @class ACE_Thread_Adapter
+ *
+ * @brief Converts a C++ function into a function that
+ * can be called from a thread creation routine
+ * (e.g., pthread_create() or _beginthreadex()) that expects an
+ * extern "C" entry point. This class also makes it possible to
+ * transparently provide hooks to register a thread with an
+ * ACE_Thread_Manager.
+ *
+ * This class is used in ACE_OS::thr_create(). In general, the
+ * thread that creates an object of this class is different from
+ * the thread that calls @c invoke() on this object. Therefore,
+ * the @c invoke() method is responsible for deleting itself.
+ */
+class ACE_Export ACE_Thread_Adapter : public ACE_Base_Thread_Adapter
+{
+public:
+ /// Constructor.
+ ACE_Thread_Adapter (ACE_THR_FUNC user_func,
+ void *arg,
+ ACE_THR_C_FUNC entry_point = (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
+ ACE_Thread_Manager *thr_mgr = 0,
+ ACE_Thread_Descriptor *td = 0
+# 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 */
+ );
+
+ /**
+ * Execute the <user_func_> with the <arg>. This function deletes
+ * @c this, thereby rendering the object useless after the call
+ * returns.
+ */
+ virtual ACE_THR_FUNC_RETURN invoke (void);
+
+ /// Accessor for the optional ACE_Thread_Manager.
+ ACE_Thread_Manager *thr_mgr (void);
+
+protected:
+
+ /// Ensure that this object must be allocated on the heap.
+ ~ACE_Thread_Adapter (void);
+
+private:
+
+ /// Called by invoke, mainly here to separate the SEH stuff because
+ /// SEH on Win32 doesn't compile with local vars with destructors.
+ virtual ACE_THR_FUNC_RETURN invoke_i (void);
+
+private:
+
+ /// Optional thread manager.
+ ACE_Thread_Manager *thr_mgr_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/Thread_Adapter.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_THREAD_ADAPTER_H */
diff --git a/ACE/ace/Thread_Adapter.inl b/ACE/ace/Thread_Adapter.inl
new file mode 100644
index 00000000000..4f1fa0fce49
--- /dev/null
+++ b/ACE/ace/Thread_Adapter.inl
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_Thread_Manager *
+ACE_Thread_Adapter::thr_mgr (void)
+{
+ return this->thr_mgr_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Control.cpp b/ACE/ace/Thread_Control.cpp
new file mode 100644
index 00000000000..594aa4618cb
--- /dev/null
+++ b/ACE/ace/Thread_Control.cpp
@@ -0,0 +1,96 @@
+// $Id$
+
+// <HACK ON>
+#include "ace/config-all.h"
+#if defined (ACE_LEGACY_MODE)
+// This silly include breaks a cycle when compiling in backwards
+// compatibility mode
+# include "ace/Thread_Exit.h"
+#endif /* ACE_LEGACY_MODE */
+// </HACK OFF>
+
+#include "ace/Thread_Control.h"
+#include "ace/Thread_Manager.h"
+
+ACE_RCSID(ace, Thread_Control, "$Id$")
+
+#if !defined (ACE_HAS_INLINED_OSCALLS)
+# include "ace/Thread_Control.inl"
+#endif /* ACE_HAS_INLINED_OSCALLS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Thread_Control::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_OS_TRACE ("ACE_Thread_Control::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Thread_Control::insert (ACE_Thread_Manager *tm, int insert)
+{
+ ACE_OS_TRACE ("ACE_Thread_Control::insert");
+
+ ACE_hthread_t t_id;
+ ACE_OS::thr_self (t_id);
+ this->tm_ = tm;
+
+ if (insert)
+ return this->tm_->insert_thr (ACE_OS::thr_self (), t_id);
+ else
+ return 0;
+}
+
+// Initialize the thread controller.
+
+ACE_Thread_Control::ACE_Thread_Control (ACE_Thread_Manager *t,
+ int insert)
+ : tm_ (t),
+ status_ (0)
+{
+ ACE_OS_TRACE ("ACE_Thread_Control::ACE_Thread_Control");
+
+ if (this->tm_ != 0 && insert)
+ {
+ ACE_hthread_t t_id;
+ ACE_OS::thr_self (t_id);
+ this->tm_->insert_thr (ACE_OS::thr_self (), t_id);
+ }
+}
+
+// Automatically kill thread on exit.
+
+ACE_Thread_Control::~ACE_Thread_Control (void)
+{
+ ACE_OS_TRACE ("ACE_Thread_Control::~ACE_Thread_Control");
+
+#if defined (ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS) || defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32)
+ this->exit (this->status_, 0);
+#else
+ this->exit (this->status_, 1);
+#endif /* ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS */
+}
+
+// Exit from thread (but clean up first).
+
+ACE_THR_FUNC_RETURN
+ACE_Thread_Control::exit (ACE_THR_FUNC_RETURN exit_status, int do_thr_exit)
+{
+ ACE_OS_TRACE ("ACE_Thread_Control::exit");
+
+ if (this->tm_ != 0)
+ return this->tm_->exit (exit_status, do_thr_exit);
+ else
+ {
+#if !defined (ACE_HAS_TSS_EMULATION)
+ // With ACE_HAS_TSS_EMULATION, we let ACE_Thread_Adapter::invoke ()
+ // exit the thread after cleaning up TSS.
+ ACE_OS::thr_exit (exit_status);
+#endif /* ! ACE_HAS_TSS_EMULATION */
+ return 0;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Control.h b/ACE/ace/Thread_Control.h
new file mode 100644
index 00000000000..ee9d7f5094b
--- /dev/null
+++ b/ACE/ace/Thread_Control.h
@@ -0,0 +1,102 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Thread_Control.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_THREAD_CONTROL_H
+#define ACE_THREAD_CONTROL_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Thread_Manager;
+
+/**
+ * @class ACE_Thread_Control
+ *
+ * @brief Used to keep track of a thread's activities within its entry
+ * point function.
+ *
+ * A ACE_Thread_Manager uses this class to ensure that threads
+ * it spawns automatically register and unregister themselves
+ * with it.
+ * This class can be stored in thread-specific storage using the
+ * ACE_TSS wrapper. When a thread exits the
+ * <ACE_TSS::cleanup> function deletes this object, thereby
+ * ensuring that it gets removed from its associated
+ * ACE_Thread_Manager.
+ */
+class ACE_Export ACE_Thread_Control
+{
+public:
+ /// Initialize the thread control object. If @a insert != 0, then
+ /// register the thread with the Thread_Manager.
+ ACE_Thread_Control (ACE_Thread_Manager *tm = 0,
+ int insert = 0);
+
+ /// Remove the thread from its associated <Thread_Manager> and exit
+ /// the thread if <do_thr_exit> is enabled.
+ ~ACE_Thread_Control (void);
+
+ /// Remove this thread from its associated ACE_Thread_Manager and exit
+ /// the thread if @a do_thr_exit is enabled.
+ ACE_THR_FUNC_RETURN exit (ACE_THR_FUNC_RETURN status,
+ int do_thr_exit);
+
+ /// Store the <Thread_Manager> and use it to register ourselves for
+ /// correct shutdown.
+ int insert (ACE_Thread_Manager *tm, int insert = 0);
+
+ /// Returns the current <Thread_Manager>.
+ ACE_Thread_Manager *thr_mgr (void);
+
+ /// Atomically set a new <Thread_Manager> and return the old
+ /// <Thread_Manager>.
+ ACE_Thread_Manager *thr_mgr (ACE_Thread_Manager *);
+
+ /// Set the exit status (and return existing status).
+ ACE_THR_FUNC_RETURN status (ACE_THR_FUNC_RETURN status);
+
+ /// Get the current exit status.
+ ACE_THR_FUNC_RETURN status (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to the thread manager for this block of code.
+ ACE_Thread_Manager *tm_;
+
+ /// Keeps track of the exit status for the thread.
+ ACE_THR_FUNC_RETURN status_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/Thread_Control.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_THREAD_CONTROL_H */
diff --git a/ACE/ace/Thread_Control.inl b/ACE/ace/Thread_Control.inl
new file mode 100644
index 00000000000..7b96cb369f8
--- /dev/null
+++ b/ACE/ace/Thread_Control.inl
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Set the exit status.
+
+ACE_INLINE ACE_THR_FUNC_RETURN
+ACE_Thread_Control::status (ACE_THR_FUNC_RETURN s)
+{
+ ACE_OS_TRACE ("ACE_Thread_Control::status");
+ return this->status_ = s;
+}
+
+// Get the exit status.
+
+ACE_INLINE ACE_THR_FUNC_RETURN
+ACE_Thread_Control::status (void)
+{
+ ACE_OS_TRACE ("ACE_Thread_Control::status");
+ return this->status_;
+}
+
+// Returns the current <Thread_Manager>.
+
+ACE_INLINE ACE_Thread_Manager *
+ACE_Thread_Control::thr_mgr (void)
+{
+ ACE_OS_TRACE ("ACE_Thread_Control::thr_mgr");
+ return this->tm_;
+}
+
+// Atomically set a new <Thread_Manager> and return the old
+// <Thread_Manager>.
+
+ACE_INLINE ACE_Thread_Manager *
+ACE_Thread_Control::thr_mgr (ACE_Thread_Manager *tm)
+{
+ ACE_OS_TRACE ("ACE_Thread_Control::thr_mgr");
+ ACE_Thread_Manager *o_tm = this->tm_;
+ this->tm_ = tm;
+ return o_tm;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Exit.cpp b/ACE/ace/Thread_Exit.cpp
new file mode 100644
index 00000000000..48f6b5dff47
--- /dev/null
+++ b/ACE/ace/Thread_Exit.cpp
@@ -0,0 +1,123 @@
+// $Id$
+
+#include "ace/Thread_Exit.h"
+#include "ace/Managed_Object.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Guard_T.h"
+
+ACE_RCSID(ace, Thread_Exit, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+bool ACE_Thread_Exit::is_constructed_ = false;
+
+void
+ACE_Thread_Exit::cleanup (void *instance)
+{
+ ACE_OS_TRACE ("ACE_Thread_Exit::cleanup");
+
+ delete (ACE_TSS_TYPE (ACE_Thread_Exit) *) instance;
+
+ // Set the thr_exit_ static to null to keep things from crashing if
+ // ACE::fini() is enabled here.
+ ACE_Thread_Manager::thr_exit_ = 0;
+
+ ACE_Thread_Exit::is_constructed_ = false;
+ // All TSS objects have been destroyed. Reset this flag so
+ // ACE_Thread_Exit singleton can be created again.
+}
+
+// NOTE: this preprocessor directive should match the one in
+// ACE_Task_Base::svc_run () below. This prevents the two statics
+// from being defined.
+
+ACE_Thread_Exit *
+ACE_Thread_Exit::instance (void)
+{
+#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)
+ ACE_OS_TRACE ("ACE_Thread_Exit::instance");
+
+ // Determines if we were dynamically allocated.
+ static ACE_TSS_TYPE (ACE_Thread_Exit) * volatile instance_;
+
+ // Implement the Double Check pattern.
+
+ if (!ACE_Thread_Exit::is_constructed_)
+ {
+ ACE_MT (ACE_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_THREAD_EXIT_LOCK);
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, *lock, 0));
+
+ if (!ACE_Thread_Exit::is_constructed_)
+ {
+ ACE_NEW_RETURN (instance_,
+ ACE_TSS_TYPE (ACE_Thread_Exit),
+ 0);
+
+ ACE_Thread_Exit::is_constructed_ = true;
+
+ ACE_Thread_Manager::set_thr_exit (instance_);
+ }
+ }
+
+ return ACE_TSS_GET (instance_, ACE_Thread_Exit);
+#else
+ return 0;
+#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+}
+
+// Grab hold of the Task * so that we can close() it in the
+// destructor.
+
+ACE_Thread_Exit::ACE_Thread_Exit (void)
+{
+ ACE_OS_TRACE ("ACE_Thread_Exit::ACE_Thread_Exit");
+}
+
+// Set the this pointer...
+
+void
+ACE_Thread_Exit::thr_mgr (ACE_Thread_Manager *tm)
+{
+ ACE_OS_TRACE ("ACE_Thread_Exit::thr_mgr");
+
+ if (tm != 0)
+ this->thread_control_.insert (tm, 0);
+}
+
+// When this object is destroyed the Task is automatically closed
+// down!
+
+ACE_Thread_Exit::~ACE_Thread_Exit (void)
+{
+ ACE_OS_TRACE ("ACE_Thread_Exit::~ACE_Thread_Exit");
+}
+
+ACE_Thread_Exit_Maybe::ACE_Thread_Exit_Maybe (int flag)
+ : instance_ (0)
+{
+ if (flag)
+ {
+ ACE_NEW (instance_, ACE_Thread_Exit);
+ }
+}
+
+ACE_Thread_Exit_Maybe::~ACE_Thread_Exit_Maybe (void)
+{
+ delete this->instance_;
+}
+
+ACE_Thread_Exit *
+ACE_Thread_Exit_Maybe::operator -> (void) const
+{
+ return this->instance_;
+}
+
+ACE_Thread_Exit *
+ACE_Thread_Exit_Maybe::instance (void) const
+{
+ return this->instance_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Exit.h b/ACE/ace/Thread_Exit.h
new file mode 100644
index 00000000000..e37776bb455
--- /dev/null
+++ b/ACE/ace/Thread_Exit.h
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Thread_Exit.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_THREAD_EXIT_H
+#define ACE_THREAD_EXIT_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/Thread_Control.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Thread_Exit
+ *
+ * @brief Keep exit information for a Thread in thread specific storage.
+ * so that the thread-specific exit hooks will get called no
+ * matter how the thread exits (e.g., via <ACE_Thread::exit>, C++
+ * or Win32 exception, "falling off the end" of the thread entry
+ * point function, etc.).
+ *
+ * This clever little helper class is stored in thread-specific
+ * storage using the <ACE_TSS> wrapper. When a thread exits the
+ * <ACE_TSS::cleanup> function deletes this object, thereby
+ * closing it down gracefully.
+ */
+class ACE_Export ACE_Thread_Exit
+{
+public:
+ /// Capture the Thread that will be cleaned up automatically.
+ ACE_Thread_Exit (void);
+
+ /// Set the ACE_Thread_Manager.
+ void thr_mgr (ACE_Thread_Manager *tm);
+
+ /// Destructor calls the thread-specific exit hooks when a thread
+ /// exits.
+ ~ACE_Thread_Exit (void);
+
+ /// Singleton access point.
+ static ACE_Thread_Exit *instance (void);
+
+ /// Cleanup method, used by the ACE_Object_Manager to destroy the
+ /// singleton.
+ static void cleanup (void *instance);
+
+private:
+ /// Automatically add/remove the thread from the
+ /// ACE_Thread_Manager.
+ ACE_Thread_Control thread_control_;
+
+ /**
+ * Used to detect whether we should create a new instance (or not)
+ * within the instance method -- we don't trust the instance_ ptr
+ * because the destructor may have run (if ACE::fini() was called).
+ * See bug #526.
+ * We don't follow the singleton pattern due to dependency issues.
+ */
+ static bool is_constructed_;
+};
+
+/**
+ * @class ACE_Thread_Exit_Maybe
+ *
+ * @brief A version of ACE_Thread_Exit that is created dynamically
+ * under the hood if the flag is set to TRUE.
+ *
+ * Allows the appearance of a "smart pointer", but is not
+ * always created.
+ */
+class ACE_Export ACE_Thread_Exit_Maybe
+{
+public:
+ /// Don't create an ACE_Thread_Exit instance by default.
+ ACE_Thread_Exit_Maybe (int flag = 0);
+
+ /// Destroys the underlying ACE_Thread_Exit instance if it exists.
+ ~ACE_Thread_Exit_Maybe (void);
+
+ /// Delegates to underlying instance.
+ ACE_Thread_Exit * operator -> (void) const;
+
+ /// Returns the underlying instance.
+ ACE_Thread_Exit * instance (void) const;
+
+private:
+
+ /// Holds the underlying instance.
+ ACE_Thread_Exit *instance_;
+
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_THREAD_EXIT_H */
diff --git a/ACE/ace/Thread_Hook.cpp b/ACE/ace/Thread_Hook.cpp
new file mode 100644
index 00000000000..e69eb0a482c
--- /dev/null
+++ b/ACE/ace/Thread_Hook.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+#include "ace/Thread_Hook.h"
+#include "ace/Object_Manager_Base.h"
+
+ACE_RCSID(ace, Thread_Hook, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Thread_Hook::~ACE_Thread_Hook ()
+{
+}
+
+ACE_THR_FUNC_RETURN
+ACE_Thread_Hook::start (ACE_THR_FUNC func,
+ void *arg)
+{
+ return (func) (arg);
+}
+
+ACE_Thread_Hook *
+ACE_Thread_Hook::thread_hook (ACE_Thread_Hook *hook)
+{
+ return ACE_OS_Object_Manager::thread_hook (hook);
+}
+
+ACE_Thread_Hook *
+ACE_Thread_Hook::thread_hook (void)
+{
+ return ACE_OS_Object_Manager::thread_hook ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Hook.h b/ACE/ace/Thread_Hook.h
new file mode 100644
index 00000000000..e7638daa941
--- /dev/null
+++ b/ACE/ace/Thread_Hook.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Thread_Hook.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_THREAD_HOOK_H
+#define ACE_THREAD_HOOK_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/ACE_export.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Thread_Hook
+ *
+ * @brief This class makes it possible to provide user-defined "start"
+ * hooks that are called before the thread entry point function
+ * is invoked.
+ */
+class ACE_Export ACE_Thread_Hook
+{
+
+public:
+
+ /// Destructor.
+ virtual ~ACE_Thread_Hook (void);
+
+ /**
+ * This method can be overridden in a subclass to customize this
+ * pre-function call "hook" invocation that can perform
+ * initialization processing before the thread entry point @a func
+ * method is called back. The @a func and @a arg passed into the
+ * start hook are the same as those passed by the application that
+ * spawned the thread.
+ */
+ virtual ACE_THR_FUNC_RETURN start (ACE_THR_FUNC func,
+ void *arg);
+
+ /// sets the system wide thread hook, returns the previous thread
+ /// hook or 0 if none is set.
+ static ACE_Thread_Hook *thread_hook (ACE_Thread_Hook *hook);
+
+ /// Returns the current system thread hook.
+ static ACE_Thread_Hook *thread_hook (void);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_THREAD_HOOK_H */
diff --git a/ACE/ace/Thread_Manager.cpp b/ACE/ace/Thread_Manager.cpp
new file mode 100644
index 00000000000..f9a6b934bde
--- /dev/null
+++ b/ACE/ace/Thread_Manager.cpp
@@ -0,0 +1,2163 @@
+// $Id$
+
+#include "ace/TSS_T.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Dynamic.h"
+#include "ace/Object_Manager.h"
+#include "ace/Singleton.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Guard_T.h"
+
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_sys_time.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Thread_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Thread_Manager,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_At_Thread_Exit::~ACE_At_Thread_Exit (void)
+{
+ this->do_apply ();
+}
+
+ACE_At_Thread_Exit_Func::~ACE_At_Thread_Exit_Func (void)
+{
+ this->do_apply ();
+}
+
+void
+ACE_At_Thread_Exit_Func::apply (void)
+{
+ this->func_ (this->object_, this->param_);
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Control)
+ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Manager)
+
+#if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
+// Process-wide Thread Manager.
+ACE_Thread_Manager *ACE_Thread_Manager::thr_mgr_ = 0;
+
+// Controls whether the Thread_Manager is deleted when we shut down
+// (we can only delete it safely if we created it!)
+bool ACE_Thread_Manager::delete_thr_mgr_ = false;
+#endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
+
+ACE_TSS_TYPE (ACE_Thread_Exit) *ACE_Thread_Manager::thr_exit_ = 0;
+
+int
+ACE_Thread_Manager::set_thr_exit (ACE_TSS_TYPE (ACE_Thread_Exit) *ptr)
+{
+ if (ACE_Thread_Manager::thr_exit_ == 0)
+ ACE_Thread_Manager::thr_exit_ = ptr;
+ else
+ return -1;
+ return 0;
+}
+
+void
+ACE_Thread_Manager::dump (void)
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Thread_Manager::dump");
+ // Cast away const-ness of this in order to use its non-const lock_.
+ ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon,
+ ((ACE_Thread_Manager *) this)->lock_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ngrp_id_ = %d"), this->grp_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncurrent_count_ = %d"), this->thr_list_.size ()));
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ iter.next ()->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Thread_Descriptor::~ACE_Thread_Descriptor (void)
+{
+ delete this->sync_;
+}
+
+void
+ACE_Thread_Descriptor::at_pop (int apply)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::at_pop");
+ // Get first at from at_exit_list
+ ACE_At_Thread_Exit* at = this->at_exit_list_;
+ // Remove at from at_exit list
+ this->at_exit_list_ = at->next_;
+ // Apply if required
+ if (apply)
+ {
+ at->apply ();
+ // Do the apply method
+ at->was_applied (1);
+ // Mark at has been applied to avoid double apply from
+ // at destructor
+ }
+ // If at is not owner delete at.
+ if (!at->is_owner ())
+ delete at;
+}
+
+void
+ACE_Thread_Descriptor::at_push (ACE_At_Thread_Exit* cleanup, bool is_owner)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::at_push");
+ cleanup->is_owner (is_owner);
+ cleanup->td_ = this;
+ cleanup->next_ = at_exit_list_;
+ at_exit_list_ = cleanup;
+}
+
+int
+ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit& cleanup)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
+ at_push (&cleanup, 1);
+ return 0;
+}
+
+int
+ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit* cleanup)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
+ if (cleanup==0)
+ return -1;
+ else
+ {
+ this->at_push (cleanup);
+ return 0;
+ }
+}
+
+void
+ACE_Thread_Descriptor::do_at_exit ()
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::do_at_exit");
+ while (at_exit_list_!=0)
+ this->at_pop ();
+}
+
+void
+ACE_Thread_Descriptor::terminate ()
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::terminate");
+
+ if (!terminated_)
+ {
+ ACE_Log_Msg* log_msg = this->log_msg_;
+ terminated_ = true;
+ // Run at_exit hooks
+ this->do_at_exit ();
+ // We must remove Thread_Descriptor from Thread_Manager list
+ if (this->tm_ != 0)
+ {
+ int close_handle = 0;
+
+#if !defined (ACE_HAS_VXTHREADS)
+ // Threads created with THR_DAEMON shouldn't exist here, but
+ // just to be safe, let's put it here.
+
+ if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_JOINING))
+ {
+ if (ACE_BIT_DISABLED (this->flags_, THR_DETACHED | THR_DAEMON)
+ || ACE_BIT_ENABLED (this->flags_, THR_JOINABLE))
+ {
+ // Mark thread as terminated.
+ ACE_SET_BITS (this->thr_state_, ACE_Thread_Manager::ACE_THR_TERMINATED);
+ tm_->register_as_terminated (this);
+ // Must copy the information here because td will be
+ // "freed" below.
+ }
+#if defined (ACE_WIN32)
+ else
+ {
+ close_handle = 1;
+ }
+#endif /* ACE_WIN32 */
+ }
+#endif /* !ACE_HAS_VXTHREADS */
+
+ // Remove thread descriptor from the table.
+ if (this->tm_ != 0)
+ tm_->remove_thr (this, close_handle);
+ }
+
+ // Check if we need delete ACE_Log_Msg instance
+ // If ACE_TSS_cleanup was not executed first log_msg == 0
+ if (log_msg == 0)
+ {
+ // Only inform to ACE_TSS_cleanup that it must delete the log instance
+ // setting ACE_LOG_MSG thr_desc to 0.
+ ACE_LOG_MSG->thr_desc (0);
+ }
+ else
+ {
+ // Thread_Descriptor is the owner of the Log_Msg instance!!
+ // deleted.
+ this->log_msg_ = 0;
+ delete log_msg;
+ }
+ }
+}
+
+int
+ACE_Thread_Descriptor::at_exit (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
+ // To keep compatibility, when cleanup_hook is null really is a at_pop
+ // without apply.
+ if (cleanup_hook == 0)
+ {
+ if (this->at_exit_list_!= 0)
+ this->at_pop(0);
+ }
+ else
+ {
+ ACE_At_Thread_Exit* cleanup = 0;
+ ACE_NEW_RETURN (cleanup,
+ ACE_At_Thread_Exit_Func (object,
+ cleanup_hook,
+ param),
+ -1);
+ this->at_push (cleanup);
+ }
+ return 0;
+}
+
+void
+ACE_Thread_Descriptor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Thread_Descriptor::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_id_ = %d"), this->thr_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_handle_ = %d"), this->thr_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ngrp_id_ = %d"), this->grp_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_state_ = %d"), this->thr_state_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncleanup_info_.cleanup_hook_ = %x"), this->cleanup_info_.cleanup_hook_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags_ = %x\n"), this->flags_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Thread_Descriptor::ACE_Thread_Descriptor (void)
+ : log_msg_ (0),
+ at_exit_list_ (0),
+ terminated_ (false)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::ACE_Thread_Descriptor");
+ ACE_NEW (this->sync_,
+ ACE_DEFAULT_THREAD_MANAGER_LOCK);
+}
+
+void
+ACE_Thread_Descriptor::acquire_release (void)
+{
+ // Just try to acquire the lock then release it.
+#if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN)
+ if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED))
+#endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */
+ {
+ this->sync_->acquire ();
+ // Acquire the lock before removing <td> from the thread table. If
+ // this thread is in the table already, it should simply acquire the
+ // lock easily.
+
+ // Once we get the lock, we must have registered.
+ ACE_ASSERT (ACE_BIT_ENABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED));
+
+ this->sync_->release ();
+ // Release the lock before putting it back to freelist.
+ }
+}
+
+void
+ACE_Thread_Descriptor::acquire (void)
+{
+ // Just try to acquire the lock then release it.
+#if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN)
+ if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED))
+#endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */
+ {
+ this->sync_->acquire ();
+ }
+}
+
+void
+ACE_Thread_Descriptor::release (void)
+{
+ // Just try to acquire the lock then release it.
+#if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN)
+ if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED))
+#endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */
+ {
+ this->sync_->release ();
+ // Release the lock before putting it back to freelist.
+ }
+}
+
+// The following macro simplifies subsequence code.
+#define ACE_FIND(OP,INDEX) \
+ ACE_Thread_Descriptor *INDEX = OP; \
+
+ACE_Thread_Descriptor *
+ACE_Thread_Manager::thread_descriptor (ACE_thread_t thr_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::thread_descriptor");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ ACE_FIND (this->find_thread (thr_id), ptr);
+ return ptr;
+}
+
+ACE_Thread_Descriptor *
+ACE_Thread_Manager::hthread_descriptor (ACE_hthread_t thr_handle)
+{
+ ACE_TRACE ("ACE_Thread_Manager::hthread_descriptor");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ ACE_FIND (this->find_hthread (thr_handle), ptr);
+ return ptr;
+}
+
+// Return the thread descriptor (indexed by ACE_hthread_t).
+
+int
+ACE_Thread_Manager::thr_self (ACE_hthread_t &self)
+{
+ ACE_TRACE ("ACE_Thread_Manager::thr_self");
+
+ ACE_Thread_Descriptor *desc =
+ this->thread_desc_self ();
+
+ if (desc == 0)
+ return -1;
+ else
+ desc->self (self);
+
+ return 0;
+}
+
+// Initialize the synchronization variables.
+
+ACE_Thread_Manager::ACE_Thread_Manager (size_t prealloc,
+ size_t lwm,
+ size_t inc,
+ size_t hwm)
+ : grp_id_ (1),
+ automatic_wait_ (1)
+#if defined (ACE_HAS_THREADS)
+ , zero_cond_ (lock_)
+#endif /* ACE_HAS_THREADS */
+ , thread_desc_freelist_ (ACE_FREE_LIST_WITH_POOL,
+ prealloc, lwm, hwm, inc)
+{
+ ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager");
+}
+
+#if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
+ACE_Thread_Manager *
+ACE_Thread_Manager::instance (void)
+{
+ ACE_TRACE ("ACE_Thread_Manager::instance");
+
+ if (ACE_Thread_Manager::thr_mgr_ == 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_Thread_Manager::thr_mgr_ == 0)
+ {
+ ACE_NEW_RETURN (ACE_Thread_Manager::thr_mgr_,
+ ACE_Thread_Manager,
+ 0);
+ ACE_Thread_Manager::delete_thr_mgr_ = true;
+ }
+ }
+
+ return ACE_Thread_Manager::thr_mgr_;
+}
+
+ACE_Thread_Manager *
+ACE_Thread_Manager::instance (ACE_Thread_Manager *tm)
+{
+ ACE_TRACE ("ACE_Thread_Manager::instance");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ ACE_Thread_Manager *t = ACE_Thread_Manager::thr_mgr_;
+ // We can't safely delete it since we don't know who created it!
+ ACE_Thread_Manager::delete_thr_mgr_ = false;
+
+ ACE_Thread_Manager::thr_mgr_ = tm;
+ return t;
+}
+
+void
+ACE_Thread_Manager::close_singleton (void)
+{
+ ACE_TRACE ("ACE_Thread_Manager::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ if (ACE_Thread_Manager::delete_thr_mgr_)
+ {
+ // First, we clean up the thread descriptor list.
+ ACE_Thread_Manager::thr_mgr_->close ();
+ delete ACE_Thread_Manager::thr_mgr_;
+ ACE_Thread_Manager::thr_mgr_ = 0;
+ ACE_Thread_Manager::delete_thr_mgr_ = false;
+ }
+
+ ACE_Thread_Exit::cleanup (ACE_Thread_Manager::thr_exit_);
+}
+#endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
+
+// Close up and release all resources.
+
+int
+ACE_Thread_Manager::close ()
+{
+ ACE_TRACE ("ACE_Thread_Manager::close");
+
+ // Clean up the thread descriptor list.
+ if (this->automatic_wait_)
+ this->wait (0, 1);
+ else
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ this->remove_thr_all ();
+ }
+
+ return 0;
+}
+
+ACE_Thread_Manager::~ACE_Thread_Manager (void)
+{
+ ACE_TRACE ("ACE_Thread_Manager::~ACE_Thread_Manager");
+ this->close ();
+}
+
+
+// Run the entry point for thread spawned under the control of the
+// <ACE_Thread_Manager>. This must be an extern "C" to make certain
+// compilers happy...
+//
+// The interaction with <ACE_Thread_Exit> and
+// <ace_thread_manager_adapter> works like this, with
+// ACE_HAS_THREAD_SPECIFIC_STORAGE or ACE_HAS_TSS_EMULATION:
+//
+// o Every thread in the <ACE_Thread_Manager> is run with
+// <ace_thread_manager_adapter>.
+//
+// o <ace_thread_manager_adapter> retrieves the singleton
+// <ACE_Thread_Exit> instance from <ACE_Thread_Exit::instance>.
+// The singleton gets created in thread-specific storage
+// in the first call to that function. The key point is that the
+// instance is in thread-specific storage.
+//
+// o A thread can exit by various means, such as <ACE_Thread::exit>, C++
+// or Win32 exception, "falling off the end" of the thread entry
+// point function, etc.
+//
+// o If you follow this so far, now it gets really fun . . .
+// When the thread-specific storage (for the thread that
+// is being destroyed) is cleaned up, the OS threads package (or
+// the ACE emulation of thread-specific storage) will destroy any
+// objects that are in thread-specific storage. It has a list of
+// them, and just walks down the list and destroys each one.
+//
+// o That's where the ACE_Thread_Exit destructor gets called.
+
+#if defined(ACE_USE_THREAD_MANAGER_ADAPTER)
+extern "C" void *
+ace_thread_manager_adapter (void *args)
+{
+#if defined (ACE_HAS_TSS_EMULATION)
+ // As early as we can in the execution of the new thread, allocate
+ // its local TS storage. Allocate it on the stack, to save dynamic
+ // allocation/dealloction.
+ void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX];
+ ACE_TSS_Emulation::tss_open (ts_storage);
+#endif /* ACE_HAS_TSS_EMULATION */
+
+ ACE_Thread_Adapter *thread_args = reinterpret_cast<ACE_Thread_Adapter *> (args);
+
+ // NOTE: this preprocessor directive should match the one in above
+ // ACE_Thread_Exit::instance (). With the Xavier Pthreads package,
+ // the exit_hook in TSS causes a seg fault. So, this works around
+ // that by creating exit_hook on the stack.
+#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)
+ // Obtain our thread-specific exit hook and make sure that it knows
+ // how to clean us up! Note that we never use this pointer directly
+ // (it's stored in thread-specific storage), so it's ok to
+ // dereference it here and only store it as a reference.
+ ACE_Thread_Exit &exit_hook = *ACE_Thread_Exit::instance ();
+#else
+ // Without TSS, create an <ACE_Thread_Exit> instance. When this
+ // function returns, its destructor will be called because the
+ // object goes out of scope. The drawback with this appraoch is
+ // that the destructor _won't_ get called if <thr_exit> is called.
+ // So, threads shouldn't exit that way. Instead, they should return
+ // from <svc>.
+ ACE_Thread_Exit exit_hook;
+#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+
+ // Keep track of the <Thread_Manager> that's associated with this
+ // <exit_hook>.
+ exit_hook.thr_mgr (thread_args->thr_mgr ());
+
+ // Invoke the user-supplied function with the args.
+ void *status = thread_args->invoke ();
+
+ delete static_cast<ACE_Base_Thread_Adapter *> (thread_args);
+ return status;
+}
+#endif
+
+// Call the appropriate OS routine to spawn a thread. Should *not* be
+// called with the lock_ held...
+
+int
+ACE_Thread_Manager::spawn_i (ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ ACE_thread_t *t_id,
+ ACE_hthread_t *t_handle,
+ long priority,
+ int grp_id,
+ void *stack,
+ size_t stack_size,
+ ACE_Task_Base *task,
+ const char** thr_name)
+{
+ // First, threads created by Thread Manager should not be daemon threads.
+ // Using assertion is probably a bit too strong. However, it helps
+ // finding this kind of error as early as possible. Perhaps we can replace
+ // assertion by returning error.
+ ACE_ASSERT (ACE_BIT_DISABLED (flags, THR_DAEMON));
+
+ // Create a new thread running <func>. *Must* be called with the
+ // <lock_> held...
+ // Get a "new" Thread Descriptor from the freelist.
+ auto_ptr<ACE_Thread_Descriptor> new_thr_desc (this->thread_desc_freelist_.remove ());
+
+ // Reset thread descriptor status
+ new_thr_desc->reset (this);
+
+ ACE_Thread_Adapter *thread_args = 0;
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_NEW_RETURN (thread_args,
+ ACE_Thread_Adapter (func,
+ args,
+ (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
+ this,
+ new_thr_desc.get (),
+ ACE_OS_Object_Manager::seh_except_selector(),
+ ACE_OS_Object_Manager::seh_except_handler()),
+ -1);
+# else
+ ACE_NEW_RETURN (thread_args,
+ ACE_Thread_Adapter (func,
+ args,
+ (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
+ this,
+ new_thr_desc.get ()),
+ -1);
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ auto_ptr <ACE_Base_Thread_Adapter> auto_thread_args (static_cast<ACE_Base_Thread_Adapter *> (thread_args));
+
+ ACE_TRACE ("ACE_Thread_Manager::spawn_i");
+ ACE_hthread_t thr_handle;
+
+ ACE_thread_t thr_id;
+ if (t_id == 0)
+ t_id = &thr_id;
+
+ // Acquire the <sync_> lock to block the spawned thread from
+ // removing this Thread Descriptor before it gets put into our
+ // thread table.
+ new_thr_desc->sync_->acquire ();
+
+ int const result = ACE_Thread::spawn (func,
+ args,
+ flags,
+ t_id,
+ &thr_handle,
+ priority,
+ stack,
+ stack_size,
+ thread_args,
+ thr_name);
+
+ if (result != 0)
+ {
+ // _Don't_ clobber errno here! result is either 0 or -1, and
+ // ACE_OS::thr_create () already set errno! D. Levine 28 Mar 1997
+ // errno = result;
+ ACE_Errno_Guard guard (errno); // Lock release may smash errno
+ new_thr_desc->sync_->release ();
+ return -1;
+ }
+ auto_thread_args.release ();
+
+#if defined (ACE_HAS_WTHREADS)
+ // Have to duplicate handle if client asks for it.
+ // @@ How are thread handles implemented on AIX? Do they
+ // also need to be duplicated?
+ if (t_handle != 0)
+# if defined (ACE_HAS_WINCE)
+ *t_handle = thr_handle;
+# else /* ! ACE_HAS_WINCE */
+ (void) ::DuplicateHandle (::GetCurrentProcess (),
+ thr_handle,
+ ::GetCurrentProcess (),
+ t_handle,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS);
+# endif /* ! ACE_HAS_WINCE */
+#else /* ! ACE_HAS_WTHREADS */
+ if (t_handle != 0)
+ *t_handle = thr_handle;
+#endif /* ! ACE_HAS_WTHREADS */
+
+ // append_thr also put the <new_thr_desc> into Thread_Manager's
+ // double-linked list. Only after this point, can we manipulate
+ // double-linked list from a spawned thread's context.
+ return this->append_thr (*t_id,
+ thr_handle,
+ ACE_THR_SPAWNED,
+ grp_id,
+ task,
+ flags,
+ new_thr_desc.release ());
+}
+
+int
+ACE_Thread_Manager::spawn (ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ ACE_thread_t *t_id,
+ ACE_hthread_t *t_handle,
+ long priority,
+ int grp_id,
+ void *stack,
+ size_t stack_size,
+ const char** thr_name)
+{
+ ACE_TRACE ("ACE_Thread_Manager::spawn");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (grp_id == -1)
+ grp_id = this->grp_id_++; // Increment the group id.
+
+ if (priority != ACE_DEFAULT_THREAD_PRIORITY)
+ ACE_CLR_BITS (flags, THR_INHERIT_SCHED);
+
+ if (this->spawn_i (func,
+ args,
+ flags,
+ t_id,
+ t_handle,
+ priority,
+ grp_id,
+ stack,
+ stack_size,
+ 0,
+ thr_name) == -1)
+ return -1;
+
+ return grp_id;
+}
+
+// Create N new threads running FUNC.
+
+int
+ACE_Thread_Manager::spawn_n (size_t n,
+ ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ long priority,
+ int grp_id,
+ ACE_Task_Base *task,
+ ACE_hthread_t thread_handles[],
+ void *stack[],
+ size_t stack_size[],
+ const char* thr_name[])
+{
+ ACE_TRACE ("ACE_Thread_Manager::spawn_n");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (grp_id == -1)
+ grp_id = this->grp_id_++; // Increment the group id.
+
+ for (size_t i = 0; i < n; i++)
+ {
+ // @@ What should happen if this fails?! e.g., should we try to
+ // cancel the other threads that we've already spawned or what?
+ if (this->spawn_i (func,
+ args,
+ flags,
+ 0,
+ thread_handles == 0 ? 0 : &thread_handles[i],
+ priority,
+ grp_id,
+ stack == 0 ? 0 : stack[i],
+ stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
+ task,
+ thr_name == 0 ? 0 : &thr_name [i]) == -1)
+ return -1;
+ }
+
+ return grp_id;
+}
+
+// Create N new threads running FUNC.
+
+int
+ACE_Thread_Manager::spawn_n (ACE_thread_t thread_ids[],
+ size_t n,
+ ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ long priority,
+ int grp_id,
+ void *stack[],
+ size_t stack_size[],
+ ACE_hthread_t thread_handles[],
+ ACE_Task_Base *task,
+ const char* thr_name[])
+{
+ ACE_TRACE ("ACE_Thread_Manager::spawn_n");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (grp_id == -1)
+ grp_id = this->grp_id_++; // Increment the group id.
+
+ for (size_t i = 0; i < n; i++)
+ {
+ // @@ What should happen if this fails?! e.g., should we try to
+ // cancel the other threads that we've already spawned or what?
+ if (this->spawn_i (func,
+ args,
+ flags,
+ thread_ids == 0 ? 0 : &thread_ids[i],
+ thread_handles == 0 ? 0 : &thread_handles[i],
+ priority,
+ grp_id,
+ stack == 0 ? 0 : stack[i],
+ stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
+ task,
+ thr_name == 0 ? 0 : &thr_name [i]) == -1)
+ return -1;
+ }
+
+ return grp_id;
+}
+
+// Append a thread into the pool (does not check for duplicates).
+// Must be called with locks held.
+
+int
+ACE_Thread_Manager::append_thr (ACE_thread_t t_id,
+ ACE_hthread_t t_handle,
+ ACE_UINT32 thr_state,
+ int grp_id,
+ ACE_Task_Base *task,
+ long flags,
+ ACE_Thread_Descriptor *td)
+{
+ ACE_TRACE ("ACE_Thread_Manager::append_thr");
+ ACE_Thread_Descriptor *thr_desc = 0;
+
+ if (td == 0)
+ {
+ ACE_NEW_RETURN (thr_desc,
+ ACE_Thread_Descriptor,
+ -1);
+ thr_desc->tm_ = this;
+ // Setup the Thread_Manager.
+ }
+ else
+ thr_desc = td;
+
+ thr_desc->thr_id_ = t_id;
+ thr_desc->thr_handle_ = t_handle;
+ thr_desc->grp_id_ = grp_id;
+ thr_desc->task_ = task;
+ thr_desc->flags_ = flags;
+
+ this->thr_list_.insert_head (thr_desc);
+ ACE_SET_BITS (thr_desc->thr_state_, thr_state);
+ thr_desc->sync_->release ();
+
+ return 0;
+}
+
+// Return the thread descriptor (indexed by ACE_hthread_t).
+
+ACE_Thread_Descriptor *
+ACE_Thread_Manager::find_hthread (ACE_hthread_t h_id)
+{
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (ACE_OS::thr_cmp (iter.next ()->thr_handle_, h_id))
+ return iter.next ();
+
+ return 0;
+}
+
+// Locate the index in the table associated with <t_id>. Must be
+// called with the lock held.
+
+ACE_Thread_Descriptor *
+ACE_Thread_Manager::find_thread (ACE_thread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::find_thread");
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (ACE_OS::thr_equal (iter.next ()->thr_id_, t_id))
+ return iter.next ();
+ return 0;
+}
+
+// Insert a thread into the pool (checks for duplicates and doesn't
+// allow them to be inserted twice).
+
+int
+ACE_Thread_Manager::insert_thr (ACE_thread_t t_id,
+ ACE_hthread_t t_handle,
+ int grp_id,
+ long flags)
+{
+ ACE_TRACE ("ACE_Thread_Manager::insert_thr");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ // Check for duplicates and bail out if we're already registered...
+ if (this->find_thread (t_id) != 0 )
+ return -1;
+
+ if (grp_id == -1)
+ grp_id = this->grp_id_++;
+
+ if (this->append_thr (t_id,
+ t_handle,
+ ACE_THR_SPAWNED,
+ grp_id,
+ 0,
+ flags) == -1)
+ return -1;
+
+ return grp_id;
+}
+
+// Run the registered hooks when the thread exits.
+
+void
+ACE_Thread_Manager::run_thread_exit_hooks (int i)
+{
+#if 0 // currently unused!
+ ACE_TRACE ("ACE_Thread_Manager::run_thread_exit_hooks");
+
+ // @@ Currently, we have just one hook. This should clearly be
+ // generalized to support an arbitrary number of hooks.
+
+ ACE_Thread_Descriptor *td = this->thread_desc_self ();
+ if (td != 0 && td->cleanup_info.cleanup_hook_ != 0)
+ {
+ (*td->cleanup_info_.cleanup_hook_)
+ (td->cleanup_info_.object_,
+ td->cleanup_info_.param_);
+
+ td->cleanup_info_.cleanup_hook_ = 0;
+ }
+ ACE_UNUSED_ARG (i);
+#else
+ ACE_UNUSED_ARG (i);
+#endif /* 0 */
+}
+
+// Remove a thread from the pool. Must be called with locks held.
+
+void
+ACE_Thread_Manager::remove_thr (ACE_Thread_Descriptor *td,
+ int close_handler)
+{
+ ACE_TRACE ("ACE_Thread_Manager::remove_thr");
+
+ td->tm_ = 0;
+ this->thr_list_.remove (td);
+
+#if defined (ACE_WIN32)
+ if (close_handler != 0)
+ ::CloseHandle (td->thr_handle_);
+#else
+ ACE_UNUSED_ARG (close_handler);
+#endif /* ACE_WIN32 */
+
+ this->thread_desc_freelist_.add (td);
+
+#if defined (ACE_HAS_THREADS)
+ // Tell all waiters when there are no more threads left in the pool.
+ if (this->thr_list_.size () == 0)
+ this->zero_cond_.broadcast ();
+#endif /* ACE_HAS_THREADS */
+}
+
+// Repeatedly call remove_thr on all table entries until there
+// is no thread left. Must be called with lock held.
+void
+ACE_Thread_Manager::remove_thr_all (void)
+{
+ ACE_Thread_Descriptor *td = 0;
+
+ while ((td = this->thr_list_.delete_head ()) != 0)
+ {
+ this->remove_thr (td, 1);
+ }
+}
+
+// ------------------------------------------------------------------
+// Factor out some common behavior to simplify the following methods.
+#define ACE_THR_OP(OP,STATE) \
+ int result = OP (td->thr_handle_); \
+ if (result == -1) { \
+ if (errno != ENOTSUP) \
+ this->thr_to_be_removed_.enqueue_tail (td); \
+ return -1; \
+ } \
+ else { \
+ ACE_SET_BITS (td->thr_state_, STATE); \
+ return 0; \
+ }
+
+int
+ACE_Thread_Manager::join_thr (ACE_Thread_Descriptor *td, int)
+{
+ ACE_TRACE ("ACE_Thread_Manager::join_thr");
+ int const result = ACE_Thread::join (td->thr_handle_);
+ if (result != 0)
+ {
+ // Since the thread are being joined, we should
+ // let it remove itself from the list.
+
+ // this->remove_thr (td);
+ errno = result;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Thread_Manager::suspend_thr (ACE_Thread_Descriptor *td, int)
+{
+ ACE_TRACE ("ACE_Thread_Manager::suspend_thr");
+
+ int const result = ACE_Thread::suspend (td->thr_handle_);
+ if (result == -1) {
+ if (errno != ENOTSUP)
+ this->thr_to_be_removed_.enqueue_tail (td);
+ return -1;
+ }
+ else {
+ ACE_SET_BITS (td->thr_state_, ACE_THR_SUSPENDED);
+ return 0;
+ }
+}
+
+int
+ACE_Thread_Manager::resume_thr (ACE_Thread_Descriptor *td, int)
+{
+ ACE_TRACE ("ACE_Thread_Manager::resume_thr");
+
+ int const result = ACE_Thread::resume (td->thr_handle_);
+ if (result == -1) {
+ if (errno != ENOTSUP)
+ this->thr_to_be_removed_.enqueue_tail (td);
+ return -1;
+ }
+ else {
+ ACE_CLR_BITS (td->thr_state_, ACE_THR_SUSPENDED);
+ return 0;
+ }
+}
+
+int
+ACE_Thread_Manager::cancel_thr (ACE_Thread_Descriptor *td, int async_cancel)
+{
+ ACE_TRACE ("ACE_Thread_Manager::cancel_thr");
+ // Must set the state first and then try to cancel the thread.
+ ACE_SET_BITS (td->thr_state_, ACE_THR_CANCELLED);
+
+ if (async_cancel != 0)
+ // Note that this call only does something relevant if the OS
+ // platform supports asynchronous thread cancellation. Otherwise,
+ // it's a no-op.
+ return ACE_Thread::cancel (td->thr_id_);
+
+ return 0;
+}
+
+int
+ACE_Thread_Manager::kill_thr (ACE_Thread_Descriptor *td, int signum)
+{
+ ACE_TRACE ("ACE_Thread_Manager::kill_thr");
+
+ ACE_thread_t tid = td->thr_id_;
+
+ int const result = ACE_Thread::kill (tid, signum);
+
+ if (result != 0)
+ {
+ // Only remove a thread from us when there is a "real" error.
+ if (errno != ENOTSUP)
+ this->thr_to_be_removed_.enqueue_tail (td);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+// ------------------------------------------------------------------
+// Factor out some common behavior to simplify the following methods.
+#define ACE_EXECUTE_OP(OP, ARG) \
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); \
+ ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); \
+ ACE_FIND (this->find_thread (t_id), ptr); \
+ if (ptr == 0) \
+ { \
+ errno = ENOENT; \
+ return -1; \
+ } \
+ int result = OP (ptr, ARG); \
+ ACE_Errno_Guard error (errno); \
+ while (! this->thr_to_be_removed_.is_empty ()) { \
+ ACE_Thread_Descriptor * td = 0; \
+ this->thr_to_be_removed_.dequeue_head (td); \
+ this->remove_thr (td, 1); \
+ } \
+ return result
+
+// Suspend a single thread.
+
+int
+ACE_Thread_Manager::suspend (ACE_thread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::suspend");
+ ACE_EXECUTE_OP (this->suspend_thr, 0);
+}
+
+// Resume a single thread.
+
+int
+ACE_Thread_Manager::resume (ACE_thread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::resume");
+ ACE_EXECUTE_OP (this->resume_thr, 0);
+}
+
+// Cancel a single thread.
+
+int
+ACE_Thread_Manager::cancel (ACE_thread_t t_id, int async_cancel)
+{
+ ACE_TRACE ("ACE_Thread_Manager::cancel");
+ ACE_EXECUTE_OP (this->cancel_thr, async_cancel);
+}
+
+// Send a signal to a single thread.
+
+int
+ACE_Thread_Manager::kill (ACE_thread_t t_id, int signum)
+{
+ ACE_TRACE ("ACE_Thread_Manager::kill");
+ ACE_EXECUTE_OP (this->kill_thr, signum);
+}
+
+int
+ACE_Thread_Manager::check_state (ACE_UINT32 state,
+ ACE_thread_t id,
+ int enable)
+{
+ ACE_TRACE ("ACE_Thread_Manager::check_state");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ ACE_UINT32 thr_state;
+
+ int self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ());
+
+ // If we're checking the state of our thread, try to get the cached
+ // value out of TSS to avoid lookup.
+ if (self_check)
+ {
+ ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc ();
+ if (desc == 0)
+ return 0; // Always return false.
+ thr_state = desc->thr_state_;
+ }
+ else
+ {
+ // Not calling from self, have to look it up from the list.
+ ACE_FIND (this->find_thread (id), ptr);
+ if (ptr == 0)
+ return 0;
+ thr_state = ptr->thr_state_;
+ }
+ if (enable)
+ return ACE_BIT_ENABLED (thr_state, state);
+
+ return ACE_BIT_DISABLED (thr_state, state);
+}
+
+// Test if a single thread has terminated.
+
+int
+ACE_Thread_Manager::testterminate (ACE_thread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::testterminate");
+ return this->check_state (ACE_THR_TERMINATED, t_id);
+}
+
+// Test if a single thread is suspended.
+
+int
+ACE_Thread_Manager::testsuspend (ACE_thread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::testsuspend");
+ return this->check_state (ACE_THR_SUSPENDED, t_id);
+}
+
+// Test if a single thread is active (i.e., resumed).
+
+int
+ACE_Thread_Manager::testresume (ACE_thread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::testresume");
+ return this->check_state (ACE_THR_SUSPENDED, t_id, 0);
+}
+
+// Test if a single thread is cancelled.
+
+int
+ACE_Thread_Manager::testcancel (ACE_thread_t t_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::testcancel");
+ return this->check_state (ACE_THR_CANCELLED, t_id);
+}
+
+// Thread information query functions.
+
+int
+ACE_Thread_Manager::hthread_within (ACE_hthread_t handle)
+{
+ ACE_TRACE ("ACE_Thread_Manager::hthread_within");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (ACE_OS::thr_cmp(iter.next ()->thr_handle_, handle))
+ return 1;
+
+ return 0;
+}
+
+int
+ACE_Thread_Manager::thread_within (ACE_thread_t tid)
+{
+ ACE_TRACE ("ACE_Thread_Manager::thread_within");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (ACE_OS::thr_equal (iter.next ()->thr_id_, tid))
+ return 1;
+
+ return 0;
+}
+
+// Get group ids for a particular thread id.
+
+int
+ACE_Thread_Manager::get_grp (ACE_thread_t t_id, int &grp_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::get_grp");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ ACE_FIND (this->find_thread (t_id), ptr);
+
+ if (ptr)
+ grp_id = ptr->grp_id_;
+ else
+ return -1;
+ return 0;
+}
+
+// Set group ids for a particular thread id.
+
+int
+ACE_Thread_Manager::set_grp (ACE_thread_t t_id, int grp_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::set_grp");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ ACE_FIND (this->find_thread (t_id), ptr);
+ if (ptr)
+ ptr->grp_id_ = grp_id;
+ else
+ return -1;
+ return 0;
+}
+
+// Suspend a group of threads.
+
+int
+ACE_Thread_Manager::apply_grp (int grp_id,
+ ACE_THR_MEMBER_FUNC func,
+ int arg)
+{
+ ACE_TRACE ("ACE_Thread_Manager::apply_grp");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
+ ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
+
+ int result = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (iter.next ()->grp_id_ == grp_id)
+ if ((this->*func) (iter.next (), arg) == -1)
+ result = -1;
+
+ // Must remove threads after we have traversed the thr_list_ to
+ // prevent clobber thr_list_'s integrity.
+
+ if (! this->thr_to_be_removed_.is_empty ())
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+
+ for (ACE_Thread_Descriptor *td;
+ this->thr_to_be_removed_.dequeue_head (td) != -1;
+ )
+ this->remove_thr (td, 1);
+ }
+
+ return result;
+}
+
+int
+ACE_Thread_Manager::suspend_grp (int grp_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::suspend_grp");
+ return this->apply_grp (grp_id,
+ ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
+}
+
+// Resume a group of threads.
+
+int
+ACE_Thread_Manager::resume_grp (int grp_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::resume_grp");
+ return this->apply_grp (grp_id,
+ ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
+}
+
+// Kill a group of threads.
+
+int
+ACE_Thread_Manager::kill_grp (int grp_id, int signum)
+{
+ ACE_TRACE ("ACE_Thread_Manager::kill_grp");
+ return this->apply_grp (grp_id,
+ ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr), signum);
+}
+
+// Cancel a group of threads.
+
+int
+ACE_Thread_Manager::cancel_grp (int grp_id, int async_cancel)
+{
+ ACE_TRACE ("ACE_Thread_Manager::cancel_grp");
+ return this->apply_grp (grp_id,
+ ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
+ async_cancel);
+}
+
+int
+ACE_Thread_Manager::apply_all (ACE_THR_MEMBER_FUNC func, int arg)
+{
+ ACE_TRACE ("ACE_Thread_Manager::apply_all");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+ ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
+
+ int result = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if ((this->*func)(iter.next (), arg) == -1)
+ result = -1;
+
+ // Must remove threads after we have traversed the thr_list_ to
+ // prevent clobber thr_list_'s integrity.
+
+ if (! this->thr_to_be_removed_.is_empty ())
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+
+ for (ACE_Thread_Descriptor *td;
+ this->thr_to_be_removed_.dequeue_head (td) != -1;
+ )
+ this->remove_thr (td, 1);
+ }
+
+ return result;
+}
+
+// Resume all threads that are suspended.
+
+int
+ACE_Thread_Manager::resume_all (void)
+{
+ ACE_TRACE ("ACE_Thread_Manager::resume_all");
+ return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
+}
+
+int
+ACE_Thread_Manager::suspend_all (void)
+{
+ ACE_TRACE ("ACE_Thread_Manager::suspend_all");
+ return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
+}
+
+int
+ACE_Thread_Manager::kill_all (int sig)
+{
+ ACE_TRACE ("ACE_Thread_Manager::kill_all");
+ return this->apply_all (&ACE_Thread_Manager::kill_thr, sig);
+}
+
+int
+ACE_Thread_Manager::cancel_all (int async_cancel)
+{
+ ACE_TRACE ("ACE_Thread_Manager::cancel_all");
+ return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
+ async_cancel);
+}
+
+int
+ACE_Thread_Manager::join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status)
+{
+ ACE_TRACE ("ACE_Thread_Manager::join");
+
+ ACE_Thread_Descriptor_Base tdb;
+ int found = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+#if !defined (ACE_HAS_VXTHREADS)
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_);
+ !biter.done ();
+ biter.advance ())
+ if (ACE_OS::thr_equal (biter.next ()->thr_id_, tid))
+ {
+ ACE_Thread_Descriptor_Base *tdb = biter.advance_and_remove (0);
+# if defined (_AIX)
+ // The AIX xlC compiler does not match the proper function here - it
+ // confuses ACE_Thread::join(ACE_thread_t, ACE_thread_t *, void **=0) and
+ // ACE_Thread::join(ACE_hthread_t, void **=0). At least at 3.1.4.7 and .8.
+ // The 2nd arg is ignored for pthreads anyway.
+
+ // And, g++ on AIX needs the three-arg thr_join, also, to pick up the
+ // proper version from the AIX libraries.
+ if (ACE_Thread::join (tdb->thr_handle_,
+ &tdb->thr_handle_,
+ status) == -1)
+# else /* ! _AIX */
+ if (ACE_Thread::join (tdb->thr_handle_, status) == -1)
+# endif /* ! _AIX */
+ return -1;
+
+ delete tdb;
+ return 0;
+ // return immediately if we've found the thread we want to join.
+ }
+#endif /* !ACE_HAS_VXTHREADS */
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ // If threads are created as THR_DETACHED or THR_DAEMON, we
+ // can't help much.
+ if (ACE_OS::thr_equal (iter.next ()->thr_id_,tid) &&
+ (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
+ || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
+ {
+ tdb = *iter.next ();
+ ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
+ found = 1;
+ break;
+ }
+
+ if (found == 0)
+ return -1;
+ // Didn't find the thread we want or the thread is not joinable.
+ }
+
+# if defined (_AIX)
+ // The AIX xlC compiler does not match the proper function here - it
+ // confuses ACE_Thread::join(ACE_thread_t, ACE_thread_t *, void **=0) and
+ // ACE_Thread::join(ACE_hthread_t, void **=0). At least at 3.1.4.7 and .8.
+ // The 2nd arg is ignored for pthreads anyway.
+
+ // And, g++ on AIX needs the three-arg thr_join, also, to pick up the
+ // proper version from the AIX libraries.
+ if (ACE_Thread::join (tdb.thr_handle_, &tdb.thr_handle_, status) == -1)
+# else /* ! _AIX */
+ if (ACE_Thread::join (tdb.thr_handle_, status) == -1)
+# endif /* ! _AIX */
+ return -1;
+
+ return 0;
+}
+
+// Wait for group of threads
+
+int
+ACE_Thread_Manager::wait_grp (int grp_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::wait_grp");
+
+ int copy_count = 0;
+ ACE_Thread_Descriptor_Base *copy_table = 0;
+
+ // We have to make sure that while we wait for these threads to
+ // exit, we do not have the lock. Therefore we make a copy of all
+ // interesting entries and let go of the lock.
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+#if !defined (ACE_HAS_VXTHREADS)
+ ACE_NEW_RETURN (copy_table,
+ ACE_Thread_Descriptor_Base [this->thr_list_.size ()
+ + this->terminated_thr_list_.size ()],
+ -1);
+#else
+ ACE_NEW_RETURN (copy_table,
+ ACE_Thread_Descriptor_Base [this->thr_list_.size ()],
+ -1);
+#endif /* !ACE_HAS_VXTHREADS */
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ // If threads are created as THR_DETACHED or THR_DAEMON, we
+ // can't help much.
+ if (iter.next ()->grp_id_ == grp_id &&
+ (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
+ || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
+ {
+ ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
+ copy_table[copy_count++] = *iter.next ();
+ }
+
+#if !defined (ACE_HAS_VXTHREADS)
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_);
+ !biter.done ();
+ biter.advance ())
+ // If threads are created as THR_DETACHED or THR_DAEMON, we
+ // can't help much.
+ if (biter.next ()->grp_id_ == grp_id)
+ {
+ ACE_Thread_Descriptor_Base *tdb = biter.advance_and_remove (0);
+ copy_table[copy_count++] = *tdb;
+ delete tdb;
+ }
+#endif /* !ACE_HAS_VXTHREADS */
+ }
+
+ // Now actually join() with all the threads in this group.
+ int result = 0;
+
+ for (int i = 0;
+ i < copy_count && result != -1;
+ i++)
+ {
+ if (ACE_Thread::join (copy_table[i].thr_handle_) == -1)
+ result = -1;
+ }
+
+ delete [] copy_table;
+
+ return result;
+}
+
+// Must be called when thread goes out of scope to clean up its table
+// slot.
+
+ACE_THR_FUNC_RETURN
+ACE_Thread_Manager::exit (ACE_THR_FUNC_RETURN status, bool do_thread_exit)
+{
+ ACE_TRACE ("ACE_Thread_Manager::exit");
+#if defined (ACE_WIN32)
+ // Remove detached thread handle.
+
+ if (do_thread_exit)
+ {
+#if 0
+ // @@ This callback is now taken care of by TSS_Cleanup. Do we
+ // need it anymore?
+
+ // On Win32, if we really wants to exit from a thread, we must
+ // first clean up the thread specific storage. By doing so,
+ // ACE_Thread_Manager::exit will be called again with
+ // do_thr_exit = 0 and cleaning up the ACE_Cleanup_Info (but not
+ // exiting the thread.) After the following call returns, we
+ // are safe to exit this thread.
+ delete ACE_Thread_Exit::instance ();
+#endif /* 0 */
+ ACE_Thread::exit (status);
+ }
+#endif /* ACE_WIN32 */
+
+ // Just hold onto the guard while finding this thread's id and
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ // Find the thread id, but don't use the cache. It might have been
+ // deleted already.
+ ACE_thread_t const id = ACE_OS::thr_self ();
+ ACE_Thread_Descriptor* td = this->find_thread (id);
+ if (td != 0)
+ {
+ // @@ We call Thread_Descriptor terminate this realize the cleanup
+ // process itself.
+ td->terminate();
+ }
+ }
+
+ if (do_thread_exit)
+ {
+ ACE_Thread::exit (status);
+ // On reasonable systems <ACE_Thread::exit> should not return.
+ // However, due to horrible semantics with Win32 thread-specific
+ // storage this call can return (don't ask...).
+ }
+
+ return 0;
+}
+
+// Wait for all the threads to exit.
+
+int
+ACE_Thread_Manager::wait (const ACE_Time_Value *timeout,
+ bool abandon_detached_threads,
+ bool use_absolute_time)
+{
+ ACE_TRACE ("ACE_Thread_Manager::wait");
+
+ ACE_Time_Value local_timeout;
+ // Check to see if we're using absolute time or not.
+ if (use_absolute_time == false && timeout != 0)
+ {
+ local_timeout = *timeout;
+ local_timeout += ACE_OS::gettimeofday ();
+ timeout = &local_timeout;
+ }
+
+#if !defined (ACE_HAS_VXTHREADS)
+ ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> term_thr_list_copy;
+#endif /* ACE_HAS_VXTHREADS */
+
+#if defined (ACE_HAS_THREADS)
+ {
+ // Just hold onto the guard while waiting.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (ACE_Object_Manager::shutting_down () != 1)
+ {
+ // Program is not shutting down. Perform a normal wait on threads.
+ if (abandon_detached_threads != 0)
+ {
+ ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>
+ iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (ACE_BIT_ENABLED (iter.next ()->flags_,
+ THR_DETACHED | THR_DAEMON)
+ && ACE_BIT_DISABLED (iter.next ()->flags_, THR_JOINABLE))
+ {
+ this->thr_to_be_removed_.enqueue_tail (iter.next ());
+ ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
+ }
+
+ if (! this->thr_to_be_removed_.is_empty ())
+ {
+ ACE_Thread_Descriptor *td = 0;
+ while (this->thr_to_be_removed_.dequeue_head (td) != -1)
+ this->remove_thr (td, 1);
+ }
+ }
+
+ while (this->thr_list_.size () > 0)
+ if (this->zero_cond_.wait (timeout) == -1)
+ return -1;
+ }
+ else
+ // Program is shutting down, no chance to wait on threads.
+ // Therefore, we'll just remove threads from the list.
+ this->remove_thr_all ();
+
+#if !defined (ACE_HAS_VXTHREADS)
+ ACE_Thread_Descriptor_Base* item = 0;
+ while ((item = this->terminated_thr_list_.delete_head ()) != 0)
+ {
+ term_thr_list_copy.insert_tail (item);
+ }
+#endif /* ACE_HAS_VXTHREADS */
+ // Release the guard, giving other threads a chance to run.
+ }
+
+#if !defined (ACE_HAS_VXTHREADS)
+ // @@ VxWorks doesn't support thr_join (yet.) We are working
+ // on our implementation. Chorus'es thr_join seems broken.
+ ACE_Thread_Descriptor_Base *item = 0;
+
+ while ((item = term_thr_list_copy.delete_head ()) != 0)
+ {
+ if (ACE_BIT_DISABLED (item->flags_, THR_DETACHED | THR_DAEMON)
+ || ACE_BIT_ENABLED (item->flags_, THR_JOINABLE))
+ // Detached handles shouldn't reached here.
+ (void) ACE_Thread::join (item->thr_handle_);
+
+ delete item;
+ }
+
+#endif /* !ACE_HAS_VXTHREADS */
+#else
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (abandon_detached_threads);
+#endif /* ACE_HAS_THREADS */
+
+ return 0;
+}
+
+int
+ACE_Thread_Manager::apply_task (ACE_Task_Base *task,
+ ACE_THR_MEMBER_FUNC func,
+ int arg)
+{
+ ACE_TRACE ("ACE_Thread_Manager::apply_task");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+ ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
+
+ int result = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (iter.next ()->task_ == task
+ && (this->*func) (iter.next (), arg) == -1)
+ result = -1;
+
+ // Must remove threads after we have traversed the thr_list_ to
+ // prevent clobber thr_list_'s integrity.
+
+ if (! this->thr_to_be_removed_.is_empty ())
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+
+ for (ACE_Thread_Descriptor *td;
+ this->thr_to_be_removed_.dequeue_head (td) != -1;
+ )
+ this->remove_thr (td, 1);
+ }
+
+ return result;
+}
+
+// Wait for all threads to exit a task.
+
+int
+ACE_Thread_Manager::wait_task (ACE_Task_Base *task)
+{
+ int copy_count = 0;
+ ACE_Thread_Descriptor_Base *copy_table = 0;
+
+ // We have to make sure that while we wait for these threads to
+ // exit, we do not have the lock. Therefore we make a copy of all
+ // interesting entries and let go of the lock.
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+#if !defined (ACE_HAS_VXTHREADS)
+ ACE_NEW_RETURN (copy_table,
+ ACE_Thread_Descriptor_Base [this->thr_list_.size ()
+ + this->terminated_thr_list_.size ()],
+ -1);
+#else
+ ACE_NEW_RETURN (copy_table,
+ ACE_Thread_Descriptor_Base [this->thr_list_.size ()],
+ -1);
+#endif /* !ACE_HAS_VXTHREADS */
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ // If threads are created as THR_DETACHED or THR_DAEMON, we
+ // can't wait on them here.
+ if (iter.next ()->task_ == task &&
+ (ACE_BIT_DISABLED (iter.next ()->flags_,
+ THR_DETACHED | THR_DAEMON)
+ || ACE_BIT_ENABLED (iter.next ()->flags_,
+ THR_JOINABLE)))
+ {
+ ACE_SET_BITS (iter.next ()->thr_state_,
+ ACE_THR_JOINING);
+ copy_table[copy_count++] = *iter.next ();
+ }
+
+#if !defined (ACE_HAS_VXTHREADS)
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> titer (this->terminated_thr_list_);
+ !titer.done ();
+ titer.advance ())
+ // If threads are created as THR_DETACHED or THR_DAEMON, we can't help much here.
+ if (titer.next ()->task_ == task)
+ {
+ ACE_Thread_Descriptor_Base *tdb =
+ titer.advance_and_remove (0);
+ copy_table[copy_count++] = *tdb;
+ delete tdb;
+ }
+#endif /* !ACE_HAS_VXTHREADS */
+ }
+
+ // Now to do the actual work
+ int result = 0;
+
+ for (int i = 0;
+ i < copy_count && result != -1;
+ i++)
+ {
+ if (ACE_Thread::join (copy_table[i].thr_handle_) == -1)
+ result = -1;
+ }
+
+ delete [] copy_table;
+
+ return result;
+}
+
+// Suspend a task
+
+int
+ACE_Thread_Manager::suspend_task (ACE_Task_Base *task)
+{
+ ACE_TRACE ("ACE_Thread_Manager::suspend_task");
+ return this->apply_task (task,
+ ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
+}
+
+// Resume a task.
+int
+ACE_Thread_Manager::resume_task (ACE_Task_Base *task)
+{
+ ACE_TRACE ("ACE_Thread_Manager::resume_task");
+ return this->apply_task (task,
+ ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
+}
+
+// Kill a task.
+
+int
+ACE_Thread_Manager::kill_task (ACE_Task_Base *task, int /* signum */)
+{
+ ACE_TRACE ("ACE_Thread_Manager::kill_task");
+ return this->apply_task (task,
+ ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr));
+}
+
+// Cancel a task.
+int
+ACE_Thread_Manager::cancel_task (ACE_Task_Base *task,
+ int async_cancel)
+{
+ ACE_TRACE ("ACE_Thread_Manager::cancel_task");
+ return this->apply_task (task,
+ ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
+ async_cancel);
+}
+
+// Locate the index in the table associated with <task> from the
+// beginning of the table up to an index. Must be called with the
+// lock held.
+
+ACE_Thread_Descriptor *
+ACE_Thread_Manager::find_task (ACE_Task_Base *task, size_t slot)
+{
+ ACE_TRACE ("ACE_Thread_Manager::find_task");
+
+ size_t i = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (i >= slot)
+ break;
+
+ if (task == iter.next ()->task_)
+ return iter.next ();
+
+ ++i;
+ }
+
+ return 0;
+}
+
+// Returns the number of ACE_Task in a group.
+
+int
+ACE_Thread_Manager::num_tasks_in_group (int grp_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::num_tasks_in_group");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ int tasks_count = 0;
+ size_t i = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (iter.next ()->grp_id_ == grp_id
+ && this->find_task (iter.next ()->task_, i) == 0
+ && iter.next ()->task_ != 0)
+ ++tasks_count;
+
+ ++i;
+ }
+ return tasks_count;
+}
+
+// Returns the number of threads in an ACE_Task.
+
+int
+ACE_Thread_Manager::num_threads_in_task (ACE_Task_Base *task)
+{
+ ACE_TRACE ("ACE_Thread_Manager::num_threads_in_task");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ int threads_count = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (iter.next ()->task_ == task)
+ ++threads_count;
+
+ return threads_count;
+}
+
+// Returns in task_list a list of ACE_Tasks registered with ACE_Thread_Manager.
+
+ssize_t
+ACE_Thread_Manager::task_all_list (ACE_Task_Base *task_list[],
+ size_t n)
+{
+ ACE_TRACE ("ACE_Thread_Manager::task_all_list");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ size_t task_list_count = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (task_list_count >= n)
+ break;
+
+ ACE_Task_Base *task_p = iter.next ()->task_;
+ if (0 != task_p)
+ {
+ // This thread has a task pointer; see if it's already in the
+ // list. Don't add duplicates.
+ size_t i = 0;
+ for (; i < task_list_count; ++i)
+ if (task_list[i] == task_p)
+ break;
+ if (i == task_list_count) // No match - add this one
+ task_list[task_list_count++] = task_p;
+ }
+ }
+
+ return task_list_count;
+}
+
+// Returns in thread_list a list of all thread ids
+
+ssize_t
+ACE_Thread_Manager::thread_all_list (ACE_thread_t thread_list[],
+ size_t n)
+{
+ ACE_TRACE ("ACE_Thread_Manager::thread_all_list");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ size_t thread_count = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (thread_count >= n)
+ break;
+
+ thread_list[thread_count] = iter.next ()->thr_id_;
+ ++thread_count;
+ }
+
+ return thread_count;
+}
+
+
+int
+ACE_Thread_Manager::thr_state (ACE_thread_t id,
+ ACE_UINT32& state)
+{
+ ACE_TRACE ("ACE_Thread_Manager::thr_state");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ int const self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ());
+
+ // If we're checking the state of our thread, try to get the cached
+ // value out of TSS to avoid lookup.
+ if (self_check)
+ {
+ ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc ();
+ if (desc == 0)
+ return 0; // Always return false.
+ state = desc->thr_state_;
+ }
+ else
+ {
+ // Not calling from self, have to look it up from the list.
+ ACE_FIND (this->find_thread (id), ptr);
+ if (ptr == 0)
+ return 0;
+ state = ptr->thr_state_;
+ }
+
+ return 1;
+}
+
+// Returns in task_list a list of ACE_Tasks in a group.
+
+ssize_t
+ACE_Thread_Manager::task_list (int grp_id,
+ ACE_Task_Base *task_list[],
+ size_t n)
+{
+ ACE_TRACE ("ACE_Thread_Manager::task_list");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ ACE_Task_Base **task_list_iterator = task_list;
+ size_t task_list_count = 0;
+ size_t i = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (task_list_count >= n)
+ break;
+
+ if (iter.next ()->grp_id_ == grp_id
+ && this->find_task (iter.next ()->task_, i) == 0)
+ {
+ task_list_iterator[task_list_count] = iter.next ()->task_;
+ ++task_list_count;
+ }
+
+ ++i;
+ }
+
+ return task_list_count;
+}
+
+// Returns in thread_list a list of thread ids in an ACE_Task.
+
+ssize_t
+ACE_Thread_Manager::thread_list (ACE_Task_Base *task,
+ ACE_thread_t thread_list[],
+ size_t n)
+{
+ ACE_TRACE ("ACE_Thread_Manager::thread_list");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ size_t thread_count = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (thread_count >= n)
+ break;
+
+ if (iter.next ()->task_ == task)
+ {
+ thread_list[thread_count] = iter.next ()->thr_id_;
+ ++thread_count;
+ }
+ }
+
+ return thread_count;
+}
+
+// Returns in thread_list a list of thread handles in an ACE_Task.
+
+ssize_t
+ACE_Thread_Manager::hthread_list (ACE_Task_Base *task,
+ ACE_hthread_t hthread_list[],
+ size_t n)
+{
+ ACE_TRACE ("ACE_Thread_Manager::hthread_list");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ size_t hthread_count = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (hthread_count >= n)
+ break;
+
+ if (iter.next ()->task_ == task)
+ {
+ hthread_list[hthread_count] = iter.next ()->thr_handle_;
+ ++hthread_count;
+ }
+ }
+
+ return hthread_count;
+}
+
+ssize_t
+ACE_Thread_Manager::thread_grp_list (int grp_id,
+ ACE_thread_t thread_list[],
+ size_t n)
+{
+ ACE_TRACE ("ACE_Thread_Manager::thread_grp_list");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ size_t thread_count = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (thread_count >= n)
+ break;
+
+ if (iter.next ()->grp_id_ == grp_id)
+ {
+ thread_list[thread_count] = iter.next ()->thr_id_;
+ thread_count++;
+ }
+ }
+
+ return thread_count;
+}
+
+// Returns in thread_list a list of thread handles in an ACE_Task.
+
+ssize_t
+ACE_Thread_Manager::hthread_grp_list (int grp_id,
+ ACE_hthread_t hthread_list[],
+ size_t n)
+{
+ ACE_TRACE ("ACE_Thread_Manager::hthread_grp_list");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ size_t hthread_count = 0;
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ {
+ if (hthread_count >= n)
+ break;
+
+ if (iter.next ()->grp_id_ == grp_id)
+ {
+ hthread_list[hthread_count] = iter.next ()->thr_handle_;
+ hthread_count++;
+ }
+ }
+
+ return hthread_count;
+}
+
+int
+ACE_Thread_Manager::set_grp (ACE_Task_Base *task, int grp_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::set_grp");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
+ !iter.done ();
+ iter.advance ())
+ if (iter.next ()->task_ == task)
+ iter.next ()->grp_id_ = grp_id;
+
+ return 0;
+}
+
+int
+ACE_Thread_Manager::get_grp (ACE_Task_Base *task, int &grp_id)
+{
+ ACE_TRACE ("ACE_Thread_Manager::get_grp");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ ACE_FIND (this->find_task (task), ptr);
+ grp_id = ptr->grp_id_;
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Manager.h b/ACE/ace/Thread_Manager.h
new file mode 100644
index 00000000000..bccfab12e1e
--- /dev/null
+++ b/ACE/ace/Thread_Manager.h
@@ -0,0 +1,1136 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Thread_Manager.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_THREAD_MANAGER_H
+#define ACE_THREAD_MANAGER_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Thread.h"
+#include "ace/Thread_Adapter.h"
+#include "ace/Thread_Exit.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Condition_Thread_Mutex.h"
+#include "ace/Unbounded_Queue.h"
+#include "ace/Containers.h"
+#include "ace/Free_List.h"
+#include "ace/Singleton.h"
+#include "ace/Log_Msg.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Basic_Types.h"
+
+// The following macros control how a Thread Manager manages a pool of
+// Thread_Descriptor. Currently, the default behavior is not to
+// preallocate any thread descriptor and never (well, almost never)
+// free up any thread descriptor until the Thread Manager gets
+// destructed. Which means, once your system is stable, you rarely
+// need to pay the price of memory allocation. On a deterministic
+// system, which means, the number of threads spawned can be
+// determined before hand, you can either redefine the memory pool
+// size macros to suit your need or constructed the Thread_Manager
+// accordingly. That way, you don't pay the price of memory
+// allocation when the system is really doing its job. OTOH, on
+// system with resources constraint, you may want to lower the size of
+// ACE_DEFAULT_THREAD_MANAGER_HWM to avoid unused memory hanging
+// around.
+
+#if !defined (ACE_DEFAULT_THREAD_MANAGER_PREALLOC)
+# define ACE_DEFAULT_THREAD_MANAGER_PREALLOC 0
+#endif /* ACE_DEFAULT_THREAD_MANAGER_PREALLOC */
+
+#if !defined (ACE_DEFAULT_THREAD_MANAGER_LWM)
+# define ACE_DEFAULT_THREAD_MANAGER_LWM 1
+#endif /* ACE_DEFAULT_THREAD_MANAGER_LWM */
+
+#if !defined (ACE_DEFAULT_THREAD_MANAGER_INC)
+# define ACE_DEFAULT_THREAD_MANAGER_INC 1
+#endif /* ACE_DEFAULT_THREAD_MANAGER_INC */
+
+#if !defined (ACE_DEFAULT_THREAD_MANAGER_HWM)
+# define ACE_DEFAULT_THREAD_MANAGER_HWM ACE_DEFAULT_FREE_LIST_HWM
+// this is a big number
+#endif /* ACE_DEFAULT_THREAD_MANAGER_HWM */
+
+// This is the synchronization mechanism used to prevent a thread
+// descriptor gets removed from the Thread_Manager before it gets
+// stash into it. If you want to disable this feature (and risk of
+// corrupting the freelist,) you define the lock as ACE_Null_Mutex.
+// Usually, if you can be sure that your threads will run for an
+// extended period of time, you can safely disable the lock.
+
+#if !defined (ACE_DEFAULT_THREAD_MANAGER_LOCK)
+# define ACE_DEFAULT_THREAD_MANAGER_LOCK ACE_SYNCH_MUTEX
+#endif /* ACE_DEFAULT_THREAD_MANAGER_LOCK */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+class ACE_Task_Base;
+class ACE_Thread_Manager;
+class ACE_Thread_Descriptor;
+
+/**
+ * @class ACE_At_Thread_Exit
+ *
+ * @brief Contains a method to be applied when a thread is terminated.
+ */
+class ACE_Export ACE_At_Thread_Exit
+{
+ friend class ACE_Thread_Descriptor;
+ friend class ACE_Thread_Manager;
+public:
+ /// Default constructor
+ ACE_At_Thread_Exit (void);
+
+ /// The destructor
+ virtual ~ACE_At_Thread_Exit (void);
+
+ /// At_Thread_Exit has the ownership?
+ bool is_owner (void) const;
+
+ /// Set the ownership of the At_Thread_Exit.
+ bool is_owner (bool owner);
+
+ /// This At_Thread_Exit was applied?
+ int was_applied (void) const;
+
+ /// Set applied state of At_Thread_Exit.
+ int was_applied (int applied);
+
+protected:
+ /// The next At_Thread_Exit hook in the list.
+ ACE_At_Thread_Exit *next_;
+
+ /// Do the apply if necessary
+ void do_apply (void);
+
+ /// The apply method.
+ virtual void apply (void) = 0;
+
+ /// The Thread_Descriptor where this at is registered.
+ ACE_Thread_Descriptor* td_;
+
+ /// The at was applied?
+ int was_applied_;
+
+ /// The at has the ownership of this?
+ bool is_owner_;
+};
+
+class ACE_Export ACE_At_Thread_Exit_Func : public ACE_At_Thread_Exit
+{
+public:
+ /// Constructor
+ ACE_At_Thread_Exit_Func (void *object,
+ ACE_CLEANUP_FUNC func,
+ void *param = 0);
+
+ virtual ~ACE_At_Thread_Exit_Func (void);
+
+protected:
+ /// The object to be cleanup
+ void *object_;
+
+ /// The cleanup func
+ ACE_CLEANUP_FUNC func_;
+
+ /// A param if required
+ void *param_;
+
+ /// The apply method
+ void apply (void);
+};
+
+/**
+ * @class ACE_Thread_Descriptor_Base
+ *
+ * @brief Basic information for thread descriptors. These information
+ * gets extracted out because we need it after a thread is
+ * terminated.
+ *
+ * @internal
+ */
+class ACE_Export ACE_Thread_Descriptor_Base : public ACE_OS_Thread_Descriptor
+{
+
+ friend class ACE_Thread_Manager;
+ friend class ACE_Double_Linked_List<ACE_Thread_Descriptor_Base>;
+ friend class ACE_Double_Linked_List_Iterator_Base<ACE_Thread_Descriptor_Base>;
+ friend class ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base>;
+ friend class ACE_Double_Linked_List<ACE_Thread_Descriptor>;
+ friend class ACE_Double_Linked_List_Iterator_Base<ACE_Thread_Descriptor>;
+ friend class ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>;
+public:
+ ACE_Thread_Descriptor_Base (void);
+ ~ACE_Thread_Descriptor_Base (void);
+
+ // = We need the following operators to make Borland happy.
+
+ /// Equality operator.
+ bool operator== (const ACE_Thread_Descriptor_Base &rhs) const;
+
+ /// Inequality operator.
+ bool operator!= (const ACE_Thread_Descriptor_Base &rhs) const;
+
+ /// Group ID.
+ int grp_id (void) const;
+
+ /// Current state of the thread.
+ ACE_UINT32 state (void) const;
+
+ /// Return the pointer to an ACE_Task_Base or NULL if there's no
+ /// ACE_Task_Base associated with this thread.;
+ ACE_Task_Base *task (void) const;
+
+protected:
+ /// Reset this base thread descriptor.
+ void reset (void);
+
+ /// Unique thread ID.
+ ACE_thread_t thr_id_;
+
+ /// Unique handle to thread (used by Win32 and AIX).
+ ACE_hthread_t thr_handle_;
+
+ /// Group ID.
+ int grp_id_;
+
+ /// Current state of the thread.
+ ACE_UINT32 thr_state_;
+
+ /// Pointer to an ACE_Task_Base or NULL if there's no
+ /// ACE_Task_Base.
+ ACE_Task_Base *task_;
+
+ /// We need these pointers to maintain the double-linked list in a
+ /// thread managers.
+ ACE_Thread_Descriptor_Base *next_;
+ ACE_Thread_Descriptor_Base *prev_;
+};
+
+/**
+ * @class ACE_Thread_Descriptor
+ *
+ * @brief Information for controlling threads that run under the control
+ * of the <Thread_Manager>.
+ */
+class ACE_Export ACE_Thread_Descriptor : public ACE_Thread_Descriptor_Base
+{
+ friend class ACE_At_Thread_Exit;
+ friend class ACE_Thread_Manager;
+ friend class ACE_Double_Linked_List<ACE_Thread_Descriptor>;
+ friend class ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>;
+public:
+ // = Initialization method.
+ ACE_Thread_Descriptor (void);
+
+ // = Accessor methods.
+ /// Unique thread id.
+ ACE_thread_t self (void) const;
+
+ /// Unique handle to thread (used by Win32 and AIX).
+ void self (ACE_hthread_t &);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /**
+ * This cleanup function must be called only for ACE_TSS_cleanup.
+ * The ACE_TSS_cleanup delegate Log_Msg instance destruction when
+ * Log_Msg cleanup is called before terminate.
+ */
+ void log_msg_cleanup(ACE_Log_Msg* log_msg);
+
+ /**
+ * Register an At_Thread_Exit hook and the ownership is acquire by
+ * Thread_Descriptor, this is the usual case when the AT is dynamically
+ * allocated.
+ */
+ int at_exit (ACE_At_Thread_Exit* cleanup);
+
+ /// Register an At_Thread_Exit hook and the ownership is retained for the
+ /// caller. Normally used when the at_exit hook is created in stack.
+ int at_exit (ACE_At_Thread_Exit& cleanup);
+
+ /**
+ * Register an object (or array) for cleanup at thread termination.
+ * "cleanup_hook" points to a (global, or static member) function
+ * that is called for the object or array when it to be destroyed.
+ * It may perform any necessary cleanup specific for that object or
+ * its class. "param" is passed as the second parameter to the
+ * "cleanup_hook" function; the first parameter is the object (or
+ * array) to be destroyed. Returns 0 on success, non-zero on
+ * failure: -1 if virtual memory is exhausted or 1 if the object (or
+ * arrayt) had already been registered.
+ */
+ int at_exit (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param);
+
+ /// Do nothing destructor to keep some compilers happy
+ ~ACE_Thread_Descriptor (void);
+
+ /**
+ * Do nothing but to acquire the thread descriptor's lock and
+ * release. This will first check if the thread is registered or
+ * not. If it is already registered, there's no need to reacquire
+ * the lock again. This is used mainly to get newly spawned thread
+ * in synch with thread manager and prevent it from accessing its
+ * thread descriptor before it gets fully built. This function is
+ * only called from ACE_Log_Msg::thr_desc.
+ */
+ void acquire_release (void);
+ void acquire (void);
+ void release (void);
+
+ /**
+ * Set/get the @c next_ pointer. These are required by the
+ * ACE_Free_List.
+ */
+ void set_next (ACE_Thread_Descriptor *td);
+ ACE_Thread_Descriptor *get_next (void) const;
+
+private:
+ /// Reset this thread descriptor.
+ void reset (ACE_Thread_Manager *tm);
+
+ /// Pop an At_Thread_Exit from at thread termination list, apply the at
+ /// if apply is true.
+ void at_pop (int apply = 1);
+
+ /// Push an At_Thread_Exit to at thread termination list and set the
+ /// ownership of at.
+ void at_push (ACE_At_Thread_Exit* cleanup,
+ bool is_owner = false);
+
+ /// Run the AT_Thread_Exit hooks.
+ void do_at_exit (void);
+
+ /// Terminate realize the cleanup process to thread termination
+ void terminate (void);
+
+ /// Thread_Descriptor is the ownership of ACE_Log_Msg if log_msg_!=0
+ /// This can occur because ACE_TSS_cleanup was executed before terminate.
+ ACE_Log_Msg *log_msg_;
+
+ /// The AT_Thread_Exit list
+ ACE_At_Thread_Exit *at_exit_list_;
+
+ /**
+ * Stores the cleanup info for a thread.
+ * @note This should be generalized to be a stack of ACE_Cleanup_Info's.
+ */
+ ACE_Cleanup_Info cleanup_info_;
+
+ /// Pointer to an ACE_Thread_Manager or NULL if there's no
+ /// ACE_Thread_Manager>
+ ACE_Thread_Manager* tm_;
+
+ /// Registration lock to prevent premature removal of thread descriptor.
+ ACE_DEFAULT_THREAD_MANAGER_LOCK *sync_;
+
+ /// Keep track of termination status.
+ bool terminated_;
+};
+
+// Forward declaration.
+class ACE_Thread_Control;
+
+// This typedef should be (and used to be) inside the
+// ACE_Thread_Manager declaration. But, it caused compilation
+// problems on g++/VxWorks/i960 with -g. Note that
+// ACE_Thread_Manager::THR_FUNC is only used internally in
+// ACE_Thread_Manager, so it's not useful for anyone else.
+// It also caused problems on IRIX5 with g++.
+#if defined (__GNUG__)
+typedef int (ACE_Thread_Manager::*ACE_THR_MEMBER_FUNC)(ACE_Thread_Descriptor *, int);
+#endif /* __GNUG__ */
+
+/**
+ * @class ACE_Thread_Manager
+ *
+ * @brief Manages a pool of threads.
+ *
+ * This class allows operations on groups of threads atomically.
+ * The default behavior of thread manager is to wait on
+ * all threads under it's management when it gets destructed.
+ * Therefore, remember to remove a thread from thread manager if
+ * you don't want it to wait for the thread. There are also
+ * function to disable this default wait-on-exit behavior.
+ * However, if your program depends on turning this off to run
+ * correctly, you are probably doing something wrong. Rule of
+ * thumb, use ACE_Thread to manage your daemon threads.
+ * Notice that if there're threads live beyond the scope of
+ * <main>, you are sure to have resource leaks in your program.
+ * Remember to wait on threads before exiting <main> if that
+ * could happen in your programs.
+ */
+class ACE_Export ACE_Thread_Manager
+{
+public:
+ friend class ACE_Thread_Control;
+
+ // Allow ACE_THread_Exit to register the global TSS instance object.
+ friend class ACE_Thread_Exit;
+ friend class ACE_Thread_Descriptor;
+
+#if !defined (__GNUG__)
+ typedef int (ACE_Thread_Manager::*ACE_THR_MEMBER_FUNC)(ACE_Thread_Descriptor *, int);
+#endif /* !__GNUG__ */
+
+ /// These are the various states a thread managed by the
+ /// ACE_Thread_Manager can be in.
+ enum
+ {
+ /// Uninitialized.
+ ACE_THR_IDLE = 0x00000000,
+
+ /// Created but not yet running.
+ ACE_THR_SPAWNED = 0x00000001,
+
+ /// Thread is active (naturally, we don't know if it's actually
+ /// *running* because we aren't the scheduler...).
+ ACE_THR_RUNNING = 0x00000002,
+
+ /// Thread is suspended.
+ ACE_THR_SUSPENDED = 0x00000004,
+
+ /// Thread has been cancelled (which is an indiction that it needs to
+ /// terminate...).
+ ACE_THR_CANCELLED = 0x00000008,
+
+ /// Thread has shutdown, but the slot in the thread manager hasn't
+ /// been reclaimed yet.
+ ACE_THR_TERMINATED = 0x00000010,
+
+ /// Join operation has been invoked on the thread by thread manager.
+ ACE_THR_JOINING = 0x10000000
+ };
+
+ // = Initialization and termination methods.
+ /**
+ * @brief Initialization and termination methods.
+ *
+ * Internally, ACE_Thread_Manager keeps a freelist for caching
+ * resources it uses to keep track of managed threads (not the
+ * threads themselves.) @a prealloc, @a lwm, @a inc, @hwm
+ * determine the initial size, the low water mark, increment step,
+ * and high water mark of the freelist.
+ *
+ * @sa ACE_Free_List
+ */
+ ACE_Thread_Manager (size_t preaolloc = ACE_DEFAULT_THREAD_MANAGER_PREALLOC,
+ size_t lwm = ACE_DEFAULT_THREAD_MANAGER_LWM,
+ size_t inc = ACE_DEFAULT_THREAD_MANAGER_INC,
+ size_t hwm = ACE_DEFAULT_THREAD_MANAGER_HWM);
+ ~ACE_Thread_Manager (void);
+
+#if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
+ /// Get pointer to a process-wide ACE_Thread_Manager.
+ static ACE_Thread_Manager *instance (void);
+
+ /// Set pointer to a process-wide ACE_Thread_Manager and return
+ /// existing pointer.
+ static ACE_Thread_Manager *instance (ACE_Thread_Manager *);
+
+ /// Delete the dynamically allocated Singleton
+ static void close_singleton (void);
+#endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
+
+ /// No-op. Currently unused.
+ int open (size_t size = 0);
+
+ /**
+ * Release all resources.
+ * By default, this method will wait till all threads
+ * exit. However, when called from <close_singleton>, most global resources
+ * are destroyed and thus, we don't try to wait but just clean up the thread
+ * descriptor list.
+ */
+ int close (void);
+
+ /**
+ * Create a new thread, which executes @a func with argument @a arg.
+ * Returns: on success a unique group id that can be used to control
+ * other threads added to the same group. On failure, returns -1.
+ */
+ int spawn (ACE_THR_FUNC func,
+ void *arg = 0,
+ long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED,
+ ACE_thread_t * = 0,
+ ACE_hthread_t *t_handle = 0,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ int grp_id = -1,
+ void *stack = 0,
+ size_t stack_size = ACE_DEFAULT_THREAD_STACKSIZE,
+ const char** thr_name = 0);
+
+ /**
+ * Spawn N new threads, which execute @a func with argument @a arg.
+ * If <thread_ids> != 0 the thread_ids of successfully spawned
+ * threads will be placed into the <thread_ids> buffer (which must
+ * be the same size as @a n). If @a stack != 0 it is assumed to be an
+ * array of @a n pointers to the base of the stacks to use for the
+ * threads being spawned. If @a stack_size != 0 it is assumed to be
+ * an array of @a n values indicating how big each of the
+ * corresponding @a stacks are. If @a thread_handles != 0 it is
+ * assumed to be an array of @a n thread_handles that will be
+ * assigned the values of the thread handles being spawned.
+ *
+ * Threads in Thread_Manager can be manipulated in groups based on
+ * @a grp_id or @a task using functions such as kill_grp() or
+ * cancel_task().
+ *
+ * If @a grp_id is assigned, the newly spawned threads are added into
+ * the group. Otherwise, the Thread_Manager assigns these @a n
+ * threads with a grp_id. You should choose either assigning
+ * @a grp_id everytime, or let the Thread_Manager handles it for
+ * you consistently.
+ *
+ * The argument @a task is usually assigned by
+ * <ACE_Task_Base::activate>. It associates the newly spawned
+ * threads with an ACE_Task instance, which defaults to @c this.
+ *
+ * @retval -1 on failure (@c errno will explain...), otherwise returns the
+ * group id of the threads.
+ */
+ int spawn_n (size_t n,
+ ACE_THR_FUNC func,
+ void *arg = 0,
+ long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ int grp_id = -1,
+ ACE_Task_Base *task = 0,
+ ACE_hthread_t thread_handles[] = 0,
+ void *stack[] = 0,
+ size_t stack_size[] = 0,
+ const char* thr_name[] = 0);
+
+ /**
+ * Spawn N new threads, which execute @a func with argument @a arg.
+ * If <thread_ids> != 0 the thread_ids of successfully spawned
+ * threads will be placed into the <thread_ids> buffer (which must
+ * be the same size as @a n). If @a stack != 0 it is assumed to be an
+ * array of @a n pointers to the base of the stacks to use for the
+ * threads being spawned. If @a stack_size != 0 it is assumed to be
+ * an array of @a n values indicating how big each of the
+ * corresponding @a stacks are. If @a thread_handles != 0 it is
+ * assumed to be an array of @a n thread_handles that will be
+ * assigned the values of the thread handles being spawned.
+ *
+ * Threads in Thread_Manager can be manipulated in groups based on
+ * @a grp_id or @a task using functions such as kill_grp() or
+ * cancel_task().
+ *
+ * If @a grp_id is assigned, the newly spawned threads are added into
+ * the group. Otherwise, the Thread_Manager assigns these @a n
+ * threads with a grp_id. You should choose either assigning
+ * @a grp_id everytime, or let the Thread_Manager handles it for
+ * you consistently.
+ *
+ * The argument @a task is usually assigned by
+ * <ACE_Task_Base::activate>. It associates the newly spawned
+ * threads with an ACE_Task instance, which defaults to @c this.
+ *
+ * @retval -1 on failure (@c errno will explain...), otherwise returns the
+ * group id of the threads.
+ */
+ int spawn_n (ACE_thread_t thread_ids[],
+ size_t n,
+ ACE_THR_FUNC func,
+ void *arg,
+ long flags,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ int grp_id = -1,
+ void *stack[] = 0,
+ size_t stack_size[] = 0,
+ ACE_hthread_t thread_handles[] = 0,
+ ACE_Task_Base *task = 0,
+ const char* thr_name[] = 0);
+
+ /**
+ * Called to clean up when a thread exits.
+ *
+ * @param do_thread_exit If non-0 then ACE_Thread::exit is called to
+ * exit the thread
+ * @param status If ACE_Thread_Exit is called, this is passed as
+ * the exit value of the thread.
+ * Should _not_ be called by main thread.
+ */
+ ACE_THR_FUNC_RETURN exit (ACE_THR_FUNC_RETURN status = 0,
+ bool do_thread_exit = true);
+
+ /**
+ * Block until there are no more threads running in this thread
+ * manager or @c timeout expires.
+ *
+ * @param timeout is treated as "absolute" time by default, but this
+ * can be changed to "relative" time by setting the @c
+ * use_absolute_time to false.
+ * @param abandon_detached_threads If true, @c wait() will first
+ * check thru its thread list for
+ * threads with THR_DETACHED or
+ * THR_DAEMON flags set and remove
+ * these threads. Notice that
+ * unlike other @c wait_*() methods,
+ * by default, @c wait() does wait on
+ * all thread spawned by this
+ * thread manager no matter the detached
+ * flags are set or not unless it is
+ * called with @c
+ * abandon_detached_threads flag set.
+ * @param use_absolute_time If true then treat @c timeout as
+ * absolute time, else relative time.
+ * @return 0 on success * and -1 on failure.
+ *
+ * @note If this function is called while the @c
+ * ACE_Object_Manager is shutting down (as a result of program
+ * rundown via @c ACE::fini()), it will not wait for any threads to
+ * complete. If you must wait for threads spawned by this thread
+ * manager to complete and you are in a ACE rundown situation (such
+ * as your object is being destroyed by the @c ACE_Object_Manager)
+ * you can use @c wait_grp() instead.
+ */
+ int wait (const ACE_Time_Value *timeout = 0,
+ bool abandon_detached_threads = false,
+ bool use_absolute_time = true);
+
+ /// Join a thread specified by @a tid. Do not wait on a detached thread.
+ int join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status = 0);
+
+ /**
+ * Block until there are no more threads running in a group.
+ * Returns 0 on success and -1 on failure. Notice that wait_grp
+ * will not wait on detached threads.
+ */
+ int wait_grp (int grp_id);
+
+ /**
+ * Return the "real" handle to the calling thread, caching it if
+ * necessary in TSS to speed up subsequent lookups. This is
+ * necessary since on some platforms (e.g., Win32) we can't get this
+ * handle via direct method calls. Notice that you should *not*
+ * close the handle passed back from this method. It is used
+ * internally by Thread Manager. On the other hand, you *have to*
+ * use this internal thread handle when working on Thread_Manager.
+ * Return -1 if fail.
+ */
+ int thr_self (ACE_hthread_t &);
+
+ /**
+ * Return the unique ID of the thread. This is not strictly
+ * necessary (because a thread can always just call
+ * <ACE_Thread::self>). However, we put it here to be complete.
+ */
+ ACE_thread_t thr_self (void);
+
+ /**
+ * Returns a pointer to the current ACE_Task_Base we're executing
+ * in if this thread is indeed running in an ACE_Task_Base, else
+ * return 0.
+ */
+ ACE_Task_Base *task (void);
+
+ // = Suspend methods, which isn't supported on POSIX pthreads (will not block).
+ /// Suspend all threads
+ int suspend_all (void);
+
+ /// Suspend a single thread.
+ int suspend (ACE_thread_t);
+
+ /// Suspend a group of threads.
+ int suspend_grp (int grp_id);
+
+ /**
+ * True if @a t_id is inactive (i.e., suspended), else false. Always
+ * return false if @a t_id is not managed by the Thread_Manager.
+ */
+ int testsuspend (ACE_thread_t t_id);
+
+ // = Resume methods, which isn't supported on POSIX pthreads (will not block).
+ /// Resume all stopped threads
+ int resume_all (void);
+
+ /// Resume a single thread.
+ int resume (ACE_thread_t);
+
+ /// Resume a group of threads.
+ int resume_grp (int grp_id);
+
+ /**
+ * True if @a t_id is active (i.e., resumed), else false. Always
+ * return false if @a t_id is not managed by the Thread_Manager.
+ */
+ int testresume (ACE_thread_t t_id);
+
+ // = Send signals to one or more threads without blocking.
+ /**
+ * Send @a signum to all stopped threads. Not supported on platforms
+ * that do not have advanced signal support, such as Win32.
+ */
+ int kill_all (int signum);
+ /**
+ * Send the @a signum to a single thread. Not supported on platforms
+ * that do not have advanced signal support, such as Win32.
+ */
+ int kill (ACE_thread_t, int signum);
+ /**
+ * Send @a signum to a group of threads, not supported on platforms
+ * that do not have advanced signal support, such as Win32.
+ */
+ int kill_grp (int grp_id, int signum);
+
+ // = Cancel methods, which provides a cooperative thread-termination mechanism (will not block).
+ /**
+ * Cancel's all the threads.
+ */
+ int cancel_all (int async_cancel = 0);
+
+ /**
+ * Cancel a single thread.
+ */
+ int cancel (ACE_thread_t, int async_cancel = 0);
+
+ /**
+ * Cancel a group of threads.
+ */
+ int cancel_grp (int grp_id, int async_cancel = 0);
+
+ /**
+ * True if @a t_id is cancelled, else false. Always return false if
+ * @a t_id is not managed by the Thread_Manager.
+ */
+ int testcancel (ACE_thread_t t_id);
+
+ /**
+ * True if @a t_id has terminated (i.e., is no longer running),
+ * but the slot in the thread manager hasn't been reclaimed yet,
+ * else false. Always return false if @a t_id is not managed by the
+ * Thread_Manager.
+ */
+ int testterminate (ACE_thread_t t_id);
+
+ /// Set group ids for a particular thread id.
+ int set_grp (ACE_thread_t,
+ int grp_id);
+
+ /// Get group ids for a particular thread id.
+ int get_grp (ACE_thread_t,
+ int &grp_id);
+
+ // = The following methods are new methods which resemble current
+ // methods in <ACE_Thread Manager>. For example, the <apply_task>
+ // method resembles the <apply_thr> method, and <suspend_task>
+ // resembles <suspend_thr>.
+
+ // = Operations on ACE_Tasks.
+
+ /**
+ * Block until there are no more threads running in a specified task.
+ * This method will not wait for either detached or daemon threads;
+ * the threads must have been spawned with the @c THR_JOINABLE flag.
+ * Upon successful completion, the threads have been joined, so further
+ * attempts to join with any of the waited-for threads will fail.
+ *
+ * @param task The ACE_Task_Base object whose threads are to waited for.
+ *
+ * @retval 0 Success.
+ * @retval -1 Failure (consult errno for further information).
+ */
+ int wait_task (ACE_Task_Base *task);
+
+ /**
+ * Suspend all threads in an ACE_Task.
+ */
+ int suspend_task (ACE_Task_Base *task);
+
+ /**
+ * Resume all threads in an ACE_Task.
+ */
+ int resume_task (ACE_Task_Base *task);
+
+ /**
+ * Send a signal @a signum to all threads in an ACE_Task.
+ */
+ int kill_task (ACE_Task_Base *task, int signum);
+
+ /**
+ * Cancel all threads in an ACE_Task. If <async_cancel> is non-0,
+ * then asynchronously cancel these threads if the OS platform
+ * supports cancellation. Otherwise, perform a "cooperative"
+ * cancellation.
+ */
+ int cancel_task (ACE_Task_Base *task, int async_cancel = 0);
+
+ // = Collect thread handles in the thread manager. Notice that
+ // the collected information is just a snapshot.
+ /// Check if the thread is managed by the thread manager. Return true if
+ /// the thread is found, false otherwise.
+ int hthread_within (ACE_hthread_t handle);
+ int thread_within (ACE_thread_t tid);
+
+ /// Returns the number of ACE_Task_Base in a group.
+ int num_tasks_in_group (int grp_id);
+
+ /// Returns the number of threads in an ACE_Task_Base.
+ int num_threads_in_task (ACE_Task_Base *task);
+
+ /**
+ * Returns a list of ACE_Task_Base pointers corresponding to the tasks
+ * that have active threads in a specified thread group.
+ *
+ * @param grp_id The thread group ID to obtain task pointers for.
+ *
+ * @param task_list is a pointer to an array to receive the list of pointers.
+ * The caller is responsible for supplying an array with at
+ * least @arg n entries.
+ *
+ * @param n The maximum number of ACE_Task_Base pointers to write
+ * in @arg task_list.
+ *
+ * @retval If successful, the number of pointers returned, which will be
+ * no greater than @arg n. Returns -1 on error.
+ *
+ * @note This method has no way to indicate if there are more than
+ * @arg n ACE_Task_Base pointers available. Therefore, it may be
+ * wise to guess a larger value of @arg n than one thinks in cases
+ * where the exact number of tasks is not known.
+ *
+ * @sa num_tasks_in_group(), task_all_list()
+ */
+ ssize_t task_list (int grp_id,
+ ACE_Task_Base *task_list[],
+ size_t n);
+
+ /**
+ * Returns in @a thread_list a list of up to @a n thread ids in an
+ * ACE_Task_Base. The caller must allocate the memory for
+ * @a thread_list. In case of an error, -1 is returned. If no
+ * requested values are found, 0 is returned, otherwise correct
+ * number of retrieved values are returned.
+ */
+ ssize_t thread_list (ACE_Task_Base *task,
+ ACE_thread_t thread_list[],
+ size_t n);
+
+ /**
+ * Returns in @a hthread_list a list of up to @a n thread handles in
+ * an ACE_Task_Base. The caller must allocate memory for
+ * @a hthread_list. In case of an error, -1 is returned. If no
+ * requested values are found, 0 is returned, otherwise correct
+ * number of retrieved values are returned.
+ */
+ ssize_t hthread_list (ACE_Task_Base *task,
+ ACE_hthread_t hthread_list[],
+ size_t n);
+
+ /**
+ * Returns in @a thread_list a list of up to @a n thread ids in a
+ * group @a grp_id. The caller must allocate the memory for
+ * @a thread_list. In case of an error, -1 is returned. If no
+ * requested values are found, 0 is returned, otherwise correct
+ * number of retrieved values are returned.
+ */
+ ssize_t thread_grp_list (int grp_id,
+ ACE_thread_t thread_list[],
+ size_t n);
+
+ /**
+ * Returns in @a hthread_list a list of up to @a n thread handles in
+ * a group @a grp_id. The caller must allocate memory for
+ * @a hthread_list.
+ */
+ ssize_t hthread_grp_list (int grp_id,
+ ACE_hthread_t hthread_list[],
+ size_t n);
+
+ /**
+ * Returns a list of ACE_Task_Base pointers corresponding to the tasks
+ * that have active threads managed by this instance.
+ *
+ * @param task_list is a pointer to an array to receive the list of pointers.
+ * The caller is responsible for supplying an array with at
+ * least @arg n entries.
+ *
+ * @param n The maximum number of ACE_Task_Base pointers to write
+ * in @arg task_list.
+ *
+ * @retval If successful, the number of pointers returned, which will be
+ * no greater than @arg n. Returns -1 on error.
+ *
+ * @note This method has no way to indicate if there are more than
+ * @arg n ACE_Task_Base pointers available. Therefore, it may be
+ * wise to guess a larger value of @arg n than one thinks in cases
+ * where the exact number of tasks is not known.
+ *
+ * @sa count_threads()
+ */
+ ssize_t task_all_list (ACE_Task_Base *task_list[],
+ size_t n);
+
+ /**
+ * Returns in @a thread_list a list of up to @a n thread ids. The
+ * caller must allocate the memory for @a thread_list. In case of an
+ * error, -1 is returned. If no requested values are found, 0 is
+ * returned, otherwise correct number of retrieved values are
+ * returned.
+ */
+ ssize_t thread_all_list (ACE_thread_t thread_list[],
+ size_t n);
+
+ /// Set group ids for a particular task.
+ int set_grp (ACE_Task_Base *task, int grp_id);
+
+ /// Get group ids for a particular task.
+ int get_grp (ACE_Task_Base *task, int &grp_id);
+
+ /// Return a count of the current number of threads active in the
+ /// <Thread_Manager>.
+ size_t count_threads (void) const;
+
+ /// Get the state of the thread. Returns false if the thread is not
+ /// managed by this thread manager.
+ int thr_state (ACE_thread_t id, ACE_UINT32& state);
+
+ /**
+ * Register an At_Thread_Exit hook and the ownership is acquire by
+ * Thread_Descriptor, this is the usual case when the AT is dynamically
+ * allocated.
+ */
+ int at_exit (ACE_At_Thread_Exit* cleanup);
+
+ /// Register an At_Thread_Exit hook and the ownership is retained for the
+ /// caller. Normally used when the at_exit hook is created in stack.
+ int at_exit (ACE_At_Thread_Exit& cleanup);
+
+ /**
+ *
+ *****
+ * @deprecated This function is deprecated. Please use the previous two
+ * at_exit method. Notice that you should avoid mixing this method
+ * with the previous two at_exit methods.
+ *****
+ *
+ * Register an object (or array) for cleanup at
+ * thread termination. "cleanup_hook" points to a (global, or
+ * static member) function that is called for the object or array
+ * when it to be destroyed. It may perform any necessary cleanup
+ * specific for that object or its class. "param" is passed as the
+ * second parameter to the "cleanup_hook" function; the first
+ * parameter is the object (or array) to be destroyed.
+ * "cleanup_hook", for example, may delete the object (or array).
+ * If <cleanup_hook> == 0, the <object> will _NOT_ get cleanup at
+ * thread exit. You can use this to cancel the previously added
+ * at_exit.
+ */
+ int at_exit (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param);
+
+ /// Access function to determine whether the Thread_Manager will
+ /// wait for its thread to exit or not when being closing down.
+ void wait_on_exit (int dowait);
+ int wait_on_exit (void);
+
+ /// Dump the state of an object.
+ void dump (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Accessors for ACE_Thread_Descriptors.
+ /**
+ * Get a pointer to the calling thread's own thread_descriptor.
+ * This must be called from a spawn thread. This function will
+ * fetch the info from TSS.
+ */
+ ACE_Thread_Descriptor *thread_desc_self (void);
+
+ /// Return a pointer to the thread's Thread_Descriptor,
+ /// 0 if fail.
+ ACE_Thread_Descriptor *thread_descriptor (ACE_thread_t);
+
+ /// Return a pointer to the thread's Thread_Descriptor,
+ /// 0 if fail.
+ ACE_Thread_Descriptor *hthread_descriptor (ACE_hthread_t);
+
+ /// Create a new thread (must be called with locks held).
+ int spawn_i (ACE_THR_FUNC func,
+ void *arg,
+ long flags,
+ ACE_thread_t * = 0,
+ ACE_hthread_t *t_handle = 0,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ int grp_id = -1,
+ void *stack = 0,
+ size_t stack_size = 0,
+ ACE_Task_Base *task = 0,
+ const char** thr_name = 0);
+
+ /// Run the registered hooks when the thread exits.
+ void run_thread_exit_hooks (int i);
+
+ /// Locate the index of the table slot occupied by <t_id>. Returns
+ /// -1 if <t_id> is not in the table doesn't contain <t_id>.
+ ACE_Thread_Descriptor *find_thread (ACE_thread_t t_id);
+
+ /// Locate the index of the table slot occupied by <h_id>. Returns
+ /// -1 if <h_id> is not in the table doesn't contain <h_id>.
+ ACE_Thread_Descriptor *find_hthread (ACE_hthread_t h_id);
+
+ /**
+ * Locate the thread descriptor address of the list occupied by
+ * @a task. Returns 0 if @a task is not in the table doesn't contain
+ * @a task.
+ */
+ ACE_Thread_Descriptor *find_task (ACE_Task_Base *task,
+ size_t slot = 0);
+
+ /// Insert a thread in the table (checks for duplicates).
+ int insert_thr (ACE_thread_t t_id,
+ ACE_hthread_t,
+ int grp_id = -1,
+ long flags = 0);
+
+ /// Append a thread in the table (adds at the end, growing the table
+ /// if necessary).
+ int append_thr (ACE_thread_t t_id, ACE_hthread_t,
+ ACE_UINT32,
+ int grp_id,
+ ACE_Task_Base *task = 0,
+ long flags = 0,
+ ACE_Thread_Descriptor *td = 0);
+
+ /// Remove thread from the table.
+ void remove_thr (ACE_Thread_Descriptor *td,
+ int close_handler);
+
+ /// Remove all threads from the table.
+ void remove_thr_all (void);
+
+ // = The following four methods implement a simple scheme for
+ // operating on a collection of threads atomically.
+
+ /**
+ * Efficiently check whether @a thread is in a particular @a state.
+ * This call updates the TSS cache if possible to speed up
+ * subsequent searches.
+ */
+ int check_state (ACE_UINT32 state,
+ ACE_thread_t thread,
+ int enable = 1);
+
+ /// Apply @a func to all members of the table that match the @a task
+ int apply_task (ACE_Task_Base *task,
+ ACE_THR_MEMBER_FUNC func,
+ int = 0);
+
+ /// Apply @a func to all members of the table that match the @a grp_id.
+ int apply_grp (int grp_id,
+ ACE_THR_MEMBER_FUNC func,
+ int arg = 0);
+
+ /// Apply @a func to all members of the table.
+ int apply_all (ACE_THR_MEMBER_FUNC,
+ int = 0);
+
+ /// Join the thread described in @a td.
+ int join_thr (ACE_Thread_Descriptor *td,
+ int = 0);
+
+ /// Resume the thread described in @a td.
+ int resume_thr (ACE_Thread_Descriptor *td,
+ int = 0);
+
+ /// Suspend the thread described in @a td.
+ int suspend_thr (ACE_Thread_Descriptor *td,
+ int = 0);
+
+ /// Send signal @a signum to the thread described in @a td.
+ int kill_thr (ACE_Thread_Descriptor *td,
+ int signum);
+
+ /// Set the cancellation flag for the thread described in @a td.
+ int cancel_thr (ACE_Thread_Descriptor *td,
+ int async_cancel = 0);
+
+ /// Register a thread as terminated and put it into the <terminated_thr_list_>.
+ int register_as_terminated (ACE_Thread_Descriptor *td);
+
+ /// Setting the static ACE_TSS_TYPE (ACE_Thread_Exit) *thr_exit_ pointer.
+ static int set_thr_exit (ACE_TSS_TYPE (ACE_Thread_Exit) *ptr);
+
+ /**
+ * Keeping a list of thread descriptors within the thread manager.
+ * Double-linked list enables us to cache the entries in TSS
+ * and adding/removing thread descriptor entries without
+ * affecting other thread's descriptor entries.
+ */
+ ACE_Double_Linked_List<ACE_Thread_Descriptor> thr_list_;
+
+#if !defined (ACE_HAS_VXTHREADS)
+ /// Collect terminated but not yet joined thread entries.
+ ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> terminated_thr_list_;
+#endif /* !ACE_HAS_VXTHREADS */
+
+ /// Collect pointers to thread descriptors of threads to be removed later.
+ ACE_Unbounded_Queue<ACE_Thread_Descriptor*> thr_to_be_removed_;
+
+ /// Keeps track of the next group id to assign.
+ int grp_id_;
+
+ /// Set if we want the Thread_Manager to wait on all threads before
+ /// being closed, reset otherwise.
+ int automatic_wait_;
+
+ // = ACE_Thread_Mutex and condition variable for synchronizing termination.
+#if defined (ACE_HAS_THREADS)
+ /// Serialize access to the <zero_cond_>.
+ ACE_Thread_Mutex lock_;
+
+ /// Keep track of when there are no more threads.
+ ACE_Condition_Thread_Mutex zero_cond_;
+#endif /* ACE_HAS_THREADS */
+
+ ACE_Locked_Free_List<ACE_Thread_Descriptor, ACE_SYNCH_MUTEX> thread_desc_freelist_;
+
+private:
+#if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
+ /// Pointer to a process-wide ACE_Thread_Manager.
+ static ACE_Thread_Manager *thr_mgr_;
+
+ /// Must delete the thr_mgr_ if true.
+ static bool delete_thr_mgr_;
+
+ /// Global ACE_TSS (ACE_Thread_Exit) object ptr.
+ static ACE_TSS_TYPE (ACE_Thread_Exit) *thr_exit_;
+#endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
+};
+
+#if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
+#define ACE_THREAD_MANAGER_SINGLETON_DEFINE \
+ ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX>;
+typedef ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX> ACE_THREAD_MANAGER_SINGLETON;
+#endif /* defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Thread_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_THREAD_MANAGER_H */
diff --git a/ACE/ace/Thread_Manager.inl b/ACE/ace/Thread_Manager.inl
new file mode 100644
index 00000000000..d7d7ca766f8
--- /dev/null
+++ b/ACE/ace/Thread_Manager.inl
@@ -0,0 +1,308 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_At_Thread_Exit::ACE_At_Thread_Exit (void)
+ : next_ (0),
+ td_ (0),
+ was_applied_ (0),
+ is_owner_ (true)
+{
+}
+
+ACE_INLINE int
+ACE_At_Thread_Exit::was_applied() const
+
+{
+ return was_applied_;
+}
+
+ACE_INLINE int
+ACE_At_Thread_Exit::was_applied (int applied)
+{
+ was_applied_ = applied;
+ if (was_applied_)
+ td_ = 0;
+ return was_applied_;
+}
+
+ACE_INLINE bool
+ACE_At_Thread_Exit::is_owner() const
+{
+ return is_owner_;
+}
+
+ACE_INLINE bool
+ACE_At_Thread_Exit::is_owner (bool owner)
+{
+ is_owner_ = owner;
+ return is_owner_;
+}
+
+ACE_INLINE void
+ACE_At_Thread_Exit::do_apply (void)
+{
+ if (!this->was_applied_ && this->is_owner_)
+ td_->at_pop();
+}
+
+ACE_INLINE
+ACE_At_Thread_Exit_Func::ACE_At_Thread_Exit_Func (void *object,
+ ACE_CLEANUP_FUNC func,
+ void *param)
+ : object_(object),
+ func_(func),
+ param_(param)
+{
+}
+
+ACE_INLINE
+ACE_Thread_Descriptor_Base::ACE_Thread_Descriptor_Base (void)
+ : ACE_OS_Thread_Descriptor (),
+ thr_id_ (ACE_OS::NULL_thread),
+ thr_handle_ (ACE_OS::NULL_hthread),
+ grp_id_ (0),
+ thr_state_ (ACE_Thread_Manager::ACE_THR_IDLE),
+ task_ (0),
+ next_ (0),
+ prev_ (0)
+{
+}
+
+ACE_INLINE
+ACE_Thread_Descriptor_Base::~ACE_Thread_Descriptor_Base (void)
+{
+}
+
+ACE_INLINE bool
+ACE_Thread_Descriptor_Base::operator== (
+ const ACE_Thread_Descriptor_Base &rhs) const
+{
+ return
+ ACE_OS::thr_cmp (this->thr_handle_, rhs.thr_handle_)
+ && ACE_OS::thr_equal (this->thr_id_, rhs.thr_id_);
+}
+
+ACE_INLINE bool
+ACE_Thread_Descriptor_Base::operator!=(const ACE_Thread_Descriptor_Base &rhs) const
+{
+ return !(*this == rhs);
+}
+
+ACE_INLINE ACE_Task_Base *
+ACE_Thread_Descriptor_Base::task (void) const
+{
+ ACE_TRACE ("ACE_Thread_Descriptor_Base::task");
+ return this->task_;
+}
+
+// Group ID.
+
+ACE_INLINE int
+ACE_Thread_Descriptor_Base::grp_id (void) const
+{
+ ACE_TRACE ("ACE_Thread_Descriptor_Base::grp_id");
+ return grp_id_;
+}
+
+// Current state of the thread.
+ACE_INLINE ACE_UINT32
+ACE_Thread_Descriptor_Base::state (void) const
+{
+ ACE_TRACE ("ACE_Thread_Descriptor_Base::state");
+ return thr_state_;
+}
+
+// Reset this base descriptor.
+ACE_INLINE void
+ACE_Thread_Descriptor_Base::reset (void)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor_Base::reset");
+ this->thr_id_ = ACE_OS::NULL_thread;
+ this->thr_handle_ = ACE_OS::NULL_hthread;
+ this->grp_id_ = 0;
+ this->thr_state_ = ACE_Thread_Manager::ACE_THR_IDLE;
+ this->task_ = 0;
+ this->flags_ = 0;
+}
+
+// Unique thread id.
+ACE_INLINE ACE_thread_t
+ACE_Thread_Descriptor::self (void) const
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::self");
+ return this->thr_id_;
+}
+
+// Unique kernel-level thread handle.
+
+ACE_INLINE void
+ACE_Thread_Descriptor::self (ACE_hthread_t &handle)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::self");
+ handle = this->thr_handle_;
+}
+
+ACE_INLINE void
+ACE_Thread_Descriptor::log_msg_cleanup (ACE_Log_Msg* log_msg)
+
+{
+ log_msg_ = log_msg;
+}
+
+// Set the <next_> pointer
+ACE_INLINE void
+ACE_Thread_Descriptor::set_next (ACE_Thread_Descriptor *td)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::set_next");
+ this->next_ = td;
+}
+
+// Get the <next_> pointer
+ACE_INLINE ACE_Thread_Descriptor *
+ACE_Thread_Descriptor::get_next (void) const
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::get_next");
+ return static_cast<ACE_Thread_Descriptor * ACE_CAST_CONST> (this->next_);
+}
+
+// Reset this thread descriptor
+ACE_INLINE void
+ACE_Thread_Descriptor::reset (ACE_Thread_Manager *tm)
+{
+ ACE_TRACE ("ACE_Thread_Descriptor::reset");
+ this->ACE_Thread_Descriptor_Base::reset ();
+ this->at_exit_list_ = 0;
+ // Start the at_exit hook list.
+ this->tm_ = tm;
+ // Setup the Thread_Manager.
+ this->log_msg_ = 0;
+ this->terminated_ = false;
+}
+
+ACE_INLINE ACE_Thread_Descriptor *
+ACE_Thread_Manager::thread_desc_self (void)
+{
+ // This method must be called with lock held.
+
+ // Try to get it from cache.
+ ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc ();
+
+#if 1
+ // ACE_ASSERT (desc != 0);
+ // Thread descriptor should always get cached.
+#else
+ if (desc == 0)
+ {
+ ACE_thread_t id = ACE_OS::thr_self ();
+
+ desc = this->find_thread (id);
+
+ // Thread descriptor adapter might not have been put into the
+ // list yet.
+ if (desc != 0)
+ // Update the TSS cache.
+ ACE_LOG_MSG->thr_desc (desc);
+ }
+#endif
+ return desc;
+}
+
+// Return the unique ID of the thread.
+
+ACE_INLINE ACE_thread_t
+ACE_Thread_Manager::thr_self (void)
+{
+ ACE_TRACE ("ACE_Thread_Manager::thr_self");
+ return ACE_Thread::self ();
+}
+
+ACE_INLINE ACE_Task_Base *
+ACE_Thread_Manager::task (void)
+{
+ ACE_TRACE ("ACE_Thread_Manager::task");
+
+ ACE_Thread_Descriptor *td = this->thread_desc_self () ;
+
+ if (td == 0)
+ return 0;
+ else
+ return td->task ();
+}
+
+ACE_INLINE int
+ACE_Thread_Manager::open (size_t)
+{
+ // Currently no-op.
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Thread_Manager::at_exit (ACE_At_Thread_Exit* at)
+{
+ ACE_Thread_Descriptor *td = this->thread_desc_self ();
+ if (td == 0)
+ return -1;
+ else
+ return td->at_exit (at);
+}
+
+ACE_INLINE int
+ACE_Thread_Manager::at_exit (ACE_At_Thread_Exit& at)
+{
+ ACE_Thread_Descriptor *td = this->thread_desc_self ();
+ if (td == 0)
+ return -1;
+ else
+ return td->at_exit (at);
+}
+
+ACE_INLINE int
+ACE_Thread_Manager::at_exit (void *object,
+ ACE_CLEANUP_FUNC cleanup_hook,
+ void *param)
+{
+ ACE_Thread_Descriptor *td = this->thread_desc_self ();
+ if (td == 0)
+ return -1;
+ else
+ return td->at_exit (object,
+ cleanup_hook,
+ param);
+}
+
+ACE_INLINE void
+ACE_Thread_Manager::wait_on_exit (int do_wait)
+{
+ this->automatic_wait_ = do_wait;
+}
+
+ACE_INLINE int
+ACE_Thread_Manager::wait_on_exit (void)
+{
+ return this->automatic_wait_;
+}
+
+ACE_INLINE int
+ACE_Thread_Manager::register_as_terminated (ACE_Thread_Descriptor *td)
+{
+#if defined (ACE_HAS_VXTHREADS)
+ ACE_UNUSED_ARG (td);
+#else /* ! ACE_HAS_VXTHREADS */
+ ACE_Thread_Descriptor_Base *tdb = 0;
+ ACE_NEW_RETURN (tdb, ACE_Thread_Descriptor_Base (*td), -1);
+ this->terminated_thr_list_.insert_tail (tdb);
+#endif /* !ACE_HAS_VXTHREADS */
+ return 0;
+}
+
+ACE_INLINE size_t
+ACE_Thread_Manager::count_threads (void) const
+{
+ return this->thr_list_.size ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Mutex.cpp b/ACE/ace/Thread_Mutex.cpp
new file mode 100644
index 00000000000..66da2cb48fd
--- /dev/null
+++ b/ACE/ace/Thread_Mutex.cpp
@@ -0,0 +1,62 @@
+/**
+ * @file Thread_Mutex.cpp
+ *
+ * $Id$
+ *
+ * Originally in Synch.cpp
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+
+#include "ace/Thread_Mutex.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Thread_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/Malloc_T.h"
+
+ACE_RCSID(ace, Thread_Mutex, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Mutex)
+
+void
+ACE_Thread_Mutex::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Thread_Mutex::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Thread_Mutex::~ACE_Thread_Mutex (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::~ACE_Thread_Mutex");
+ this->remove ();
+}
+
+ACE_Thread_Mutex::ACE_Thread_Mutex (const ACE_TCHAR *name, ACE_mutexattr_t *arg)
+ : removed_ (false)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::ACE_Thread_Mutex");
+
+ if (ACE_OS::thread_mutex_init (&this->lock_,
+ 0,
+ name,
+ arg) != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Thread_Mutex::ACE_Thread_Mutex")));
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/Thread_Mutex.h b/ACE/ace/Thread_Mutex.h
new file mode 100644
index 00000000000..d8f5369b01a
--- /dev/null
+++ b/ACE/ace/Thread_Mutex.h
@@ -0,0 +1,175 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Thread_Mutex.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_THREAD_MUTEX_H
+#define ACE_THREAD_MUTEX_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_HAS_THREADS)
+# include "ace/Null_Mutex.h"
+#else /* ACE_HAS_THREADS */
+// ACE platform supports some form of threading.
+
+#include /**/ "ace/ACE_export.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Thread_Mutex
+ *
+ * @brief ACE_Thread_Mutex wrapper (only valid for threads in the same
+ * process).
+ *
+ * This implementation is optimized for locking threads that are
+ * in the same process. It maps to <CRITICAL_SECTION>s on NT
+ * and <ACE_mutex_t> with <type> set to <USYNC_THREAD> on UNIX.
+ * ACE_Thread_Mutex is recursive on some platforms (like
+ * Win32). However, on most platforms (like Solaris) it is not
+ * recursive. To be totally safe and portable, developers
+ * should use ACE_Recursive_Thread_Mutex when they need a
+ * recursive mutex.
+ */
+class ACE_Export ACE_Thread_Mutex
+{
+ friend class ACE_Condition_Thread_Mutex;
+public:
+ /// Constructor.
+ ACE_Thread_Mutex (const ACE_TCHAR *name = 0,
+ ACE_mutexattr_t *attributes = 0);
+
+ /// Implicitly destroy the mutex.
+ ~ACE_Thread_Mutex (void);
+
+ /**
+ * Explicitly destroy the mutex. Note that only one thread should
+ * call this method since it doesn't protect against race
+ * conditions.
+ */
+ int remove (void);
+
+ /// Acquire lock ownership (wait on queue if necessary).
+ int acquire (void);
+
+ /**
+ * Block the thread until we acquire the mutex or until @a tv times
+ * out, in which case -1 is returned with @c errno == @c ETIME. Note
+ * that @a tv is assumed to be in "absolute" rather than "relative"
+ * time. The value of @a tv is updated upon return to show the
+ * actual (absolute) acquisition time.
+ */
+ int acquire (ACE_Time_Value &tv);
+
+ /**
+ * If @a tv == 0 the call <acquire()> directly. Otherwise, Block the
+ * thread until we acquire the mutex or until @a tv times out, in
+ * which case -1 is returned with @c errno == @c ETIME. Note that
+ * @a tv is assumed to be in "absolute" rather than "relative" time.
+ * The value of @a tv is updated upon return to show the actual
+ * (absolute) acquisition time.
+ */
+ int acquire (ACE_Time_Value *tv);
+
+ /**
+ * Conditionally acquire lock (i.e., don't wait on queue). Returns
+ * -1 on failure. If we "failed" because someone else already had
+ * the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire (void);
+
+ /// Release lock and unblock a thread at head of queue.
+ int release (void);
+
+ /**
+ * Acquire mutex ownership. This calls acquire() and is only here
+ * to make the ACE_Thread_Mutex interface consistent with the
+ * other synchronization APIs.
+ */
+ int acquire_read (void);
+
+ /**
+ * Acquire mutex ownership. This calls acquire() and is only here
+ * to make the ACE_Thread_Mutex interface consistent with the
+ * other synchronization APIs.
+ */
+ int acquire_write (void);
+
+ /**
+ * Conditionally acquire mutex (i.e., won't block). This calls
+ * tryacquire() and is only here to make the ACE_Thread_Mutex
+ * interface consistent with the other synchronization APIs.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_read (void);
+
+ /**
+ * Conditionally acquire mutex (i.e., won't block). This calls
+ * tryacquire() and is only here to make the ACE_Thread_Mutex
+ * interface consistent with the other synchronization APIs.
+ * Returns -1 on failure. If we "failed" because someone else
+ * already had the lock, @c errno is set to @c EBUSY.
+ */
+ int tryacquire_write (void);
+
+ /**
+ * This is only here to make the ACE_Thread_Mutex
+ * interface consistent with the other synchronization APIs.
+ * Assumes the caller has already acquired the mutex using one of
+ * the above calls, and returns 0 (success) always.
+ */
+ int tryacquire_write_upgrade (void);
+
+ /// Return the underlying mutex.
+ const ACE_thread_mutex_t &lock (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // protected:
+ /// Mutex type that supports single-process locking efficiently.
+ ACE_thread_mutex_t lock_;
+
+ /// Keeps track of whether remove() has been called yet to avoid
+ /// multiple <remove> calls, e.g., explicitly and implicitly in the
+ /// destructor. This flag isn't protected by a lock, so make sure
+ /// that you don't have multiple threads simultaneously calling
+ /// <remove> on the same object, which is a bad idea anyway...
+ bool removed_;
+
+private:
+ // = Prevent assignment and initialization.
+ void operator= (const ACE_Thread_Mutex &);
+ ACE_Thread_Mutex (const ACE_Thread_Mutex &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Thread_Mutex.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* !ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_THREAD_MUTEX_H */
diff --git a/ACE/ace/Thread_Mutex.inl b/ACE/ace/Thread_Mutex.inl
new file mode 100644
index 00000000000..146521722dd
--- /dev/null
+++ b/ACE/ace/Thread_Mutex.inl
@@ -0,0 +1,97 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE const ACE_thread_mutex_t &
+ACE_Thread_Mutex::lock (void) const
+{
+// ACE_TRACE ("ACE_Thread_Mutex::lock");
+ return this->lock_;
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::acquire_read (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::acquire_read");
+ return ACE_OS::thread_mutex_lock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::acquire_write (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::acquire_write");
+ return ACE_OS::thread_mutex_lock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::tryacquire_read (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::tryacquire_read");
+ return ACE_OS::thread_mutex_trylock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::tryacquire_write (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::tryacquire_write");
+ return ACE_OS::thread_mutex_trylock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::tryacquire_write_upgrade (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::tryacquire_write_upgrade");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::acquire (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::acquire");
+ return ACE_OS::thread_mutex_lock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::acquire (ACE_Time_Value &tv)
+{
+ // ACE_TRACE ("ACE_Thread_Mutex::acquire");
+ return ACE_OS::thread_mutex_lock (&this->lock_, tv);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::acquire (ACE_Time_Value *tv)
+{
+ // ACE_TRACE ("ACE_Thread_Mutex::acquire");
+ return ACE_OS::thread_mutex_lock (&this->lock_, tv);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::tryacquire (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::tryacquire");
+ return ACE_OS::thread_mutex_trylock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::release (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::release");
+ return ACE_OS::thread_mutex_unlock (&this->lock_);
+}
+
+ACE_INLINE int
+ACE_Thread_Mutex::remove (void)
+{
+// ACE_TRACE ("ACE_Thread_Mutex::remove");
+ int result = 0;
+ if (this->removed_ == false)
+ {
+ this->removed_ = true;
+ result = ACE_OS::thread_mutex_destroy (&this->lock_);
+ }
+ return result;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Thread_Semaphore.cpp b/ACE/ace/Thread_Semaphore.cpp
new file mode 100644
index 00000000000..741c7c5ec99
--- /dev/null
+++ b/ACE/ace/Thread_Semaphore.cpp
@@ -0,0 +1,62 @@
+/**
+ * @file Thread_Semaphore.cpp
+ *
+ * $Id$
+ *
+ * Originally in Synch.cpp
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+
+#include "ace/Thread_Semaphore.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Thread_Semaphore.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/ACE.h"
+
+ACE_RCSID(ace, Thread_Semaphore, "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+ACE_Thread_Semaphore::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+// ACE_TRACE ("ACE_Thread_Semaphore::dump");
+
+ ACE_Semaphore::dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Thread_Semaphore::ACE_Thread_Semaphore (unsigned int count,
+ const ACE_TCHAR *name,
+ void *arg,
+ int max)
+ : ACE_Semaphore (count, USYNC_THREAD, name, arg, max)
+{
+// ACE_TRACE ("ACE_Thread_Semaphore::ACE_Thread_Semaphore");
+}
+
+/*****************************************************************************/
+
+ACE_Thread_Semaphore *
+ACE_Malloc_Lock_Adapter_T<ACE_Thread_Semaphore>::operator () (const ACE_TCHAR *name)
+{
+ ACE_Thread_Semaphore *p = 0;
+ if (name == 0)
+ ACE_NEW_RETURN (p, ACE_Thread_Semaphore (1, name), 0);
+ else
+ ACE_NEW_RETURN (p, ACE_Thread_Semaphore (1, ACE::basename (name,
+ ACE_DIRECTORY_SEPARATOR_CHAR)),
+ 0);
+ return p;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/Thread_Semaphore.h b/ACE/ace/Thread_Semaphore.h
new file mode 100644
index 00000000000..fb88634dd24
--- /dev/null
+++ b/ACE/ace/Thread_Semaphore.h
@@ -0,0 +1,89 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Thread_Semaphore.h
+ *
+ * $Id$
+ *
+ * Moved from Synch.h.
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_THREAD_SEMAPHORE_H
+#define ACE_THREAD_SEMAPHORE_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_HAS_THREADS)
+# include "ace/Null_Semaphore.h"
+#else /* ACE_HAS_THREADS */
+// ACE platform supports some form of threading.
+
+#include "ace/Semaphore.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Thread_Semaphore
+ *
+ * @brief Wrapper for Dijkstra style general semaphores that work
+ * only within one process.
+ */
+class ACE_Export ACE_Thread_Semaphore : public ACE_Semaphore
+{
+public:
+ /// Initialize the semaphore, with an initial value of @a count,
+ /// maximum value of @a max, and unlocked by default.
+ ACE_Thread_Semaphore (unsigned int count = 1, // By default make this unlocked.
+ const ACE_TCHAR *name = 0,
+ void * = 0,
+ int max = 0x7FFFFFFF);
+
+ /// Default dtor.
+ ~ACE_Thread_Semaphore (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+/*****************************************************************************/
+
+template <class T> class ACE_Malloc_Lock_Adapter_T;
+
+/**
+ * @class ACE_Malloc_Lock_Adapter_T<ACE_Thread_Semaphore>
+ *
+ * @brief Template specialization of ACE_Malloc_Lock_Adapter_T for
+ * ACE_Thread_Semaphore.
+ *
+ * This is needed since the ctor for ACE_Thread_Semaphore doesn't match
+ * the standard form used by other lock strategy classes.
+ */
+template<>
+class ACE_Export ACE_Malloc_Lock_Adapter_T<ACE_Thread_Semaphore>
+{
+public:
+ ACE_Thread_Semaphore * operator () (const ACE_TCHAR *name);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Thread_Semaphore.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* !ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_THREAD_SEMAPHORE_H */
diff --git a/ACE/ace/Thread_Semaphore.inl b/ACE/ace/Thread_Semaphore.inl
new file mode 100644
index 00000000000..e9535ff088e
--- /dev/null
+++ b/ACE/ace/Thread_Semaphore.inl
@@ -0,0 +1,12 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE
+ACE_Thread_Semaphore::~ACE_Thread_Semaphore (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Throughput_Stats.cpp b/ACE/ace/Throughput_Stats.cpp
new file mode 100644
index 00000000000..d76f5cb6ebc
--- /dev/null
+++ b/ACE/ace/Throughput_Stats.cpp
@@ -0,0 +1,202 @@
+// $Id$
+
+#include "ace/Throughput_Stats.h"
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Throughput_Stats, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Throughput_Stats::ACE_Throughput_Stats (void)
+ : ACE_Basic_Stats ()
+ , throughput_last_ (0)
+#if 0
+ // @@TODO: This is what I really wanted to compute, but it just
+ // does not work.
+ , throughput_sum_x_ (0)
+ , throughput_sum_x2_ (0)
+ , throughput_sum_y_ (0)
+ , throughput_sum_y2_ (0)
+ , throughput_sum_xy_ (0)
+#endif /* 0 */
+{
+}
+
+void
+ACE_Throughput_Stats::sample (ACE_UINT64 throughput,
+ ACE_UINT64 latency)
+{
+ this->ACE_Basic_Stats::sample (latency);
+
+ if (this->samples_count () == 1u)
+ {
+
+ this->throughput_last_ = throughput;
+#if 0
+ // @@TODO: This is what I really wanted to compute, but it just
+ // does not work.
+ this->throughput_sum_y_ = this->samples_count_;
+ this->throughput_sum_y2_ = this->samples_count_ * this->samples_count_;
+ this->throughput_sum_x_ = throughput;
+ this->throughput_sum_x2_ = throughput * throughput;
+ this->throughput_sum_xy_ = throughput * this->samples_count_;
+
+ ACE_OS::printf ("%f %qu\n", throughput / 400000000.0, this->samples_count_);
+#endif /* 0 */
+ }
+ else
+ {
+ this->throughput_last_ = throughput;
+
+#if 0
+ // @@TODO: This is what I really wanted to compute, but it just
+ // does not work.
+ this->throughput_sum_y_ += this->samples_count_;
+ this->throughput_sum_y2_ += this->samples_count_ * this->samples_count_;
+ this->throughput_sum_x_ += throughput;
+ this->throughput_sum_x2_ += throughput * throughput;
+ this->throughput_sum_xy_ += throughput * this->samples_count_;
+
+ ACE_OS::printf ("%f %qu\n", throughput / 400000000.0, this->samples_count_);
+#endif /* 0 */
+ }
+}
+
+void
+ACE_Throughput_Stats::accumulate (const ACE_Throughput_Stats &rhs)
+{
+ if (rhs.samples_count () == 0u)
+ return;
+
+ this->ACE_Basic_Stats::accumulate (rhs);
+
+ if (this->samples_count () == 0u)
+ {
+ this->throughput_last_ = rhs.throughput_last_;
+#if 0
+ // @@TODO: This is what I really wanted to compute, but it just
+ // does not work.
+ this->throughput_sum_x_ = rhs.throughput_sum_x_;
+ this->throughput_sum_x2_ = rhs.throughput_sum_x2_;
+ this->throughput_sum_y_ = rhs.throughput_sum_y_;
+ this->throughput_sum_y2_ = rhs.throughput_sum_y2_;
+ this->throughput_sum_xy_ = rhs.throughput_sum_xy_;
+#endif /* 0 */
+
+ return;
+ }
+
+
+ if (this->throughput_last_ < rhs.throughput_last_)
+ this->throughput_last_ = rhs.throughput_last_;
+
+#if 0
+ // @@TODO: This is what I really wanted to compute, but it just
+ // does not work.
+ this->throughput_sum_x_ += rhs.throughput_sum_x_;
+ this->throughput_sum_x2_ += rhs.throughput_sum_x2_;
+ this->throughput_sum_y_ += rhs.throughput_sum_y_;
+ this->throughput_sum_y2_ += rhs.throughput_sum_y2_;
+ this->throughput_sum_xy_ += rhs.throughput_sum_xy_;
+#endif /* 0 */
+}
+
+void
+ACE_Throughput_Stats::dump_results (const ACE_TCHAR* msg,
+ ACE_UINT32 sf)
+{
+ if (this->samples_count () == 0u)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%s : no data collected\n"), msg));
+ return;
+ }
+
+ this->ACE_Basic_Stats::dump_results (msg, sf);
+
+ ACE_Throughput_Stats::dump_throughput (msg, sf,
+ this->throughput_last_,
+ this->samples_count ());
+
+#if 0
+ // @@TODO: This is what I really wanted to generate, but it just
+ // doesn't work.
+ double t_sum_x =
+ ACE_CU64_TO_CU32 (this->throughput_sum_x_);// / sf);
+ //t_sum_x /= 1000000.0;
+ double t_sum_y =
+ ACE_CU64_TO_CU32 (this->throughput_sum_y_);
+ double t_sum_x2 =
+ ACE_CU64_TO_CU32 (this->throughput_sum_x2_);// / (sf*sf));
+ //t_sum_x2 /= 1000000.0;
+ //t_sum_x2 /= 1000000.0;
+ double t_sum_y2 =
+ ACE_CU64_TO_CU32 (this->throughput_sum_y2_);
+ double t_sum_xy =
+ ACE_CU64_TO_CU32 (this->throughput_sum_xy_);// / sf);
+ //t_sum_xy /= 1000000.0;
+ double t_avgx = t_sum_x / this->samples_count ();
+ double t_avgy = t_sum_y / this->samples_count ();
+
+ double t_a =
+ (this->samples_count () * t_sum_xy - t_sum_x * t_sum_y)
+ / (this->samples_count () * t_sum_x2 - t_sum_x * t_sum_x);
+ double t_b = (t_avgy - t_a * t_avgx);
+
+ t_a *= 1000000.0;
+
+ double d_r =
+ (t_sum_xy - t_avgx * t_sum_y - t_avgy * t_sum_x
+ + this->samples_count () * t_avgx * t_avgy);
+ double n_r =
+ (t_sum_x2
+ - this->samples_count () * t_avgx * t_avgx)
+ * (t_sum_y2
+ - this->samples_count () * t_avgy * t_avgy);
+ double t_r = d_r * d_r / n_r;
+
+ // ACE_DEBUG ((LM_DEBUG,
+ // "%s throughput: %.2f/%.2f/%.2f/%.6f/%.2f (avg/a/b/r/elapsed)\n",
+ // msg, t_avg, t_a, t_b, t_r, seconds));
+ // ACE_DEBUG ((LM_DEBUG,
+ // "%s data: %.2f/%.2f/%.2f/%.6f/%.2f (x/x2/y/y2/xy)\n",
+ // msg, t_sum_x, t_sum_x2, t_sum_y, t_sum_y2, t_sum_xy));
+#endif
+}
+
+void
+ACE_Throughput_Stats::dump_throughput (const ACE_TCHAR *msg,
+ ACE_UINT32 sf,
+ ACE_UINT64 elapsed_time,
+ ACE_UINT32 samples_count)
+{
+#ifndef ACE_NLOGGING
+ double seconds =
+# if defined ACE_LACKS_LONGLONG_T
+ elapsed_time / sf;
+#elif defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+ static_cast<double> (ACE_UINT64_DBLCAST_ADAPTER (
+ ACE_U_LongLong(elapsed_time / sf)));
+# else /* ! ACE_LACKS_LONGLONG_T */
+ static_cast<double> (ACE_UINT64_DBLCAST_ADAPTER (elapsed_time / sf));
+# endif /* ! ACE_LACKS_LONGLONG_T */
+ seconds /= ACE_HR_SCALE_CONVERSION;
+
+ const double t_avg = samples_count / seconds;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%s throughput: %.2f (events/second)\n"),
+ msg, t_avg));
+#else
+ ACE_UNUSED_ARG (msg);
+ ACE_UNUSED_ARG (sf);
+ ACE_UNUSED_ARG (elapsed_time);
+ ACE_UNUSED_ARG (samples_count);
+#endif /* ACE_NLOGGING */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Throughput_Stats.h b/ACE/ace/Throughput_Stats.h
new file mode 100644
index 00000000000..ed59c6fb908
--- /dev/null
+++ b/ACE/ace/Throughput_Stats.h
@@ -0,0 +1,86 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Throughput_Stats.h
+ *
+ * $Id$
+ *
+ * @author David L. Levine
+ */
+//==========================================================================
+
+
+#ifndef ACE_THROUGHPUT_STATS_H
+#define ACE_THROUGHPUT_STATS_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Basic_Stats.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// A simple class to make throughput and latency analysis.
+/**
+ *
+ * Keep the relevant information to perform throughput and latency
+ * analysis, including:
+ * -# Minimum, Average and Maximum latency
+ * -# Jitter for the latency
+ * -# Linear regression for throughput
+ * -# Accumulate results from several samples to obtain aggregated
+ * results, across several threads or experiments.
+ *
+ * @todo The idea behind this class was to use linear regression to
+ * determine if the throughput was linear or exhibited jitter.
+ * Unfortunately it never worked quite right, so only average
+ * throughput is computed.
+ */
+class ACE_Export ACE_Throughput_Stats : public ACE_Basic_Stats
+{
+public:
+ /// Constructor
+ ACE_Throughput_Stats (void);
+
+ /// Store one sample
+ void sample (ACE_UINT64 throughput, ACE_UINT64 latency);
+
+ /// Update the values to reflect the stats in @a throughput
+ void accumulate (const ACE_Throughput_Stats &throughput);
+
+ /// Print down the stats
+ void dump_results (const ACE_TCHAR* msg, ACE_UINT32 scale_factor);
+
+ /// Dump the average throughput stats.
+ static void dump_throughput (const ACE_TCHAR *msg,
+ ACE_UINT32 scale_factor,
+ ACE_UINT64 elapsed_time,
+ ACE_UINT32 samples_count);
+private:
+ /// The last throughput measurement.
+ ACE_UINT64 throughput_last_;
+
+#if 0
+ /// These are the fields that we should keep to perform linear
+ /// regression
+ //@{
+ ///@}
+ ACE_UINT64 throughput_sum_x_;
+ ACE_UINT64 throughput_sum_x2_;
+ ACE_UINT64 throughput_sum_y_;
+ ACE_UINT64 throughput_sum_y2_;
+ ACE_UINT64 throughput_sum_xy_;
+#endif /* 0 */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ! ACE_THROUGHPUT_STATS_H */
diff --git a/ACE/ace/Time_Value.cpp b/ACE/ace/Time_Value.cpp
new file mode 100644
index 00000000000..33ebdd8fa7f
--- /dev/null
+++ b/ACE/ace/Time_Value.cpp
@@ -0,0 +1,264 @@
+#include "ace/Time_Value.h"
+
+ACE_RCSID (ace,
+ Time_Value,
+ "$Id$")
+
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Time_Value.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Numeric_Limits.h"
+#include "ace/If_Then_Else.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Static constant representing `zero-time'.
+// Note: this object requires static construction.
+const ACE_Time_Value ACE_Time_Value::zero;
+
+// Constant for maximum time representable. Note that this time
+// is not intended for use with select () or other calls that may
+// have *their own* implementation-specific maximum time representations.
+// Its primary use is in time computations such as those used by the
+// dynamic subpriority strategies in the ACE_Dynamic_Message_Queue class.
+// Note: this object requires static construction.
+const ACE_Time_Value ACE_Time_Value::max_time (
+ ACE_Numeric_Limits<time_t>::max (),
+ ACE_ONE_SECOND_IN_USECS - 1);
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Time_Value)
+
+// Increment microseconds (the only reason this is here is to allow
+// the use of ACE_Atomic_Op with ACE_Time_Value).
+
+ACE_Time_Value
+ACE_Time_Value::operator ++ (int)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator ++ (int)");
+ ACE_Time_Value tv (*this);
+ ++*this;
+ return tv;
+}
+
+ACE_Time_Value &
+ACE_Time_Value::operator ++ (void)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator ++ (void)");
+ this->usec (this->usec () + 1);
+ this->normalize ();
+ return *this;
+}
+
+// Decrement microseconds (the only reason this is here is / to allow
+// the use of ACE_Atomic_Op with ACE_Time_Value).
+
+ACE_Time_Value
+ACE_Time_Value::operator -- (int)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator -- (int)");
+ ACE_Time_Value tv (*this);
+ --*this;
+ return tv;
+}
+
+ACE_Time_Value &
+ACE_Time_Value::operator -- (void)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator -- (void)");
+ this->usec (this->usec () - 1);
+ this->normalize ();
+ return *this;
+}
+
+#if defined (ACE_WIN32)
+// Static constant to remove time skew between FILETIME and POSIX
+// time. POSIX and Win32 use different epochs (Jan. 1, 1970 v.s.
+// Jan. 1, 1601). The following constant defines the difference
+// in 100ns ticks.
+//
+// In the beginning (Jan. 1, 1601), there was no time and no computer.
+// And Bill said: "Let there be time," and there was time....
+# if defined (ACE_LACKS_LONGLONG_T)
+const ACE_U_LongLong ACE_Time_Value::FILETIME_to_timval_skew =
+ACE_U_LongLong (0xd53e8000, 0x19db1de);
+# else
+const DWORDLONG ACE_Time_Value::FILETIME_to_timval_skew =
+ACE_INT64_LITERAL (0x19db1ded53e8000);
+# endif
+
+// Initializes the ACE_Time_Value object from a Win32 FILETIME
+
+ACE_Time_Value::ACE_Time_Value (const FILETIME &file_time)
+{
+ // // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value");
+ this->set (file_time);
+}
+
+void ACE_Time_Value::set (const FILETIME &file_time)
+{
+ // Initializes the ACE_Time_Value object from a Win32 FILETIME
+#if defined (ACE_LACKS_LONGLONG_T)
+ ACE_U_LongLong LL_100ns(file_time.dwLowDateTime, file_time.dwHighDateTime);
+ LL_100ns -= ACE_Time_Value::FILETIME_to_timval_skew;
+ // Convert 100ns units to seconds;
+ this->tv_.tv_sec = (long) (LL_100ns / ((double) (10000 * 1000)));
+ // Convert remainder to microseconds;
+ this->tv_.tv_usec = (suseconds_t)((LL_100ns % ((ACE_UINT32)(10000 * 1000))) / 10);
+#else
+ // Don't use a struct initializer, gcc don't like it.
+ ULARGE_INTEGER _100ns;
+ _100ns.LowPart = file_time.dwLowDateTime;
+ _100ns.HighPart = file_time.dwHighDateTime;
+
+ _100ns.QuadPart -= ACE_Time_Value::FILETIME_to_timval_skew;
+
+ // Convert 100ns units to seconds;
+ this->tv_.tv_sec = (long) (_100ns.QuadPart / (10000 * 1000));
+ // Convert remainder to microseconds;
+ this->tv_.tv_usec = (suseconds_t) ((_100ns.QuadPart % (10000 * 1000)) / 10);
+#endif // ACE_LACKS_LONGLONG_T
+ this->normalize ();
+}
+
+// Returns the value of the object as a Win32 FILETIME.
+
+ACE_Time_Value::operator FILETIME () const
+{
+ FILETIME file_time;
+ // ACE_OS_TRACE ("ACE_Time_Value::operator FILETIME");
+
+#if defined (ACE_LACKS_LONGLONG_T)
+ ACE_U_LongLong LL_sec(this->tv_.tv_sec);
+ ACE_U_LongLong LL_usec(this->tv_.tv_usec);
+ ACE_U_LongLong LL_100ns = LL_sec * (ACE_UINT32)(10000 * 1000) +
+ LL_usec * (ACE_UINT32)10 +
+ ACE_Time_Value::FILETIME_to_timval_skew;
+ file_time.dwLowDateTime = LL_100ns.lo();
+ file_time.dwHighDateTime = LL_100ns.hi();
+#else
+ ULARGE_INTEGER _100ns;
+ _100ns.QuadPart = (((DWORDLONG) this->tv_.tv_sec * (10000 * 1000) +
+ this->tv_.tv_usec * 10) +
+ ACE_Time_Value::FILETIME_to_timval_skew);
+
+ file_time.dwLowDateTime = _100ns.LowPart;
+ file_time.dwHighDateTime = _100ns.HighPart;
+#endif //ACE_LACKS_LONGLONG_T
+
+ return file_time;
+}
+
+#endif /* ACE_WIN32 */
+
+void
+ACE_Time_Value::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_OS_TRACE ("ACE_Time_Value::dump");
+#if 0
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntv_sec_ = %d"), this->tv_.tv_sec));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntv_usec_ = %d\n"), this->tv_.tv_usec));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* 0 */
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Time_Value::normalize (void)
+{
+ // // ACE_OS_TRACE ("ACE_Time_Value::normalize");
+ // From Hans Rohnert...
+
+ if (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS)
+ {
+ /*! \todo This loop needs some optimization.
+ */
+ do
+ {
+ ++this->tv_.tv_sec;
+ this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS;
+ }
+ while (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS);
+ }
+ else if (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS)
+ {
+ /*! \todo This loop needs some optimization.
+ */
+ do
+ {
+ --this->tv_.tv_sec;
+ this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS;
+ }
+ while (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS);
+ }
+
+ if (this->tv_.tv_sec >= 1 && this->tv_.tv_usec < 0)
+ {
+ --this->tv_.tv_sec;
+ this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS;
+ }
+// tv_sec in qnxnto is unsigned
+#if !defined ( __QNXNTO__)
+ else if (this->tv_.tv_sec < 0 && this->tv_.tv_usec > 0)
+ {
+ ++this->tv_.tv_sec;
+ this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS;
+ }
+#endif /* __QNXNTO__ */
+}
+
+
+ACE_Time_Value &
+ACE_Time_Value::operator *= (double d)
+{
+ // The floating type to be used in the computations. It should be
+ // large enough to hold a time_t. We actually want a floating type
+ // with enough digits in its mantissa to hold a time_t without
+ // losing precision. For example, if FLT_RADIX is 2 and
+ // LDBL_MANT_DIG is 64, a long double has a 64 bit wide mantissa,
+ // which would be sufficient to hold a 64 bit time_t value without
+ // losing precision.
+ //
+ // For now we'll simply go with long double if it is larger than
+ // time_t. We're hosed if long double isn't large enough.
+ typedef ACE::If_Then_Else<(sizeof (double) > sizeof (time_t)),
+ double,
+ long double>::result_type float_type;
+
+ float_type time_total =
+ (this->sec ()
+ + static_cast<float_type> (this->usec ()) / ACE_ONE_SECOND_IN_USECS) * d;
+
+ // shall we saturate the result?
+ static const float_type max_int =
+ ACE_Numeric_Limits<time_t>::max () + 0.999999;
+ static const float_type min_int =
+ ACE_Numeric_Limits<time_t>::min () - 0.999999;
+
+ if (time_total > max_int)
+ time_total = max_int;
+ if (time_total < min_int)
+ time_total = min_int;
+
+ const time_t time_sec = static_cast<time_t> (time_total);
+
+ time_total -= time_sec;
+ time_total *= ACE_ONE_SECOND_IN_USECS;
+
+ suseconds_t time_usec = static_cast<suseconds_t> (time_total);
+
+ // round up the result to save the last usec
+ if (time_usec > 0 && (time_total - time_usec) >= 0.5)
+ ++time_usec;
+ else if (time_usec < 0 && (time_total - time_usec) <= -0.5)
+ --time_usec;
+
+ this->set (time_sec, time_usec);
+
+ return *this;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Time_Value.h b/ACE/ace/Time_Value.h
new file mode 100644
index 00000000000..8c294f943ab
--- /dev/null
+++ b/ACE/ace/Time_Value.h
@@ -0,0 +1,360 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Time_Value.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIME_VALUE_H
+#define ACE_TIME_VALUE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+# include "ace/os_include/os_time.h"
+
+// Define some helpful constants.
+// Not type-safe, and signed. For backward compatibility.
+#define ACE_ONE_SECOND_IN_MSECS 1000L
+suseconds_t const ACE_ONE_SECOND_IN_USECS = 1000000;
+#define ACE_ONE_SECOND_IN_NSECS 1000000000L
+
+// needed for ACE_UINT64
+#include "ace/Basic_Types.h"
+
+// This forward declaration is needed by the set() and FILETIME() functions
+#if defined (ACE_LACKS_LONGLONG_T)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_Export ACE_U_LongLong;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_LACKS_LONGLONG_T */
+
+// -------------------------------------------------------------------
+
+/**
+ * @class ACE_Time_Value
+ *
+ * @brief Operations on "timeval" structures, which express time in
+ * seconds (secs) and microseconds (usecs).
+ *
+ * This class centralizes all the time related processing in
+ * ACE. These time values are typically used in conjunction with OS
+ * mechanisms like <select>, <poll>, or <cond_timedwait>.
+ */
+#if defined (ACE_WIN32) && defined (_WIN32_WCE)
+// Something is a bit brain-damaged here and I'm not sure what... this code
+// compiled before the OS reorg for ACE 5.4. Since then it hasn't - eVC
+// complains that the operators that return ACE_Time_Value are C-linkage
+// functions that can't return a C++ class. The only way I've found to
+// defeat this is to wrap the whole class in extern "C++".
+// - Steve Huston, 23-Aug-2004
+extern "C++" {
+#endif
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Export ACE_Time_Value
+{
+public:
+
+ /// Constant "0".
+ static const ACE_Time_Value zero;
+
+ /**
+ * Constant for maximum time representable. Note that this time is
+ * not intended for use with <select> or other calls that may have
+ * *their own* implementation-specific maximum time representations.
+ * Its primary use is in time computations such as those used by the
+ * dynamic subpriority strategies in the ACE_Dynamic_Message_Queue
+ * class.
+ */
+ static const ACE_Time_Value max_time;
+
+ // = Initialization methods.
+
+ /// Default Constructor.
+ ACE_Time_Value (void);
+
+ /// Constructor.
+ explicit ACE_Time_Value (time_t sec, suseconds_t usec = 0);
+
+ // = Methods for converting to/from various time formats.
+
+ /// Construct the ACE_Time_Value from a timeval.
+ explicit ACE_Time_Value (const struct timeval &t);
+
+ /// Construct the ACE_Time_Value object from a timespec_t.
+ explicit ACE_Time_Value (const timespec_t &t);
+
+# if defined (ACE_WIN32)
+ /// Construct the ACE_Time_Value object from a Win32 FILETIME
+ explicit ACE_Time_Value (const FILETIME &ft);
+# endif /* ACE_WIN32 */
+
+ /// Initializes the ACE_Time_Value from seconds and useconds.
+ void set (time_t sec, suseconds_t usec);
+
+ /// Initializes the ACE_Time_Value from a double, which is assumed to be
+ /// in second format, with any remainder treated as microseconds.
+ void set (double d);
+
+ /// Initializes the ACE_Time_Value from a timeval.
+ void set (const timeval &t);
+
+ /// Initializes the ACE_Time_Value object from a timespec_t.
+ void set (const timespec_t &t);
+
+# if defined (ACE_WIN32)
+ /// Initializes the ACE_Time_Value object from a Win32 FILETIME.
+ void set (const FILETIME &ft);
+# endif /* ACE_WIN32 */
+
+ /// Converts from ACE_Time_Value format into milli-seconds format.
+ /**
+ * @return Sum of second field (in milliseconds) and microsecond field
+ * (in milliseconds). Note that this method can overflow if
+ * the second and microsecond field values are large, so use
+ * the msec (ACE_UINT64 &ms) method instead.
+ *
+ * @note The semantics of this method differs from the sec() and
+ * usec() methods. There is no analogous "millisecond"
+ * component in an ACE_Time_Value.
+ */
+ unsigned long msec (void) const;
+
+ /**
+ * @return Sum of second field (in milliseconds) and microsecond field
+ * (in milliseconds) and return them via the @param ms parameter.
+ *
+ * @note The semantics of this method differs from the sec() and
+ * usec() methods. There is no analogous "millisecond"
+ * component in an ACE_Time_Value.
+ */
+ void msec (ACE_UINT64 &ms) const;
+
+ /// Converts from milli-seconds format into ACE_Time_Value format.
+ /**
+ * @note The semantics of this method differs from the sec() and
+ * usec() methods. There is no analogous "millisecond"
+ * component in an ACE_Time_Value.
+ */
+ void msec (long);
+
+ /// Returns the value of the object as a timespec_t.
+ operator timespec_t () const;
+
+ /// Returns the value of the object as a timeval.
+ operator timeval () const;
+
+ /// Returns a pointer to the object as a timeval.
+ operator const timeval *() const;
+
+# if defined (ACE_WIN32)
+ /// Returns the value of the object as a Win32 FILETIME.
+ operator FILETIME () const;
+# endif /* ACE_WIN32 */
+
+ // = The following are accessor/mutator methods.
+
+ /// Get seconds.
+ /**
+ * @return The second field/component of this ACE_Time_Value.
+ *
+ * @note The semantics of this method differs from the msec()
+ * method.
+ */
+ time_t sec (void) const;
+
+ /// Set seconds.
+ void sec (time_t sec);
+
+ /// Get microseconds.
+ /**
+ * @return The microsecond field/component of this ACE_Time_Value.
+ *
+ * @note The semantics of this method differs from the msec()
+ * method.
+ */
+ suseconds_t usec (void) const;
+
+ /// Set microseconds.
+ void usec (suseconds_t usec);
+
+ /**
+ * @return Sum of second field (in microseconds) and microsecond field
+ * and return them via the @param usec parameter.
+ */
+ void to_usec (ACE_UINT64 &usec) const;
+
+ // = The following arithmetic methods operate on ACE_Time_Value's.
+
+ /// Add @a tv to this.
+ ACE_Time_Value &operator += (const ACE_Time_Value &tv);
+
+ /// Add @a tv to this.
+ ACE_Time_Value &operator += (time_t tv);
+
+ /// Assign @ tv to this
+ ACE_Time_Value &operator = (const ACE_Time_Value &tv);
+
+ /// Assign @ tv to this
+ ACE_Time_Value &operator = (time_t tv);
+
+ /// Subtract @a tv to this.
+ ACE_Time_Value &operator -= (const ACE_Time_Value &tv);
+
+ /// Substract @a tv to this.
+ ACE_Time_Value &operator -= (time_t tv);
+
+ /**
+ \brief Multiply the time value by the @a d factor.
+ \note The result of the operator is valid for results from range
+ < (ACE_INT32_MIN, -999999), (ACE_INT32_MAX, 999999) >. Result
+ outside this range are saturated to a limit.
+ */
+ ACE_Time_Value &operator *= (double d);
+
+ /// Increment microseconds as postfix.
+ /**
+ * @note The only reason this is here is to allow the use of ACE_Atomic_Op
+ * with ACE_Time_Value.
+ */
+ ACE_Time_Value operator++ (int);
+
+ /// Increment microseconds as prefix.
+ /**
+ * @note The only reason this is here is to allow the use of ACE_Atomic_Op
+ * with ACE_Time_Value.
+ */
+ ACE_Time_Value &operator++ (void);
+
+ /// Decrement microseconds as postfix.
+ /**
+ * @note The only reason this is here is to allow the use of ACE_Atomic_Op
+ * with ACE_Time_Value.
+ */
+ ACE_Time_Value operator-- (int);
+
+ /// Decrement microseconds as prefix.
+ /**
+ * @note The only reason this is here is to allow the use of ACE_Atomic_Op
+ * with ACE_Time_Value.
+ */
+ ACE_Time_Value &operator-- (void);
+
+ /// Adds two ACE_Time_Value objects together, returns the sum.
+ friend ACE_Export ACE_Time_Value operator + (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2);
+
+ /// Subtracts two ACE_Time_Value objects, returns the difference.
+ friend ACE_Export ACE_Time_Value operator - (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2);
+
+ /// True if @a tv1 < @a tv2.
+ friend ACE_Export bool operator < (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2);
+
+ /// True if @a tv1 > @a tv2.
+ friend ACE_Export bool operator > (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2);
+
+ /// True if @a tv1 <= @a tv2.
+ friend ACE_Export bool operator <= (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2);
+
+ /// True if @a tv1 >= @a tv2.
+ friend ACE_Export bool operator >= (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2);
+
+ /// True if @a tv1 == @a tv2.
+ friend ACE_Export bool operator == (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2);
+
+ /// True if @a tv1 != @a tv2.
+ friend ACE_Export bool operator != (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2);
+
+ //@{
+ /// Multiplies the time value by @a d
+ friend ACE_Export ACE_Time_Value operator * (double d,
+ const ACE_Time_Value &tv);
+
+ friend ACE_Export ACE_Time_Value operator * (const ACE_Time_Value &tv,
+ double d);
+ //@}
+
+ /// Dump is a no-op.
+ /**
+ * The dump() method is a no-op. It's here for backwards compatibility
+ * only, but does not dump anything. Invoking logging methods here
+ * violates layering restrictions in ACE because this class is part
+ * of the OS layer and @c ACE_Log_Msg is at a higher level.
+ */
+ void dump (void) const;
+
+# if defined (ACE_WIN32)
+ /// Const time difference between FILETIME and POSIX time.
+# if defined (ACE_LACKS_LONGLONG_T)
+ static const ACE_U_LongLong FILETIME_to_timval_skew;
+# else
+ static const DWORDLONG FILETIME_to_timval_skew;
+# endif // ACE_LACKS_LONGLONG_T
+# endif /* ACE_WIN32 */
+
+private:
+ /// Put the timevalue into a canonical form.
+ void normalize (void);
+
+ /// Store the values as a timeval.
+#if defined (ACE_HAS_TIME_T_LONG_MISMATCH)
+ // Windows' timeval is non-conformant, so swap in a struct that conforms
+ // to the proper data types to represent the entire time range that this
+ // class's API can accept.
+ // Also, since this class can supply a pointer to a timeval that things
+ // like select() expect, we need the OS-defined one as well. To make this
+ // available, use a real timeval called ext_tv_ and set it up when needed.
+ // Since this is most often for relative times that don't approach 32 bits
+ // in size, reducing a time_t to fit should be no problem.
+ struct {
+ time_t tv_sec;
+ suseconds_t tv_usec;
+ } tv_;
+ timeval ext_tv_;
+#else
+ timeval tv_;
+#endif /* ACE_HAS_TIME_T_LONG_MISMATCH */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Time_Value.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_WIN32) && defined (_WIN32_WCE)
+}
+#endif
+
+#if defined (__MINGW32__)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+// The MingW linker has problems with the exported statics
+// zero and max_time with these two statics the linker will be able to
+// resolve the static exported symbols.
+static const ACE_Time_Value& __zero_time = ACE_Time_Value::zero;
+static const ACE_Time_Value& __max_time = ACE_Time_Value::max_time;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* __MINGW32__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_TIME_VALUE_H */
diff --git a/ACE/ace/Time_Value.inl b/ACE/ace/Time_Value.inl
new file mode 100644
index 00000000000..8884ee785bb
--- /dev/null
+++ b/ACE/ace/Time_Value.inl
@@ -0,0 +1,407 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Truncate.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_WIN32) && defined (_WIN32_WCE)
+// Something is a bit brain-damaged here and I'm not sure what... this code
+// compiled before the OS reorg for ACE 5.4. Since then it hasn't - eVC
+// complains that the operators that return ACE_Time_Value are C-linkage
+// functions that can't return a C++ class. The only way I've found to
+// defeat this is to wrap the whole class in extern "C++".
+// - Steve Huston, 23-Aug-2004
+extern "C++" {
+#endif
+
+// Returns the value of the object as a timeval.
+
+ACE_INLINE
+ACE_Time_Value::operator timeval () const
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator timeval");
+#if defined (ACE_HAS_TIME_T_LONG_MISMATCH)
+ // Recall that on some Windows we substitute another type for timeval in tv_
+ ACE_Time_Value *me = const_cast<ACE_Time_Value*> (this);
+ me->ext_tv_.tv_sec = ACE_Utils::truncate_cast<long> (this->tv_.tv_sec);
+ me->ext_tv_.tv_usec = ACE_Utils::truncate_cast<long> (this->tv_.tv_usec);
+ return this->ext_tv_;
+#else
+ return this->tv_;
+#endif /* ACE_HAS_TIME_T_LONG_MISMATCH */
+}
+
+ACE_INLINE void
+ACE_Time_Value::set (const timeval &tv)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::set");
+ this->tv_.tv_sec = tv.tv_sec;
+ this->tv_.tv_usec = tv.tv_usec;
+
+ this->normalize ();
+}
+
+ACE_INLINE
+ACE_Time_Value::ACE_Time_Value (const struct timeval &tv)
+ // : tv_ ()
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value");
+ this->set (tv);
+}
+
+ACE_INLINE
+ACE_Time_Value::operator const timeval * () const
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator const timeval *");
+#if defined (ACE_HAS_TIME_T_LONG_MISMATCH)
+ // Recall that on some Windows we substitute another type for timeval in tv_
+ ACE_Time_Value *me = const_cast<ACE_Time_Value*> (this);
+ me->ext_tv_.tv_sec = ACE_Utils::truncate_cast<long> (this->tv_.tv_sec);
+ me->ext_tv_.tv_usec = ACE_Utils::truncate_cast<long> (this->tv_.tv_usec);
+ return (const timeval *) &this->ext_tv_;
+#else
+ return (const timeval *) &this->tv_;
+#endif /* ACE_HAS_TIME_T_LONG_MISMATCH */
+}
+
+ACE_INLINE void
+ACE_Time_Value::set (time_t sec, suseconds_t usec)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::set");
+ this->tv_.tv_sec = sec;
+ this->tv_.tv_usec = usec;
+#if __GNUC__
+ if (__builtin_constant_p(sec) &&
+ __builtin_constant_p(usec) &&
+ (sec >= 0 && usec >= 0 && usec < ACE_ONE_SECOND_IN_USECS))
+ return;
+#endif
+ this->normalize ();
+}
+
+ACE_INLINE void
+ACE_Time_Value::set (double d)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::set");
+ long l = (long) d;
+ this->tv_.tv_sec = l;
+ this->tv_.tv_usec = (suseconds_t) ((d - (double) l) * ACE_ONE_SECOND_IN_USECS + .5);
+ this->normalize ();
+}
+
+// Initializes a timespec_t. Note that this approach loses precision
+// since it converts the nano-seconds into micro-seconds. But then
+// again, do any real systems have nano-second timer precision?!
+
+ACE_INLINE void
+ACE_Time_Value::set (const timespec_t &tv)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::set");
+
+ this->set (tv.tv_sec,
+ tv.tv_nsec / 1000); // Convert nanoseconds into microseconds.
+}
+
+ACE_INLINE
+ACE_Time_Value::ACE_Time_Value (void)
+ // : tv_ ()
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value");
+ this->set (0, 0);
+}
+
+ACE_INLINE
+ACE_Time_Value::ACE_Time_Value (time_t sec, suseconds_t usec)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value");
+ this->set (sec, usec);
+}
+
+// Returns number of seconds.
+
+ACE_INLINE time_t
+ACE_Time_Value::sec (void) const
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::sec");
+ return this->tv_.tv_sec;
+}
+
+// Sets the number of seconds.
+
+ACE_INLINE void
+ACE_Time_Value::sec (time_t sec)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::sec");
+ this->tv_.tv_sec = sec;
+}
+
+// Converts from Time_Value format into milli-seconds format.
+
+ACE_INLINE unsigned long
+ACE_Time_Value::msec (void) const
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::msec");
+
+ // Note - we're truncating a value here, which can lose data. This is
+ // called out in the user documentation for this with a recommendation to
+ // use msec(ACE_UINT64&) instead, so just go ahead and truncate.
+ time_t secs = this->tv_.tv_sec * 1000 + this->tv_.tv_usec / 1000;
+ return ACE_Utils::truncate_cast<unsigned long> (secs);
+}
+
+ACE_INLINE void
+ACE_Time_Value::msec (ACE_UINT64 &ms) const
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::msec");
+ ms = ACE_Utils::truncate_cast<ACE_UINT64> (this->tv_.tv_sec);
+ ms *= 1000;
+ ms += (this->tv_.tv_usec / 1000);
+}
+
+// Converts from milli-seconds format into Time_Value format.
+
+ACE_INLINE void
+ACE_Time_Value::msec (long milliseconds)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::msec");
+ // Convert millisecond units to seconds;
+ long secs = milliseconds / 1000;
+ this->tv_.tv_sec = secs;
+ // Convert remainder to microseconds;
+ this->tv_.tv_usec = (milliseconds - (secs * 1000)) * 1000;
+}
+
+// Returns number of micro-seconds.
+
+ACE_INLINE suseconds_t
+ACE_Time_Value::usec (void) const
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::usec");
+ return this->tv_.tv_usec;
+}
+
+// Sets the number of micro-seconds.
+
+ACE_INLINE void
+ACE_Time_Value::usec (suseconds_t usec)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::usec");
+ this->tv_.tv_usec = usec;
+}
+
+ACE_INLINE void
+ACE_Time_Value::to_usec (ACE_UINT64 & usec) const
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::to_usec");
+
+#if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+ usec = ACE_U_LongLong (static_cast<long long> (this->tv_.tv_sec));
+#elif defined (ACE_LACKS_LONGLONG_T)
+ // No native 64-bit type, meaning time_t is most likely 32 bits.
+ usec = ACE_U_LongLong (this->tv_.tv_sec);
+#else
+ usec = static_cast<ACE_UINT64> (this->tv_.tv_sec);
+#endif /* ACE_LACKS_LONG_LONG_T */
+ usec *= 1000000;
+ usec += this->tv_.tv_usec;
+}
+
+ACE_INLINE ACE_Time_Value
+operator * (double d, const ACE_Time_Value &tv)
+{
+ return ACE_Time_Value (tv) *= d;
+}
+
+ACE_INLINE ACE_Time_Value
+operator * (const ACE_Time_Value &tv, double d)
+{
+ return ACE_Time_Value (tv) *= d;
+}
+
+// True if tv1 > tv2.
+
+ACE_INLINE bool
+operator > (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2)
+{
+ // ACE_OS_TRACE ("operator >");
+ if (tv1.sec () > tv2.sec ())
+ return 1;
+ else if (tv1.sec () == tv2.sec ()
+ && tv1.usec () > tv2.usec ())
+ return 1;
+ else
+ return 0;
+}
+
+// True if tv1 >= tv2.
+
+ACE_INLINE bool
+operator >= (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2)
+{
+ // ACE_OS_TRACE ("operator >=");
+ if (tv1.sec () > tv2.sec ())
+ return 1;
+ else if (tv1.sec () == tv2.sec ()
+ && tv1.usec () >= tv2.usec ())
+ return 1;
+ else
+ return 0;
+}
+
+// Returns the value of the object as a timespec_t.
+
+ACE_INLINE
+ACE_Time_Value::operator timespec_t () const
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator timespec_t");
+ timespec_t tv;
+ tv.tv_sec = this->sec ();
+ // Convert microseconds into nanoseconds.
+ tv.tv_nsec = this->tv_.tv_usec * 1000;
+ return tv;
+}
+
+// Initializes the ACE_Time_Value object from a timespec_t.
+
+ACE_INLINE
+ACE_Time_Value::ACE_Time_Value (const timespec_t &tv)
+ // : tv_ ()
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value");
+ this->set (tv);
+}
+
+// True if tv1 < tv2.
+
+ACE_INLINE bool
+operator < (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2)
+{
+ // ACE_OS_TRACE ("operator <");
+ return tv2 > tv1;
+}
+
+// True if tv1 >= tv2.
+
+ACE_INLINE bool
+operator <= (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2)
+{
+ // ACE_OS_TRACE ("operator <=");
+ return tv2 >= tv1;
+}
+
+// True if tv1 == tv2.
+
+ACE_INLINE bool
+operator == (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2)
+{
+ // ACE_OS_TRACE ("operator ==");
+ return tv1.sec () == tv2.sec ()
+ && tv1.usec () == tv2.usec ();
+}
+
+// True if tv1 != tv2.
+
+ACE_INLINE bool
+operator != (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2)
+{
+ // ACE_OS_TRACE ("operator !=");
+ return !(tv1 == tv2);
+}
+
+// Add TV to this.
+
+ACE_INLINE ACE_Time_Value &
+ACE_Time_Value::operator+= (const ACE_Time_Value &tv)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator+=");
+ this->sec (this->sec () + tv.sec ());
+ this->usec (this->usec () + tv.usec ());
+ this->normalize ();
+ return *this;
+}
+
+ACE_INLINE ACE_Time_Value &
+ACE_Time_Value::operator+= (time_t tv)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator+=");
+ this->sec (this->sec () + tv);
+ return *this;
+}
+
+ACE_INLINE ACE_Time_Value &
+ACE_Time_Value::operator= (const ACE_Time_Value &tv)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator=");
+ this->sec (tv.sec ());
+ this->usec (tv.usec ());
+ return *this;
+}
+
+ACE_INLINE ACE_Time_Value &
+ACE_Time_Value::operator= (time_t tv)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator=");
+ this->sec (tv);
+ this->usec (0);
+ return *this;
+}
+
+// Subtract TV to this.
+
+ACE_INLINE ACE_Time_Value &
+ACE_Time_Value::operator-= (const ACE_Time_Value &tv)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator-=");
+ this->sec (this->sec () - tv.sec ());
+ this->usec (this->usec () - tv.usec ());
+ this->normalize ();
+ return *this;
+}
+
+ACE_INLINE ACE_Time_Value &
+ACE_Time_Value::operator-= (time_t tv)
+{
+ // ACE_OS_TRACE ("ACE_Time_Value::operator-=");
+ this->sec (this->sec () - tv);
+ return *this;
+}
+
+// Adds two ACE_Time_Value objects together, returns the sum.
+
+ACE_INLINE ACE_Time_Value
+operator + (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2)
+{
+ // ACE_OS_TRACE ("operator +");
+ ACE_Time_Value sum (tv1);
+ sum += tv2;
+
+ return sum;
+}
+
+// Subtracts two ACE_Time_Value objects, returns the difference.
+
+ACE_INLINE ACE_Time_Value
+operator - (const ACE_Time_Value &tv1,
+ const ACE_Time_Value &tv2)
+{
+ // ACE_OS_TRACE ("operator -");
+ ACE_Time_Value delta (tv1);
+ delta -= tv2;
+
+ return delta;
+}
+
+#if defined (ACE_WIN32) && defined (_WIN32_WCE)
+}
+#endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Timeprobe.cpp b/ACE/ace/Timeprobe.cpp
new file mode 100644
index 00000000000..aea68f74ba0
--- /dev/null
+++ b/ACE/ace/Timeprobe.cpp
@@ -0,0 +1,15 @@
+// $Id$
+
+#include "ace/config-all.h"
+
+ACE_RCSID(ace, Timeprobe, "$Id$")
+
+#if defined (ACE_COMPILE_TIMEPROBES)
+
+#include "ace/Timeprobe.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Timeprobe.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_COMPILE_TIMEPROBES */
diff --git a/ACE/ace/Timeprobe.h b/ACE/ace/Timeprobe.h
new file mode 100644
index 00000000000..4978fe45845
--- /dev/null
+++ b/ACE/ace/Timeprobe.h
@@ -0,0 +1,201 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timeprobe.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali
+ *
+ * If users want to use time probes, the ACE_COMPILE_TIMEPROBES
+ * flag must be defined when compiling ACE. This can be achieved
+ * by doing one of the following:
+ *
+ * . Use make probe = 1, if you are using the make utility.
+ *
+ * . Define ACE_COMPILE_TIMEPROBES in config.h
+ *
+ * . Define ACE_COMPILE_TIMEPROBES in the VC project file.
+ *
+ * . Other regular methods will also work.
+ *
+ * It is not necessary to define ACE_COMPILE_TIMEPROBES when using
+ * time probes, you simply need ACE_ENABLE_TIMEPROBES. You can use
+ * the ACE_TIMEPROBE_* macros to program the time probes, and use
+ * the ACE_ENABLE_TIMEPROBE to enable the time probes. If you
+ * define ACE_ENABLE_TIMEPROBE in your code, but forget to compile
+ * ACE with ACE_COMPILE_TIMEPROBES, you will end up with linker
+ * errors.
+ *
+ * Remember that ACE_COMPILE_TIMEPROBES means that the ACE library
+ * will contain code for time probes. This is only useful when
+ * compiling ACE. ACE_ENABLE_TIMEPROBES means that the
+ * ACE_TIMEPROBE_* macros should spring to life.
+ */
+//=============================================================================
+
+#ifndef ACE_TIMEPROBE_H
+#define ACE_TIMEPROBE_H
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+#include /**/ "ace/ACE_export.h"
+#include "ace/Malloc_Allocator.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/* Enable ACE Timeprobes */
+#if defined (ACE_ENABLE_TIMEPROBES)
+ #if !defined (ACE_COMPILE_TIMEPROBES)
+ #define ACE_COMPILE_TIMEPROBES
+ #endif /* ACE_COMPILE_TIMEPROBES */
+#endif /* ACE_ENABLE_TIMEPROBES */
+
+#if defined (ACE_COMPILE_TIMEPROBES)
+
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Event_Descriptions
+ *
+ * @brief Event Descriptions.
+ */
+class ACE_Export ACE_Event_Descriptions
+{
+public:
+ /// Event descriptions
+ const char **descriptions_;
+
+ /// Minimum id of this description set
+ u_long minimum_id_;
+
+ /// Comparison
+ bool operator== (const ACE_Event_Descriptions &rhs) const;
+};
+
+/**
+ * @class ACE_timeprobe_t
+ *
+ * @brief Time probe record.
+ */
+class ACE_Export ACE_timeprobe_t
+{
+public:
+ /// Events are record as strings or numbers.
+ union event
+ {
+ u_long event_number_;
+ const char *event_description_;
+ };
+
+ /// Type of event.
+ enum event_type
+ {
+ NUMBER,
+ STRING
+ };
+
+ /// Event.
+ event event_;
+
+ /// Type of event.
+ event_type event_type_;
+
+ /// Timestamp.
+ ACE_hrtime_t time_;
+
+ /// Id of thread posting the time probe.
+ ACE_thread_t thread_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Timeprobe.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Synch_Traits.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Singleton.h"
+#include "ace/Timeprobe_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// If ACE_MT_TIMEPROBES is defined, use a Thread_Mutex to lock the
+// internal state of ACE_Timerprobe. This allows multiple threads to
+// use the same ACE_Timerprobe.
+# if defined (ACE_MT_TIMEPROBES)
+typedef ACE_SYNCH_MUTEX ACE_TIMEPROBE_MUTEX;
+# else /* ACE_MT_TIMEPROBES */
+typedef ACE_SYNCH_NULL_MUTEX ACE_TIMEPROBE_MUTEX;
+# endif /* ACE_MT_TIMEPROBES */
+
+typedef ACE_New_Allocator ACE_TIMEPROBE_ALLOCATOR;
+
+typedef ACE_Timeprobe_Ex<ACE_TIMEPROBE_MUTEX, ACE_TIMEPROBE_ALLOCATOR>
+ ACE_TIMEPROBE_WITH_LOCKING;
+
+// If ACE_TSS_TIMEPROBES is defined, store the ACE_Timeprobe singleton
+// in thread specific storage. This allows multiple threads to use
+// their own instance of ACE_Timerprobe, without interfering with each
+// other.
+
+# if defined (ACE_TSS_TIMEPROBES)
+# define ACE_TIMEPROBE_SINGLETON_TYPE ACE_TSS_Singleton
+# define ACE_TIMEPROBE_SINGLETON_LOCK_TYPE ACE_SYNCH_NULL_MUTEX
+# else /* ACE_TSS_TIMEPROBES */
+# define ACE_TIMEPROBE_SINGLETON_TYPE ACE_Singleton
+# define ACE_TIMEPROBE_SINGLETON_LOCK_TYPE ACE_SYNCH_MUTEX
+# endif /* ACE_TSS_TIMEPROBES */
+
+ACE_SINGLETON_DECLARE (ACE_TIMEPROBE_SINGLETON_TYPE, \
+ ACE_TIMEPROBE_WITH_LOCKING, \
+ ACE_TIMEPROBE_SINGLETON_LOCK_TYPE)
+
+typedef ACE_TIMEPROBE_SINGLETON_TYPE<ACE_TIMEPROBE_WITH_LOCKING, ACE_TIMEPROBE_SINGLETON_LOCK_TYPE>
+ ACE_TIMEPROBE_SINGLETON;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_COMPILE_TIMEPROBES */
+
+// If ACE_ENABLE_TIMEPROBES is defined, the macros below will
+// work. Otherwise, they just vanish. Using this macro, you can
+// control which files/libraries are probed.
+#if defined (ACE_ENABLE_TIMEPROBES) && defined (ACE_COMPILE_TIMEPROBES)
+
+# define ACE_TIMEPROBE_RESET ACE_TIMEPROBE_SINGLETON::instance ()->reset ()
+
+# define ACE_TIMEPROBE(id) ACE_TIMEPROBE_SINGLETON::instance ()->timeprobe (id)
+
+# define ACE_TIMEPROBE_PRINT ACE_TIMEPROBE_SINGLETON::instance ()->print_times ()
+
+# define ACE_TIMEPROBE_PRINT_ABSOLUTE ACE_TIMEPROBE_SINGLETON::instance ()->print_absolute_times ()
+
+# define ACE_TIMEPROBE_EVENT_DESCRIPTIONS(descriptions, minimum_id) \
+static int ace_timeprobe_##descriptions##_return = \
+ ACE_TIMEPROBE_SINGLETON::instance ()->event_descriptions \
+ (descriptions, minimum_id)
+
+# define ACE_FUNCTION_TIMEPROBE(X) \
+ ACE_Function_Timeprobe<ACE_TIMEPROBE_WITH_LOCKING> function_timeprobe \
+ (*ACE_TIMEPROBE_SINGLETON::instance (), X)
+
+#else /* ACE_ENABLE_TIMEPROBES && ACE_COMPILE_TIMEPROBES */
+
+# define ACE_TIMEPROBE_RESET
+# define ACE_TIMEPROBE(id)
+# define ACE_TIMEPROBE_PRINT
+# define ACE_TIMEPROBE_PRINT_ABSOLUTE
+# define ACE_TIMEPROBE_EVENT_DESCRIPTIONS(descriptions, minimum_id)
+# define ACE_FUNCTION_TIMEPROBE(X)
+
+#endif /* ACE_ENABLE_TIMEPROBES && ACE_COMPILE_TIMEPROBES */
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMEPROBE_H */
diff --git a/ACE/ace/Timeprobe.inl b/ACE/ace/Timeprobe.inl
new file mode 100644
index 00000000000..d25eb4b0cfa
--- /dev/null
+++ b/ACE/ace/Timeprobe.inl
@@ -0,0 +1,14 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE bool
+ACE_Event_Descriptions::operator== (const ACE_Event_Descriptions &rhs) const
+{
+ return this->minimum_id_ == rhs.minimum_id_ &&
+ this->descriptions_ == rhs.descriptions_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Timeprobe_T.cpp b/ACE/ace/Timeprobe_T.cpp
new file mode 100644
index 00000000000..dcb1edbb791
--- /dev/null
+++ b/ACE/ace/Timeprobe_T.cpp
@@ -0,0 +1,427 @@
+// $Id$
+
+#ifndef ACE_TIMEPROBE_T_CPP
+#define ACE_TIMEPROBE_T_CPP
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_COMPILE_TIMEPROBES)
+
+#include "ace/Timeprobe.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::ACE_Timeprobe_Ex (u_long size)
+ : timeprobes_ (0),
+ lock_ (),
+ max_size_ (size),
+ current_size_ (0),
+ report_buffer_full_ (0),
+ allocator_ (0)
+{
+ ACE_timeprobe_t *temp;
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_NEW_MALLOC_ARRAY (temp,
+ (ACE_timeprobe_t *) this->allocator ()->
+ malloc (this->max_size_*sizeof(ACE_timeprobe_t)),
+ ACE_timeprobe_t,
+ this->max_size_);
+ //FUZZ: enable check_for_lack_ACE_OS
+ this->timeprobes_ = temp;
+
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::
+ACE_Timeprobe_Ex (ALLOCATOR *allocator,
+ u_long size)
+ : timeprobes_ (0),
+ lock_ (),
+ max_size_ (size),
+ current_size_ (0),
+ report_buffer_full_ (0),
+ allocator_ (allocator)
+{
+ ACE_timeprobe_t *temp = 0;
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_NEW_MALLOC_ARRAY (temp,
+ (ACE_timeprobe_t *) this->allocator ()->
+ malloc (this->max_size_*sizeof(ACE_timeprobe_t)),
+ ACE_timeprobe_t,
+ this->max_size_);
+ //FUZZ: enable check_for_lack_ACE_OS
+ this->timeprobes_ = temp;
+
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::ACE_Timeprobe_Ex (const ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR> &)
+{
+ //
+ // Stupid MSVC is forcing me to define this; please don't use it.
+ //
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_NOTSUP: %N, line %l\n")));
+ errno = ENOTSUP;
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::~ACE_Timeprobe_Ex (void)
+{
+ ACE_DES_ARRAY_FREE ((ACE_timeprobe_t *) (this->timeprobes_),
+ this->max_size_,
+ this->allocator ()->free,
+ ACE_timeprobe_t);
+}
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobe (u_long event)
+{
+ ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ this->timeprobes_[this->current_size_].event_.event_number_ = event;
+ this->timeprobes_[this->current_size_].event_type_ = ACE_timeprobe_t::NUMBER;
+ this->timeprobes_[this->current_size_].time_ = ACE_OS::gethrtime ();
+ this->timeprobes_[this->current_size_].thread_ = ACE_OS::thr_self ();
+
+ ++this->current_size_;
+
+#if !defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
+ // wrap around to the beginning on overflow
+ if (this->current_size_ >= this->max_size_)
+ {
+ this->current_size_ = 0;
+ this->report_buffer_full_ = 1;
+ }
+#endif /* ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
+
+ ACE_ASSERT (this->current_size_ < this->max_size_);
+}
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobe (const char *event)
+{
+ ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ this->timeprobes_[this->current_size_].event_.event_description_ = event;
+ this->timeprobes_[this->current_size_].event_type_ = ACE_timeprobe_t::STRING;
+ this->timeprobes_[this->current_size_].time_ = ACE_OS::gethrtime ();
+ this->timeprobes_[this->current_size_].thread_ = ACE_OS::thr_self ();
+
+ ++this->current_size_;
+
+#if !defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
+ // wrap around to the beginning on overflow
+ if (this->current_size_ >= this->max_size_)
+ {
+ this->current_size_ = 0;
+ this->report_buffer_full_ = 1;
+ }
+#endif /* ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
+
+ ACE_ASSERT (this->current_size_ < this->max_size_);
+}
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::reset (void)
+{
+ ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ this->current_size_ = 0;
+ this->report_buffer_full_ = 0;
+}
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::increase_size (u_long size)
+{
+ ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ if (size > this->max_size_)
+ {
+ ACE_timeprobe_t *temp = 0;
+ //FUZZ: disable check_for_lack_ACE_OS
+ ACE_NEW_MALLOC_ARRAY (temp,
+ (ACE_timeprobe_t *) this->allocator ()->
+ malloc (this->max_size_
+ * sizeof (ACE_timeprobe_t)),
+ ACE_timeprobe_t,
+ size);
+ //FUZZ: enable check_for_lack_ACE_OS
+
+ if (this->max_size_ > 0)
+ {
+ ACE_OS::memcpy (temp,
+ this->timeprobes_,
+ this->max_size_ * sizeof (ACE_timeprobe_t));
+
+ // Iterates over the array explicitly calling the destructor for
+ // each probe instance, then deallocates the memory
+
+ ACE_DES_ARRAY_FREE ((ACE_timeprobe_t *)(this->timeprobes_),
+ this->max_size_,
+ this->allocator ()->free,
+ ACE_timeprobe_t);
+ }
+ this->timeprobes_ = temp;
+ this->max_size_ = size;
+ }
+}
+
+template <class ACE_LOCK, class ALLOCATOR> ACE_Unbounded_Set<ACE_Event_Descriptions> &
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::event_descriptions (void)
+{
+ return this->event_descriptions_;
+}
+
+template <class ACE_LOCK, class ALLOCATOR> ACE_Unbounded_Set<ACE_Event_Descriptions> &
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::sorted_event_descriptions (void)
+{
+ return this->sorted_event_descriptions_;
+}
+
+template <class ACE_LOCK, class ALLOCATOR> ACE_timeprobe_t *
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobes (void)
+{
+ return this->timeprobes_;
+}
+
+template <class ACE_LOCK, class ALLOCATOR> ACE_LOCK &
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::lock (void)
+{
+ return this->lock_;
+}
+
+template <class ACE_LOCK, class ALLOCATOR> u_long
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::max_size (void)
+{
+ return this->max_size_;
+}
+
+template <class ACE_LOCK, class ALLOCATOR> u_long
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::current_size (void)
+{
+ return this->current_size_;
+}
+
+template <class ACE_LOCK, class ALLOCATOR> int
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::event_descriptions (const char **descriptions,
+ u_long minimum_id)
+{
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ ACE_Event_Descriptions events;
+ events.descriptions_ = descriptions;
+ events.minimum_id_ = minimum_id;
+
+ this->event_descriptions_.insert (events);
+
+ return 0;
+}
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_times (void)
+{
+ ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ // Sort the event descriptions
+ this->sort_event_descriptions_i ();
+
+ u_long size = this->report_buffer_full_ ? this->max_size_
+ : this->current_size_;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nACE_Timeprobe_Ex; %u timestamps were recorded:\n",
+ size));
+
+ if (size == 0)
+ return;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\n%-50.50s %8.8s %13.13s\n\n",
+ "Event",
+ "thread",
+ "usec"));
+
+ double gsf = ACE_High_Res_Timer::global_scale_factor ();
+ u_long i, j;
+
+ // First element
+ i = this->report_buffer_full_ ? this->current_size_ : 0;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%-50.50s %8.8x %13.13s\n",
+ this->find_description_i (i),
+ this->timeprobes_[i].thread_,
+ "START"));
+
+ if (size == 1)
+ return;
+
+ bool has_timestamp_inversion = false;
+
+ j = i;
+ i = (i + 1) % this->max_size_;
+
+ do
+ {
+ // When reusing the same ACE_Timeprobe from multiple threads
+ // with Linux on Intel SMP, it sometimes happens that the
+ // recorded times go backward in time if they are recorded from
+ // different threads (see bugzilla #2342). To obtain the
+ // correct signed difference between consecutive recorded times,
+ // one has to cast the time difference to an intermediate signed
+ // integral type of the same size as ACE_hrtime_t.
+
+ double time_difference =
+ (ACE_INT64) (this->timeprobes_[i].time_ - this->timeprobes_[j].time_);
+
+ if (time_difference < 0)
+ has_timestamp_inversion = true;
+
+ // Convert to microseconds.
+ time_difference /= gsf;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%-50.50s %8.8x %14.3f\n",
+ this->find_description_i (i),
+ this->timeprobes_[i].thread_,
+ time_difference));
+
+ j = i;
+ i = (i + 1) % this->max_size_;
+ }
+ while (i != this->current_size_);
+
+ static bool inversion_warning_printed = false;
+ if (!inversion_warning_printed && has_timestamp_inversion)
+ {
+ inversion_warning_printed = true;
+ ACE_DEBUG ((LM_DEBUG,
+ "\nWARNING: The timestamps recorded by gethrtime() on"
+ " this platform are\n"
+ "not monotonic across different threads.\n"));
+ }
+}
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_absolute_times (void)
+{
+ ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ // Sort the event descriptions
+ this->sort_event_descriptions_i ();
+
+ u_long size = this->report_buffer_full_ ? this->max_size_
+ : this->current_size_;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nACE_Timeprobe_Ex; %u timestamps were recorded:\n",
+ size));
+
+ if (size == 0)
+ return;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\n%-50.50s %8.8s %13.13s\n\n",
+ "Event",
+ "thread",
+ "stamp"));
+
+ u_long i = this->report_buffer_full_ ? this->current_size_ : 0;
+
+ ACE_Time_Value tv; // to convert ACE_hrtime_t
+ do
+ {
+ ACE_High_Res_Timer::hrtime_to_tv (tv, this->timeprobes_ [i].time_);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%-50.50s %8.8x %12.12u\n",
+ this->find_description_i (i),
+ this->timeprobes_ [i].thread_,
+ tv.sec () * 1000000
+ + tv.usec ()));
+
+ // Modulus increment: loops around at the end.
+ i = (i + 1) % this->max_size_;
+ }
+ while (i != this->current_size_);
+}
+
+template <class ACE_LOCK, class ALLOCATOR> const char *
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::find_description_i (u_long i)
+{
+ if (this->timeprobes_[i].event_type_ == ACE_timeprobe_t::STRING)
+ return this->timeprobes_[i].event_.event_description_;
+ else
+ {
+ EVENT_DESCRIPTIONS::iterator iterator = this->sorted_event_descriptions_.begin ();
+ for (u_long j = 0;
+ j < this->sorted_event_descriptions_.size () - 1;
+ iterator++, j++)
+ {
+ EVENT_DESCRIPTIONS::iterator next_event_descriptions = iterator;
+ ++next_event_descriptions;
+
+ if (this->timeprobes_[i].event_.event_number_ < (*next_event_descriptions).minimum_id_)
+ break;
+ }
+ return (*iterator).descriptions_[this->timeprobes_[i].event_.event_number_ - (*iterator).minimum_id_];
+ }
+}
+
+template <class ACE_LOCK, class ALLOCATOR> void
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::sort_event_descriptions_i (void)
+{
+ size_t total_elements = this->event_descriptions_.size ();
+
+ for (size_t i = 0;
+ i < total_elements;
+ i++)
+ {
+ EVENT_DESCRIPTIONS::iterator iterator = this->event_descriptions_.begin ();
+ ACE_Event_Descriptions min_entry = *iterator;
+
+ for (;
+ iterator != this->event_descriptions_.end ();
+ iterator++)
+ if ((*iterator).minimum_id_ < min_entry.minimum_id_)
+ min_entry = *iterator;
+
+ this->sorted_event_descriptions_.insert (min_entry);
+ this->event_descriptions_.remove (min_entry);
+ }
+}
+
+template <class ACE_LOCK, class ALLOCATOR> ALLOCATOR *
+ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::allocator (void)
+{
+ return allocator_ ? allocator_ : ACE_Singleton<ALLOCATOR, ACE_LOCK>::instance ();
+}
+
+template <class Timeprobe>
+ACE_Function_Timeprobe<Timeprobe>::ACE_Function_Timeprobe (Timeprobe &timeprobe,
+ u_long event)
+ : timeprobe_ (timeprobe),
+ event_ (event)
+{
+ this->timeprobe_.timeprobe (this->event_);
+}
+
+template <class Timeprobe>
+ACE_Function_Timeprobe<Timeprobe>::~ACE_Function_Timeprobe (void)
+{
+ this->timeprobe_.timeprobe (this->event_ + 1);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_COMPILE_TIMEPROBES */
+#endif /* ACE_TIMEPROBE_T_CPP */
diff --git a/ACE/ace/Timeprobe_T.h b/ACE/ace/Timeprobe_T.h
new file mode 100644
index 00000000000..ff339660780
--- /dev/null
+++ b/ACE/ace/Timeprobe_T.h
@@ -0,0 +1,220 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timeprobe_T.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali
+ */
+//=============================================================================
+
+
+#ifndef ACE_TIMEPROBE_T_H
+#define ACE_TIMEPROBE_T_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_COMPILE_TIMEPROBES)
+
+#include "ace/Unbounded_Set.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Timeprobe_Ex
+ *
+ * @brief This class is used to instrument code. This is accomplished
+ * by inserting time probes at different location in the code.
+ * ACE_Timeprobe then measures the time difference between two
+ * time probes.
+ *
+ * This class provides a lightweight implementation for
+ * measuring the time required to execute code between two time
+ * probes. When a time probe executes, it records the time, the
+ * id of the calling thread, and an event description. The
+ * event description can either be an unsigned long or a string
+ * (char *). If string are used, care must be taken cause only
+ * pointer copies are done and the string data is *not* copied.
+ * The recorded time probes can then be printed by calling
+ * <print_times>. If you have used unsigned longs as event
+ * descriptions in any of your time probes, you must have
+ * provided an event description table that maps the unsigned
+ * longs to readable strings. This map is a simple array of
+ * strings, and the event number is used as the index into the
+ * array when looking for the event description. If you have
+ * only used strings for the event description, this map is not
+ * necessary.
+ * Multiple maps can also be used to chunk up the time probes.
+ * Each one can be added by calling <event_descriptions>.
+ * Different tables are used internally by consulting the
+ * minimum_id for each table. It is up to the user to make sure
+ * that multiple tables do not share the same event id range.
+ */
+template <class ACE_LOCK, class ALLOCATOR>
+class ACE_Timeprobe_Ex
+{
+public:
+
+ /// Self
+ typedef ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>
+ SELF;
+
+ /**
+ * ACE_Timeprobe
+ */
+ typedef ACE_Timeprobe_Ex <ACE_LOCK, ACE_Allocator> ACE_Timeprobe;
+
+
+ /// We can hold multiple event description tables.
+ typedef ACE_Unbounded_Set<ACE_Event_Descriptions>
+ EVENT_DESCRIPTIONS;
+
+ /// Create Timeprobes with @a size slots
+ ACE_Timeprobe_Ex (u_long size = ACE_DEFAULT_TIMEPROBE_TABLE_SIZE);
+
+ /// Create Timeprobes with @a size slots
+ ACE_Timeprobe_Ex (ALLOCATOR *allocator,
+ u_long size = ACE_DEFAULT_TIMEPROBE_TABLE_SIZE);
+ /// Destructor.
+ ~ACE_Timeprobe_Ex (void);
+
+ /// Record a time. @a event is used to describe this time probe.
+ void timeprobe (u_long event);
+
+ /// Record a time. @a id is used to describe this time probe.
+ void timeprobe (const char *id);
+
+ /// Record event descriptions.
+ int event_descriptions (const char **descriptions,
+ u_long minimum_id);
+
+ /// Print the time probes.
+ void print_times (void);
+
+ /// Print the time probes.
+ void print_absolute_times (void);
+
+ /// Reset the slots. All old time probes will be lost.
+ void reset (void);
+
+ void increase_size (u_long size);
+
+ /// Not implemented (stupid MSVC won't let it be protected).
+ ACE_Timeprobe_Ex (const ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR> &);
+
+ // = (Somewhat private) Accessors
+
+ /// Event Descriptions
+ ACE_Unbounded_Set<ACE_Event_Descriptions> &event_descriptions (void);
+
+ /// Sorted Event Descriptions.
+ ACE_Unbounded_Set<ACE_Event_Descriptions> &sorted_event_descriptions (void);
+
+ /// Find description of event @a i
+ const char *find_description_i (u_long i);
+
+ /// Sort event descriptions
+ void sort_event_descriptions_i (void);
+
+ /// Time probe slots
+ ACE_timeprobe_t *timeprobes (void);
+
+ /// Synchronization variable.
+ ACE_LOCK &lock (void);
+
+ /// Max size of timestamp table
+ u_long max_size (void);
+
+ /// Current size of timestamp table
+ u_long current_size (void);
+
+protected:
+
+ /// Obtain an allocator pointer. If there is no allocator stored in
+ /// the instance, the singleton allocator in the current process is used.
+ ALLOCATOR * allocator (void);
+
+ /// Event Descriptions
+ EVENT_DESCRIPTIONS event_descriptions_;
+
+ /// Sorted Event Descriptions.
+ EVENT_DESCRIPTIONS sorted_event_descriptions_;
+
+ /// Time probe slots
+ ACE_timeprobe_t *timeprobes_;
+
+ /// Synchronization variable.
+ ACE_LOCK lock_;
+
+ /// Max size of timestamp table
+ u_long max_size_;
+
+ /// Current size of timestamp table
+ u_long current_size_;
+
+ /// Flag indicating the report buffer has filled up, and is now
+ /// acting as a ring-buffer using modulus arithmetic: this saves the
+ /// max_size_ most recent time stamps and loses earlier ones until
+ /// drained.
+ u_short report_buffer_full_;
+
+private:
+ ALLOCATOR * allocator_;
+};
+
+// template <class ACE_LOCK>
+// class ACE_Timeprobe : public ACE_Timeprobe_Ex <ACE_LOCK, ACE_Allocator>
+// {
+// public:
+// // Initialize a ACE_Timeprobe with default size
+// ACE_Timeprobe (ACE_Allocator *allocator = ACE_Allocator::instance());
+
+// /// Create Timeprobes with @a size slots
+// ACE_Timeprobe (ACE_Allocator *allocator = ACE_Allocator::instance(),
+// u_long size = ACE_DEFAULT_TIMEPROBE_TABLE_SIZE);
+// };
+
+/**
+ * @class ACE_Function_Timeprobe
+ *
+ * @brief Auto pointer like time probes. It will record <event> on
+ * construction and <event + 1> on destruction.
+ */
+template <class Timeprobe>
+class ACE_Function_Timeprobe
+{
+public:
+ /// Constructor.
+ ACE_Function_Timeprobe (Timeprobe &timeprobe, u_long event);
+
+ /// Destructor.
+ ~ACE_Function_Timeprobe (void);
+
+protected:
+ /// Reference to timeprobe.
+ Timeprobe &timeprobe_;
+
+ /// Event.
+ u_long event_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Timeprobe_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Timeprobe_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_COMPILE_TIMEPROBES */
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMEPROBE_T_H */
diff --git a/ACE/ace/Timer_Hash.h b/ACE/ace/Timer_Hash.h
new file mode 100644
index 00000000000..2d959be39c5
--- /dev/null
+++ b/ACE/ace/Timer_Hash.h
@@ -0,0 +1,75 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Timer_Hash.h
+ *
+ * $Id$
+ *
+ * @author Darrell Brunsch <brunsch@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_TIMER_HASH_H
+#define ACE_TIMER_HASH_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Timer_Hash_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Timer_Heap_T.h"
+#include "ace/Timer_List_T.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// The following typedef are here for ease of use
+
+typedef ACE_Timer_Hash_Upcall <ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Hash_Upcall;
+
+typedef ACE_Timer_List_T <ACE_Event_Handler *,
+ ACE_Hash_Upcall,
+ ACE_Null_Mutex>
+ ACE_Hash_Timer_List;
+
+typedef ACE_Timer_Heap_T <ACE_Event_Handler *,
+ ACE_Hash_Upcall,
+ ACE_Null_Mutex>
+ ACE_Hash_Timer_Heap;
+
+
+typedef ACE_Timer_Hash_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX,
+ ACE_Hash_Timer_List>
+
+ ACE_Timer_Hash;
+
+typedef ACE_Timer_Hash_Iterator_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX,
+ ACE_Hash_Timer_List>
+ ACE_Timer_Hash_Iterator;
+
+typedef ACE_Timer_Hash_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX,
+ ACE_Hash_Timer_Heap>
+ ACE_Timer_Hash_Heap;
+
+typedef ACE_Timer_Hash_Iterator_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX,
+ ACE_Hash_Timer_Heap>
+ ACE_Timer_Hash_Heap_Iterator;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_HASH_H */
diff --git a/ACE/ace/Timer_Hash_T.cpp b/ACE/ace/Timer_Hash_T.cpp
new file mode 100644
index 00000000000..a2a81fc3773
--- /dev/null
+++ b/ACE/ace/Timer_Hash_T.cpp
@@ -0,0 +1,873 @@
+// $Id$
+
+#ifndef ACE_TIMER_HASH_T_CPP
+#define ACE_TIMER_HASH_T_CPP
+
+#include "ace/Timer_Hash_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace,
+ Timer_Hash_T,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TYPE>
+class Hash_Token
+{
+public:
+ // This constructor is required by ACE_Locked_Free_List::alloc.
+ Hash_Token (void)
+ {}
+
+ Hash_Token<TYPE> *get_next (void)
+ {
+ return this->next_;
+ }
+
+ void set_next (Hash_Token<TYPE> *next)
+ {
+ this->next_ = next;
+ }
+
+ void set (const void *act,
+ size_t pos,
+ long orig_id,
+ const TYPE &type)
+ {
+ this->act_ = act;
+ this->pos_ = pos;
+ this->orig_id_ = orig_id;
+ this->type_ = type;
+ this->next_ = 0;
+ }
+
+ const void *act_;
+ size_t pos_;
+ long orig_id_;
+ TYPE type_;
+ /// Pointer to next token.
+ Hash_Token<TYPE> *next_;
+};
+
+// Default constructor
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall (void)
+ : timer_hash_ (0)
+{
+ // Nothing
+}
+
+// Constructor that specifies a Timer_Hash to call up to
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall (
+ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> *timer_hash)
+ : timer_hash_ (timer_hash)
+{
+ // Nothing
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::registration (
+ TIMER_QUEUE &,
+ ACE_Event_Handler *,
+ const void *)
+{
+ // Registration will be handled by the upcall functor of the timer
+ // hash.
+ return 0;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::preinvoke (TIMER_QUEUE &,
+ ACE_Event_Handler *,
+ const void *,
+ int,
+ const ACE_Time_Value &,
+ const void *&)
+{
+ // This method should never be invoked since we don't invoke
+ // expire() on the buckets.
+ ACE_ASSERT (0);
+ return 0;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::postinvoke (
+ TIMER_QUEUE &,
+ ACE_Event_Handler *,
+ const void *,
+ int,
+ const ACE_Time_Value &,
+ const void *)
+{
+ // This method should never be invoked since we don't invoke
+ // expire() on the buckets.
+ ACE_ASSERT (0);
+ return 0;
+}
+
+// Calls up to timer_hash's upcall functor
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::timeout (
+ TIMER_QUEUE &,
+ ACE_Event_Handler *,
+ const void *,
+ int,
+ const ACE_Time_Value &)
+{
+ // This method should never be invoked since we don't invoke
+ // expire() on the buckets.
+ ACE_ASSERT (0);
+ return 0;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancel_type (
+ TIMER_QUEUE &,
+ ACE_Event_Handler *,
+ int,
+ int &)
+{
+ // Cancellation will be handled by the upcall functor of the timer
+ // hash.
+ return 0;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancel_timer (
+ TIMER_QUEUE &,
+ ACE_Event_Handler *,
+ int,
+ int)
+{
+ // Cancellation will be handled by the upcall functor of the timer
+ // hash.
+ return 0;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::deletion (
+ TIMER_QUEUE &,
+ ACE_Event_Handler *event_handler,
+ const void *arg)
+{
+ // Call up to the upcall functor of the timer hash since the timer
+ // hash does not invoke deletion() on its upcall functor directly.
+ Hash_Token<TYPE> *h =
+ reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (arg));
+
+ int result =
+ this->timer_hash_->upcall_functor ().
+ deletion (*this->timer_hash_,
+ event_handler,
+ h->act_);
+
+ return result;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_Iterator_T (ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET> &hash)
+ : timer_hash_ (hash)
+{
+ this->first ();
+ // Nothing
+}
+
+// Positions the iterator at the first node in the timing hash table
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::first (void)
+{
+ for (this->position_ = 0;
+ this->position_ < this->timer_hash_.table_size_;
+ ++this->position_)
+ {
+ // Check for an empty entry
+ if (!this->timer_hash_.table_[this->position_]->is_empty ())
+ {
+ this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
+ this->iter_->first ();
+ return;
+ }
+ }
+
+ // Didn't find any
+ this->iter_ = 0;
+}
+
+// Positions the iterator at the next node in the bucket or goes to the next
+// bucket
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::next (void)
+{
+ if (this->isdone ())
+ return;
+
+ // If there is no more in the current bucket, go to the next
+ if (this->iter_->isdone ())
+ {
+ for (++this->position_;
+ this->position_ < this->timer_hash_.table_size_;
+ ++this->position_)
+ {
+ // Check for an empty entry
+ if (!this->timer_hash_.table_[this->position_]->is_empty ())
+ {
+ this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
+ this->iter_->first ();
+ return;
+ }
+ }
+
+ // Didn't find any.
+ this->iter_ = 0;
+ }
+ else
+ this->iter_->next ();
+}
+
+// Returns true when we are at the end (when bucket_item_ == 0)
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> bool
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::isdone (void) const
+{
+ return this->iter_ == 0;
+}
+
+// Returns the node at the current position in the sequence
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::item (void)
+{
+ if (this->isdone ())
+ return 0;
+
+ return this->iter_->item ();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::iter (void)
+{
+ this->iterator_->first ();
+ return *this->iterator_;
+}
+
+// Create an empty queue.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_T (
+ size_t table_size,
+ FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> (upcall_functor, freelist),
+ size_ (0),
+ table_size_ (table_size),
+ table_functor_ (this),
+ earliest_position_ (0)
+#if defined (ACE_WIN64)
+ , pointer_base_ (0)
+#endif /* ACE_WIN64 */
+ , token_list_ ()
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
+
+ ACE_NEW (table_,
+ BUCKET *[table_size]);
+
+ this->gettimeofday (ACE_OS::gettimeofday);
+
+ for (size_t i = 0;
+ i < table_size;
+ ++i)
+ {
+ ACE_NEW (this->table_[i],
+ BUCKET (&this->table_functor_,
+ this->free_list_));
+ this->table_[i]->gettimeofday (ACE_OS::gettimeofday);
+ }
+
+ ACE_NEW (iterator_,
+ HASH_ITERATOR (*this));
+}
+
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_T (
+ FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> (upcall_functor, freelist),
+ size_ (0),
+ table_size_ (ACE_DEFAULT_TIMER_HASH_TABLE_SIZE),
+ table_functor_ (this),
+ earliest_position_ (0)
+#if defined (ACE_WIN64)
+ , pointer_base_ (0)
+#endif /* ACE_WIN64 */
+ , token_list_ ()
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
+
+ ACE_NEW (table_,
+ BUCKET *[ACE_DEFAULT_TIMER_HASH_TABLE_SIZE]);
+
+
+ this->gettimeofday (ACE_OS::gettimeofday);
+
+ for (size_t i = 0;
+ i < this->table_size_;
+ ++i)
+ {
+ ACE_NEW (this->table_[i],
+ BUCKET (&this->table_functor_,
+ this->free_list_));
+ this->table_[i]->gettimeofday (ACE_OS::gettimeofday);
+ }
+
+ ACE_NEW (iterator_,
+ HASH_ITERATOR (*this));
+}
+
+// Remove all remaining items in the Queue.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::~ACE_Timer_Hash_T (void)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::~ACE_Timer_Hash_T");
+ ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
+
+ delete iterator_;
+
+ for (size_t i = 0;
+ i < this->table_size_;
+ ++i)
+ delete this->table_[i];
+
+ delete [] this->table_;
+}
+
+// Checks if queue is empty.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> bool
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::is_empty");
+ return this->table_[this->earliest_position_]->is_empty ();
+}
+
+// Returns earliest time in a non-empty bucket
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+const ACE_Time_Value &
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::earliest_time (void) const
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::earliest_time");
+ return this->table_[this->earliest_position_]->earliest_time ();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Timer_Hash_T::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntable_size_ = %d"), this->table_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nearliest_position_ = %d"), this->earliest_position_));
+
+ for (size_t i = 0; i < this->table_size_; ++i)
+ if (!this->table_[i]->is_empty ())
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nBucket %d contains nodes"), i));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// Reschedule a periodic timer. This function must be called with the
+// mutex lock held.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+void
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::reschedule (
+ ACE_Timer_Node_T<TYPE> *expired)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::reschedule");
+
+ Hash_Token<TYPE> *h =
+ reinterpret_cast<Hash_Token<TYPE> *> (
+ const_cast<void *> (expired->get_act ()));
+
+ // Don't use ACE_Utils::truncate_cast<> here. A straight
+ // static_cast<> will provide more unique results when the number
+ // of seconds is greater than std::numeric_limits<size_t>::max().
+ size_t const secs_hash_input =
+ static_cast<size_t> (expired->get_timer_value ().sec ());
+ h->pos_ = secs_hash_input % this->table_size_;
+
+ h->orig_id_ =
+ this->table_[h->pos_]->schedule (expired->get_type (),
+ h,
+ expired->get_timer_value (),
+ expired->get_interval ());
+ ACE_ASSERT (h->orig_id_ != -1);
+
+#if 0
+ ACE_DEBUG ((LM_DEBUG, "Hash::reschedule() resets %d in slot %d where it's id is %d and token is %x\n",
+ expired->get_timer_value ().msec (),
+ h->pos_,
+ h->orig_id_,
+ h));
+#endif
+
+ // Since schedule() above will allocate a new node
+ // then here schedule <expired> for deletion. Don't call
+ // this->free_node() because that will invalidate <h>
+ // and that's what user have as timer_id.
+ ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::free_node (expired);
+
+ if (this->table_[this->earliest_position_]->is_empty ()
+ || this->table_[h->pos_]->earliest_time ()
+ < this->table_[this->earliest_position_]->earliest_time ())
+ this->earliest_position_ = h->pos_;
+}
+
+// Insert a new handler that expires at time future_time; if interval
+// is > 0, the handler will be reinvoked periodically.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+long
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::schedule_i (
+ const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::schedule_i");
+
+ // Don't use ACE_Utils::truncate_cast<> here. A straight
+ // static_cast<> will provide more unique results when the number
+ // of seconds is greater than std::numeric_limits<size_t>::max().
+ size_t const secs_hash_input = static_cast<size_t> (future_time.sec ());
+ size_t const position = secs_hash_input % this->table_size_;
+
+ // Don't create Hash_Token directly. Instead we get one from Free_List
+ // and then set it properly.
+ Hash_Token<TYPE> *h = this->token_list_.remove ();
+ h->set (act, position, 0, type);
+
+ h->orig_id_ =
+ this->table_[position]->schedule (type,
+ h,
+ future_time,
+ interval);
+ ACE_ASSERT (h->orig_id_ != -1);
+
+#if 0
+ ACE_DEBUG ((LM_DEBUG, "Hash::schedule() placing %d in slot %d where it's id is %d and token is %x\n",
+ future_time.msec (),
+ position,
+ h->orig_id_,
+ h));
+#endif
+
+ if (this->table_[this->earliest_position_]->is_empty ()
+ || this->table_[position]->earliest_time ()
+ < this->table_[this->earliest_position_]->earliest_time ())
+ this->earliest_position_ = position;
+
+ ++this->size_;
+
+#if defined (ACE_WIN64)
+ // This is a Win64 hack, necessary because of the original (bad) decision
+ // to use a pointer as the timer ID. This class doesn't follow the usual
+ // timer expiration rules (see comments in header file) and is probably
+ // not used much. The dynamic allocation of Hash_Tokens without
+ // recording them anywhere is a large problem for Win64 since the
+ // size of a pointer is 64 bits, but a long is 32. Since this class
+ // is not much used, I'm hacking this, at least for now. If it becomes
+ // an issue, I'll look at it again then.
+ intptr_t hi = reinterpret_cast<intptr_t> (h);
+ if (this->pointer_base_ == 0)
+ this->pointer_base_ = hi & 0xffffffff00000000;
+ return static_cast<long> (hi & 0xffffffff);
+#else
+ return reinterpret_cast<long> (h);
+#endif
+}
+
+// Locate and update the inteval on the timer_id
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::reset_interval (
+ long timer_id,
+ const ACE_Time_Value & interval)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::reset_interval");
+
+ // Make sure we are getting a valid <timer_id>, not an error
+ // returned by <schedule>.
+ if (timer_id == -1)
+ return -1;
+
+#if defined (ACE_WIN64)
+ unsigned long const timer_offset =
+ static_cast<unsigned long> (timer_id);
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ Hash_Token<TYPE> * const h =
+ reinterpret_cast<Hash_Token<TYPE> *> (this->pointer_base_ + timer_offset);
+#else
+ Hash_Token<TYPE> * const h =
+ reinterpret_cast<Hash_Token<TYPE> *> (timer_id);
+
+ // Grab the lock before accessing the table. We don't need to do so
+ // before this point since no members are accessed until now.
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+#endif /* ACE_WIN64 */
+
+ return this->table_[h->pos_]->reset_interval (h->orig_id_,
+ interval);
+}
+
+// Locate and remove the single <ACE_Event_Handler> with a value of
+// @a timer_id from the correct table timer queue.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (long timer_id,
+ const void **act,
+ int dont_call)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::cancel");
+
+ // Make sure we are getting a valid <timer_id>, not an error
+ // returned by <schedule>.
+ if (timer_id == -1)
+ return 0;
+
+#if defined (ACE_WIN64)
+ unsigned long const timer_offset =
+ static_cast<unsigned long> (timer_id);
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ Hash_Token<TYPE> * const h =
+ reinterpret_cast<Hash_Token<TYPE> *> (this->pointer_base_ + timer_offset);
+#else
+ Hash_Token<TYPE> * const h =
+ reinterpret_cast<Hash_Token<TYPE> *> (timer_id);
+
+ // Grab the lock before accessing the table. We don't need to do so
+ // before this point since no members are accessed until now.
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+#endif /* ACE_WIN64 */
+
+ int const result = this->table_[h->pos_]->cancel (h->orig_id_,
+ 0,
+ dont_call);
+
+ if (result == 1)
+ {
+ // Call the close hooks.
+ int cookie = 0;
+
+ // cancel_type() called once per <type>.
+ this->upcall_functor ().cancel_type (*this,
+ h->type_,
+ dont_call,
+ cookie);
+
+ // cancel_timer() called once per <timer>.
+ this->upcall_functor ().cancel_timer (*this,
+ h->type_,
+ dont_call,
+ cookie);
+
+ if (h->pos_ == this->earliest_position_)
+ this->find_new_earliest ();
+
+ if (act != 0)
+ *act = h->act_;
+
+ // We could destruct Hash_Token explicitly but we better
+ // schedule it for destruction. In this case next
+ // token_list_.remove () will use it.
+ this->token_list_.add (h);
+
+ --this->size_;
+ }
+
+ return result;
+}
+
+// Locate and remove all values of <type> from the timer queue.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (const TYPE &type,
+ int dont_call)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::cancel");
+
+ size_t i; // loop variable.
+
+ Hash_Token<TYPE> **timer_ids = 0;
+ size_t pos = 0;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ ACE_NEW_RETURN (timer_ids,
+ Hash_Token<TYPE> *[this->size_],
+ -1);
+
+ for (i = 0;
+ i < this->table_size_;
+ ++i)
+ {
+ ACE_Timer_Queue_Iterator_T<TYPE,
+ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>,
+ ACE_Null_Mutex> &iter =
+ this->table_[i]->iter ();
+
+ for (iter.first ();
+ !iter.isdone ();
+ iter.next ())
+ if (iter.item ()->get_type () == type)
+ timer_ids[pos++] =
+ reinterpret_cast<Hash_Token<TYPE> *> (
+ const_cast<void *> (iter.item ()->get_act ()));
+ }
+
+ if (pos > this->size_)
+ return -1;
+
+ for (i = 0; i < pos; ++i)
+ {
+ int const result =
+ this->table_[timer_ids[i]->pos_]->cancel (timer_ids[i]->orig_id_,
+ 0,
+ dont_call);
+ ACE_ASSERT (result == 1);
+ ACE_UNUSED_ARG (result);
+
+ // We could destruct Hash_Token explicitly but we better
+ // schedule it for destruction.
+ this->token_list_.add (timer_ids[i]);
+
+ --this->size_;
+ }
+
+ delete [] timer_ids;
+
+ this->find_new_earliest ();
+
+ // Call the close hooks.
+ int cookie = 0;
+
+ // cancel_type() called once per <type>.
+ this->upcall_functor ().cancel_type (*this,
+ type,
+ dont_call,
+ cookie);
+
+ for (i = 0;
+ i < pos;
+ ++i)
+ {
+ // cancel_timer() called once per <timer>.
+ this->upcall_functor ().cancel_timer (*this,
+ type,
+ dont_call,
+ cookie);
+ }
+
+ return static_cast<int> (pos);
+}
+
+// Removes the earliest node and finds the new earliest position
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::remove_first (void)
+{
+ if (this->is_empty ())
+ return 0;
+
+ ACE_Timer_Node_T<TYPE> *temp =
+ this->table_[this->earliest_position_]->remove_first ();
+
+ this->find_new_earliest ();
+
+ --this->size_;
+
+ return temp;
+}
+
+// Finds a new earliest position
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::find_new_earliest (void)
+{
+ for (size_t i = 0; i < this->table_size_; ++i)
+ if (!this->table_[i]->is_empty ())
+ if (this->table_[this->earliest_position_]->is_empty ()
+ || this->earliest_time () == ACE_Time_Value::zero
+ || this->table_[i]->earliest_time () <= this->earliest_time ())
+ this->earliest_position_ = i;
+}
+
+// Returns the earliest node without removing it
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::get_first (void)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::get_first");
+
+ if (this->is_empty ())
+ return 0;
+
+ return this->table_[this->earliest_position_]->get_first ();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::free_node (ACE_Timer_Node_T<TYPE> *node)
+{
+ ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::free_node (node);
+
+ Hash_Token<TYPE> *h =
+ reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (node->get_act ()));
+ this->token_list_.add (h);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::dispatch_info_i (const ACE_Time_Value &cur_time,
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> &info)
+{
+ int const result =
+ ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::dispatch_info_i (cur_time,
+ info);
+
+ if (result == 1)
+ {
+ Hash_Token<TYPE> *h =
+ reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (info.act_));
+
+ info.act_ = h->act_;
+ }
+
+ return result;
+}
+
+// Dummy version of expire to get rid of warnings in Sun CC 4.2
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire ()
+{
+ return ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::expire();
+}
+
+// Specialized expire for Timer Hash
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value &cur_time)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::expire");
+
+ int number_of_timers_expired = 0;
+
+ ACE_Timer_Node_T<TYPE> *expired = 0;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ // Go through the table and expire anything that can be expired
+
+ for (size_t i = 0;
+ i < this->table_size_;
+ ++i)
+ {
+ while (!this->table_[i]->is_empty ()
+ && this->table_[i]->earliest_time () <= cur_time)
+ {
+ expired = this->table_[i]->remove_first ();
+ const void *act = expired->get_act ();
+ bool reclaim = true;
+
+ Hash_Token<TYPE> *h =
+ reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (act));
+
+ ACE_ASSERT (h->pos_ == i);
+
+#if 0
+ ACE_DEBUG ((LM_DEBUG, "Hash::expire() expiring %d in slot %d where it's id is %d and token is %x\n",
+ expired->get_timer_value ().msec (),
+ h->pos_,
+ h->orig_id_,
+ h));
+#endif
+
+ // Check if this is an interval timer.
+ if (expired->get_interval () > ACE_Time_Value::zero)
+ {
+ // Make sure that we skip past values that have already
+ // "expired".
+ do
+ expired->set_timer_value (expired->get_timer_value ()
+ + expired->get_interval ());
+ while (expired->get_timer_value () <= cur_time);
+
+ // Since this is an interval timer, we need to
+ // reschedule it.
+ this->reschedule (expired);
+ reclaim = false;
+ }
+ else
+ {
+ this->free_node (expired);
+ }
+
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
+
+ // Get the dispatch info
+ expired->get_dispatch_info (info);
+
+ info.act_ = h->act_;
+
+ const void *upcall_act = 0;
+
+ this->preinvoke (info, cur_time, upcall_act);
+
+ this->upcall (info, cur_time);
+
+ this->postinvoke (info, cur_time, upcall_act);
+
+ if (reclaim)
+ {
+ --this->size_;
+ }
+
+ ++number_of_timers_expired;
+ }
+ }
+
+ if (number_of_timers_expired > 0)
+ this->find_new_earliest ();
+
+ return number_of_timers_expired;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TIMER_HASH_T_CPP */
diff --git a/ACE/ace/Timer_Hash_T.h b/ACE/ace/Timer_Hash_T.h
new file mode 100644
index 00000000000..53072ebd51c
--- /dev/null
+++ b/ACE/ace/Timer_Hash_T.h
@@ -0,0 +1,342 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Timer_Hash_T.h
+ *
+ * $Id$
+ *
+ * @author Darrell Brunsch <brunsch@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_HASH_T_H
+#define ACE_TIMER_HASH_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Timer_Queue_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Free_List.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration.
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+class ACE_Timer_Hash_T;
+template <typename TYPE>
+class Hash_Token;
+
+/**
+ * @class ACE_Timer_Hash_Upcall
+ *
+ * @brief Functor for Timer_Hash
+ *
+ * This class calls up to the Timer Hash's functor from the
+ * timer queues in the hash table
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Hash_Upcall
+{
+public:
+ typedef ACE_Timer_Queue_T<ACE_Event_Handler *,
+ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>,
+ ACE_Null_Mutex>
+ TIMER_QUEUE;
+
+ /// Default constructor (creates an invalid object, but needs to be here
+ /// so timer queues using this functor can be constructed)
+ ACE_Timer_Hash_Upcall (void);
+
+ /// Constructor that specifies a Timer_Hash to call up to
+ ACE_Timer_Hash_Upcall (ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> *timer_hash);
+
+ /// This method is called when a timer is registered.
+ int registration (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg);
+
+ /// This method is called before the timer expires.
+ int preinvoke (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time,
+ const void *&upcall_act);
+
+ /// This method is called when the timer expires.
+ int timeout (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time);
+
+ /// This method is called after the timer expires.
+ int postinvoke (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time,
+ const void *upcall_act);
+
+ /// This method is called when a handler is cancelled
+ int cancel_type (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ int dont_call,
+ int &requires_reference_counting);
+
+ /// This method is called when a timer is cancelled
+ int cancel_timer (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ int dont_call,
+ int requires_reference_counting);
+
+ /// 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_Event_Handler *handler,
+ const void *arg);
+
+private:
+ /// Timer Queue to do the calling up to
+ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> *timer_hash_;
+
+ // = Don't allow these operations for now.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Timer_Hash_Upcall (const ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK> &))
+};
+
+/**
+ * @class ACE_Timer_Hash_Iterator_T
+ *
+ * @brief Iterates over an ACE_Timer_Hash_T.
+ *
+ * This is a generic iterator that can be used to visit every
+ * node of a timer queue. Be aware that it doesn't transverse
+ * in the order of timeout values.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+class ACE_Timer_Hash_Iterator_T : public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, ACE_LOCK>
+{
+public:
+ /// Constructor.
+ ACE_Timer_Hash_Iterator_T (ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET> &);
+
+ /// Positions the iterator at the earliest node in the Timer Queue
+ virtual void first (void);
+
+ /// Positions the iterator at the next node in the Timer Queue
+ virtual void next (void);
+
+ /// Returns true when there are no more nodes in the sequence
+ virtual bool isdone (void) const;
+
+ /// Returns the node at the current position in the sequence
+ virtual ACE_Timer_Node_T<TYPE> *item (void);
+
+protected:
+ /// Pointer to the ACE_Timer_Hash that we are iterating over.
+ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET> &timer_hash_;
+
+ /// Current position in <timer_hash_>'s table
+ size_t position_;
+
+ /// Current iterator used on <position>'s bucket
+ ACE_Timer_Queue_Iterator_T<TYPE, ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>, ACE_Null_Mutex> *iter_;
+};
+
+/**
+ * @class ACE_Timer_Hash_T
+ *
+ * @brief Provides a hash table of BUCKETs as an implementation for
+ * a timer queue.
+ *
+ * This implementation uses a hash table of BUCKETs. The hash
+ * is based on the time_value of the event. Unlike other Timer
+ * Queues, ACE_Timer_Hash does not expire events in order.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
+class ACE_Timer_Hash_T : public ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>
+{
+public:
+ /// Type of iterator
+ typedef ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>
+ HASH_ITERATOR;
+
+ /// Iterator is a friend
+ friend class ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>;
+
+ /// Type inherited from
+ typedef ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> INHERITED;
+
+ // = Initialization and termination methods.
+ /**
+ * Default constructor. @a table_size determines the size of the
+ * hash table. @a upcall_functor is the instance of the FUNCTOR
+ * to be used by the buckets. If @a upcall_functor is 0, a default
+ * FUNCTOR will be created.
+ */
+ ACE_Timer_Hash_T (size_t table_size,
+ FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+
+ /**
+ * Default constructor. @a upcall_functor is the instance of the
+ * FUNCTOR to be used by the queue. If @a upcall_functor is 0, Timer
+ * Hash will create a default FUNCTOR. @a freelist the freelist of
+ * timer nodes. If 0, then a default freelist will be created. The default
+ * size will be ACE_DEFAULT_TIMERS and there will be no preallocation.
+ */
+ ACE_Timer_Hash_T (FUNCTOR *upcall_functor = 0, ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+
+ /// Destructor
+ virtual ~ACE_Timer_Hash_T (void);
+
+ /// True if queue is empty, else false.
+ virtual bool is_empty (void) const;
+
+ /// Returns the time of the earlier node in the <ACE_Timer_Hash>.
+ /// Must be called on a non-empty queue.
+ virtual const ACE_Time_Value &earliest_time (void) const;
+
+ /**
+ * Resets the interval of the timer represented by @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a 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_interval (long timer_id,
+ const ACE_Time_Value &interval);
+
+ /**
+ * Cancel all timer associated with @a type. If <dont_call> is 0
+ * then the <functor> will be invoked. Returns number of timers
+ * cancelled. If any valid timer is not cancelled before destruction
+ * of this instance of ACE_Timer_Hash_T then user will get a memory
+ * leak.
+ */
+ virtual int cancel (const TYPE &type,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel the single timer that matches the @a 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 timer was registered. This makes it possible
+ * to free up the memory and avoid memory leaks. If <dont_call> is
+ * 0 then the <functor> will be invoked. Returns 1 if cancellation
+ * succeeded and 0 if the @a timer_id wasn't found. If any valid
+ * timer is not cancelled before destruction of this instance of
+ * ACE_Timer_Hash_T then user will get a memory leak.
+ */
+ virtual int cancel (long timer_id,
+ const void **act = 0,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Run the <functor> for all timers whose values are <=
+ * <ACE_OS::gettimeofday>. Also accounts for <timer_skew>. Returns
+ * the number of timers canceled.
+ */
+ virtual int expire (void);
+
+ /**
+ * Run the <functor> for all timers whose values are <= @a current_time.
+ * This does not account for <timer_skew>. Returns the number of
+ * timers canceled.
+ */
+ virtual int expire (const ACE_Time_Value &current_time);
+
+ /// Returns a pointer to this ACE_Timer_Queue's iterator.
+ virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &iter (void);
+
+ /// Removes the earliest node from the queue and returns it
+ virtual ACE_Timer_Node_T<TYPE> *remove_first (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Reads the earliest node from the queue and returns it.
+ virtual ACE_Timer_Node_T<TYPE> *get_first (void);
+
+protected:
+ /// Factory method that frees a previously allocated node.
+ virtual void free_node (ACE_Timer_Node_T<TYPE> *);
+
+private:
+
+ /**
+ * Schedule @a type that will expire at @a future_time,
+ * which is specified in absolute time. If it expires then @a act is
+ * passed in as the value to the <functor>. If @a interval is != to
+ * ACE_Time_Value::zero then it is used to reschedule the @a type
+ * automatically, using relative time to the current <gettimeofday>.
+ * This method returns a <timer_id> that is a pointer to a token
+ * which stores information about the event. This <timer_id> can be
+ * used to cancel the timer before it expires. Returns -1 on
+ * failure.
+ */
+ virtual long schedule_i (const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval);
+
+ /// Non-locking version of dispatch_info ()
+ virtual int dispatch_info_i (const ACE_Time_Value &current_time,
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> &info);
+
+ /// Reschedule an "interval" ACE_Timer_Node.
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
+
+ /// Finds the earliest node
+ void find_new_earliest (void);
+
+ /// Keeps track of the size of the queue
+ size_t size_;
+
+ /// Table of BUCKETS
+ BUCKET **table_;
+
+ /// Keeps track of the size of table_
+ size_t table_size_;
+
+ /// Functor used for the table's timer queues
+ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK> table_functor_;
+
+ /// Index to the position with the earliest entry
+ size_t earliest_position_;
+
+ /// Iterator used to expire timers.
+ HASH_ITERATOR *iterator_;
+
+#if defined (ACE_WIN64)
+ // Part of a hack... see comments in schedule().
+ // This is, essentially, the upper 32 bits of a 64-bit pointer on Win64.
+ ptrdiff_t pointer_base_;
+#endif
+
+ /// Hash_Token is usually allocated in schedule but its
+ /// deallocation is problematic and token_list_ helps with this.
+ ACE_Locked_Free_List<Hash_Token<TYPE>, ACE_Null_Mutex> token_list_;
+
+ // = Don't allow these operations for now.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Timer_Hash_T (const ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Timer_Hash_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Timer_Hash_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_HASH_T_H */
diff --git a/ACE/ace/Timer_Heap.h b/ACE/ace/Timer_Heap.h
new file mode 100644
index 00000000000..a0c9301ebc8
--- /dev/null
+++ b/ACE/ace/Timer_Heap.h
@@ -0,0 +1,41 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Timer_Heap.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_HEAP_H
+#define ACE_TIMER_HEAP_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Timer_Heap_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// The following typedefs are here for ease of use and backward
+// compatibility.
+
+typedef ACE_Timer_Heap_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Timer_Heap;
+
+typedef ACE_Timer_Heap_Iterator_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Timer_Heap_Iterator;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_HEAP_H */
diff --git a/ACE/ace/Timer_Heap_T.cpp b/ACE/ace/Timer_Heap_T.cpp
new file mode 100644
index 00000000000..b31aed4b46a
--- /dev/null
+++ b/ACE/ace/Timer_Heap_T.cpp
@@ -0,0 +1,889 @@
+// $Id$
+
+#ifndef ACE_TIMER_HEAP_T_CPP
+#define ACE_TIMER_HEAP_T_CPP
+
+#include "ace/Timer_Heap_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Guard_T.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Numeric_Limits.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/*
+** The ACE_Timer_Heap::max_size_ and array loops, checks, etc. are all size_t.
+** The timer IDs are long, and since they are indices into the heap, we need
+** to be sure that the timer heap size can fit in a long. Hence, when size
+** is (re)set, limit it to the maximum long value. We use the C++ standard
+** limits if available.
+*/
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Define some simple inlined functions to clarify the code.
+inline size_t
+ACE_HEAP_PARENT (size_t X)
+{
+ return (X == 0 ? 0 : ((X - 1) / 2));
+}
+
+inline size_t
+ACE_HEAP_LCHILD (size_t X)
+{
+ return X + X + 1;
+}
+
+// Constructor that takes in an <ACE_Timer_Heap_T> to iterate over.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_Iterator_T (
+ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &heap)
+ : timer_heap_ (heap)
+{
+ ACE_TRACE ("ACE_Timer_Heap_Iterator_T::ACE_Timer_Heap_Iterator");
+ this->first ();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Heap_Iterator_T (void)
+{
+}
+
+// Positions the iterator at the first node in the heap array
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::first (void)
+{
+ this->position_ = 0;
+}
+
+// Positions the iterator at the next node in the heap array
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::next (void)
+{
+ if (this->position_ != this->timer_heap_.cur_size_)
+ ++this->position_;
+}
+
+// Returns true the <position_> is at the end of the heap array
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::isdone (void) const
+{
+ return this->position_ == this->timer_heap_.cur_size_;
+}
+
+// Returns the node at the current position in the heap or 0 if at the end
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
+{
+ if (this->position_ != this->timer_heap_.cur_size_)
+ return this->timer_heap_.heap_[this->position_];
+ return 0;
+}
+
+// Constructor
+// Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
+// Since timer IDs are assigned by first incrementing the timer_ids_curr_
+// value, the first ID assigned will be 1 (just as in the previous design).
+// When it's time to wrap, the next ID given out will be 0.
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (
+ size_t size,
+ bool preallocated,
+ FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK> (upcall_functor, freelist),
+ max_size_ (size),
+ cur_size_ (0),
+ cur_limbo_ (0),
+ timer_ids_curr_ (0),
+ timer_ids_min_free_ (0),
+ preallocated_nodes_ (0),
+ preallocated_nodes_freelist_ (0)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
+
+ // Possibly reduce size to fit in a long.
+ if (size > static_cast<size_t> (ACE_Numeric_Limits<long>::max ()))
+ {
+ size = static_cast<size_t> (ACE_Numeric_Limits<long>::max ());
+ this->max_size_ = size;
+ }
+
+ // Create the heap array.
+ ACE_NEW (this->heap_,
+ ACE_Timer_Node_T<TYPE> *[size]);
+
+ // Create the parallel
+ ACE_NEW (this->timer_ids_,
+ ssize_t[size]);
+
+ // Initialize the "freelist," which uses negative values to
+ // distinguish freelist elements from "pointers" into the <heap_>
+ // array.
+ for (size_t i = 0; i < size; ++i)
+ this->timer_ids_[i] = -1;
+
+ if (preallocated)
+ {
+ ACE_NEW (this->preallocated_nodes_,
+ ACE_Timer_Node_T<TYPE>[size]);
+
+ // Add allocated array to set of such arrays for deletion on
+ // cleanup.
+ this->preallocated_node_set_.insert (this->preallocated_nodes_);
+
+ // Form the freelist by linking the next_ pointers together.
+ for (size_t j = 1; j < size; ++j)
+ this->preallocated_nodes_[j - 1].set_next (&this->preallocated_nodes_[j]);
+
+ // NULL-terminate the freelist.
+ this->preallocated_nodes_[size - 1].set_next (0);
+
+ // Assign the freelist pointer to the front of the list.
+ this->preallocated_nodes_freelist_ =
+ &this->preallocated_nodes_[0];
+ }
+
+ ACE_NEW (iterator_,
+ HEAP_ITERATOR (*this));
+}
+
+// Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
+// Since timer IDs are assigned by first incrementing the timer_ids_curr_
+// value, the first ID assigned will be 1 (just as in the previous design).
+// When it's time to wrap, the next ID given out will be 0.
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (
+ FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK> (upcall_functor, freelist),
+ max_size_ (ACE_DEFAULT_TIMERS),
+ cur_size_ (0),
+ cur_limbo_ (0),
+ timer_ids_curr_ (0),
+ timer_ids_min_free_ (0),
+ preallocated_nodes_ (0),
+ preallocated_nodes_freelist_ (0)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
+
+ // Possibly reduce size to fit in a long.
+ if (this->max_size_ > static_cast<size_t> (ACE_Numeric_Limits<long>::max ()))
+ this->max_size_ = static_cast<size_t> (ACE_Numeric_Limits<long>::max ());
+
+ // Create the heap array.
+ ACE_NEW (this->heap_,
+ ACE_Timer_Node_T<TYPE> *[this->max_size_]);
+
+ // Create the parallel array.
+ ACE_NEW (this->timer_ids_,
+ ssize_t[this->max_size_]);
+
+ // Initialize the "freelist," which uses negative values to
+ // distinguish freelist elements from "pointers" into the <heap_>
+ // array.
+ for (size_t i = 0; i < this->max_size_; ++i)
+ this->timer_ids_[i] = -1;
+
+ ACE_NEW (iterator_,
+ HEAP_ITERATOR (*this));
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Heap_T (void)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::~ACE_Timer_Heap_T");
+
+ delete iterator_;
+
+ size_t current_size =
+ this->cur_size_;
+
+ // Clean up all the nodes still in the queue
+ for (size_t i = 0; i < current_size; ++i)
+ {
+ // Grab the event_handler and act, then delete the node before calling
+ // back to the handler. Prevents a handler from trying to cancel_timer()
+ // inside handle_close(), ripping the current timer node out from
+ // under us.
+ TYPE eh = this->heap_[i]->get_type ();
+ const void *act = this->heap_[i]->get_act ();
+ this->free_node (this->heap_[i]);
+ this->upcall_functor ().deletion (*this, eh, act);
+ }
+
+ delete [] this->heap_;
+ delete [] this->timer_ids_;
+
+ // clean up any preallocated timer nodes
+ if (preallocated_nodes_ != 0)
+ {
+ ACE_Unbounded_Set_Iterator<ACE_Timer_Node_T<TYPE> *>
+ set_iterator (this->preallocated_node_set_);
+
+ for (ACE_Timer_Node_T<TYPE> **entry = 0;
+ set_iterator.next (entry) !=0;
+ set_iterator.advance ())
+ delete [] *entry;
+ }
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+long
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::pop_freelist (void)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::pop_freelist");
+
+ // Scan for a free timer ID. Note that since this function is called
+ // _after_ the check for a full timer heap, we are guaranteed to find
+ // a free ID, even if we need to wrap around and start reusing freed IDs.
+ // On entry, the curr_ index is at the previous ID given out; start
+ // up where we left off last time.
+ // NOTE - a timer_ids_ slot with -2 is out of the heap, but not freed.
+ // It must be either freed (free_node) or rescheduled (reschedule).
+ ++this->timer_ids_curr_;
+ while (this->timer_ids_curr_ < this->max_size_ &&
+ (this->timer_ids_[this->timer_ids_curr_] >= 0 ||
+ this->timer_ids_[this->timer_ids_curr_] == -2 ))
+ ++this->timer_ids_curr_;
+ if (this->timer_ids_curr_ == this->max_size_)
+ {
+ ACE_ASSERT (this->timer_ids_min_free_ < this->max_size_);
+ this->timer_ids_curr_ = this->timer_ids_min_free_;
+ // We restarted the free search at min. Since min won't be
+ // free anymore, and curr_ will just keep marching up the list
+ // on each successive need for an ID, reset min_free_ to the
+ // size of the list until an ID is freed that curr_ has already
+ // gone past (see push_freelist).
+ this->timer_ids_min_free_ = this->max_size_;
+ }
+
+ return static_cast<long> (this->timer_ids_curr_);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::push_freelist (long old_id)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::push_freelist");
+
+ // Since this ID has already been checked by one of the public
+ // functions, it's safe to cast it here.
+ size_t oldid = static_cast<size_t> (old_id);
+
+ // The freelist values in the <timer_ids_> are negative, so set the
+ // freed entry back to 'free'. If this is the new lowest value free
+ // timer ID that curr_ won't see on it's normal march through the list,
+ // remember it.
+ ACE_ASSERT (this->timer_ids_[oldid] >= 0 || this->timer_ids_[oldid] == -2);
+ if (this->timer_ids_[oldid] == -2)
+ --this->cur_limbo_;
+ else
+ --this->cur_size_;
+ this->timer_ids_[oldid] = -1;
+ if (oldid < this->timer_ids_min_free_ && oldid <= this->timer_ids_curr_)
+ this->timer_ids_min_free_ = oldid;
+ return;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+long
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::timer_id (void)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::timer_id");
+
+ // Return the next item off the freelist and use it as the timer id.
+ return this->pop_freelist ();
+}
+
+// Checks if queue is empty.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+bool
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::is_empty");
+ return this->cur_size_ == 0;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void)
+{
+ this->iterator_->first ();
+ return *this->iterator_;
+}
+
+// Returns earliest time in a non-empty queue.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> const ACE_Time_Value &
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::earliest_time (void) const
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::earliest_time");
+ return this->heap_[0]->get_timer_value ();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Timer_Heap_T::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmax_size_ = %d"), this->max_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_limbo_= %d"), this->cur_limbo_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nids_curr_ = %d"),
+ this->timer_ids_curr_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmin_free_ = %d"),
+ this->timer_ids_min_free_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nheap_ = \n")));
+
+ for (size_t i = 0; i < this->cur_size_; ++i)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%d\n"),
+ i));
+ this->heap_[i]->dump ();
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntimer_ids_ = \n")));
+
+ for (size_t j = 0; j < this->max_size_; ++j)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%d\t%d\n"),
+ j,
+ this->timer_ids_[j]));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::copy (
+ size_t slot,
+ ACE_Timer_Node_T<TYPE> *moved_node)
+{
+ // Insert <moved_node> into its new location in the heap.
+ this->heap_[slot] = moved_node;
+
+ ACE_ASSERT (moved_node->get_timer_id () >= 0
+ && moved_node->get_timer_id () < (int) this->max_size_);
+
+ // Update the corresponding slot in the parallel <timer_ids_> array.
+ this->timer_ids_[moved_node->get_timer_id ()] = static_cast<ssize_t> (slot);
+}
+
+// Remove the slot'th timer node from the heap, but do not reclaim its
+// timer ID or change the size of this timer heap object. The caller of
+// this function must call either free_node (to reclaim the timer ID
+// and the timer node memory, as well as decrement the size of the queue)
+// or reschedule (to reinsert the node in the heap at a new time).
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::remove (size_t slot)
+{
+ ACE_Timer_Node_T<TYPE> *removed_node =
+ this->heap_[slot];
+
+ // NOTE - the cur_size_ is being decremented since the queue has one
+ // less active timer in it. However, this ACE_Timer_Node is not being
+ // freed, and there is still a place for it in timer_ids_ (the timer ID
+ // is not being relinquished). The node can still be rescheduled, or
+ // it can be freed via free_node.
+ --this->cur_size_;
+
+ // Only try to reheapify if we're not deleting the last entry.
+
+ if (slot < this->cur_size_)
+ {
+ ACE_Timer_Node_T<TYPE> *moved_node =
+ this->heap_[this->cur_size_];
+
+ // Move the end node to the location being removed and update
+ // the corresponding slot in the parallel <timer_ids> array.
+ this->copy (slot, moved_node);
+
+ // If the <moved_node->time_value_> is great than or equal its
+ // parent it needs be moved down the heap.
+ size_t parent = ACE_HEAP_PARENT (slot);
+
+ if (moved_node->get_timer_value ()
+ >= this->heap_[parent]->get_timer_value ())
+ this->reheap_down (moved_node,
+ slot,
+ ACE_HEAP_LCHILD (slot));
+ else
+ this->reheap_up (moved_node,
+ slot,
+ parent);
+ }
+
+ this->timer_ids_[removed_node->get_timer_id ()] = -2;
+ ++this->cur_limbo_;
+ return removed_node;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reheap_down (
+ ACE_Timer_Node_T<TYPE> *moved_node,
+ size_t slot,
+ size_t child)
+{
+ // Restore the heap property after a deletion.
+
+ while (child < this->cur_size_)
+ {
+ // Choose the smaller of the two children.
+ if (child + 1 < this->cur_size_
+ && this->heap_[child + 1]->get_timer_value ()
+ < this->heap_[child]->get_timer_value ())
+ child++;
+
+ // Perform a <copy> if the child has a larger timeout value than
+ // the <moved_node>.
+ if (this->heap_[child]->get_timer_value ()
+ < moved_node->get_timer_value ())
+ {
+ this->copy (slot,
+ this->heap_[child]);
+ slot = child;
+ child = ACE_HEAP_LCHILD (child);
+ }
+ else
+ // We've found our location in the heap.
+ break;
+ }
+
+ this->copy (slot, moved_node);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reheap_up (
+ ACE_Timer_Node_T<TYPE> *moved_node,
+ size_t slot,
+ size_t parent)
+{
+ // Restore the heap property after an insertion.
+
+ while (slot > 0)
+ {
+ // If the parent node is greater than the <moved_node> we need
+ // to copy it down.
+ if (moved_node->get_timer_value ()
+ < this->heap_[parent]->get_timer_value ())
+ {
+ this->copy (slot, this->heap_[parent]);
+ slot = parent;
+ parent = ACE_HEAP_PARENT (slot);
+ }
+ else
+ break;
+ }
+
+ // Insert the new node into its proper resting place in the heap and
+ // update the corresponding slot in the parallel <timer_ids> array.
+ this->copy (slot,
+ moved_node);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::insert (
+ ACE_Timer_Node_T<TYPE> *new_node)
+{
+ if (this->cur_size_ + this->cur_limbo_ + 2 >= this->max_size_)
+ this->grow_heap ();
+
+ this->reheap_up (new_node,
+ this->cur_size_,
+ ACE_HEAP_PARENT (this->cur_size_));
+ this->cur_size_++;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::grow_heap (void)
+{
+ // All the containers will double in size from max_size_.
+ size_t new_size = this->max_size_ * 2;
+
+#if 0
+ // Yikes - there's no way to flag a failure of going out of range of
+ // a 'long' - this is a problem that should be addressed at some point.
+ if (new_size > ACE_Numeric_Limits<long>::max ())
+ new_size = ACE_Numeric_Limits<long>::max ();
+
+ if (new_size <= this->max_size_) // We are already at the limit
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+#endif /* 0 */
+
+ // First grow the heap itself.
+
+ ACE_Timer_Node_T<TYPE> **new_heap = 0;
+
+ ACE_NEW (new_heap,
+ ACE_Timer_Node_T<TYPE> *[new_size]);
+
+ ACE_OS::memcpy (new_heap,
+ this->heap_,
+ this->max_size_ * sizeof *new_heap);
+ delete [] this->heap_;
+ this->heap_ = new_heap;
+
+ // Grow the array of timer ids.
+
+ ssize_t *new_timer_ids = 0;
+
+ ACE_NEW (new_timer_ids,
+ ssize_t[new_size]);
+
+ ACE_OS::memcpy (new_timer_ids,
+ this->timer_ids_,
+ this->max_size_ * sizeof (ssize_t));
+
+ delete [] timer_ids_;
+ this->timer_ids_ = new_timer_ids;
+
+ // And add the new elements to the end of the "freelist".
+ for (size_t i = this->max_size_; i < new_size; ++i)
+ this->timer_ids_[i] = -(static_cast<ssize_t> (i) + 1);
+
+ // Grow the preallocation array (if using preallocation)
+ if (this->preallocated_nodes_ != 0)
+ {
+ // Create a new array with max_size elements to link in to
+ // existing list.
+ ACE_NEW (this->preallocated_nodes_,
+ ACE_Timer_Node_T<TYPE>[this->max_size_]);
+
+ // Add it to the set for later deletion
+ this->preallocated_node_set_.insert (this->preallocated_nodes_);
+
+ // Link new nodes together (as for original list).
+ for (size_t k = 1; k < this->max_size_; ++k)
+ this->preallocated_nodes_[k - 1].set_next (&this->preallocated_nodes_[k]);
+
+ // NULL-terminate the new list.
+ this->preallocated_nodes_[this->max_size_ - 1].set_next (0);
+
+ // Link new array to the end of the existling list.
+ if (this->preallocated_nodes_freelist_ == 0)
+ this->preallocated_nodes_freelist_ =
+ &preallocated_nodes_[0];
+ else
+ {
+ ACE_Timer_Node_T<TYPE> *previous =
+ this->preallocated_nodes_freelist_;
+
+ for (ACE_Timer_Node_T<TYPE> *current = this->preallocated_nodes_freelist_->get_next ();
+ current != 0;
+ current = current->get_next ())
+ previous = current;
+
+ previous->set_next (&this->preallocated_nodes_[0]);
+ }
+ }
+
+ this->max_size_ = new_size;
+ // Force rescan of list from beginning for a free slot (I think...)
+ // This fixed Bugzilla #2447.
+ this->timer_ids_min_free_ = this->max_size_;
+}
+
+// Reschedule a periodic timer. This function must be called with the
+// mutex lock held.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reschedule (
+ ACE_Timer_Node_T<TYPE> *expired)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::reschedule");
+
+ // If we are rescheduling, then the most recent call was to
+ // remove_first (). That called remove () to remove the node from the
+ // heap, but did not free the timer ID. The ACE_Timer_Node still has
+ // its assigned ID - just needs to be inserted at the new proper
+ // place, and the heap restored properly.
+ if (this->timer_ids_[expired->get_timer_id ()] == -2)
+ --this->cur_limbo_;
+ this->insert (expired);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::alloc_node (void)
+{
+ ACE_Timer_Node_T<TYPE> *temp = 0;
+
+ // Only allocate a node if we are *not* using the preallocated heap.
+ if (this->preallocated_nodes_ == 0)
+ ACE_NEW_RETURN (temp,
+ ACE_Timer_Node_T<TYPE>,
+ 0);
+ else
+ {
+ // check to see if the heap needs to grow
+ if (this->preallocated_nodes_freelist_ == 0)
+ this->grow_heap ();
+
+ temp = this->preallocated_nodes_freelist_;
+
+ // Remove the first element from the freelist.
+ this->preallocated_nodes_freelist_ =
+ this->preallocated_nodes_freelist_->get_next ();
+ }
+ return temp;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+void
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::free_node (
+ ACE_Timer_Node_T<TYPE> *node)
+{
+ // Return this timer id to the freelist.
+ this->push_freelist (node->get_timer_id ());
+
+ // Only free up a node if we are *not* using the preallocated heap.
+ if (this->preallocated_nodes_ == 0)
+ delete node;
+ else
+ {
+ node->set_next (this->preallocated_nodes_freelist_);
+ this->preallocated_nodes_freelist_ = node;
+ }
+}
+
+// Insert a new timer that expires at time future_time; if interval is
+// > 0, the handler will be reinvoked periodically.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+long
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (
+ const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::schedule_i");
+
+ if ((this->cur_size_ + this->cur_limbo_) < this->max_size_)
+ {
+ // Obtain the next unique sequence number.
+ long timer_id = this->timer_id ();
+
+ // Obtain the memory to the new node.
+ ACE_Timer_Node_T<TYPE> *temp = 0;
+
+ ACE_ALLOCATOR_RETURN (temp,
+ this->alloc_node (),
+ -1);
+ temp->set (type,
+ act,
+ future_time,
+ interval,
+ 0,
+ timer_id);
+
+ this->insert (temp);
+ return timer_id;
+ }
+ else
+ return -1;
+}
+
+// Locate and remove the single timer with a value of @a timer_id from
+// the timer queue.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+int
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
+ const void **act,
+ int dont_call)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::cancel");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ // Locate the ACE_Timer_Node that corresponds to the timer_id.
+
+ // Check to see if the timer_id is out of range
+ if (timer_id < 0
+ || (size_t) timer_id > this->max_size_)
+ return 0;
+
+ ssize_t timer_node_slot = this->timer_ids_[timer_id];
+
+ // Check to see if timer_id is still valid.
+ if (timer_node_slot < 0)
+ return 0;
+
+ if (timer_id != this->heap_[timer_node_slot]->get_timer_id ())
+ {
+ ACE_ASSERT (timer_id == this->heap_[timer_node_slot]->get_timer_id ());
+ return 0;
+ }
+ else
+ {
+ ACE_Timer_Node_T<TYPE> *temp =
+ this->remove (timer_node_slot);
+
+ // Call the close hooks.
+ int cookie = 0;
+
+ // cancel_type() called once per <type>.
+ this->upcall_functor ().cancel_type (*this,
+ temp->get_type (),
+ dont_call,
+ cookie);
+
+ // cancel_timer() called once per <timer>.
+ this->upcall_functor ().cancel_timer (*this,
+ temp->get_type (),
+ dont_call,
+ cookie);
+
+ if (act != 0)
+ *act = temp->get_act ();
+
+ this->free_node (temp);
+ return 1;
+ }
+}
+
+// Locate and update the inteval on the timer_id
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+int
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::reset_interval");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ // Locate the ACE_Timer_Node that corresponds to the timer_id.
+
+ // Check to see if the timer_id is out of range
+ if (timer_id < 0
+ || (size_t) timer_id > this->max_size_)
+ return -1;
+
+ ssize_t timer_node_slot = this->timer_ids_[timer_id];
+
+ // Check to see if timer_id is still valid.
+ if (timer_node_slot < 0)
+ return -1;
+
+ if (timer_id != this->heap_[timer_node_slot]->get_timer_id ())
+ {
+ ACE_ASSERT (timer_id == this->heap_[timer_node_slot]->get_timer_id ());
+ return -1;
+ }
+ else
+ {
+ // Reset the timer interval
+ this->heap_[timer_node_slot]->set_interval (interval);
+ return 0;
+ }
+}
+
+// Locate and remove all values of @a type from the timer queue.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+int
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE &type,
+ int dont_call)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::cancel");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ int number_of_cancellations = 0;
+
+ // Try to locate the ACE_Timer_Node that matches the timer_id.
+
+ for (size_t i = 0; i < this->cur_size_; )
+ {
+ if (this->heap_[i]->get_type () == type)
+ {
+ ACE_Timer_Node_T<TYPE> *temp = this->remove (i);
+
+ ++number_of_cancellations;
+
+ this->free_node (temp);
+
+ // We reset to zero so that we don't miss checking any nodes
+ // if a reheapify occurs when a node is removed. There
+ // may be a better fix than this, however.
+ i = 0;
+ }
+ else
+ ++i;
+ }
+
+ // Call the close hooks.
+ int cookie = 0;
+
+ // cancel_type() called once per <type>.
+ this->upcall_functor ().cancel_type (*this,
+ type,
+ dont_call,
+ cookie);
+
+ for (int j = 0;
+ j < number_of_cancellations;
+ ++j)
+ {
+ // cancel_timer() called once per <timer>.
+ this->upcall_functor ().cancel_timer (*this,
+ type,
+ dont_call,
+ cookie);
+ }
+
+ return number_of_cancellations;
+}
+
+// Returns the earliest node or returns 0 if the heap is empty.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T <TYPE> *
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first (void)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::remove_first");
+
+ if (this->cur_size_ == 0)
+ return 0;
+
+ return this->remove (0);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T <TYPE> *
+ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::get_first");
+
+ return this->cur_size_ == 0 ? 0 : this->heap_[0];
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TIMER_HEAP_T_CPP */
diff --git a/ACE/ace/Timer_Heap_T.h b/ACE/ace/Timer_Heap_T.h
new file mode 100644
index 00000000000..75f3e98ad10
--- /dev/null
+++ b/ACE/ace/Timer_Heap_T.h
@@ -0,0 +1,338 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timer_Heap_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_HEAP_T_H
+#define ACE_TIMER_HEAP_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Timer_Queue_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Free_List.h"
+#include "ace/Unbounded_Set.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Heap_T;
+
+/**
+ * @class ACE_Timer_Heap_Iterator_T
+ *
+ * @brief Iterates over an ACE_Timer_Heap_T.
+ *
+ * This is a generic iterator that can be used to visit every
+ * node of a timer queue. Be aware that it doesn't transverse
+ * in the order of timeout values.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Heap_Iterator_T : public ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>
+{
+public:
+ /// Constructor.
+ ACE_Timer_Heap_Iterator_T (ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &);
+
+ /// Destructor.
+ ~ACE_Timer_Heap_Iterator_T (void);
+
+ /// Positions the iterator at the earliest node in the Timer Queue
+ virtual void first (void);
+
+ /// Positions the iterator at the next node in the Timer Queue
+ virtual void next (void);
+
+ /// Returns true when there are no more nodes in the sequence
+ virtual bool isdone (void) const;
+
+ /// Returns the node at the current position in the sequence
+ virtual ACE_Timer_Node_T<TYPE> *item (void);
+
+protected:
+ /// Pointer to the ACE_Timer_Heap that we are iterating over.
+ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &timer_heap_;
+
+ /// Position in the array where the iterator is at
+ size_t position_;
+};
+
+/**
+ * @class ACE_Timer_Heap_T
+ *
+ * @brief Provides a very fast and predictable timer implementation.
+ *
+ * This implementation uses a heap-based callout queue of
+ * absolute times. Therefore, in the average and worst case,
+ * scheduling, canceling, and expiring timers is O(log N) (where
+ * N is the total number of timers). In addition, we can also
+ * preallocate as many @c ACE_Timer_Node objects as there are slots
+ * in the heap. This allows us to completely remove the need for
+ * dynamic memory allocation, which is important for real-time
+ * systems.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Heap_T : public ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>
+{
+public:
+ typedef ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> HEAP_ITERATOR;
+ friend class ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>;
+
+ typedef ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> INHERITED;
+
+ // = Initialization and termination methods.
+ /**
+ * The Constructor creates a heap with specified number of elements.
+ * This can also take in a upcall functor and freelist (if 0, then
+ * defaults will be created).
+ *
+ * @param size The maximum number of timers that can be
+ * inserted into the new object.
+ * @param preallocated Default false, true then all the memory
+ * for the @c ACE_Timer_Node objects will be pre-allocated. This saves
+ * time and is more predictable (though it requires more space).
+ * Otherwise, timer nodes are allocated as needed.
+ * @param freelist is the freelist of timer nodes.
+ * @param upcall_functor If 0 Timer Heap will create a default FUNCTOR.
+ */
+ ACE_Timer_Heap_T (size_t size,
+ bool preallocated = false,
+ FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+
+ /**
+ * Default constructor. @c upcall_functor is the instance of the
+ * FUNCTOR to be used by the queue. If @c upcall_functor is 0, Timer
+ * Heap will create a default FUNCTOR. @c freelist is the freelist of
+ * timer nodes. If 0, then a default freelist will be created. The default
+ * size will be ACE_DEFAULT_TIMERS and there will be no preallocation.
+ */
+ ACE_Timer_Heap_T (FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+
+ /// Destructor.
+ virtual ~ACE_Timer_Heap_T (void);
+
+ /// True if heap is empty, else false.
+ virtual bool is_empty (void) const;
+
+ /// Returns the time of the earliest node in the Timer_Queue.
+ /// Must be called on a non-empty queue.
+ virtual const ACE_Time_Value &earliest_time (void) const;
+
+ /**
+ * Resets the interval of the timer represented by @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a 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_interval (long timer_id,
+ const ACE_Time_Value &interval);
+
+ /**
+ * Cancel all timers associated with @a type. If @a dont_call_handle_close
+ * is 0then the <functor> will be invoked. Returns number of timers
+ * cancelled.
+ */
+ virtual int cancel (const TYPE &type,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel the single timer that matches the @a 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 timer was registered. This makes it possible
+ * to free up the memory and avoid memory leaks. If @a dont_call_handle_close
+ * is 0 then the <functor> will be invoked. Returns 1 if cancellation
+ * succeeded and 0 if the @a timer_id wasn't found.
+ */
+ virtual int cancel (long timer_id,
+ const void **act = 0,
+ int dont_call_handle_close = 1);
+
+ /// Returns a pointer to this ACE_Timer_Queue's iterator.
+ virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &iter (void);
+
+ /**
+ * Removes the earliest node from the queue and returns it. Note that
+ * the timer is removed from the heap, but is not freed, and its ID
+ * is not reclaimed. The caller is responsible for calling either
+ * @c reschedule() or @c free_node() after this function returns. Thus,
+ * this function is for support of @c ACE_Timer_Queue::expire and
+ * should not be used unadvisedly in other conditions.
+ */
+ ACE_Timer_Node_T <TYPE> *remove_first (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Reads the earliest node from the queue and returns it.
+ virtual ACE_Timer_Node_T<TYPE> *get_first (void);
+
+protected:
+
+ /**
+ * Schedule a timer that may optionally auto-reset.
+ * Schedule @a type that will expire at @a future_time,
+ * which is specified in absolute time. If it expires then @a act is
+ * passed in as the value to the <functor>. If @a interval is != to
+ * ACE_Time_Value::zero then it is used to reschedule the @a type
+ * automatically, using relative time to the current <gettimeofday>.
+ * This method returns a <timer_id> that uniquely identifies the the
+ * @a type entry in an internal list. This <timer_id> can be used to
+ * cancel the 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_i (const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval);
+
+ /// Reschedule an "interval" ACE_Timer_Node.
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
+
+ /// Factory method that allocates a new node (uses operator new if
+ /// we're *not* preallocating, otherwise uses an internal freelist).
+ virtual ACE_Timer_Node_T<TYPE> *alloc_node (void);
+
+ /**
+ * Factory method that frees a previously allocated node (uses
+ * operator delete if we're *not* preallocating, otherwise uses an
+ * internal freelist).
+ */
+ virtual void free_node (ACE_Timer_Node_T<TYPE> *);
+
+private:
+ /// Remove and return the @a sloth ACE_Timer_Node and restore the
+ /// heap property.
+ ACE_Timer_Node_T<TYPE> *remove (size_t slot);
+
+ /// Insert @a new_node into the heap and restore the heap property.
+ void insert (ACE_Timer_Node_T<TYPE> *new_node);
+
+ /**
+ * Doubles the size of the heap and the corresponding timer_ids array.
+ * If preallocation is used, will also double the size of the
+ * preallocated array of ACE_Timer_Nodes.
+ */
+ void grow_heap (void);
+
+ /// Restore the heap property, starting at @a slot.
+ void reheap_up (ACE_Timer_Node_T<TYPE> *new_node,
+ size_t slot,
+ size_t parent);
+
+ /// Restore the heap property, starting at @a slot.
+ void reheap_down (ACE_Timer_Node_T<TYPE> *moved_node,
+ size_t slot,
+ size_t child);
+
+ /// Copy @a moved_node into the @a slot slot of <heap_> and move
+ /// @a slot into the corresponding slot in the <timer_id_> array.
+ void copy (size_t slot, ACE_Timer_Node_T<TYPE> *moved_node);
+
+ /**
+ * Returns a timer id that uniquely identifies this timer. This id
+ * can be used to cancel a timer via the <cancel (int)> method. The
+ * timer id returned from this method will never == -1 to avoid
+ * conflicts with other failure return values.
+ */
+ long timer_id (void);
+
+ /// Pops and returns a new timer id from the freelist.
+ long pop_freelist (void);
+
+ /// Pushes @a old_id onto the freelist.
+ void push_freelist (long old_id);
+
+ /// Maximum size of the heap.
+ size_t max_size_;
+
+ /// Current size of the heap.
+ size_t cur_size_;
+
+ /// Number of heap entries in transition (removed from the queue, but
+ /// not freed) and may be rescheduled or freed.
+ size_t cur_limbo_;
+
+ /// Iterator used to expire timers.
+ HEAP_ITERATOR *iterator_;
+
+ /**
+ * Current contents of the Heap, which is organized as a "heap" of
+ * ACE_Timer_Node *'s. In this context, a heap is a "partially
+ * ordered, almost complete" binary tree, which is stored in an
+ * array.
+ */
+ ACE_Timer_Node_T<TYPE> **heap_;
+
+ /**
+ * An array of "pointers" that allows each ACE_Timer_Node in the
+ * <heap_> to be located in O(1) time. Basically, <timer_id_[i]>
+ * contains the slot in the <heap_> array where an ACE_Timer_Node
+ * * with timer id \<i\> resides. Thus, the timer id passed back from
+ * <schedule> is really a slot into the <timer_ids> array. The
+ * <timer_ids_> array serves two purposes: negative values are
+ * indications of free timer IDs, whereas positive values are
+ * "pointers" into the <heap_> array for assigned timer IDs.
+ */
+ ssize_t *timer_ids_;
+
+ /// "Pointer" to the element in the <timer_ids_> array that was
+ /// last given out as a timer ID.
+ size_t timer_ids_curr_;
+
+ /// Index representing the lowest timer ID that has been freed. When
+ /// the timer_ids_next_ value wraps around, it starts back at this
+ /// point.
+ size_t timer_ids_min_free_;
+
+ /**
+ * If this is non-0, then we preallocate <max_size_> number of
+ * ACE_Timer_Node objects in order to reduce dynamic allocation
+ * costs. In auto-growing implementation, this points to the
+ * last array of nodes allocated.
+ */
+ ACE_Timer_Node_T<TYPE> *preallocated_nodes_;
+
+ /// This points to the head of the <preallocated_nodes_> freelist,
+ /// which is organized as a stack.
+ ACE_Timer_Node_T<TYPE> *preallocated_nodes_freelist_;
+
+ /// Set of pointers to the arrays of preallocated timer nodes.
+ /// Used to delete the allocated memory when required.
+ ACE_Unbounded_Set<ACE_Timer_Node_T<TYPE> *> preallocated_node_set_;
+
+ // = Don't allow these operations for now.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Timer_Heap_T (const ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Timer_Heap_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Timer_Heap_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_HEAP_T_H */
diff --git a/ACE/ace/Timer_List.h b/ACE/ace/Timer_List.h
new file mode 100644
index 00000000000..0bc689465ea
--- /dev/null
+++ b/ACE/ace/Timer_List.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timer_List.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_TIMER_LIST_H
+#define ACE_TIMER_LIST_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Timer_List_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// The following typedefs are here for ease of use and backward
+// compatibility.
+
+typedef ACE_Timer_List_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Timer_List;
+
+typedef ACE_Timer_List_Iterator_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Timer_List_Iterator;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_LIST_H */
diff --git a/ACE/ace/Timer_List_T.cpp b/ACE/ace/Timer_List_T.cpp
new file mode 100644
index 00000000000..e2313d0e002
--- /dev/null
+++ b/ACE/ace/Timer_List_T.cpp
@@ -0,0 +1,418 @@
+// $Id$
+
+#ifndef ACE_TIMER_LIST_T_C
+#define ACE_TIMER_LIST_T_C
+
+#include "ace/Timer_List_T.h"
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_RCSID(ace, Timer_List_T, "$Id$")
+
+// Default Constructor
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_List_Iterator_T (List& lst)
+ : list_ (lst)
+{
+ this->first();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_List_Iterator_T (void)
+{
+}
+
+// Positions the iterator at the node right after the dummy node
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::first (void)
+{
+ this->current_node_ = this->list_.get_first();
+}
+
+// Positions the iterator at the next node in the Timer Queue
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::next (void)
+{
+ // Make sure that if we are at the end, we don't wrap around
+ if (! this->isdone())
+ this->current_node_ = this->current_node_->get_next ();
+ if (this->current_node_ == this->list_.head_)
+ this->current_node_ = 0;
+}
+
+// Returns true when we are at <head_>
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::isdone (void) const
+{
+ return this->current_node_ == 0;
+}
+
+// Returns the node at <position_> or 0 if we are at the end
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
+{
+ if (! this->isdone())
+ return this->current_node_;
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+// Return our instance of the iterator
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void)
+{
+ this->iterator_->first ();
+ return *this->iterator_;
+}
+
+// Create an empty list.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_List_T (FUNCTOR* uf, FreeList* fl)
+ : Base(uf, fl)
+ , head_ (new ACE_Timer_Node_T<TYPE>)
+ , id_counter_ (0)
+{
+ ACE_TRACE ("ACE_Timer_List_T::ACE_Timer_List_T");
+
+ this->head_->set_next (this->head_);
+ this->head_->set_prev (this->head_);
+
+ ACE_NEW (iterator_, Iterator(*this));
+}
+
+
+// Checks if list is empty.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Timer_List_T::is_empty");
+ return this->get_first_i() == 0;
+}
+
+
+// Returns earliest time in a non-empty list.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> const ACE_Time_Value &
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::earliest_time (void) const
+{
+ ACE_TRACE ("ACE_Timer_List_T::earliest_time");
+ ACE_Timer_Node_T<TYPE>* first = this->get_first_i();
+ if (first != 0)
+ return first->get_timer_value ();
+ return ACE_Time_Value::zero;
+}
+
+
+// Remove all remaining items in the list.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_List_T (void)
+{
+ ACE_TRACE ("ACE_Timer_List_T::~ACE_Timer_List_T");
+ ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
+
+ delete iterator_;
+
+ if (!this->is_empty())
+ {
+ for (ACE_Timer_Node_T<TYPE>* n = this->get_first();
+ n != this->head_;
+ )
+ {
+ this->upcall_functor ().deletion (*this,
+ n->get_type(),
+ n->get_act());
+
+ ACE_Timer_Node_T<TYPE> *next =
+ n->get_next ();
+
+ this->free_node (n);
+
+ n = next;
+ }
+ }
+
+ // delete the dummy node
+ delete this->head_;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Timer_List_T::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ int count = 0;
+
+ ACE_Timer_Node_T<TYPE>* n = this->get_first_i();
+ if (n != 0) {
+ for (; n != this->head_; n = n->get_next()) {
+ ++count;
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nsize_ = %d"), count));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+
+// Reschedule a periodic timer. This function must be called with the
+// lock held.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::reschedule (ACE_Timer_Node_T<TYPE>* n)
+{
+ ACE_TRACE ("ACE_Timer_List_T::reschedule");
+ this->schedule_i(n, n->get_timer_value());
+}
+
+
+// Insert a new handler that expires at time future_time; if interval
+// is > 0, the handler will be reinvoked periodically.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> long
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Timer_List_T::schedule_i");
+
+ ACE_Timer_Node_T<TYPE>* n = this->alloc_node();
+
+ if (n != 0)
+ {
+ long id = this->id_counter_++;
+
+ if (id != -1) {
+ n->set (type, act, future_time, interval, 0, 0, id);
+ this->schedule_i (n, future_time);
+ }
+ return id;
+ }
+
+ // Failure return
+ errno = ENOMEM;
+ return -1;
+}
+
+/// The shared scheduling functionality between schedule() and reschedule()
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (ACE_Timer_Node_T<TYPE>* n,
+ const ACE_Time_Value& expire)
+{
+ if (this->is_empty()) {
+ n->set_prev(this->head_);
+ n->set_next(this->head_);
+ this->head_->set_prev(n);
+ this->head_->set_next(n);
+ return;
+ }
+
+ // We always want to search backwards from the tail of the list, because
+ // this minimizes the search in the extreme case when lots of timers are
+ // scheduled for exactly the same time, and it also assumes that most of
+ // the timers will be scheduled later than existing timers.
+ ACE_Timer_Node_T<TYPE>* p = this->head_->get_prev();
+ while (p != this->head_ && p->get_timer_value() > expire)
+ p = p->get_prev();
+
+ // insert after
+ n->set_prev(p);
+ n->set_next(p->get_next());
+ p->get_next()->set_prev(n);
+ p->set_next(n);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T<TYPE>*
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::find_node (long timer_id) const
+{
+ ACE_Timer_Node_T<TYPE>* n = this->get_first_i();
+ if (n == 0)
+ return 0;
+
+ for (; n != this->head_; n = n->get_next()) {
+ if (n->get_timer_id() == timer_id) {
+ return n;
+ }
+ }
+ return 0;
+}
+
+// Locate and update the inteval on the timer_id
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Timer_List_T::reset_interval");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+ ACE_Timer_Node_T<TYPE>* n = this->find_node(timer_id);
+ if (n != 0) {
+ n->set_interval(interval); // The interval will take effect the next time this node is expired.
+ return 0;
+ }
+ return -1;
+}
+
+// Locate and remove the single <ACE_Event_Handler> with a value of
+// @a timer_id from the timer queue.
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
+ const void **act,
+ int skip_close)
+{
+ ACE_TRACE ("ACE_Timer_List_T::cancel");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+ ACE_Timer_Node_T<TYPE>* n = this->find_node(timer_id);
+ if (n != 0)
+ {
+ if (act != 0)
+ *act = n->get_act ();
+
+ // Call the close hooks.
+ int cookie = 0;
+
+ // cancel_type() called once per <type>.
+ this->upcall_functor ().cancel_type (*this,
+ n->get_type (),
+ skip_close,
+ cookie);
+
+ // cancel_timer() called once per <timer>.
+ this->upcall_functor ().cancel_timer (*this,
+ n->get_type (),
+ skip_close,
+ cookie);
+
+ this->cancel_i (n);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+// Locate and remove all values of <handler> from the timer queue.
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE &type, int skip_close)
+{
+ ACE_TRACE ("ACE_Timer_List_T::cancel");
+
+ int num_canceled = 0; // Note : Technically this can overflow.
+
+ int cookie = 0;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ if (!this->is_empty ())
+ {
+ for (ACE_Timer_Node_T<TYPE>* n = this->get_first();
+ n != this->head_;
+ )
+ {
+ if (n->get_type() == type) // Note: Typically Type is an ACE_Event_Handler*
+ {
+ ++num_canceled;
+
+ ACE_Timer_Node_T<TYPE>* tmp = n;
+ n = n->get_next();
+
+ this->cancel_i (tmp);
+ }
+ else
+ {
+ n = n->get_next();
+ }
+ }
+ }
+
+ // Call the close hooks.
+
+ // cancel_type() called once per <type>.
+ this->upcall_functor ().cancel_type (*this,
+ type,
+ skip_close,
+ cookie);
+
+ for (int i = 0;
+ i < num_canceled;
+ ++i)
+ {
+ // cancel_timer() called once per <timer>.
+ this->upcall_functor ().cancel_timer (*this,
+ type,
+ skip_close,
+ cookie);
+ }
+
+ return num_canceled;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::unlink (ACE_Timer_Node_T<TYPE>* n)
+{
+ n->get_prev()->set_next(n->get_next());
+ n->get_next()->set_prev(n->get_prev());
+ n->set_prev(0);
+ n->set_next(0);
+}
+
+/// Shared subset of the two cancel() methods.
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n)
+{
+ this->unlink (n);
+ this->free_node (n);
+}
+
+// Reads the first node on the list and returns it.
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
+{
+ ACE_TRACE ("ACE_Timer_List_T::get_first");
+ return this->get_first_i();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const
+{
+ ACE_TRACE ("ACE_Timer_List_T::get_first_i");
+ ACE_Timer_Node_T<TYPE>* first = this->head_->get_next();
+ if (first != this->head_) // Note : is_empty() uses get_first()
+ return first;
+ return 0;
+}
+
+
+// Removes the first node on the list and returns it.
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first (void)
+{
+ ACE_TRACE ("ACE_Timer_List_T::remove_first");
+ ACE_Timer_Node_T<TYPE>* first = this->get_first();
+ if (first != 0) {
+ this->unlink(first);
+ return first;
+ }
+ return 0;
+}
+
+#endif /* ACE_TIMER_LIST_T_C */
diff --git a/ACE/ace/Timer_List_T.h b/ACE/ace/Timer_List_T.h
new file mode 100644
index 00000000000..d4ec800340e
--- /dev/null
+++ b/ACE/ace/Timer_List_T.h
@@ -0,0 +1,226 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Timer_List_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_LIST_T_H
+#define ACE_TIMER_LIST_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Timer_Queue_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Forward declaration.
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_List_T;
+
+/**
+ * @class ACE_Timer_List_Iterator_T
+ *
+ * @brief Iterates over an ACE_Timer_List.
+ *
+ * This is a generic iterator that can be used to visit every
+ * node of a timer queue.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_List_Iterator_T
+: public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, ACE_LOCK>
+{
+public:
+ typedef ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK> List;
+ /// Constructor.
+ ACE_Timer_List_Iterator_T (List& lst);
+
+ /// Destructor.
+ virtual ~ACE_Timer_List_Iterator_T (void);
+
+ /// Positions the iterator at the earliest node in the Timer Queue
+ virtual void first (void);
+
+ /// Positions the iterator at the next node in the Timer Queue
+ virtual void next (void);
+
+ /// Returns true when there are no more nodes in the sequence
+ virtual bool isdone (void) const;
+
+ /// Returns the node at the current position in the sequence
+ virtual ACE_Timer_Node_T<TYPE> *item (void);
+
+protected:
+ /// Pointer to the ACE_Timer_List that we are iterating over.
+ List& list_;
+
+ /// Current position in the ACE_Timer_List
+ ACE_Timer_Node_T<TYPE>* current_node_;
+};
+
+/**
+ * @class ACE_Timer_List_T
+ *
+ * @brief Provides a simple implementation of timers.
+ *
+ * This implementation uses a linked list of absolute times.
+ * Therefore, in the average case, scheduling and canceling
+ * timers is O(N) (where N is the total number of timers) and
+ * expiring timers is O(K) (where K is the total number of timers
+ * that are < the current time of day).
+ * More clever implementations could use a delta-list, a heap,
+ * or timing wheels, etc. For instance, ACE_Timer_Heap
+ * is a subclass of ACE_Timer_List that implements a
+ * heap-based callout queue. For most applications, the
+ * ACE_Timer_Heap will perform substantially faster than the
+ * ACE_Timer_List.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_List_T : public ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>
+{
+public:
+ /// Type of iterator
+ typedef ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> Iterator;
+
+ /// Iterator is a friend
+ friend class ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>;
+
+ typedef ACE_Timer_Node_T<TYPE> Node;
+ /// Type inherited from
+ typedef ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> Base;
+ typedef ACE_Free_List<Node> FreeList;
+
+ // = Initialization and termination methods.
+ /**
+ * Default constructor. @a upcall_functor is the instance of the
+ * FUNCTOR to be used by the list. If @a upcall_functor is 0, a
+ * default FUNCTOR will be created. @a freelist is the freelist of
+ * timer nodes. If 0, then a default freelist will be created.
+ */
+ ACE_Timer_List_T (FUNCTOR* upcall_functor = 0, FreeList* freelist = 0);
+
+ /// Destructor
+ virtual ~ACE_Timer_List_T (void);
+
+ /// True if queue is empty, else false.
+ virtual bool is_empty (void) const;
+
+ /// Returns the time of the earlier node in the ACE_Timer_List.
+ /// Must be called on a non-empty queue.
+ virtual const ACE_Time_Value& earliest_time (void) const;
+
+ /**
+ * Resets the interval of the timer represented by @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a 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_interval (long timer_id,
+ const ACE_Time_Value& interval);
+
+ /**
+ * Cancel all timers associated with @a type. If dont_call_handle_close is 0
+ * then the @a functor will be invoked. Returns the number of timers
+ * cancelled.
+ */
+ virtual int cancel (const TYPE& type,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel the single timer that matches the @a 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 timer was registered. This makes it possible
+ * to free up the memory and avoid memory leaks. If <dont_call> is
+ * 0 then the <functor> will be invoked. Returns 1 if cancellation
+ * succeeded and 0 if the @a timer_id wasn't found.
+ */
+ virtual int cancel (long timer_id,
+ const void** act = 0,
+ int dont_call_handle_close = 1);
+
+ /// Returns a pointer to this ACE_Timer_Queue's iterator.
+ virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>& iter (void);
+
+ /// Removes the earliest node from the queue and returns it
+ virtual ACE_Timer_Node_T<TYPE>* remove_first (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Reschedule an "interval" ACE_Timer_Node_T. This should be private
+ /// but for now it needs to be public for <ACE_Timer_Hash_T>
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
+
+ /// Reads the earliest node from the queue and returns it.
+ virtual ACE_Timer_Node_T<TYPE>* get_first (void);
+
+private:
+
+ /**
+ * Schedule @a type that will expire at @a future_time, which is
+ * specified in absolute time. If it expires then @a act is passed
+ * in as the value to the <functor>. If @a interval is != to
+ * ACE_Time_Value::zero then it is used to reschedule the @a type
+ * automatically, using relative time to the current <gettimeofday>.
+ * This method returns a <timer_id> that uniquely identifies the the
+ * @a type entry in an internal list. This <timer_id> can be used to
+ * cancel the 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_i (const TYPE& type,
+ const void* act,
+ const ACE_Time_Value& future_time,
+ const ACE_Time_Value& interval);
+
+ void schedule_i(ACE_Timer_Node_T<TYPE>* n, const ACE_Time_Value& exp);
+
+ ACE_Timer_Node_T<TYPE>* find_node(long timer_id) const;
+
+ void cancel_i (ACE_Timer_Node_T<TYPE>* n);
+
+ void unlink (ACE_Timer_Node_T<TYPE>* n);
+
+ ACE_Timer_Node_T<TYPE>* get_first_i(void) const;
+
+private:
+
+ /// Pointer to linked list of <ACE_Timer_Handles>.
+ ACE_Timer_Node_T<TYPE>* head_;
+
+ /// Iterator used to expire timers.
+ Iterator* iterator_;
+
+ /**
+ * Keeps track of the timer id that uniquely identifies each timer.
+ * This id can be used to cancel a timer via the <cancel(long)>
+ * method.
+ */
+ long id_counter_;
+
+ // = Don't allow these operations for now.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Timer_List_T (const ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK> &))
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Timer_List_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Timer_List_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_LIST_T_H */
diff --git a/ACE/ace/Timer_Queue.h b/ACE/ace/Timer_Queue.h
new file mode 100644
index 00000000000..36182f15f95
--- /dev/null
+++ b/ACE/ace/Timer_Queue.h
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timer_Queue.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_QUEUE_H
+#define ACE_TIMER_QUEUE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Synch_Traits.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Timer_Queuefwd.h"
+#include "ace/Timer_Queue_T.h"
+#if defined (ACE_HAS_THREADS)
+# include "ace/Recursive_Thread_Mutex.h"
+#else
+# include "ace/Null_Mutex.h"
+#endif /* ACE_HAS_THREADS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// The following typedef are here for ease of use and backward
+// compatibility.
+typedef ACE_Timer_Node_Dispatch_Info_T<ACE_Event_Handler *>
+ ACE_Timer_Node_Dispatch_Info;
+
+typedef ACE_Timer_Node_T<ACE_Event_Handler *>
+ ACE_Timer_Node;
+
+typedef ACE_Timer_Queue_Iterator_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Timer_Queue_Iterator;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_TIMER_QUEUE_H */
diff --git a/ACE/ace/Timer_Queue_Adapters.cpp b/ACE/ace/Timer_Queue_Adapters.cpp
new file mode 100644
index 00000000000..96010773ad2
--- /dev/null
+++ b/ACE/ace/Timer_Queue_Adapters.cpp
@@ -0,0 +1,361 @@
+// $Id$
+
+#ifndef ACE_TIMER_QUEUE_ADAPTERS_CPP
+#define ACE_TIMER_QUEUE_ADAPTERS_CPP
+
+#include "ace/Timer_Queue_Adapters.h"
+
+#if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
+#include "ace/Functor.h"
+#endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+# if !defined (__ACE_INLINE__)
+# include "ace/Timer_Queue_Adapters.inl"
+# endif /* __ACE_INLINE__ */
+
+#include "ace/Signal.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_time.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TQ> TQ &
+ACE_Async_Timer_Queue_Adapter<TQ>::timer_queue (void)
+{
+ return this->timer_queue_;
+}
+
+template <class TQ> int
+ACE_Async_Timer_Queue_Adapter<TQ>::cancel (long timer_id,
+ const void **act)
+{
+ // Block designated signals.
+ ACE_Sig_Guard sg (&this->mask_);
+ ACE_UNUSED_ARG (sg);
+
+ return this->timer_queue_.cancel (timer_id, act);
+}
+
+template <class TQ> int
+ACE_Async_Timer_Queue_Adapter<TQ>::expire (void)
+{
+ // Block designated signals.
+ ACE_Sig_Guard sg (&this->mask_);
+ ACE_UNUSED_ARG (sg);
+
+ return this->timer_queue_.expire ();
+}
+
+template <class TQ> int
+ACE_Async_Timer_Queue_Adapter<TQ>::schedule_ualarm (void)
+{
+ ACE_Time_Value tv = this->timer_queue_.earliest_time ()
+ - this->timer_queue_.gettimeofday ();
+
+ // Beware of negative times and zero times (which cause problems for
+ // <ualarm>).
+ if (tv < ACE_Time_Value::zero)
+ tv = ACE_Time_Value (0, 1);
+
+ // @@ This code should be clever enough to avoid updating the
+ // <ualarm> if we haven't actually changed the earliest time.
+ // Schedule a new timer.
+ ACE_OS::ualarm (tv);
+ return 0;
+}
+
+template <class TQ> long
+ACE_Async_Timer_Queue_Adapter<TQ>::schedule (ACE_Event_Handler *eh,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_UNUSED_ARG (act);
+ ACE_UNUSED_ARG (interval);
+
+ // Block designated signals.
+ ACE_Sig_Guard sg (&this->mask_);
+ ACE_UNUSED_ARG (sg);
+
+ // @@ We still need to implement interval timers...
+ long tid = this->timer_queue_.schedule (eh, act, future_time);
+
+ if (tid == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("schedule_timer")),
+ -1);
+
+ if (this->schedule_ualarm () == -1)
+ return 0;
+
+ return tid;
+}
+
+template <class TQ>
+ACE_Async_Timer_Queue_Adapter<TQ>::ACE_Async_Timer_Queue_Adapter (ACE_Sig_Set *mask)
+ // If <mask> == 0, block *all* signals when the SIGARLM handler is
+ // running, else just block those in the mask.
+ : mask_ (mask)
+{
+ // The following code is necessary to selectively "block" certain
+ // signals when SIGALRM is running. Also, we always restart system
+ // calls that are interrupted by the signals.
+
+ ACE_Sig_Action sa ((ACE_SignalHandler) 0,
+ this->mask_,
+ SA_RESTART);
+
+ if (this->sig_handler_.register_handler (SIGALRM, this, &sa) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")));
+}
+
+// This is the signal handler function for the asynchronous timer
+// list. It gets invoked asynchronously when the SIGALRM signal
+// occurs.
+
+template <class TQ> int
+ACE_Async_Timer_Queue_Adapter<TQ>::handle_signal (int signum,
+ siginfo_t *,
+ ucontext_t *)
+{
+ switch (signum)
+ {
+ case SIGALRM:
+ {
+ // Expire the pending timers.
+
+ // @@ We need to figure out how to implement interval
+ // timers...
+ this->timer_queue_.expire ();
+
+ // Only schedule a new timer if there is one in the list.
+
+ // @@ This code should also become smarter to avoid
+ // unnecessary calls to ualarm().
+ if (this->timer_queue_.is_empty () == 0)
+ return this->schedule_ualarm ();
+ else
+ return 0;
+ /* NOTREACHED */
+ }
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "unexpected signal %S\n",
+ signum),
+ -1);
+ /* NOTREACHED */
+ }
+}
+
+template<class TQ>
+ACE_Thread_Timer_Queue_Adapter<TQ>::ACE_Thread_Timer_Queue_Adapter (ACE_Thread_Manager *tm,
+ TQ* timer_queue)
+ : ACE_Task_Base (tm),
+ timer_queue_(timer_queue),
+ delete_timer_queue_(false),
+ condition_ (mutex_),
+ active_ (true), // Assume that we start in active mode.
+ thr_id_ (ACE_OS::NULL_thread)
+{
+ if (timer_queue_ == 0)
+ {
+ ACE_NEW (this->timer_queue_,
+ TQ);
+ this->delete_timer_queue_ = true;
+ }
+}
+
+template<class TQ>
+ACE_Thread_Timer_Queue_Adapter<TQ>::~ACE_Thread_Timer_Queue_Adapter (void)
+{
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->timer_queue_ = 0;
+ this->delete_timer_queue_ = false;
+ }
+}
+
+template<class TQ> ACE_SYNCH_RECURSIVE_MUTEX &
+ACE_Thread_Timer_Queue_Adapter<TQ>::mutex (void)
+{
+ return this->mutex_;
+}
+
+template<class TQ> long
+ACE_Thread_Timer_Queue_Adapter<TQ>::schedule
+ (ACE_Event_Handler* handler,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
+
+ long result = this->timer_queue_->schedule (handler, act, future_time, interval);
+ this->condition_.signal ();
+ return result;
+}
+
+template<class TQ> int
+ACE_Thread_Timer_Queue_Adapter<TQ>::cancel (long timer_id,
+ const void **act)
+{
+ ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
+
+ int result = this->timer_queue_->cancel (timer_id, act);
+ condition_.signal ();
+ return result;
+}
+
+template<class TQ> void
+ACE_Thread_Timer_Queue_Adapter<TQ>::deactivate (void)
+{
+ ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_);
+
+ this->active_ = false;
+ this->condition_.signal ();
+}
+
+template<class TQ> int
+ACE_Thread_Timer_Queue_Adapter<TQ>::svc (void)
+{
+ ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
+
+ this->thr_id_ = ACE_Thread::self ();
+
+ // Thread cancellation point, if ACE supports it.
+ //
+ // Note: This call generates a warning under Solaris because the header
+ // file /usr/include/pthread.h redefines the routine argument. This
+ // is a bug in the Solaris header files and has nothing to do with
+ // ACE.
+# if !defined (ACE_LACKS_PTHREAD_CANCEL)
+ ACE_PTHREAD_CLEANUP_PUSH (&this->condition_.mutex ().get_nesting_mutex ());
+# endif /* ACE_LACKS_PTHREAD_CANCEL */
+
+ while (this->active_)
+ {
+# if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
+ // Temporarily suspend ownership of the timer queue mutex in
+ // order to dispatch deferred execution commands. These
+ // commands are to be treated as executing in a context
+ // "external" to the timer queue adapter, and thus must compete
+ // separately for this lock.
+ mutex_.release ();
+ this->dispatch_commands ();
+
+ // Re-acquire ownership of the timer queue mutex in order to
+ // restore the "internal" timer queue adapter context
+ mutex_.acquire ();
+# endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
+
+ // If the queue is empty, sleep until there is a change on it.
+ if (this->timer_queue_->is_empty ())
+ this->condition_.wait ();
+ else
+ {
+ // Compute the remaining time, being careful not to sleep
+ // for "negative" amounts of time.
+ ACE_Time_Value const tv_curr = this->timer_queue_->gettimeofday ();
+ ACE_Time_Value const tv_earl = this->timer_queue_->earliest_time ();
+
+ if (tv_earl > tv_curr)
+ {
+ // The earliest time on the Timer_Queue is in future, so
+ // use ACE_OS::gettimeofday() to convert the tv to the
+ // absolute time.
+ ACE_Time_Value const tv = ACE_OS::gettimeofday () + (tv_earl - tv_curr);
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("waiting until %u.%3.3u secs\n"),
+ // tv.sec(), tv.msec()));
+ this->condition_.wait (&tv);
+ }
+ }
+
+ // Expire timers anyway, at worst this is a no-op.
+ this->timer_queue_->expire ();
+ }
+
+ // Thread cancellation point, if ACE supports it.
+# if !defined (ACE_LACKS_PTHREAD_CANCEL)
+ ACE_PTHREAD_CLEANUP_POP (0);
+# endif /* ACE_LACKS_PTHREAD_CANCEL */
+
+ return 0;
+}
+
+template<class TQ> int
+ACE_Thread_Timer_Queue_Adapter<TQ>::activate (long flags,
+ int ,
+ int ,
+ long priority,
+ int grp_id,
+ ACE_Task_Base *task,
+ ACE_hthread_t [],
+ void *stack[],
+ size_t stack_size[],
+ ACE_thread_t thread_ids[],
+ const char* thr_name[])
+{
+ // Make sure to set this flag in case we were deactivated earlier.
+ this->active_ = true;
+
+ // Make sure that we only allow a single thread to be spawned for
+ // our adapter. Otherwise, too many weird things can happen.
+ return ACE_Task_Base::activate (flags, 1, 0, priority, grp_id, task, 0,
+ stack, stack_size, thread_ids, thr_name);
+}
+
+# if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
+
+// Enqueues a command object for execution just before waiting on the next
+// timer event. This allows deferred execution of commands that cannot
+// be performed in the timer event handler context, such as registering
+// or cancelling timers on platforms where the timer queue mutex is not
+// recursive.
+
+template<class TQ> int
+ACE_Thread_Timer_Queue_Adapter<TQ>::enqueue_command (ACE_Command_Base *cmd,
+ COMMAND_ENQUEUE_POSITION pos)
+{
+ // Serialize access to the command queue.
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->command_mutex_, -1);
+
+ if (pos == ACE_Thread_Timer_Queue_Adapter<TQ>::TAIL)
+ return command_queue_.enqueue_tail (cmd);
+ else
+ return command_queue_.enqueue_head (cmd);
+}
+
+// Dispatches all command objects enqueued in the most recent event
+// handler context.
+
+template<class TQ> int
+ACE_Thread_Timer_Queue_Adapter<TQ>::dispatch_commands (void)
+{
+ // Serialize access to the command queue.
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->command_mutex_, -1);
+
+ // loop through the enqueued commands
+ ACE_Command_Base *cmd = 0;
+ while (command_queue_.dequeue_head (cmd) == 0)
+ if (cmd)
+ {
+ cmd->execute ();
+ delete cmd;
+ }
+
+ return 0;
+}
+
+# endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TIMER_QUEUE_ADAPTERS_CPP */
diff --git a/ACE/ace/Timer_Queue_Adapters.h b/ACE/ace/Timer_Queue_Adapters.h
new file mode 100644
index 00000000000..08ea47075f3
--- /dev/null
+++ b/ACE/ace/Timer_Queue_Adapters.h
@@ -0,0 +1,261 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timer_Queue_Adapters.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+ * Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_QUEUE_ADAPTERS_H
+#define ACE_TIMER_QUEUE_ADAPTERS_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Task.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+#include "ace/Condition_Recursive_Thread_Mutex.h"
+
+#if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
+# include "ace/Unbounded_Queue.h"
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_Command_Base;
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Sig_Set;
+
+/**
+ * @class ACE_Async_Timer_Queue_Adapter
+ *
+ * @brief Adapts an ACE timer queue to be driven asynchronously using signals.
+ *
+ * This implementation uses the ACE_OS::ualarm call, to generate
+ * the SIGARLM signal that is caught by this class.
+ *
+ * @note This adapter only works on platforms that support ualarm().
+ * POSIX platforms generally do; Windows and some others do not.
+ *
+ * @todo This adapter does not automatically reschedule repeating timers.
+ */
+template <class TQ>
+class ACE_Async_Timer_Queue_Adapter : public ACE_Event_Handler
+{
+public:
+ typedef TQ TIMER_QUEUE;
+
+ /// Constructor
+ /**
+ * Register the SIGALRM handler. If @a mask == 0 then block all
+ * signals when @c SIGALRM is run. Otherwise, just block the signals
+ * indicated in @a mask.
+ */
+ ACE_Async_Timer_Queue_Adapter (ACE_Sig_Set *mask = 0);
+
+ /// Schedule the timer according to the semantics of the
+ /// ACE_Timer_List.
+ /**
+ * This timer gets dispatched via a signal, rather than by a user
+ * calling expire(). Note that interval timers are not implemented
+ * yet.
+ */
+ long schedule (ACE_Event_Handler *type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+
+ /// Cancel the @a timer_id and pass back the @a act if an address is
+ /// passed in.
+ int cancel (long timer_id, const void **act = 0);
+
+ /// Dispatch all timers with expiry time at or before the current time.
+ /// Returns the number of timers expired.
+ int expire (void);
+
+ /// Return a reference to the underlying timer queue.
+ TQ &timer_queue (void);
+
+private:
+ /// Perform the logic to compute the new ualarm(2) setting.
+ virtual int schedule_ualarm (void);
+
+ /// Called back by @c SIGALRM handler.
+ virtual int handle_signal (int signum, siginfo_t *, ucontext_t *);
+
+ /// Handler for the @c SIGALRM signal, so that we can access our state
+ /// without requiring any global variables.
+ ACE_Sig_Handler sig_handler_;
+
+ /// Implementation of the timer queue (e.g., ACE_Timer_List,
+ /// ACE_Timer_Heap, etc.).
+ TQ timer_queue_;
+
+ /// Mask of signals to be blocked when we're servicing @c SIGALRM.
+ ACE_Sig_Set mask_;
+};
+
+/**
+ * @class ACE_Thread_Timer_Queue_Adapter
+ *
+ * @brief Adapts an ACE timer queue using a separate thread for dispatching.
+ *
+ * This implementation uses a separate thread to dispatch the timers.
+ * The base queue need not be thread safe; this class takes all the
+ * necessary locks.
+ *
+ * @note This is a case where template parameters will be useful, but
+ * (IMHO) the effort and portability problems discourage their
+ * use.
+ *
+ */
+template <class TQ>
+class ACE_Thread_Timer_Queue_Adapter : public ACE_Task_Base
+{
+public:
+ /// Trait for the underlying queue type.
+ typedef TQ TIMER_QUEUE;
+
+# if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
+
+ /// Typedef for the position at which to enqueue a deferred
+ /// execution command.
+ enum COMMAND_ENQUEUE_POSITION {HEAD, TAIL};
+
+# endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
+
+ /// Creates the timer queue. Activation of the task is the user's
+ /// responsibility. Optionally a pointer to a timer queue can be passed,
+ /// when no pointer is passed, a TQ is dynamically created
+ ACE_Thread_Timer_Queue_Adapter (ACE_Thread_Manager * = ACE_Thread_Manager::instance (),
+ TQ* timer_queue = 0);
+
+ /// Destructor.
+ virtual ~ACE_Thread_Timer_Queue_Adapter (void);
+
+ /// Schedule the timer according to the semantics of the <TQ>; wakes
+ /// up the dispatching thread.
+ long schedule (ACE_Event_Handler *handler,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+
+ /// Cancel the @a timer_id and return the @a act parameter if an
+ /// address is passed in. Also wakes up the dispatching thread.
+ int cancel (long timer_id, const void **act = 0);
+
+ /// Runs the dispatching thread.
+ virtual int svc (void);
+
+ /// Inform the dispatching thread that it should terminate.
+ virtual void deactivate (void);
+
+ /// Access the locking mechanism, useful for iteration.
+ ACE_SYNCH_RECURSIVE_MUTEX &mutex (void);
+
+ /// Set a user-specified timer queue.
+ int timer_queue (TQ *tq);
+
+ /// Return the current <TQ>.
+ TQ *timer_queue (void) const;
+
+ /// Return the thread id of our active object.
+ ACE_thread_t thr_id (void) const;
+
+ /**
+ * We override the default activate() method so that we can ensure
+ * that only a single thread is ever spawned. Otherwise, too many
+ * weird things can happen...
+ */
+ virtual int activate (long flags = THR_NEW_LWP | THR_JOINABLE,
+ int n_threads = 1,
+ int force_active = 0,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ int grp_id = -1,
+ ACE_Task_Base *task = 0,
+ ACE_hthread_t thread_handles[] = 0,
+ void *stack[] = 0,
+ size_t stack_size[] = 0,
+ ACE_thread_t thread_ids[] = 0,
+ const char* thr_name[] = 0);
+
+# if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
+
+ /**
+ * Enqueues a command object for execution just before waiting on the next
+ * timer event. This allows deferred execution of commands that cannot
+ * be performed in the timer event handler context, such as registering
+ * or cancelling timers on platforms where the timer queue mutex is not
+ * recursive.
+ */
+ int enqueue_command (ACE_Command_Base *command_,
+ COMMAND_ENQUEUE_POSITION pos = TAIL);
+
+# endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
+
+private:
+
+# if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
+ /// Dispatches all command objects enqueued in the most
+ /// recent event handler context.
+ int dispatch_commands (void);
+
+ /// Queue of commands for deferred execution.
+ ACE_Unbounded_Queue<ACE_Command_Base *> command_queue_;
+
+ /// The mutual exclusion mechanism for the command queue.
+ ACE_SYNCH_MUTEX command_mutex_;
+# endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
+
+ /// The underlying Timer_Queue.
+ TQ* timer_queue_;
+
+ /// Keeps track of whether we should delete the timer queue (if we
+ /// didn't create it, then we don't delete it).
+ bool delete_timer_queue_;
+
+ /// The mutual exclusion mechanism that is required to use the
+ /// <condition_>.
+ ACE_SYNCH_RECURSIVE_MUTEX mutex_;
+
+ /**
+ * The dispatching thread sleeps on this condition while waiting to
+ * dispatch the next timer; it is used to wake it up if there is a
+ * change on the timer queue.
+ */
+ ACE_SYNCH_RECURSIVE_CONDITION condition_;
+
+ /// When deactivate is called this variable turns to false and the
+ /// dispatching thread is signalled, to terminate its main loop.
+ bool active_;
+
+ /// Thread id of our active object task.
+ ACE_thread_t thr_id_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "ace/Timer_Queue_Adapters.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+# include "ace/Timer_Queue_Adapters.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+# pragma implementation ("Timer_Queue_Adapters.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_QUEUE_ADAPTERS_H */
diff --git a/ACE/ace/Timer_Queue_Adapters.inl b/ACE/ace/Timer_Queue_Adapters.inl
new file mode 100644
index 00000000000..3252b186e07
--- /dev/null
+++ b/ACE/ace/Timer_Queue_Adapters.inl
@@ -0,0 +1,29 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class TQ> ACE_INLINE TQ *
+ACE_Thread_Timer_Queue_Adapter<TQ>::timer_queue (void) const
+{
+ return this->timer_queue_;
+}
+
+template<class TQ> ACE_INLINE int
+ACE_Thread_Timer_Queue_Adapter<TQ>::timer_queue (TQ *tq)
+{
+ if (this->delete_timer_queue_)
+ delete this->timer_queue_;
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = false;
+ return 0;
+}
+
+template<class TQ> ACE_INLINE ACE_thread_t
+ACE_Thread_Timer_Queue_Adapter<TQ>::thr_id (void) const
+{
+ return this->thr_id_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Timer_Queue_T.cpp b/ACE/ace/Timer_Queue_T.cpp
new file mode 100644
index 00000000000..4643090ecd5
--- /dev/null
+++ b/ACE/ace/Timer_Queue_T.cpp
@@ -0,0 +1,481 @@
+// $Id$
+
+#ifndef ACE_TIMER_QUEUE_T_CPP
+#define ACE_TIMER_QUEUE_T_CPP
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/*
+ * Hook to specialize to add includes
+ */
+//@@ REACTOR_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK
+
+#include "ace/Timer_Queue_T.h"
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor_Timer_Interface.h"
+#include "ace/Null_Mutex.h"
+#include "ace/OS_NS_sys_time.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Timer_Queue_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This fudge factor can be overriden for timers that need it, such as on
+// Solaris, by defining the ACE_TIMER_SKEW symbol in the appropriate config
+// header.
+#if !defined (ACE_TIMER_SKEW)
+# define ACE_TIMER_SKEW 0
+#endif /* ACE_TIMER_SKEW */
+
+template <class TYPE> void
+ACE_Timer_Node_T<TYPE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Timer_Node_T::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nact_ = %x"), this->act_));
+ this->timer_value_.dump ();
+ this->interval_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nprev_ = %x"), this->prev_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnext_ = %x"), this->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntimer_id_ = %d\n"), this->timer_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class TYPE>
+ACE_Timer_Node_T<TYPE>::ACE_Timer_Node_T (void)
+{
+ ACE_TRACE ("ACE_Timer_Node_T::ACE_Timer_Node_T");
+}
+
+template <class TYPE>
+ACE_Timer_Node_T<TYPE>::~ACE_Timer_Node_T (void)
+{
+ ACE_TRACE ("ACE_Timer_Node_T::~ACE_Timer_Node_T");
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Queue_Iterator_T (void)
+{
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Queue_Iterator_T (void)
+{
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Time_Value *
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_timeout (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, max_wait_time));
+
+ if (this->is_empty ())
+ // Nothing on the Timer_Queue, so use whatever the caller gave us.
+ return max_wait_time;
+ else
+ {
+ ACE_Time_Value const cur_time = this->gettimeofday ();
+
+ if (this->earliest_time () > cur_time)
+ {
+ // The earliest item on the Timer_Queue is still in the
+ // future. Therefore, use the smaller of (1) caller's wait
+ // time or (2) the delta time between now and the earliest
+ // time on the Timer_Queue.
+
+ this->timeout_ = this->earliest_time () - cur_time;
+ if (max_wait_time == 0 || *max_wait_time > timeout_)
+ return &this->timeout_;
+ else
+ return max_wait_time;
+ }
+ else
+ {
+ // The earliest item on the Timer_Queue is now in the past.
+ // Therefore, we've got to "poll" the Reactor, i.e., it must
+ // just check the descriptors and then dispatch timers, etc.
+ this->timeout_ = ACE_Time_Value::zero;
+ return &this->timeout_;
+ }
+ }
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Time_Value *
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_timeout (ACE_Time_Value *max_wait_time,
+ ACE_Time_Value *the_timeout)
+{
+ ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout");
+
+ if (the_timeout == 0)
+ return 0;
+
+ if (this->is_empty ())
+ {
+ // Nothing on the Timer_Queue, so use whatever the caller gave us.
+ if (max_wait_time)
+ *the_timeout = *max_wait_time;
+ else
+ return 0;
+ }
+ else
+ {
+ ACE_Time_Value cur_time = this->gettimeofday ();
+
+ if (this->earliest_time () > cur_time)
+ {
+ // The earliest item on the Timer_Queue is still in the
+ // future. Therefore, use the smaller of (1) caller's wait
+ // time or (2) the delta time between now and the earliest
+ // time on the Timer_Queue.
+
+ *the_timeout = this->earliest_time () - cur_time;
+ if (!(max_wait_time == 0 || *max_wait_time > *the_timeout))
+ *the_timeout = *max_wait_time;
+ }
+ else
+ {
+ // The earliest item on the Timer_Queue is now in the past.
+ // Therefore, we've got to "poll" the Reactor, i.e., it must
+ // just check the descriptors and then dispatch timers, etc.
+ *the_timeout = ACE_Time_Value::zero;
+ }
+ }
+ return the_timeout;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Timer_Queue_T::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->timeout_.dump ();
+ this->timer_skew_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Queue_T (FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : gettimeofday_ (ACE_OS::gettimeofday),
+ delete_upcall_functor_ (upcall_functor == 0),
+ delete_free_list_ (freelist == 0),
+ timer_skew_ (0, ACE_TIMER_SKEW)
+{
+ ACE_TRACE ("ACE_Timer_Queue_T::ACE_Timer_Queue_T");
+
+ if (!freelist)
+ ACE_NEW (free_list_,
+ (ACE_Locked_Free_List<ACE_Timer_Node_T<TYPE>,ACE_Null_Mutex>));
+ else
+ free_list_ = freelist;
+
+ if (!upcall_functor)
+ ACE_NEW (upcall_functor_,
+ FUNCTOR);
+ else
+ upcall_functor_ = upcall_functor;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Queue_T (void)
+{
+ ACE_TRACE ("ACE_Timer_Queue_T::~ACE_Timer_Queue_T");
+
+ // Cleanup the functor and free_list on the way out
+ if (this->delete_upcall_functor_)
+ delete this->upcall_functor_;
+
+ if (this->delete_free_list_)
+ delete this->free_list_;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::alloc_node (void)
+{
+ return this->free_list_->remove ();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::free_node (ACE_Timer_Node_T<TYPE> *node)
+{
+ this->free_list_->add (node);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_LOCK &
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::mutex (void)
+{
+ return this->mutex_;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> long
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::schedule (const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ // Schedule the timer.
+ long const result =
+ this->schedule_i (type,
+ act,
+ future_time,
+ interval);
+
+ // Return on failure.
+ if (result == -1)
+ return result;
+
+ // Inform upcall functor of successful registration.
+ this->upcall_functor ().registration (*this,
+ type,
+ act);
+
+ // Return result;
+ return result;
+}
+
+// Run the <handle_timeout> method for all Timers whose values are <=
+// <cur_time>.
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value &cur_time)
+{
+ ACE_TRACE ("ACE_Timer_Queue_T::expire");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ // Keep looping while there are timers remaining and the earliest
+ // timer is <= the <cur_time> passed in to the method.
+
+ if (this->is_empty ())
+ return 0;
+
+ int number_of_timers_expired = 0;
+ int result = 0;
+
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
+
+ while ((result = this->dispatch_info_i (cur_time, info)) != 0)
+ {
+ const void *upcall_act = 0;
+
+ this->preinvoke (info, cur_time, upcall_act);
+
+ this->upcall (info, cur_time);
+
+ this->postinvoke (info, cur_time, upcall_act);
+
+ ++number_of_timers_expired;
+
+ }
+
+ ACE_UNUSED_ARG (result);
+ return number_of_timers_expired;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info_i (const ACE_Time_Value &cur_time,
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> &info)
+{
+ ACE_TRACE ("ACE_Timer_Queue_T::dispatch_info_i");
+
+ if (this->is_empty ())
+ return 0;
+
+ ACE_Timer_Node_T<TYPE> *expired = 0;
+
+ if (this->earliest_time () <= cur_time)
+ {
+ expired = this->remove_first ();
+
+ // Get the dispatch info
+ expired->get_dispatch_info (info);
+
+ // Check if this is an interval timer.
+ if (expired->get_interval () > ACE_Time_Value::zero)
+ {
+ // Make sure that we skip past values that have already
+ // "expired".
+ do
+ expired->set_timer_value (expired->get_timer_value () +
+ expired->get_interval ());
+ while (expired->get_timer_value () <= cur_time);
+
+ // Since this is an interval timer, we need to reschedule
+ // it.
+ this->reschedule (expired);
+ }
+ else
+ {
+ // Call the factory method to free up the node.
+ this->free_node (expired);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::return_node (ACE_Timer_Node_T<TYPE> *node)
+{
+ ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
+ this->free_node (node);
+}
+
+
+template <class ACE_LOCK>
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::ACE_Event_Handler_Handle_Timeout_Upcall (void)
+{
+}
+
+template <class ACE_LOCK>
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::~ACE_Event_Handler_Handle_Timeout_Upcall (void)
+{
+}
+
+template <class ACE_LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::registration (TIMER_QUEUE &,
+ ACE_Event_Handler *event_handler,
+ const void *)
+{
+ event_handler->add_reference ();
+ return 0;
+}
+
+template <class ACE_LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::preinvoke (TIMER_QUEUE & /* timer_queue */,
+ ACE_Event_Handler *event_handler,
+ const void * /* timer_act */,
+ int /* recurring_timer */,
+ const ACE_Time_Value & /* cur_time */,
+ const void *&upcall_act)
+{
+ bool const requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ if (requires_reference_counting)
+ {
+ event_handler->add_reference ();
+
+ upcall_act = &this->requires_reference_counting_;
+ }
+
+ return 0;
+}
+
+template <class ACE_LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::postinvoke (TIMER_QUEUE & /* timer_queue */,
+ ACE_Event_Handler *event_handler,
+ const void * /* timer_act */,
+ int /* recurring_timer */,
+ const ACE_Time_Value & /* cur_time */,
+ const void *upcall_act)
+{
+ if (upcall_act == &this->requires_reference_counting_)
+ {
+ event_handler->remove_reference ();
+ }
+
+ return 0;
+}
+
+template <class ACE_LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::timeout (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *event_handler,
+ const void *act,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time)
+{
+ int requires_reference_counting = 0;
+
+ if (!recurring_timer)
+ {
+ requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+ }
+
+ // Upcall to the <handler>s handle_timeout method.
+ if (event_handler->handle_timeout (cur_time, act) == -1)
+ {
+ if (event_handler->reactor_timer_interface ())
+ event_handler->reactor_timer_interface ()->cancel_timer (event_handler, 0);
+ else
+ timer_queue.cancel (event_handler, 0); // 0 means "call handle_close()".
+ }
+
+ if (!recurring_timer &&
+ requires_reference_counting)
+ {
+ event_handler->remove_reference ();
+ }
+
+ return 0;
+}
+
+template <class ACE_LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::cancel_type (TIMER_QUEUE &,
+ ACE_Event_Handler *event_handler,
+ int dont_call,
+ int &requires_reference_counting)
+{
+ requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ // Upcall to the <handler>s handle_close method
+ if (dont_call == 0)
+ event_handler->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::TIMER_MASK);
+
+ return 0;
+}
+
+template <class ACE_LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::cancel_timer (TIMER_QUEUE &,
+ ACE_Event_Handler *event_handler,
+ int,
+ int requires_reference_counting)
+{
+ if (requires_reference_counting)
+ event_handler->remove_reference ();
+
+ return 0;
+}
+
+template <class ACE_LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::deletion (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *event_handler,
+ const void *)
+{
+ int requires_reference_counting = 0;
+
+ this->cancel_type (timer_queue,
+ event_handler,
+ 0,
+ requires_reference_counting);
+
+ this->cancel_timer (timer_queue,
+ event_handler,
+ 0,
+ requires_reference_counting);
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TIMER_QUEUE_T_CPP */
diff --git a/ACE/ace/Timer_Queue_T.h b/ACE/ace/Timer_Queue_T.h
new file mode 100644
index 00000000000..8aef637579e
--- /dev/null
+++ b/ACE/ace/Timer_Queue_T.h
@@ -0,0 +1,562 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timer_Queue_T.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Irfan Pyarali <irfan@cs.wustl.edu> and
+ * @author Darrell Brunsch <brunsch@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_QUEUE_T_H
+#define ACE_TIMER_QUEUE_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Free_List.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event_Handler.h"
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Timer_Node_Dispatch_Info_T
+ *
+ * @brief Maintains generated dispatch information for Timer nodes.
+ *
+ */
+template <class TYPE>
+class ACE_Timer_Node_Dispatch_Info_T
+{
+public:
+ /// The type of object held in the queue
+ TYPE type_;
+
+ /// Asynchronous completion token associated with the timer.
+ const void *act_;
+
+ /// Flag to check if the timer is recurring.
+ int recurring_timer_;
+};
+
+/**
+ * @class ACE_Timer_Node_T
+ *
+ * @brief Maintains the state associated with a Timer entry.
+ */
+template <class TYPE>
+class ACE_Timer_Node_T
+{
+public:
+ /// Default constructor
+ ACE_Timer_Node_T (void);
+
+ /// Destructor
+ ~ACE_Timer_Node_T (void);
+
+ /// Useful typedef ..
+ typedef ACE_Timer_Node_Dispatch_Info_T <TYPE> DISPATCH_INFO;
+
+ /// Singly linked list
+ void set (const TYPE &type,
+ const void *a,
+ const ACE_Time_Value &t,
+ const ACE_Time_Value &i,
+ ACE_Timer_Node_T<TYPE> *n,
+ long timer_id);
+
+ /// Doubly linked list version
+ void set (const TYPE &type,
+ const void *a,
+ const ACE_Time_Value &t,
+ const ACE_Time_Value &i,
+ ACE_Timer_Node_T<TYPE> *p,
+ ACE_Timer_Node_T<TYPE> *n,
+ long timer_id);
+
+ // = Accessors
+
+ /// Get the type.
+ TYPE &get_type (void);
+
+ /// Set the type.
+ void set_type (TYPE &type);
+
+ /// Get the asynchronous completion token.
+ const void *get_act (void);
+
+ /// Set the asynchronous completion token.
+ void set_act (void *act);
+
+ /// Get the timer value.
+ const ACE_Time_Value &get_timer_value (void) const;
+
+ /// Set the timer value.
+ void set_timer_value (const ACE_Time_Value &timer_value);
+
+ /// Get the timer interval.
+ const ACE_Time_Value &get_interval (void) const;
+
+ /// Set the timer interval.
+ void set_interval (const ACE_Time_Value &interval);
+
+ /// Get the previous pointer.
+ ACE_Timer_Node_T<TYPE> *get_prev (void);
+
+ /// Set the previous pointer.
+ void set_prev (ACE_Timer_Node_T<TYPE> *prev);
+
+ /// Get the next pointer.
+ ACE_Timer_Node_T<TYPE> *get_next (void);
+
+ /// Set the next pointer.
+ void set_next (ACE_Timer_Node_T<TYPE> *next);
+
+ /// Get the timer_id.
+ long get_timer_id (void) const;
+
+ /// Set the timer_id.
+ void set_timer_id (long timer_id);
+
+ /// Get the dispatch info. The dispatch information is got
+ /// through <info>. This form helps us in preventing allocation and
+ /// deleting data along the criticl path.
+ /// @@TODO: We may want to have a copying version too, so that our
+ /// interface will be complete..
+ void get_dispatch_info (ACE_Timer_Node_Dispatch_Info_T <TYPE> &info);
+
+ /// Dump the state of an TYPE.
+ void dump (void) const;
+
+private:
+ /// Type of object stored in the Queue
+ TYPE type_;
+
+ /// Asynchronous completion token associated with the timer.
+ const void *act_;
+
+ /// Time until the timer expires.
+ ACE_Time_Value timer_value_;
+
+ /// If this is a periodic timer this holds the time until the next
+ /// timeout.
+ ACE_Time_Value interval_;
+
+ /// Pointer to previous timer.
+ ACE_Timer_Node_T<TYPE> *prev_;
+
+ /// Pointer to next timer.
+ ACE_Timer_Node_T<TYPE> *next_;
+
+ /// Id of this timer (used to cancel timers before they expire).
+ long timer_id_;
+};
+
+/**
+ * @class ACE_Timer_Queue_Iterator_T
+ *
+ * @brief Generic interface for iterating over a subclass of
+ * ACE_Timer_Queue.
+ *
+ * This is a generic iterator that can be used to visit every
+ * node of a timer queue. Be aware that it isn't guaranteed
+ * that the transversal will be in order of timeout values.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Queue_Iterator_T
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Timer_Queue_Iterator_T (void);
+
+ /// Destructor.
+ virtual ~ACE_Timer_Queue_Iterator_T (void);
+
+ /// Positions the iterator at the earliest node in the Timer Queue
+ virtual void first (void) = 0;
+
+ /// Positions the iterator at the next node in the Timer Queue
+ virtual void next (void) = 0;
+
+ /// Returns true when there are no more nodes in the sequence
+ virtual bool isdone (void) const = 0;
+
+ /// Returns the node at the current position in the sequence
+ virtual ACE_Timer_Node_T<TYPE> *item (void) = 0;
+};
+
+/**
+ * @class ACE_Timer_Queue_T
+ *
+ * @brief Provides an interface to timers.
+ *
+ * This is an abstract base class that provides hook for
+ * implementing specialized policies such as ACE_Timer_List
+ * and ACE_Timer_Heap.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Queue_T
+{
+public:
+ /// Type of Iterator.
+ typedef ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> ITERATOR;
+
+ // = Initialization and termination methods.
+ /**
+ * Default constructor. @a upcall_functor is the instance of the
+ * FUNCTOR to be used by the queue. If @a upcall_functor is 0, Timer
+ * Queue will create a default FUNCTOR. @a freelist the freelist of
+ * timer nodes. If 0, then a default freelist will be created.
+ */
+ ACE_Timer_Queue_T (FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+
+ /// Destructor - make virtual for proper destruction of inherited
+ /// classes.
+ virtual ~ACE_Timer_Queue_T (void);
+
+ /// True if queue is empty, else false.
+ virtual bool is_empty (void) const = 0;
+
+ /// Returns the time of the earlier node in the Timer_Queue. Must
+ /// be called on a non-empty queue.
+ virtual const ACE_Time_Value &earliest_time (void) const = 0;
+
+ /**
+ * Schedule @a type that will expire at @a future_time, which is
+ * specified in absolute time. If it expires then @a act is passed
+ * in as the value to the <functor>. If @a interval is != to
+ * ACE_Time_Value::zero then it is used to reschedule the @a type
+ * automatically, using relative time to the current <gettimeofday>.
+ * This method returns a <timer_id> that uniquely identifies the the
+ * @a type entry in an internal list. This <timer_id> can be used to
+ * cancel the 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 (const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+
+ /**
+ * Resets the interval of the timer represented by @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a 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_interval (long timer_id,
+ const ACE_Time_Value &interval) = 0;
+
+ /**
+ * Cancel all timer associated with @a type. If
+ * @a dont_call_handle_close is 0 then the <functor> will be invoked,
+ * which typically invokes the <handle_close> hook. Returns number
+ * of timers cancelled.
+ */
+ virtual int cancel (const TYPE &type,
+ int dont_call_handle_close = 1) = 0;
+
+ /**
+ * Cancel the single timer that matches the @a 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 timer was registered. This makes it possible
+ * to free up the memory and avoid memory leaks. If
+ * @a dont_call_handle_close is 0 then the <functor> will be invoked,
+ * which typically calls the <handle_close> hook. Returns 1 if
+ * cancellation succeeded and 0 if the @a timer_id wasn't found.
+ */
+ virtual int cancel (long timer_id,
+ const void **act = 0,
+ int dont_call_handle_close = 1) = 0;
+
+ /**
+ * Run the <functor> for all timers whose values are <= @a current_time.
+ * This does not account for <timer_skew>. Returns the number of
+ * timers canceled.
+ */
+ virtual int expire (const ACE_Time_Value &current_time);
+
+ /**
+ * Get the dispatch information for a timer whose value is <= @a current_time.
+ * This does not account for <timer_skew>. Returns 1 if
+ * there is a node whose value <= @a current_time else returns a 0.
+ *
+ */
+ virtual int dispatch_info (const ACE_Time_Value &current_time,
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> &info);
+
+ /**
+ * Run the <functor> for all timers whose values are <=
+ * <ACE_OS::gettimeofday>. Also accounts for <timer_skew>.
+ *
+ * Depending on the resolution of the underlying OS the system calls
+ * like select()/poll() might return at time different than that is
+ * specified in the timeout. Suppose the OS guarantees a resolution of t ms.
+ * The timeline will look like
+ *
+ * A B
+ * | |
+ * V V
+ * |-------------|-------------|-------------|-------------|
+ * t t t t t
+ *
+ *
+ * If you specify a timeout value of A, then the timeout will not occur
+ * at A but at the next interval of the timer, which is later than
+ * that is expected. Similarly, if your timeout value is equal to B,
+ * then the timeout will occur at interval after B. Now depending upon the
+ * resolution of your timeouts and the accuracy of the timeouts
+ * needed for your application, you should set the value of
+ * <timer_skew>. In the above case, if you want the timeout A to fire
+ * no later than A, then you should specify your <timer_skew> to be
+ * A % t.
+ *
+ * The timeout value should be specified via the macro ACE_TIMER_SKEW
+ * in your config.h file. The default value is zero.
+ *
+ * Things get interesting if the t before the timeout value B is zero
+ * i.e your timeout is less than the interval. In that case, you are
+ * almost sure of not getting the desired timeout behaviour. Maybe you
+ * should look for a better OS :-)
+ *
+ * Returns the number of timers canceled.
+ */
+
+ /* virtual */ int expire (void);
+
+ /**
+ * Returns the current time of day. This method allows different
+ * implementations of the timer queue to use special high resolution
+ * timers.
+ */
+ /* virtual */ ACE_Time_Value gettimeofday (void);
+
+ /// Allows applications to control how the timer queue gets the time
+ /// of day.
+ void gettimeofday (ACE_Time_Value (*gettimeofday)(void));
+
+ /// Determine the next event to timeout. Returns @a max if there are
+ /// no pending timers or if all pending timers are longer than max.
+ /// This method acquires a lock internally since it modifies internal state.
+ virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max);
+
+ /**
+ * Determine the next event to timeout. Returns @a max if there are
+ * no pending timers or if all pending timers are longer than max.
+ * <the_timeout> should be a pointer to storage for the timeout value,
+ * and this value is also returned. This method does not acquire a
+ * lock internally since it doesn't modify internal state. If you
+ * need to call this method when the queue is being modified
+ * concurrently, however, you should make sure to acquire the <mutex()>
+ * externally before making the call.
+ */
+ virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max,
+ ACE_Time_Value *the_timeout);
+
+ /// Set the timer skew for the Timer_Queue.
+ void timer_skew (const ACE_Time_Value &skew);
+
+ /// Get the timer skew for the Timer_Queue.
+ const ACE_Time_Value &timer_skew (void) const;
+
+ /// Synchronization variable used by the queue
+ ACE_LOCK &mutex (void);
+
+ /// Accessor to the upcall functor
+ FUNCTOR &upcall_functor (void);
+
+ /// Returns a pointer to this ACE_Timer_Queue's iterator.
+ virtual ITERATOR &iter (void) = 0;
+
+ /// Removes the earliest node from the queue and returns it
+ virtual ACE_Timer_Node_T<TYPE> *remove_first (void) = 0;
+
+ /// Dump the state of a object.
+ virtual void dump (void) const;
+
+ /// Reads the earliest node from the queue and returns it.
+ virtual ACE_Timer_Node_T<TYPE> *get_first (void) = 0;
+
+ /// Method used to return a timer node to the queue's ownership
+ /// after it is returned by a method like <remove_first>.
+ virtual void return_node (ACE_Timer_Node_T<TYPE> *);
+
+ /// This method will call the preinvoke() on <functor>.
+ void preinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
+ const ACE_Time_Value &cur_time,
+ const void *&upcall_act);
+
+ /// This method will call the timeout() on <functor>.
+ void upcall (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
+ const ACE_Time_Value &cur_time);
+
+ /// This method will call the postinvoke() on <functor>.
+ void postinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
+ const ACE_Time_Value &cur_time,
+ const void *upcall_act);
+
+protected:
+
+ /// Schedule a timer.
+ virtual long schedule_i (const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval) = 0;
+
+ /// Reschedule an "interval" ACE_Timer_Node.
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *) = 0;
+
+ /// Factory method that allocates a new node.
+ virtual ACE_Timer_Node_T<TYPE> *alloc_node (void);
+
+ /// Factory method that frees a previously allocated node.
+ virtual void free_node (ACE_Timer_Node_T<TYPE> *);
+
+ /// Non-locking version of dispatch_info ()
+ virtual int dispatch_info_i (const ACE_Time_Value &current_time,
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> &info);
+
+ /// Synchronization variable for ACE_Timer_Queue.
+ /// @note The right name would be lock_, but HP/C++ will choke on that!
+ ACE_LOCK mutex_;
+
+ /// Class that implements a free list
+ ACE_Free_List<ACE_Timer_Node_T<TYPE> > *free_list_;
+
+ /// Pointer to function that returns the current time of day.
+ ACE_Time_Value (*gettimeofday_)(void);
+
+ /// Upcall functor
+ FUNCTOR *upcall_functor_;
+
+ /// To delete or not to delete is the question?
+ bool const delete_upcall_functor_;
+
+ /// Flag to delete only if the class created the <free_list_>
+ bool const delete_free_list_;
+
+private:
+
+ /// Returned by <calculate_timeout>.
+ ACE_Time_Value timeout_;
+
+ /// Adjusts for timer skew in various clocks.
+ ACE_Time_Value timer_skew_;
+
+ // = Don't allow these operations for now.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Timer_Queue_T (const ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> &))
+};
+
+/**
+ * @class ACE_Event_Handler_Handle_Timeout_Upcall
+ *
+ * @brief Functor for Timer_Queues.
+ *
+ * This class implements the functor required by the Timer
+ * Queue to call <handle_timeout> on ACE_Event_Handlers.
+ */
+template <class ACE_LOCK>
+class ACE_Event_Handler_Handle_Timeout_Upcall
+{
+public:
+ typedef ACE_Timer_Queue_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>,
+ ACE_LOCK>
+ TIMER_QUEUE;
+
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Event_Handler_Handle_Timeout_Upcall (void);
+
+ /// Destructor.
+ ~ACE_Event_Handler_Handle_Timeout_Upcall (void);
+
+ /// This method is called when a timer is registered.
+ int registration (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg);
+
+ /// This method is called before the timer expires.
+ int preinvoke (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time,
+ const void *&upcall_act);
+
+ /// This method is called when the timer expires.
+ int timeout (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time);
+
+ /// This method is called after the timer expires.
+ int postinvoke (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time,
+ const void *upcall_act);
+
+ /// This method is called when a handler is cancelled
+ int cancel_type (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ int dont_call,
+ int &requires_reference_counting);
+
+ /// This method is called when a timer is cancelled
+ int cancel_timer (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ int dont_call,
+ int requires_reference_counting);
+
+ /// 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_Event_Handler *handler,
+ const void *arg);
+
+private:
+
+ /// Flag indicating that reference counting is required for this
+ /// event handler upcall.
+ int requires_reference_counting_;
+
+ // = Don't allow these operations for now.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Event_Handler_Handle_Timeout_Upcall (const ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Timer_Queue_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Timer_Queue_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Timer_Queue_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_QUEUE_T_H */
diff --git a/ACE/ace/Timer_Queue_T.inl b/ACE/ace/Timer_Queue_T.inl
new file mode 100644
index 00000000000..7275119e2e1
--- /dev/null
+++ b/ACE/ace/Timer_Queue_T.inl
@@ -0,0 +1,222 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set (const TYPE &type,
+ const void *a,
+ const ACE_Time_Value &t,
+ const ACE_Time_Value &i,
+ ACE_Timer_Node_T<TYPE> *n,
+ long timer_id)
+{
+ this->type_ = type;
+ this->act_ = a;
+ this->timer_value_ = t;
+ this->interval_ = i;
+ this->next_ = n;
+ this->timer_id_ = timer_id;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set (const TYPE &type,
+ const void *a,
+ const ACE_Time_Value &t,
+ const ACE_Time_Value &i,
+ ACE_Timer_Node_T<TYPE> *p,
+ ACE_Timer_Node_T<TYPE> *n,
+ long timer_id)
+{
+ this->type_ = type;
+ this->act_ = a;
+ this->timer_value_ = t;
+ this->interval_ = i;
+ this->prev_ = p;
+ this->next_ = n;
+ this->timer_id_ = timer_id;
+}
+
+template <class TYPE> ACE_INLINE TYPE &
+ACE_Timer_Node_T<TYPE>::get_type (void)
+{
+ return this->type_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_type (TYPE &type)
+{
+ this->type_ = type;
+}
+
+template <class TYPE> ACE_INLINE const void *
+ACE_Timer_Node_T<TYPE>::get_act (void)
+{
+ return this->act_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_act (void *act)
+{
+ this->act_ = act;
+}
+
+template <class TYPE> ACE_INLINE const ACE_Time_Value &
+ACE_Timer_Node_T<TYPE>::get_timer_value (void) const
+{
+ return this->timer_value_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_timer_value (const ACE_Time_Value &timer_value)
+{
+ this->timer_value_ = timer_value;
+}
+
+template <class TYPE> ACE_INLINE const ACE_Time_Value &
+ACE_Timer_Node_T<TYPE>::get_interval (void) const
+{
+ return this->interval_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_interval (const ACE_Time_Value &interval)
+{
+ this->interval_ = interval;
+}
+
+template <class TYPE> ACE_INLINE ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Node_T<TYPE>::get_prev (void)
+{
+ return this->prev_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_prev (ACE_Timer_Node_T<TYPE> *prev)
+{
+ this->prev_ = prev;
+}
+
+template <class TYPE> ACE_INLINE ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Node_T<TYPE>::get_next (void)
+{
+ return this->next_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_next (ACE_Timer_Node_T<TYPE> *next)
+{
+ this->next_ = next;
+}
+
+template <class TYPE> ACE_INLINE long
+ACE_Timer_Node_T<TYPE>::get_timer_id (void) const
+{
+ return this->timer_id_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_timer_id (long timer_id)
+{
+ this->timer_id_ = timer_id;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::get_dispatch_info (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info)
+{
+ // Yes, do a copy
+ info.type_ = this->type_;
+ info.act_ = this->act_;
+ info.recurring_timer_ =
+ this->interval_ > ACE_Time_Value::zero;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::timer_skew (const ACE_Time_Value &skew)
+{
+ timer_skew_ = skew;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE const ACE_Time_Value &
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::timer_skew (void) const
+{
+ return timer_skew_;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE int
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire (void)
+{
+ if (!this->is_empty ())
+ return this->expire (this->gettimeofday () + timer_skew_);
+ else
+ return 0;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info (const ACE_Time_Value &cur_time,
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> &info)
+{
+ ACE_TRACE ("ACE_Timer_Queue_T::dispatch_info");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, 0));
+
+ return this->dispatch_info_i (cur_time, info);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::upcall (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
+ const ACE_Time_Value &cur_time)
+{
+ this->upcall_functor ().timeout (*this,
+ info.type_,
+ info.act_,
+ info.recurring_timer_,
+ cur_time);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::preinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
+ const ACE_Time_Value &cur_time,
+ const void *&upcall_act)
+{
+ this->upcall_functor ().preinvoke (*this,
+ info.type_,
+ info.act_,
+ info.recurring_timer_,
+ cur_time,
+ upcall_act);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::postinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
+ const ACE_Time_Value &cur_time,
+ const void *upcall_act)
+{
+ this->upcall_functor ().postinvoke (*this,
+ info.type_,
+ info.act_,
+ info.recurring_timer_,
+ cur_time,
+ upcall_act);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE ACE_Time_Value
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::gettimeofday (void)
+{
+ // Invoke gettimeofday via pointer to function.
+ return this->gettimeofday_ ();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::gettimeofday (ACE_Time_Value (*gettimeofday)(void))
+{
+ this->gettimeofday_ = gettimeofday;
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE FUNCTOR &
+ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::upcall_functor (void)
+{
+ return *this->upcall_functor_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Timer_Queuefwd.h b/ACE/ace/Timer_Queuefwd.h
new file mode 100644
index 00000000000..6e03204bdde
--- /dev/null
+++ b/ACE/ace/Timer_Queuefwd.h
@@ -0,0 +1,38 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timer_Queuefwd.h
+ *
+ * $Id$
+ *
+ * Forward declarations and typedefs of ACE_Timer_Queue class.
+ *
+ * @author Ossama Othman <ossama@dre.vanderbilt.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_QUEUE_FWD_H
+#define ACE_TIMER_QUEUE_FWD_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Synch_Traits.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> class ACE_Timer_Queue_T;
+template <class ACE_LOCK> class ACE_Event_Handler_Handle_Timeout_Upcall;
+
+class ACE_Event_Handler;
+
+typedef ACE_Timer_Queue_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Timer_Queue;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_TIMER_QUEUE_FWD_H */
diff --git a/ACE/ace/Timer_Wheel.h b/ACE/ace/Timer_Wheel.h
new file mode 100644
index 00000000000..307e56b5542
--- /dev/null
+++ b/ACE/ace/Timer_Wheel.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timer_Wheel.h
+ *
+ * $Id$
+ *
+ * @author Darrell Brunsch (brunsch@cs.wustl.edu)
+ */
+//=============================================================================
+
+
+#ifndef ACE_TIMER_WHEEL_H
+#define ACE_TIMER_WHEEL_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Timer_Wheel_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// The following typedefs are here for ease of use and backward
+// compatibility.
+
+typedef ACE_Timer_Wheel_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Timer_Wheel;
+
+typedef ACE_Timer_Wheel_Iterator_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Timer_Wheel_Iterator;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_WHEEL_H */
diff --git a/ACE/ace/Timer_Wheel_T.cpp b/ACE/ace/Timer_Wheel_T.cpp
new file mode 100644
index 00000000000..2855de8a8a7
--- /dev/null
+++ b/ACE/ace/Timer_Wheel_T.cpp
@@ -0,0 +1,967 @@
+// $Id$
+
+#ifndef ACE_TIMER_WHEEL_T_CPP
+#define ACE_TIMER_WHEEL_T_CPP
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Guard_T.h"
+#include "ace/Timer_Wheel_T.h"
+#include "ace/Log_Msg.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Design/implementation notes for ACE_Timer_Wheel_T.
+//
+// Each timer queue entry is represented by a ACE_Timer_Node.
+// The timing wheel is divided into a number of "spokes"; there are
+// spoke_count_ spokes in the wheel. Each timer is hashed into one of the
+// spokes. Entries within each spoke are linked in a double-linked list
+// in order of increasing expiration. The first ACE_Timer_Node in each
+// spoke is a "dummy node" that marks the end of the list of ACE_Timer_Nodes
+// in that spoke.
+//
+// The timer ID for a scheduled timer is formed by its spoke position in
+// the wheel, and the number of timers that have been inserted in that spoke
+// since the queue was initialized. N bits of the long timer_id are used
+// to determine the spoke, and M bits are used as a counter.
+// Each time a Node is inserted into a spoke, it's counter
+// is incremented. The count is kept in the timer ID field
+// of the dummy root Node. In the event of overflow of the counter, the spoke
+// must be searched for each new id to make sure it's not already in use. To
+// prevent having to do an exhaustive search each time, we keep extra data
+// in the dummy root Node.
+/**
+* Default Constructor that sets defaults for spoke_count_ and resolution_
+* and doesn't do any preallocation.
+*
+* @param upcall_functor A pointer to a functor to use instead of the default
+* @param freelist A pointer to a freelist to use instead of the default
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Wheel_T
+(FUNCTOR* upcall_functor
+ , FreeList* freelist
+ )
+: Base (upcall_functor, freelist)
+, spokes_(0)
+, spoke_count_(0) // calculated in open_i
+, spoke_bits_(0)
+, res_bits_ (0)
+, earliest_spoke_ (0)
+, iterator_(0)
+, timer_count_(0)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::ACE_Timer_Wheel_T");
+ this->open_i (0,
+ ACE_DEFAULT_TIMER_WHEEL_SIZE,
+ ACE_DEFAULT_TIMER_WHEEL_RESOLUTION);
+}
+
+/**
+* Constructor that sets up the timing wheel and also may preallocate
+* some nodes on the free list
+*
+* @param spoke_count The number of lists in the timer wheel
+* @param resolution The time resolution in milliseconds used by the hashing function
+* @param prealloc The number of entries to prealloc in the free_list
+* @param upcall_functor A pointer to a functor to use instead of the default
+* @param freelist A pointer to a freelist to use instead of the default
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Wheel_T
+ (u_int spoke_count,
+ u_int resolution,
+ size_t prealloc,
+ FUNCTOR* upcall_functor,
+ FreeList* freelist)
+: Base (upcall_functor, freelist)
+, spokes_ (0)
+, spoke_count_ (0) // calculated in open_i
+, spoke_bits_ (0)
+, res_bits_ (0)
+, earliest_spoke_ (0)
+, iterator_ (0)
+, timer_count_ (0)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::ACE_Timer_Wheel_T");
+ this->open_i (prealloc, spoke_count, resolution);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::power2bits (int n,
+ int min_bits,
+ int max_bits)
+{
+ int max = (1 << max_bits) - 1;
+ if (n > max)
+ return max_bits;
+
+ // count the bits in n.
+ int i = 0;
+ int tmp = n;
+ do
+ {
+ tmp >>= 1;
+ ++i;
+ }
+ while (tmp != 0);
+
+ if (i <= min_bits)
+ return min_bits;
+
+ // Which is nearest?
+ int a = (1 << i) - n;
+ int b = (1 << (i - 1)) - n;
+ if (b < 0)
+ b = -b;
+ if (b < a)
+ return i - 1;
+ return i;
+}
+
+/**
+* Initialize the queue. Uses the established members for all needed
+* information.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::open_i
+ (size_t prealloc, u_int spokes, u_int res)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::open_i");
+
+ this->gettimeofday (ACE_OS::gettimeofday);
+
+ // Rather than waste bits in our timer id, we might as well round up
+ // the spoke count to the next power of two - 1 . (i.e 1,3,7,15,...127,etc.)
+ const int MIN_SPOKE_BITS = 3; // Allow between 8 and 4096 spokes
+ const int MAX_SPOKE_BITS = 12;
+ const int MAX_RES_BITS = 20; // 20 is plenty, even on 64 bit platforms.
+
+ this->spoke_bits_ = power2bits (spokes, MIN_SPOKE_BITS, MAX_SPOKE_BITS);
+ this->res_bits_ = power2bits (res, 1, MAX_RES_BITS);
+
+ this->spoke_count_ = 1 << this->spoke_bits_;
+
+ this->free_list_->resize (prealloc + this->spoke_count_);
+
+ this->wheel_time_.msec (1 << (this->res_bits_ + this->spoke_bits_));
+
+ ACE_NEW (this->spokes_, ACE_Timer_Node_T<TYPE>* [this->spoke_count_]);
+
+ // Create the root nodes. These will be treated specially
+ for (u_int i = 0; i < this->spoke_count_; ++i)
+ {
+ ACE_Timer_Node_T<TYPE>* root = this->alloc_node ();
+ root->set (0, 0, ACE_Time_Value::zero, ACE_Time_Value::zero, root, root, 0);
+ this->spokes_[i] = root;
+ }
+
+ ACE_NEW (iterator_, Iterator (*this));
+}
+
+/// Destructor just cleans up its memory
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Wheel_T (void)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::~ACE_Timer_Wheel_T");
+
+ delete iterator_;
+
+ for (u_int i = 0; i < this->spoke_count_; ++i)
+ {
+ // Free all the nodes starting at the root
+ ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
+ for (ACE_Timer_Node_T<TYPE>* n = root->get_next (); n != root;)
+ {
+ ACE_Timer_Node_T<TYPE>* next = n->get_next ();
+ this->upcall_functor ().deletion (*this,
+ n->get_type (),
+ n->get_act ());
+ this->free_node (n);
+ n = next;
+ }
+ delete root;
+ }
+ delete[] this->spokes_;
+}
+
+/// Searches for a node by timer_id within one spoke.
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T<TYPE>*
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::find_spoke_node
+ (u_int spoke, long timer_id) const
+{
+ ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
+ for (ACE_Timer_Node_T<TYPE>* n = root->get_next ();
+ n != root;
+ n = n->get_next ())
+ {
+ if (n->get_timer_id () == timer_id)
+ return n;
+ }
+ return 0;
+}
+
+/// Searches all spokes for a node matching the specified timer_id
+/// Uses the spoke encoded in the timer_id as a starting place.
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T<TYPE>*
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::find_node (long timer_id) const
+{
+ if (timer_id == -1)
+ return 0;
+
+ // Search the spoke where timer_id was originally scheduled
+ u_int spoke_mask = this->spoke_count_ - 1;
+ u_int start = timer_id & spoke_mask;
+ ACE_Timer_Node_T<TYPE>* n = this->find_spoke_node (start, timer_id);
+ if (n != 0)
+ return n;
+
+ //ACE_ERROR((LM_ERROR, "Node not found in original spoke.\n"));
+
+ // Search the rest of the spokes
+ for (u_int i = 0; i < this->spoke_count_; ++i)
+ {
+ if (i != start)
+ { // already searched this one
+ n = this->find_spoke_node (i, timer_id);
+ if (n != 0)
+ return n;
+ }
+ }
+
+ //ACE_ERROR((LM_ERROR, "Node not found.\n"));
+ return 0;
+}
+
+/**
+* Check to see if the wheel is empty
+*
+* @return True if empty
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::is_empty");
+ return timer_count_ == 0;
+}
+
+
+/**
+* @return First (earliest) node in the wheel_'s earliest_spoke_ list
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> const ACE_Time_Value &
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::earliest_time (void) const
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::earliest_time");
+ ACE_Timer_Node_T<TYPE>* n = this->get_first_i ();
+ if (n != 0)
+ return n->get_timer_value ();
+ return ACE_Time_Value::zero;
+}
+
+/// Uses a simple hash to find which spoke to use based on when the
+/// timer is due to expire. Hopefully the 64bit int operations avoid
+/// any overflow problems.
+template <class TYPE, class FUNCTOR, class ACE_LOCK> u_int
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_spoke
+ (const ACE_Time_Value& t) const
+{
+ return static_cast<u_int> ((t.msec () >> this->res_bits_) & (this->spoke_count_ - 1));
+}
+
+/// Generates a unique timer_id for the given spoke. It should be pretty
+/// fast until the point where the counter overflows. At that time you
+/// have to do exhaustive searches within the spoke to ensure that a particular
+/// timer id is not already in use. Some optimizations are in place so
+/// that this hopefully doesn't have to happen often.
+template <class TYPE, class FUNCTOR, class ACE_LOCK> long
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::generate_timer_id (u_int spoke)
+{
+
+ int cnt_bits = sizeof (long) * 8 - this->spoke_bits_;
+ long max_cnt = ((long)1 << cnt_bits) - 1;
+ if (spoke == this->spoke_count_)
+ --max_cnt; // Because -1 is used as a special invalid timer_id.
+
+ ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
+
+ if (root == root->get_next ())
+ root->set_act(0);
+
+ // We use this field to keep track of the next counter value that
+ // may be in use. Of course it may have expired, so we just use
+ // this field so that we know when we don't have to check for duplicates
+#if defined (ACE_WIN64)
+ // The cast below is legit... we know that long is shorter than a
+ // pointer, but are only using it as a 'long' storage area.
+# pragma warning(push)
+# pragma warning(disable : 4311)
+#endif /* ACE_WIN64 */
+ long next_cnt = reinterpret_cast<long> (root->get_act ());
+#if defined (ACE_WIN64)
+# pragma warning(pop)
+#endif /* ACE_WIN64 */
+
+ // This field is used as a counter instead of a timer_id.
+ long cnt = root->get_timer_id ();
+
+ if (cnt >= max_cnt && root == root->get_next ())
+ {
+ // Special case when we overflow on an empty spoke. We can just
+ // wrap the count around without searching for duplicates. We only
+ // want to do this when the counter overflows, so that we return
+ // unique timer_id values as often as possible.
+ root->set_timer_id (1);
+ return spoke;
+ }
+ else if (cnt >= max_cnt)
+ { // overflow
+ cnt = 0; // try again starting at zero
+ }
+ else if (next_cnt == 0 || cnt < next_cnt)
+ {
+ root->set_timer_id (cnt + 1);
+ return (cnt << this->spoke_bits_) | spoke;
+ }
+
+ //ACE_ERROR((LM_ERROR, "Timer id overflow. We have to search now.\n"));
+
+ // We've run out of consecutive id numbers so now we have to search
+ // for a unique id.
+ // We'll try increasing numbers until we find one that is not in use,
+ // and we'll record the next highest number so that we can avoid this
+ // search as often as possible.
+ for (; cnt < max_cnt - 1; ++cnt)
+ {
+ long id = (cnt << this->spoke_bits_) | spoke;
+ ACE_Timer_Node_T<TYPE>* n = this->find_spoke_node (spoke, id);
+ if (n == 0)
+ {
+ root->set_timer_id (cnt + 1);
+ // Now we need to find the next highest cnt in use
+ next_cnt = 0;
+ for (; n != root; n = n->get_next ())
+ {
+ long tmp = n->get_timer_id () >> this->spoke_bits_;
+ if (tmp > cnt && (tmp < next_cnt || next_cnt == 0))
+ next_cnt = tmp;
+ }
+#if defined (ACE_WIN64)
+ // The cast below is legit... we know we're storing a long in
+ // a pointer, but are only using it as a 'long' storage area.
+# pragma warning(push)
+# pragma warning(disable : 4312)
+#endif /* ACE_WIN64 */
+ root->set_act (reinterpret_cast<void*> (next_cnt));
+#if defined (ACE_WIN64)
+# pragma warning(pop)
+#endif /* ACE_WIN64 */
+ return id;
+ }
+ }
+
+ return -1; // We did our best, but the spoke is full.
+}
+
+/**
+* Creates a ACE_Timer_Node_T based on the input parameters. Then inserts
+* the node into the wheel using reschedule (). Then returns a timer_id.
+*
+* @param type The data of the timer node
+* @param act Asynchronous Completion Token (AKA magic cookie)
+* @param future_time The time the timer is scheduled for (absolute time)
+* @param interval If not ACE_Time_Value::zero, then this is a periodic
+* timer and interval is the time period
+*
+* @return Unique identifier (can be used to cancel the timer).
+* -1 on failure.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> long
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (const TYPE& type,
+ const void* act,
+ const ACE_Time_Value& future_time,
+ const ACE_Time_Value& interval)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::schedule_i");
+
+ ACE_Timer_Node_T<TYPE>* n = this->alloc_node ();
+
+ if (n != 0)
+ {
+ u_int spoke = calculate_spoke (future_time);
+ long id = generate_timer_id (spoke);
+
+ //ACE_ERROR((LM_ERROR, "Scheduling %x spoke:%d id:%d\n", (long) n, spoke, id));
+
+ if (id != -1)
+ {
+ n->set (type, act, future_time, interval, 0, 0, id);
+ this->schedule_i (n, spoke, future_time);
+ }
+ return id;
+ }
+
+ // Failure return
+ errno = ENOMEM;
+ return -1;
+}
+
+/**
+* Takes an ACE_Timer_Node and inserts it into the correct position in
+* the correct list. Also makes sure to update the earliest time.
+*
+* @param n The timer node to reschedule
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::reschedule (ACE_Timer_Node_T<TYPE>* n)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::reschedule");
+ const ACE_Time_Value& expire = n->get_timer_value ();
+ u_int spoke = calculate_spoke (expire);
+ this->schedule_i (n, spoke, expire);
+}
+
+/// The shared scheduling functionality between schedule() and reschedule()
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i
+ (ACE_Timer_Node_T<TYPE>* n,
+ u_int spoke,
+ const ACE_Time_Value& expire)
+{
+ // See if we need to update the earliest time
+ if (this->is_empty() || expire < this->earliest_time ())
+ this->earliest_spoke_ = spoke;
+
+ ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
+ ACE_Timer_Node_T<TYPE>* last = root->get_prev ();
+
+ ++timer_count_;
+
+ // If the spoke is empty
+ if (last == root) {
+ n->set_prev (root);
+ n->set_next (root);
+ root->set_prev (n);
+ root->set_next (n);
+ return;
+ }
+
+ // We always want to search backwards from the tail of the list, because
+ // this minimizes the search in the extreme case when lots of timers are
+ // scheduled for exactly the same time
+ ACE_Timer_Node_T<TYPE>* p = root->get_prev ();
+ while (p != root && p->get_timer_value () > expire)
+ p = p->get_prev ();
+
+ // insert after
+ n->set_prev (p);
+ n->set_next (p->get_next ());
+ p->get_next ()->set_prev (n);
+ p->set_next (n);
+}
+
+
+/**
+* Find the timer node by using the id as a pointer. Then use set_interval()
+* on the node to update the interval.
+*
+* @param timer_id The timer identifier
+* @param interval The new interval
+*
+* @return 0 if successful, -1 if no.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id,
+ const ACE_Time_Value &interval
+ )
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::reset_interval");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+ ACE_Timer_Node_T<TYPE>* n = this->find_node (timer_id);
+ if (n != 0)
+ {
+ // The interval will take effect the next time this node is expired.
+ n->set_interval (interval);
+ return 0;
+ }
+ return -1;
+}
+
+
+/**
+* Goes through every list in the wheel and whenever we find one with the
+* correct type value, we remove it and continue. At the end make sure
+* we reset the earliest time value in case the earliest timers were
+* removed.
+*
+* @param type The value to search for.
+* @param skip_close If this non-zero, the cancellation method of the
+* functor will not be called for each cancelled timer.
+*
+* @return Number of timers cancelled
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE& type, int skip_close)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::cancel");
+
+ int num_canceled = 0; // Note : Technically this can overflow.
+ int cookie = 0;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ if (!this->is_empty ())
+ {
+ ACE_Timer_Node_T<TYPE>* first = this->get_first ();
+ ACE_Time_Value last = first->get_timer_value ();
+ int recalc = 0;
+
+ for (u_int i = 0; i < this->spoke_count_; ++i)
+ {
+ ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
+ for (ACE_Timer_Node_T<TYPE>* n = root->get_next (); n != root; )
+ {
+ if (n->get_type () == type)
+ {
+ ++num_canceled;
+ if (n == first)
+ recalc = 1;
+
+ ACE_Timer_Node_T<TYPE>* tmp = n;
+ n = n->get_next ();
+
+ this->cancel_i (tmp);
+ }
+ else
+ {
+ n = n->get_next ();
+ }
+ }
+ }
+
+ if (recalc)
+ this->recalc_earliest (last);
+ }
+
+ // Call the close hooks.
+
+ // cancel_type() called once per <type>.
+ this->upcall_functor ().cancel_type (*this,
+ type,
+ skip_close,
+ cookie);
+
+ for (int i = 0;
+ i < num_canceled;
+ ++i)
+ {
+ // cancel_timer() called once per <timer>.
+ this->upcall_functor ().cancel_timer (*this,
+ type,
+ skip_close,
+ cookie);
+ }
+
+ return num_canceled;
+}
+
+
+/**
+* Cancels the single timer that is specified by the timer_id. In this
+* case the timer_id is actually a pointer to the node, so we cast it
+* to the node. This can be dangerous if the timer_id is made up
+* (or deleted twice) so we do a little sanity check. Finally we update
+* the earliest time in case the earliest timer was removed.
+*
+* @param timer_id Timer Identifier
+* @param act Asychronous Completion Token (AKA magic cookie):
+* If this is non-zero, stores the magic cookie of
+* the cancelled timer here.
+* @param skip_close If this non-zero, the cancellation method of the
+* functor will not be called.
+*
+* @return 1 for sucess and 0 if the timer_id wasn't found (or was
+* found to be invalid)
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
+ const void **act,
+ int skip_close)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::cancel");
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+ ACE_Timer_Node_T<TYPE>* n = this->find_node (timer_id);
+ if (n != 0)
+ {
+ ACE_Time_Value last = n->get_timer_value ();
+
+ int recalc = (this->get_first_i () == n);
+
+ // Call the close hooks.
+ int cookie = 0;
+
+ // cancel_type() called once per <type>.
+ this->upcall_functor ().cancel_type (*this,
+ n->get_type (),
+ skip_close,
+ cookie);
+
+ // cancel_timer() called once per <timer>.
+ this->upcall_functor ().cancel_timer (*this,
+ n->get_type (),
+ skip_close,
+ cookie);
+ if (act != 0)
+ *act = n->get_act ();
+
+ this->cancel_i (n);
+
+ if (recalc)
+ this->recalc_earliest (last);
+
+ return 1;
+ }
+ return 0;
+}
+
+/// Shared subset of the two cancel() methods.
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n)
+{
+ this->unlink (n);
+ this->free_node (n);
+}
+
+/// There are a few places where we have to figure out which timer
+/// will expire next. This method makes the assumption that spokes
+/// are always sorted, and that timers are always in the correct spoke
+/// determined from their expiration time.
+/// The last time is always passed in, even though you can often calculate
+/// it as get_first()->get_timer_value().
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::recalc_earliest
+ (const ACE_Time_Value& last)
+{
+ // This is possible because we use a count for is_empty()
+ if (this->is_empty ())
+ return;
+
+ ACE_Time_Value et = ACE_Time_Value::zero;
+ u_int es = 0;
+ u_int spoke = this->earliest_spoke_;
+
+ // We will have to go around the wheel at most one time.
+ for (u_int i = 0; i < this->spoke_count_; ++i)
+ {
+ ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
+ ACE_Timer_Node_T<TYPE>* n = root->get_next ();
+ if (n != root)
+ {
+ ACE_Time_Value t = n->get_timer_value ();
+ if (t < last + this->wheel_time_)
+ {
+ this->earliest_spoke_ = spoke;
+ return;
+ }
+ else if (et == ACE_Time_Value::zero || t < et)
+ {
+ et = t;
+ es = spoke;
+ }
+ }
+ if (++spoke >= this->spoke_count_)
+ spoke = 0;
+ }
+
+ this->earliest_spoke_ = es;
+ //ACE_ERROR((LM_ERROR, "We had to search the whole wheel.\n"));
+}
+
+/**
+* Dumps out the size of the wheel, the resolution, and the contents
+* of the wheel.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Timer_Wheel_T::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\nspoke_count_ = %d"), this->spoke_count_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\nresolution_ = %d"), 1 << this->res_bits_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\nwheel_ = \n")));
+
+ for (u_int i = 0; i < this->spoke_count_; ++i)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d\n"), i));
+ ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
+ for (ACE_Timer_Node_T<TYPE>* n = root->get_next ();
+ n != root;
+ n = n->get_next ())
+ {
+ n->dump ();
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+
+/**
+* Removes the earliest node and then find the new <earliest_spoke_>
+*
+* @return The earliest timer node.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first (void)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::remove_first");
+ return remove_first_expired (ACE_Time_Value::max_time);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::unlink (ACE_Timer_Node_T<TYPE>* n)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::unlink");
+ --timer_count_;
+ n->get_prev ()->set_next (n->get_next ());
+ n->get_next ()->set_prev (n->get_prev ());
+ n->set_prev (0);
+ n->set_next (0);
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first_expired (const ACE_Time_Value& now)
+{
+ ACE_Timer_Node_T<TYPE>* n = this->get_first ();
+ if (n != 0 && n->get_timer_value() <= now)
+ {
+ this->unlink (n);
+ this->recalc_earliest (n->get_timer_value ());
+ return n;
+ }
+ return 0;
+}
+
+/**
+* Returns the earliest node without removing it
+*
+* @return The earliest timer node.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T<TYPE>*
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::get_first");
+ return this->get_first_i ();
+}
+
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Node_T<TYPE>*
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const
+{
+ ACE_Timer_Node_T<TYPE>* root = this->spokes_[this->earliest_spoke_];
+ ACE_Timer_Node_T<TYPE>* first = root->get_next ();
+ if (first != root)
+ return first;
+ return 0;
+}
+
+
+/**
+* @return The iterator
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>&
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void)
+{
+ this->iterator_->first ();
+ return *this->iterator_;
+}
+
+/**
+* Dummy version of expire to get rid of warnings in Sun CC 4.2
+* Just call the expire of the base class.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire ()
+{
+ return ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::expire ();
+}
+
+/**
+* This is a specialized version of expire that is more suited for the
+* internal data representation.
+*
+* @param cur_time The time to expire timers up to.
+*
+* @return Number of timers expired
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> int
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value& cur_time)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::expire");
+
+ int expcount = 0;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
+
+ ACE_Timer_Node_T<TYPE>* n = this->remove_first_expired (cur_time);
+
+ while (n != 0)
+ {
+ ++expcount;
+
+ //ACE_ERROR((LM_ERROR, "Expiring %x\n", (long) n));
+
+ ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
+
+ // Get the dispatch info
+ n->get_dispatch_info (info);
+
+ if (n->get_interval () > ACE_Time_Value::zero)
+ {
+ // Make sure that we skip past values that have already
+ // "expired".
+ do
+ n->set_timer_value (n->get_timer_value () +
+ n->get_interval ());
+ while (n->get_timer_value () <= cur_time);
+
+ this->reschedule (n);
+ }
+ else
+ {
+ this->free_node (n);
+ }
+
+ const void *upcall_act = 0;
+
+ this->preinvoke (info, cur_time, upcall_act);
+
+ this->upcall (info, cur_time);
+
+ this->postinvoke (info, cur_time, upcall_act);
+
+ n = this->remove_first_expired (cur_time);
+ }
+
+ return expcount;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// ACE_Timer_Wheel_Iterator_T
+
+/**
+* Just initializes the iterator with a ACE_Timer_Wheel_T and then calls
+* first() to initialize the rest of itself.
+*
+* @param wheel A reference for a timer queue to iterate over
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Wheel_Iterator_T<TYPE,FUNCTOR,ACE_LOCK>::ACE_Timer_Wheel_Iterator_T
+(Wheel& wheel)
+: timer_wheel_ (wheel)
+{
+ this->first();
+}
+
+
+/**
+* Destructor, at this level does nothing.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+ACE_Timer_Wheel_Iterator_T<TYPE,
+FUNCTOR,
+ACE_LOCK>::~ACE_Timer_Wheel_Iterator_T (void)
+{
+}
+
+
+/**
+* Positions the iterator at the first position in the timing wheel
+* that contains something. spoke_ will be set to the spoke position of
+* this entry and current_node_ will point to the first entry in that spoke.
+*
+* If the wheel is empty, spoke_ will be equal timer_wheel_.spoke_count_ and
+* current_node_ would be 0.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::first (void)
+{
+ this->goto_next(0);
+}
+
+
+/**
+* Positions the iterator at the next node.
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::next (void)
+{
+ if (this->isdone())
+ return;
+
+ ACE_Timer_Node_T<TYPE>* n = this->current_node_->get_next ();
+ ACE_Timer_Node_T<TYPE>* root = this->timer_wheel_.spokes_[this->spoke_];
+ if (n == root)
+ this->goto_next (this->spoke_ + 1);
+ else
+ this->current_node_ = n;
+}
+
+/// Helper class for common functionality of next() and first()
+template <class TYPE, class FUNCTOR, class ACE_LOCK> void
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::goto_next (u_int start_spoke)
+{
+ // Find the first non-empty entry.
+ u_int sc = this->timer_wheel_.spoke_count_;
+ for (u_int i = start_spoke; i < sc; ++i)
+ {
+ ACE_Timer_Node_T<TYPE>* root = this->timer_wheel_.spokes_[i];
+ ACE_Timer_Node_T<TYPE>* n = root->get_next ();
+ if (n != root)
+ {
+ this->spoke_ = i;
+ this->current_node_ = n;
+ return;
+ }
+ }
+ // empty
+ this->spoke_ = sc;
+ this->current_node_ = 0;
+}
+
+/**
+* @return True when we there aren't any more items (when current_node_ == 0)
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::isdone (void) const
+{
+ return this->current_node_ == 0;
+}
+
+/**
+* @return The node at the current spokeition in the sequence or 0 if the wheel
+* is empty
+*/
+template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
+{
+ return this->current_node_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TIMER_WHEEL_T_CPP */
diff --git a/ACE/ace/Timer_Wheel_T.h b/ACE/ace/Timer_Wheel_T.h
new file mode 100644
index 00000000000..c30587594a5
--- /dev/null
+++ b/ACE/ace/Timer_Wheel_T.h
@@ -0,0 +1,226 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Timer_Wheel_T.h
+ *
+ * $Id$
+ *
+ * @author Darrell Brunsch <brunsch@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TIMER_WHEEL_T_H
+#define ACE_TIMER_WHEEL_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Timer_Queue_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declaration
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Wheel_T;
+
+/**
+ * @class ACE_Timer_Wheel_Iterator_T
+ *
+ * @brief Iterates over an ACE_Timer_Wheel.
+ *
+ * This is a generic iterator that can be used to visit every
+ * node of a timer queue. Be aware that it doesn't traverse
+ * in the order of timeout values.
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Wheel_Iterator_T
+ : public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, ACE_LOCK>
+{
+public:
+ typedef ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK> Wheel;
+ typedef ACE_Timer_Node_T<TYPE> Node;
+
+ /// Constructor
+ ACE_Timer_Wheel_Iterator_T (Wheel &);
+
+ /// Destructor
+ ~ACE_Timer_Wheel_Iterator_T (void);
+
+ /// Positions the iterator at the earliest node in the Timer Queue
+ virtual void first (void);
+
+ /// Positions the iterator at the next node in the Timer Queue
+ virtual void next (void);
+
+ /// Returns true when there are no more nodes in the sequence
+ virtual bool isdone (void) const;
+
+ /// Returns the node at the current position in the sequence
+ virtual ACE_Timer_Node_T<TYPE>* item (void);
+
+protected:
+ /// Pointer to the ACE_Timer_List that we are iterating over.
+ Wheel& timer_wheel_;
+
+ /// Current position in the timing wheel
+ u_int spoke_;
+
+ /// Pointer to the position in the the <pos_>th list
+ ACE_Timer_Node_T<TYPE>* current_node_;
+private:
+ void goto_next(u_int start_spoke);
+};
+
+/**
+ * @class ACE_Timer_Wheel_T
+ *
+ * @brief Provides a Timing Wheel version of ACE_Timer_Queue.
+ *
+ * This implementation uses a hash table of ordered doubly-
+ * linked lists of absolute times. The enhancements over the
+ * @c ACE_Timer_List include adding a free list and the ability
+ * to preallocate nodes. Timer Wheel is based on the timing
+ * wheel implementation used in Adam M. Costello and
+ * George Varghese's paper "Redesigning the BSD Callout and
+ * Timer Facilities"
+ * (http://dworkin.wustl.edu/~varghese/PAPERS/newbsd.ps.Z)
+ */
+template <class TYPE, class FUNCTOR, class ACE_LOCK>
+class ACE_Timer_Wheel_T : public ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>
+{
+public:
+ /// Type of iterator
+ typedef ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> Iterator;
+ /// Iterator is a friend
+ friend class ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>;
+ typedef ACE_Timer_Node_T<TYPE> Node;
+ /// Type inherited from
+ typedef ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> Base;
+ typedef ACE_Free_List<Node> FreeList;
+
+ /// Default constructor
+ ACE_Timer_Wheel_T (FUNCTOR* upcall_functor = 0, FreeList* freelist = 0);
+
+ /// Constructor with opportunities to set the wheelsize and resolution
+ ACE_Timer_Wheel_T (u_int spoke_count,
+ u_int resolution,
+ size_t prealloc = 0,
+ FUNCTOR* upcall_functor = 0,
+ FreeList* freelist = 0);
+
+ /// Destructor
+ virtual ~ACE_Timer_Wheel_T (void);
+
+ /// True if queue is empty, else false.
+ virtual bool is_empty (void) const;
+
+ /// Returns the time of the earlier node in the ACE_Timer_Wheel.
+ /// Must be called on a non-empty queue.
+ virtual const ACE_Time_Value& earliest_time (void) const;
+
+ /// Changes the interval of a timer (and can make it periodic or non
+ /// periodic by setting it to ACE_Time_Value::zero or not).
+ virtual int reset_interval (long timer_id,
+ const ACE_Time_Value& interval);
+
+ /// Cancel all timer associated with @a type. If <dont_call> is 0
+ /// then the <functor> will be invoked. Returns number of timers
+ /// cancelled.
+ virtual int cancel (const TYPE& type,
+ int dont_call_handle_close = 1);
+
+ // Cancel a timer, storing the magic cookie in act (if nonzero).
+ // Calls the functor if dont_call_handle_close is 0 and returns 1
+ // on success
+ virtual int cancel (long timer_id,
+ const void** act = 0,
+ int dont_call_handle_close = 1);
+
+ /// Run the <functor> for all timers whose values are <=
+ /// <ACE_OS::gettimeofday>. Also accounts for <timer_skew>. Returns
+ /// the number of timers canceled.
+ virtual int expire (void);
+
+ // Run the <functor> for all timers whose values are <= @a current_time.
+ // This does not account for <timer_skew>. Returns the number of
+ // timers canceled.
+ int expire (const ACE_Time_Value& current_time);
+
+ /// Returns a pointer to this <ACE_Timer_Queue_T>'s iterator.
+ virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>& iter (void);
+
+ /// Removes the earliest node from the queue and returns it
+ virtual ACE_Timer_Node_T<TYPE>* remove_first (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Reads the earliest node from the queue and returns it.
+ virtual ACE_Timer_Node_T<TYPE>* get_first (void);
+
+protected:
+
+ /// Schedules a timer.
+ virtual long schedule_i (const TYPE& type,
+ const void* act,
+ const ACE_Time_Value& future_time,
+ const ACE_Time_Value& interval);
+
+private:
+ // The following are documented in the .cpp file.
+ ACE_Timer_Node_T<TYPE>* get_first_i (void) const;
+ ACE_Timer_Node_T<TYPE>* remove_first_expired (const ACE_Time_Value& now);
+ void open_i (size_t prealloc, u_int spokes, u_int res);
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
+ ACE_Timer_Node_T<TYPE>* find_spoke_node(u_int spoke, long timer_id) const;
+ ACE_Timer_Node_T<TYPE>* find_node(long timer_id) const;
+ u_int calculate_spoke(const ACE_Time_Value& expire) const;
+ long generate_timer_id(u_int spoke);
+ void schedule_i (ACE_Timer_Node_T<TYPE>* n, u_int spoke, const ACE_Time_Value& expire);
+ void cancel_i (ACE_Timer_Node_T<TYPE>* n);
+ void unlink (ACE_Timer_Node_T<TYPE>* n);
+ void recalc_earliest(const ACE_Time_Value& last);
+
+private:
+ int power2bits (int n, int min_bits, int max_bits);
+
+ /// Timing Wheel.
+ ACE_Timer_Node_T<TYPE>** spokes_;
+ /// Size of the timing wheel.
+ u_int spoke_count_;
+ /// Number of timer_id bits used for the spoke
+ int spoke_bits_;
+ /// Maximum number of timers per spoke
+ u_int max_per_spoke_;
+ /// Resolution (in microsoconds) of the timing wheel.
+ int res_bits_;
+ /// Index of the list with the earliest time
+ u_int earliest_spoke_;
+ /// Iterator used to expire timers.
+ Iterator* iterator_;
+ /// The total amount of time in one iteration of the wheel. (resolution * spoke_count)
+ ACE_Time_Value wheel_time_;
+ /// The total number of timers currently scheduled.
+ u_int timer_count_;
+
+ // = Don't allow these operations for now, don't split into multiple lines
+ // breaks sun compilers
+ ACE_UNIMPLEMENTED_FUNC (ACE_Timer_Wheel_T (const ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK> &))
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Timer_Wheel_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Timer_Wheel_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TIMER_WHEEL_T_H */
diff --git a/ACE/ace/TkReactor/ACE_TkReactor.pc.in b/ACE/ace/TkReactor/ACE_TkReactor.pc.in
new file mode 100644
index 00000000000..e53797e600c
--- /dev/null
+++ b/ACE/ace/TkReactor/ACE_TkReactor.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE_TkReactor
+Description: ACE TkReactor Library
+Requires: ACE
+Version: @VERSION@
+Libs: -L${libdir} -lACE_TkReactor
+Cflags: -I${includedir}
diff --git a/ACE/ace/TkReactor/ACE_TkReactor_export.h b/ACE/ace/TkReactor/ACE_TkReactor_export.h
new file mode 100644
index 00000000000..bd74f861e60
--- /dev/null
+++ b/ACE/ace/TkReactor/ACE_TkReactor_export.h
@@ -0,0 +1,58 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl -s ACE_TkReactor
+// ------------------------------
+#ifndef ACE_TKREACTOR_EXPORT_H
+#define ACE_TKREACTOR_EXPORT_H
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_TKREACTOR_HAS_DLL)
+# define ACE_TKREACTOR_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ACE_TKREACTOR_HAS_DLL */
+
+#if !defined (ACE_TKREACTOR_HAS_DLL)
+# define ACE_TKREACTOR_HAS_DLL 1
+#endif /* ! ACE_TKREACTOR_HAS_DLL */
+
+#if defined (ACE_TKREACTOR_HAS_DLL) && (ACE_TKREACTOR_HAS_DLL == 1)
+# if defined (ACE_TKREACTOR_BUILD_DLL)
+# define ACE_TkReactor_Export ACE_Proper_Export_Flag
+# define ACE_TKREACTOR_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define ACE_TKREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* ACE_TKREACTOR_BUILD_DLL */
+# define ACE_TkReactor_Export ACE_Proper_Import_Flag
+# define ACE_TKREACTOR_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define ACE_TKREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ACE_TKREACTOR_BUILD_DLL */
+#else /* ACE_TKREACTOR_HAS_DLL == 1 */
+# define ACE_TkReactor_Export
+# define ACE_TKREACTOR_SINGLETON_DECLARATION(T)
+# define ACE_TKREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* ACE_TKREACTOR_HAS_DLL == 1 */
+
+// Set ACE_TKREACTOR_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (ACE_TKREACTOR_NTRACE)
+# if (ACE_NTRACE == 1)
+# define ACE_TKREACTOR_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define ACE_TKREACTOR_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !ACE_TKREACTOR_NTRACE */
+
+#if (ACE_TKREACTOR_NTRACE == 1)
+# define ACE_TKREACTOR_TRACE(X)
+#else /* (ACE_TKREACTOR_NTRACE == 1) */
+# if !defined (ACE_HAS_TRACE)
+# define ACE_HAS_TRACE
+# endif /* ACE_HAS_TRACE */
+# define ACE_TKREACTOR_TRACE(X) ACE_TRACE_IMPL(X)
+# include "ace/Trace.h"
+#endif /* (ACE_TKREACTOR_NTRACE == 1) */
+
+#endif /* ACE_TKREACTOR_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/TkReactor/TkReactor.cpp b/ACE/ace/TkReactor/TkReactor.cpp
new file mode 100644
index 00000000000..942f66d7d1d
--- /dev/null
+++ b/ACE/ace/TkReactor/TkReactor.cpp
@@ -0,0 +1,439 @@
+#include "ace/TkReactor/TkReactor.h"
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+
+ACE_RCSID(ace, TkReactor, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ 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 (event_handler,
+ arg,
+ delay,
+ 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;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/TkReactor/TkReactor.h b/ACE/ace/TkReactor/TkReactor.h
new file mode 100644
index 00000000000..159022a518b
--- /dev/null
+++ b/ACE/ace/TkReactor/TkReactor.h
@@ -0,0 +1,136 @@
+// -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/TkReactor/ACE_TkReactor_export.h"
+#include "ace/Select_Reactor.h"
+#include /**/ <tk.h>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_TkReactor_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_TkReactor_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_TkReactor_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 *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ 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 @a 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 @a handler associated with this @a 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 &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TK_REACTOR_H */
diff --git a/ACE/ace/Token.cpp b/ACE/ace/Token.cpp
new file mode 100644
index 00000000000..a209b02183d
--- /dev/null
+++ b/ACE/ace/Token.cpp
@@ -0,0 +1,545 @@
+// $Id$
+
+#include "ace/Token.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/Token.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Token, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Thread.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_TOKEN_DEBUGGING)
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+#endif /* ACE_TOKEN_DEBUGGING */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Token)
+
+void
+ACE_Token::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Token::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthread = %d"), ACE_Thread::self ()));
+ // @@ Is there a portable way to do this?
+ // ACE_DEBUG ((LM_DEBUG, "\nowner_ = %d", (long) this->owner_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nowner_ addr = %x"), &this->owner_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nwaiters_ = %d"), this->waiters_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nin_use_ = %d"), this->in_use_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnesting level = %d"), this->nesting_level_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_Token::ACE_Token_Queue_Entry::ACE_Token_Queue_Entry (ACE_Thread_Mutex &m,
+ ACE_thread_t t_id)
+ : next_ (0),
+ thread_id_ (t_id),
+#if defined (ACE_TOKEN_USES_SEMAPHORE)
+ cv_ (0),
+#else
+ cv_ (m),
+#endif /* ACE_TOKEN_USES_SEMAPHORE */
+ runable_ (0)
+{
+#if defined (ACE_TOKEN_USES_SEMAPHORE)
+ ACE_UNUSED_ARG (m);
+#endif /* ACE_TOKEN_USES_SEMAPHORE */
+
+ ACE_TRACE ("ACE_Token::ACE_Token_Queue_Entry::ACE_Token_Queue_Entry");
+}
+
+ACE_Token::ACE_Token_Queue_Entry::ACE_Token_Queue_Entry (ACE_Thread_Mutex &m,
+ ACE_thread_t t_id,
+ ACE_Condition_Attributes &attributes)
+ : next_ (0),
+ thread_id_ (t_id),
+#if defined (ACE_TOKEN_USES_SEMAPHORE)
+ cv_ (0),
+#else
+ cv_ (m, attributes),
+#endif /* ACE_TOKEN_USES_SEMAPHORE */
+ runable_ (0)
+{
+#if defined (ACE_TOKEN_USES_SEMAPHORE)
+ ACE_UNUSED_ARG (m);
+ ACE_UNUSED_ARG (attributes);
+#endif /* ACE_TOKEN_USES_SEMAPHORE */
+
+ ACE_TRACE ("ACE_Token::ACE_Token_Queue_Entry::ACE_Token_Queue_Entry");
+}
+
+ACE_Token::ACE_Token_Queue::ACE_Token_Queue (void)
+ : head_ (0),
+ tail_ (0)
+{
+ ACE_TRACE ("ACE_Token::ACE_Token_Queue::ACE_Token_Queue");
+}
+
+//
+// Remove an entry from the list. Must be called with locks held.
+//
+void
+ACE_Token::ACE_Token_Queue::remove_entry (ACE_Token::ACE_Token_Queue_Entry *entry)
+{
+ ACE_TRACE ("ACE_Token::ACE_Token_Queue::remove_entry");
+ ACE_Token_Queue_Entry *curr = 0;
+ ACE_Token_Queue_Entry *prev = 0;
+
+ if (this->head_ == 0)
+ return;
+
+ for (curr = this->head_;
+ curr != 0 && curr != entry;
+ curr = curr->next_)
+ prev = curr;
+
+ if (curr == 0)
+ // Didn't find the entry...
+ return;
+ else if (prev == 0)
+ // Delete at the head.
+ this->head_ = this->head_->next_;
+ else
+ // Delete in the middle.
+ prev->next_ = curr->next_;
+
+ // We need to update the tail of the list if we've deleted the last
+ // entry.
+ if (curr->next_ == 0)
+ this->tail_ = prev;
+}
+
+//
+// Add an entry into the list. Must be called with locks held.
+//
+void
+ACE_Token::ACE_Token_Queue::insert_entry (ACE_Token::ACE_Token_Queue_Entry &entry,
+ int requeue_position)
+{
+ if (this->head_ == 0)
+ {
+ // No other threads - just add me
+ this->head_ = &entry;
+ this->tail_ = &entry;
+ }
+ else if (requeue_position == -1)
+ {
+ // Insert at the end of the queue.
+ this->tail_->next_ = &entry;
+ this->tail_ = &entry;
+ }
+ else if (requeue_position == 0)
+ {
+ // Insert at head of queue.
+ entry.next_ = this->head_;
+ this->head_ = &entry;
+ }
+ else
+ // Insert in the middle of the queue somewhere.
+ {
+ // Determine where our thread should go in the queue of waiters.
+
+ ACE_Token::ACE_Token_Queue_Entry *insert_after = this->head_;
+ while (requeue_position-- && insert_after->next_ != 0)
+ insert_after = insert_after->next_;
+
+ entry.next_ = insert_after->next_;
+
+ if (entry.next_ == 0)
+ this->tail_ = &entry;
+
+ insert_after->next_ = &entry;
+ }
+}
+
+ACE_Token::ACE_Token (const ACE_TCHAR *name, void *any)
+ : lock_ (name, (ACE_mutexattr_t *) any),
+ owner_ (ACE_OS::NULL_thread),
+ in_use_ (0),
+ waiters_ (0),
+ nesting_level_ (0),
+ attributes_ (USYNC_THREAD),
+ queueing_strategy_ (FIFO)
+{
+// ACE_TRACE ("ACE_Token::ACE_Token");
+}
+
+ACE_Token::~ACE_Token (void)
+{
+ ACE_TRACE ("ACE_Token::~ACE_Token");
+}
+
+int
+ACE_Token::shared_acquire (void (*sleep_hook_func)(void *),
+ void *arg,
+ ACE_Time_Value *timeout,
+ ACE_Token_Op_Type op_type)
+{
+ ACE_TRACE ("ACE_Token::shared_acquire");
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
+
+#if defined (ACE_TOKEN_DEBUGGING)
+ this->dump ();
+#endif /* ACE_TOKEN_DEBUGGING */
+
+ ACE_thread_t const thr_id = ACE_Thread::self ();
+
+ // Nobody holds the token.
+ if (!this->in_use_)
+ {
+ // Its mine!
+ this->in_use_ = op_type;
+ this->owner_ = thr_id;
+ return 0;
+ }
+
+ //
+ // Someone already holds the token.
+ //
+
+ // Check if it is us.
+ if (ACE_OS::thr_equal (thr_id, this->owner_))
+ {
+ ++this->nesting_level_;
+ return 0;
+ }
+
+ // Do a quick check for "polling" behavior.
+ if (timeout != 0 && timeout->sec () == 0 && timeout->usec () == 0)
+ {
+ errno = ETIME;
+ return -1;
+ }
+
+ //
+ // We've got to sleep until we get the token.
+ //
+
+ // Which queue we should end up in...
+ ACE_Token_Queue *queue = (op_type == ACE_Token::READ_TOKEN
+ ? &this->readers_
+ : &this->writers_);
+
+ // Allocate queue entry on stack. This works since we don't exit
+ // this method's activation record until we've got the token.
+ ACE_Token::ACE_Token_Queue_Entry my_entry (this->lock_,
+ thr_id,
+ this->attributes_);
+ queue->insert_entry (my_entry, this->queueing_strategy_);
+ ++this->waiters_;
+
+ // Execute appropriate <sleep_hook> callback. (@@ should these
+ // methods return a success/failure status, and if so, what should
+ // we do with it?)
+ int ret = 0;
+ if (sleep_hook_func)
+ {
+ (*sleep_hook_func) (arg);
+ ++ret;
+ }
+ else
+ {
+ // Execute virtual method.
+ this->sleep_hook ();
+ ++ret;
+ }
+
+ bool timed_out = false;
+ bool error = false;
+
+ // Sleep until we've got the token (ignore signals).
+ do
+ {
+ int const result = my_entry.wait (timeout, this->lock_);
+
+ if (result == -1)
+ {
+ // Note, this should obey whatever thread-specific interrupt
+ // policy is currently in place...
+ if (errno == EINTR)
+ continue;
+
+#if defined (ACE_TOKEN_DEBUGGING)
+ cerr << '(' << ACE_Thread::self () << ')'
+ << " acquire: "
+ << (errno == ETIME ? "timed out" : "error occurred")
+ << endl;
+#endif /* ACE_TOKEN_DEBUGGING */
+
+ // We come here if a timeout occurs or some serious
+ // ACE_Condition object error.
+ if (errno == ETIME)
+ timed_out = true;
+ else
+ error = true;
+
+ // Stop the loop.
+ break;
+ }
+ }
+ while (!ACE_OS::thr_equal (thr_id, this->owner_));
+
+ // Do this always and irrespective of the result of wait().
+ --this->waiters_;
+ queue->remove_entry (&my_entry);
+
+#if defined (ACE_TOKEN_DEBUGGING)
+ ACE_DEBUG ((LM_DEBUG, "(%t) ACE_Token::shared_acquire (UNBLOCKED)\n"));
+#endif /* ACE_TOKEN_DEBUGGING */
+
+ // If timeout occured
+ if (timed_out)
+ {
+ // This thread was still selected to own the token.
+ if (my_entry.runable_)
+ {
+ // Wakeup next waiter since this thread timed out.
+ this->wakeup_next_waiter ();
+ }
+
+ // Return error.
+ return -1;
+ }
+ else if (error)
+ {
+ // Return error.
+ return -1;
+ }
+
+ // If this is a normal wakeup, this thread should be runnable.
+ ACE_ASSERT (my_entry.runable_);
+
+ return ret;
+}
+
+// By default this is a no-op.
+
+/* virtual */
+void
+ACE_Token::sleep_hook (void)
+{
+ ACE_TRACE ("ACE_Token::sleep_hook");
+}
+
+int
+ACE_Token::acquire (ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Token::acquire");
+ return this->shared_acquire (0, 0, timeout, ACE_Token::WRITE_TOKEN);
+}
+
+// Acquire the token, sleeping until it is obtained or until <timeout>
+// expires.
+
+int
+ACE_Token::acquire (void (*sleep_hook_func)(void *),
+ void *arg,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Token::acquire");
+ return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::WRITE_TOKEN);
+}
+
+// Try to renew the token.
+
+int
+ACE_Token::renew (int requeue_position,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Token::renew");
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
+
+#if defined (ACE_TOKEN_DEBUGGING)
+ this->dump ();
+#endif /* ACE_TOKEN_DEBUGGING */
+ // ACE_ASSERT (ACE_OS::thr_equal (ACE_Thread::self (), this->owner_));
+
+ // Check to see if there are any waiters worth giving up the lock
+ // for.
+
+ // If no writers and either we are a writer or there are no readers.
+ if (this->writers_.head_ == 0 &&
+ (this->in_use_ == ACE_Token::WRITE_TOKEN ||
+ this->readers_.head_ == 0))
+ // Immediate return.
+ return 0;
+
+ // We've got to sleep until we get the token again.
+
+ // Determine which queue should this thread go to.
+ ACE_Token::ACE_Token_Queue *this_threads_queue =
+ this->in_use_ == ACE_Token::READ_TOKEN ?
+ &this->readers_ : &this->writers_;
+
+ ACE_Token::ACE_Token_Queue_Entry my_entry (this->lock_,
+ this->owner_);
+
+ this_threads_queue->insert_entry (my_entry,
+ // if requeue_position == 0 then we want to go next,
+ // otherwise use the queueing strategy, which might also
+ // happen to be 0.
+ requeue_position == 0 ? 0 : this->queueing_strategy_);
+ ++this->waiters_;
+
+ // Remember nesting level...
+ int const save_nesting_level_ = this->nesting_level_;
+
+ // Reset state for new owner.
+ this->nesting_level_ = 0;
+
+ // Wakeup waiter.
+ this->wakeup_next_waiter ();
+
+ bool timed_out = false;
+ bool error = false;
+
+ // Sleep until we've got the token (ignore signals).
+ do
+ {
+ int const result = my_entry.wait (timeout, this->lock_);
+
+ if (result == -1)
+ {
+ // Note, this should obey whatever thread-specific interrupt
+ // policy is currently in place...
+ if (errno == EINTR)
+ continue;
+
+#if defined (ACE_TOKEN_DEBUGGING)
+ cerr << '(' << ACE_Thread::self () << ')'
+ << " renew: "
+ << (errno == ETIME ? "timed out" : "error occurred")
+ << endl;
+#endif /* ACE_TOKEN_DEBUGGING */
+
+ // We come here if a timeout occurs or some serious
+ // ACE_Condition object error.
+ if (errno == ETIME)
+ timed_out = true;
+ else
+ error = true;
+
+ // Stop the loop.
+ break;
+ }
+ }
+ while (!ACE_OS::thr_equal (my_entry.thread_id_, this->owner_));
+
+ // Do this always and irrespective of the result of wait().
+ --this->waiters_;
+ this_threads_queue->remove_entry (&my_entry);
+
+#if defined (ACE_TOKEN_DEBUGGING)
+ ACE_DEBUG ((LM_DEBUG, "(%t) ACE_Token::renew (UNBLOCKED)\n"));
+#endif /* ACE_TOKEN_DEBUGGING */
+
+ // If timeout occured
+ if (timed_out)
+ {
+ // This thread was still selected to own the token.
+ if (my_entry.runable_)
+ {
+ // Wakeup next waiter since this thread timed out.
+ this->wakeup_next_waiter ();
+ }
+
+ // Return error.
+ return -1;
+ }
+ else if (error)
+ {
+ // Return error.
+ return -1;
+ }
+
+ // If this is a normal wakeup, this thread should be runnable.
+ ACE_ASSERT (my_entry.runable_);
+
+ // Reinstate nesting level.
+ this->nesting_level_ = save_nesting_level_;
+
+ return 0;
+}
+
+// Release the current holder of the token (which had
+// better be the caller's thread!).
+
+int
+ACE_Token::release (void)
+{
+ ACE_TRACE ("ACE_Token::release");
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
+
+#if defined (ACE_TOKEN_DEBUGGING)
+ this->dump ();
+#endif /* ACE_TOKEN_DEBUGGING */
+
+ // Nested release...
+ if (this->nesting_level_ > 0)
+ --this->nesting_level_;
+ else
+ {
+ //
+ // Regular release...
+ //
+
+ // Wakeup waiter.
+ this->wakeup_next_waiter ();
+ }
+
+ return 0;
+}
+
+void
+ACE_Token::wakeup_next_waiter (void)
+{
+ ACE_TRACE ("ACE_Token::wakeup_next_waiter");
+
+ // Reset state for new owner.
+ this->owner_ = ACE_OS::NULL_thread;
+ this->in_use_ = 0;
+
+ // Any waiters...
+ if (this->writers_.head_ == 0 &&
+ this->readers_.head_ == 0)
+ {
+ // No more waiters...
+ return;
+ }
+
+ // Wakeup next waiter.
+ ACE_Token_Queue *queue = 0;
+
+ // Writer threads get priority to run first.
+ if (this->writers_.head_ != 0)
+ {
+ this->in_use_ = ACE_Token::WRITE_TOKEN;
+ queue = &this->writers_;
+ }
+ else
+ {
+ this->in_use_ = ACE_Token::READ_TOKEN;
+ queue = &this->readers_;
+ }
+
+ // Wake up waiter and make it runable.
+ queue->head_->runable_ = 1;
+ queue->head_->signal ();
+
+ this->owner_ = queue->head_->thread_id_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/Token.h b/ACE/ace/Token.h
new file mode 100644
index 00000000000..81b2d7173af
--- /dev/null
+++ b/ACE/ace/Token.h
@@ -0,0 +1,376 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Token.h
+ *
+ * $Id$
+ *
+ * @author Original author
+ * @author Karl-Heinz Dorn (kdorn@erlh.siemens.de)
+ * @author Ported to ACE by
+ * @author Douglas C. Schmidt (schmidt@cs.wustl.edu)
+ */
+//=============================================================================
+
+#ifndef ACE_TOKEN_H
+#define ACE_TOKEN_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Null_Mutex.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Thread_Mutex.h"
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || defined (ACE_HAS_VXTHREADS)
+// If platforms support semaphores with timed wait, then we use semaphores instead of c.v.
+# define ACE_TOKEN_USES_SEMAPHORE
+#endif /* (ACE_WIN32 && !ACE_HAS_WINCE) || VXWORKS */
+
+#if defined (ACE_TOKEN_USES_SEMAPHORE)
+# include "ace/Semaphore.h"
+#endif /* ACE_TOKEN_USES_SEMAPHORE */
+
+#include "ace/Condition_Thread_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Time_Value;
+
+/**
+ * @class ACE_Token
+ *
+ * @brief Class that acquires, renews, and releases a synchronization
+ * token that is serviced in strict FIFO/LIFO ordering and that also
+ * supports (1) recursion and (2) readers/writer semantics.
+ *
+ * This class is a more general-purpose synchronization mechanism
+ * than many native OS mutexes. For example, it implements
+ * "recursive mutex" semantics, where a thread that owns the token
+ * can reacquire it without deadlocking. If the same thread calls
+ * <acquire> multiple times, however, it must call <release> an
+ * equal number of times before the token is actually released.
+ * Threads that are blocked awaiting the token are serviced in
+ * strict FIFO/LIFO order as other threads release the token (Solaris
+ * and Pthread mutexes don't strictly enforce an acquisition
+ * order). There are two lists within the class. Write
+ * acquires always have higher priority over read acquires. Which
+ * means, if you use both write/read operations, care must be
+ * taken to avoid starvation on the readers. Notice that the
+ * read/write acquire operations do not have the usual semantic of
+ * reader/writer locks. Only one reader can acquire the token at
+ * a time (which is different from the usual reader/writer locks
+ * where several readers can acquire a lock at the same time as
+ * long as there is no writer waiting for the lock). We choose
+ * the names to (1) borrow the semantic to give writers higher
+ * priority and (2) support a common interface for all locking
+ * classes in ACE.
+ */
+class ACE_Export ACE_Token
+{
+public:
+
+ /**
+ * Available queueing strategies.
+ */
+ enum QUEUEING_STRATEGY
+ {
+ /// FIFO, First In, First Out.
+ FIFO = -1,
+ /// LIFO, Last In, First Out
+ LIFO = 0
+ };
+
+ // = Initialization and termination.
+
+ /// Constructor
+ ACE_Token (const ACE_TCHAR *name = 0, void * = 0);
+
+ /// Destructor
+ virtual ~ACE_Token (void);
+
+ // = Strategies
+
+ /// Retrieve the current queueing strategy.
+ int queueing_strategy (void);
+
+ /// Set the queueing strategy.
+ void queueing_strategy (int queueing_strategy);
+
+ // = Synchronization operations.
+
+ /**
+ * Acquire the token, sleeping until it is obtained or until the
+ * expiration of @a timeout, which is treated as "absolute" time. If
+ * some other thread currently holds the token then <sleep_hook> is
+ * called before our thread goes to sleep. This <sleep_hook> can be
+ * used by the requesting thread to unblock a token-holder that is
+ * sleeping, e.g., by means of writing to a pipe (the ACE
+ * ACE_Reactor uses this functionality). Return values: 0 if
+ * acquires without calling <sleep_hook> 1 if <sleep_hook> is
+ * called. 2 if the token is signaled. -1 if failure or timeout
+ * occurs (if timeout occurs errno == ETIME) If @a timeout ==
+ * <&ACE_Time_Value::zero> then acquire has polling semantics (and
+ * does *not* call <sleep_hook>).
+ */
+ int acquire (void (*sleep_hook)(void *),
+ void *arg = 0,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * This behaves just like the previous <acquire> method, except that
+ * it invokes the virtual function called <sleep_hook> that can be
+ * overridden by a subclass of ACE_Token.
+ */
+ int acquire (ACE_Time_Value *timeout = 0);
+
+ /**
+ * This should be overridden by a subclass to define the appropriate
+ * behavior before <acquire> goes to sleep. By default, this is a
+ * no-op...
+ */
+ virtual void sleep_hook (void);
+
+ /**
+ * An optimized method that efficiently reacquires the token if no
+ * other threads are waiting. This is useful for situations where
+ * you don't want to degrade the quality of service if there are
+ * other threads waiting to get the token. If <requeue_position> ==
+ * -1 and there are other threads waiting to obtain the token we are
+ * queued according to the queueing strategy. If <requeue_position>
+ * > -1 then it indicates how many entries to skip over before
+ * inserting our thread into the list of waiters (e.g.,
+ * <requeue_position> == 0 means "insert at front of the queue").
+ * Renew has the rather odd semantics such that if there are other
+ * waiting threads it will give up the token even if the
+ * nesting_level_ > 1. I'm not sure if this is really the right
+ * thing to do (since it makes it possible for shared data to be
+ * changed unexpectedly) so use with caution... This method
+ * maintians the original token priority. As in <acquire>, the
+ * @a timeout value is an absolute time.
+ */
+ int renew (int requeue_position = 0,
+ ACE_Time_Value *timeout = 0);
+
+ /// Become interface-compliant with other lock mechanisms (implements
+ /// a non-blocking <acquire>).
+ int tryacquire (void);
+
+ /// Shuts down the ACE_Token instance.
+ int remove (void);
+
+ /// Relinquish the token. If there are any waiters then the next one
+ /// in line gets it.
+ int release (void);
+
+ /// Behaves like acquire() but at a lower priority. It should probably
+ /// be called acquire_yield() since the semantics aren't really
+ /// what's commonly expected for readers/writer locks. See the class
+ /// documentation above for more details.
+ int acquire_read (void);
+
+ /// Behaves like acquire() but at a lower priority. It should probably
+ /// be called acquire_yield() since the semantics aren't really
+ /// what's commonly expected for readers/writer locks. See the class
+ /// documentation above for more details.
+ int acquire_read (void (*sleep_hook)(void *),
+ void *arg = 0,
+ ACE_Time_Value *timeout = 0);
+
+ /// Calls acquire().
+ int acquire_write (void);
+
+ /// Calls acquire().
+ int acquire_write (void (*sleep_hook)(void *),
+ void *arg = 0,
+ ACE_Time_Value *timeout = 0);
+
+ /// Lower priority try_acquire().
+ int tryacquire_read (void);
+
+ /// Just calls <tryacquire>.
+ int tryacquire_write (void);
+
+ /// Assumes the caller has acquired the token and returns 0.
+ int tryacquire_write_upgrade (void);
+
+ // = Accessor methods.
+
+ /// Return the number of threads that are currently waiting to get
+ /// the token.
+ int waiters (void);
+
+ /// Return the id of the current thread that owns the token.
+ ACE_thread_t current_owner (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// The following structure implements a LIFO/FIFO queue of waiter threads
+ /// that are asleep waiting to obtain the token.
+ struct ACE_Token_Queue_Entry
+ {
+ /// Constructor
+ ACE_Token_Queue_Entry (ACE_Thread_Mutex &m,
+ ACE_thread_t t_id);
+
+ /// Constructor using a pre-allocated attributes
+ ACE_Token_Queue_Entry (ACE_Thread_Mutex &m,
+ ACE_thread_t t_id,
+ ACE_Condition_Attributes &attributes);
+
+ /// Entry blocks on the token.
+ int wait (ACE_Time_Value *timeout, ACE_Thread_Mutex &lock);
+
+ /// Notify (unblock) the entry.
+ int signal (void);
+
+ /// Pointer to next waiter.
+ ACE_Token_Queue_Entry *next_;
+
+ /// ACE_Thread id of this waiter.
+ ACE_thread_t thread_id_;
+
+#if defined (ACE_TOKEN_USES_SEMAPHORE)
+ /// ACE_Semaphore object used to wake up waiter when it can run again.
+ ACE_Semaphore cv_;
+#else
+ /// ACE_Condition object used to wake up waiter when it can run again.
+ ACE_Condition_Thread_Mutex cv_;
+#endif /* ACE_TOKEN_USES_SEMAPHORE */
+
+ /// Ok to run.
+ int runable_;
+ };
+
+private:
+ enum ACE_Token_Op_Type
+ {
+ READ_TOKEN = 1,
+ WRITE_TOKEN
+ };
+
+ struct ACE_Token_Queue
+ {
+ /// Constructor
+ ACE_Token_Queue (void);
+
+ /// Remove a waiter from the queue.
+ void remove_entry (ACE_Token_Queue_Entry *);
+
+ /// Insert a waiter into the queue.
+ void insert_entry (ACE_Token_Queue_Entry &entry,
+ int requeue_position = -1);
+
+ /// Head of the list of waiting threads.
+ ACE_Token_Queue_Entry *head_;
+
+ /// Tail of the list of waiting threads.
+ ACE_Token_Queue_Entry *tail_;
+ };
+
+ /// Implements the <acquire> and <tryacquire> methods above.
+ int shared_acquire (void (*sleep_hook_func)(void *),
+ void *arg,
+ ACE_Time_Value *timeout,
+ ACE_Token_Op_Type op_type);
+
+ /// Wake next in line for ownership.
+ void wakeup_next_waiter (void);
+
+ /// A queue of writer threads.
+ ACE_Token_Queue writers_;
+
+ /// A queue of reader threads.
+ ACE_Token_Queue readers_;
+
+ /// ACE_Thread_Mutex used to lock internal data structures.
+ ACE_Thread_Mutex lock_;
+
+ /// Current owner of the token.
+ ACE_thread_t owner_;
+
+ /// Some thread (i.e., <owner_>) is using the token. We need this
+ /// extra variable to deal with POSIX pthreads madness...
+ int in_use_;
+
+ /// Number of waiters.
+ int waiters_;
+
+ /// Current nesting level.
+ int nesting_level_;
+
+ /// The attributes for the condition variables, optimizes lock time.
+ ACE_Condition_Attributes attributes_;
+
+ /// Queueing strategy, LIFO/FIFO.
+ int queueing_strategy_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#else
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Export ACE_Token
+{
+public:
+ int queueing_strategy (void) { ACE_NOTSUP_RETURN (-1); }
+ void queueing_strategy (int /*queueing_strategy*/) { }
+ int acquire (ACE_Time_Value * = 0) { ACE_NOTSUP_RETURN (-1); }
+ int tryacquire (void) { ACE_NOTSUP_RETURN (-1); }
+ int remove (void) { ACE_NOTSUP_RETURN (-1); }
+ int release (void) { ACE_NOTSUP_RETURN (-1); }
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Export ACE_Noop_Token : public ACE_Null_Mutex
+{
+public:
+ /// Queueing strategy
+ enum QUEUEING_STRATEGY
+ {
+ FIFO = -1,
+ LIFO = 0
+ };
+
+ /// Get queueing strategy.
+ int queueing_strategy (void);
+
+ /// Set queueing strategy.
+ void queueing_strategy (int queueing_strategy);
+
+ int renew (int = 0, ACE_Time_Value * =0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Token.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TOKEN_H */
diff --git a/ACE/ace/Token.inl b/ACE/ace/Token.inl
new file mode 100644
index 00000000000..d375789fbd1
--- /dev/null
+++ b/ACE/ace/Token.inl
@@ -0,0 +1,176 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/config-macros.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Guard_T.h"
+#include "ace/Time_Value.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Token::queueing_strategy (void)
+{
+ return this->queueing_strategy_;
+}
+
+ACE_INLINE void
+ACE_Token::queueing_strategy (int queueing_strategy)
+{
+ this->queueing_strategy_ = queueing_strategy == -1 ? -1 : 0;
+}
+
+ACE_INLINE int
+ACE_Token::remove (void)
+{
+ ACE_TRACE ("ACE_Token::remove");
+ // Don't have an implementation for this yet...
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_Token::tryacquire (void)
+{
+ ACE_TRACE ("ACE_Token::tryacquire");
+ return this->shared_acquire
+ (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::WRITE_TOKEN);
+}
+
+ACE_INLINE int
+ACE_Token::waiters (void)
+{
+ ACE_TRACE ("ACE_Token::waiters");
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
+
+ int const ret = this->waiters_;
+ return ret;
+}
+
+ACE_INLINE ACE_thread_t
+ACE_Token::current_owner (void)
+{
+ ACE_TRACE ("ACE_Token::current_owner");
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, this->owner_);
+
+ return this->owner_;
+}
+
+ACE_INLINE int
+ACE_Token::acquire_read (void)
+{
+ ACE_TRACE ("ACE_Token::acquire_read");
+ return this->shared_acquire
+ (0, 0, 0, ACE_Token::READ_TOKEN);
+}
+
+ACE_INLINE int
+ACE_Token::acquire_write (void)
+{
+ ACE_TRACE ("ACE_Token::acquire_write");
+ return this->shared_acquire
+ (0, 0, 0, ACE_Token::WRITE_TOKEN);
+}
+
+ACE_INLINE int
+ACE_Token::tryacquire_read (void)
+{
+ ACE_TRACE ("ACE_Token::tryacquire_read");
+ return this->shared_acquire
+ (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::READ_TOKEN);
+}
+
+ACE_INLINE int
+ACE_Token::acquire_read (void (*sleep_hook_func)(void *),
+ void *arg,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Token::acquire_read");
+ return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::READ_TOKEN);
+}
+
+ACE_INLINE int
+ACE_Token::tryacquire_write (void)
+{
+ ACE_TRACE ("ACE_Token::tryacquire_write");
+ return this->shared_acquire
+ (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::WRITE_TOKEN);
+}
+
+ACE_INLINE int
+ACE_Token::tryacquire_write_upgrade (void)
+{
+ ACE_TRACE ("ACE_Token::tryacquire_write_upgrade");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Token::acquire_write (void (*sleep_hook_func)(void *),
+ void *arg,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Token::acquire_write");
+ return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::WRITE_TOKEN);
+}
+
+ACE_INLINE int
+ACE_Token::ACE_Token_Queue_Entry::wait (ACE_Time_Value *timeout, ACE_Thread_Mutex &lock)
+{
+#if defined (ACE_TOKEN_USES_SEMAPHORE)
+ lock.release ();
+ int const retv = (timeout == 0 ?
+ this->cv_.acquire () :
+ this->cv_.acquire (*timeout));
+ lock.acquire ();
+ return retv;
+#else
+ ACE_UNUSED_ARG (lock);
+ return this->cv_.wait (timeout);
+#endif /* ACE_TOKEN_USES_SEMAPHORE */
+}
+
+ACE_INLINE int
+ACE_Token::ACE_Token_Queue_Entry::signal (void)
+{
+ return
+#if defined (ACE_TOKEN_USES_SEMAPHORE)
+ this->cv_.release ();
+#else
+ this->cv_.signal ();
+#endif /* ACE_TOKEN_USES_SEMAPHORE */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
+
+/*****************************************************************************/
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_Noop_Token::queueing_strategy (void)
+{
+ return -1;
+}
+
+ACE_INLINE void
+ACE_Noop_Token::queueing_strategy (int /* queueing_strategy */)
+{
+}
+
+ACE_INLINE int
+ACE_Noop_Token::renew (int, ACE_Time_Value *)
+{
+ return 0;
+}
+
+ACE_INLINE void
+ACE_Noop_Token::dump (void) const
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
diff --git a/ACE/ace/Token_Collection.cpp b/ACE/ace/Token_Collection.cpp
new file mode 100644
index 00000000000..8ed4fca1d39
--- /dev/null
+++ b/ACE/ace/Token_Collection.cpp
@@ -0,0 +1,294 @@
+#include "ace/Token_Collection.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Token_Collection.inl"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_RCSID (ace,
+ Token_Collection,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Token_Collection::ACE_Token_Collection (bool debug,
+ const ACE_TCHAR *name)
+: debug_ (debug)
+{
+ ACE_TRACE ("ACE_Token_Collection::ACE_Token_Collection");
+
+ if (name == 0)
+ name = ACE_TEXT ("no name");
+
+ ACE_OS::strsncpy (this->name_,
+ const_cast<ACE_TCHAR *> (name),
+ ACE_MAXTOKENNAMELEN);
+}
+
+int
+ACE_Token_Collection::insert (ACE_Token_Proxy &new_token)
+{
+ ACE_TRACE ("ACE_Token_Collection::insert");
+
+ TOKEN_NAME name (new_token.name ());
+
+ // Check if the new_proxy is already in the list.
+ if (collection_.find (name) == 1)
+ // One already exists, so fail.
+ return -1;
+
+ // Clone the new token.
+ ACE_Token_Proxy *temp = new_token.clone ();
+
+ if (collection_.bind (name, temp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("bind failed\n")), -1);
+ return 0;
+}
+
+int
+ACE_Token_Collection::extract (const ACE_TCHAR *token_name, ACE_Token_Proxy *&proxy)
+{
+ ACE_TRACE ("ACE_Token_Collection::extract");
+ TOKEN_NAME name (token_name);
+ return collection_.unbind (token_name, proxy);
+}
+
+ACE_Token_Proxy *
+ACE_Token_Collection::is_member (const ACE_TCHAR *token_name)
+{
+ ACE_TRACE ("ACE_Token_Collection::is_member");
+ TOKEN_NAME name (token_name);
+ ACE_Token_Proxy *temp;
+ // Get the token from the collection.
+ return collection_.find (name, temp) == -1 ? 0 : temp;
+}
+
+int
+ACE_Token_Collection::is_member (const ACE_Token_Proxy &token)
+{
+ ACE_TRACE ("ACE_Token_Collection::is_member");
+ TOKEN_NAME token_name (token.name ());
+ return collection_.find (token_name) == 0;
+}
+
+int
+ACE_Token_Collection::acquire (int notify,
+ void (*sleep_hook)(void *),
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Token_Collection::acquire");
+
+ COLLECTION::ITERATOR iterator (collection_);
+
+ for (COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("collection acquiring %s\n"),
+ temp->int_id_->name ()));
+ if (temp->int_id_->acquire (notify,
+ sleep_hook,
+ options) == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ this->release ();
+ ACE_RETURN (-1);
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_Token_Collection::acquire (const ACE_TCHAR *token_name,
+ int notify,
+ void (*sleep_hook)(void *),
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Token_Collection::acquire");
+ TOKEN_NAME name (token_name);
+ ACE_Token_Proxy *temp;
+ // Get the token from the collection.
+ int result = collection_.find (name, temp);
+ // did we find it?
+ if (result == -1)
+ return result;
+ // perform the operation
+ return temp->acquire (notify, sleep_hook, options);
+}
+
+
+int
+ACE_Token_Collection::tryacquire (const ACE_TCHAR *token_name,
+ void (*sleep_hook)(void *))
+{
+ ACE_TRACE ("ACE_Token_Collection::tryacquire");
+ TOKEN_NAME name (token_name);
+ ACE_Token_Proxy *temp;
+ // Get the token from the collection.
+ int result = collection_.find (name, temp);
+ // did we find it?
+ if (result == -1)
+ return result;
+
+ // perform the operation
+ return temp->tryacquire (sleep_hook);
+}
+
+int
+ACE_Token_Collection::tryacquire (void (*sleep_hook)(void *))
+{
+ ACE_TRACE ("ACE_Token_Collection::tryacquire");
+
+ COLLECTION::ITERATOR iterator (collection_);
+
+ for (COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("collection acquiring %s\n"),
+ temp->int_id_->name ()));
+ // We will fail if _any_ token is not free.
+ if (temp->int_id_->tryacquire (sleep_hook) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Token_Collection::renew (int requeue_position,
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Token_Collection::renew");
+
+ COLLECTION::ITERATOR iterator (collection_);
+
+ for (COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("collection renewing %s\n"),
+ temp->int_id_->name ()));
+ if (temp->int_id_->renew (requeue_position, options) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Token_Collection::renew (const ACE_TCHAR *token_name,
+ int requeue_position,
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Token_Collection::renew");
+ TOKEN_NAME name (token_name);
+ ACE_Token_Proxy *temp;
+
+ // Get the token from the collection.
+ int result = collection_.find (name, temp);
+
+ // Did we find it?
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG, ACE_TEXT ("%p %s\n"),
+ ACE_TEXT ("not in collection "),
+ token_name), -1);
+ // perform the operation
+ return temp->renew (requeue_position, options);
+}
+
+int
+ACE_Token_Collection::release (ACE_Synch_Options &)
+
+{
+ ACE_TRACE ("ACE_Token_Collection::release");
+ COLLECTION::ITERATOR iterator (collection_);
+
+ for (COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (debug_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("collection releasing %s\n"),
+ temp->int_id_->name ()));
+ temp->int_id_->release ();
+ }
+
+ return 0;
+}
+
+int
+ACE_Token_Collection::release (const ACE_TCHAR *token_name,
+ ACE_Synch_Options &options)
+{
+ ACE_TRACE ("ACE_Token_Collection::release");
+ TOKEN_NAME name (token_name);
+ ACE_Token_Proxy *temp;
+ // get the token from the collection
+ int result = collection_.find (name, temp);
+ // did we find it?
+ if (result != 0)
+ return result;
+ // perform the operation
+ return temp->release (options);
+}
+
+ACE_Token_Collection::~ACE_Token_Collection (void)
+{
+ ACE_TRACE ("ACE_Token_Collection::~ACE_Token_Collection");
+ COLLECTION::ITERATOR iterator (collection_);
+
+ for (COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ delete temp->int_id_;
+ // The ext_id_'s delete themselves when the array of
+ // COLLECTION::ENTRYs goes away.
+ }
+}
+
+
+// This method doesn't mean anything for a collection.
+ACE_Token_Proxy *
+ACE_Token_Collection::clone (void) const
+{
+ ACE_TRACE ("ACE_Token_Collection::clone");
+ return (ACE_Token_Proxy *) 0;
+}
+
+// This method doesn't mean anything for a collection.
+ACE_Tokens *
+ACE_Token_Collection::create_token (const ACE_TCHAR *)
+{
+ ACE_TRACE ("ACE_Token_Collection::create_token");
+ return (ACE_Tokens *) 0;
+}
+
+void
+ACE_Token_Collection::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Token_Collection::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Token_Collection::dump:\n")
+ ACE_TEXT (" debug_ = %d\n"), debug_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("collection_\n")));
+ collection_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("base:\n")));
+ ACE_Token_Proxy::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Token_Collection.h b/ACE/ace/Token_Collection.h
new file mode 100644
index 00000000000..fa91532aaa6
--- /dev/null
+++ b/ACE/ace/Token_Collection.h
@@ -0,0 +1,243 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Token_Collection.h
+ *
+ * $Id$
+ *
+ * The ACE_Token class offers methods for acquiring, renewing,
+ * and releasing a synchronization token on a per-token basis. The
+ * ACE_Token_Collection offers an interface for performing
+ * operations on groups of tokens as a whole, or on a single token
+ * within the collection.
+ *
+ * The atomic group operations are not yet implemented.
+ *
+ *
+ * @author Douglas C. Schmidt (schmidt@cs.wustl.edu)
+ * @author Tim Harrison (harrison@cs.wustl.edu)
+ */
+//=============================================================================
+
+#ifndef ACE_TOKEN_COLLECTION_H
+#define ACE_TOKEN_COLLECTION_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Map_Manager.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#include "ace/Local_Tokens.h"
+#include "ace/Null_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Token_Collection
+ *
+ * @brief Allows atomic token group operations AND
+ * provides a ACE_Token manager interface.
+ *
+ * There are two types of operations offered by
+ * ACE_Token_Collection. The first is atomic operations on
+ * collections of Token_Proxies. In this respect, the
+ * ACE_Token_Collection can be thought of as a single token
+ * consisting of multiple Token_Proxies. The second role of the
+ * ACE_Token_Collection is as a ACE_Token manager.
+ * ACE_Token_Collection allows individual operations on single
+ * members of a collection of Token_Proxies. This provides a
+ * single access point for operations on multiple tokens.
+ *
+ * @bug Although ACE_Token_Collection inherits from ACE_Token_Proxy, it
+ * can not be including in a collection. This is because <clone>
+ * returns zero for now.
+ *
+ */
+class ACE_Export ACE_Token_Collection : public ACE_Token_Proxy
+{
+public:
+ /**
+ * @a debug print out verbose debugging messages. @a name will give a
+ * name to the collection. Collections don't really need names, but
+ * are sometimes useful for debugging.
+ */
+ ACE_Token_Collection (bool debug = false,
+ const ACE_TCHAR *name = 0);
+
+// Collection Management operations
+
+ /**
+ * Insert a Token into the collection. All ACE_Token type
+ * operations performed on the collection will also be performed on
+ * the new_proxy until it is removed. Note that no operations
+ * performed prior to the insertion will be performed. Returns: 0
+ * on success, -1 on failure with @c errno == problem. If a token
+ * proxy already exists in the collection with the same name, the
+ * insertion will fail. Also, <token> is copied. Note that during
+ * the copy, client_id's are *not* inherited. The client ID of the
+ * thread using the collection will be used. Client ID's can be
+ * changed explicity on each proxy using is_member.
+ */
+ int insert (ACE_Token_Proxy &token);
+
+ /**
+ * Removes the ACE_Token matching the given token_name from the
+ * collection. On success, extract returns 0. On failure
+ * (token_name was not in the collection,) extract returns -1. On
+ * success, the state of the token found is copied into proxy.
+ * The returned ACE_Token_Proxy* must be deleted by the user.
+ */
+ int extract (const ACE_TCHAR *token_name, ACE_Token_Proxy *&proxy);
+
+ /// Returns the proxy if true. 0 otherwise.
+ ACE_Token_Proxy *is_member (const ACE_TCHAR *token_name);
+
+ /**
+ * Is the specified token in the collection?
+ * 1, yes.
+ * 0, no.
+ */
+ int is_member (const ACE_Token_Proxy &token);
+
+// = Collective operation semantics.
+
+// For acquire, renew, and release, there are two interfaces. Once
+// interface allows an operation on a single token in the
+// collection. The collective interfaces perform atomic operations
+// on the entire collection. For instance, a collective acquire
+// will perform an acquire for each and every token in the
+// collection or the operation will fail. Currently, these
+// operations are performed with no ordering heuristics. That is,
+// the Collection steps through the tokens in the order they were
+// inserted. For each one it performs the operation (acquire,
+// renew, or release).
+
+ /**
+ * Acquire "atomically" all resources in the collection. This is
+ * only successfull if all tokens in the collection could be
+ * acquired. options contains the blocking semantics, timeout
+ * value, etc. Returns: 0 on success, -1 on failure with @c errno ==
+ * problem. If and error or deadlock occurs for one of the tokens,
+ * all the tokens will be released and the method will return -1.
+ * Note that returning on detection of deadlock prevents livelock
+ * between competing collections. If a collection returns after
+ * detecting deadlock, it is the application's responsibility to not
+ * to blindly loop on the collection::acquire operation. In other
+ * words, once the collection reports deadlock, it is out of our
+ * hands.
+ */
+ virtual int acquire (int notify = 0,
+ void (*sleep_hook)(void *) = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /// Acquire the token corresponding to @a token_name. The other
+ /// parameters are passed to <token>::acquire.
+ virtual int acquire (const ACE_TCHAR *token_name,
+ int notify = 0,
+ void (*sleep_hook)(void *) = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /// Try to acquire all tokens in collection.
+ virtual int tryacquire (void (*sleep_hook)(void *) = 0);
+
+ /// Try to acquire @a token_name.
+ virtual int tryacquire (const ACE_TCHAR *token_name,
+ void (*sleep_hook)(void *) = 0);
+
+ /**
+ * Renews "atomically" all resources in the collection. This is
+ * only successfull if all tokens in the collection could be
+ * renewed. options contains the blocking semantics, timeout
+ * value, etc. Returns: 0 on success, -1 on failure with @c errno ==
+ * problem.
+ */
+ virtual int renew (int requeue_position = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+
+ /// Renew the token corresponding to @a token_name. The other
+ /// parameters are passed to <token>::renew.
+ virtual int renew (const ACE_TCHAR *token_name,
+ int requeue_position = 0,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ /**
+ * Releases "atomically" all resources in the collection. This is
+ * only successfull if all tokens in the collection could be
+ * released. options contains the blocking semantics, timeout
+ * value, etc. Returns: 0 on success, -1 on failure with @c errno ==
+ * problem.
+ */
+ virtual int release (ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+
+ /// Release the token corresponding to <token_name>. The other
+ /// parameters are passed to <token>::release.
+ virtual int release (const ACE_TCHAR *token_name,
+ ACE_Synch_Options &options =
+ ACE_Synch_Options::defaults);
+
+ ~ACE_Token_Collection (void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Return the name of the collection. Not very functionally
+ /// important, but sometimes a useful debugging tool.
+ virtual const ACE_TCHAR *name (void) const;
+
+protected:
+
+ typedef ACE_Token_Name TOKEN_NAME;
+
+ /// COLLECTION maintains a mapping from token names to ACE_Tokens*
+ typedef ACE_Map_Manager<TOKEN_NAME, ACE_Token_Proxy *, ACE_Null_Mutex>
+ COLLECTION;
+
+ /// Allows iterations through collection_
+ /**
+ * @deprecated Deprecated typedef. Use COLLECTION::ITERATOR trait instead.
+ */
+ typedef COLLECTION::ITERATOR COLLECTION_ITERATOR;
+
+ /// Allows iterations through collection_
+ /**
+ * @deprecated Deprecated typedef. Use COLLECTION::ENTRY trait instead.
+ */
+ typedef COLLECTION::ENTRY COLLECTION_ENTRY;
+
+ /// COLLECTION maintains a mapping from token names to ACE_Tokens*.
+ COLLECTION collection_;
+
+ /// Whether to print out debug messages or not.
+ bool debug_;
+
+ /// Name of the collection.
+ ACE_TCHAR name_[ACE_MAXTOKENNAMELEN];
+
+ // = I'm not sure what these mean, but they have to be defined since they're
+ // pure virtual in ACE_Token_Proxy.
+ virtual ACE_Token_Proxy *clone (void) const;
+ virtual ACE_Tokens *create_token (const ACE_TCHAR *name);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Token_Collection.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TOKEN_COLLECTION_H */
diff --git a/ACE/ace/Token_Collection.inl b/ACE/ace/Token_Collection.inl
new file mode 100644
index 00000000000..db86701a325
--- /dev/null
+++ b/ACE/ace/Token_Collection.inl
@@ -0,0 +1,17 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Token_Collection::name (void) const
+{
+ return name_;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Token_Invariants.cpp b/ACE/ace/Token_Invariants.cpp
new file mode 100644
index 00000000000..fe411815dee
--- /dev/null
+++ b/ACE/ace/Token_Invariants.cpp
@@ -0,0 +1,355 @@
+#include "ace/Token_Invariants.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#include "ace/Object_Manager.h"
+
+ACE_RCSID (ace,
+ Token_Invariants,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Token_Invariant_Manager *ACE_Token_Invariant_Manager::instance_ = 0;
+
+ACE_Token_Invariant_Manager *
+ACE_Token_Invariant_Manager::instance (void)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::instance");
+
+ // Perform the Double-Check pattern...
+ if (instance_ == 0)
+ {
+ ACE_MT (ACE_TOKEN_CONST::MUTEX *lock =
+ ACE_Managed_Object<ACE_TOKEN_CONST::MUTEX>::get_preallocated_object
+ (ACE_Object_Manager::ACE_TOKEN_INVARIANTS_CREATION_LOCK);
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, *lock, 0));
+
+ if (instance_ == 0)
+ {
+ ACE_NEW_RETURN (instance_,
+ ACE_Token_Invariant_Manager,
+ 0);
+ // Register for destruction with ACE_Object_Manager.
+ ACE_Object_Manager::at_exit (instance_);
+ }
+ }
+
+ return instance_;
+}
+
+ACE_Token_Invariant_Manager::ACE_Token_Invariant_Manager (void)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::ACE_Token_Invariant_Manager");
+}
+
+int
+ACE_Token_Invariant_Manager::mutex_acquired (const ACE_TCHAR *token_name)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::mutex_acquired");
+
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
+
+ ACE_Mutex_Invariants *inv = 0;
+ if (this->get_mutex (token_name, inv) == -1)
+ return -1;
+
+ return inv->acquired ();
+}
+
+int
+ACE_Token_Invariant_Manager::acquired (const ACE_Token_Proxy *proxy)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::acquired");
+
+ // Reach into the proxy to find the token type.
+ if (proxy->token_->type () == ACE_Tokens::MUTEX)
+ return this->mutex_acquired (proxy->name ());
+ else // ACE_Tokens::RWLOCK.
+ {
+ if (proxy->type () == ACE_RW_Token::READER)
+ return this->reader_acquired (proxy->name ());
+ else // ACE_RW_Token::WRITER.
+ return this->writer_acquired (proxy->name ());
+ }
+}
+
+void
+ACE_Token_Invariant_Manager::releasing (const ACE_Token_Proxy *proxy)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::releasing");
+
+ // Reach into the proxy to find the token type.
+ if (proxy->token_->type () == ACE_Tokens::MUTEX)
+ this->mutex_releasing (proxy->name ());
+ else // ACE_Tokens::RWLOCK.
+ this->rwlock_releasing (proxy->name ());
+}
+
+void
+ACE_Token_Invariant_Manager::mutex_releasing (const ACE_TCHAR *token_name)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::mutex_releasing");
+ ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_);
+
+ ACE_Mutex_Invariants *inv = 0;
+ if (this->get_mutex (token_name, inv) == 0)
+ inv->releasing ();
+}
+
+int
+ACE_Token_Invariant_Manager::reader_acquired (const ACE_TCHAR *token_name)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::reader_acquired");
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
+
+ ACE_RWLock_Invariants *inv = 0;
+ if (this->get_rwlock (token_name, inv) == -1)
+ return -1;
+
+ return inv->reader_acquired ();
+}
+
+int
+ACE_Token_Invariant_Manager::writer_acquired (const ACE_TCHAR *token_name)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::writer_acquired");
+
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
+
+ ACE_RWLock_Invariants *inv = 0;
+ if (this->get_rwlock (token_name, inv) == -1)
+ return -1;
+
+ return inv->writer_acquired ();
+}
+
+void
+ACE_Token_Invariant_Manager::rwlock_releasing (const ACE_TCHAR *token_name)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::rwlock_releasing");
+
+ ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_);
+
+ ACE_RWLock_Invariants *inv = 0;
+ if (this->get_rwlock (token_name, inv) == 0)
+ inv->releasing ();
+}
+
+void
+ACE_Token_Invariant_Manager::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Token_Invariant_Manager::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("mutex_collection_:\n")));
+ mutex_collection_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("rwlock_collection_:\n")));
+ rwlock_collection_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+
+int
+ACE_Token_Invariant_Manager::get_mutex (const ACE_TCHAR *token_name,
+ ACE_Mutex_Invariants *&inv)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::get_mutex");
+ TOKEN_NAME name (token_name);
+ if (mutex_collection_.find (name, inv) == -1)
+ // We did not find one in the collection.
+ {
+ ACE_Mutex_Invariants *new_invariant;
+
+ ACE_NEW_RETURN (new_invariant,
+ ACE_Mutex_Invariants,
+ -1);
+ if (mutex_collection_.bind (name, new_invariant) == -1)
+ {
+ delete new_invariant;
+ return -1;
+ }
+
+ if (mutex_collection_.find (name, inv) == -1)
+ // We did not find one in the collection.
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Token_Invariant_Manager::get_rwlock (const ACE_TCHAR *token_name,
+ ACE_RWLock_Invariants *&inv)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::get_rwlock");
+ TOKEN_NAME name (token_name);
+ if (rwlock_collection_.find (name, inv) == -1)
+ // We did not find one in the collection.
+ {
+ ACE_RWLock_Invariants *new_invariant;
+
+ ACE_NEW_RETURN (new_invariant,
+ ACE_RWLock_Invariants,
+ -1);
+ if (rwlock_collection_.bind (name, new_invariant) == -1)
+ return -1;
+
+ if (rwlock_collection_.find (name, inv) == -1)
+ // We did not find one in the collection.
+ return -1;
+ }
+
+ return 0;
+}
+
+
+ACE_Token_Invariant_Manager::~ACE_Token_Invariant_Manager (void)
+{
+ ACE_TRACE ("ACE_Token_Invariant_Manager::~ACE_Token_Invariant_Manager");
+
+ MUTEX_COLLECTION::ITERATOR iterator (mutex_collection_);
+
+ for (MUTEX_COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ delete temp->int_id_;
+
+ RWLOCK_COLLECTION::ITERATOR iterator2 (rwlock_collection_);
+
+ for (RWLOCK_COLLECTION::ENTRY *temp2 = 0;
+ iterator2.next (temp2) != 0;
+ iterator2.advance ())
+ delete temp2->int_id_;
+}
+
+// **************************************************
+// **************************************************
+// **************************************************
+
+ACE_Mutex_Invariants::ACE_Mutex_Invariants (void)
+: owners_ (0)
+{
+}
+
+int
+ACE_Mutex_Invariants::acquired (void)
+{
+ if (++owners_ > 1)
+ {
+ owners_ = 42;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+void
+ACE_Mutex_Invariants::releasing (void)
+{
+ if (owners_ == 1)
+ --owners_;
+}
+
+ACE_Mutex_Invariants::ACE_Mutex_Invariants (const ACE_Mutex_Invariants &rhs)
+: owners_ (rhs.owners_)
+{
+}
+
+void
+ACE_Mutex_Invariants::operator= (const ACE_Mutex_Invariants &rhs)
+{
+ owners_ = rhs.owners_;
+}
+
+void
+ACE_Mutex_Invariants::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Mutex_Invariants::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("owners_ = %d\n"), owners_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// **************************************************
+// **************************************************
+// **************************************************
+
+ACE_RWLock_Invariants::ACE_RWLock_Invariants (void)
+: writers_ (0),
+ readers_ (0)
+{
+}
+
+int
+ACE_RWLock_Invariants::writer_acquired (void)
+{
+ if (readers_ > 0)
+ {
+ writers_ = readers_ = 42;
+ return 0;
+ }
+ else if (++writers_ > 1)
+ {
+ writers_ = readers_ = 42;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+int
+ACE_RWLock_Invariants::reader_acquired (void)
+{
+ if (writers_ > 0)
+ {
+ writers_ = readers_ = 42;
+ return 0;
+ }
+ else
+ {
+ ++readers_;
+ return 1;
+ }
+}
+
+void
+ACE_RWLock_Invariants::releasing (void)
+{
+ if (writers_ == 1)
+ writers_ = 0;
+ else if (readers_ > 0)
+ --readers_;
+}
+
+ACE_RWLock_Invariants::ACE_RWLock_Invariants (const ACE_RWLock_Invariants &rhs)
+: writers_ (rhs.writers_),
+ readers_ (rhs.readers_)
+{
+}
+
+void
+ACE_RWLock_Invariants::operator= (const ACE_RWLock_Invariants &rhs)
+{
+ writers_ = rhs.writers_;
+ readers_ = rhs.readers_;
+}
+
+void
+ACE_RWLock_Invariants::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_RWLock_Invariants::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("writers_ = %d readers_ = %d\n"),
+ writers_, readers_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Token_Invariants.h b/ACE/ace/Token_Invariants.h
new file mode 100644
index 00000000000..8bc294106ed
--- /dev/null
+++ b/ACE/ace/Token_Invariants.h
@@ -0,0 +1,245 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Token_Invariants.h
+ *
+ * $Id$
+ *
+ * @author Tim Harrison (harrison@cs.wustl.edu)
+ *
+ * Allows applications to test that invariants are always
+ * satisfied. Can test mutexes and readers/writer locks. Does
+ * not test recursive acquisition.
+ *
+ *
+ */
+//=============================================================================
+
+#ifndef ACE_TOKEN_INVARIANTS_H
+#define ACE_TOKEN_INVARIANTS_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_HAS_TOKENS_LIBRARY)
+
+#include "ace/Map_Manager.h"
+#include "ace/Local_Tokens.h"
+#include "ace/Null_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Mutex_Invariants
+ *
+ * @brief Mutex Invariants
+ * = INVARIANTS
+ * 1. Only one owner at a time.
+ */
+class ACE_Export ACE_Mutex_Invariants
+{
+public:
+ /// Default construction.
+ ACE_Mutex_Invariants (void);
+
+ /// Returns 1 on success, 0 when an invariant has been violated and
+ /// -1 on error.
+ int acquired (void);
+
+ /// Updates internal database.
+ void releasing (void);
+
+ // = Map_Manager operations.
+
+ /// Copy construction.
+ ACE_Mutex_Invariants (const ACE_Mutex_Invariants &rhs);
+
+ /// Copy.
+ void operator= (const ACE_Mutex_Invariants &rhs);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+private:
+ /// Number of owners. This had better be 0 >= owners_ <= 1;
+ int owners_;
+};
+
+/**
+ * @class ACE_RWLock_Invariants
+ *
+ * @brief RWLock Invariants
+ *
+ * Preserve the following invariants:
+ * -# Only one writer at a time.
+ * -# If there is an owning writer, there are no owning readers.
+ */
+class ACE_Export ACE_RWLock_Invariants
+{
+public:
+ /// Default construction.
+ ACE_RWLock_Invariants (void);
+
+ /// Returns 1 on success, 0 when an invariant has been violated and
+ /// -1 on error.
+ int writer_acquired (void);
+
+ /// Returns 1 on success, 0 when an invariant has been violated and
+ /// -1 on error.
+ int reader_acquired (void);
+
+ /// Updates internal database.
+ void releasing (void);
+
+ // = Map_Manager operations.
+
+ /// Copy construction.
+ ACE_RWLock_Invariants (const ACE_RWLock_Invariants &rhs);
+
+ /// Copy.
+ void operator= (const ACE_RWLock_Invariants &rhs);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+private:
+ /// Number of owning writers.
+ int writers_;
+
+ /// Number of owning readers.
+ int readers_;
+};
+
+/**
+ * @class ACE_Token_Invariant_Manager
+ *
+ * @brief Token Invariants
+ *
+ * The Token Invariant Manager allows applications to test that
+ * invariants are always satisfied. Currently, Token_Invariants
+ * can test mutexes and readers/writer locks. Does not test
+ * recursive acquisition.
+ * Note that this class does not ever clean its database. Until
+ * destroyed, it's size will forever increase.
+ */
+class ACE_Export ACE_Token_Invariant_Manager : public ACE_Cleanup
+{
+public:
+
+ /// Singleton access point.
+ static ACE_Token_Invariant_Manager *instance (void);
+
+ // = Polymorphic methods. Just pass in the proxy and the method
+ // figures out the type of the token.
+
+ /// Returns 1 on success, 0 when an invariant has been violated and
+ /// -1 on error.
+ int acquired (const ACE_Token_Proxy *proxy);
+
+ /// Updates internal database.
+ void releasing (const ACE_Token_Proxy *proxy);
+
+ // = Explicit methods. These to not require actual proxies in order
+ // to test a scenario.
+
+ /// Returns 1 on success, 0 when an invariant has been violated and
+ /// -1 on error.
+ int mutex_acquired (const ACE_TCHAR *token_name);
+
+ /// Updates internal database.
+ void mutex_releasing (const ACE_TCHAR *token_name);
+
+ /// Returns 1 on success, 0 when an invariant has been violated and
+ /// -1 on error.
+ int reader_acquired (const ACE_TCHAR *token_name);
+
+ /// Returns 1 on success, 0 when an invariant has been violated and
+ /// -1 on error.
+ int writer_acquired (const ACE_TCHAR *token_name);
+
+ /// Updates internal database.
+ void rwlock_releasing (const ACE_TCHAR *token_name);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ // = The following two method should be in the protected part of the
+ // class. Bugs with certain compilers preclude this.
+ /// Prevent non-singleton construction.
+ ACE_Token_Invariant_Manager (void);
+
+ /// Destruction.
+ virtual ~ACE_Token_Invariant_Manager (void);
+
+protected:
+ /// Return or create.
+ int get_mutex (const ACE_TCHAR *token_name,
+ ACE_Mutex_Invariants *&inv);
+
+ /// Return or create.
+ int get_rwlock (const ACE_TCHAR *token_name,
+ ACE_RWLock_Invariants *&inv);
+
+ /// ACE_Mutex_Token used to lock internal data structures.
+ ACE_TOKEN_CONST::MUTEX lock_;
+
+ /// This may be changed to a template type.
+ typedef ACE_Token_Name TOKEN_NAME;
+
+ /// COLLECTION maintains a mapping from token names to mutexes.
+ typedef ACE_Map_Manager<TOKEN_NAME, ACE_Mutex_Invariants *, ACE_Null_Mutex>
+ MUTEX_COLLECTION;
+
+ /// Allows iterations through collection.
+ /**
+ * @deprecated Deprecated typedef. Use MUTEX_COLLECTION::ITERATOR trait
+ * instead.
+ */
+ typedef MUTEX_COLLECTION::ITERATOR MUTEX_COLLECTION_ITERATOR;
+
+ /// Allows iterations through collection.
+ /**
+ * @deprecated Deprecated typedef. Use MUTEX_COLLECTION::ENTRY trait
+ * instead.
+ */
+ typedef MUTEX_COLLECTION::ENTRY MUTEX_COLLECTION_ENTRY;
+
+ /// MUTEX_COLLECTION maintains a mapping from token names to mutexes.
+ MUTEX_COLLECTION mutex_collection_;
+
+ /// COLLECTION maintains a mapping from token names to mutexes.
+ typedef ACE_Map_Manager<TOKEN_NAME, ACE_RWLock_Invariants *, ACE_Null_Mutex>
+ RWLOCK_COLLECTION;
+
+ /// Allows iterations through collection.
+ /**
+ * @deprecated Deprecated typedef. Use RWLOCK_COLLECTION::ITERATOR trait
+ * instead.
+ */
+ typedef RWLOCK_COLLECTION::ITERATOR RWLOCK_COLLECTION_ITERATOR;
+
+ /// Allows iterations through collection.
+ /**
+ * @deprecated Deprecated typedef. Use RWLOCK_COLLECTION::ENTRY trait
+ * instead.
+ */
+ typedef RWLOCK_COLLECTION::ENTRY RWLOCK_COLLECTION_ENTRY;
+
+ /// MUTEX_COLLECTION maintains a mapping from token names to mutexes.
+ RWLOCK_COLLECTION rwlock_collection_;
+
+ /// Singleton pointer.
+ static ACE_Token_Invariant_Manager *instance_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TOKEN_INVARIANTS_H */
diff --git a/ACE/ace/Token_Manager.cpp b/ACE/ace/Token_Manager.cpp
new file mode 100644
index 00000000000..0bc2a276494
--- /dev/null
+++ b/ACE/ace/Token_Manager.cpp
@@ -0,0 +1,273 @@
+#include "ace/Token_Manager.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#include "ace/Object_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Token_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ace,
+ Token_Manager,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// singleton token manager
+ACE_Token_Manager *ACE_Token_Manager::token_manager_ = 0;
+
+ACE_Token_Manager::ACE_Token_Manager ()
+{
+ ACE_TRACE ("ACE_Token_Manager::ACE_Token_Manager");
+}
+
+ACE_Token_Manager::~ACE_Token_Manager ()
+{
+ ACE_TRACE ("ACE_Token_Manager::~ACE_Token_Manager");
+
+ COLLECTION::ITERATOR iterator (collection_);
+
+ for (COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ // @ should I be doing an unbind here?
+ delete temp->int_id_;
+ // The ext_id_'s delete themselves when the array of
+ // COLLECTION::ENTRYs goes away.
+ }
+}
+
+ACE_Token_Manager *
+ACE_Token_Manager::instance (void)
+{
+ ACE_TRACE ("ACE_Token_Manager::instance");
+
+ // This first check is to avoid acquiring the mutex in the common
+ // case. Double-Check pattern rules.
+ if (token_manager_ == 0)
+ {
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_TOKEN_CONST::MUTEX *lock =
+ ACE_Managed_Object<ACE_TOKEN_CONST::MUTEX>::get_preallocated_object
+ (ACE_Object_Manager::ACE_TOKEN_MANAGER_CREATION_LOCK);
+ ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, *lock, 0);
+#endif /* ACE_MT_SAFE */
+
+ if (token_manager_ == 0)
+ {
+ ACE_NEW_RETURN (token_manager_,
+ ACE_Token_Manager,
+ 0);
+ // Register for destruction with ACE_Object_Manager.
+ ACE_Object_Manager::at_exit (token_manager_);
+ }
+ }
+
+ return token_manager_;
+}
+
+void
+ACE_Token_Manager::get_token (ACE_Token_Proxy *proxy,
+ const ACE_TCHAR *token_name)
+{
+ ACE_TRACE ("ACE_Token_Manager::get_token");
+ // Hmm. I think this makes sense. We perform our own locking here
+ // (see safe_acquire.) We have to make sure that only one thread
+ // uses the collection at a time.
+
+ ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_);
+
+ TOKEN_NAME name (token_name);
+
+ if (collection_.find (name, proxy->token_) == -1)
+ // We did not find one in the collection.
+ {
+ // Make one.
+ proxy->token_ = proxy->create_token (token_name);
+
+ // Put it in the collection.
+ if (collection_.bind (name, proxy->token_) == -1)
+ {
+ delete proxy->token_;
+ proxy->token_ = 0;
+ }
+ }
+
+ if (proxy->token_ != 0)
+ proxy->token_->inc_reference ();
+
+ // We may be returning proxy->token_ == 0 if new failed, caller must
+ // check.
+}
+
+// 0. check_deadlock (TOKEN)
+// 1. if TOKEN->visited (), return 0.
+// 2. mark TOKEN visited.
+// 3. get ALL_OWNERS
+// 4. if CLIENT in ALL_OWNERS, return *DEADLOCK*.
+// 5. for each OWNER in ALL_OWNERS,
+// 6. if OWNER is not waiting for a NEW_TOKEN, continue.
+// 7. else, if check_deadlock (NEW_TOKEN) == 1, return *DEADLOCK*
+// 8. return 0.
+
+int
+ACE_Token_Manager::check_deadlock (ACE_Token_Proxy *proxy)
+{
+ ACE_TRACE ("ACE_Token_Manager::check_deadlock");
+
+ // Start the recursive deadlock detection algorithm.
+ int result = this->check_deadlock (proxy->token_, proxy);
+
+ // Whether or not we detect deadlock, we have to unmark all tokens
+ // for the next time.
+ COLLECTION::ITERATOR iterator (collection_);
+ for (COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ temp->int_id_->visit (0);
+
+ return result;
+}
+
+int
+ACE_Token_Manager::check_deadlock (ACE_Tokens *token, ACE_Token_Proxy *proxy)
+{
+ ACE_TRACE ("ACE_Token_Manager::check_deadlock");
+
+ if (token->visited ())
+ return 0;
+
+ token->visit (1);
+
+ ACE_Tokens::OWNER_STACK owners;
+
+ int is_owner = token->owners (owners, proxy->client_id ());
+
+ switch (is_owner)
+ {
+ case -1:
+ // Error.
+ return -1;
+ case 1:
+ // The caller is an owner, so we have a deadlock situation.
+ if (debug_)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Deadlock detected.\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%s owns %s and is waiting for %s.\n"),
+ proxy->client_id (),
+ token->name (),
+ proxy->token_->name ()));
+ }
+
+ return 1;
+ case 0:
+ default:
+ // Recurse on each owner.
+ while (!owners.is_empty ())
+ {
+ ACE_TPQ_Entry *e;
+ owners.pop (e);
+ // If the owner is waiting on another token, recurse.
+ ACE_Tokens *twf = this->token_waiting_for (e->client_id ());
+ if ((twf != 0) &&
+ (this->check_deadlock (twf, proxy) == 1))
+ {
+ if (debug_)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%s owns %s and is waiting for %s.\n"),
+ e->client_id (),
+ token->name (),
+ twf->name ()));
+ }
+ return 1;
+ }
+ // else, check the next owner.
+ }
+
+ // We've checked all the owners and found no deadlock.
+ return 0;
+ }
+}
+
+
+ACE_Tokens *
+ACE_Token_Manager::token_waiting_for (const ACE_TCHAR *client_id)
+{
+ COLLECTION::ITERATOR iterator (collection_);
+ for (COLLECTION::ENTRY *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ if (temp->int_id_->is_waiting_for (client_id))
+ return temp->int_id_;
+ }
+
+ // nothing was found, return NULL.
+ return 0;
+}
+
+// Notify the token manager that a token is has been released. If
+// as a result, there is no owner of the token, the token is
+// deleted.
+void
+ACE_Token_Manager::release_token (ACE_Tokens *&token)
+{
+ ACE_TRACE ("ACE_Token_Manager::release_token");
+ // again, let's perform our own locking here.
+
+ ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_);
+
+ if (token->dec_reference () == 0)
+ {
+ // No one has the token, so we can delete it and remove it from
+ // our collection. First, let's get it from the collection.
+ TOKEN_NAME token_name (token->name ());
+
+ ACE_Tokens *temp;
+
+ if (collection_.unbind (token_name, temp) == -1)
+ // we did not find one in the collection
+ {
+ errno = ENOENT;
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("Token Manager could not release %s:%d\n"),
+ token->name (), token->type ()));
+ // @@ bad
+ }
+ else
+ // we found it
+ {
+ // sanity pointer comparison. The token referenced by the
+ // proxy better be the one we found in the list.
+ ACE_ASSERT (token == temp);
+ delete token; // or delete temp
+ // we set their token to zero. if the calling proxy is
+ // still going to be used, it had better check it's token
+ // value before calling a method on it!
+ token = 0;
+ }
+ }
+ // else
+ // someone is still interested in the token, so keep it around.
+}
+
+void
+ACE_Token_Manager::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Token_Manager::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Token_Manager::dump:\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("lock_\n")));
+ lock_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("collection_\n")));
+ collection_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Token_Manager.h b/ACE/ace/Token_Manager.h
new file mode 100644
index 00000000000..619fa418d20
--- /dev/null
+++ b/ACE/ace/Token_Manager.h
@@ -0,0 +1,150 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Token_Manager.h
+ *
+ * $Id$
+ *
+ * @author Tim Harrison (harrison@cs.wustl.edu)
+ */
+//=============================================================================
+
+#ifndef ACE_TOKEN_MANAGER_H
+#define ACE_TOKEN_MANAGER_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/Local_Tokens.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#include "ace/Null_Mutex.h"
+#include "ace/Map_Manager.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Local_Mutex;
+class ACE_Mutex_Token;
+
+/**
+ * @class ACE_Token_Manager
+ *
+ * @brief Manages all tokens in a process space.
+ *
+ * Factory: Proxies use the token manager to obtain token
+ * references. This allows multiple proxies to reference the same
+ * logical token.
+ * Deadlock detection: Tokens use the manager to check for
+ * deadlock situations during acquires.
+ */
+class ACE_Export ACE_Token_Manager : public ACE_Cleanup
+{
+
+ // To add a new type of token (e.g. semaphore), do the following
+ // steps: 1. Create a new derivation of ACE_Token. This class
+ // defines the semantics of the new Token. 2. Create a
+ // derivation of ACE_Token_Manager. You will only need to
+ // redefine make_mutex.
+public:
+ ACE_Token_Manager (void);
+ virtual ~ACE_Token_Manager (void);
+
+ /// Get the pointer to token manager singleton.
+ static ACE_Token_Manager *instance (void);
+
+ /// Set the pointer to token manager singleton.
+ void instance (ACE_Token_Manager *);
+
+ /**
+ * The Token manager uses ACE_Token_Proxy::token_id_ to look for
+ * an existing token. If none is found, the Token Manager calls
+ * ACE_Token_Proxy::create_token to create a new one. When
+ * finished, sets ACE_Token_Proxy::token_. @a token_name uniquely
+ * id's the token name.
+ */
+ void get_token (ACE_Token_Proxy *, const ACE_TCHAR *token_name);
+
+ /**
+ * Check whether acquire will cause deadlock or not.
+ * returns 1 if the acquire will _not_ cause deadlock.
+ * returns 0 if the acquire _will_ cause deadlock.
+ * This method ignores recursive acquisition. That is, it will not
+ * report deadlock if the client holding the token requests the
+ * token again. Thus, it assumes recursive mutexes.
+ */
+ int check_deadlock (ACE_Token_Proxy *proxy);
+ int check_deadlock (ACE_Tokens *token, ACE_Token_Proxy *proxy);
+
+ /// Notify the token manager that a token has been released. If as a
+ /// result, there is no owner of the token, the token is deleted.
+ void release_token (ACE_Tokens *&token);
+
+ /**
+ * This is to allow Tokens to perform atomic transactions. The
+ * typical usage is to acquire this mutex, check for a safe_acquire,
+ * perform some queueing (if need be) and then release the lock.
+ * This is necessary since safe_acquire is implemented in terms of
+ * the Token queues.
+ */
+ ACE_TOKEN_CONST::MUTEX &mutex (void);
+
+ /// Dump the state of the class.
+ void dump (void) const;
+
+ /// Turn debug mode on/off.
+ void debug (bool d);
+
+private:
+ /// Whether to print debug messages or not.
+ bool debug_;
+
+ /// pointer to singleton token manager.
+ static ACE_Token_Manager *token_manager_;
+
+ /// Return the token that the given client_id is waiting for, if any
+ ACE_Tokens *token_waiting_for (const ACE_TCHAR *client_id);
+
+ /// ACE_Mutex_Token used to lock internal data structures.
+ ACE_TOKEN_CONST::MUTEX lock_;
+
+ /// This may be changed to a template type.
+ typedef ACE_Token_Name TOKEN_NAME;
+
+ /// COLLECTION maintains a mapping from token names to ACE_Tokens*
+ typedef ACE_Map_Manager<TOKEN_NAME, ACE_Tokens *, ACE_Null_Mutex>
+ COLLECTION;
+
+ /// Allows iterations through collection_
+ /**
+ * @deprecated Deprecated typedef. Use COLLECTION::ITERATOR trait
+ * instead.
+ */
+ typedef COLLECTION::ITERATOR COLLECTION_ITERATOR;
+
+ /// Allows iterations through collection_
+ /**
+ * @deprecated Deprecated typedef. Use COLLECTION::ENTRY trait
+ * instead.
+ */
+ typedef COLLECTION::ENTRY COLLECTION_ENTRY;
+
+ /// COLLECTION maintains a mapping from token names to ACE_Tokens*.
+ COLLECTION collection_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Token_Manager.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TOKEN_MANAGER_H */
diff --git a/ACE/ace/Token_Manager.inl b/ACE/ace/Token_Manager.inl
new file mode 100644
index 00000000000..b779b57b9de
--- /dev/null
+++ b/ACE/ace/Token_Manager.inl
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_TOKEN_CONST::MUTEX &
+ACE_Token_Manager::mutex (void)
+{
+ ACE_TRACE ("ACE_Token_Manager::mutex");
+ return lock_;
+}
+
+ACE_INLINE void
+ACE_Token_Manager::debug (bool d)
+{
+ ACE_TRACE ("ACE_Token_Manager::debug");
+ debug_ = d;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Token_Request_Reply.cpp b/ACE/ace/Token_Request_Reply.cpp
new file mode 100644
index 00000000000..24c1098238f
--- /dev/null
+++ b/ACE/ace/Token_Request_Reply.cpp
@@ -0,0 +1,186 @@
+// $Id$
+
+#include "ace/Token_Request_Reply.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Token_Request_Reply.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Token_Request_Reply, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Default "do nothing" constructor.
+
+ACE_Token_Request::ACE_Token_Request (void)
+ : token_name_ (0),
+ client_id_ (0)
+{
+}
+
+// Create a ACE_Token_Request message.
+
+ACE_Token_Request::ACE_Token_Request (int token_type,
+ int proxy_type,
+ ACE_UINT32 operation_type,
+ const ACE_TCHAR token_name[],
+ const ACE_TCHAR client_id[],
+ const ACE_Synch_Options &options)
+{
+ this->token_type (token_type);
+ this->proxy_type (proxy_type);
+ this->operation_type (operation_type);
+ this->requeue_position (0); // to avoid Purify UMR
+ this->notify (0); // to avoid Purify UMR
+ transfer_.arg_ = 0; // to avoid Purify UMR
+ ACE_OS::memset (transfer_.data_, 0, sizeof transfer_.data_); // to avoid Purify UMR
+ this->token_name (token_name, client_id);
+ this->options (options);
+}
+
+// Encode the transfer buffer into network byte order
+// so that it can be sent to the server.
+
+int
+ACE_Token_Request::encode (void *&buf)
+{
+ buf = (void *) &this->transfer_;
+ return this->length ();
+}
+
+// Decode the transfer buffer into host byte byte order
+// so that it can be used by the server.
+
+int
+ACE_Token_Request::decode (void)
+{
+ this->token_name_ = this->transfer_.data_;
+
+ options_.set (transfer_.use_timeout_ == 1 ? ACE_Synch_Options::USE_TIMEOUT : 0,
+ ACE_Time_Value (transfer_.sec_, transfer_.usec_),
+ (void *) transfer_.arg_);
+
+ // Decode the variable-sized portion.
+ size_t token_len = ACE_OS::strlen (this->token_name_);
+
+ // Check to make sure this->tokenName_ isn't too long!
+ if (token_len >= ACE_MAXTOKENNAMELEN)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ else // Skip this->tokenName_ + '\0' + ':'.
+ this->client_id_ =
+ &this->token_name_[(token_len + 2) * sizeof (ACE_TCHAR)];
+
+ // Fixed size header
+ // token_name_ plus '\0'
+ // ':'
+ // client_id_ plus '\0'
+ size_t data_size = ACE_TOKEN_REQUEST_HEADER_SIZE
+ + ACE_OS::strlen (this->token_name_) + 1
+ + ACE_OS::strlen (this->client_id_) + 1
+ + 1;
+
+ // Make sure the message was correctly received and framed.
+ return this->length () == data_size ? 0 : -1;
+}
+
+// Print out the current values of the ACE_Token_Request.
+
+void
+ACE_Token_Request::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("*******\nlength = %d\ntoken name = %s\nclient id = %s\n"),
+ this->length (), this->token_name (), this->client_id ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("type = ")));
+
+ if (this->token_type () == ACE_Tokens::MUTEX)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("MUTEX\n")));
+ else // == ACE_Tokens::RWLOCK
+ {
+ if (this->proxy_type () == ACE_RW_Token::READER)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("RLOCK\n")));
+ else // == WRITER
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("WLOCK\n")));
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("operation = ")));
+ switch (this->operation_type ())
+ {
+ case ACE_Token_Request::ACQUIRE:
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACQUIRE\n")));
+ break;
+ case ACE_Token_Request::RELEASE:
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("RELEASE\n")));
+ break;
+ case ACE_Token_Request::RENEW:
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("RENEW\n")));
+ break;
+ default:
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("<unknown operation type> = %d\n"), this->operation_type ()));
+ break;
+ }
+
+ if (this->options ()[ACE_Synch_Options::USE_TIMEOUT] == 0)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("blocking forever\n")));
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("waiting for %d secs and %d usecs\n"),
+ this->options ().timeout ().sec (), this->options ().timeout ().usec ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+// ************************************************************
+// ************************************************************
+// ************************************************************
+
+// Create a ACE_Token_Reply message.
+
+ACE_Token_Reply::ACE_Token_Reply (void) // Type of reply.
+{
+ this->arg (0);
+ this->errnum (0);
+ this->length (sizeof (Transfer));
+}
+
+// Encode the transfer buffer into network byte order
+// so that it can be sent to the client.
+
+int
+ACE_Token_Reply::encode (void *&buf)
+{
+ buf = (void *) &this->transfer_;
+ return this->length ();
+}
+
+// Decode the transfer buffer into host byte order
+// so that it can be used by the client.
+
+int
+ACE_Token_Reply::decode (void)
+{
+ return 0;
+}
+
+// Print out current values of the ACE_Token_Reply object.
+
+void
+ACE_Token_Reply::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("*******\nlength = %d\nerrnum = %d"),
+ this->length (), this->errnum ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("arg = %d"), this->arg ()));
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Token_Request_Reply.h b/ACE/ace/Token_Request_Reply.h
new file mode 100644
index 00000000000..4341eb65cd5
--- /dev/null
+++ b/ACE/ace/Token_Request_Reply.h
@@ -0,0 +1,270 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Token_Request_Reply.h
+ *
+ * $Id$
+ *
+ * Define the format used to exchange messages between the
+ * ACE_Token Server and its clients.
+ *
+ *
+ * @author Douglas C. Schmidt (schmidt@cs.wustl.edu)
+ * @author Tim Harrison (harrison@cs.wustl.edu)
+ */
+//=============================================================================
+
+
+#ifndef ACE_TOKEN_REQUEST_REPLY_H
+#define ACE_TOKEN_REQUEST_REPLY_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Local_Tokens.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Specifies the size of the fixed length portion of
+/// the Transfer structure in ACE_Token_Request
+#define ACE_TOKEN_REQUEST_HEADER_SIZE 40
+
+/**
+ * @class ACE_Token_Request
+ *
+ * @brief Message format for delivering requests to the ACE_Token Server.
+ *
+ * This class is implemented to minimize data copying.
+ * In particular, all marshaling is done in situ...
+ */
+class ACE_Export ACE_Token_Request
+{
+public:
+ /// Operation types.
+ enum OPERATION
+ {
+ /// Acquire the token.
+ ACQUIRE,
+ /// Release the token.
+ RELEASE,
+ /// Renew the token.
+ RENEW,
+ /// Remove the token.
+ REMOVE,
+ // Try to acquire the token.
+ TRY_ACQUIRE
+ };
+
+ /// Default constructor.
+ ACE_Token_Request (void);
+
+ /**
+ * @param token_type MUTEX, RWLOCK
+ * @param proxy_type MUTEX, RLOCK, WLOCK (acquires mean different things)
+ * @param operation method
+ * @param token_name
+ * @param client_id
+ * @param options We check USE_TIMEOUT and use the arg.
+ */
+ ACE_Token_Request (int token_type,
+ int proxy_type,
+ ACE_UINT32 operation,
+ const ACE_TCHAR token_name[],
+ const ACE_TCHAR client_id[],
+ const ACE_Synch_Options &options);
+
+ /// Get the length of the encoded/decoded message.
+ ACE_UINT32 length (void) const;
+
+ /// Set the length of the encoded/decoded message.
+ void length (ACE_UINT32);
+
+ /// Get the type of proxy
+ int proxy_type (void) const;
+
+ /// Set the type of proxy
+ void proxy_type (int proxy_type);
+
+ /// Get the type of token
+ int token_type (void) const;
+
+ /// Set the type of token
+ void token_type (int token_type);
+
+ /// Get the type of the operation.
+ ACE_UINT32 operation_type (void) const;
+
+ /// Set the type of the operation.
+ void operation_type (ACE_UINT32);
+
+ /// Get the requeue position. These should be used when renew
+ /// is the operation type.
+ ACE_UINT32 requeue_position (void) const;
+
+ /// Set the requeue position. These should be used when renew
+ /// is the operation type.
+ void requeue_position (ACE_UINT32);
+
+ /// Get notify. These should be used when acquire is the operation type.
+ ACE_UINT32 notify (void) const;
+
+ /// Set notify. These should be used when acquire is the operation type.
+ void notify (ACE_UINT32);
+
+ /// Get the timeout.
+ ACE_Synch_Options &options (void) const;
+
+ /// Set the timeout.
+ void options (const ACE_Synch_Options &options);
+
+ // = Set/get the name of the token and the client id. The set
+ // method is combined to make it easier on us. We're copying the
+ // names as a contiguous buffer.
+ ACE_TCHAR *token_name (void) const;
+ ACE_TCHAR *client_id (void) const;
+ void token_name (const ACE_TCHAR *token_name, const ACE_TCHAR *client_id);
+
+ /// Encode the message before transmission.
+ int encode (void *&);
+
+ /// Decode message after reception. This must be called to set the
+ /// internal options.
+ 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
+ {
+ /// Length of entire request.
+ ACE_UINT32 length_;
+
+ /// Type of the request (i.e., MUTEX, RLOCK, WLOCK...
+ ACE_UINT32 token_type_;
+
+ /// Type of the request (i.e., MUTEX, RLOCK, WLOCK...
+ ACE_UINT32 proxy_type_;
+
+ /// Type of the request (i.e., <ACQUIRE>, <RELEASE>, <RENEW>, and <REMOVE>).
+ ACE_UINT32 operation_type_;
+
+ /// this only makes sense when operation type is renew
+ ACE_UINT32 requeue_position_;
+
+ /// this only makes sense when operation type is renew
+ ACE_UINT32 notify_;
+
+ // = ACE_Synch_Options stuff
+
+ /// Indicates if we should block forever. If 1, then <secTimeout_>
+ /// and <usecTimeout_> indicates how long we should wait. If 0,
+ /// then we block forever.
+ ACE_UINT32 use_timeout_;
+
+ /// Max seconds willing to wait for token if not blocking forever.
+ ACE_UINT32 sec_;
+
+ /// Max micro seconds to wait for token if not blocking forever.
+ ACE_UINT32 usec_;
+
+ /// value returned in <Token_Reply::arg>;
+ ACE_UINT32 arg_;
+
+ /// The data portion contains the <tokenName_> including a 0 terminator,
+ /// a ':', then the <clientId> including a 0 terminator
+ ACE_TCHAR data_[ACE_MAXTOKENNAMELEN + ACE_MAXCLIENTIDLEN + 3];
+ } transfer_;
+
+ /// Pointer to the beginning of the token name in this->data_.
+ ACE_TCHAR *token_name_;
+
+ /// Pointer to the beginning of the client id in this->data_;
+ ACE_TCHAR *client_id_;
+
+ /// Holds arg, sec, usec, etc.
+ ACE_Synch_Options options_;
+};
+
+/**
+ * @class ACE_Token_Reply
+ *
+ * @brief Message format for delivering replies from the ACE_Token Server.
+ *
+ * This class is implemented to minimize data copying.
+ * In particular, all marshaling is done in situ...
+ */
+class ACE_Export ACE_Token_Reply
+{
+public:
+ /// Default constructor.
+ ACE_Token_Reply (void);
+
+ /// Get the length of the encoded/decoded message.
+ ACE_UINT32 length (void) const;
+
+ /// Set the length of the encoded/decoded message.
+ void length (ACE_UINT32);
+
+ /// Get the errno of a reply.
+ ACE_UINT32 errnum (void) const;
+
+ /// Set the errno of a reply.
+ void errnum (ACE_UINT32);
+
+ /// Get the arg of a reply.
+ ACE_UINT32 arg (void) const;
+
+ /// Set the arg of a reply.
+ void arg (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 2 fields in the <Transfer> struct are transmitted to the server.
+
+ struct Transfer
+ {
+ /// Length of entire reply.
+ ACE_UINT32 length_;
+
+ /// Indicates why error occurred if <this->type_> == <FAILURE>.
+ /// Typical reasons include:
+ /// @c EWOULDBLOCK (if client requested a non-blocking check for the token).
+ /// @c ETIME (if the client timed out after waiting for the token).
+ /// <ENOLCK> (if the token lock was removed out from underneath a waiter).
+ /// <EACCES> (attempt to renew a token that isn't owned by the client).
+ ACE_UINT32 errno_;
+
+ /// magic cookie
+ ACE_UINT32 arg_;
+
+ } transfer_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Token_Request_Reply.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TOKEN_REQUEST_REPLY_H */
diff --git a/ACE/ace/Token_Request_Reply.inl b/ACE/ace/Token_Request_Reply.inl
new file mode 100644
index 00000000000..36688fb8d63
--- /dev/null
+++ b/ACE/ace/Token_Request_Reply.inl
@@ -0,0 +1,205 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+#include "ace/Truncate.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// = Set/get the length of the encoded/decoded message.
+
+ACE_INLINE ACE_UINT32
+ACE_Token_Request::length (void) const
+{
+ return ntohl (this->transfer_.length_);
+}
+
+ACE_INLINE void
+ACE_Token_Request::length (ACE_UINT32 l)
+{
+ this->transfer_.length_ = htonl (l);
+}
+
+// = Set/get the type of the message.
+ACE_INLINE int
+ACE_Token_Request::token_type (void) const
+{
+ return (int) ntohl (this->transfer_.token_type_);
+}
+
+ACE_INLINE void
+ACE_Token_Request::token_type (int t)
+{
+ this->transfer_.token_type_ = htonl ((ACE_UINT32) t);
+}
+
+// = Set/get the type of the message.
+ACE_INLINE int
+ACE_Token_Request::proxy_type (void) const
+{
+ return (int) ntohl (this->transfer_.proxy_type_);
+}
+
+ACE_INLINE void
+ACE_Token_Request::proxy_type (int t)
+{
+ this->transfer_.proxy_type_ = htonl ((ACE_UINT32) t);
+}
+
+// = Set/get the type of the message.
+ACE_INLINE ACE_UINT32
+ACE_Token_Request::operation_type (void) const
+{
+ return ntohl (this->transfer_.operation_type_);
+}
+
+ACE_INLINE void
+ACE_Token_Request::operation_type (ACE_UINT32 t)
+{
+ this->transfer_.operation_type_ = htonl (t);
+}
+
+// = Set/get the requeue position
+ACE_INLINE ACE_UINT32
+ACE_Token_Request::requeue_position (void) const
+{
+ return ntohl (this->transfer_.requeue_position_);
+}
+
+ACE_INLINE void
+ACE_Token_Request::requeue_position (ACE_UINT32 rq)
+{
+ this->transfer_.requeue_position_ = htonl (rq);
+}
+
+// = Set/get the requeue position
+ACE_INLINE ACE_UINT32
+ACE_Token_Request::notify (void) const
+{
+ return ntohl (this->transfer_.notify_);
+}
+
+ACE_INLINE void
+ACE_Token_Request::notify (ACE_UINT32 rq)
+{
+ this->transfer_.notify_ = htonl (rq);
+}
+
+// = Set/get the blocking semantics.
+ACE_INLINE ACE_Synch_Options &
+ACE_Token_Request::options (void) const
+{
+ return (ACE_Synch_Options &) options_;
+}
+
+ACE_INLINE void
+ACE_Token_Request::options (const ACE_Synch_Options &opt)
+{
+ // fight the friggin const from hell
+ ACE_Synch_Options *options = (ACE_Synch_Options *) &opt;
+
+ transfer_.use_timeout_ = options->operator[](ACE_Synch_Options::USE_TIMEOUT);
+ if (transfer_.use_timeout_ == 1)
+ {
+ transfer_.usec_ = options->timeout ().usec ();
+ if (options->timeout ().sec () > (time_t) ACE_UINT32_MAX)
+ transfer_.sec_ = ACE_UINT32_MAX;
+ else
+ transfer_.sec_ = static_cast<ACE_UINT32> (options->timeout ().sec ());
+ }
+ else
+ {
+ transfer_.usec_ = 0;
+ transfer_.sec_ = 0;
+ }
+}
+
+// = Set/get the name of the token.
+ACE_INLINE ACE_TCHAR *
+ACE_Token_Request::token_name (void) const
+{
+ return token_name_;
+}
+
+ACE_INLINE void
+ACE_Token_Request::token_name (const ACE_TCHAR *token_name,
+ const ACE_TCHAR *client_id)
+{
+ size_t token_name_length = ACE_OS::strlen (token_name) + 1; // Add 1 for '\0'.
+ size_t client_id_length = ACE_OS::strlen (client_id) + 1; // Add 1 for '\0'.
+
+ // Set up pointers and copy token_name and client_id into request.
+ token_name_ = this->transfer_.data_;
+ client_id_ = &this->token_name_[token_name_length + 1]; // Add 1 for ':';
+ client_id_[-1] = ACE_TEXT (':'); // Insert the ':' before this->clientId_.
+
+ (void) ACE_OS::memcpy (this->token_name_,
+ token_name,
+ token_name_length * sizeof (ACE_TCHAR));
+ (void) ACE_OS::memcpy (this->client_id_,
+ client_id,
+ client_id_length * sizeof (ACE_TCHAR));
+
+ // Fixed length header size
+ size_t len = ACE_TOKEN_REQUEST_HEADER_SIZE;
+
+ // ... then add in the amount of the variable-sized portion.
+ len += token_name_length + client_id_length + 1;
+ this->length (ACE_Utils::truncate_cast<ACE_UINT32> (len));
+}
+
+// = Set/get the id of the client.
+ACE_INLINE ACE_TCHAR *
+ACE_Token_Request::client_id (void) const
+{
+ return this->client_id_;
+}
+
+// ************************************************************
+// ************************************************************
+// ************************************************************
+
+// = Set/get the length of the encoded/decoded message.
+ACE_INLINE ACE_UINT32
+ACE_Token_Reply::length (void) const
+{
+ return ntohl (this->transfer_.length_);
+}
+
+ACE_INLINE void
+ACE_Token_Reply::length (ACE_UINT32 l)
+{
+ this->transfer_.length_ = htonl (l);
+}
+
+// = Set/get the errno of a failed reply.
+ACE_INLINE ACE_UINT32
+ACE_Token_Reply::errnum (void) const
+{
+ return ntohl (this->transfer_.errno_);
+}
+
+ACE_INLINE void
+ACE_Token_Reply::errnum (ACE_UINT32 e)
+{
+ this->transfer_.errno_ = htonl (e);
+}
+
+// = Set/get the length of the encoded/decoded message.
+ACE_INLINE ACE_UINT32
+ACE_Token_Reply::arg (void) const
+{
+ return ntohl (this->transfer_.arg_);
+}
+
+ACE_INLINE void
+ACE_Token_Reply::arg (ACE_UINT32 arg)
+{
+ this->transfer_.arg_ = htonl (arg);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_TOKENS_LIBRARY */
diff --git a/ACE/ace/Trace.cpp b/ACE/ace/Trace.cpp
new file mode 100644
index 00000000000..f83e8e96511
--- /dev/null
+++ b/ACE/ace/Trace.cpp
@@ -0,0 +1,137 @@
+// $Id$
+
+
+#include "ace/Trace.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/Log_Msg.h"
+#include "ace/Object_Manager_Base.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// = 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
+{
+#if defined (ACE_HAS_DUMP)
+#endif /* ACE_HAS_DUMP */
+}
+
+// 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 has not yet been initialized, don't try to trace... there's
+ // too much stuff not yet initialized.
+ if (ACE_Trace::enable_tracing_ && !ACE_OS_Object_Manager::starting_up ())
+ {
+ ACE_Log_Msg *lm = ACE_LOG_MSG;
+ if (lm->tracing_enabled ()
+ && lm->trace_active () == 0)
+ {
+ lm->trace_active (1);
+ ACE_DEBUG ((LM_TRACE,
+ ACE_TEXT ("%*s(%t) calling %s in file `%s' on line %d\n"),
+ ACE_Trace::nesting_indent_ * lm->inc (),
+ ACE_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 has not yet been initialized, don't try to trace... there's
+ // too much stuff not yet initialized.
+ if (ACE_Trace::enable_tracing_ && !ACE_OS_Object_Manager::starting_up ())
+ {
+ ACE_Log_Msg *lm = ACE_LOG_MSG;
+ if (lm->tracing_enabled ()
+ && lm->trace_active () == 0)
+ {
+ lm->trace_active (1);
+ ACE_DEBUG ((LM_TRACE,
+ ACE_TEXT ("%*s(%t) leaving %s\n"),
+ ACE_Trace::nesting_indent_ * lm->dec (),
+ ACE_TEXT (""),
+ this->name_));
+ lm->trace_active (0);
+ }
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Trace.h b/ACE/ace/Trace.h
new file mode 100644
index 00000000000..4fdb86a3367
--- /dev/null
+++ b/ACE/ace/Trace.h
@@ -0,0 +1,96 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_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
+ };
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_TRACE_H */
diff --git a/ACE/ace/Truncate.h b/ACE/ace/Truncate.h
new file mode 100644
index 00000000000..7e03d90ca57
--- /dev/null
+++ b/ACE/ace/Truncate.h
@@ -0,0 +1,1016 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Truncate.h
+ *
+ * $Id$
+ *
+ * @author Steve Huston <shuston@riverace.com>
+ * @author Ossama Othman <ossama_othman at symantec dot com>
+ * @author Russell Mora <russell_mora at symantec dot com>
+ */
+//=============================================================================
+
+#ifndef ACE_TRUNCATE_H
+#define ACE_TRUNCATE_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/Global_Macros.h"
+#include "ace/If_Then_Else.h"
+#include "ace/Numeric_Limits.h"
+
+#if defined (ACE_LACKS_LONGLONG_T) \
+ || defined (__BORLANDC__) && __BORLANDC__ < 0x590
+# include "ace/Basic_Types.h"
+#endif /* ACE_LACKS_LONGLONG_T || __BORLANDC__ < 0x590 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_Utils
+{
+
+#if !defined (__BORLANDC__) || __BORLANDC__ >= 0x590
+
+ template<typename T> struct Sign_Check;
+
+ // Specialize the unsigned signed cases.
+ template<> struct Sign_Check<unsigned char> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
+ template<> struct Sign_Check<unsigned short> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
+ template<> struct Sign_Check<unsigned int> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
+ template<> struct Sign_Check<unsigned long> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
+#if !(defined(ACE_LACKS_LONGLONG_T) || defined(ACE_LACKS_UNSIGNEDLONGLONG_T))
+# ifdef __GNUC__
+ // Silence g++ "-pedantic" warnings regarding use of "long long"
+ // type.
+ __extension__
+# endif /* __GNUC__ */
+ template<> struct Sign_Check<unsigned long long> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
+#else
+ template<> struct Sign_Check<ACE_U_LongLong> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
+#endif /* !ACE_LACKS_LONGLONG_T */
+
+ // Specialize the signed cases.
+ template<> struct Sign_Check<signed char> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
+ template<> struct Sign_Check<signed short> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
+ template<> struct Sign_Check<signed int> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
+ template<> struct Sign_Check<signed long> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
+#ifndef ACE_LACKS_LONGLONG_T
+# ifdef __GNUC__
+ // Silence g++ "-pedantic" warnings regarding use of "long long"
+ // type.
+ __extension__
+# endif /* __GNUC__ */
+ template<> struct Sign_Check<signed long long> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
+#endif /* !ACE_LACKS_LONGLONG_T */
+
+ // -----------------------------------------------------
+
+ /**
+ * @struct To_Unsigned
+ *
+ * @brief Retrieve unsigned counterpart to given type or value.
+ *
+ * Retrieve unsigned counterpart to given type or value.
+ */
+ template<typename T> struct To_Unsigned;
+
+ template<>
+ struct To_Unsigned<unsigned char>
+ {
+ typedef unsigned char unsigned_type;
+
+ unsigned_type operator() (unsigned_type x) { return x; }
+ };
+
+ template<>
+ struct To_Unsigned<unsigned short>
+ {
+ typedef unsigned short unsigned_type;
+
+ unsigned_type operator() (unsigned_type x) { return x; }
+ };
+
+ template<>
+ struct To_Unsigned<unsigned int>
+ {
+ typedef unsigned int unsigned_type;
+
+ unsigned_type operator() (unsigned_type x) { return x; }
+ };
+
+ template<>
+ struct To_Unsigned<unsigned long>
+ {
+ typedef unsigned long unsigned_type;
+
+ unsigned_type operator() (unsigned_type x) { return x; }
+ };
+
+#if !(defined(ACE_LACKS_LONGLONG_T) || defined(ACE_LACKS_UNSIGNEDLONGLONG_T))
+# ifdef __GNUC__
+ // Silence g++ "-pedantic" warnings regarding use of "long long"
+ // type.
+ __extension__
+# endif /* __GNUC__ */
+ template<>
+ struct To_Unsigned<unsigned long long>
+ {
+ typedef unsigned long long unsigned_type;
+
+ unsigned_type operator() (unsigned_type x) { return x; }
+ };
+#else
+ template<>
+ struct To_Unsigned<ACE_U_LongLong>
+ {
+ typedef ACE_U_LongLong unsigned_type;
+
+ unsigned_type operator() (unsigned_type x) { return x; }
+ };
+#endif /* !ACE_LACKS_LONGLONG_T */
+
+ // ----------------
+
+ template<>
+ struct To_Unsigned<signed char>
+ {
+ typedef signed char signed_type;
+ typedef unsigned char unsigned_type;
+
+ unsigned_type operator() (signed_type x)
+ {
+ return static_cast<unsigned_type> (x);
+ }
+ };
+
+ template<>
+ struct To_Unsigned<signed short>
+ {
+ typedef signed short signed_type;
+ typedef unsigned short unsigned_type;
+
+ unsigned_type operator() (signed_type x)
+ {
+ return static_cast<unsigned_type> (x);
+ }
+ };
+
+ template<>
+ struct To_Unsigned<signed int>
+ {
+ typedef signed int signed_type;
+ typedef unsigned int unsigned_type;
+
+ unsigned_type operator() (signed_type x)
+ {
+ return static_cast<unsigned_type> (x);
+ }
+ };
+
+ template<>
+ struct To_Unsigned<signed long>
+ {
+ typedef signed long signed_type;
+ typedef unsigned long unsigned_type;
+
+ unsigned_type operator() (signed_type x)
+ {
+ return static_cast<unsigned_type> (x);
+ }
+ };
+
+#if !(defined(ACE_LACKS_LONGLONG_T) || defined(ACE_LACKS_UNSIGNEDLONGLONG_T))
+# ifdef __GNUC__
+ // Silence g++ "-pedantic" warnings regarding use of "long long"
+ // type.
+ __extension__
+# endif /* __GNUC__ */
+ template<>
+ struct To_Unsigned<signed long long>
+ {
+ typedef signed long long signed_type;
+ typedef unsigned long long unsigned_type;
+
+ unsigned_type operator() (signed_type x)
+ {
+ return static_cast<unsigned_type> (x);
+ }
+ };
+#endif /* !ACE_LACKS_LONGLONG_T */
+
+ // -----------------------------------------------------
+
+ /**
+ * @struct Safe_Comparator
+ *
+ * @brief Conservative comparison of types that may not be safely
+ * promoted and/or converted to each other.
+ *
+ * The comparison operations provided by this structure perform
+ * negative value checking when necessary to prevent wrap-around
+ * when explicitly casting to an unsigned type.
+ *
+ * @internal This structure is not meant for general use.
+ */
+ template<typename LEFT,
+ typename RIGHT,
+ bool IS_LEFT_SIGNED,
+ bool IS_RIGHT_SIGNED> struct Safe_Comparator;
+
+ // LEFT: signed, RIGHT: unsigned
+ template<typename LEFT, typename RIGHT>
+ struct Safe_Comparator<LEFT, RIGHT, true, false>
+ {
+ static bool greater_than (LEFT lhs, RIGHT rhs)
+ {
+ // Prevent wrap-around when casting to unsigned.
+ if (lhs < 0)
+ return false; // since rhs is always positive
+ else
+ {
+ // Implicit promotion of unsigned LEFT and RIGHT types here.
+ return To_Unsigned<LEFT>() (lhs) > rhs;
+ }
+ }
+ };
+
+ // LEFT: unsigned, RIGHT: signed
+ template<typename LEFT, typename RIGHT>
+ struct Safe_Comparator<LEFT, RIGHT, false, true>
+ {
+ static bool greater_than (LEFT lhs, RIGHT rhs)
+ {
+ // Prevent wrap-around when casting to unsigned.
+ if (rhs < 0)
+ return true; // since lhs is always positive
+ else
+ {
+ // Implicit promotion of unsigned LEFT and RIGHT types here.
+ return lhs > To_Unsigned<RIGHT>() (rhs);
+ }
+ }
+ };
+
+ // LEFT: unsigned, RIGHT: unsigned
+ template<typename LEFT, typename RIGHT>
+ struct Safe_Comparator<LEFT, RIGHT, false, false>
+ {
+ static bool greater_than (LEFT lhs, RIGHT rhs)
+ {
+ // Implicit promotion of unsigned LEFT and RIGHT types here.
+ return lhs > rhs;
+ }
+ };
+
+ // LEFT: signed, RIGHT: signed
+ template<typename LEFT, typename RIGHT>
+ struct Safe_Comparator<LEFT, RIGHT, true, true>
+ {
+ static bool greater_than (LEFT lhs, RIGHT rhs)
+ {
+ // Implicit promotion of signed LEFT and RIGHT types here.
+ return lhs > rhs;
+ }
+ };
+
+ // -----------------------------------------------------
+
+ /**
+ * @struct Fast_Comparator
+ *
+ * @brief Quick comparison of types that can be safely promoted
+ * and/or converted to each other.
+ *
+ * The comparison operations provided by this structure perform no
+ * negative value checking, meaning it is not applicable to all
+ * types. Check the value of the @c USABLE enumerator to determine
+ * if it applies to the types in question.
+ *
+ * @internal This structure is not meant for general use.
+ */
+ template<typename LEFT, typename RIGHT>
+ struct Fast_Comparator
+ {
+ ACE_STATIC_CONSTANT (
+ bool,
+ USE_LEFT = ((sizeof (LEFT) > sizeof (RIGHT)
+ && (Sign_Check<LEFT>::is_signed == 1
+ || Sign_Check<RIGHT>::is_signed == 0))
+
+ // The following is basically the case where LEFT
+ // and RIGHT are the same integral type.
+ || (sizeof (LEFT) == sizeof (RIGHT)
+ // Can't portably do
+ // Sign_Check<LEFT>::is_signed ==
+ // Sign_Check<RIGHT>::is_signed,
+ // i.e. comparison of anonymous enumerations,
+ // without triggering a compiler diagnostic
+ // so expand the comparison.
+ && ((Sign_Check<LEFT>::is_signed == 1
+ && Sign_Check<RIGHT>::is_signed == 1)
+ || (Sign_Check<LEFT>::is_signed == 0
+ && Sign_Check<RIGHT>::is_signed == 0)))));
+
+ ACE_STATIC_CONSTANT (
+ bool,
+ USE_RIGHT = (sizeof (RIGHT) > sizeof (LEFT)
+ && (Sign_Check<RIGHT>::is_signed == 1
+ || Sign_Check<LEFT>::is_signed == 0)));
+
+ ACE_STATIC_CONSTANT (bool, USABLE = (USE_LEFT || USE_RIGHT));
+
+ typedef typename ACE::If_Then_Else<
+ USE_LEFT,
+ LEFT,
+ typename ACE::If_Then_Else<
+ USE_RIGHT,
+ RIGHT,
+ void>::result_type>::result_type promote_type;
+
+ static bool greater_than (LEFT lhs, RIGHT rhs)
+ {
+ // The explicit cast is assumed to change the type of rhs without
+ // changing its value.
+ return
+ (static_cast<promote_type> (lhs) > static_cast<promote_type> (rhs));
+ }
+
+ };
+
+ // -----------------------------------------------------
+
+ /**
+ * @struct Comparator
+ *
+ * @brief Structure that provides optimal comparison operation for
+ * given types.
+ *
+ * The comparison operations provided by this structure are chosen
+ * at compile time based on the signs and sizes of types being
+ * compared.
+ * @par
+ * Comparisons of values with the same sign or those with types that
+ * can be promoted safely are done quickly, without any range
+ * checking.
+ * @par
+ * Comparisons of values of different types that cannot be safely
+ * promoted incur an additional check for a negative value to allow
+ * the compiler to perform the appropriate implicit unsigned type
+ * promotion.
+ *
+ * @note In general, the operations found in this structure should
+ * not be used to work around compiler diagnostics regarding
+ * comparison of signed and unsigned types. Verify that your
+ * types are correct before relying on those operations.
+ *
+ * @internal This structure is not meant for general use.
+ */
+ template<typename LEFT, typename RIGHT>
+ struct Comparator
+ {
+ typedef typename ACE::If_Then_Else<
+ Fast_Comparator<LEFT, RIGHT>::USABLE,
+ Fast_Comparator<LEFT, RIGHT>,
+ Safe_Comparator<LEFT,
+ RIGHT,
+ Sign_Check<LEFT>::is_signed,
+ Sign_Check<RIGHT>::is_signed> >::result_type comp_type;
+ };
+
+ // -----------------------------------------------------
+
+ /**
+ * @struct Truncator
+ *
+ * @brief Truncate value of type @c FROM to value of type @c TO.
+ *
+ * Truncate a value of type @c FROM to value of type @c TO, if the
+ * value is larger than the maximum of value of type @c TO.
+ */
+ template<typename FROM, typename TO>
+ struct Truncator
+ {
+ ACE_STATIC_CONSTANT (
+ bool,
+ // max FROM always greater than max TO
+ MAX_FROM_GT_MAX_TO = (sizeof(FROM) > sizeof (TO)
+ || (sizeof(FROM) == sizeof (TO)
+ && Sign_Check<FROM>::is_signed == 0)));
+
+ typedef typename ACE::If_Then_Else<
+ MAX_FROM_GT_MAX_TO,
+ FROM,
+ TO>::result_type comp_to_type;
+
+ // Take advantage of knowledge that we're casting a positive value
+ // to a type large enough to hold it so that we can bypass
+ // negative value checks at compile-time. Otherwise fallback on
+ // the safer comparison.
+ typedef typename ACE::If_Then_Else<
+ MAX_FROM_GT_MAX_TO,
+ Fast_Comparator<FROM, comp_to_type>,
+ typename Comparator<FROM, comp_to_type>::comp_type>::result_type comparator;
+
+ /// Truncate a value of type @c FROM to value of type @c TO, if
+ /// the value is larger than the maximum of value of type @c TO.
+ TO operator() (FROM val)
+ {
+ return
+ (comparator::greater_than (val, ACE_Numeric_Limits<TO>::max ())
+ ? ACE_Numeric_Limits<TO>::max ()
+ : static_cast<TO> (val));
+ }
+
+ };
+
+ // Partial specialization for the case where the types are the same.
+ // No truncation is necessary.
+ template<typename T>
+ struct Truncator<T, T>
+ {
+ T operator() (T val)
+ {
+ return val;
+ }
+ };
+
+
+#if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+ // Partial specialization for the case where we're casting from
+ // ACE_U_LongLong to a smaller integer. We assume that we're always
+ // truncating from ACE_U_LongLong to a smaller type. The partial
+ // specialization above handles the case where both the FROM and TO
+ // types are ACE_U_LongLong.
+ template<typename TO>
+ struct Truncator<ACE_U_LongLong, TO>
+ {
+ TO operator() (ACE_U_LongLong const & val)
+ {
+ // If val less than or equal to ACE_Numeric_Limits<TO>::max(),
+ // val.lo() must be less than or equal to
+ // ACE_Numeric_Limits<TO>::max (), as well.
+ return
+ (val > ACE_Numeric_Limits<TO>::max ()
+ ? ACE_Numeric_Limits<TO>::max ()
+ : static_cast<TO> (val.lo ()));
+ }
+ };
+#endif /* ACE_LACKS_LONGLONG_T || ACE_LACKS_UNSIGNEDLONGLONG_T */
+
+ // -----------------------------------------------------
+ /**
+ * @struct Noop_Truncator
+ *
+ * @brief No-op truncation.
+ *
+ * This structure/functor performs no truncation since it assumes
+ * that @c sizeof(FROM) @c < @c sizeof(TO), meaning that
+ * @c numeric_limits<FROM>::max() @c < @c numeric_limits<TO>::max().
+ */
+ template<typename FROM, typename TO>
+ struct Noop_Truncator
+ {
+ TO operator() (FROM val)
+ {
+ return static_cast<TO> (val);
+ }
+ };
+ // -----------------------------------------------------
+
+ /**
+ * @class truncate_cast
+ *
+ * @brief Helper function to truncate an integral value to the
+ * maximum value of the given type.
+ *
+ * Very useful since ACE methods return @c int very often and
+ * the value's source is often a different-size integral
+ * type, such as @c size_t. This function hides the
+ * truncation logic and resolves compiler diagnostics.
+ *
+ * @internal Internal use only.
+ */
+ template<typename TO, typename FROM>
+ inline TO truncate_cast (FROM val)
+ {
+ // If the size of FROM is less than the size of TO, "val" will
+ // never be greater than the maximum "TO" value, so there is no
+ // need to attempt to truncate.
+ typedef typename ACE::If_Then_Else<
+ (sizeof (FROM) < sizeof (TO)),
+ Noop_Truncator<FROM, TO>,
+ Truncator<FROM, TO> >::result_type truncator;
+
+ return truncator() (val);
+ }
+
+#else
+
+ // Borland can't handle the template meta-programming above so
+ // provide explicit specializations for a few types. More will be
+ // added if necessary.
+
+ /**
+ * @deprecated Borland ACE_Utils::Truncator<> specializations should
+ * be removed.
+ */
+
+ template<typename FROM, typename TO> struct Truncator;
+
+ //----------------------------------------------------------
+ // sizeof(FROM) > sizeof(TO)
+ //----------------------------------------------------------
+
+ template<>
+ struct Truncator<ACE_INT32, ACE_INT8>
+ {
+ ACE_INT8 operator() (ACE_INT32 val)
+ {
+ return
+ (val > ACE_Numeric_Limits<ACE_INT8>::max ()
+ ? ACE_Numeric_Limits<ACE_INT8>::max ()
+ : static_cast<ACE_INT8> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT32, ACE_UINT8>
+ {
+ ACE_UINT8 operator() (ACE_UINT32 val)
+ {
+ return
+ (val > static_cast<ACE_UINT32> (ACE_Numeric_Limits<ACE_UINT8>::max ())
+ ? ACE_Numeric_Limits<ACE_UINT8>::max ()
+ : static_cast<ACE_UINT8> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_INT32, ACE_UINT8>
+ {
+ ACE_UINT8 operator() (ACE_INT32 val)
+ {
+ return
+ (val > static_cast<ACE_INT32> (ACE_Numeric_Limits<ACE_UINT8>::max ())
+ ? ACE_Numeric_Limits<ACE_UINT8>::max ()
+ : static_cast<ACE_UINT8> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT32, ACE_INT8>
+ {
+ ACE_INT8 operator() (ACE_UINT32 val)
+ {
+ return
+ (val > static_cast<ACE_UINT32> (ACE_Numeric_Limits<ACE_INT8>::max ())
+ ? ACE_Numeric_Limits<ACE_INT8>::max ()
+ : static_cast<ACE_INT8> (val));
+ }
+ };
+
+#if defined (ACE_SIZEOF_LONG) && ACE_SIZEOF_LONG < 8
+ template<>
+ struct Truncator<ACE_INT64, signed long>
+ {
+ signed long operator() (ACE_INT64 val)
+ {
+ return
+ (val > ACE_Numeric_Limits<signed long>::max ()
+ ? ACE_Numeric_Limits<signed long>::max ()
+ : static_cast<signed long> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_INT64, unsigned long>
+ {
+ unsigned long operator() (ACE_INT64 val)
+ {
+ return
+ (val > static_cast<ACE_INT64> (ACE_Numeric_Limits<unsigned long>::max ())
+ ? ACE_Numeric_Limits<unsigned long>::max ()
+ : static_cast<unsigned long> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT64, unsigned long>
+ {
+ unsigned long operator() (ACE_UINT64 val)
+ {
+ return
+ (val > static_cast<ACE_UINT64> (ACE_Numeric_Limits<unsigned long>::max ())
+ ? ACE_Numeric_Limits<unsigned long>::max ()
+ : static_cast<unsigned long> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT64, signed long>
+ {
+ signed long operator() (ACE_UINT64 val)
+ {
+ return
+ (val > static_cast<ACE_UINT64> (ACE_Numeric_Limits<signed long>::max ())
+ ? ACE_Numeric_Limits<signed long>::max ()
+ : static_cast<signed long> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<const ACE_UINT64, signed long>
+ {
+ signed long operator() (const ACE_UINT64 val)
+ {
+ return
+ (val > static_cast<ACE_UINT64> (ACE_Numeric_Limits<signed long>::max ())
+ ? ACE_Numeric_Limits<signed long>::max ()
+ : static_cast<signed long> (val));
+ }
+ };
+
+#endif /* ACE_SIZEOF_LONG < 8 */
+
+#if defined (ACE_SIZEOF_INT) && ACE_SIZEOF_INT < 8
+ template<>
+ struct Truncator<ACE_INT64, signed int>
+ {
+ ACE_INT32 operator() (ACE_INT64 val)
+ {
+ return
+ (val > ACE_Numeric_Limits<signed int>::max ()
+ ? ACE_Numeric_Limits<signed int>::max ()
+ : static_cast<signed int> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_INT64, unsigned int>
+ {
+ ACE_UINT32 operator() (ACE_INT64 val)
+ {
+ return
+ (val > static_cast<ACE_INT64> (ACE_Numeric_Limits<unsigned int>::max ())
+ ? ACE_Numeric_Limits<unsigned int>::max ()
+ : static_cast<unsigned int> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT64, unsigned int>
+ {
+ ACE_UINT32 operator() (ACE_UINT64 val)
+ {
+ return
+ (val > static_cast<ACE_UINT64> (ACE_Numeric_Limits<unsigned int>::max ())
+ ? ACE_Numeric_Limits<unsigned int>::max ()
+ : static_cast<unsigned int> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT64, signed int>
+ {
+ signed int operator() (ACE_UINT64 val)
+ {
+ return
+ (val > static_cast<ACE_UINT64> (ACE_Numeric_Limits<signed int>::max ())
+ ? ACE_Numeric_Limits<signed int>::max ()
+ : static_cast<signed int> (val));
+ }
+ };
+
+#endif /* ACE_SIZEOF_INT < 8 */
+
+ //----------------------------------------------------------
+ // sizeof(FROM) == sizeof(TO)
+ //----------------------------------------------------------
+
+ template<>
+ struct Truncator<signed int, unsigned int>
+ {
+ unsigned int operator() (signed int val)
+ {
+ return static_cast<unsigned int> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<unsigned int, signed int>
+ {
+ signed int operator() (unsigned int val)
+ {
+ return
+ (val > static_cast<unsigned int> (ACE_Numeric_Limits<signed int>::max ())
+ ? ACE_Numeric_Limits<signed int>::max ()
+ : static_cast<signed int> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<signed long, unsigned long>
+ {
+ unsigned long operator() (signed long val)
+ {
+ return static_cast<unsigned long> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<unsigned long, signed long>
+ {
+ signed long operator() (unsigned long val)
+ {
+ return
+ (val > static_cast<unsigned long> (ACE_Numeric_Limits<signed long>::max ())
+ ? ACE_Numeric_Limits<signed long>::max ()
+ : static_cast<signed long> (val));
+ }
+ };
+
+#if defined (ACE_SIZEOF_INT) && defined (ACE_SIZEOF_LONG) \
+ && ACE_SIZEOF_INT == ACE_SIZEOF_LONG
+
+ template<>
+ struct Truncator<signed int, unsigned long>
+ {
+ unsigned long operator() (signed int val)
+ {
+ return static_cast<unsigned long> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<unsigned long, signed int>
+ {
+ signed int operator() (unsigned long val)
+ {
+ return
+ (val > static_cast<unsigned long> (ACE_Numeric_Limits<signed int>::max ())
+ ? ACE_Numeric_Limits<signed int>::max ()
+ : static_cast<signed int> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<signed long, signed int>
+ {
+ signed int operator() (signed long val)
+ {
+ return static_cast<signed int> (val);
+// This code causes asserts and compiler crashes with BCB6 Static and
+// BCB2007 Static
+// return
+// (val > static_cast<signed long> (ACE_Numeric_Limits<signed int>::max ())
+// ? ACE_Numeric_Limits<signed int>::max ()
+// : static_cast<signed int> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<signed long, unsigned int>
+ {
+ unsigned int operator() (signed long val)
+ {
+ return static_cast<unsigned int> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<const signed long, unsigned int>
+ {
+ unsigned int operator() (const signed long val)
+ {
+ return static_cast<unsigned int> (val);
+ }
+ };
+
+
+ template<>
+ struct Truncator<unsigned int, signed long>
+ {
+ signed long operator() (unsigned int val)
+ {
+ return
+ (val > static_cast<unsigned int> (ACE_Numeric_Limits<signed long>::max ())
+ ? ACE_Numeric_Limits<signed long>::max ()
+ : static_cast<signed long> (val));
+ }
+ };
+
+#endif /* ACE_SIZEOF_INT == ACE_SIZEOF_LONG */
+
+ template<>
+ struct Truncator<ACE_INT64, ACE_UINT64>
+ {
+ ACE_UINT64 operator() (ACE_INT64 val)
+ {
+ return static_cast<ACE_UINT64> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT64, ACE_INT64>
+ {
+ ACE_INT64 operator() (ACE_UINT64 val)
+ {
+ return
+ (val > static_cast<ACE_UINT64> (ACE_Numeric_Limits<ACE_INT64>::max ())
+ ? ACE_Numeric_Limits<ACE_INT64>::max ()
+ : static_cast<ACE_INT64> (val));
+ }
+ };
+
+ //----------------------------------------------------------
+ // sizeof(FROM) < sizeof(TO)
+ //----------------------------------------------------------
+
+ template<>
+ struct Truncator<ACE_INT8, ACE_INT32>
+ {
+ ACE_INT32 operator() (ACE_INT8 val)
+ {
+ return static_cast<ACE_INT32> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT8, ACE_UINT32>
+ {
+ ACE_UINT32 operator() (ACE_UINT8 val)
+ {
+ return static_cast<ACE_UINT32> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_UINT8, ACE_INT32>
+ {
+ ACE_INT32 operator() (ACE_UINT8 val)
+ {
+ return static_cast<ACE_INT32> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<ACE_INT8, ACE_UINT32>
+ {
+ ACE_UINT32 operator() (ACE_INT8 val)
+ {
+ return static_cast<ACE_UINT32> (val);
+ }
+ };
+
+#if defined (ACE_SIZEOF_LONG) && ACE_SIZEOF_LONG < 8
+ template<>
+ struct Truncator<signed long, ACE_INT64>
+ {
+ ACE_INT64 operator() (signed long val)
+ {
+ return static_cast<ACE_INT64> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<signed long, ACE_UINT64>
+ {
+ ACE_UINT64 operator() (signed long val)
+ {
+ return static_cast<ACE_UINT64> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<const signed long, ACE_UINT64>
+ {
+ ACE_UINT64 operator() (const signed long val)
+ {
+ return
+ (val > static_cast<ACE_UINT64> (ACE_Numeric_Limits<signed long>::max ())
+ ? ACE_Numeric_Limits<signed long>::max ()
+ : static_cast<signed long> (val));
+ }
+ };
+
+ template<>
+ struct Truncator<unsigned long, ACE_UINT64>
+ {
+ ACE_UINT64 operator() (unsigned long val)
+ {
+ return static_cast<ACE_UINT64> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<unsigned long, ACE_INT64>
+ {
+ ACE_INT64 operator() (unsigned long val)
+ {
+ return static_cast<ACE_INT64> (val);
+ }
+ };
+#endif /* ACE_SIZEOF_LONG < 8 */
+
+#if defined (ACE_SIZEOF_INT) && ACE_SIZEOF_INT < 8
+ template<>
+ struct Truncator<signed int, ACE_INT64>
+ {
+ ACE_INT64 operator() (signed int val)
+ {
+ return static_cast<ACE_INT64> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<signed int, ACE_UINT64>
+ {
+ ACE_UINT64 operator() (signed int val)
+ {
+ return static_cast<ACE_UINT64> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<unsigned int, ACE_UINT64>
+ {
+ ACE_UINT64 operator() (unsigned int val)
+ {
+ return static_cast<ACE_UINT64> (val);
+ }
+ };
+
+ template<>
+ struct Truncator<unsigned int, ACE_INT64>
+ {
+ ACE_INT64 operator() (unsigned int val)
+ {
+ return static_cast<ACE_INT64> (val);
+ }
+ };
+#endif /* ACE_SIZEOF_INT < 8 */
+
+ template<>
+ struct Truncator<size_t, unsigned long>
+ {
+ unsigned long operator() (size_t val)
+ {
+ return
+ (val > static_cast<unsigned long> (ACE_Numeric_Limits<size_t>::max ())
+ ? ACE_Numeric_Limits<size_t>::max ()
+ : static_cast<size_t> (val));
+ }
+ };
+
+ // Partial specialization for the case where the types are the same.
+ // No truncation is necessary.
+ template<typename T>
+ struct Truncator<T, T>
+ {
+ T operator() (T val)
+ {
+ return val;
+ }
+ };
+
+ // Partial specialization for the case where the types are the same,
+ // but the from type is const. No truncation is necessary.
+ //
+ // This is only necessary to workaround a problem with the BCB6
+ // compiler.
+ template<typename T>
+ struct Truncator<T const, T>
+ {
+ T operator() (T val)
+ {
+ return val;
+ }
+ };
+
+ // -------------------------------------
+
+ template<typename TO, typename FROM>
+ inline TO truncate_cast (FROM val)
+ {
+ typedef Truncator<FROM, TO> truncator;
+
+ return truncator() (val);
+ }
+
+#endif /* !__BORLANDC__ || __BORLANDC__ >= 0x590 */
+
+} // namespace ACE_Utils
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_TRUNCATE_H*/
diff --git a/ACE/ace/Typed_SV_Message.cpp b/ACE/ace/Typed_SV_Message.cpp
new file mode 100644
index 00000000000..79f931b77df
--- /dev/null
+++ b/ACE/ace/Typed_SV_Message.cpp
@@ -0,0 +1,30 @@
+// $Id$
+
+#ifndef ACE_TYPED_SV_MESSAGE_CPP
+#define ACE_TYPED_SV_MESSAGE_CPP
+
+#include "ace/Typed_SV_Message.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Typed_SV_Message.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Typed_SV_Message)
+
+template <class T> void
+ACE_Typed_SV_Message<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TYPED_SV_MESSAGE_CPP */
diff --git a/ACE/ace/Typed_SV_Message.h b/ACE/ace/Typed_SV_Message.h
new file mode 100644
index 00000000000..f57e02084c2
--- /dev/null
+++ b/ACE/ace/Typed_SV_Message.h
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Typed_SV_Message.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//==========================================================================
+
+
+#ifndef ACE_TYPED_SV_MESSAGE_H
+#define ACE_TYPED_SV_MESSAGE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Typed_SV_Message
+ *
+ * @brief Defines the header file for the C++ wrapper for System V
+ * message queues.
+ */
+template <class T>
+class ACE_Typed_SV_Message
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Typed_SV_Message (long type = 0,
+ int length = sizeof (T),
+ int max_size = sizeof (T));
+ ACE_Typed_SV_Message (const T &data,
+ long type = 0,
+ int length = sizeof (T),
+ int max_size = sizeof (T));
+ ~ACE_Typed_SV_Message (void);
+
+ /// Get the type of the message.
+ long type (void) const;
+
+ /// Set the type of the message.
+ void type (long type);
+
+ /// Get the length of the message.
+ int length (void) const;
+
+ /// Set the length of the message.
+ void length (int l);
+
+ /// Get the maximum size of the message.
+ int max_size (void) const;
+
+ /// Set the maximum size of the message.
+ void max_size (int m);
+
+ /// Get a pointer to the data in the message.
+ T &data (void);
+
+ /// Set a pointer to the data in the message.
+ void data (const T &data);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Type of message.
+ long type_;
+
+ /// Length of this message.
+ int length_;
+
+ /// Maximum length of any message.
+ int max_;
+
+ /// Data stored in a message.
+ T data_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Typed_SV_Message.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Typed_SV_Message.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Typed_SV_Message.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_TYPED_SV_MESSAGE_H */
diff --git a/ACE/ace/Typed_SV_Message.inl b/ACE/ace/Typed_SV_Message.inl
new file mode 100644
index 00000000000..00ff07109ac
--- /dev/null
+++ b/ACE/ace/Typed_SV_Message.inl
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/config-all.h"
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> ACE_INLINE
+ACE_Typed_SV_Message<T>::ACE_Typed_SV_Message (long t,
+ int l,
+ int m)
+ : type_ (t)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::ACE_Typed_SV_Message");
+ this->length (l);
+ this->max_size (m);
+}
+
+template <class T> ACE_INLINE
+ACE_Typed_SV_Message<T>::ACE_Typed_SV_Message (const T &d,
+ long t,
+ int l,
+ int m)
+ : type_ (t),
+ data_ (d)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::ACE_Typed_SV_Message");
+ this->length (l);
+ this->max_size (m);
+}
+
+template <class T> ACE_INLINE
+ACE_Typed_SV_Message<T>::~ACE_Typed_SV_Message (void)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::~ACE_Typed_SV_Message");
+}
+
+template <class T> ACE_INLINE long
+ACE_Typed_SV_Message<T>::type (void) const
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::type");
+ return this->type_;
+}
+
+template <class T> ACE_INLINE void
+ACE_Typed_SV_Message<T>::type (long t)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::type");
+ this->type_ = t;
+}
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message<T>::length (void) const
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::length");
+ return this->length_;
+}
+
+template <class T> ACE_INLINE void
+ACE_Typed_SV_Message<T>::length (int len)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::length");
+ this->length_ = len + (sizeof *this - (sizeof this->type_ + sizeof this->data_));
+}
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message<T>::max_size (void) const
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::max_size");
+ return this->max_;
+}
+
+template <class T> ACE_INLINE void
+ACE_Typed_SV_Message<T>::max_size (int m)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::max_size");
+ this->max_ = m + (sizeof *this - (sizeof this->type_ + sizeof this->data_));
+}
+
+template <class T> T &
+ACE_Typed_SV_Message<T>::data (void)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::data");
+ return this->data_;
+}
+
+template <class T> void
+ACE_Typed_SV_Message<T>::data (const T &d)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message<T>::data");
+ this->data_ = d;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Typed_SV_Message_Queue.cpp b/ACE/ace/Typed_SV_Message_Queue.cpp
new file mode 100644
index 00000000000..7fc2b0fd38d
--- /dev/null
+++ b/ACE/ace/Typed_SV_Message_Queue.cpp
@@ -0,0 +1,56 @@
+// $Id$
+
+#ifndef ACE_TYPED_SV_MESSAGE_QUEUE_CPP
+#define ACE_TYPED_SV_MESSAGE_QUEUE_CPP
+
+#include "ace/Typed_SV_Message.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Typed_SV_Message_Queue.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Typed_SV_Message_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Typed_SV_Message_Queue)
+
+template <class T> void
+ACE_Typed_SV_Message_Queue<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Typed_SV_Message_Queue<T>::ACE_Typed_SV_Message_Queue (void)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::ACE_Typed_SV_Message_Queue");
+}
+
+template <class T>
+ACE_Typed_SV_Message_Queue<T>::ACE_Typed_SV_Message_Queue (key_t external_id,
+ int create,
+ int perms)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::ACE_Typed_SV_Message_Queue");
+ if (this->open (external_id, create, perms) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "ACE_Typed_SV_Message_Queue::ACE_Typed_SV_Message_Queue"));
+}
+
+template <class T>
+ACE_Typed_SV_Message_Queue<T>::~ACE_Typed_SV_Message_Queue (void)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::~ACE_Typed_SV_Message_Queue");
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TYPED_SV_MESSAGE_QUEUE_CPP */
diff --git a/ACE/ace/Typed_SV_Message_Queue.h b/ACE/ace/Typed_SV_Message_Queue.h
new file mode 100644
index 00000000000..f7c2c066654
--- /dev/null
+++ b/ACE/ace/Typed_SV_Message_Queue.h
@@ -0,0 +1,92 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Typed_SV_Message_Queue.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TYPED_MESSAGE_QUEUE_H
+#define ACE_TYPED_MESSAGE_QUEUE_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SV_Message_Queue.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Typed_SV_Message.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Typed_SV_Message_Queue
+ *
+ * @brief Defines the header file for the C++ wrapper facade for typed message queues.
+ */
+template <class T>
+class ACE_Typed_SV_Message_Queue
+{
+public:
+ enum
+ {
+ ACE_CREATE = IPC_CREAT,
+ ACE_OPEN = 0,
+ ACE_NOWAIT = IPC_NOWAIT
+ };
+
+ // = Initialization and termination operations.
+ ACE_Typed_SV_Message_Queue (void);
+ ACE_Typed_SV_Message_Queue (key_t external_id,
+ int create = ACE_OPEN,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+ int open (key_t external_id,
+ int create = ACE_OPEN,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+ int close (void);
+ int remove (void);
+ ~ACE_Typed_SV_Message_Queue (void);
+
+ /// Send method.
+ int send (const ACE_Typed_SV_Message<T> &mb, int mflags = 0);
+
+ /// Recv method.
+ int recv (ACE_Typed_SV_Message<T> &mb, int mflags = 0);
+
+ /// Return the id of the underlying ACE_SV_Message_Queue.
+ int get_id (void) const;
+
+ /// Control the underlying message queue.
+ int control (int option, void *arg = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ACE_SV_Message_Queue message_queue_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Typed_SV_Message_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Typed_SV_Message_Queue.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Typed_SV_Message_Queue.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_TYPED_MESSAGE_QUEUE_H */
diff --git a/ACE/ace/Typed_SV_Message_Queue.inl b/ACE/ace/Typed_SV_Message_Queue.inl
new file mode 100644
index 00000000000..21ae9536501
--- /dev/null
+++ b/ACE/ace/Typed_SV_Message_Queue.inl
@@ -0,0 +1,80 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/SV_Message_Queue.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message_Queue<T>::open (key_t external_id,
+ int create,
+ int perms)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::open");
+ return this->message_queue_.open (external_id, create, perms);
+}
+
+// What does it mean to close a message queue?!
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message_Queue<T>::close (void)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::close");
+ return 1;
+}
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message_Queue<T>::recv (ACE_Typed_SV_Message<T> &mb,
+ int mflags)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::recv");
+
+ int length =
+ this->message_queue_.recv (reinterpret_cast<ACE_SV_Message &> (mb),
+ mb.max_size (),
+ mb.type (),
+ mflags);
+ if (length != -1)
+ mb.length (length);
+
+ return length;
+}
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message_Queue<T>::send (const ACE_Typed_SV_Message<T> &mb,
+ int mflags)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::send");
+ return
+ this->message_queue_.send (
+ reinterpret_cast<ACE_SV_Message &> (
+ const_cast<ACE_Typed_SV_Message<T> &> (mb)),
+ mb.length (),
+ mflags);
+}
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message_Queue<T>::remove (void)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::remove");
+
+ return this->message_queue_.remove ();
+}
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message_Queue<T>::control (int option,
+ void *arg)
+{
+ ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::control");
+
+ return this->message_queue_.control (option, arg);
+}
+
+template <class T> ACE_INLINE int
+ACE_Typed_SV_Message_Queue<T>::get_id (void) const
+{
+ return this->message_queue_.get_id ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/UNIX_Addr.cpp b/ACE/ace/UNIX_Addr.cpp
new file mode 100644
index 00000000000..8dd3c52a36c
--- /dev/null
+++ b/ACE/ace/UNIX_Addr.cpp
@@ -0,0 +1,151 @@
+// $Id$
+
+#include "ace/UNIX_Addr.h"
+
+ACE_RCSID(ace, UNIX_Addr, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/UNIX_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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);
+}
+
+// Return a pointer to the underlying address.
+
+void *
+ACE_UNIX_Addr::get_addr (void) const
+{
+ return (void *) &this->unix_addr_;
+}
+
+// Transform the string into the current addressing format.
+
+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.
+
+int
+ACE_UNIX_Addr::addr_to_string (ACE_TCHAR s[], size_t len) const
+{
+ ACE_OS::strsncpy (s,
+ ACE_TEXT_CHAR_TO_TCHAR (this->unix_addr_.sun_path),
+ len);
+ return 0;
+}
+
+u_long
+ACE_UNIX_Addr::hash (void) const
+{
+ return ACE::hash_pjw (this->unix_addr_.sun_path);
+}
+
+void
+ACE_UNIX_Addr::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+#endif /* ACE_HAS_DUMP */
+}
+
+// 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;
+ (void) ACE_OS::strsncpy (this->unix_addr_.sun_path,
+ rendezvous_point,
+ sizeof this->unix_addr_.sun_path);
+
+ 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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/ace/UNIX_Addr.h b/ACE/ace/UNIX_Addr.h
new file mode 100644
index 00000000000..6e684e4e583
--- /dev/null
+++ b/ACE/ace/UNIX_Addr.h
@@ -0,0 +1,117 @@
+// -*- 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/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#include "ace/Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/os_include/sys/os_un.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 (ACE_TCHAR addr[], size_t) const;
+
+ /// Transform the string into the current addressing format.
+ virtual int string_to_addr (const char addr[]);
+
+#if defined (ACE_HAS_WCHAR)
+ /// Creates an ACE_UNIX_Addr from a string.
+ ACE_UNIX_Addr (const wchar_t rendezvous_point[]);
+
+ /// Creates an ACE_UNIX_Addr from a string.
+ int set (const wchar_t rendezvous_point[]);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Compare two addresses for equality.
+ bool operator == (const ACE_UNIX_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ bool 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/UNIX_Addr.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_UNIX_ADDR_H */
diff --git a/ACE/ace/UNIX_Addr.inl b/ACE/ace/UNIX_Addr.inl
new file mode 100644
index 00000000000..48f9fd123ab
--- /dev/null
+++ b/ACE/ace/UNIX_Addr.inl
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#include "ace/OS_NS_string.h"
+
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_HAS_WCHAR)
+/// Creates an ACE_UNIX_Addr from a string.
+ACE_INLINE
+ACE_UNIX_Addr::ACE_UNIX_Addr (const wchar_t rendezvous_point[])
+{
+ this->set (ACE_Wide_To_Ascii (rendezvous_point).char_rep ());
+}
+
+/// Creates an ACE_UNIX_Addr from a string.
+ACE_INLINE int
+ACE_UNIX_Addr::set (const wchar_t rendezvous_point[])
+{
+ return this->set (ACE_Wide_To_Ascii (rendezvous_point).char_rep ());
+}
+#endif /* ACE_HAS_WCHAR */
+
+// Compare two addresses for equality.
+
+ACE_INLINE bool
+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 bool
+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_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/ace/UPIPE_Acceptor.cpp b/ACE/ace/UPIPE_Acceptor.cpp
new file mode 100644
index 00000000000..08878a8b5c5
--- /dev/null
+++ b/ACE/ace/UPIPE_Acceptor.cpp
@@ -0,0 +1,129 @@
+// $Id$
+
+#include "ace/UPIPE_Acceptor.h"
+
+ACE_RCSID(ace, UPIPE_Acceptor, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_unistd.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/UPIPE_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Acceptor)
+
+void
+ACE_UPIPE_Acceptor::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_UPIPE_Acceptor::dump");
+#endif /* ACE_HAS_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_TEXT ("%p\n"),
+ ACE_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_TEXT ("ACE_UPIPE_Acceptor: %p\n"),
+ ACE_TEXT ("read stream address failed")));
+ else if (new_stream.stream_.link (remote_stream->stream_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_UPIPE_Acceptor: %p\n"),
+ ACE_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_TEXT ("ACE_UPIPE_Acceptor: %p\n"),
+ ACE_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;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/UPIPE_Acceptor.h b/ACE/ace/UPIPE_Acceptor.h
new file mode 100644
index 00000000000..b7b94179cb6
--- /dev/null
+++ b/ACE/ace/UPIPE_Acceptor.h
@@ -0,0 +1,99 @@
+// -*- 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 */
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Thread_Manager.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a timeout of 0 means
+ * block forever, a @a timeout of {0, 0} means poll. @a 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_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/UPIPE_Acceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_UPIPE_ACCEPTOR_H */
diff --git a/ACE/ace/UPIPE_Acceptor.inl b/ACE/ace/UPIPE_Acceptor.inl
new file mode 100644
index 00000000000..731d6be4a6c
--- /dev/null
+++ b/ACE/ace/UPIPE_Acceptor.inl
@@ -0,0 +1,14 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+ACE_UPIPE_Acceptor::remove (void)
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::remove");
+ return this->ACE_SPIPE_Acceptor::remove ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/UPIPE_Addr.h b/ACE/ace/UPIPE_Addr.h
new file mode 100644
index 00000000000..75f948c6bf5
--- /dev/null
+++ b/ACE/ace/UPIPE_Addr.h
@@ -0,0 +1,33 @@
+// -*- 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 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+typedef ACE_SPIPE_Addr ACE_UPIPE_Addr;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_UPIPE_ADDR_H */
diff --git a/ACE/ace/UPIPE_Connector.cpp b/ACE/ace/UPIPE_Connector.cpp
new file mode 100644
index 00000000000..2af0ab5ee16
--- /dev/null
+++ b/ACE/ace/UPIPE_Connector.cpp
@@ -0,0 +1,101 @@
+// $Id$
+
+#include "ace/UPIPE_Connector.h"
+
+ACE_RCSID(ace, UPIPE_Connector, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Handle_Ops.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stropts.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/UPIPE_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Connector)
+
+void
+ACE_UPIPE_Connector::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_UPIPE_Connector::dump");
+#endif /* ACE_HAS_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_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_TEXT ("ACE_UPIPE_Connector %p\n"),
+ ACE_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_TEXT ("ACE_UPIPE_Connector %p\n"),
+ ACE_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 static_cast<int> (result);
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/UPIPE_Connector.h b/ACE/ace/UPIPE_Connector.h
new file mode 100644
index 00000000000..77bbf00550e
--- /dev/null
+++ b/ACE/ace/UPIPE_Connector.h
@@ -0,0 +1,115 @@
+// -*- 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 */
+
+#if defined (ACE_HAS_THREADS)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a new_stream if things go well.
+ * The @a addr is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a reuse_addr == 1 then the
+ * @a local_addr is reused, even if it hasn't been cleanedup yet.
+ * The @a flags and @a 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 @a new_stream if things go well.
+ * The @a addr is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a reuse_addr == 1 then the
+ * @a local_addr is reused, even if it hasn't been cleanedup yet.
+ * The @a flags and @a 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/UPIPE_Connector.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_UPIPE_CONNECTOR_H */
diff --git a/ACE/ace/UPIPE_Connector.inl b/ACE/ace/UPIPE_Connector.inl
new file mode 100644
index 00000000000..24252234f2e
--- /dev/null
+++ b/ACE/ace/UPIPE_Connector.inl
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Creates a Local ACE_UPIPE.
+ACE_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_TEXT ("address %s, %p\n"),
+ addr.get_path_name (),
+ ACE_TEXT ("ACE_UPIPE_Connector")));
+}
+
+ACE_INLINE int
+ACE_UPIPE_Connector::reset_new_handle (ACE_HANDLE /* handle */)
+{
+ // Nothing to do here since the handle is not a socket
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/UPIPE_Stream.cpp b/ACE/ace/UPIPE_Stream.cpp
new file mode 100644
index 00000000000..c1cddb1ab57
--- /dev/null
+++ b/ACE/ace/UPIPE_Stream.cpp
@@ -0,0 +1,231 @@
+// $Id$
+
+#include "ace/UPIPE_Stream.h"
+
+ACE_RCSID(ace, UPIPE_Stream, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_string.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/UPIPE_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Stream)
+
+ACE_UPIPE_Stream::ACE_UPIPE_Stream (void)
+ : mb_last_ (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 ();
+ this->mb_last_ = 0;
+ }
+}
+
+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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_UPIPE_Stream::dump");
+#endif /* ACE_HAS_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.
+
+ssize_t
+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
+ : static_cast<ssize_t> (n);
+}
+
+// Receive a buffer.
+
+ssize_t
+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.
+ size_t this_len = this->mb_last_->length ();
+ if (this_len < n)
+ {
+ // The remaining data is not enough.
+
+ ACE_OS::memcpy ((void *) &buffer[bytes_read],
+ this->mb_last_->rd_ptr (),
+ this_len);
+ bytes_read += this_len;
+ this->mb_last_ = this->mb_last_->release (); // mb_last_ now 0
+ return static_cast<ssize_t> (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);
+
+ if (this->mb_last_->length () == 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 static_cast<ssize_t> (bytes_read);
+ else
+ return -1;
+ }
+ }
+
+ return static_cast<ssize_t> (bytes_read);
+}
+
+ssize_t
+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;
+}
+
+ssize_t
+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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/ace/UPIPE_Stream.h b/ACE/ace/UPIPE_Stream.h
new file mode 100644
index 00000000000..87bcf82d1e2
--- /dev/null
+++ b/ACE/ace/UPIPE_Stream.h
@@ -0,0 +1,140 @@
+// -*- 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 */
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/SPIPE.h"
+#include "ace/Message_Queue.h"
+#include "ace/UPIPE_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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;
+
+ typedef ACE_Stream<ACE_SYNCH> MT_Stream;
+
+ // = 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 @a n bytes through the message queue. Returns -1
+ /// on error, else number of bytes sent.
+ ssize_t send (const char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout = 0);
+
+ /// Recv a buffer of upto @a n bytes from the message queue. Returns
+ /// -1 on error, else number of bytes read.
+ ssize_t recv (char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout = 0);
+
+ /// Send a buffer of exactly @a n bytes to the message queue. Returns
+ /// -1 on error, else number of bytes written (which should == n).
+ ssize_t send_n (const char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout = 0);
+
+ /// Recv a buffer of exactly @a n bytes from the message queue.
+ /// Returns -1 on error, else the number of bytes read.
+ ssize_t 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;
+
+ // = Meta-type info
+ typedef ACE_UPIPE_Addr PEER_ADDR;
+
+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_;
+
+ /// Address of who we are connected to.
+ ACE_UPIPE_Addr remote_addr_;
+
+ /// Stream component used by the @c UPIPE_Acceptor and
+ /// @c UPIPE_Connector to link together two UPIPE_Streams.
+ MT_Stream stream_;
+
+ /// Keep track of whether the sender and receiver have both shutdown.
+ 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 */
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/UPIPE_Stream.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_THREADS */
+
+#include /**/ "ace/post.h"
+
+#endif /*ACE_UPIPE_STREAM_H */
diff --git a/ACE/ace/UPIPE_Stream.inl b/ACE/ace/UPIPE_Stream.inl
new file mode 100644
index 00000000000..3a33d287b0b
--- /dev/null
+++ b/ACE/ace/UPIPE_Stream.inl
@@ -0,0 +1,14 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE ACE_HANDLE
+ACE_UPIPE_Stream::get_handle (void) const
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::get_handle");
+ return this->ACE_SPIPE::get_handle ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/UTF16_Encoding_Converter.cpp b/ACE/ace/UTF16_Encoding_Converter.cpp
new file mode 100644
index 00000000000..d57ab9e5154
--- /dev/null
+++ b/ACE/ace/UTF16_Encoding_Converter.cpp
@@ -0,0 +1,364 @@
+// $Id$
+
+// ======================================================================
+//
+// The actual conversion methods are covered by the copyright information
+// below. It is not the actual code provided by Unicode, Inc. but is an
+// ACE-ified and only slightly modified version.
+// Chad Elliott 4/28/2005
+//
+// Copyright 2001-2004 Unicode, Inc.
+//
+// Limitations on Rights to Redistribute This Code
+//
+// Unicode, Inc. hereby grants the right to freely use the information
+// supplied in this file in the creation of products supporting the
+// Unicode Standard, and to make copies of this file in any form
+// for internal or external distribution as long as this notice
+// remains attached.
+//
+// ======================================================================
+
+#include "ace/UTF16_Encoding_Converter.h"
+
+#if defined (ACE_USES_WCHAR)
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_Memory.h"
+#include "ace/Min_Max.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/UTF16_Encoding_Converter.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+static const ACE_UINT32 halfShift = 10;
+static const ACE_UINT32 halfBase = 0x00010000;
+static const ACE_UINT32 halfMask = 0x000003FF;
+
+static const ACE_UINT32 UNI_SUR_HIGH_START = 0x0000D800;
+static const ACE_UINT32 UNI_SUR_HIGH_END = 0x0000DBFF;
+static const ACE_UINT32 UNI_SUR_LOW_START = 0x0000DC00;
+static const ACE_UINT32 UNI_SUR_LOW_END = 0x0000DFFF;
+static const ACE_UINT32 UNI_REPLACEMENT_CHAR = 0x0000FFFD;
+static const ACE_UINT32 UNI_MAX_BMP = 0x0000FFFF;
+static const ACE_UINT32 UNI_MAX_UTF16 = 0x0010FFFF;
+
+// Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+// into the first byte, depending on how many bytes follow. There are
+// as many entries in this table as there are UTF-8 sequence types.
+// (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+// for *legal* UTF-8 will be 4 or fewer bytes total.
+static const ACE_Byte firstByteMark[7] = { 0x00, 0x00, 0xC0,
+ 0xE0, 0xF0, 0xF8, 0xFC };
+
+// Index into the table below with the first byte of a UTF-8 sequence to
+// get the number of trailing bytes that are supposed to follow it.
+// Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+// left as-is for anyone who may want to do such conversion, which was
+// allowed in earlier algorithms.
+static const ACE_Byte trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+// Magic values subtracted from a buffer value during UTF8 conversion.
+// This table contains as many values as there might be trailing bytes
+// in a UTF-8 sequence.
+static const ACE_UINT32 offsetsFromUTF8[6] = { 0x00000000, 0x00003080,
+ 0x000E2080, 0x03C82080,
+ 0xFA082080, 0x82082080 };
+
+
+ACE_UTF16_Encoding_Converter::ACE_UTF16_Encoding_Converter (bool swap)
+ : swap_ (swap)
+{
+}
+
+ACE_UTF16_Encoding_Converter::~ACE_UTF16_Encoding_Converter (void)
+{
+}
+
+ACE_UTF16_Encoding_Converter::Result
+ACE_UTF16_Encoding_Converter::to_utf8 (const void* source,
+ size_t source_size,
+ ACE_Byte* target,
+ size_t target_size,
+ bool strict)
+{
+ static const ACE_UINT32 byteMask = 0xBF;
+ static const ACE_UINT32 byteMark = 0x80;
+ Result result = CONVERSION_OK;
+
+ ACE_Byte* targetEnd = target + target_size;
+ const ACE_UINT16* sourceStart = static_cast<const ACE_UINT16*> (source);
+ const ACE_UINT16* sourceEnd = sourceStart +
+ (source_size / sizeof (ACE_UINT16));
+
+ while (sourceStart < sourceEnd)
+ {
+ ACE_UINT16 nw = *sourceStart++;
+ ACE_UINT32 ch = (this->swap_ ? ACE_SWAP_WORD (nw) : nw);
+
+ // If we have a surrogate pair, convert to ACE_UINT32 first.
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END)
+ {
+ // If the 16 bits following the high surrogate are in the
+ // sourceStart buffer...
+ if (sourceStart < sourceEnd)
+ {
+ ACE_UINT32 ch2 = (this->swap_ ? ACE_SWAP_WORD (*sourceStart) :
+ *sourceStart);
+ // If it's a low surrogate, convert to ACE_UINT32.
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END)
+ {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++sourceStart;
+ }
+ else if (strict)
+ {
+ // it's an unpaired high surrogate
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+ }
+ else
+ {
+ // We don't have the 16 bits following the high surrogate.
+ result = SOURCE_EXHAUSTED;
+ break;
+ }
+ }
+ else if (strict)
+ {
+ // UTF-16 surrogate values are illegal in UTF-32
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+ }
+
+ // Figure out how many bytes the result will require
+ unsigned short bytesToWrite = 0;
+ if (ch < 0x80)
+ bytesToWrite = 1;
+ else if (ch < 0x800)
+ bytesToWrite = 2;
+ else if (ch < 0x10000)
+ bytesToWrite = 3;
+ else if (ch < 0x110000)
+ bytesToWrite = 4;
+ else
+ {
+ bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd)
+ {
+ result = TARGET_EXHAUSTED;
+ break;
+ }
+
+ // NOTE: Everything falls through for efficiency purposes.
+ switch (bytesToWrite)
+ {
+ case 4:
+ *--target = (ACE_Byte)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 3:
+ *--target = (ACE_Byte)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 2:
+ *--target = (ACE_Byte)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 1:
+ *--target = (ACE_Byte)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+
+ return result;
+}
+
+ACE_UTF16_Encoding_Converter::Result
+ACE_UTF16_Encoding_Converter::from_utf8 (const ACE_Byte* source,
+ size_t source_size,
+ void* target,
+ size_t target_size,
+ bool strict)
+{
+ Result result = CONVERSION_OK;
+ const ACE_Byte* sourceEnd = source + source_size;
+ ACE_UINT16* targetStart = static_cast<ACE_UINT16*> (target);
+ ACE_UINT16* targetEnd = targetStart + target_size;
+
+ while (source < sourceEnd)
+ {
+ ACE_UINT32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd)
+ {
+ result = SOURCE_EXHAUSTED;
+ break;
+ }
+
+ // Do this check whether lenient or strict
+ if (!this->is_legal_utf8 (source, extraBytesToRead + 1))
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+
+ // The cases all fall through. See "Note A" below.
+ switch (extraBytesToRead)
+ {
+ case 5: // remember, illegal UTF-8
+ ch += *source++;
+ ch <<= 6;
+ case 4: // remember, illegal UTF-8
+ ch += *source++;
+ ch <<= 6;
+ case 3:
+ ch += *source++;
+ ch <<= 6;
+ case 2:
+ ch += *source++;
+ ch <<= 6;
+ case 1:
+ ch += *source++;
+ ch <<= 6;
+ case 0:
+ ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (targetStart >= targetEnd)
+ {
+ result = TARGET_EXHAUSTED;
+ break;
+ }
+
+ if (ch <= UNI_MAX_BMP) // Target is a character <= 0xFFFF
+ {
+ // UTF-16 surrogate values are illegal in UTF-32
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
+ {
+ if (strict)
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+ else
+ {
+ *targetStart++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ else
+ {
+ *targetStart++ = (ACE_UINT16)ch;
+ }
+ }
+ else if (ch > UNI_MAX_UTF16)
+ {
+ if (strict)
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+ else
+ {
+ *targetStart++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ else
+ {
+ // targetStart is a character in range 0xFFFF - 0x10FFFF.
+ if (targetStart + 1 >= targetEnd)
+ {
+ result = TARGET_EXHAUSTED;
+ break;
+ }
+ ch -= halfBase;
+ *targetStart++ = (ACE_UINT16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *targetStart++ = (ACE_UINT16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+
+ return result;
+}
+
+ACE_UTF16_Encoding_Converter*
+ACE_UTF16_Encoding_Converter::encoded (const ACE_Byte* source,
+ size_t source_size)
+{
+ static const size_t begin = 16;
+ static const size_t converted = begin * 4;
+
+ ACE_Byte target[converted];
+ ACE_UTF16_Encoding_Converter* converter;
+ ACE_NEW_RETURN (converter,
+ ACE_UTF16_Encoding_Converter (false),
+ 0);
+ if (converter->to_utf8 (source,
+ ACE_MIN (begin, source_size),
+ target,
+ converted) == CONVERSION_OK)
+ {
+ return converter;
+ }
+ else
+ {
+ delete converter;
+ }
+
+ return 0;
+}
+
+ACE_UINT32
+ACE_UTF16_Encoding_Converter::get_UNI_SUR_HIGH_START (void)
+{
+ return UNI_SUR_HIGH_START;
+}
+
+ACE_UINT32
+ACE_UTF16_Encoding_Converter::get_UNI_SUR_LOW_END (void)
+{
+ return UNI_SUR_LOW_END;
+}
+
+ACE_UINT32
+ACE_UTF16_Encoding_Converter::get_UNI_REPLACEMENT_CHAR (void)
+{
+ return UNI_REPLACEMENT_CHAR;
+}
+
+const ACE_Byte*
+ACE_UTF16_Encoding_Converter::get_first_byte_mark (void)
+{
+ return firstByteMark;
+}
+
+const ACE_Byte*
+ACE_UTF16_Encoding_Converter::get_trailing_bytes_for_utf8 (void)
+{
+ return trailingBytesForUTF8;
+}
+
+const ACE_UINT32*
+ACE_UTF16_Encoding_Converter::get_offsets_from_utf8 (void)
+{
+ return offsetsFromUTF8;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
diff --git a/ACE/ace/UTF16_Encoding_Converter.h b/ACE/ace/UTF16_Encoding_Converter.h
new file mode 100644
index 00000000000..82d8255b286
--- /dev/null
+++ b/ACE/ace/UTF16_Encoding_Converter.h
@@ -0,0 +1,86 @@
+// -*- C++ -*-
+
+//=========================================================================
+/**
+ * @file UTF16_Encoding_Converter.h
+ *
+ * $Id$
+ *
+ * This class contains declarations for methods that convert between
+ * UTF-16 (both BE and LE) and UTF-8
+ *
+ * @author Chad Elliott <elliott_c@ociweb.com>
+ */
+//=========================================================================
+
+#ifndef ACE_UTF16_ENCODING_CONVERTER_H
+#define ACE_UTF16_ENCODING_CONVERTER_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Encoding_Converter.h"
+
+#if defined (ACE_USES_WCHAR)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/** Convert from UTF-16 to UTF-8 and from UTF-8 to UTF-16.
+ * This class implements the ACE_Encoding_Converter interface.
+ */
+class ACE_UTF16_Encoding_Converter: public ACE_Encoding_Converter
+{
+public:
+ /// The swap parameter determines whether we need to swap byte order on
+ /// the stream as each word is pulled off when converting to UTF-8.
+ ACE_UTF16_Encoding_Converter (bool swap = false);
+
+ /// This is a do nothing destructor.
+ virtual ~ACE_UTF16_Encoding_Converter (void);
+
+ /// Convert the source from UTF-16 to UTF-8 and store it in the
+ /// provided target buffer.
+ virtual Result to_utf8 (const void* source,
+ size_t source_size,
+ ACE_Byte* target,
+ size_t target_size,
+ bool strict = true);
+
+ /// Convert the UTF-8 source into a UTF-16 encoding and store it
+ /// in the provided target buffer.
+ virtual Result from_utf8 (const ACE_Byte* source,
+ size_t source_size,
+ void* target,
+ size_t target_size,
+ bool strict = true);
+
+ /// This factory helper method determines if the source stream is UTF-16
+ /// encoded. If it is, allocate an ACE_UTF16_Encoding_Converter and
+ /// return it. The caller then owns the allocated object.
+ static ACE_UTF16_Encoding_Converter* encoded (const ACE_Byte* source,
+ size_t source_size);
+
+protected:
+ /// Determines if the source buffer is legal UTF-8
+ bool is_legal_utf8 (const ACE_Byte* source,
+ size_t length) const;
+
+ static ACE_UINT32 get_UNI_SUR_HIGH_START (void);
+ static ACE_UINT32 get_UNI_SUR_LOW_END (void);
+ static ACE_UINT32 get_UNI_REPLACEMENT_CHAR (void);
+ static const ACE_Byte* get_first_byte_mark (void);
+ static const ACE_Byte* get_trailing_bytes_for_utf8 (void);
+ static const ACE_UINT32* get_offsets_from_utf8 (void);
+
+ bool swap_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/UTF16_Encoding_Converter.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_USES_WCHAR */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_UTF16_ENCODING_CONVERTER_H */
diff --git a/ACE/ace/UTF16_Encoding_Converter.inl b/ACE/ace/UTF16_Encoding_Converter.inl
new file mode 100644
index 00000000000..1c716092092
--- /dev/null
+++ b/ACE/ace/UTF16_Encoding_Converter.inl
@@ -0,0 +1,76 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ======================================================================
+//
+// The actual conversion methods are covered by the copyright information
+// below.
+// Chad Elliott 4/28/2005
+//
+// Copyright 2001-2004 Unicode, Inc.
+//
+// Limitations on Rights to Redistribute This Code
+//
+// Unicode, Inc. hereby grants the right to freely use the information
+// supplied in this file in the creation of products supporting the
+// Unicode Standard, and to make copies of this file in any form
+// for internal or external distribution as long as this notice
+// remains attached.
+//
+// ======================================================================
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE bool
+ACE_UTF16_Encoding_Converter::is_legal_utf8 (const ACE_Byte* source,
+ size_t length) const
+{
+ ACE_Byte a;
+ const ACE_Byte* srcptr = source + length;
+
+ switch (length)
+ {
+ default:
+ return false;
+
+ // Everything else falls through when "true"...
+ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 2: if ((a = (*--srcptr)) > 0xBF) return false;
+
+ switch (*source)
+ {
+ // no fall-through in this inner switch
+ case 0xE0:
+ if (a < 0xA0)
+ return false;
+ break;
+ case 0xED:
+ if (a > 0x9F)
+ return false;
+ break;
+ case 0xF0:
+ if (a < 0x90)
+ return false;
+ break;
+ case 0xF4:
+ if (a > 0x8F)
+ return false;
+ break;
+ default:
+ if (a < 0x80)
+ return false;
+ }
+
+ case 1:
+ if (*source >= 0x80 && *source < 0xC2)
+ return false;
+ }
+
+ if (*source > 0xF4)
+ return false;
+
+ return true;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/UTF32_Encoding_Converter.cpp b/ACE/ace/UTF32_Encoding_Converter.cpp
new file mode 100644
index 00000000000..2280232e58a
--- /dev/null
+++ b/ACE/ace/UTF32_Encoding_Converter.cpp
@@ -0,0 +1,254 @@
+// $Id$
+
+// ======================================================================
+//
+// The actual conversion methods are covered by the copyright information
+// below. It is not the actual code provided by Unicode, Inc. but is an
+// ACE-ified and only slightly modified version.
+//
+// Chad Elliott 4/28/2005
+//
+// Copyright 2001-2004 Unicode, Inc.
+//
+// Limitations on Rights to Redistribute This Code
+//
+// Unicode, Inc. hereby grants the right to freely use the information
+// supplied in this file in the creation of products supporting the
+// Unicode Standard, and to make copies of this file in any form
+// for internal or external distribution as long as this notice
+// remains attached.
+//
+// ======================================================================
+
+#include "ace/UTF32_Encoding_Converter.h"
+
+#if defined (ACE_USES_WCHAR)
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_Memory.h"
+#include "ace/Min_Max.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+static const ACE_UINT32 UNI_MAX_LEGAL_UTF32 = 0x0010FFFF;
+
+ACE_UTF32_Encoding_Converter::ACE_UTF32_Encoding_Converter (bool swap)
+ : ACE_UTF16_Encoding_Converter (swap)
+{
+}
+
+ACE_UTF32_Encoding_Converter::~ACE_UTF32_Encoding_Converter (void)
+{
+}
+
+ACE_UTF32_Encoding_Converter::Result
+ACE_UTF32_Encoding_Converter::to_utf8 (const void* source,
+ size_t source_size,
+ ACE_Byte* target,
+ size_t target_size,
+ bool strict)
+{
+ static const ACE_UINT32 byteMask = 0xBF;
+ static const ACE_UINT32 byteMark = 0x80;
+ static const ACE_UINT32 UNI_SUR_HIGH_START = get_UNI_SUR_HIGH_START ();
+ static const ACE_UINT32 UNI_SUR_LOW_END = get_UNI_SUR_LOW_END ();
+ static const ACE_Byte* firstByteMark = get_first_byte_mark ();
+
+ Result result = CONVERSION_OK;
+ ACE_Byte* targetEnd = target + target_size;
+ const ACE_UINT32* sourceStart = static_cast<const ACE_UINT32*> (source);
+ const ACE_UINT32* sourceEnd = sourceStart + (source_size / sizeof (ACE_UINT32));
+
+ while (sourceStart < sourceEnd)
+ {
+ ACE_UINT32 nw = *sourceStart++;
+ ACE_UINT32 ch = (this->swap_ ? ACE_SWAP_LONG (nw) : nw);
+ unsigned short bytesToWrite = 0;
+
+ if (strict)
+ {
+ // UTF-16 surrogate values are illegal in UTF-32
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+ }
+
+ // Figure out how many bytes the result will require. Turn any
+ // illegally large ACE_UINT32 things (> Plane 17) into replacement
+ // chars.
+ if (ch < 0x80)
+ {
+ bytesToWrite = 1;
+ }
+ else if (ch < 0x800)
+ {
+ bytesToWrite = 2;
+ }
+ else if (ch < 0x10000)
+ {
+ bytesToWrite = 3;
+ }
+ else if (ch <= UNI_MAX_LEGAL_UTF32)
+ {
+ bytesToWrite = 4;
+ }
+ else
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd)
+ {
+ result = TARGET_EXHAUSTED;
+ break;
+ }
+
+ // NOTE: everything falls through.
+ switch (bytesToWrite)
+ {
+ case 4:
+ *--target = (ACE_Byte)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 3:
+ *--target = (ACE_Byte)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 2:
+ *--target = (ACE_Byte)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 1:
+ *--target = (ACE_Byte) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+
+ return result;
+}
+
+ACE_UTF32_Encoding_Converter::Result
+ACE_UTF32_Encoding_Converter::from_utf8 (const ACE_Byte* source,
+ size_t source_size,
+ void* target,
+ size_t target_size,
+ bool strict)
+{
+ static const ACE_UINT32 UNI_SUR_HIGH_START = get_UNI_SUR_HIGH_START ();
+ static const ACE_UINT32 UNI_SUR_LOW_END = get_UNI_SUR_LOW_END ();
+ static const ACE_UINT32 UNI_REPLACEMENT_CHAR = get_UNI_REPLACEMENT_CHAR ();
+ static const ACE_Byte* trailingBytesForUTF8 = get_trailing_bytes_for_utf8 ();
+ static const ACE_UINT32* offsetsFromUTF8 = get_offsets_from_utf8 ();
+
+ Result result = CONVERSION_OK;
+ const ACE_Byte* sourceEnd = source + source_size;
+ ACE_UINT32* targetStart = static_cast<ACE_UINT32*> (target);
+ ACE_UINT32* targetEnd = targetStart + target_size;
+
+ while (source < sourceEnd)
+ {
+ ACE_UINT32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd)
+ {
+ result = SOURCE_EXHAUSTED;
+ break;
+ }
+
+ // Do this check whether lenient or strict
+ if (!this->is_legal_utf8 (source, extraBytesToRead + 1))
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+
+ // The cases all fall through. See "Note A" below.
+ switch (extraBytesToRead)
+ {
+ case 5:
+ ch += *source++;
+ ch <<= 6;
+ case 4:
+ ch += *source++;
+ ch <<= 6;
+ case 3:
+ ch += *source++;
+ ch <<= 6;
+ case 2:
+ ch += *source++;
+ ch <<= 6;
+ case 1:
+ ch += *source++;
+ ch <<= 6;
+ case 0:
+ ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (targetStart >= targetEnd)
+ {
+ result = TARGET_EXHAUSTED;
+ break;
+ }
+
+ if (ch <= UNI_MAX_LEGAL_UTF32)
+ {
+ // UTF-16 surrogate values are illegal in UTF-32, and anything
+ // over Plane 17 (> 0x10FFFF) is illegal.
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
+ {
+ if (strict)
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+ else
+ {
+ *targetStart++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ else
+ {
+ *targetStart++ = ch;
+ }
+ }
+ else
+ {
+ result = SOURCE_ILLEGAL;
+ break;
+ }
+ }
+
+ return result;
+}
+
+ACE_UTF32_Encoding_Converter*
+ACE_UTF32_Encoding_Converter::encoded (const ACE_Byte* source,
+ size_t source_size)
+{
+ static const size_t begin = 16;
+ static const size_t converted = begin * 4;
+
+ ACE_Byte target[converted];
+ ACE_UTF32_Encoding_Converter* converter = 0;
+ ACE_NEW_RETURN (converter,
+ ACE_UTF32_Encoding_Converter (false),
+ 0);
+
+ if (converter->to_utf8 (source,
+ ACE_MIN (begin, source_size),
+ target,
+ converted) == CONVERSION_OK)
+ {
+ return converter;
+ }
+ else
+ {
+ delete converter;
+ }
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
diff --git a/ACE/ace/UTF32_Encoding_Converter.h b/ACE/ace/UTF32_Encoding_Converter.h
new file mode 100644
index 00000000000..3777d2eff0a
--- /dev/null
+++ b/ACE/ace/UTF32_Encoding_Converter.h
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+
+//=========================================================================
+/**
+ * @file UTF32_Encoding_Converter.h
+ *
+ * $Id$
+ *
+ * This class contains declarations for methods that convert between
+ * UTF-32 (both BE and LE) and UTF-8
+ *
+ * @author Chad Elliott <elliott_c@ociweb.com>
+ */
+//=========================================================================
+
+#ifndef ACE_UTF32_ENCODING_CONVERTER_H
+#define ACE_UTF32_ENCODING_CONVERTER_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/UTF16_Encoding_Converter.h"
+
+#if defined (ACE_USES_WCHAR)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/** Convert from UTF-32 to UTF-8 and from UTF-8 to UTF-32.
+ * This class implements the ACE_Encoding_Converter interface.
+ */
+class ACE_UTF32_Encoding_Converter: public ACE_UTF16_Encoding_Converter
+{
+public:
+ /// This class has some similarities to the UTF16 converter, so
+ /// we just construct our base class and pass the swap parameter.
+ ACE_UTF32_Encoding_Converter (bool swap = false);
+
+ /// This is a do nothing destructor.
+ virtual ~ACE_UTF32_Encoding_Converter (void);
+
+ /// Convert the source from UTF-32 to UTF-8 and store it in the
+ /// provided target buffer.
+ virtual Result to_utf8 (const void* source,
+ size_t source_size,
+ ACE_Byte* target,
+ size_t target_size,
+ bool strict = true);
+
+ /// Convert the UTF-8 source into a UTF-32 encoding and store it
+ /// in the provided target buffer.
+ virtual Result from_utf8 (const ACE_Byte* source,
+ size_t source_size,
+ void* target,
+ size_t target_size,
+ bool strict = true);
+
+ /// This factory helper method determines if the source stream is UTF-32
+ /// encoded. If it is, allocate an ACE_UTF32_Encoding_Converter and
+ /// return it. The caller then owns the allocated object.
+ static ACE_UTF32_Encoding_Converter* encoded (const ACE_Byte* source,
+ size_t source_size);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_UTF32_ENCODING_CONVERTER_H */
diff --git a/ACE/ace/UTF8_Encoding_Converter.cpp b/ACE/ace/UTF8_Encoding_Converter.cpp
new file mode 100644
index 00000000000..0a6ee6e54f5
--- /dev/null
+++ b/ACE/ace/UTF8_Encoding_Converter.cpp
@@ -0,0 +1,92 @@
+// $Id$
+
+#include "ace/UTF8_Encoding_Converter.h"
+
+#if defined (ACE_USES_WCHAR)
+#include "ace/UTF16_Encoding_Converter.h"
+#include "ace/UTF32_Encoding_Converter.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Memory.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_UTF8_Encoding_Converter::ACE_UTF8_Encoding_Converter (void)
+ : native_ (0)
+{
+ // Choose a converter for the ASCII or UTF-8 string to a wide character
+ // string which we will use in from_utf8. We have to make an
+ // assumption here about the encoding based on the size of ACE_TCHAR.
+ switch (sizeof (ACE_TCHAR))
+ {
+ case 4:
+ ACE_NEW(this->native_, ACE_UTF32_Encoding_Converter);
+ break;
+ case 2:
+ ACE_NEW(this->native_, ACE_UTF16_Encoding_Converter);
+ break;
+ }
+}
+
+ACE_UTF8_Encoding_Converter::~ACE_UTF8_Encoding_Converter (void)
+{
+ delete native_;
+}
+
+ACE_UTF8_Encoding_Converter::Result
+ACE_UTF8_Encoding_Converter::to_utf8 (const void* source,
+ size_t source_size,
+ ACE_Byte* target,
+ size_t target_size,
+ bool /*strict*/)
+{
+ if (target_size >= source_size)
+ {
+ ACE_OS::memcpy (target, source, source_size);
+ return CONVERSION_OK;
+ }
+
+ return TARGET_EXHAUSTED;
+}
+
+ACE_UTF8_Encoding_Converter::Result
+ACE_UTF8_Encoding_Converter::from_utf8 (const ACE_Byte* source,
+ size_t source_size,
+ void* target,
+ size_t target_size,
+ bool strict)
+{
+ if (this->native_ != 0)
+ {
+ return this->native_->from_utf8(source, source_size,
+ target, target_size, strict);
+ }
+
+ ACE_TCHAR* targetStart = static_cast<ACE_TCHAR*> (target);
+ ACE_OS::strncpy (targetStart,
+ ACE_TEXT_CHAR_TO_TCHAR (
+ reinterpret_cast<const char*> (source)),
+ source_size);
+ targetStart[source_size] = 0;
+ return CONVERSION_OK;
+}
+
+ACE_UTF8_Encoding_Converter*
+ACE_UTF8_Encoding_Converter::encoded (const ACE_Byte* source,
+ size_t source_size)
+{
+ for(size_t i = 0; i < source_size; i++)
+ {
+ if (source[i] < 0x01 || source[i] > 0x7f)
+ return 0;
+ }
+
+ // All characters are "valid" ASCII
+ ACE_UTF8_Encoding_Converter* converter = 0;
+ ACE_NEW_RETURN (converter,
+ ACE_UTF8_Encoding_Converter,
+ 0);
+ return converter;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
diff --git a/ACE/ace/UTF8_Encoding_Converter.h b/ACE/ace/UTF8_Encoding_Converter.h
new file mode 100644
index 00000000000..4ef6fb7fad3
--- /dev/null
+++ b/ACE/ace/UTF8_Encoding_Converter.h
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+
+//=========================================================================
+/**
+ * @file UTF8_Encoding_Converter.h
+ *
+ * $Id$
+ *
+ * This class contains declarations for methods that convert between
+ * UTF-8 and the native ACE_TCHAR representation.
+ *
+ * @author Chad Elliott <elliott_c@ociweb.com>
+ */
+//=========================================================================
+
+#ifndef ACE_UTF8_ENCODING_CONVERTER_H
+#define ACE_UTF8_ENCODING_CONVERTER_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Encoding_Converter.h"
+
+#if defined (ACE_USES_WCHAR)
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/** Convert from UTF-16 or UTF-32 to UTF-8.
+ * This class implements the ACE_Encoding_Converter interface.
+ */
+class ACE_UTF8_Encoding_Converter: public ACE_Encoding_Converter
+{
+public:
+ /// Allocate the converter to be used by the from_utf8() method based
+ /// on the size of the native wide character.
+ ACE_UTF8_Encoding_Converter (void);
+
+ /// De-allocate the native converter.
+ virtual ~ACE_UTF8_Encoding_Converter (void);
+
+ /// Since the source *must be* UTF-8, there is no conversion required.
+ /// This method just copies the source to the target given that there
+ /// is enough space.
+ virtual Result to_utf8 (const void* source,
+ size_t source_size,
+ ACE_Byte* target,
+ size_t target_size,
+ bool strict = true);
+
+ /// Utilize the native converter to convert the UTF-8 source into an
+ /// alternate encoding and store it in the provided target buffer.
+ virtual Result from_utf8 (const ACE_Byte* source,
+ size_t source_size,
+ void* target,
+ size_t target_size,
+ bool strict = true);
+
+
+ /// This factory helper method determines if the source stream is UTF-8
+ /// encoded. If it is, allocate an ACE_UTF8_Encoding_Converter and
+ /// return it. The caller then owns the allocated object.
+ static ACE_UTF8_Encoding_Converter* encoded (const ACE_Byte* source,
+ size_t source_size);
+
+private:
+ ACE_Encoding_Converter* native_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+#endif /* ACE_USES_WCHAR */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_UTF8_ENCODING_CONVERTER_H */
diff --git a/ACE/ace/UUID.cpp b/ACE/ace/UUID.cpp
new file mode 100644
index 00000000000..f65475b3cf8
--- /dev/null
+++ b/ACE/ace/UUID.cpp
@@ -0,0 +1,554 @@
+//$Id$
+
+#include "ace/UUID.h"
+#include "ace/Guard_T.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/UUID.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/ACE.h"
+
+ACE_RCSID (ace,
+ UUID,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_Utils
+{
+ UUID_Node::UUID_Node (void)
+ {
+ for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
+ node_ID_[i] = 0;
+ }
+
+ UUID_Node::Node_ID&
+ UUID_Node::node_ID (void)
+ {
+ return node_ID_;
+ }
+
+ void
+ UUID_Node::node_ID (Node_ID& node_ID)
+ {
+ for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
+ node_ID_[i] = node_ID[i];
+ }
+
+ UUID UUID::NIL_UUID;
+
+ /// Construct a nil UUID. Such a UUID has every one of it's data
+ /// elements set to zero.
+ UUID::UUID (void)
+ : time_low_ (0),
+ time_mid_ (0),
+ time_hi_and_version_ (0),
+ clock_seq_hi_and_reserved_ (0),
+ clock_seq_low_ (0),
+ node_ (0),
+ node_release_ (true),
+ as_string_ (0)
+ {
+ ACE_NEW (node_,
+ UUID_Node);
+ }
+
+ /// Construct a UUID from a string representation of an UUID.
+ UUID::UUID (const ACE_CString& uuid_string)
+ : time_low_ (0),
+ time_mid_ (0),
+ time_hi_and_version_ (0),
+ clock_seq_hi_and_reserved_ (0),
+ clock_seq_low_ (0),
+ node_ (0),
+ node_release_ (true),
+ as_string_ (0)
+ {
+ ACE_NEW (node_,
+ UUID_Node);
+
+ this->from_string_i (uuid_string);
+ }
+
+ UUID::UUID (const UUID &right)
+ : time_low_ (right.time_low_),
+ time_mid_ (right.time_mid_),
+ time_hi_and_version_ (right.time_hi_and_version_),
+ clock_seq_hi_and_reserved_ (right.clock_seq_hi_and_reserved_),
+ clock_seq_low_ (right.clock_seq_low_),
+ as_string_ (0)
+ {
+ ACE_NEW (node_,
+ UUID_Node (*right.node_));
+ }
+
+ UUID::~UUID (void)
+ {
+ if (node_release_)
+ delete node_;
+
+ if (as_string_ != 0)
+ delete as_string_;
+ }
+
+ const ACE_CString*
+ UUID::to_string (void)
+ {
+ /// Only compute the string representation once.
+ if (as_string_ == 0)
+ {
+ // Get a buffer exactly the correct size. Use the nil UUID as a
+ // gauge. Don't forget the trailing nul.
+ size_t UUID_STRING_LENGTH = 36 + thr_id_.length () + pid_.length ();
+ char *buf = 0;
+
+ if ((thr_id_.length () != 0) && (pid_.length () != 0))
+ {
+ UUID_STRING_LENGTH += 2; //for '-'
+ ACE_NEW_RETURN (buf,
+ char[UUID_STRING_LENGTH + 1],
+ 0);
+
+ ACE_OS::sprintf (buf,
+ "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x-%s-%s",
+ this->time_low_,
+ this->time_mid_,
+ this->time_hi_and_version_,
+ this->clock_seq_hi_and_reserved_,
+ this->clock_seq_low_,
+ (this->node_->node_ID ()) [0],
+ (this->node_->node_ID ()) [1],
+ (this->node_->node_ID ()) [2],
+ (this->node_->node_ID ()) [3],
+ (this->node_->node_ID ()) [4],
+ (this->node_->node_ID ()) [5],
+ thr_id_.c_str (),
+ pid_.c_str ()
+ );
+ }
+ else
+ {
+ ACE_NEW_RETURN (buf,
+ char[UUID_STRING_LENGTH + 1],
+ 0);
+
+ ACE_OS::sprintf (buf,
+ "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
+ this->time_low_,
+ this->time_mid_,
+ this->time_hi_and_version_,
+ this->clock_seq_hi_and_reserved_,
+ this->clock_seq_low_,
+ (this->node_->node_ID ()) [0],
+ (this->node_->node_ID ()) [1],
+ (this->node_->node_ID ()) [2],
+ (this->node_->node_ID ()) [3],
+ (this->node_->node_ID ()) [4],
+ (this->node_->node_ID ()) [5]
+ );
+ }
+
+ // We allocated 'buf' above dynamically, so we shouldn't use
+ // ACE_NEW_RETURN here to avoid a possible memory leak.
+ ACE_NEW_NORETURN (this->as_string_,
+ ACE_CString (buf, UUID_STRING_LENGTH));
+
+ // we first free the dynamically allocated 'buf'.
+ delete [] buf;
+
+ // then we test that ACE_NEW succeded for 'as_string_'
+ // if not, we return 0 (NULL) to indicate failure.
+ if (this->as_string_ == 0 )
+ return 0;
+ }
+
+ return as_string_;
+ }
+
+ void
+ UUID::from_string_i (const ACE_CString& uuid_string)
+ {
+ if (uuid_string.length () < NIL_UUID.to_string ()->length ())
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%N ACE_UUID::from_string_i - "
+ "IllegalArgument (incorrect string length)\n"));
+ return;
+ }
+
+ /// Special case for the nil UUID.
+ if (uuid_string == *NIL_UUID.to_string ())
+ {
+ bool copy_constructor_not_supported = false;
+ ACE_ASSERT (copy_constructor_not_supported);
+ //*this = NIL_UUID;
+ ACE_UNUSED_ARG (copy_constructor_not_supported);
+ return;
+ }
+
+ unsigned int time_low;
+ unsigned int time_mid;
+ unsigned int time_hi_and_version;
+ unsigned int clock_seq_hi_and_reserved;
+ unsigned int clock_seq_low;
+ unsigned int node [UUID_Node::NODE_ID_SIZE];
+ char thr_pid_buf [BUFSIZ];
+
+ if (uuid_string.length () == NIL_UUID.to_string ()->length ())
+ {
+ // This might seem quite strange this being in ACE, but it
+ // seems to be a bit difficult to write a facade for ::sscanf
+ // because some compilers dont support vsscanf, including
+ // MSVC. It appears that most platforms support sscanf though
+ // so we need to use it directly.
+ const int nScanned =
+#if defined (ACE_HAS_TR24731_2005_CRT)
+ sscanf_s (
+#else
+ ::sscanf (
+#endif /* ACE_HAS_TR24731_2005_CRT */
+ uuid_string.c_str (),
+ "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
+ &time_low,
+ &time_mid,
+ &time_hi_and_version,
+ &clock_seq_hi_and_reserved,
+ &clock_seq_low,
+ &node[0],
+ &node[1],
+ &node[2],
+ &node[3],
+ &node[4],
+ &node[5]
+ );
+
+ if (nScanned != 11)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "UUID::from_string_i - "
+ "IllegalArgument (invalid string representation)\n"));
+ return;
+ }
+ }
+ else
+ {
+ const int nScanned =
+#if defined (ACE_HAS_TR24731_2005_CRT)
+ sscanf_s (uuid_string.c_str (),
+ "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
+ &time_low,
+ &time_mid,
+ &time_hi_and_version,
+ &clock_seq_hi_and_reserved,
+ &clock_seq_low,
+ &node[0],
+ &node[1],
+ &node[2],
+ &node[3],
+ &node[4],
+ &node[5],
+ thr_pid_buf,
+ BUFSIZ
+ );
+#else
+ ::sscanf (uuid_string.c_str (),
+ "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
+ &time_low,
+ &time_mid,
+ &time_hi_and_version,
+ &clock_seq_hi_and_reserved,
+ &clock_seq_low,
+ &node[0],
+ &node[1],
+ &node[2],
+ &node[3],
+ &node[4],
+ &node[5],
+ thr_pid_buf
+ );
+#endif /* ACE_HAS_TR24731_2005_CRT */
+
+ if (nScanned != 12)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_UUID::from_string_i - "
+ "IllegalArgument (invalid string representation)\n"));
+ return;
+ }
+ }
+
+ this->time_low_ = static_cast<ACE_UINT32> (time_low);
+ this->time_mid_ = static_cast<ACE_UINT16> (time_mid);
+ this->time_hi_and_version_ = static_cast<ACE_UINT16> (time_hi_and_version);
+ this->clock_seq_hi_and_reserved_ = static_cast<u_char> (clock_seq_hi_and_reserved);
+ this->clock_seq_low_ = static_cast<u_char> (clock_seq_low);
+
+ UUID_Node::Node_ID node_id;
+ for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
+ node_id [i] = static_cast<u_char> (node[i]);
+
+ this->node_->node_ID (node_id);
+
+ // Support varient 10- only
+ if ((this->clock_seq_hi_and_reserved_ & 0xc0) != 0x80 && (this->clock_seq_hi_and_reserved_ & 0xc0) != 0xc0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_UUID::from_string_i - "
+ "IllegalArgument (unsupported variant)\n"));
+ return;
+ }
+
+ /// Support versions 1, 3, and 4 only
+ ACE_UINT16 V1 = this->time_hi_and_version_;
+
+ if ((V1 & 0xF000) != 0x1000 &&
+ (V1 & 0xF000) != 0x3000 &&
+ (V1 & 0xF000) != 0x4000)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_UUID::from_string_i - "
+ "IllegalArgument (unsupported version)\n"));
+ return;
+ }
+
+ if ((this->clock_seq_hi_and_reserved_ & 0xc0) == 0xc0)
+ {
+ if (uuid_string.length () == NIL_UUID.to_string ()->length ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_UUID::from_string_i - "
+ "IllegalArgument (Missing Thread and Process Id)\n"));
+ return;
+ }
+ ACE_CString thr_pid_str (thr_pid_buf);
+ ssize_t pos = static_cast<ssize_t> (thr_pid_str.find ('-'));
+ if (pos == -1)
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_UUID::from_string_i - "
+ "IllegalArgument (Thread and Process Id format incorrect)\n"));
+
+ this->thr_id_ = thr_pid_str.substr (0, pos);
+ this->pid_ = thr_pid_str.substr (pos+1, thr_pid_str.length ()-pos-1);
+ }
+ }
+
+ UUID_Generator::UUID_Generator ()
+ : time_last_ (0),
+ destroy_lock_ (true)
+ {
+ ACE_NEW (lock_,
+ ACE_SYNCH_MUTEX);
+ }
+
+ UUID_Generator::~UUID_Generator ()
+ {
+ if (destroy_lock_)
+ delete lock_;
+ }
+
+ void
+ UUID_Generator::init (void)
+ {
+ ACE_OS::macaddr_node_t macaddress;
+ int result = ACE_OS::getmacaddress (&macaddress);
+
+ UUID_Node::Node_ID node_id;
+ if (result != -1)
+ {
+// ACE_DEBUG ((LM_DEBUG,
+// "%02X-%02X-%02X-%02X-%02X-%02X\n",
+// macaddress.node [0],
+// macaddress.node [1],
+// macaddress.node [2],
+// macaddress.node [3],
+// macaddress.node [4],
+// macaddress.node [5]));
+
+ ACE_OS::memcpy (&node_id,
+ macaddress.node,
+ sizeof (node_id));
+ }
+ else
+ {
+ node_id [0] = static_cast<u_char> (ACE_OS::rand ());
+ node_id [1] = static_cast<u_char> (ACE_OS::rand ());
+ node_id [2] = static_cast<u_char> (ACE_OS::rand ());
+ node_id [3] = static_cast<u_char> (ACE_OS::rand ());
+ node_id [4] = static_cast<u_char> (ACE_OS::rand ());
+ node_id [5] = static_cast<u_char> (ACE_OS::rand ());
+ }
+
+ this->get_timestamp (time_last_);
+
+ {
+ ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, *lock_);
+ uuid_state_.timestamp = time_last_;
+ uuid_state_.node.node_ID (node_id);
+ }
+ }
+
+ void
+ UUID_Generator::generate_UUID (UUID& uuid,ACE_UINT16 version,
+ u_char variant)
+ {
+ UUID_Time timestamp;
+ ACE_UINT16 clock_sequence;
+
+ this->get_timestamp_and_clocksequence (timestamp,
+ clock_sequence);
+
+ // Construct a Version 1 UUID with the information in the arguements.
+ uuid.time_low (static_cast<ACE_UINT32> (timestamp & 0xFFFFFFFF));
+ uuid.time_mid (static_cast<ACE_UINT16> ((timestamp >> 32) & 0xFFFF));
+
+ ACE_UINT16 tHAV = static_cast<ACE_UINT16> ((timestamp >> 48) & 0xFFFF);
+ tHAV |= (version << 12);
+ uuid.time_hi_and_version (tHAV);
+
+ u_char cseqHAV;
+ uuid.clock_seq_low (static_cast<u_char> (clock_sequence & 0xFF));
+ cseqHAV = static_cast<u_char> ((clock_sequence & 0x3f00) >> 8);
+ uuid_state_.timestamp = timestamp;
+
+ cseqHAV |= variant;
+ uuid.clock_seq_hi_and_reserved (cseqHAV);
+ uuid.node (& (uuid_state_.node));
+
+ if (variant == 0xc0)
+ {
+ ACE_Thread_ID thread_id;
+ char buf [BUFSIZ];
+ thread_id.to_string (buf);
+ uuid.thr_id (buf);
+
+ ACE_OS::sprintf (buf,
+ "%d",
+ static_cast<int> (ACE_OS::getpid ()));
+ uuid.pid (buf);
+ }
+ }
+
+ UUID*
+ UUID_Generator::generate_UUID (ACE_UINT16 version, u_char variant)
+ {
+ UUID* uuid;
+ ACE_NEW_RETURN (uuid,
+ UUID,
+ 0);
+
+ this->generate_UUID (*uuid, version, variant);
+ return uuid;
+ }
+
+ /// Obtain a new timestamp. If UUID's are being generated too quickly
+ /// the clock sequence will be incremented
+ void
+ UUID_Generator::get_timestamp (UUID_Time& timestamp)
+ {
+ ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
+
+ this->get_systemtime (timestamp);
+
+ // Account for the clock being set back. Increment the clock /
+ // sequence.
+ if (timestamp <= time_last_)
+ {
+ uuid_state_.clock_sequence = static_cast<ACE_UINT16>
+ ((uuid_state_.clock_sequence + 1) & ACE_UUID_CLOCK_SEQ_MASK);
+ }
+ // If the system time ticked since the last UUID was
+ // generated. Set / the clock sequence back.
+ else if (timestamp > time_last_)
+ {
+ uuid_state_.clock_sequence = 0;
+ }
+
+ time_last_ = timestamp;
+ }
+
+ void
+ UUID_Generator::get_timestamp_and_clocksequence (UUID_Time& timestamp,
+ ACE_UINT16& clock_sequence)
+ {
+ ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
+
+ this->get_systemtime (timestamp);
+
+ // Account for the clock being set back. Increment the clock /
+ // sequence.
+ if (timestamp <= time_last_)
+ uuid_state_.clock_sequence = static_cast<u_char> ((uuid_state_.clock_sequence + 1) & ACE_UUID_CLOCK_SEQ_MASK);
+
+ // If the system time ticked since the last UUID was
+ // generated. Set / the clock sequence back.
+ else if (timestamp > time_last_)
+ uuid_state_.clock_sequence = 0;
+
+ time_last_ = timestamp;
+ clock_sequence = uuid_state_.clock_sequence;
+ }
+
+ /**
+ * ACE_Time_Value is in POSIX time, seconds since Jan 1, 1970. UUIDs use
+ * time in 100ns ticks since 15 October 1582. The difference is:
+ * 15 Oct 1582 - 1 Jan 1600: 17 days in Oct, 30 in Nov, 31 in Dec +
+ * 17 years and 4 leap days (1584, 88, 92 and 96)
+ * 1 Jan 1600 - 1 Jan 1900: 3 centuries + 73 leap days ( 25 in 17th cent.
+ * and 24 each in 18th and 19th centuries)
+ * 1 Jan 1900 - 1 Jan 1970: 70 years + 17 leap days.
+ * This adds up, in days: (17+30+31+365*17+4)+ (365*300+73)+ (365*70+17) or
+ * 122192928000000000U (0x1B21DD213814000) 100 ns ticks.
+ */
+ void
+ UUID_Generator::get_systemtime (UUID_Time & timestamp)
+ {
+ const UUID_Time timeOffset =
+#if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+ ACE_U_LongLong (ACE_INT64_LITERAL (0x1B21DD213814000));
+#elif defined (ACE_LACKS_LONGLONG_T)
+ ACE_U_LongLong (0x13814000u, 0x1B21DD2u);
+#else
+ ACE_UINT64_LITERAL (0x1B21DD213814000);
+#endif /* ACE_LACKS_UNSIGNEDLONGLONG_T */
+
+ /// Get the time of day, convert to 100ns ticks then add the offset.
+ ACE_Time_Value now = ACE_OS::gettimeofday ();
+ ACE_UINT64 time;
+ now.to_usec (time);
+ time = time * 10;
+ timestamp = time + timeOffset;
+}
+
+ ACE_SYNCH_MUTEX*
+ UUID_Generator::lock (void)
+ {
+ return this->lock_;
+ }
+
+ void
+ UUID_Generator::lock (ACE_SYNCH_MUTEX* lock,
+ bool release_lock)
+ {
+ if (this->destroy_lock_)
+ delete this->lock_;
+
+ this->lock_ = lock;
+ this->destroy_lock_ = release_lock;
+ }
+
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX> *
+ ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/UUID.h b/ACE/ace/UUID.h
new file mode 100644
index 00000000000..5be6a4c065a
--- /dev/null
+++ b/ACE/ace/UUID.h
@@ -0,0 +1,239 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UUID.h
+ *
+ * $Id$
+ *
+ * @author Andrew T. Finnel <andrew@activesol.net>
+ * @author Yamuna Krishnmaurthy <yamuna@oomworks.com>
+ */
+//=============================================================================
+
+#ifndef ACE_UUID_H
+#define ACE_UUID_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/SString.h"
+#include "ace/Singleton.h"
+#include "ace/Synch_Traits.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_Utils
+{
+ /// Class to hold a MAC address
+ class ACE_Export UUID_Node
+ {
+ public:
+
+ /// Constructor
+ UUID_Node (void);
+
+ enum {NODE_ID_SIZE = 6};
+ typedef u_char Node_ID[NODE_ID_SIZE];
+
+ Node_ID &node_ID (void);
+ void node_ID (Node_ID&);
+
+ ///// Equality Operations
+ bool operator == (const UUID_Node& right) const;
+ bool operator != (const UUID_Node& right) const;
+
+ ///// Relational Operations
+ //bool operator < (const UUID_Node& right) const;
+
+ private:
+ Node_ID node_ID_;
+ };
+
+ /**
+ * @class ACE_UUID
+ *
+ * ACE_UUID represents a Universally Unique IDentifier (UUID) as
+ * described in (the expired) INTERNET-DRAFT specification entitled
+ * UUIDs and GUIDs. All instances of UUID are of the time-based
+ * variety. That is, the version number part of the timeHiAndVersion
+ * field is 1.
+ *
+ * The default constructor creates a nil UUID.
+ *
+ * UUIDs have value semantics. In addition, they may be compared for
+ * ordering and equality.
+ *
+ * Additionally in this implementation provisions have been made to include
+ * process and thread ids to make the UUIDs more unique. The variant 0xc0
+ * has been added to facilitate this.
+ */
+ class ACE_Export UUID
+ {
+ public:
+
+ /// Constructor
+ UUID (void);
+
+ /// Constructs a UUID from a string representation.
+ UUID (const ACE_CString& uuidString);
+
+ UUID (const UUID &right);
+
+ // Destructor
+ ~UUID (void);
+
+ ACE_UINT32 time_low (void) const;
+ void time_low (ACE_UINT32);
+
+ ACE_UINT16 time_mid (void) const;
+ void time_mid (ACE_UINT16);
+
+ ACE_UINT16 time_hi_and_version (void) const;
+ void time_hi_and_version (ACE_UINT16);
+
+ u_char clock_seq_hi_and_reserved (void) const;
+ void clock_seq_hi_and_reserved (u_char);
+
+ u_char clock_seq_low (void) const;
+ void clock_seq_low (u_char);
+
+ UUID_Node* node (void) const;
+ void node (UUID_Node*);
+
+ ACE_CString* thr_id (void);
+ void thr_id (char*);
+
+ ACE_CString* pid (void);
+ void pid (char*);
+
+ /// Returns a string representation of the UUID
+ const ACE_CString* to_string (void);
+
+ /// Set the value using a string
+ void from_string (const ACE_CString& uuid_string);
+
+ static UUID NIL_UUID;
+
+ /// Equality Operations
+ bool operator== (const UUID &right) const;
+ bool operator!= (const UUID &right) const;
+
+ /// Relational Operations
+ //bool operator< (const UUID &right) const;
+ //bool operator> (const UUID &right) const;
+ //bool operator<= (const UUID &right) const;
+ //bool operator>= (const UUID &right) const;
+
+ private:
+ void from_string_i (const ACE_CString& uuid_string);
+
+ UUID& operator= (const UUID&);
+
+ /// Data Members for Class Attributes
+ ACE_UINT32 time_low_;
+ ACE_UINT16 time_mid_;
+ ACE_UINT16 time_hi_and_version_;
+ u_char clock_seq_hi_and_reserved_;
+ u_char clock_seq_low_;
+ UUID_Node* node_;
+ bool node_release_;
+ ACE_CString thr_id_;
+ ACE_CString pid_;
+
+ /// The string representation of the UUID. This is created and
+ /// updated only on demand.
+ ACE_CString *as_string_;
+ };
+
+ /**
+ * @class ACE_UUID_Generator
+ *
+ * Singleton class that generates UUIDs.
+ *
+ */
+ class ACE_Export UUID_Generator
+ {
+ public:
+
+ enum {ACE_UUID_CLOCK_SEQ_MASK = 0x3FFF};
+
+ UUID_Generator();
+ ~UUID_Generator();
+
+ void init (void);
+
+ /// Format timestamp, clockseq, and nodeID into an UUID of the
+ /// specified version and variant. For generating UUID's with
+ /// thread and process ids use variant=0xc0
+ void generate_UUID (UUID&, ACE_UINT16 version=0x0001, u_char variant=0x80);
+
+ /// Format timestamp, clockseq, and nodeID into a VI UUID. For
+ /// generating UUID's with thread and process ids use variant=0xc0
+ UUID* generate_UUID (ACE_UINT16 version=0x0001, u_char variant=0x80);
+
+ /// Type to represent UTC as a count of 100 nanosecond intervals
+ /// since 00:00:00.00, 15 October 1582.
+ typedef ACE_UINT64 UUID_Time;
+
+ /// The locking strategy prevents multiple generators from accessing
+ /// the UUID_state at the same time. Get the locking strategy.
+ ACE_SYNCH_MUTEX* lock (void);
+
+ /// Set a new locking strategy and return the old one.
+ void lock (ACE_SYNCH_MUTEX* lock,
+ bool release_lock);
+
+ private:
+
+ /// The system time when that last uuid was generated.
+ UUID_Time time_last_;
+
+ /// Type to contain the UUID generator persistent state. This will
+ /// be kept in memory mapped shared memory
+ struct UUID_State
+ {
+ UUID_Time timestamp;
+ UUID_Node node;
+ ACE_UINT16 clock_sequence;
+ };
+
+ /// Obtain a UUID timestamp. Compensate for the fact that the time
+ /// obtained from getSystem time has a resolution less than 100ns.
+ void get_timestamp (UUID_Time& timestamp);
+
+ /// Obtain a UUID timestamp and clock sequence. Compensate for the
+ /// fact that the time obtained from getSystem time has a
+ /// resolution less than 100ns.
+ void get_timestamp_and_clocksequence (UUID_Time& timestamp,
+ ACE_UINT16& clockSequence);
+
+ /// Obtain the system time in UTC as a count of 100 nanosecond intervals
+ /// since 00:00:00.00, 15 October 1582 (the date of Gregorian reform to
+ /// the Christian calendar).
+ void get_systemtime( UUID_Time& timeNow);
+
+ /// The UUID generator persistent state.
+ UUID_State uuid_state_;
+
+ ACE_SYNCH_MUTEX* lock_;
+ bool destroy_lock_;
+ };
+
+ typedef ACE_Singleton<UUID_Generator, ACE_SYNCH_MUTEX> UUID_GENERATOR;
+
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/UUID.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif // ACE_UUID_H
+
diff --git a/ACE/ace/UUID.inl b/ACE/ace/UUID.inl
new file mode 100644
index 00000000000..89526473b0a
--- /dev/null
+++ b/ACE/ace/UUID.inl
@@ -0,0 +1,200 @@
+// -*- C++ -*-
+//
+//$Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE_Utils
+{
+
+ /// Data Members for Class Attributes
+ ACE_INLINE ACE_UINT32
+ UUID::time_low (void) const
+ {
+ return this->time_low_;
+ }
+
+ ACE_INLINE void
+ UUID::time_low (ACE_UINT32 timelow)
+ {
+ this->time_low_ = timelow;
+ }
+
+ ACE_INLINE ACE_UINT16
+ UUID::time_mid (void) const
+ {
+ return this->time_mid_;
+ }
+
+ ACE_INLINE void
+ UUID::time_mid (ACE_UINT16 time_mid)
+ {
+ this->time_mid_ = time_mid;
+ }
+
+ ACE_INLINE ACE_UINT16
+ UUID::time_hi_and_version (void) const
+ {
+ return this->time_hi_and_version_;
+ }
+
+ ACE_INLINE void
+ UUID::time_hi_and_version (ACE_UINT16 time_hi_and_version)
+ {
+ this->time_hi_and_version_ = time_hi_and_version;
+ }
+
+ ACE_INLINE u_char
+ UUID::clock_seq_hi_and_reserved (void) const
+ {
+ return this->clock_seq_hi_and_reserved_;
+ }
+
+ ACE_INLINE void
+ UUID::clock_seq_hi_and_reserved (u_char clock_seq_hi_and_reserved)
+ {
+ this->clock_seq_hi_and_reserved_ = clock_seq_hi_and_reserved;
+ }
+
+ ACE_INLINE u_char
+ UUID::clock_seq_low (void) const
+ {
+ return this->clock_seq_low_;
+ }
+
+ ACE_INLINE void
+ UUID::clock_seq_low (u_char clock_seq_low)
+ {
+ this->clock_seq_low_ = clock_seq_low;
+ }
+
+ ACE_INLINE UUID_Node*
+ UUID::node (void) const
+ {
+ return this->node_;
+ }
+
+ ACE_INLINE void
+ UUID::node (UUID_Node* node)
+ {
+ if (node_release_)
+ delete node_;
+
+ this->node_ = node;
+ node_release_ = false;
+ }
+
+ ACE_INLINE ACE_CString*
+ UUID::thr_id (void)
+ {
+ return &this->thr_id_;
+ }
+
+ ACE_INLINE void
+ UUID::thr_id (char* thr_id)
+ {
+ this->thr_id_ = thr_id;
+ }
+
+ ACE_INLINE ACE_CString*
+ UUID::pid (void)
+ {
+ return &this->pid_;
+ }
+
+ ACE_INLINE void
+ UUID::pid (char* pid)
+ {
+ this->pid_ = pid;
+ }
+
+ ACE_INLINE void
+ UUID::from_string (const ACE_CString& uuidString)
+ {
+ this->from_string_i (uuidString);
+ }
+
+ ACE_INLINE bool
+ UUID::operator == (const UUID &right) const
+ {
+ if ((this->time_low_ != right.time_low ()) ||
+ (this->time_mid_ != right.time_mid ()) ||
+ (this->time_hi_and_version_ != right.time_hi_and_version ()) ||
+ (this->clock_seq_hi_and_reserved_ != right.clock_seq_hi_and_reserved ()) ||
+ (this->clock_seq_low_ != right.clock_seq_low ()) ||
+ (*this->node_ != *right.node ()))
+ return false;
+
+ return true;
+ }
+
+ ACE_INLINE bool
+ UUID::operator != (const UUID &right) const
+ {
+ return !(*this == right);
+ }
+
+// ACE_INLINE bool
+//UUID::operator < (const UUID &rt) const
+// {
+// UUID right (rt);
+// if ((timeLow_ < right.timeLow ()) ||
+// (timeMid_ < right.timeMid ()) ||
+// (timeHiAndVersion_ < right.timeHiAndVersion ()) ||
+// (clockSeqHiAndReserved_ < right.clockSeqHiAndReserved ()) ||
+// (clockSeqLow_ < right.clockSeqLow ()) ||
+// (node_ < right.node ()))
+// {
+// return true;
+// }
+//
+// return false;
+// }
+//
+// ACE_INLINE bool
+// UUID::operator > (const UUID &right) const
+// {
+// return right < *this;
+// }
+//
+// ACE_INLINE bool
+// UUID::operator <= (const UUID &right) const
+// {
+// return !(*this > right);
+// }
+//
+// ACE_INLINE bool
+// UUID::operator >= (const UUID &right) const
+// {
+// return !(*this < right);
+// }
+//
+ ACE_INLINE bool
+ UUID_Node::operator == (const UUID_Node& rt) const
+ {
+ for (size_t i = 0; i < NODE_ID_SIZE; ++i)
+ if (node_ID_ [i] != rt.node_ID_ [i])
+ return false;
+
+ return true;
+ }
+
+ ACE_INLINE bool
+ UUID_Node::operator != (const UUID_Node& right) const
+ {
+ return !(*this == right);
+ }
+
+// ACE_INLINE bool
+// UUID_node::operator < (const UUID_node& rt) const
+// {
+// UUID_node right = rt;
+// for (size_t i = 0; i < NODE_ID_SIZE; ++i)
+// if (nodeID_ [i] < right.nodeID ()[i])
+// return true;
+//
+// return false;
+// }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Unbounded_Queue.cpp b/ACE/ace/Unbounded_Queue.cpp
new file mode 100644
index 00000000000..96a1603952a
--- /dev/null
+++ b/ACE/ace/Unbounded_Queue.cpp
@@ -0,0 +1,434 @@
+// $Id$
+
+#ifndef ACE_UNBOUNDED_QUEUE_CPP
+#define ACE_UNBOUNDED_QUEUE_CPP
+
+#include "ace/Unbounded_Queue.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Unbounded_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Malloc_Base.h"
+#include "ace/Log_Msg.h"
+#include "ace/os_include/os_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Queue)
+
+template <class T>
+ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (ACE_Allocator *alloc)
+ : head_ (0),
+ cur_size_ (0),
+ allocator_ (alloc)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (void)");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_NEW_MALLOC (this->head_,
+ (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)),
+ ACE_Node<T>);
+ // Make the list circular by pointing it back to itself.
+ this->head_->next_ = this->head_;
+}
+
+template <class T>
+ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (const ACE_Unbounded_Queue<T> &us)
+ : head_ (0),
+ cur_size_ (0),
+ allocator_ (us.allocator_)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_NEW_MALLOC (this->head_,
+ (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)),
+ ACE_Node<T>);
+ this->head_->next_ = this->head_;
+ this->copy_nodes (us);
+}
+
+template <class T> void
+ACE_Unbounded_Queue<T>::operator= (const ACE_Unbounded_Queue<T> &us)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::operator=");
+
+ if (this != &us)
+ {
+ this->delete_nodes ();
+ this->copy_nodes (us);
+ }
+}
+
+template <class T> ACE_Unbounded_Queue_Iterator<T>
+ACE_Unbounded_Queue<T>::begin (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::begin");
+ return ACE_Unbounded_Queue_Iterator<T> (*this);
+}
+
+template <class T> ACE_Unbounded_Queue_Iterator<T>
+ACE_Unbounded_Queue<T>::end (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::end");
+ return ACE_Unbounded_Queue_Iterator<T> (*this, 1);
+}
+
+template <class T> void
+ACE_Unbounded_Queue<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_ = %u"), this->head_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_->next_ = %u"), this->head_->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d\n"), this->cur_size_));
+
+ T *item = 0;
+#if !defined (ACE_NLOGGING)
+ size_t count = 1;
+#endif /* ! ACE_NLOGGING */
+
+ for (ACE_Unbounded_Queue_Iterator<T> iter (*(ACE_Unbounded_Queue<T> *) this);
+ iter.next (item) != 0;
+ iter.advance ())
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("count = %d\n"), count++));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T> void
+ACE_Unbounded_Queue<T>::copy_nodes (const ACE_Unbounded_Queue<T> &us)
+{
+ for (ACE_Node<T> *curr = us.head_->next_;
+ curr != us.head_;
+ curr = curr->next_)
+ if (this->enqueue_tail (curr->item_) == -1)
+ // @@ What's the right thing to do here?
+ this->delete_nodes ();
+}
+
+template <class T> void
+ACE_Unbounded_Queue<T>::delete_nodes (void)
+{
+ for (ACE_Node<T> *curr = this->head_->next_;
+ // Keep looking until we've hit the dummy node.
+ curr != this->head_;
+ )
+ {
+ ACE_Node<T> *temp = curr;
+ curr = curr->next_;
+
+ ACE_DES_FREE_TEMPLATE (temp,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+ --this->cur_size_;
+ // @@ Doesnt make sense to have this check since
+ // this will always be true.
+ // ACE_ASSERT (this->cur_size_ >= 0);
+ }
+
+ // Reset the list to be a circular list with just a dummy node.
+ this->head_->next_ = this->head_;
+}
+
+template <class T>
+ACE_Unbounded_Queue<T>::~ACE_Unbounded_Queue (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::~ACE_Unbounded_Queue (void)");
+
+ this->delete_nodes ();
+ ACE_DES_FREE_TEMPLATE (head_,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+ this->head_ = 0;
+}
+
+template <class T> int
+ACE_Unbounded_Queue<T>::enqueue_head (const T &new_item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::enqueue_head");
+
+ ACE_Node<T> *temp = 0;
+
+ // Create a new node that points to the original head.
+ ACE_NEW_MALLOC_RETURN (temp,
+ static_cast<ACE_Node<T> *> (this->allocator_->malloc (sizeof (ACE_Node<T>))),
+ ACE_Node<T> (new_item, this->head_->next_),
+ -1);
+ // Link this pointer into the front of the list. Note that the
+ // "real" head of the queue is <head_->next_>, whereas <head_> is
+ // just a pointer to the dummy node.
+ this->head_->next_ = temp;
+
+ ++this->cur_size_;
+ return 0;
+}
+
+template <class T> int
+ACE_Unbounded_Queue<T>::enqueue_tail (const T &new_item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::enqueue_tail");
+
+ // Insert <item> into the old dummy node location. Note that this
+ // isn't actually the "head" item in the queue, it's a dummy node at
+ // the "tail" of the queue...
+ this->head_->item_ = new_item;
+
+ ACE_Node<T> *temp = 0;
+
+ // Create a new dummy node.
+ ACE_NEW_MALLOC_RETURN (temp,
+ static_cast<ACE_Node<T> *> (this->allocator_->malloc (sizeof (ACE_Node<T>))),
+ ACE_Node<T> (this->head_->next_),
+ -1);
+ // Link this dummy pointer into the list.
+ this->head_->next_ = temp;
+
+ // Point the head to the new dummy node.
+ this->head_ = temp;
+
+ ++this->cur_size_;
+ return 0;
+}
+
+template <class T> int
+ACE_Unbounded_Queue<T>::dequeue_head (T &item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::dequeue_head");
+
+ // Check for empty queue.
+ if (this->is_empty ())
+ return -1;
+
+ ACE_Node<T> *temp = this->head_->next_;
+
+ item = temp->item_;
+ this->head_->next_ = temp->next_;
+ ACE_DES_FREE_TEMPLATE (temp,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+ --this->cur_size_;
+ return 0;
+}
+
+template <class T> void
+ACE_Unbounded_Queue<T>::reset (void)
+{
+ ACE_TRACE ("reset");
+
+ this->delete_nodes ();
+}
+
+template <class T> int
+ACE_Unbounded_Queue<T>::get (T *&item, size_t slot) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::get");
+
+ ACE_Node<T> *curr = this->head_->next_;
+
+ size_t i;
+
+ for (i = 0; i < this->cur_size_; i++)
+ {
+ if (i == slot)
+ break;
+
+ curr = curr->next_;
+ }
+
+ if (i < this->cur_size_)
+ {
+ item = &curr->item_;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <class T> int
+ACE_Unbounded_Queue<T>::set (const T &item,
+ size_t slot)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::set");
+
+ ACE_Node<T> *curr = this->head_->next_;
+
+ size_t i;
+
+ for (i = 0;
+ i < slot && i < this->cur_size_;
+ ++i)
+ curr = curr->next_;
+
+ if (i < this->cur_size_)
+ {
+ // We're in range, so everything's cool.
+ curr->item_ = item;
+ return 0;
+ }
+ else
+ {
+ // We need to expand the list.
+
+ // A common case will be increasing the set size by 1.
+ // Therefore, we'll optimize for this case.
+ if (i == slot)
+ {
+ // Try to expand the size of the set by 1.
+ if (this->enqueue_tail (item) == -1)
+ return -1;
+ else
+ return 0;
+ }
+ else
+ {
+ T const dummy = T ();
+
+ // We need to expand the list by multiple (dummy) items.
+ for (; i < slot; ++i)
+ {
+ // This head points to the existing dummy node, which is
+ // about to be overwritten when we add the new dummy
+ // node.
+ curr = this->head_;
+
+ // Try to expand the size of the set by 1, but don't
+ // store anything in the dummy node (yet).
+ if (this->enqueue_tail (dummy) == -1)
+ return -1;
+ }
+
+ curr->item_ = item;
+ return 0;
+ }
+ }
+}
+
+// ****************************************************************
+
+template <class T> void
+ACE_Unbounded_Queue_Const_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Unbounded_Queue_Const_Iterator<T>::ACE_Unbounded_Queue_Const_Iterator (const ACE_Unbounded_Queue<T> &q, int end)
+ : current_ (end == 0 ? q.head_->next_ : q.head_ ),
+ queue_ (q)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::ACE_Unbounded_Queue_Const_Iterator");
+}
+
+template <class T> int
+ACE_Unbounded_Queue_Const_Iterator<T>::advance (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::advance");
+ this->current_ = this->current_->next_;
+ return this->current_ != this->queue_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Queue_Const_Iterator<T>::first (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::first");
+ this->current_ = this->queue_.head_->next_;
+ return this->current_ != this->queue_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Queue_Const_Iterator<T>::done (void) const
+{
+ ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::done");
+
+ return this->current_ == this->queue_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Queue_Const_Iterator<T>::next (T *&item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::next");
+ if (this->current_ == this->queue_.head_)
+ return 0;
+ else
+ {
+ item = &this->current_->item_;
+ return 1;
+ }
+}
+
+// ****************************************************************
+
+template <class T> void
+ACE_Unbounded_Queue_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Unbounded_Queue_Iterator<T>::ACE_Unbounded_Queue_Iterator (ACE_Unbounded_Queue<T> &q, int end)
+ : current_ (end == 0 ? q.head_->next_ : q.head_ ),
+ queue_ (q)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::ACE_Unbounded_Queue_Iterator");
+}
+
+template <class T> int
+ACE_Unbounded_Queue_Iterator<T>::advance (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::advance");
+ this->current_ = this->current_->next_;
+ return this->current_ != this->queue_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Queue_Iterator<T>::first (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::first");
+ this->current_ = this->queue_.head_->next_;
+ return this->current_ != this->queue_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Queue_Iterator<T>::done (void) const
+{
+ ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::done");
+
+ return this->current_ == this->queue_.head_;
+}
+
+template <class T> int
+ACE_Unbounded_Queue_Iterator<T>::next (T *&item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::next");
+ if (this->current_ == this->queue_.head_)
+ return 0;
+ else
+ {
+ item = &this->current_->item_;
+ return 1;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_UNBOUNDED_QUEUE_CPP */
diff --git a/ACE/ace/Unbounded_Queue.h b/ACE/ace/Unbounded_Queue.h
new file mode 100644
index 00000000000..ae70125ffbd
--- /dev/null
+++ b/ACE/ace/Unbounded_Queue.h
@@ -0,0 +1,297 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Unbounded_Queue.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_UNBOUNDED_QUEUE_H
+#define ACE_UNBOUNDED_QUEUE_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Node.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_stddef.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Allocator;
+
+template <class T>
+class ACE_Unbounded_Queue;
+
+/**
+ * @class ACE_Unbounded_Queue_Iterator
+ *
+ * @brief Implement an iterator over an unbounded queue.
+ */
+template <class T>
+class ACE_Unbounded_Queue_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Unbounded_Queue_Iterator (ACE_Unbounded_Queue<T> &q, int end = 0);
+
+ // = Iteration methods.
+
+ /// Pass back the @a next_item that hasn't been seen in the queue.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (T *&next_item);
+
+ /// Move forward by one element in the set. Returns 0 when all the
+ /// items in the queue have been seen, else 1.
+ int advance (void);
+
+ /// Move to the first element in the queue. Returns 0 if the
+ /// queue is empty, else 1.
+ int first (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to the current node in the iteration.
+ ACE_Node<T> *current_;
+
+ /// Pointer to the queue we're iterating over.
+ ACE_Unbounded_Queue<T> &queue_;
+};
+
+/**
+ * @class ACE_Unbounded_Queue_Const_Iterator
+ *
+ * @brief Implement an iterator over an const unbounded queue.
+ */
+template <class T>
+class ACE_Unbounded_Queue_Const_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Unbounded_Queue_Const_Iterator (const ACE_Unbounded_Queue<T> &q, int end = 0);
+
+ // = Iteration methods.
+
+ /// Pass back the @a next_item that hasn't been seen in the queue.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (T *&next_item);
+
+ /// Move forward by one element in the set. Returns 0 when all the
+ /// items in the queue have been seen, else 1.
+ int advance (void);
+
+ /// Move to the first element in the queue. Returns 0 if the
+ /// queue is empty, else 1.
+ int first (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to the current node in the iteration.
+ ACE_Node<T> *current_;
+
+ /// Pointer to the queue we're iterating over.
+ const ACE_Unbounded_Queue<T> &queue_;
+};
+
+/**
+ * @class ACE_Unbounded_Queue
+ *
+ * @brief A Queue of "infinite" length.
+ *
+ * This implementation of an unbounded queue uses a circular
+ * linked list with a dummy node.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Circular linked list
+ * - Duplicates allowed?
+ * Yes
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * N/A
+ * - Insert/replace speed
+ * N/A
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * Yes
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ *
+ */
+template <class T>
+class ACE_Unbounded_Queue
+{
+public:
+ friend class ACE_Unbounded_Queue_Iterator<T>;
+ friend class ACE_Unbounded_Queue_Const_Iterator<T>;
+
+ // Trait definition.
+ typedef ACE_Unbounded_Queue_Iterator<T> ITERATOR;
+ typedef ACE_Unbounded_Queue_Const_Iterator<T> CONST_ITERATOR;
+
+ // = Initialization and termination methods.
+ /// Construction. Use user specified allocation strategy
+ /// if specified.
+ /**
+ * Initialize an empty queue using the strategy provided.
+ */
+ ACE_Unbounded_Queue (ACE_Allocator *alloc = 0);
+
+ /// Copy constructor.
+ /**
+ * Initialize the queue to be a copy of the provided queue.
+ */
+ ACE_Unbounded_Queue (const ACE_Unbounded_Queue<T> &);
+
+ /// Assignment operator.
+ /**
+ * Perform a deep copy of rhs.
+ */
+ void operator= (const ACE_Unbounded_Queue<T> &);
+
+ /// Destructor.
+ /**
+ * Clean up the memory for the queue.
+ */
+ ~ACE_Unbounded_Queue (void);
+
+ // = Check boundary conditions.
+
+ /// Returns 1 if the container is empty, otherwise returns 0.
+ /**
+ * Constant time check to see if the queue is empty.
+ */
+ int is_empty (void) const;
+
+ /// Returns 0.
+ /**
+ * The queue cannot be full, so it always returns 0.
+ */
+ int is_full (void) const;
+
+ // = Classic queue operations.
+
+ /// Adds @a new_item to the tail of the queue. Returns 0 on success,
+ /// -1 on failure.
+ /**
+ * Insert an item at the end of the queue.
+ */
+ int enqueue_tail (const T &new_item);
+
+ /// Adds @a new_item to the head of the queue. Returns 0 on success,
+ /// -1 on failure.
+ /**
+ * Insert an item at the head of the queue.
+ */
+ int enqueue_head (const T &new_item);
+
+ /// Removes and returns the first @a item on the queue. Returns 0 on
+ /// success, -1 if the queue was empty.
+ /**
+ * Remove an item from the head of the queue.
+ */
+ int dequeue_head (T &item);
+
+ // = Additional utility methods.
+
+ /// Reset the ACE_Unbounded_Queue to be empty and release all its
+ /// dynamically allocated resources.
+ /**
+ * Delete the queue nodes.
+ */
+ void reset (void);
+
+ /// Get the @a slot th element in the set. Returns -1 if the element
+ /// isn't in the range {0..#cur_size_ - 1}, else 0.
+ /**
+ * Find the item in the queue between 0 and the provided index of the
+ * queue.
+ */
+ int get (T *&item, size_t slot = 0) const;
+
+ /// Set the @a slot th element of the queue to @a item.
+ /**
+ * Set the @a slot th element in the set. Will pad out the set with
+ * empty nodes if @a slot is beyond the range {0..#cur_size_ - 1}.
+ * Returns -1 on failure, 0 if @a slot isn't initially in range, and
+ * 0 otherwise.
+ */
+ int set (const T &item, size_t slot);
+
+ /// The number of items in the queue.
+ /**
+ * Return the size of the queue.
+ */
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL-styled unidirectional iterator factory.
+ ACE_Unbounded_Queue_Iterator<T> begin (void);
+ ACE_Unbounded_Queue_Iterator<T> end (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Delete all the nodes in the queue.
+ void delete_nodes (void);
+
+ /// Copy nodes into this queue.
+ void copy_nodes (const ACE_Unbounded_Queue<T> &);
+
+ /// Pointer to the dummy node in the circular linked Queue.
+ ACE_Node<T> *head_;
+
+ /// Current size of the queue.
+ size_t cur_size_;
+
+ /// Allocation Strategy of the queue.
+ ACE_Allocator *allocator_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Unbounded_Queue.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Unbounded_Queue.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Unbounded_Queue.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_UNBOUNDED_QUEUE_H */
diff --git a/ACE/ace/Unbounded_Queue.inl b/ACE/ace/Unbounded_Queue.inl
new file mode 100644
index 00000000000..35bb7fb9cdf
--- /dev/null
+++ b/ACE/ace/Unbounded_Queue.inl
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> ACE_INLINE size_t
+ACE_Unbounded_Queue<T>::size (void) const
+{
+ return this->cur_size_;
+}
+
+template <class T> ACE_INLINE int
+ACE_Unbounded_Queue<T>::is_empty (void) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::is_empty");
+ return this->head_ == this->head_->next_;
+}
+
+template <class T> ACE_INLINE int
+ACE_Unbounded_Queue<T>::is_full (void) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Queue<T>::is_full");
+ return 0; // We should implement a "node of last resort for this..."
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Unbounded_Set.cpp b/ACE/ace/Unbounded_Set.cpp
new file mode 100644
index 00000000000..0d7491c0c4d
--- /dev/null
+++ b/ACE/ace/Unbounded_Set.cpp
@@ -0,0 +1,478 @@
+// $Id$
+
+#ifndef ACE_UNBOUNDED_SET_CPP
+#define ACE_UNBOUNDED_SET_CPP
+
+#include "ace/Unbounded_Set.h"
+#include "ace/Malloc_Base.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Unbounded_Set.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Set)
+
+ template <class T> size_t
+ACE_Unbounded_Set<T>::size (void) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::size");
+ return this->cur_size_;
+}
+
+template <class T> int
+ACE_Unbounded_Set<T>::insert_tail (const T &item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::insert_tail");
+ ACE_Node<T> *temp = 0;
+
+ // Insert <item> into the old dummy node location.
+ this->head_->item_ = item;
+
+ // Create a new dummy node.
+ ACE_NEW_MALLOC_RETURN (temp,
+ static_cast<ACE_Node<T>*> (this->allocator_->malloc (sizeof (ACE_Node<T>))),
+ ACE_Node<T> (this->head_->next_),
+ -1);
+ // Link this pointer into the list.
+ this->head_->next_ = temp;
+
+ // Point the head to the new dummy node.
+ this->head_ = temp;
+
+ ++this->cur_size_;
+ return 0;
+}
+
+template <class T> void
+ACE_Unbounded_Set<T>::reset (void)
+{
+ ACE_TRACE ("reset");
+
+ this->delete_nodes ();
+}
+
+template <class T> void
+ACE_Unbounded_Set<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Unbounded_Set<T>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_ = %u"), this->head_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_->next_ = %u"), this->head_->next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d\n"), this->cur_size_));
+
+ T *item = 0;
+#if !defined (ACE_NLOGGING)
+ size_t count = 1;
+#endif /* ! ACE_NLOGGING */
+
+ const_iterator const the_end = this->end ();
+ for (const_iterator i (this->begin ());
+ i != end;
+ ++i)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("count = %u\n"), count++));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T> void
+ACE_Unbounded_Set<T>::copy_nodes (const ACE_Unbounded_Set<T> &us)
+{
+ for (ACE_Node<T> *curr = us.head_->next_;
+ curr != us.head_;
+ curr = curr->next_)
+ this->insert_tail (curr->item_);
+}
+
+template <class T> void
+ACE_Unbounded_Set<T>::delete_nodes (void)
+{
+ ACE_Node<T> *curr = this->head_->next_;
+
+ // Keep looking until we've hit the dummy node.
+
+ while (curr != this->head_)
+ {
+ ACE_Node<T> *temp = curr;
+ curr = curr->next_;
+ ACE_DES_FREE_TEMPLATE (temp,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+ --this->cur_size_;
+ }
+
+ // Reset the list to be a circular list with just a dummy node.
+ this->head_->next_ = this->head_;
+}
+
+template <class T>
+ACE_Unbounded_Set<T>::~ACE_Unbounded_Set (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::~ACE_Unbounded_Set");
+
+ this->delete_nodes ();
+
+ // Delete the dummy node.
+ ACE_DES_FREE_TEMPLATE (head_,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+ this->head_ = 0;
+}
+
+template <class T>
+ACE_Unbounded_Set<T>::ACE_Unbounded_Set (ACE_Allocator *alloc)
+ : head_ (0),
+ cur_size_ (0),
+ allocator_ (alloc)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::ACE_Unbounded_Set");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_NEW_MALLOC (this->head_,
+ (ACE_Node<T>*) this->allocator_->malloc (sizeof (ACE_Node<T>)),
+ ACE_Node<T>);
+ // Make the list circular by pointing it back to itself.
+ this->head_->next_ = this->head_;
+}
+
+template <class T>
+ACE_Unbounded_Set<T>::ACE_Unbounded_Set (const ACE_Unbounded_Set<T> &us)
+ : head_ (0),
+ cur_size_ (0),
+ allocator_ (us.allocator_)
+{
+ ACE_TRACE ("ACE_Unbounded_Set<T>::ACE_Unbounded_Set");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+
+ ACE_NEW_MALLOC (this->head_,
+ (ACE_Node<T>*) this->allocator_->malloc (sizeof (ACE_Node<T>)),
+ ACE_Node<T>);
+ this->head_->next_ = this->head_;
+ this->copy_nodes (us);
+}
+
+template <class T> ACE_Unbounded_Set<T> &
+ACE_Unbounded_Set<T>::operator= (const ACE_Unbounded_Set<T> &us)
+{
+ ACE_TRACE ("ACE_Unbounded_Set<T>::operator=");
+
+ if (this != &us)
+ {
+ this->delete_nodes ();
+ this->copy_nodes (us);
+ }
+
+ return *this;
+}
+
+template <class T> int
+ACE_Unbounded_Set<T>::find (const T &item) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::find");
+ const_iterator const the_end = this->end ();
+ for (const_iterator i = this->begin (); i != the_end; ++i)
+ if ((*i) == item)
+ return 0;
+
+ return -1;
+}
+
+template <class T> int
+ACE_Unbounded_Set<T>::insert (const T &item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::insert");
+ if (this->find (item) == 0)
+ return 1;
+ else
+ return this->insert_tail (item);
+}
+
+template <class T> int
+ACE_Unbounded_Set<T>::remove (const T &item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::remove");
+
+ // Insert the item to be founded into the dummy node.
+ this->head_->item_ = item;
+
+ ACE_Node<T> *curr = this->head_;
+
+ while (!(curr->next_->item_ == item))
+ curr = curr->next_;
+
+ if (curr->next_ == this->head_)
+ return -1; // Item was not found.
+ else
+ {
+ ACE_Node<T> *temp = curr->next_;
+ // Skip over the node that we're deleting.
+ curr->next_ = temp->next_;
+ --this->cur_size_;
+ ACE_DES_FREE_TEMPLATE (temp,
+ this->allocator_->free,
+ ACE_Node,
+ <T>);
+ return 0;
+ }
+}
+
+template <class T> typename ACE_Unbounded_Set<T>::iterator
+ACE_Unbounded_Set<T>::begin (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::begin");
+ return iterator (*this);
+}
+
+template <class T> typename ACE_Unbounded_Set<T>::iterator
+ACE_Unbounded_Set<T>::end (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::end");
+ return iterator (*this, 1);
+}
+
+template <class T> typename ACE_Unbounded_Set<T>::const_iterator
+ACE_Unbounded_Set<T>::begin (void) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::begin");
+ return const_iterator (*this);
+}
+
+template <class T> typename ACE_Unbounded_Set<T>::const_iterator
+ACE_Unbounded_Set<T>::end (void) const
+{
+ // ACE_TRACE ("ACE_Unbounded_Set<T>::end");
+ return const_iterator (*this, 1);
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Set_Iterator)
+
+ template <class T> void
+ACE_Unbounded_Set_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Unbounded_Set_Iterator<T>::ACE_Unbounded_Set_Iterator (
+ ACE_Unbounded_Set<T> &s,
+ bool end)
+ : current_ (!end ? s.head_->next_ : s.head_ ),
+ set_ (&s)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::ACE_Unbounded_Set_Iterator");
+}
+
+template <class T> int
+ACE_Unbounded_Set_Iterator<T>::advance (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::advance");
+ this->current_ = this->current_->next_;
+ return this->current_ != this->set_->head_;
+}
+
+template <class T> int
+ACE_Unbounded_Set_Iterator<T>::first (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::first");
+ this->current_ = this->set_->head_->next_;
+ return this->current_ != this->set_->head_;
+}
+
+template <class T> int
+ACE_Unbounded_Set_Iterator<T>::done (void) const
+{
+ ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::done");
+
+ return this->current_ == this->set_->head_;
+}
+
+template <class T> int
+ACE_Unbounded_Set_Iterator<T>::next (T *&item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::next");
+ if (this->current_ == this->set_->head_)
+ return 0;
+ else
+ {
+ item = &this->current_->item_;
+ return 1;
+ }
+}
+
+template <class T> ACE_Unbounded_Set_Iterator<T>
+ACE_Unbounded_Set_Iterator<T>::operator++ (int)
+{
+ //ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::operator++ (int)");
+ ACE_Unbounded_Set_Iterator<T> retv (*this);
+
+ // postfix operator
+
+ this->advance ();
+ return retv;
+}
+
+template <class T> ACE_Unbounded_Set_Iterator<T>&
+ACE_Unbounded_Set_Iterator<T>::operator++ (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::operator++ (void)");
+
+ // prefix operator
+
+ this->advance ();
+ return *this;
+}
+
+template <class T> T&
+ACE_Unbounded_Set_Iterator<T>::operator* (void)
+{
+ //ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::operator*");
+ T *retv = 0;
+
+ int result = this->next (retv);
+ ACE_ASSERT (result != 0);
+ ACE_UNUSED_ARG (result);
+
+ return *retv;
+}
+
+template <class T> bool
+ACE_Unbounded_Set_Iterator<T>::operator== (const ACE_Unbounded_Set_Iterator<T> &rhs) const
+{
+ //ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::operator==");
+ return (this->set_ == rhs.set_ && this->current_ == rhs.current_);
+}
+
+template <class T> bool
+ACE_Unbounded_Set_Iterator<T>::operator!= (const ACE_Unbounded_Set_Iterator<T> &rhs) const
+{
+ //ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::operator!=");
+ return (this->set_ != rhs.set_ || this->current_ != rhs.current_);
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Set_Const_Iterator)
+
+template <class T> void
+ACE_Unbounded_Set_Const_Iterator<T>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ // ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+template <class T>
+ACE_Unbounded_Set_Const_Iterator<T>::ACE_Unbounded_Set_Const_Iterator (
+ const ACE_Unbounded_Set<T> &s,
+ bool end)
+ : current_ (!end ? s.head_->next_ : s.head_ ),
+ set_ (&s)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::ACE_Unbounded_Set_Const_Iterator");
+}
+
+template <class T> int
+ACE_Unbounded_Set_Const_Iterator<T>::advance (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::advance");
+ this->current_ = this->current_->next_;
+ return this->current_ != this->set_->head_;
+}
+
+template <class T> int
+ACE_Unbounded_Set_Const_Iterator<T>::first (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::first");
+ this->current_ = this->set_->head_->next_;
+ return this->current_ != this->set_->head_;
+}
+
+template <class T> int
+ACE_Unbounded_Set_Const_Iterator<T>::done (void) const
+{
+ ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::done");
+
+ return this->current_ == this->set_->head_;
+}
+
+template <class T> int
+ACE_Unbounded_Set_Const_Iterator<T>::next (T *&item)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::next");
+ if (this->current_ == this->set_->head_)
+ return 0;
+ else
+ {
+ item = &this->current_->item_;
+ return 1;
+ }
+}
+
+template <class T> ACE_Unbounded_Set_Const_Iterator<T>
+ACE_Unbounded_Set_Const_Iterator<T>::operator++ (int)
+{
+ //ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::operator++ (int)");
+ ACE_Unbounded_Set_Const_Iterator<T> retv (*this);
+
+ // postfix operator
+
+ this->advance ();
+ return retv;
+}
+
+template <class T> ACE_Unbounded_Set_Const_Iterator<T>&
+ACE_Unbounded_Set_Const_Iterator<T>::operator++ (void)
+{
+ // ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::operator++ (void)");
+
+ // prefix operator
+
+ this->advance ();
+ return *this;
+}
+
+template <class T> T&
+ACE_Unbounded_Set_Const_Iterator<T>::operator* (void)
+{
+ //ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::operator*");
+ T *retv = 0;
+
+ int const result = this->next (retv);
+ ACE_ASSERT (result != 0);
+ ACE_UNUSED_ARG (result);
+
+ return *retv;
+}
+
+template <class T> bool
+ACE_Unbounded_Set_Const_Iterator<T>::operator== (const ACE_Unbounded_Set_Const_Iterator<T> &rhs) const
+{
+ //ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::operator==");
+ return (this->set_ == rhs.set_ && this->current_ == rhs.current_);
+}
+
+template <class T> bool
+ACE_Unbounded_Set_Const_Iterator<T>::operator!= (const ACE_Unbounded_Set_Const_Iterator<T> &rhs) const
+{
+ //ACE_TRACE ("ACE_Unbounded_Set_Const_Iterator<T>::operator!=");
+ return (this->set_ != rhs.set_ || this->current_ != rhs.current_);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_UNBOUNDED_SET_CPP */
diff --git a/ACE/ace/Unbounded_Set.h b/ACE/ace/Unbounded_Set.h
new file mode 100644
index 00000000000..610ae1733ff
--- /dev/null
+++ b/ACE/ace/Unbounded_Set.h
@@ -0,0 +1,322 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Unbounded_Set.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_UNBOUNDED_SET_H
+#define ACE_UNBOUNDED_SET_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Node.h"
+#include "ace/os_include/os_stddef.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Allocator;
+
+/**
+ * @class ACE_Unbounded_Set_Iterator
+ *
+ * @brief Implement an iterator over an unbounded set.
+ */
+template <class T>
+class ACE_Unbounded_Set_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Unbounded_Set_Iterator (ACE_Unbounded_Set<T> &s, bool end = false);
+
+ // = 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 (T *&next_item);
+
+ /// 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);
+
+ /// Move to the first element in the set. Returns 0 if the
+ /// set is empty, else 1.
+ int first (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Postfix advance.
+ ACE_Unbounded_Set_Iterator<T> operator++ (int);
+
+ /// Prefix advance.
+ ACE_Unbounded_Set_Iterator<T>& operator++ (void);
+
+ /// Returns a reference to the internal element @c this is pointing to.
+ T& operator* (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Unbounded_Set_Iterator<T> &) const;
+ bool operator!= (const ACE_Unbounded_Set_Iterator<T> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /// Pointer to the current node in the iteration.
+ ACE_Node<T> *current_;
+
+ /// Pointer to the set we're iterating over.
+ ACE_Unbounded_Set<T> *set_;
+};
+
+/**
+ * @class ACE_Unbounded_Set_Const_Iterator
+ *
+ * @brief Implement an const iterator over an unbounded set.
+ */
+template <class T>
+class ACE_Unbounded_Set_Const_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Unbounded_Set_Const_Iterator (const ACE_Unbounded_Set<T> &s,
+ bool end = false);
+
+ // = Iteration methods.
+
+ /// Pass back the @a next_item that hasn't been seen in the Set.
+ /// @return Returns 0 when all items have been seen, else 1.
+ int next (T *&next_item);
+
+ /// 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);
+
+ /// Move to the first element in the set. Returns 0 if the
+ /// set is empty, else 1.
+ int first (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = STL styled iteration, compare, and reference functions.
+
+ /// Postfix advance.
+ ACE_Unbounded_Set_Const_Iterator<T> operator++ (int);
+
+ /// Prefix advance.
+ ACE_Unbounded_Set_Const_Iterator<T>& operator++ (void);
+
+ /// Returns a reference to the internal element @c this is pointing to.
+ T& operator* (void);
+
+ /// Check if two iterators point to the same position
+ bool operator== (const ACE_Unbounded_Set_Const_Iterator<T> &) const;
+ bool operator!= (const ACE_Unbounded_Set_Const_Iterator<T> &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /// Pointer to the current node in the iteration.
+ ACE_Node<T> *current_;
+
+ /// Pointer to the set we're iterating over.
+ const ACE_Unbounded_Set<T> *set_;
+};
+
+/**
+ * @class ACE_Unbounded_Set
+ *
+ * @brief Implement a simple unordered set of <T> of unbounded size.
+ *
+ * This implementation of an unordered set uses a circular
+ * linked list with a dummy node. This implementation does not
+ * allow duplicates, but it maintains FIFO ordering of insertions.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * Circular linked list
+ * - Duplicates allowed?
+ * No
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * Linear
+ * - Insert/replace speed
+ * Linear
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * Yes
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ * -# operator==
+ *
+ */
+template <class T>
+class ACE_Unbounded_Set
+{
+public:
+ friend class ACE_Unbounded_Set_Iterator<T>;
+ friend class ACE_Unbounded_Set_Const_Iterator<T>;
+
+ // Trait definition.
+ typedef ACE_Unbounded_Set_Iterator<T> ITERATOR;
+ typedef ACE_Unbounded_Set_Iterator<T> iterator;
+ typedef ACE_Unbounded_Set_Const_Iterator<T> CONST_ITERATOR;
+ typedef ACE_Unbounded_Set_Const_Iterator<T> const_iterator;
+
+ // = Initialization and termination methods.
+ /// Constructor. Use user specified allocation strategy
+ /// if specified.
+ /**
+ * Initialize an empty set using the allocation strategy of the user if
+ * provided.
+ */
+ ACE_Unbounded_Set (ACE_Allocator *alloc = 0);
+
+ /// Copy constructor.
+ /**
+ * Initialize this set to be an exact copy of the set provided.
+ */
+ ACE_Unbounded_Set (const ACE_Unbounded_Set<T> &);
+
+ /// Assignment operator.
+ /**
+ * Perform a deep copy of the rhs into the lhs.
+ */
+ ACE_Unbounded_Set<T> & operator= (const ACE_Unbounded_Set<T> &);
+
+ /// Destructor.
+ /**
+ * Destroy the nodes of the set.
+ */
+ ~ACE_Unbounded_Set (void);
+
+ // = Check boundary conditions.
+
+ /// Returns @c true if the container is empty, otherwise returns @c false.
+ /**
+ * Constant time is_empty check.
+ */
+ bool is_empty (void) const;
+
+ /// Returns @c false.
+ /**
+ * Always returns @c false since the set can never fill up.
+ */
+ bool is_full (void) const;
+
+ // = Classic unordered set operations.
+
+ /// Linear insertion of an item.
+ /**
+ * Insert @a new_item into the set (doesn't allow duplicates).
+ * Returns -1 if failures occur, 1 if item is already present, else
+ * 0.
+ */
+ int insert (const T &new_item);
+
+ /// Insert @a item at the tail of the set (doesn't check for
+ /// duplicates).
+ /**
+ * Constant time insert at the end of the set.
+ */
+ int insert_tail (const T &item);
+
+ /// Linear remove operation.
+ /**
+ * Remove first occurrence of @a item from the set. Returns 0 if
+ * it removes the item, -1 if it can't find the item, and -1 if a
+ * failure occurs.
+ */
+ int remove (const T &item);
+
+ /// Finds if @a item occurs in the set. Returns 0 if find succeeds,
+ /// else -1.
+ /**
+ * Performs a linear find operation.
+ */
+ int find (const T &item) const;
+
+ /// Size of the set.
+ /**
+ * Access the size of the set.
+ */
+ size_t size (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Reset the ACE_Unbounded_Set to be empty.
+ /**
+ * Delete the nodes of the set.
+ */
+ void reset (void);
+
+ // = STL-styled unidirectional iterator factory.
+ iterator begin (void);
+ iterator end (void);
+ const_iterator begin (void) const;
+ const_iterator end (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Delete all the nodes in the Set.
+ void delete_nodes (void);
+
+ /// Copy nodes into this set.
+ void copy_nodes (const ACE_Unbounded_Set<T> &);
+
+ /// Head of the linked list of Nodes.
+ ACE_Node<T> *head_;
+
+ /// Current size of the set.
+ size_t cur_size_;
+
+ /// Allocation strategy of the set.
+ ACE_Allocator *allocator_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Unbounded_Set.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Unbounded_Set.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Unbounded_Set.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_UNBOUNDED_SET_H */
diff --git a/ACE/ace/Unbounded_Set.inl b/ACE/ace/Unbounded_Set.inl
new file mode 100644
index 00000000000..00ba23802ef
--- /dev/null
+++ b/ACE/ace/Unbounded_Set.inl
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Global_Macros.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T> ACE_INLINE bool
+ACE_Unbounded_Set<T>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Unbounded_Set<T>::is_empty");
+ return this->head_ == this->head_->next_;
+}
+
+template <class T> ACE_INLINE bool
+ACE_Unbounded_Set<T>::is_full (void) const
+{
+ ACE_TRACE ("ACE_Unbounded_Set<T>::is_full");
+ return 0; // We should implement a "node of last resort for this..."
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Value_Ptr.h b/ACE/ace/Value_Ptr.h
new file mode 100644
index 00000000000..70570f9c34b
--- /dev/null
+++ b/ACE/ace/Value_Ptr.h
@@ -0,0 +1,167 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Value_Ptr.h
+ *
+ * $Id$
+ *
+ * Value_Ptr implementation based on code in Herb Sutter's book "More
+ * Exceptional C++".
+ *
+ * @author Ossama Othman <ossama@dre.vanderbilt.edu>
+ */
+//==========================================================================
+
+#ifndef ACE_VALUE_PTR_H
+#define ACE_VALUE_PTR_H
+
+#include "ace/config-lite.h"
+
+#include <algorithm>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace ACE
+{
+ /**
+ * @struct VP_traits
+ *
+ * @brief @c Value_Ptr traits template structure.
+ *
+ * The @c Value_Ptr template class delegates some operations to this
+ * template traits structure.
+ *
+ * Specialize this trait template if cloning through copy
+ * construction is not sufficient. For example, to avoid slicing
+ * when copying an object through a base class pointer, one can
+ * implement a virtual "clone" method that can be used to
+ * polymorphically invoke the appropriate cloning operation(s).
+ * That virtual method would then be invoked by the @c VP_traits\<\>
+ * specialization.
+ */
+ template <typename T>
+ struct VP_traits
+ {
+ /// Copy the given object.
+ static T * clone (T const * p) { return new T (*p); }
+ };
+
+ /**
+ * @class Value_Ptr
+ *
+ * @brief Smart pointer implementation designed for use as a class
+ * member.
+ *
+ * Using a @c std::auto_ptr\<\> as a class member is sometimes
+ * problematic since ownership of memory is transferred when copying
+ * such members. This @c Value_Ptr class is explicitly designed to
+ * avoid such problems by performing copies of the underlying object
+ * rather than transfer ownership. This, for example, allows it to
+ * be readily used as a member in classes placed inside STL
+ * containers.
+ *
+ * @see Item 31 in "More Exceptional C++" by Herb Sutter.
+ */
+ template <typename T>
+ class Value_Ptr
+ {
+ public:
+
+ /// Constructor.
+ explicit Value_Ptr (T * p = 0) : p_ (p) { }
+
+ /// Destructor.
+ ~Value_Ptr (void) { delete this->p_; }
+
+ /// Deference operator.
+ T & operator* (void) const { return *this->p_; }
+
+ /// Pointer operator.
+ T * operator-> (void) const { return this->p_; }
+
+ /// Non-throwing swap operation used to make assignment strongly
+ /// exception-safe.
+ /**
+ * @note As implemented, the swap operation may not work correctly
+ * for @c auto_ptr\<\>s, but why would one use an @c
+ * auto_ptr\<\> as the template argument for this particular
+ * template class!?
+ */
+ void swap (Value_Ptr & other) { std::swap (this->p_, other.p_); }
+
+ /// Copy constructor.
+ Value_Ptr (Value_Ptr const & other)
+ : p_ (create_from (other.p_)) { }
+
+ /// Assignment operator.
+ Value_Ptr & operator= (Value_Ptr const & other)
+ {
+ // Strongly exception-safe.
+ Value_Ptr temp (other);
+ this->swap (temp);
+ return *this;
+ }
+
+#ifndef ACE_LACKS_MEMBER_TEMPLATES
+
+ // Compiler can't handle member templates so we lose converting
+ // copy operations.
+
+ /// Converting copy constructor.
+ template <typename U>
+ Value_Ptr (Value_Ptr<U> const & other)
+ : p_ (create_from (other.p_)) { }
+
+ /// Converting assignment operator.
+ template <typename U>
+ Value_Ptr & operator= (Value_Ptr<U> const & other)
+ {
+ // Strongly exception-safe.
+ Value_Ptr temp (other);
+ this->swap (temp);
+ return *this;
+ }
+
+#endif /* !ACE_LACKS_MEMBER_TEMPLATES */
+
+ private:
+
+#ifndef ACE_LACKS_MEMBER_TEMPLATES
+
+ /// Copying method invoked when copy constructing.
+ template <typename U>
+ T * create_from (U const * p) const
+ {
+ return p ? VP_traits<U>::clone (p) : 0;
+ }
+
+#else
+
+ // Compiler can't handle member templates so we lose converting
+ // copy operations.
+
+ /// Copying method invoked when copy constructing.
+ T * create_from (T const * p) const
+ {
+ return p ? VP_traits<T>::clone (p) : 0;
+ }
+
+#endif /* !ACE_LACKS_MEMBER_TEMPLATES */
+
+ private:
+
+#ifndef ACE_LACKS_MEMBER_TEMPLATES
+ template <typename U> friend class Value_Ptr;
+#endif /* !ACE_LACKS_MEMBER_TEMPLATES */
+
+ /// Object owned by this @c Value_Ptr.
+ T * p_;
+
+ };
+
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_VALUE_PTR_H */
diff --git a/ACE/ace/Vector_T.cpp b/ACE/ace/Vector_T.cpp
new file mode 100644
index 00000000000..d66abd411ac
--- /dev/null
+++ b/ACE/ace/Vector_T.cpp
@@ -0,0 +1,154 @@
+// $Id$
+
+#ifndef ACE_VECTOR_T_CPP
+#define ACE_VECTOR_T_CPP
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Vector_T.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Vector_T.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Vector)
+
+template <class T, size_t DEFAULT_SIZE>
+void ACE_Vector<T, DEFAULT_SIZE>::resize (const size_t new_size,
+ const T& t)
+{
+ ACE_Array<T>::size (new_size);
+ if (new_size > length_)
+ for (size_t i = length_; i < new_size; ++i)
+ (*this)[i]=t;
+
+ curr_max_size_ = this->max_size ();
+ length_ = new_size;
+}
+
+template <class T, size_t DEFAULT_SIZE>
+void ACE_Vector<T, DEFAULT_SIZE>::push_back (const T& elem)
+{
+ if (length_ == curr_max_size_)
+ {
+ ACE_Array<T>::size (curr_max_size_ * 2);
+ curr_max_size_ = this->max_size ();
+ }
+ else
+ ACE_Array<T>::size (length_ + 1);
+
+ ++length_;
+ (*this)[length_-1] = elem;
+}
+
+template <class T, size_t DEFAULT_SIZE>
+void ACE_Vector<T, DEFAULT_SIZE>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+#if 0
+ // Can't do this unless the vector is an object with a dump
+ // function.
+ for (size_t i = 0; i < this->size (); ++i)
+ (*this)[i].dump ();
+#endif /* 0 */
+#endif /* ACE_HAS_DUMP */
+}
+
+// Compare this vector with <s> for equality.
+template <class T, size_t DEFAULT_SIZE> bool
+ACE_Vector<T, DEFAULT_SIZE>::operator== (const ACE_Vector<T, DEFAULT_SIZE> &s) const
+{
+ if (this == &s)
+ return true;
+ else if (this->size () != s.size ())
+ return false;
+
+ const size_t len = s.size ();
+ for (size_t slot = 0; slot < len; ++slot)
+ if ((*this)[slot] != s[slot])
+ return false;
+
+ return true;
+}
+
+#if 0
+template<class T>
+int compare(const ACE_Vector<T>& v1,
+ const ACE_Vector<T>& v2,
+ const size_t from_ndx,
+ const size_t to_ndx)
+{
+ size_t last1 = v1.size () - 1;
+ size_t last2 = v2.size () - 1;
+ if (last1 < from_ndx || last1 < to_ndx)
+ return false;
+ if (last2 < from_ndx || last2 < to_ndx)
+ return false;
+ if (last1 != last2)
+ return false;
+
+ // cout<<"compare() <================="<<endl;
+ for (size_t i = from_ndx; i <= to_ndx; ++i)
+ // cout<<"V1["<<i<<"]="<<v1[i];
+ // cout<<", V2["<<i<<"]="<<v2[i];
+ // cout<<": NOT EQUAL == "<<(v1[i]!=v2[i])<<endl;
+ if (v1[i] != v2[i])
+ return false;
+
+ // cout<<"compare() ====================>"<<endl;
+ return true;
+}
+
+template<class T>
+int partial_compare(const ACE_Vector<T>& v1,
+ const ACE_Vector<T>& v2,
+ const size_t from_ndx,
+ const size_t to_ndx)
+{
+ size_t last1 = v1.size () - 1;
+ size_t last2 = v2.size () - 1;
+
+ if (last1 < from_ndx || last1 < to_ndx)
+ return false;
+ if (last2 < from_ndx || last2 < to_ndx)
+ return false;
+
+ // cout<<"partial_compare() <================="<<endl;
+ for (size_t i = from_ndx; i <= to_ndx; ++i)
+ // cout<<"V1["<<i<<"]="<<v1[i];
+ // cout<<", V2["<<i<<"]="<<v2[i];
+ // cout<<": NOT EQUAL == "<<(v1[i]!=v2[i])<<endl;
+ if (v1[i] != v2[i])
+ return false;
+
+ // cout<<"partial_compare() ====================>"<<endl;
+ return true;
+}
+#endif
+
+// ****************************************************************
+
+template <class T, size_t DEFAULT_SIZE> int
+ACE_Vector_Iterator<T, DEFAULT_SIZE>::next (T *&item)
+{
+ // ACE_TRACE ("ACE_Vector_Iterator<T>::next");
+
+ if (this->done ())
+ {
+ item = 0;
+ return 0;
+ }
+ else
+ {
+ item = &vector_[current_];
+ return 1;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_VECTOR_T_CPP */
diff --git a/ACE/ace/Vector_T.h b/ACE/ace/Vector_T.h
new file mode 100644
index 00000000000..d6a6b455099
--- /dev/null
+++ b/ACE/ace/Vector_T.h
@@ -0,0 +1,316 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file Vector_T.h
+ *
+ * $Id$
+ *
+ * @author Craig L. Ching <cching@mqsoftware.com>
+ * @author Gonzalo Diethelm <gonzalo.diethelm@aditiva.com>
+ */
+//==========================================================================
+
+#ifndef ACE_VECTOR_T_H
+#define ACE_VECTOR_T_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Array.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/*
+ * Default size for an ACE_Vector.
+ */
+static const size_t ACE_VECTOR_DEFAULT_SIZE = 32;
+
+// Forward declaration.
+template <class T, size_t DEFAULT_SIZE> class ACE_Vector_Iterator;
+
+/**
+ * @class ACE_Vector
+ *
+ * @brief Defines an STL-like vector container.
+ *
+ * This is an STL-like template vector container, a wrapper around
+ * ACE_Array. It provides at least the basic std::vector look and
+ * feel: push_back(), clear(), resize(), capacity(). This template
+ * class uses the copy semantic paradigm, though it is okay to use
+ * reference counted smart pointers (see ACE_Ptr&lt;T&gt;) with this
+ * template class.
+ *
+ * <b> Requirements and Performance Characteristics</b>
+ * - Internal Structure
+ * ACE_Array
+ * - Duplicates allowed?
+ * Yes
+ * - Random access allowed?
+ * No
+ * - Search speed
+ * N/A
+ * - Insert/replace speed
+ * Linear
+ * - Iterator still valid after change to container?
+ * Yes
+ * - Frees memory for removed elements?
+ * No
+ * - Items inserted by
+ * Value
+ * - Requirements for contained type
+ * -# Default constructor
+ * -# Copy constructor
+ * -# operator=
+ */
+template<class T, size_t DEFAULT_SIZE = ACE_VECTOR_DEFAULT_SIZE>
+class ACE_Vector : public ACE_Array<T>
+{
+public:
+ /**
+ * A short name for iterator for ACE_Vector.
+ */
+ typedef ACE_Vector_Iterator<T, DEFAULT_SIZE> Iterator;
+
+
+ /**
+ * General constructor.
+ *
+ * @param init_size Initial size of the vector with the default
+ * value of DEFAULT_SIZE
+ * @param alloc Pointer to an ACE allocator. If it is NULL then the
+ * default ACE allocator is used
+ */
+ ACE_Vector (const size_t init_size = DEFAULT_SIZE,
+ ACE_Allocator* alloc = 0);
+
+ /**
+ * Destructor.
+ */
+ ~ACE_Vector ();
+
+ /**
+ * Returns the current vector capacity, that is, the currently
+ * allocated buffer size.
+ *
+ * @return Current buffer size of the vector
+ */
+ size_t capacity (void) const;
+
+ /**
+ * Returns the vector's dynamic size / actual current size of the
+ * vector. Do not confuse it with ACE_Array::size(), which returns
+ * the array's capacity. Unfortunately, ACE is not very consistent
+ * with the function names.
+ *
+ * @return Dynamic size / actual current size of the vector.
+ */
+ size_t size (void) const;
+
+ /**
+ * Clears out the vector. It does not reallocate the vector's
+ * buffer, it is just sets the vector's dynamic size to 0.
+ */
+ void clear (void);
+
+ /**
+ * Resizes the vector to the new capacity. If the vector's current
+ * capacity is smaller than the size to be specified, then the
+ * buffer gets reallocated. If the new capacity is less than the
+ * current capacity of the vector, the buffer size stays the same.
+ *
+ * @param new_size New capacity of the vector
+ * @param t A filler value (of the class T) for initializing the
+ * elements of the vector with. By default, if this
+ * parameter is not specified, the default value of the
+ * class T will be used (for more detail, see the
+ * initialization clause for this parameter).
+ */
+ void resize (const size_t new_size,
+ const T& t);
+
+ /**
+ * Appends a new element to the vector ("push back"). If the
+ * dynamic size of the vector is equal to the capacity of the vector
+ * (vector is at capacity), the vector automatically doubles its
+ * capacity.
+ *
+ * @param elem A reference to the new element to be appended. By
+ * default, this parameters gets initialized with the
+ * default value of the class T.
+ */
+ void push_back (const T& elem);
+
+ /**
+ * Deletes the last element from the vector ("pop back"). What this
+ * function really does is decrement the dynamic size of the
+ * vector. The vector's buffer does not get reallocated for
+ * performance.
+ */
+ void pop_back (void);
+
+ /**
+ * This function dumps the content of the vector. TO BE MOVED out
+ * of this class. It needs to be implemented as a global template
+ * function that accepts a const ACE_Vector&lt;T&gt;, in order to
+ * make instances of this class compile on Linux, AIX. G++ and xlC
+ * have template instantiation algoriths, which are different from
+ * the one in Visual C++. The algorithms try to instantiate ALL
+ * methods declared in the template class, regardless of whether the
+ * functions are used or not. That is, all of the classes, that are
+ * used as elements in ACE_Vector's, have to have the dump() methods
+ * defined in them (seems to be overkill).
+ *
+ * This function calls T::dump() for each element of the vector.
+ */
+ void dump (void) const;
+
+ // = Compare operators
+
+ ///Equality comparison operator.
+ /**
+ * Compare this vector with @arg s for equality. Two vectors are equal
+ * if their sizes are equal and all the elements are equal.
+ */
+ bool operator== (const ACE_Vector<T, DEFAULT_SIZE> &s) const;
+
+ ///Inequality comparison operator.
+ /**
+ * Compare this vector with @arg s for inequality such that @c *this !=
+ * @arg s is always the complement of the boolean return value of
+ * @c *this == @arg s.
+ */
+ bool operator!= (const ACE_Vector<T, DEFAULT_SIZE> &s) const;
+
+ void swap (ACE_Vector &rhs);
+
+protected:
+
+ /**
+ * Dynamic size (length) of the vector.
+ */
+ size_t length_;
+
+ /**
+ * Current capacity (buffer size) of the vector.
+ */
+ size_t curr_max_size_;
+
+ friend class ACE_Vector_Iterator<T, DEFAULT_SIZE>;
+};
+
+#if 0
+/*
+ * Not sure about including these functions, if for no other reason,
+ * because they polute the global namespace!
+ */
+
+/**
+ * Compare two vectors in the range of [from_ndx..to_ndx]. This
+ * template function requires class T to have the bool operator!=()
+ * declared in the class. It is safe to define vectors of scalar data
+ * types, like int, double, etc., including class ACE_TString.
+ *
+ * @param v1 The first vector (out of the two) to be compared.
+ * @param v2 The Second vector (out of the two) to be compared.
+ * @param from_ndx Compare vector v1 and v2, starting with the
+ * "from_ndx" index .
+ * @param to_ndx Compare vector v1 and v2, from "from_ndx" to
+ * "to_ndx".
+ * @return Returns true if v1==v2 in the specified index range,
+ * returns false otherwise. Also, returns false in case if
+ * v1's size is not equal to v2's size.
+ */
+template<class T>
+int compare (const ACE_Vector<T>& v1,
+ const ACE_Vector<T>& v2,
+ const size_t from_ndx,
+ const size_t to_ndx);
+
+/**
+ * Does a partial comparison of two vectors in the range of
+ * [from_ndx..to_ndx]. The only difference between this function and
+ * the template compare&lt;T&gt; function is that this function does
+ * not require v1 and v2 to be of equal size.
+ *
+ * @param v1 The first vector (out of the two) to be compared.
+ * @param v2 The Second vector (out of the two) to be compared.
+ * @param from_ndx Compare vector v1 and v2, starting with the
+ * "from_ndx" index .
+ * @param to_ndx Compare vector v1 and v2, from "from_ndx" to
+ * "to_ndx".
+ * @return Returns true if vector v1 and v2 are equal in the specified
+ * index range.
+ */
+
+template<class T>
+int partial_compare (const ACE_Vector<T>& v1,
+ const ACE_Vector<T>& v2,
+ const size_t from_ndx,
+ const size_t to_ndx);
+#endif /* 0 */
+// ****************************************************************
+
+/**
+ * @class ACE_Vector_Iterator
+ *
+ * @brief Implement an iterator over an ACE_Vector.
+ *
+ * This iterator is safe in the face of vector element deletions.
+ * But it is NOT safe if the vector is resized via the assignment
+ * operator during iteration. That would be very odd, and dangerous.
+ */
+template <class T, size_t DEFAULT_SIZE = ACE_VECTOR_DEFAULT_SIZE>
+class ACE_Vector_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Vector_Iterator (ACE_Vector<T, DEFAULT_SIZE> &);
+
+ // = Iteration methods.
+
+ /// Pass back the <next_item> that hasn't been seen in the vector.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (T *&next_item);
+
+ /// Move forward by one element in the vector. Returns 0 when all the
+ /// items in the vector have been seen, else 1.
+ int advance (void);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Pointer to the current item in the iteration.
+ size_t current_;
+
+ /// Reference to the vector we're iterating over.
+ ACE_Vector<T, DEFAULT_SIZE> &vector_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Vector_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Vector_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Vector_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_VECTOR_T_H */
diff --git a/ACE/ace/Vector_T.inl b/ACE/ace/Vector_T.inl
new file mode 100644
index 00000000000..8dea22cd361
--- /dev/null
+++ b/ACE/ace/Vector_T.inl
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include <algorithm>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE
+ACE_Vector<T, DEFAULT_SIZE>::ACE_Vector (const size_t init_size,
+ ACE_Allocator* alloc)
+ : ACE_Array<T> (init_size == 0 ? DEFAULT_SIZE : init_size, alloc),
+ length_ (0),
+ curr_max_size_ (this->max_size ())
+{
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE
+ACE_Vector<T, DEFAULT_SIZE>::~ACE_Vector ()
+{
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE
+size_t ACE_Vector<T, DEFAULT_SIZE>::capacity (void) const
+{
+ return curr_max_size_;
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE
+size_t ACE_Vector<T, DEFAULT_SIZE>::size (void) const
+{
+ return length_;
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE
+void ACE_Vector<T, DEFAULT_SIZE>::clear (void)
+{
+ length_ = 0;
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE
+void ACE_Vector<T, DEFAULT_SIZE>::pop_back (void)
+{
+ if (length_ > 0)
+ {
+ --length_;
+ ACE_Array<T>::size (length_);
+ }
+}
+
+// Compare this vector with <s> for inequality.
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE bool
+ACE_Vector<T, DEFAULT_SIZE>::operator!= (const ACE_Vector<T, DEFAULT_SIZE> &s) const
+{
+ return !(*this == s);
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE void
+ACE_Vector<T, DEFAULT_SIZE>::swap (ACE_Vector &rhs)
+{
+ ACE_Array<T>::swap (rhs);
+ std::swap (this->length_, rhs.length_);
+ std::swap (this->curr_max_size_, rhs.curr_max_size_);
+}
+
+// ****************************************************************
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE void
+ACE_Vector_Iterator<T, DEFAULT_SIZE>::dump (void) const
+{
+ // ACE_TRACE ("ACE_Vector_Iterator<T>::dump");
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE
+ACE_Vector_Iterator<T, DEFAULT_SIZE>::ACE_Vector_Iterator (ACE_Vector<T, DEFAULT_SIZE> &v)
+ : current_ (0),
+ vector_ (v)
+{
+ // ACE_TRACE ("ACE_Vector_Iterator<T>::ACE_Vector_Iterator");
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE int
+ACE_Vector_Iterator<T, DEFAULT_SIZE>::advance (void)
+{
+ // ACE_TRACE ("ACE_Vector_Iterator<T>::advance");
+
+ if (this->current_ < vector_.size ())
+ {
+ ++this->current_;
+ return 1;
+ }
+ else
+ // Already finished iterating.
+ return 0;
+}
+
+template <class T, size_t DEFAULT_SIZE> ACE_INLINE int
+ACE_Vector_Iterator<T, DEFAULT_SIZE>::done (void) const
+{
+ ACE_TRACE ("ACE_Vector_Iterator<T>::done");
+
+ return this->current_ >= vector_.size ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
diff --git a/ACE/ace/Version.h b/ACE/ace/Version.h
new file mode 100644
index 00000000000..d95084dd112
--- /dev/null
+++ b/ACE/ace/Version.h
@@ -0,0 +1,9 @@
+
+// -*- C++ -*-
+// $Id$
+// This is file was automatically generated by \$ACE_ROOT/bin/make_release.
+
+#define ACE_MAJOR_VERSION 5
+#define ACE_MINOR_VERSION 6
+#define ACE_BETA_VERSION 3
+#define ACE_VERSION "5.6.3"
diff --git a/ACE/ace/Versioned_Namespace.h b/ACE/ace/Versioned_Namespace.h
new file mode 100644
index 00000000000..542254876ff
--- /dev/null
+++ b/ACE/ace/Versioned_Namespace.h
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Versioned_Namespace.h
+ *
+ * $Id$
+ *
+ * Versioned namespace support.
+ *
+ * Useful for preventing conflicts when using a third party library.
+ *
+ * @author Ossama Othman <ossama@dre.vanderbilt.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_VERSIONED_NAMESPACE_H
+#define ACE_VERSIONED_NAMESPACE_H
+
+#ifndef ACE_CONFIG_MACROS_H
+# error This header is only meant to be included by or after "ace/config-lite.h".
+#endif /* !ACE_CONFIG_LITE_H */
+
+
+#if defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1
+
+# ifndef ACE_VERSIONED_NAMESPACE_NAME
+//# include "ace/Version.h"
+
+// Preprocessor symbols will not be expanded if they are
+// concatenated. Force the preprocessor to expand them during the
+// argument prescan by calling a macro that itself calls another that
+// performs the actual concatenation.
+# define ACE_MAKE_VERSIONED_NAMESPACE_NAME_IMPL(MAJOR,MINOR,BETA) ACE_ ## MAJOR ## _ ## MINOR ## _ ## BETA
+# define ACE_MAKE_VERSIONED_NAMESPACE_NAME(MAJOR,MINOR,BETA) ACE_MAKE_VERSIONED_NAMESPACE_NAME_IMPL(MAJOR,MINOR,BETA)
+# define ACE_VERSIONED_NAMESPACE_NAME ACE_MAKE_VERSIONED_NAMESPACE_NAME(ACE_MAJOR_VERSION,ACE_MINOR_VERSION,ACE_BETA_VERSION)
+# endif /* !ACE_VERSIONED_NAMESPACE_NAME */
+
+# define ACE_BEGIN_VERSIONED_NAMESPACE_DECL namespace ACE_VERSIONED_NAMESPACE_NAME {
+# define ACE_END_VERSIONED_NAMESPACE_DECL } \
+ using namespace ACE_VERSIONED_NAMESPACE_NAME;
+
+#else
+
+# define ACE_VERSIONED_NAMESPACE_NAME
+# define ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+# define ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_VERSIONED_NAMESPACE */
+
+#endif /* !ACE_VERSIONED_NAMESPACE_H */
diff --git a/ACE/ace/WFMO_Reactor.cpp b/ACE/ace/WFMO_Reactor.cpp
new file mode 100644
index 00000000000..54c4221de02
--- /dev/null
+++ b/ACE/ace/WFMO_Reactor.cpp
@@ -0,0 +1,2754 @@
+// $Id$
+
+#include "ace/WFMO_Reactor.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Handle_Set.h"
+#include "ace/Timer_Heap.h"
+#include "ace/Thread.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/Null_Condition.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/WFMO_Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, WFMO_Reactor, "$Id$")
+
+#include "ace/Auto_Ptr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_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 const 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_ = true;
+ // 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_ = true;
+ // 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_ = true;
+ // 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,
+ bool delete_event)
+{
+ if (event_handler == 0)
+ return -1;
+
+ // 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 and that total pending
+ // additions should not exceed what the <to_be_added_info_> array
+ // can hold.
+ if (current_size < this->max_size_ &&
+ this->handles_to_be_added_ < 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_;
+
+ event_handler->add_reference ();
+
+ // 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)
+ {
+ size_t i = 0;
+ while (i < this->max_handlep1_)
+ {
+ // 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_ )
+ {
+ size_t last_valid_slot = this->max_handlep1_ - 1;
+ // If this is the last handle in the set, no need to swap
+ // places. Simply remove it.
+ if (i < last_valid_slot)
+ // 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 this slot
+ this->current_info_[last_valid_slot].reset ();
+ this->current_handles_[last_valid_slot] = ACE_INVALID_HANDLE;
+ --this->max_handlep1_;
+ }
+ else
+ {
+ // This current entry is not up for deletion or
+ // suspension. Proceed to the next entry in the current
+ // handles.
+ ++i;
+ }
+
+ // Now that all internal structures have been updated, make
+ // the upcall.
+ if (event_handler != 0)
+ {
+ bool const requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ event_handler->handle_close (handle, masks);
+
+ if (requires_reference_counting)
+ {
+ event_handler->remove_reference ();
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::make_changes_in_suspension_infos (void)
+{
+ // Go through the <suspended_handle> array
+ if (this->handles_to_be_deleted_ > 0 || this->handles_to_be_resumed_ > 0)
+ {
+ size_t i = 0;
+ while (i < this->suspended_handles_)
+ {
+ // 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 an entry needs to be removed, either because it
+ // was deleted or resumed, remove it now before doing
+ // the upcall.
+ if (this->current_suspended_info_[i].resume_entry_ ||
+ this->current_suspended_info_[i].delete_entry_)
+ {
+ size_t last_valid_slot = this->suspended_handles_ - 1;
+ // Net effect is that we're removing an entry and
+ // compressing the list from the end. So, if removing
+ // an entry from the middle, copy the last valid one to the
+ // removed slot. Reset the end and decrement the number
+ // of suspended handles.
+ if (i < last_valid_slot)
+ // Struct copy
+ this->current_suspended_info_[i] =
+ this->current_suspended_info_[last_valid_slot];
+ this->current_suspended_info_[last_valid_slot].reset ();
+ --this->suspended_handles_;
+ }
+ else
+ {
+ // This current entry is not up for deletion or
+ // resumption. Proceed to the next entry in the
+ // suspended handles.
+ ++i;
+ }
+
+ // Now that all internal structures have been updated, make
+ // the upcall.
+ if (event_handler != 0)
+ {
+ int requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ event_handler->handle_close (handle, masks);
+
+ if (requires_reference_counting)
+ {
+ event_handler->remove_reference ();
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::make_changes_in_to_be_added_infos (void)
+{
+ // Go through the <to_be_added_*> arrays
+ for (size_t i = 0; i < 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)
+ {
+ int requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ event_handler->handle_close (handle, masks);
+
+ if (requires_reference_counting)
+ {
+ event_handler->remove_reference ();
+ }
+ }
+ }
+
+ // 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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("Max size = %d\n"),
+ this->max_size_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Current info table\n\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\tSize = %d\n"),
+ this->max_handlep1_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_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_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("To-be-added info table\n\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_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_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Suspended info table\n\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\tSize = %d\n"),
+ this->suspended_handles_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_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_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Total handles to be deleted = %d\n"),
+ this->handles_to_be_deleted_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+/************************************************************/
+
+int
+ACE_WFMO_Reactor::work_pending (const ACE_Time_Value &)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+#if defined (ACE_WIN32_VC8)
+# pragma warning (push)
+# pragma warning (disable:4355) /* Use of 'this' in initializer list */
+# endif
+ACE_WFMO_Reactor::ACE_WFMO_Reactor (ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ ACE_Reactor_Notify *notify)
+ : signal_handler_ (0),
+ delete_signal_handler_ (false),
+ timer_queue_ (0),
+ delete_timer_queue_ (false),
+ delete_handler_rep_ (false),
+ notify_handler_ (0),
+ delete_notify_handler_ (false),
+ 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_ (false),
+ deactivated_ (0)
+{
+ if (this->open (ACE_WFMO_Reactor::DEFAULT_SIZE, 0, sh, tq, 0, notify) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("WFMO_Reactor")));
+}
+
+ACE_WFMO_Reactor::ACE_WFMO_Reactor (size_t size,
+ int unused,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ ACE_Reactor_Notify *notify)
+ : signal_handler_ (0),
+ delete_signal_handler_ (false),
+ timer_queue_ (0),
+ delete_timer_queue_ (false),
+ delete_handler_rep_ (false),
+ notify_handler_ (0),
+ delete_notify_handler_ (false),
+ 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_ (false),
+ deactivated_ (0)
+{
+ ACE_UNUSED_ARG (unused);
+
+ if (this->open (size, 0, sh, tq, 0, notify) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("WFMO_Reactor")));
+}
+#if defined (ACE_WIN32_VC8)
+# pragma warning (pop)
+#endif
+
+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_ = true;
+ }
+ else
+ {
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = false;
+ }
+
+ // 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_ = true;
+ }
+ else
+ {
+ this->signal_handler_ = sh;
+ this->delete_signal_handler_ = false;
+ }
+
+ // 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 ();
+
+ // Prevent memory leaks when the ACE_WFMO_Reactor is reopened.
+ if (this->delete_handler_rep_)
+ {
+ 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 ();
+ }
+
+ 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_TEXT ("%p\n"),
+ ACE_TEXT ("opening handler repository")),
+ -1);
+ else
+ this->delete_handler_rep_ = true;
+
+ if (this->notify_handler_ != 0 && this->delete_notify_handler_)
+ delete this->notify_handler_;
+
+ 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_ = true;
+ }
+
+ /* 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_TEXT ("%p\n"),
+ ACE_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_TEXT ("%p\n"),
+ ACE_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_ = true;
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor::set_sig_handler (ACE_Sig_Handler *signal_handler)
+{
+ if (this->signal_handler_ != 0 && this->delete_signal_handler_)
+ delete this->signal_handler_;
+ this->signal_handler_ = signal_handler;
+ this->delete_signal_handler_ = false;
+ 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_)
+ delete this->timer_queue_;
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = false;
+ return 0;
+}
+
+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_ = false;
+ // 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_ = false;
+ }
+
+ if (this->delete_signal_handler_)
+ {
+ delete this->signal_handler_;
+ this->signal_handler_ = 0;
+ this->delete_signal_handler_ = false;
+ }
+
+ if (this->delete_notify_handler_)
+ {
+ delete this->notify_handler_;
+ this->notify_handler_ = 0;
+ this->delete_notify_handler_ = false;
+ }
+}
+
+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;
+ bool delete_event = false;
+ 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 = true;
+ }
+
+ 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_WINSOCK2 || ACE_HAS_WINSOCK2 == 0 */
+
+}
+
+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;
+ bool delete_event = false;
+ 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,
+ bool &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;
+}
+
+ACE_Event_Handler *
+ACE_WFMO_Reactor_Handler_Repository::find_handler (ACE_HANDLE handle)
+{
+ long existing_masks_ignored = 0;
+ return this->handler (handle, existing_masks_ignored);
+}
+
+ACE_Event_Handler *
+ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle,
+ long &existing_masks)
+{
+ int found = 0;
+ size_t i = 0;
+ ACE_Event_Handler *event_handler = 0;
+ 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 (event_handler)
+ event_handler->add_reference ();
+
+ return event_handler;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask user_masks,
+ ACE_Event_Handler **user_event_handler)
+{
+ long existing_masks = 0;
+ int found = 0;
+
+ ACE_Event_Handler_var safe_event_handler =
+ this->handler (handle,
+ existing_masks);
+
+ if (safe_event_handler.handler ())
+ found = 1;
+
+ 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 = safe_event_handler.release ();
+
+ 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);
+
+ int result;
+ do
+ {
+ // 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
+ 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 ();
+
+ // Calculate timeout
+ int timeout = this->calculate_timeout (max_wait_time);
+
+ // Wait for event to happen
+ DWORD 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
+
+ // We need to wait for both the <lock_> and <ok_to_wait_> event.
+ // If not on WinCE, use WaitForMultipleObjects() to wait for both atomically.
+ // On WinCE, the waitAll arg to WFMO must be false, so wait for the
+ // ok_to_wait_ event first (since that's likely to take the longest) then
+ // grab the lock and recheck the ok_to_wait_ event. When we can get them
+ // both, or there's an error/timeout, return.
+#if defined (ACE_HAS_WINCE)
+ ACE_Time_Value timeout = ACE_OS::gettimeofday ();
+ if (max_wait_time != 0)
+ timeout += *max_wait_time;
+ while (1)
+ {
+ int status;
+ if (max_wait_time == 0)
+ status = this->ok_to_wait_.wait ();
+ else
+ status = this->ok_to_wait_.wait (&timeout);
+ if (status == -1)
+ return -1;
+ // The event is signaled, so it's ok to wait; grab the lock and
+ // recheck the event. If something has changed, restart the wait.
+ if (max_wait_time == 0)
+ status = this->lock_.acquire ();
+ else
+ status = this->lock_.acquire (timeout);
+ if (status == -1)
+ return -1;
+
+ // Have the lock_, now re-check the event. If it's not signaled,
+ // another thread changed something so go back and wait again.
+ ACE_Time_Value poll_it = ACE_OS::gettimeofday ();
+ if (this->ok_to_wait_.wait (&poll_it) == 0)
+ break;
+ this->lock_.release ();
+ }
+ return 1;
+
+#else
+ int timeout = max_wait_time == 0 ? INFINITE : max_wait_time->msec ();
+ 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);
+
+ if (result != WAIT_IO_COMPLETION)
+ break;
+
+# else
+ result = ::WaitForMultipleObjectsEx (sizeof this->atomic_wait_array_ / sizeof (ACE_HANDLE),
+ this->atomic_wait_array_,
+ TRUE,
+ timeout,
+ alertable);
+
+ if (result != WAIT_IO_COMPLETION)
+ break;
+
+# endif /* ACE_HAS_PHARLAP */
+ }
+
+ 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;
+#endif /* ACE_HAS_WINCE */
+}
+
+DWORD
+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) || defined (ACE_HAS_WINCE)
+ // 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 (DWORD 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 (DWORD wait_status)
+{
+ int handlers_dispatched = 0;
+
+ // Expire timers
+ handlers_dispatched += this->expire_timers ();
+
+ switch (wait_status)
+ {
+ case WAIT_FAILED: // Failure.
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+
+ case WAIT_TIMEOUT: // Timeout.
+ errno = ETIME;
+ return handlers_dispatched;
+
+#ifndef ACE_HAS_WINCE
+ case WAIT_IO_COMPLETION: // APC.
+ return handlers_dispatched;
+#endif // ACE_HAS_WINCE
+
+ 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 (DWORD wait_status)
+{
+ // dispatch_slot is the absolute slot. Only += is used to
+ // increment it.
+ DWORD dispatch_slot = 0;
+
+ // Cache this value, this is the absolute value.
+ DWORD max_handlep1 = this->handler_rep_.max_handlep1 ();
+
+ // nCount starts off at <max_handlep1>, this is a transient count of
+ // handles last waited on.
+ DWORD nCount = max_handlep1;
+
+ for (int number_of_handlers_dispatched = 1;
+ ;
+ ++number_of_handlers_dispatched)
+ {
+ const bool ok = (
+#if ! defined(__BORLANDC__) \
+ && !defined (ghs) \
+ && !defined (__MINGW32__) \
+ && !(defined (_MSC_VER) && _MSC_VER >= 1300)
+ // wait_status is unsigned in Borland, Green Hills,
+ // mingw32 and MSVC++ >= 7.1.
+ // 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 (DWORD slot,
+ DWORD 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 (DWORD slot,
+ ACE_HANDLE event_handle)
+{
+ // This dispatch is used for non-I/O entires
+
+ // Assign the ``signaled'' HANDLE so that callers can get it.
+ // siginfo_t is an ACE - specific fabrication. Constructor exists.
+ siginfo_t sig (event_handle);
+
+ ACE_Event_Handler *event_handler =
+ this->handler_rep_.current_info ()[slot].event_handler_;
+
+ int requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ if (requires_reference_counting)
+ {
+ event_handler->add_reference ();
+ }
+
+ // Upcall
+ if (event_handler->handle_signal (0, &sig) == -1)
+ this->handler_rep_.unbind (event_handle,
+ ACE_Event_Handler::NULL_MASK);
+
+ // Call remove_reference() if needed.
+ if (requires_reference_counting)
+ {
+ event_handler->remove_reference ();
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor::complex_dispatch_handler (DWORD 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)
+ {
+ ACE_Event_Handler *event_handler =
+ current_info.event_handler_;
+
+ int reference_counting_required =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ // Call add_reference() if needed.
+ if (reference_counting_required)
+ {
+ event_handler->add_reference ();
+ }
+
+ // Upcall
+ problems |= this->upcall (current_info.event_handler_,
+ current_info.io_handle_,
+ events);
+
+ // Call remove_reference() if needed.
+ if (reference_counting_required)
+ {
+ event_handler->remove_reference ();
+ }
+
+ 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_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_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_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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_WFMO_Reactor::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Count of currently active threads = %d\n"),
+ this->active_threads_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_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));
+#endif /* ACE_HAS_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 (size_t max_notifies)
+ : timer_queue_ (0),
+ message_queue_ (max_notifies * sizeof (ACE_Notification_Buffer),
+ max_notifies * sizeof (ACE_Notification_Buffer)),
+ 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_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 =
+ reinterpret_cast <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)
+ {
+ ACE_Event_Handler *event_handler =
+ buffer->eh_;
+
+ bool const requires_reference_counting =
+ event_handler->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
+
+ int result = 0;
+
+ switch (buffer->mask_)
+ {
+ case ACE_Event_Handler::READ_MASK:
+ case ACE_Event_Handler::ACCEPT_MASK:
+ result = event_handler->handle_input (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::WRITE_MASK:
+ result = event_handler->handle_output (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::EXCEPT_MASK:
+ result = event_handler->handle_exception (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::QOS_MASK:
+ result = event_handler->handle_qos (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::GROUP_QOS_MASK:
+ result = event_handler->handle_group_qos (ACE_INVALID_HANDLE);
+ break;
+ default:
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("invalid mask = %d\n"),
+ buffer->mask_));
+ break;
+ }
+
+ if (result == -1)
+ event_handler->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::EXCEPT_MASK);
+
+ if (requires_reference_counting)
+ {
+ event_handler->remove_reference ();
+ }
+ }
+
+ // 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 *event_handler,
+ ACE_Reactor_Mask mask,
+ ACE_Time_Value *timeout)
+{
+ if (event_handler != 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_ = event_handler;
+ 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;
+ }
+
+ event_handler->add_reference ();
+ }
+
+ 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 = 0;
+ if (-1 == this->message_queue_.dequeue_head (mb))
+ return -1; // This shouldn't happen...
+
+ ACE_Notification_Buffer *buffer =
+ 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
+ {
+ ACE_Event_Handler *event_handler = buffer->eh_;
+
+ event_handler->remove_reference ();
+
+ 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 = 0;
+ 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_WFMO_Reactor_Notify::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->timer_queue_->dump ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Max. iteration: %d\n"),
+ this->max_notify_iterations_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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 */)
+{
+ return -1;
+}
+
+int
+WSAEnumNetworkEvents (SOCKET /* s */,
+ WSAEVENT /* hEventObject */,
+ LPWSANETWORKEVENTS /* lpNetworkEvents */)
+{
+ return -1;
+}
+#endif /* !defined ACE_HAS_WINSOCK2 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 */
diff --git a/ACE/ace/WFMO_Reactor.h b/ACE/ace/WFMO_Reactor.h
new file mode 100644
index 00000000000..da7ccdefe48
--- /dev/null
+++ b/ACE/ace/WFMO_Reactor.h
@@ -0,0 +1,1368 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file WFMO_Reactor.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_WFMO_REACTOR_H
+#define ACE_WFMO_REACTOR_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)
+
+#include "ace/Signal.h"
+#include "ace/Timer_Queue.h"
+#include "ace/Event_Handler.h"
+#include "ace/Auto_Event.h"
+#include "ace/Manual_Event.h"
+#include "ace/Condition_Thread_Mutex.h"
+#include "ace/Lock_Adapter_T.h"
+#include "ace/Reactor_Impl.h"
+#include "ace/Message_Queue.h"
+#include "ace/Process_Mutex.h"
+
+// 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 */
+
+class ACE_WFMO_Reactor_Test; // Must be out of versioned namespace.
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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
+ *
+ * @internal This class is for internal ACE use only.
+ *
+ * @brief Used to map ACE_HANDLEs 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.
+ */
+ bool delete_event_;
+
+ /// This is set when the entry needed to be deleted.
+ bool 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,
+ bool delete_event,
+ bool 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,
+ bool delete_event,
+ bool delete_entry = false,
+ 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,
+ bool delete_event,
+ bool delete_entry = false,
+ 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,
+ bool delete_event,
+ bool delete_entry = false,
+ 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 @a 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,
+ bool delete_event);
+
+ /// Remove the binding of ACE_HANDLE in accordance with the @a 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.
+ DWORD 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 @a 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,
+ bool &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 @a slot from the table.
+ int remove_handler_i (size_t slot,
+ ACE_Reactor_Mask mask);
+
+ /// Removes the ACE_Event_Handler at @a slot from the table.
+ int remove_suspended_handler_i (size_t slot,
+ ACE_Reactor_Mask mask);
+
+ /// Removes the ACE_Event_Handler at @a slot from the table.
+ int remove_to_be_added_handler_i (size_t slot,
+ ACE_Reactor_Mask to_be_removed_masks);
+
+ /**
+ * Return the Event_Handler associated with <handle>. Return 0 if
+ * <handle> is not registered.
+ */
+ ACE_Event_Handler *find_handler (ACE_HANDLE handle);
+
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to @a mask. Return the <event_handler> associated with this
+ * @a handler if <event_handler> != 0.
+ */
+ int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler = 0);
+
+ /**
+ * Check to see if <handle> is associated with a valid
+ * Event_Handler. Return Event_Handler and associated masks.
+ */
+ ACE_Event_Handler *handler (ACE_HANDLE handle,
+ long &existing_masks);
+
+ /// 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.
+ DWORD 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 (size_t max_notifies = 1024);
+
+ /// 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 @a 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 @a timeout ==
+ * 0, the caller will block until action is possible, else will wait
+ * until the relative time specified in @a timeout elapses).
+ */
+ virtual int 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_;
+
+ /// 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.
+ ACE_Message_Queue<ACE_MT_SYNCH> message_queue_;
+
+ /**
+ * 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_;
+};
+
+/**
+ * @class ACE_WFMO_Reactor
+ *
+ * @brief An object oriented event demultiplexor and event handler.
+ * ACE_WFMO_Reactor is a Windows-only implementation of the ACE_Reactor
+ * interface that uses the WaitForMultipleObjects() event demultiplexer.
+ *
+ * Like the other ACE Reactors, ACE_WFMO_Reactor can schedule timers.
+ * It also reacts to signalable handles, such as events (see the documentation
+ * for WaitForMultipleObjects() for a complete list of signalable handle
+ * types). Therefore, I/O handles are not directly usable for registering
+ * for input, output, and exception notification. The exception to this
+ * is ACE_SOCK-based handles, which can be registered for input, output, and
+ * exception notification just as with other platforms. See Chapter 4 in
+ * C++NPv2 for complete details.
+ *
+ * Note that changes to the state of ACE_WFMO_Reactor are not
+ * instantaneous. Most changes (registration, removal,
+ * suspension, and resumption of handles, and changes in
+ * ownership) are made when the ACE_WFMO_Reactor reaches a stable
+ * state. Users should be careful, especially when removing
+ * handlers. This is because the ACE_WFMO_Reactor will call
+ * handle_close() on the handler when it is finally removed and
+ * not when remove_handler() is called. If the registered handler's pointer
+ * is not valid when ACE_WFMO_Reactor calls ACE_Event_Handler::handle_close(),
+ * use the DONT_CALL flag with remove_handler(). Preferably, use dynamically
+ * allocated event handlers and call "delete this" inside the handle_close()
+ * hook method.
+ *
+ * Note that although multiple threads can concurrently run the
+ * ACE_WFMO_Reactor event loop, the concept of the reactor "owner" is still
+ * important. Only the owner thread can expire timers and wait on the
+ * notifications handle. Thus, be careful to properly set the owner thread
+ * when spawning threads to run the event loop while you are using timers
+ * or notifications.
+ */
+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 @a 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,
+ ACE_Reactor_Notify * = 0);
+
+ /**
+ * Initialize ACE_WFMO_Reactor with the specified size.
+ *
+ * @param size The maximum number of handles the reactor can
+ * register. The value should not exceed
+ * ACE_WFMO_Reactor::DEFAULT_SIZE. Two slots will be
+ * added to the @a 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,
+ ACE_Reactor_Notify * = 0);
+
+ /**
+ * Initialize ACE_WFMO_Reactor with the specified size.
+ *
+ * @param size The maximum number of handles the reactor can
+ * register. The value should not exceed
+ * ACE_WFMO_Reactor::DEFAULT_SIZE. Two slots will be
+ * added to the @a 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);
+
+ /// Set a user-specified timer queue.
+ virtual int timer_queue (ACE_Timer_Queue *tq);
+
+ /// Return the current ACE_Timer_Queue.
+ virtual ACE_Timer_Queue *timer_queue (void) const;
+
+ /// Close down the ACE_WFMO_Reactor and release all of its resources.
+ virtual int close (void);
+
+ /// Close down the ACE_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 @a max_wait_time before
+ * returning. It will return earlier if timer events, I/O events,
+ * or signal events occur. Note that @a max_wait_time can be 0, in
+ * which case this method blocks indefinitely until events occur.
+ *
+ * @a 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,
+ * @a 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_Handlers
+ * that were dispatched, 0 if the @a 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
+ * @a 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>. @a 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 @a 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 @a 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 @a 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 @a 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 @a 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 @a 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 @a 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 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 @a timer_id to
+ * @a interval, which is specified in relative time to the current
+ * <gettimeofday>. If @a 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 @a 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 @a 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 @a 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 @a 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
+ * @a timeout == 0, the caller will block until action is possible,
+ * else will wait until the relative time specified in @a 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.
+
+ /**
+ * Return the Event_Handler associated with <handle>. Return 0 if
+ * <handle> is not registered.
+ */
+ ACE_Event_Handler *find_handler (ACE_HANDLE handle);
+
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to @a mask. Return the <event_handler> associated with this
+ * @a 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 @a signum is associated with a valid Event_Handler
+ * bound to a signal. Return the <event_handler> associated with
+ * this @a 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 bool 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 @a 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 @a 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);
+
+ /// Wait up to @a max_wait_time until it's ok to enter
+ /// WaitForMultipleObjects. Returns 1 (and holding lock_) if ok to wait;
+ /// -1 (and not holding lock_) if not.
+ virtual int ok_to_wait (ACE_Time_Value *max_wait_time,
+ int alertable);
+
+ /// Wait for timer and I/O events to occur.
+ virtual DWORD wait_for_multiple_events (int timeout,
+ int alertable);
+
+ /// Check for activity on remaining handles.
+ virtual DWORD poll_remaining_handles (DWORD 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 (DWORD wait_status);
+
+ /// Protect against structured exceptions caused by user code when
+ /// dispatching handles
+ virtual int safe_dispatch (DWORD wait_status);
+
+ /**
+ * Dispatches any active handles from handles_[@a slot] to
+ * handles_[active_handles_] using <WaitForMultipleObjects> to poll
+ * through our handle set looking for active handles.
+ */
+ virtual int dispatch_handles (DWORD slot);
+
+ /// Dispatches a single handler. Returns 0 on success, -1 if the
+ /// handler was removed.
+ virtual int dispatch_handler (DWORD slot,
+ DWORD max_handlep1);
+
+ /// Dispatches a single handler. Returns 0 on success, -1 if the
+ /// handler was removed.
+ virtual int simple_dispatch_handler (DWORD slot,
+ ACE_HANDLE event_handle);
+
+ /// Dispatches a single handler. Returns 0 on success, -1 if the
+ /// handler was removed.
+ virtual int complex_dispatch_handler (DWORD 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).
+ bool 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).
+ bool delete_timer_queue_;
+
+ /// Keeps track of whether we should delete the handler repository
+ bool delete_handler_rep_;
+
+ /// Used when <notify> is called.
+ ACE_Reactor_Notify *notify_handler_;
+
+ /// Keeps track of whether we should delete the notify handler.
+ bool 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.
+ bool 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 &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/WFMO_Reactor.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_WIN32 */
+#include /**/ "ace/post.h"
+#endif /* ACE_WFMO_REACTOR_H */
diff --git a/ACE/ace/WFMO_Reactor.inl b/ACE/ace/WFMO_Reactor.inl
new file mode 100644
index 00000000000..1b6b47c0f28
--- /dev/null
+++ b/ACE/ace/WFMO_Reactor.inl
@@ -0,0 +1,1173 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/Handle_Set.h"
+#include "ace/Reactor.h"
+#include "ace/Thread.h"
+#include "ace/Sig_Handler.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/************************************************************/
+
+ACE_INLINE int
+ACE_Wakeup_All_Threads_Handler::handle_signal (int /* signum */,
+ siginfo_t * /* siginfo */,
+ ucontext_t *)
+{
+ // 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_TEXT ("(%t) waking up to get updated handle set info\n")));
+ return 0;
+}
+
+#if defined (ACE_WIN32)
+
+/************************************************************/
+
+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_ (false),
+ delete_entry_ (false),
+ 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_ = false;
+ this->delete_entry_ = false;
+ 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,
+ bool delete_event,
+ bool 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
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_WFMO_Reactor_Handler_Repository::Common_Info::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("I/O Entry = %d\n"),
+ this->io_entry_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Event Handler = %d\n"),
+ this->event_handler_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("I/O Handle = %d\n"),
+ this->io_handle_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Network Events = %d\n"),
+ this->network_events_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Delete Event = %d\n"),
+ this->delete_event_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Delete Entry = %d\n"),
+ this->delete_entry_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Close Masks = %d\n"),
+ this->close_masks_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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,
+ bool delete_event,
+ bool 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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("Event Handle = %d\n"),
+ event_handle));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Suspend Entry = %d\n"),
+ this->suspend_entry_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#else /* !ACE_HAS_DUMP */
+ ACE_UNUSED_ARG (event_handle);
+#endif /* ACE_HAS_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,
+ bool delete_event,
+ bool 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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("Event Handle = %d\n"),
+ this->event_handle_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Suspend Entry = %d\n"),
+ this->suspend_entry_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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,
+ bool delete_event,
+ bool 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
+{
+#if defined (ACE_HAS_DUMP)
+ 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_TEXT ("Event Handle = %d\n"),
+ this->event_handle_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Resume Entry = %d\n"),
+ this->resume_entry_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_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 DWORD
+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_ == true;
+ else
+ return this->current_info_[slot + 1].delete_entry_ == true;
+}
+
+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 const 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");
+
+ if (0 != this->timer_queue_)
+ {
+ 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;
+ }
+
+ errno = ESHUTDOWN;
+ return -1;
+}
+
+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");
+
+ if (0 != this->timer_queue_)
+ {
+ 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;
+ }
+
+ errno = ESHUTDOWN;
+ return -1;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::cancel_timer");
+ if (0 != this->timer_queue_)
+ return this->timer_queue_->cancel (handler, dont_call_handle_close);
+ return 0;
+}
+
+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");
+ if (0 != this->timer_queue_)
+ return this->timer_queue_->cancel (timer_id, arg, dont_call_handle_close);
+ return 0;
+}
+
+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 const 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 (DWORD 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 = 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 ACE_Event_Handler *
+ACE_WFMO_Reactor::find_handler (ACE_HANDLE handle)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, 0);
+
+ return this->handler_rep_.find_handler (handle);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->handler_rep_.handler (handle,
+ mask,
+ event_handler);
+}
+
+ACE_INLINE bool
+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 */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/WIN32_Asynch_IO.cpp b/ACE/ace/WIN32_Asynch_IO.cpp
new file mode 100644
index 00000000000..a2544c7c2f3
--- /dev/null
+++ b/ACE/ace/WIN32_Asynch_IO.cpp
@@ -0,0 +1,3767 @@
+// $Id$
+
+#include "ace/WIN32_Asynch_IO.h"
+
+ACE_RCSID (ace,
+ Win32_Asynch_IO,
+ "$Id$")
+
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) && \
+ (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 1))
+
+#include "ace/WIN32_Proactor.h"
+#include "ace/Proactor.h"
+#include "ace/Message_Block.h"
+#include "ace/Service_Config.h"
+#include "ace/INET_Addr.h"
+#include "ace/Task_T.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+size_t
+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 = dynamic_cast<ACE_WIN32_Proactor *> (proactor);
+
+ if (win32_proactor == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_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 (size_t 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void* act,
+ ACE_HANDLE event,
+ u_long offset,
+ u_long offset_high,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ OVERLAPPED (),
+ handler_proxy_ (handler_proxy),
+ 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ this->proactor_ = proactor;
+ this->handler_proxy_ = handler_proxy;
+ this->handle_ = handle;
+
+ // Grab the handle from the <handler> if <handle> is invalid
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ {
+ ACE_Handler *handler = handler_proxy.get ()->handler ();
+ if (handler != 0)
+ this->handle_ = handler->handle ();
+ }
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ return -1;
+
+ if (this->proactor_!= 0)
+ // update implementation.
+ this->win32_proactor_ =
+ dynamic_cast <ACE_WIN32_Proactor *>(this->proactor_->implementation ());
+
+ // 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_WIN32_OVERLAPPED_IO) \
+ && ( (defined (_MSC_VER)) \
+ || (defined (__BORLANDC__)) \
+ || (defined (__MINGW32)))
+ // 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 const 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_WIN32_OVERLAPPED_IO && _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),
+ handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+ACE_WIN32_Asynch_Operation::~ACE_WIN32_Asynch_Operation (void)
+{
+}
+
+// ************************************************************
+
+size_t
+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 (
+ const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number,
+ int scatter_enabled)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Stream_Result_Impl (),
+ ACE_WIN32_Asynch_Result (handler_proxy,
+ act,
+ event,
+ 0,
+ 0,
+ priority,
+ signal_number),
+ bytes_to_read_ (bytes_to_read),
+ message_block_ (message_block),
+ handle_ (handle),
+ scatter_enabled_ (scatter_enabled)
+{
+}
+
+void
+ACE_WIN32_Asynch_Read_Stream_Result::complete (size_t 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.
+ if (!this->scatter_enabled ())
+ this->message_block_.wr_ptr (bytes_transferred);
+ else
+ {
+ for (ACE_Message_Block* mb = &this->message_block_;
+ (mb != 0) && (bytes_transferred > 0);
+ mb = mb->cont ())
+ {
+ size_t len_part = mb->space ();
+
+ if (len_part > bytes_transferred)
+ len_part = bytes_transferred;
+
+ mb->wr_ptr (len_part);
+
+ bytes_transferred -= len_part;
+ }
+ }
+
+ // Create the interface result class.
+ ACE_Asynch_Read_Stream::Result result (this);
+
+ // Call the application handler.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ 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.
+
+size_t
+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);
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream_Result::scatter_enabled (void) const
+{
+ return this->scatter_enabled_;
+}
+
+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,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ size_t space = message_block.space ();
+ if (bytes_to_read > space)
+ bytes_to_read = space;
+
+ if (bytes_to_read == 0)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ // Create the Asynch_Result.
+ ACE_WIN32_Asynch_Read_Stream_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Read_Stream_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Shared read
+ int const return_val = this->shared_read (result);
+
+ // Upon errors
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream::readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+#if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+
+ // We should not read more than user requested,
+ // but it is allowed to read less
+
+ for (const ACE_Message_Block* msg = &message_block;
+ msg != 0 && bytes_to_read > 0 && iovcnt < ACE_IOV_MAX;
+ msg = msg->cont () , ++iovcnt )
+ {
+ size_t msg_space = msg->space ();
+
+ // OS should correctly process zero length buffers
+ // if ( msg_space == 0 )
+ // ACE_ERROR_RETURN ((LM_ERROR,
+ // ACE_TEXT ("ACE_WIN32_Asynch_Read_Stream::readv:")
+ // ACE_TEXT ("No space in the message block\n")),
+ // -1);
+
+ if (msg_space > bytes_to_read)
+ msg_space = bytes_to_read;
+ bytes_to_read -= msg_space;
+
+ // Make as many iovec as needed to fit all of msg_space.
+ size_t wr_ptr_offset = 0;
+ while (msg_space > 0 && iovcnt < ACE_IOV_MAX)
+ {
+ u_long this_chunk_length;
+ if (msg_space > ULONG_MAX)
+ this_chunk_length = ULONG_MAX;
+ else
+ this_chunk_length = static_cast<u_long> (msg_space);
+ // Collect the data in the iovec.
+ iov[iovcnt].iov_base = msg->wr_ptr () + wr_ptr_offset;
+ iov[iovcnt].iov_len = this_chunk_length;
+ msg_space -= this_chunk_length;
+ wr_ptr_offset += this_chunk_length;
+
+ // Increment iovec counter if there's more to do.
+ if (msg_space > 0)
+ ++iovcnt;
+ }
+ if (msg_space > 0) // Ran out of iovecs before msg_space exhausted
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ // Re-calculate number bytes to read
+ bytes_to_read = 0;
+
+ for (int i = 0; i < iovcnt ; ++i)
+ bytes_to_read += iov[i].iov_len;
+
+ if (bytes_to_read == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Read_Stream::readv:")
+ ACE_TEXT ("Attempt to read 0 bytes\n")),
+ -1);
+
+ // Create the Asynch_Result.
+ ACE_WIN32_Asynch_Read_Stream_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Read_Stream_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number,
+ 1), // scatter read enabled
+ -1);
+
+ // do the scatter recv
+
+ result->set_error (0); // Clear error before starting IO.
+
+ DWORD bytes_recvd = 0;
+ u_long flags = 0;
+
+ int initiate_result = ::WSARecv (reinterpret_cast<SOCKET> (result->handle ()),
+ reinterpret_cast<WSABUF *> (iov),
+ iovcnt,
+ &bytes_recvd,
+ &flags,
+ result,
+ 0);
+
+ if (0 == initiate_result)
+ // Immediate success: the OVERLAPPED will still get queued.
+ return 1;
+
+ ACE_ASSERT (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_TEXT ("%p\n"),
+ ACE_TEXT ("WSARecv")));
+ }
+
+ delete result;
+ initiate_result = -1;
+ break;
+ }
+
+ return initiate_result;
+#else
+ ACE_UNUSED_ARG (message_block);
+ ACE_UNUSED_ARG (bytes_to_read);
+ ACE_UNUSED_ARG (act);
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (signal_number);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */
+}
+
+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)
+{
+ // ReadFile API limits us to DWORD range.
+ if (result->bytes_to_read () > MAXDWORD)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ DWORD bytes_to_read = static_cast<DWORD> (result->bytes_to_read ());
+ 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 (),
+ bytes_to_read,
+ &bytes_read,
+ result);
+ if (initiate_result == 1)
+ // Immediate success: the OVERLAPPED will still get queued.
+ return 0;
+
+ // If initiate failed, check for a bad error.
+ ACE_OS::set_errno_to_last_error ();
+ switch (errno)
+ {
+ case ERROR_IO_PENDING:
+ /* FALLTHRU */
+ case ERROR_MORE_DATA:
+ // 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_TEXT ("%p\n"),
+ ACE_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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ 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 ();
+}
+
+size_t
+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 (
+ const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number,
+ int gather_enabled)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Stream_Result_Impl (),
+ ACE_WIN32_Asynch_Result
+ (handler_proxy, act, event, 0, 0, priority, signal_number),
+ bytes_to_write_ (bytes_to_write),
+ message_block_ (message_block),
+ handle_ (handle),
+ gather_enabled_ (gather_enabled)
+{
+}
+
+void
+ACE_WIN32_Asynch_Write_Stream_Result::complete (size_t 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.
+ if (!this->gather_enabled ())
+ this->message_block_.rd_ptr (bytes_transferred);
+ else
+ {
+ for (ACE_Message_Block* mb = &this->message_block_;
+ (mb != 0) && (bytes_transferred > 0);
+ mb = mb->cont ())
+ {
+ size_t len_part = mb->length ();
+
+ if ( len_part > bytes_transferred)
+ len_part = bytes_transferred;
+
+ mb->rd_ptr (len_part);
+
+ bytes_transferred -= len_part;
+ }
+ }
+
+ // Create the interface result class.
+ ACE_Asynch_Write_Stream::Result result (this);
+
+ // Call the application handler.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ 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.
+
+size_t
+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);
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream_Result::gather_enabled (void) const
+{
+ return this->gather_enabled_;
+}
+
+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,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ size_t len = message_block.length();
+
+ if (bytes_to_write > len)
+ bytes_to_write = len ;
+
+ if (bytes_to_write == 0)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Write_Stream::write:")
+ ACE_TEXT ("Attempt to write 0 bytes\n")),
+ -1);
+
+ ACE_WIN32_Asynch_Write_Stream_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Write_Stream_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Shared write
+ int return_val = this->shared_write (result);
+
+ // Upon errors
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream::writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+#if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+
+ // We should not write more than user requested,
+ // but it is allowed to write less
+
+ for (const ACE_Message_Block* msg = &message_block;
+ msg != 0 && bytes_to_write > 0 && iovcnt < ACE_IOV_MAX;
+ msg = msg->cont ())
+ {
+ size_t msg_len = msg->length ();
+
+ // Skip 0-length blocks.
+ if (msg_len == 0)
+ continue;
+ if (msg_len > bytes_to_write)
+ msg_len = bytes_to_write;
+ bytes_to_write -= msg_len;
+
+ // Make as many iovec as needed to fit all of msg_len.
+ size_t rd_ptr_offset = 0;
+ while (msg_len > 0 && iovcnt < ACE_IOV_MAX)
+ {
+ u_long this_chunk_length;
+ if (msg_len > ULONG_MAX)
+ this_chunk_length = ULONG_MAX;
+ else
+ this_chunk_length = static_cast<u_long> (msg_len);
+ // Collect the data in the iovec.
+ iov[iovcnt].iov_base = msg->rd_ptr () + rd_ptr_offset;
+ iov[iovcnt].iov_len = this_chunk_length;
+ msg_len -= this_chunk_length;
+ rd_ptr_offset += this_chunk_length;
+
+ // Increment iovec counter if there's more to do.
+ if (msg_len > 0)
+ iovcnt++;
+ }
+ if (msg_len > 0) // Ran out of iovecs before msg_space exhausted
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ ++iovcnt;
+ }
+
+ // Re-calculate number bytes to write
+ bytes_to_write = 0;
+
+ for ( int i=0; i < iovcnt ; ++i )
+ bytes_to_write += iov[i].iov_len;
+
+ if ( bytes_to_write == 0 )
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Write_Stream::writev:")
+ ACE_TEXT ("Attempt to write 0 bytes\n")),
+ -1);
+
+
+ ACE_WIN32_Asynch_Write_Stream_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Write_Stream_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number,
+ 1), // gather write enabled
+ -1);
+
+ // do the gather send
+
+ u_long bytes_sent = 0;
+
+ int initiate_result = ::WSASend (reinterpret_cast<SOCKET> (result->handle ()),
+ reinterpret_cast<WSABUF *> (iov),
+ iovcnt,
+ &bytes_sent,
+ 0, // flags
+ result,
+ 0);
+
+ if (0 == initiate_result)
+ // Immediate success: the OVERLAPPED will still get queued.
+ return 1;
+
+ ACE_ASSERT (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_TEXT ("%p\n"),
+ ACE_TEXT ("WSASend")));
+ }
+
+ delete result;
+ initiate_result = -1;
+ break;
+ }
+
+ return initiate_result;
+#else
+ ACE_UNUSED_ARG (message_block);
+ ACE_UNUSED_ARG (bytes_to_write);
+ ACE_UNUSED_ARG (act);
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (signal_number);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */
+}
+
+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;
+ if (result->bytes_to_write () > MAXDWORD)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ DWORD bytes_to_write = static_cast<DWORD> (result->bytes_to_write ());
+
+ result->set_error (0); // Clear error before starting IO.
+
+ // Initiate the write
+ int initiate_result = ::WriteFile (result->handle (),
+ result->message_block ().rd_ptr (),
+ bytes_to_write,
+ &bytes_written,
+ result);
+ if (initiate_result == 1)
+ // Immediate success: the OVERLAPPED will still get queued.
+ return 0;
+
+ // 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_TEXT ("%p\n"),
+ ACE_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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ 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 (
+ const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number,
+ int scatter_enabled)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Stream_Result_Impl (),
+ ACE_Asynch_Read_File_Result_Impl (),
+ ACE_WIN32_Asynch_Read_Stream_Result (handler_proxy,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number,
+ scatter_enabled)
+{
+ this->Offset = offset;
+ this->OffsetHigh = offset_high;
+}
+
+void
+ACE_WIN32_Asynch_Read_File_Result::complete (size_t 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.
+ if (!this->scatter_enabled ())
+ this->message_block_.wr_ptr (bytes_transferred);
+ else
+ {
+ static const size_t page_size = ACE_OS::getpagesize();
+
+ for (ACE_Message_Block* mb = &this->message_block_;
+ (mb != 0) && (bytes_transferred > 0);
+ mb = mb->cont ())
+ {
+ // mb->space () is ought to be >= page_size.
+ // this is verified in the readv method
+ // ACE_ASSERT (mb->space () >= page_size);
+
+ size_t len_part = page_size ;
+
+ if ( len_part > bytes_transferred)
+ len_part = bytes_transferred;
+
+ mb->wr_ptr (len_part);
+
+ bytes_transferred -= len_part;
+ }
+ }
+
+ // Create the interface result class.
+ ACE_Asynch_Read_File::Result result (this);
+
+ // Call the application handler.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ 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.
+
+size_t
+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.
+
+size_t
+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,
+ size_t bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ size_t space = message_block.space ();
+ if ( bytes_to_read > space )
+ bytes_to_read = space;
+
+ if ( bytes_to_read == 0 )
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Read_File::read:")
+ ACE_TEXT ("Attempt to read 0 bytes or no space in the message block\n")),
+ -1);
+
+
+ ACE_WIN32_Asynch_Read_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Read_File_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Shared read
+ int return_val = this->shared_read (result);
+
+ // Upon errors
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+int
+ACE_WIN32_Asynch_Read_File::readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+ static const size_t page_size = ACE_OS::getpagesize();
+
+ FILE_SEGMENT_ELEMENT buffer_pointers[ACE_IOV_MAX + 1];
+ int buffer_pointers_count = 0;
+
+ // Each buffer must be at least the size of a system memory page
+ // and must be aligned on a system memory page size boundary
+
+ // We should not read more than user requested,
+ // but it is allowed to read less
+
+ size_t total_space = 0;
+
+ for (const ACE_Message_Block* msg = &message_block;
+ msg != 0 && buffer_pointers_count < ACE_IOV_MAX && total_space < bytes_to_read;
+ msg = msg->cont(), ++buffer_pointers_count )
+ {
+ size_t msg_space = msg->space ();
+
+ if (msg_space < page_size)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Read_File::readv:")
+ ACE_TEXT ("Invalid message block size\n")),
+ -1);
+
+ buffer_pointers[buffer_pointers_count].Buffer = msg->wr_ptr ();
+ total_space += page_size;
+ }
+
+ // not read more than buffers space
+ if (bytes_to_read > total_space)
+ bytes_to_read = total_space;
+
+ // ReadFileScatter API limits us to DWORD range.
+ if (bytes_to_read > MAXDWORD)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ DWORD dword_bytes_to_read = static_cast<DWORD> (bytes_to_read);
+
+ // last one should be completely 0
+ buffer_pointers[buffer_pointers_count].Buffer = 0;
+
+ ACE_WIN32_Asynch_Read_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Read_File_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number,
+ 1), // scatter read enabled
+ -1);
+
+ // do the scatter read
+ result->set_error (0); // Clear error before starting IO.
+
+ int initiate_result = ::ReadFileScatter (result->handle (),
+ buffer_pointers,
+ dword_bytes_to_read,
+ 0, // reserved, must be NULL
+ result);
+
+ if (0 != initiate_result)
+ // 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.
+ initiate_result = 0;
+ break;
+
+ default:
+ // Something else went wrong: the OVERLAPPED will not get
+ // queued.
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ReadFileScatter")));
+ }
+
+ delete result;
+ initiate_result = -1;
+ break;
+ }
+
+ return initiate_result;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32_OVERLAPPED_IO */
+}
+
+
+ACE_WIN32_Asynch_Read_File::~ACE_WIN32_Asynch_Read_File (void)
+{
+}
+
+int
+ACE_WIN32_Asynch_Read_File::read (ACE_Message_Block &message_block,
+ size_t 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);
+}
+
+int
+ACE_WIN32_Asynch_Read_File::readv (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return ACE_WIN32_Asynch_Read_Stream::readv (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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ 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 (
+ const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number,
+ int gather_enabled)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Stream_Result_Impl (),
+ ACE_Asynch_Write_File_Result_Impl (),
+ ACE_WIN32_Asynch_Write_Stream_Result (handler_proxy,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number,
+ gather_enabled)
+{
+ this->Offset = offset;
+ this->OffsetHigh = offset_high;
+}
+
+void
+ACE_WIN32_Asynch_Write_File_Result::complete (size_t 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.
+ if (!this->gather_enabled ())
+ this->message_block_.rd_ptr (bytes_transferred);
+ else
+ {
+ static const size_t page_size = ACE_OS::getpagesize();
+
+ for (ACE_Message_Block* mb = &this->message_block_;
+ (mb != 0) && (bytes_transferred > 0);
+ mb = mb->cont ())
+ {
+ // mb->length () is ought to be >= page_size.
+ // this is verified in the writev method
+ // ACE_ASSERT (mb->length () >= page_size);
+
+ size_t len_part = page_size;
+
+ if ( len_part > bytes_transferred)
+ len_part = bytes_transferred;
+
+ mb->rd_ptr (len_part);
+
+ bytes_transferred -= len_part;
+ }
+
+ }
+
+ // Create the interface result class.
+ ACE_Asynch_Write_File::Result result (this);
+
+ // Call the application handler.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ 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.
+
+size_t
+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.
+
+size_t
+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,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ size_t len = message_block.length ();
+ if ( bytes_to_write > len )
+ bytes_to_write = len;
+
+ if ( bytes_to_write == 0 )
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Write_File::write:")
+ ACE_TEXT ("Attempt to read 0 bytes\n")),
+ -1);
+
+ ACE_WIN32_Asynch_Write_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Write_File_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Shared write
+ int return_val = this->shared_write (result);
+
+ // Upon errors
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+int
+ACE_WIN32_Asynch_Write_File::writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+ static const size_t page_size = ACE_OS::getpagesize();
+
+ FILE_SEGMENT_ELEMENT buffer_pointers[ACE_IOV_MAX + 1];
+ int buffer_pointers_count = 0;
+
+ // Each buffer must be at least the size of a system memory page
+ // and must be aligned on a system memory page size boundary
+
+ // We should not read more than user requested,
+ // but it is allowed to read less
+
+ size_t total_len = 0;
+
+ for (const ACE_Message_Block* msg = &message_block;
+ msg != 0 && buffer_pointers_count < ACE_IOV_MAX && total_len < bytes_to_write;
+ msg = msg->cont (), ++buffer_pointers_count )
+ {
+ size_t msg_len = msg->length ();
+
+ // Don't allow writing less than page_size, unless
+ // the size of the message block is big enough (so we don't write from
+ // memory which does not belong to the message block), and the message
+ // block is the last in the chain.
+ if (msg_len < page_size &&
+ (msg->size () - (msg->rd_ptr () - msg->base ()) < page_size || // message block too small
+ bytes_to_write - total_len > page_size ))// NOT last chunk
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Write_File::writev:")
+ ACE_TEXT ("Invalid message block length\n")),
+ -1);
+
+ buffer_pointers[buffer_pointers_count].Buffer = msg->rd_ptr ();
+ total_len += page_size;
+ }
+
+ // not write more than we have in buffers
+ if (bytes_to_write > total_len)
+ bytes_to_write = total_len;
+ // WriteFileGather API limits us to DWORD range.
+ if (bytes_to_write > MAXDWORD)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ DWORD dword_bytes_to_write = static_cast<DWORD> (bytes_to_write);
+
+ // last one should be completely 0
+ buffer_pointers[buffer_pointers_count].Buffer = 0;
+
+ ACE_WIN32_Asynch_Write_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Write_File_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number,
+ 1), // gather write enabled
+ -1);
+
+ result->set_error(0);
+
+ // do the gather write
+ int initiate_result = ::WriteFileGather (result->handle (),
+ buffer_pointers,
+ dword_bytes_to_write,
+ 0, // reserved, must be NULL
+ result);
+
+ if (0 != initiate_result)
+ // 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.
+ initiate_result = 0;
+ break;
+
+ default:
+ // Something else went wrong: the OVERLAPPED will not get
+ // queued.
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("WriteFileGather")));
+ }
+
+ delete result;
+ initiate_result = -1;
+ break;
+ }
+
+ return initiate_result;
+#else
+
+ ACE_NOTSUP_RETURN (-1);
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
+}
+
+
+ACE_WIN32_Asynch_Write_File::~ACE_WIN32_Asynch_Write_File (void)
+{
+}
+
+int
+ACE_WIN32_Asynch_Write_File::write (ACE_Message_Block &message_block,
+ size_t 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);
+}
+
+int
+ACE_WIN32_Asynch_Write_File::writev (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return ACE_WIN32_Asynch_Write_Stream::writev (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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ 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 ();
+}
+
+size_t
+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 (
+ const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ 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 (size_t 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);
+
+ if (!success && this->accept_handle_ != ACE_INVALID_HANDLE)
+ {
+ ACE_OS::closesocket (this->accept_handle_);
+ this->accept_handle_ = ACE_INVALID_HANDLE;
+ }
+
+ // Create the interface result class.
+ ACE_Asynch_Accept::Result result (this);
+
+ // Call the application handler.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ 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.
+
+size_t
+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,
+ size_t bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number,
+ int addr_family)
+{
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (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 =
+#if defined (ACE_HAS_IPV6)
+ addr_family == AF_INET ? sizeof (sockaddr_in) : sizeof (sockaddr_in6);
+#else
+ sizeof (sockaddr_in);
+#endif /* ACE_HAS_IPV6 */
+ address_size += 16; // AcceptEx requires address size + 16 (minimum)
+ size_t available_space = message_block.space ();
+ size_t space_needed = bytes_to_read + 2 * address_size;
+ if (available_space < space_needed)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Buffer too small\n")), -1);
+
+ // WIN Specific.
+
+ // AcceptEx API limits us to DWORD range.
+ if (bytes_to_read > MAXDWORD)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ DWORD dword_bytes_to_read = static_cast<DWORD> (bytes_to_read);
+
+ 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 (addr_family,
+ SOCK_STREAM,
+ 0);
+ if (accept_handle == ACE_INVALID_HANDLE)
+ {
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_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_proxy_,
+ 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 (),
+ dword_bytes_to_read,
+ static_cast<DWORD> (address_size),
+ static_cast<DWORD> (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_TEXT ("%p\n"),
+ ACE_TEXT ("AcceptEx")));
+ }
+ return -1;
+ }
+#else
+ 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_UNUSED_ARG (addr_family);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) */
+}
+
+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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ 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_Connect_Result::connect_handle (void) const
+{
+ return this->connect_handle_;
+}
+
+void ACE_WIN32_Asynch_Connect_Result::connect_handle ( ACE_HANDLE handle )
+{
+ this->connect_handle_ = handle;
+}
+
+
+ACE_WIN32_Asynch_Connect_Result::ACE_WIN32_Asynch_Connect_Result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Connect_Result_Impl (),
+ ACE_WIN32_Asynch_Result
+ (handler_proxy, act, event, 0, 0, priority, signal_number),
+ connect_handle_ (connect_handle)
+{
+ ;
+}
+
+void
+ACE_WIN32_Asynch_Connect_Result::complete (size_t 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;
+
+ // Create the interface result class.
+ ACE_Asynch_Connect::Result result (this);
+
+ // Call the application handler.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_connect (result);
+}
+
+ACE_WIN32_Asynch_Connect_Result::~ACE_WIN32_Asynch_Connect_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+size_t
+ACE_WIN32_Asynch_Connect_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Connect_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Connect_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Connect_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Connect_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Connect_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Connect_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Connect_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Connect_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Connect_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+int
+ACE_WIN32_Asynch_Connect_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+// *********************************************************************
+
+ACE_WIN32_Asynch_Connect::ACE_WIN32_Asynch_Connect (ACE_WIN32_Proactor * win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Connect_Impl (),
+ ACE_WIN32_Asynch_Operation (win32_proactor),
+ flg_open_ (false)
+{
+}
+
+ACE_WIN32_Asynch_Connect::~ACE_WIN32_Asynch_Connect (void)
+{
+ this->close ();
+ this->reactor (0); // to avoid purge_pending_notifications
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Connect::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Connect::get_handle (void) const
+{
+
+ ACE_ASSERT (0);
+ return ACE_INVALID_HANDLE;
+}
+
+void
+ACE_WIN32_Asynch_Connect::set_handle (ACE_HANDLE)
+{
+ ACE_ASSERT (0) ;
+}
+
+int
+ACE_WIN32_Asynch_Connect::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::open");
+
+ // if we are already opened,
+ // we could not create a new handler without closing the previous
+ if (this->flg_open_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%N:%l:ACE_WIN32_Asynch_Connect::open:")
+ ACE_TEXT ("connector already open \n")),
+ -1);
+
+ //int result =
+ ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ ACE_INVALID_HANDLE,
+ completion_key,
+ proactor);
+
+ // Ignore result as we pass ACE_INVALID_HANDLE
+ //if (result == -1)
+ // return result;
+
+ this->flg_open_ = true;
+
+ return 0;
+}
+
+int
+ACE_WIN32_Asynch_Connect::connect (ACE_HANDLE connect_handle,
+ const ACE_Addr & remote_sap,
+ const ACE_Addr & local_sap,
+ int reuse_addr,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::connect");
+
+ if (!this->flg_open_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%N:%l:ACE_WIN32_Asynch_Connect::connect")
+ ACE_TEXT ("connector was not opened before\n")),
+ -1);
+
+ // Common code for both WIN and WIN32.
+ // Create future Asynch_Connect_Result
+ ACE_WIN32_Asynch_Connect_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Connect_Result (this->handler_proxy_,
+ connect_handle,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ int rc = connect_i (result,
+ remote_sap,
+ local_sap,
+ reuse_addr);
+
+ // update handle
+ connect_handle = result->connect_handle ();
+
+ if (rc != 0)
+ return post_result (result, true);
+
+ // Enqueue result we will wait for completion
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ if (this->result_map_.bind (connect_handle, result) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect: %p\n"),
+ ACE_TEXT ("bind")));
+ result->set_error (EFAULT);
+ return post_result (result, true);
+ }
+ }
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->win32_proactor_->get_asynch_pseudo_task ();
+
+ if (-1 == task.register_io_handler (connect_handle,
+ this,
+ ACE_Event_Handler::CONNECT_MASK,
+ 0)) // not to suspend after register
+ {
+ result = 0;
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+ this->result_map_.unbind (connect_handle, result);
+ }
+ if (result != 0)
+ {
+ result->set_error (EFAULT);
+ this->post_result (result, true);
+ }
+ }
+
+ return 0;
+}
+
+int ACE_WIN32_Asynch_Connect::post_result (ACE_WIN32_Asynch_Connect_Result * result,
+ bool post_enable)
+{
+ ACE_HANDLE handle = result->connect_handle ();
+ if (this->flg_open_ && post_enable)
+ {
+ // NOTE: result is invalid after post_completion(). It's either deleted
+ // or will be shortly via the proactor dispatch, regardless of success
+ // or fail of the call.
+ if (this->win32_proactor_ ->post_completion (result) == 0)
+ return 0;
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Error:(%P | %t):%p\n"),
+ ACE_TEXT ("ACE_WIN32_Asynch_Connect::post_result: ")
+ ACE_TEXT (" <post_completion> failed")));
+ }
+ else
+ {
+ // There was no call to post_completion() so manually delete result.
+ delete result;
+ }
+
+ if (handle != ACE_INVALID_HANDLE)
+ ACE_OS::closesocket (handle);
+
+ return -1;
+}
+
+// connect_i
+// return code :
+// -1 errors before attempt to connect
+// 0 connect started
+// 1 connect finished ( may be unsuccessfully)
+
+int
+ACE_WIN32_Asynch_Connect::connect_i (ACE_WIN32_Asynch_Connect_Result *result,
+ const ACE_Addr & remote_sap,
+ const ACE_Addr & local_sap,
+ int reuse_addr)
+{
+ result->set_bytes_transferred (0);
+
+ ACE_HANDLE handle = result->connect_handle ();
+ if (handle == ACE_INVALID_HANDLE)
+ {
+ int protocol_family = remote_sap.get_type ();
+ handle = ACE_OS::socket (protocol_family,
+ SOCK_STREAM,
+ 0);
+
+ // save it
+ result->connect_handle (handle);
+ if (handle == ACE_INVALID_HANDLE)
+ {
+ result->set_error (errno);
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
+ ACE_TEXT ("socket")),
+ -1);
+ }
+
+ // Reuse the address
+ int one = 1;
+ if (protocol_family != PF_UNIX &&
+ reuse_addr != 0 &&
+ ACE_OS::setsockopt (handle,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (const char*) &one,
+ sizeof one) == -1)
+ {
+ result->set_error (errno);
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
+ ACE_TEXT ("setsockopt")),
+ -1);
+ }
+ }
+
+ if (local_sap != ACE_Addr::sap_any)
+ {
+ sockaddr * laddr = reinterpret_cast<sockaddr *> (local_sap.get_addr ());
+ int size = local_sap.get_size ();
+ if (ACE_OS::bind (handle, laddr, size) == -1)
+ {
+ result->set_error (errno);
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
+ ACE_TEXT ("bind")),
+ -1);
+ }
+ }
+
+ // set non blocking mode
+ if (ACE::set_flags (handle, ACE_NONBLOCK) != 0)
+ {
+ result->set_error (errno);
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
+ ACE_TEXT ("set_flags")),
+ -1);
+ }
+
+ for (;;)
+ {
+ int rc = ACE_OS::connect
+ (handle,
+ reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
+ remote_sap.get_size ());
+
+ if (rc < 0) // failure
+ {
+ if (errno == EWOULDBLOCK || errno == EINPROGRESS)
+ return 0; // connect started
+
+ if (errno == EINTR)
+ continue;
+
+ result->set_error (errno);
+ }
+ return 1 ; // connect finished
+ }
+}
+
+
+// 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 WIN32 standards we should receive notifications
+// on canceled AIO requests
+//
+// Return value : number of cancelled requests
+//
+
+int
+ACE_WIN32_Asynch_Connect::cancel_uncompleted (bool flg_notify,
+ ACE_Handle_Set &set)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::cancel_uncompleted");
+
+ int retval = 0;
+
+ MAP_MANAGER::ITERATOR iter (result_map_);
+ MAP_MANAGER::ENTRY * me = 0;
+
+ set.reset ();
+
+ for (; iter.next (me) != 0; retval++, iter.advance ())
+ {
+ ACE_HANDLE handle = me->ext_id_;
+ ACE_WIN32_Asynch_Connect_Result* result = me->int_id_ ;
+
+ set.set_bit (handle);
+
+ result->set_bytes_transferred (0);
+ result->set_error (ERROR_OPERATION_ABORTED);
+ this->post_result (result, flg_notify);
+ }
+
+ result_map_.unbind_all ();
+
+ return retval;
+}
+
+int
+ACE_WIN32_Asynch_Connect::cancel (void)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::cancel");
+
+ int rc = -1 ; // ERRORS
+
+ ACE_Handle_Set set;
+ int num_cancelled = 0;
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ num_cancelled = cancel_uncompleted (flg_open_, set);
+ }
+ if (num_cancelled == 0)
+ rc = 1; // AIO_ALLDONE
+ else if (num_cancelled > 0)
+ rc = 0; // AIO_CANCELED
+
+ if (!this->flg_open_)
+ return rc;
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->win32_proactor_->get_asynch_pseudo_task ();
+
+ task.remove_io_handler (set);
+ return rc;
+}
+
+int
+ACE_WIN32_Asynch_Connect::close (void)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::close");
+
+ ACE_Handle_Set set;
+ int num_cancelled = 0;
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ num_cancelled = cancel_uncompleted (flg_open_, set);
+ }
+ if (num_cancelled == 0 || this->flg_open_ == 0)
+ {
+ this->flg_open_ = false;
+ return 0;
+ }
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->win32_proactor_->get_asynch_pseudo_task ();
+
+ task.remove_io_handler (set);
+ return 0;
+}
+
+int
+ACE_WIN32_Asynch_Connect::handle_exception (ACE_HANDLE fd)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_exception");
+ return handle_output (fd);
+}
+
+int
+ACE_WIN32_Asynch_Connect::handle_input (ACE_HANDLE fd)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_input");
+ return handle_output (fd);
+}
+
+int
+ACE_WIN32_Asynch_Connect::handle_output (ACE_HANDLE fd)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_output");
+
+ ACE_WIN32_Asynch_Connect_Result* result = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
+ if (this->result_map_.unbind (fd, result) != 0) // not found
+ return -1;
+ }
+
+ int sockerror = 0 ;
+ int lsockerror = sizeof sockerror;
+
+ ACE_OS::getsockopt (fd,
+ SOL_SOCKET,
+ SO_ERROR,
+ (char*) & sockerror,
+ & lsockerror);
+
+ // This previously just did a "return -1" and let handle_close() clean
+ // things up. However, this entire object may be gone as a result of
+ // the application's completion handler, so don't count on 'this' being
+ // legitimate on return from post_result().
+ // remove_io_handler() contains flag DONT_CALL
+ this->win32_proactor_->get_asynch_pseudo_task().remove_io_handler (fd);
+
+ result->set_bytes_transferred (0);
+ result->set_error (sockerror);
+ this->post_result (result, this->flg_open_);
+ return 0;
+}
+
+
+int
+ACE_WIN32_Asynch_Connect::handle_close (ACE_HANDLE fd, ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_close");
+
+ ACE_Asynch_Pseudo_Task & task =
+ this->win32_proactor_->get_asynch_pseudo_task ();
+ task.remove_io_handler (fd);
+
+ ACE_WIN32_Asynch_Connect_Result* result = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
+ if (this->result_map_.unbind (fd, result) != 0) // not found
+ return -1;
+ }
+
+ result->set_bytes_transferred (0);
+ result->set_error (ERROR_OPERATION_ABORTED);
+ this->post_result (result, this->flg_open_);
+
+ return 0;
+}
+
+// *********************************************************************
+
+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_;
+}
+
+size_t
+ACE_WIN32_Asynch_Transmit_File_Result::bytes_to_write (void) const
+{
+ return this->bytes_to_write_;
+}
+
+size_t
+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 (
+ const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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_proxy,
+ 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 (size_t 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ 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.
+
+size_t
+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,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t bytes_per_send,
+ u_long flags,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+
+ // TransmitFile API limits us to DWORD range.
+ if (bytes_to_write > MAXDWORD || bytes_per_send > MAXDWORD)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ DWORD dword_bytes_to_write = static_cast<DWORD> (bytes_to_write);
+ DWORD dword_bytes_per_send = static_cast<DWORD> (bytes_per_send);
+
+ ACE_WIN32_Asynch_Transmit_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Transmit_File_Result (this->handler_proxy_,
+ 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 (),
+ dword_bytes_to_write,
+ dword_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_TEXT ("%p\n"),
+ ACE_TEXT ("TransmitFile")));
+ }
+ return -1;
+ }
+#else
+ 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_WIN32_OVERLAPPED_IO || ACE_HAS_WINSOCK2 */
+}
+
+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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ 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 ();
+}
+
+size_t
+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_;
+}
+
+size_t
+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 (
+ const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_Result_Impl (),
+ ACE_Asynch_Read_Dgram_Result_Impl(),
+ ACE_WIN32_Asynch_Result (handler_proxy, 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 ();
+
+ ACE_UNUSED_ARG (protocol_family);
+}
+
+void
+ACE_WIN32_Asynch_Read_Dgram_Result::complete (size_t 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 ())
+ {
+ size_t len_part = mb->space ();
+
+ if ( len_part > bytes_transferred)
+ len_part = bytes_transferred;
+
+ mb->wr_ptr (len_part);
+
+ bytes_transferred -= len_part;
+ }
+
+ // 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.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ 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;
+
+ size_t bytes_to_read = 0;
+
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+
+ for (const ACE_Message_Block* msg = message_block;
+ msg != 0 && iovcnt < ACE_IOV_MAX;
+ msg = msg->cont () , ++iovcnt )
+ {
+ size_t msg_space = msg->space ();
+
+ // OS should correctly process zero length buffers
+ // if ( msg_space == 0 )
+ // ACE_ERROR_RETURN ((LM_ERROR,
+ // ACE_TEXT ("ACE_WIN32_Asynch_Read_Dgram::recv:")
+ // ACE_TEXT ("No space in the message block\n")),
+ // -1);
+
+ bytes_to_read += msg_space;
+
+ // Make as many iovec as needed to fit all of msg_len.
+ size_t wr_ptr_offset = 0;
+ while (msg_space > 0 && iovcnt < ACE_IOV_MAX)
+ {
+ u_long this_chunk_length;
+ if (msg_space > ULONG_MAX)
+ this_chunk_length = ULONG_MAX;
+ else
+ this_chunk_length = static_cast<u_long> (msg_space);
+ // Collect the data in the iovec.
+ iov[iovcnt].iov_base = msg->wr_ptr () + wr_ptr_offset;
+ iov[iovcnt].iov_len = this_chunk_length;
+ msg_space -= this_chunk_length;
+ wr_ptr_offset += this_chunk_length;
+
+ // Increment iovec counter if there's more to do.
+ if (msg_space > 0)
+ iovcnt++;
+ }
+ if (msg_space > 0) // Ran out of iovecs before msg_space exhausted
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ if (bytes_to_read == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Read_Dgram::recv:")
+ ACE_TEXT ("Attempt to read 0 bytes\n")),
+ -1);
+
+ // Create the Asynch_Result.
+ ACE_WIN32_Asynch_Read_Dgram_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Read_Dgram_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ flags,
+ protocol_family,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // do the scatter/gather recv
+ ssize_t initiate_result = ACE_OS::recvfrom (result->handle (),
+ iov,
+ iovcnt,
+ number_of_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_TEXT ("%p\n"),
+ ACE_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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ 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)
+{
+}
+
+//***********************************************
+
+size_t
+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_;
+}
+
+size_t
+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 (
+ const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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 (size_t 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 ())
+ {
+ size_t len_part = mb->length ();
+
+ if ( len_part > bytes_transferred)
+ len_part = bytes_transferred;
+
+ mb->rd_ptr (len_part);
+
+ bytes_transferred -= len_part;
+ }
+
+ // Create the interface result class.
+ ACE_Asynch_Write_Dgram::Result result (this);
+
+ // Call the application handler.
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ 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;
+
+ size_t bytes_to_write = 0;
+
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+
+ for (const ACE_Message_Block* msg = message_block;
+ msg != 0 && iovcnt < ACE_IOV_MAX;
+ msg = msg->cont () , ++iovcnt )
+ {
+ size_t msg_len = msg->length ();
+
+ // OS should process zero length block correctly
+ // if ( msg_len == 0 )
+ // ACE_ERROR_RETURN ((LM_ERROR,
+ // ACE_TEXT ("ACE_WIN32_Asynch_Write_Dgram::send:")
+ // ACE_TEXT ("Zero-length message block\n")),
+ // -1);
+
+ bytes_to_write += msg_len;
+
+ // Make as many iovec as needed to fit all of msg_len.
+ size_t rd_ptr_offset = 0;
+ while (msg_len > 0 && iovcnt < ACE_IOV_MAX)
+ {
+ u_long this_chunk_length;
+ if (msg_len > ULONG_MAX)
+ this_chunk_length = ULONG_MAX;
+ else
+ this_chunk_length = static_cast<u_long> (msg_len);
+ // Collect the data in the iovec.
+ iov[iovcnt].iov_base = msg->rd_ptr () + rd_ptr_offset;
+ iov[iovcnt].iov_len = this_chunk_length;
+ msg_len -= this_chunk_length;
+ rd_ptr_offset += this_chunk_length;
+
+ // Increment iovec counter if there's more to do.
+ if (msg_len > 0)
+ iovcnt++;
+ }
+ if (msg_len > 0) // Ran out of iovecs before msg_space exhausted
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ if ( bytes_to_write == 0 )
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("ACE_WIN32_Asynch_Write_Dgram::send:")
+ ACE_TEXT ("Attempt to write 0 bytes\n")),
+ -1);
+
+ // Create the Asynch_Result.
+ ACE_WIN32_Asynch_Write_Dgram_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Write_Dgram_Result (this->handler_proxy_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ flags,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // do the scatter/gather send
+
+ ssize_t initiate_result = ACE_OS::sendto (result->handle (),
+ iov,
+ iovcnt,
+ number_of_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_TEXT ("%p\n"),
+ ACE_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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler_proxy,
+ 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)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO && ACE_HAS_WINSOCK2 */
diff --git a/ACE/ace/WIN32_Asynch_IO.h b/ACE/ace/WIN32_Asynch_IO.h
new file mode 100644
index 00000000000..cd3dc63a213
--- /dev/null
+++ b/ACE/ace/WIN32_Asynch_IO.h
@@ -0,0 +1,1937 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file WIN32_Asynch_IO.h
+ *
+ * $Id$
+ *
+ *
+ * These classes only works on Win32 platforms.
+ *
+ * The implementation of ACE_Asynch_Transmit_File,
+ * ACE_Asynch_Accept, and ACE_Asynch_Connect 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>
+ * @author Alexander Libman <alibman@ihug.com.au>
+ */
+//=============================================================================
+
+#ifndef ACE_WIN32_ASYNCH_IO_H
+#define ACE_WIN32_ASYNCH_IO_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_HAS_WIN32_OVERLAPPED_IO) && \
+ (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 1))
+
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Addr.h"
+#include "ace/Event_Handler.h"
+#include "ace/Handle_Set.h"
+#include "ace/Map_Manager.h"
+#include "ace/Null_Mutex.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// 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.
+ size_t 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 @c 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 (size_t nbytes);
+
+protected:
+ /// Constructor.
+ ACE_WIN32_Asynch_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void* act,
+ ACE_HANDLE event,
+ u_long offset,
+ u_long offset_high,
+ int priority,
+ int signal_number = 0);
+
+ /// Proxy for the ACE_Handler that will be called back.
+ ACE_Handler::Proxy_Ptr handler_proxy_;
+
+ /// ACT for this operation.
+ const void *act_;
+
+ /// Bytes transferred by this operation.
+ size_t 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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::Proxy_Ptr handler_proxy_;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Read_Stream_Result
+ *
+ * @brief This 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.
+ size_t 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.
+ size_t 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 @c this to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+ /// Accessor for the scatter read flag
+ int scatter_enabled (void) const;
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Read_Stream factory.
+ ACE_WIN32_Asynch_Read_Stream_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0,
+ int scatter_enabled = 0);
+
+ /// Proactor will call this method when the read completes.
+ virtual void complete (size_t 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.
+ size_t bytes_to_read_;
+
+ /// Message block for reading the data into.
+ ACE_Message_Block &message_block_;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle_;
+
+ /// Flag for scatter read
+ int scatter_enabled_;
+};
+
+/**
+ * @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 @a 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 @a bytes_to_read will
+ /// be read and stored in the @a message_block.
+ int read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /**
+ * Same as above but with scatter support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ int readv (ACE_Message_Block &message_block,
+ size_t 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 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.
+ size_t 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.
+ size_t 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 @c this to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+ /// Accessor for the gather write flag
+ int gather_enabled (void) const;
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Write_Stream factory.
+ ACE_WIN32_Asynch_Write_Stream_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0,
+ int gather_enabled = 0);
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (size_t 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.
+ size_t 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_;
+
+ /// Flag for gather write
+ int gather_enabled_;
+};
+
+/**
+ * @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 @a 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 @a bytes_to_write
+ /// will be written from the @a message_block.
+ int write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /**
+ * Same as above but with gather support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ int writev (ACE_Message_Block &message_block,
+ size_t 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 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.
+ size_t 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.
+ size_t 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 @c this to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Read_File factory.
+ ACE_WIN32_Asynch_Read_File_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0,
+ int scatter_enabled = 0);
+
+ /// ACE_Proactor will call this method when the read completes.
+ virtual void complete (size_t 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 @a 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 @a bytes_to_read will
+ * be read and stored in the @a message_block. The read will start
+ * at @a offset from the beginning of the file.
+ */
+ int read (ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /**
+ * Same as above but with scatter support, through chaining of
+ * composite message blocks using the continuation field.
+ * @note Each data block payload must be at least the size of a
+ * system memory page and must be aligned on a system memory page
+ * size boundary
+ */
+ int readv (ACE_Message_Block &message_block,
+ size_t 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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,
+ size_t bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /**
+ * Same as above but with scatter support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ int readv (ACE_Message_Block &message_block,
+ size_t 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
+ * @a 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 @a handler instead
+ * of <ACE_Handler::handle_write_stream>. No additional state
+ * is required by this class as ACE_Asynch_Result can store
+ * the @a 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.
+ size_t 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.
+ size_t 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 @c this to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Write_File factory.
+ ACE_WIN32_Asynch_Write_File_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0,
+ int gather_enabled = 0);
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (size_t 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 @a 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 @a bytes_to_write
+ * will be write and stored in the @a message_block. The write will
+ * start at @a offset from the beginning of the file.
+ */
+ int write (ACE_Message_Block &message_block,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /**
+ * Same as above but with gather support, through chaining of
+ * composite message blocks using the continuation field.
+ * @note Each data block payload must be at least the size of a
+ * system memory page and must be aligned on a system memory page
+ * size boundary
+ */
+ int writev (ACE_Message_Block &message_block,
+ size_t 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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,
+ size_t bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /**
+ * Same as above but with gather support, through chaining of composite
+ * message blocks using the continuation field.
+ */
+ int writev (ACE_Message_Block &message_block,
+ size_t 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
+ * @a 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.
+ size_t 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.
+ size_t 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 @c this to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Accept factory.
+ ACE_WIN32_Asynch_Accept_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ /// ACE_Proactor will call this method when the accept completes.
+ virtual void complete (size_t 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.
+ size_t 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 @a 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
+ * @a handler. Upto @a bytes_to_read will be read and stored in the
+ * @a message_block. The <accept_handle> will be used for the
+ * <accept> call. If (<accept_handle> == INVALID_HANDLE), a new
+ * handle will be created.
+ *
+ * @a 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,
+ size_t bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number = 0,
+ int addr_family = AF_INET);
+
+ /// 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_Connect_Result
+ *
+ * @brief This is that class which will be passed back to the
+ * completion handler when the asynchronous connect completes.
+ *
+ * This class has all the information necessary for the
+ * completion handler to uniquiely identify the completion of the
+ * asynchronous connect.
+ */
+class ACE_Export ACE_WIN32_Asynch_Connect_Result : public virtual ACE_Asynch_Connect_Result_Impl,
+ public ACE_WIN32_Asynch_Result
+{
+ /// Factory classes will have special permissions.
+ friend class ACE_WIN32_Asynch_Connect;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_WIN32_Proactor;
+
+public:
+
+ /// I/O handle for the connection.
+ ACE_HANDLE connect_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.
+ size_t bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * 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 object to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Connect factory.
+ ACE_WIN32_Asynch_Connect_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+
+ /// ACE_Proactor will call this method when the accept completes.
+ virtual void complete (size_t bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Connect_Result (void);
+
+ /// Set the I/O handle for the new connection.
+ void connect_handle (ACE_HANDLE handle);
+
+ ACE_HANDLE connect_handle_;
+};
+
+
+/**
+ * @class ACE_WIN32_Asynch_Connect
+ */
+class ACE_Export ACE_WIN32_Asynch_Connect :
+ public virtual ACE_Asynch_Connect_Impl,
+ public ACE_WIN32_Asynch_Operation,
+ public ACE_Event_Handler
+{
+public:
+
+ /// Constructor.
+ ACE_WIN32_Asynch_Connect (ACE_WIN32_Proactor * win32_proactor);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Connect (void);
+
+ /**
+ * This open belongs to ACE_WIN32_Asynch_Operation. We forward
+ * this call to that method. We have put this here to avoid the
+ * compiler warnings.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * Start an asynchronous connect.
+ *
+ * @param connect_handle Handle to use for the connect. If the value
+ * ACE_INVALID_HANDLE, a new handle will be created.
+ *
+ * @retval 0 Success
+ * @retval -1 Error
+ */
+ int connect (ACE_HANDLE connect_handle,
+ const ACE_Addr &remote_sap,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /**
+ * Cancel all pending pseudo-asynchronus requests
+ * Behavior as usual AIO request
+ */
+ int cancel (void);
+
+ /**
+ * Close performs cancellation of all pending requests
+ * and close the connect handle
+ */
+ int close (void);
+
+ /// Virtual from ACE_Event_Handler
+ ACE_HANDLE get_handle (void) const;
+
+ /// Virtual from ACE_Event_Handler
+ void set_handle (ACE_HANDLE handle);
+
+ /// Virtual from ACE_Event_Handler
+ int handle_input ( ACE_HANDLE handle);
+ int handle_output ( ACE_HANDLE handle);
+ int handle_exception ( ACE_HANDLE handle);
+
+ /// Virtual from ACE_Event_Handler
+ int handle_close (ACE_HANDLE handle, ACE_Reactor_Mask close_mask) ;
+
+ // = Methods belong to ACE_WIN32_Asynch_Operation base class. These
+ // methods are defined here to avoid dominace warnings. They route
+ // the call to the ACE_WIN32_Asynch_Operation base class.
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+private:
+ int connect_i (ACE_WIN32_Asynch_Connect_Result *result,
+ const ACE_Addr &remote_sap,
+ const ACE_Addr &local_sap,
+ int reuse_addr);
+
+ int post_result (ACE_WIN32_Asynch_Connect_Result *result, bool flg_post);
+
+ /// Cancel uncompleted connect operations.
+ /**
+ * @param flg_notify Indicates whether or not to send notification about
+ * canceled connect operations. If false, don't send
+ * notifications. If true, notify user about canceled
+ * connects.
+ * According WIN32 standards we should receive
+ * notifications on canceled AIO requests.
+ *
+ * @param set Receives the set of I/O handles on which asynchronous
+ * connect requests were canceled as a result of this
+ * method. The contents of @a set are completely
+ * replaced.
+ */
+ int cancel_uncompleted (bool flg_notify, ACE_Handle_Set &set);
+
+ /// true - Connect is registered in ACE_Asynch_Pseudo_Task
+ /// false - Accept is deregisted in ACE_Asynch_Pseudo_Task
+ bool flg_open_ ;
+
+ typedef ACE_Map_Manager<ACE_HANDLE, ACE_WIN32_Asynch_Connect_Result *, ACE_SYNCH_NULL_MUTEX>
+ MAP_MANAGER;
+
+ /// Map of Result pointers that correspond to all the <accept>'s
+ /// pending.
+ MAP_MANAGER result_map_;
+
+ /// The lock to protect the result map which is shared. The queue
+ /// is updated by main thread in the register function call and
+ /// through the auxillary thread in the asynch pseudo task.
+ ACE_SYNCH_MUTEX lock_;
+};
+
+/**
+ * @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
+ * @a 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.
+ size_t bytes_to_write (void) const;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ size_t 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.
+ size_t 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 @c this to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Transmit_File factory.
+ ACE_WIN32_Asynch_Transmit_File_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ /// Proactor will call this method when the write completes.
+ virtual void complete (size_t 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.
+ size_t bytes_to_write_;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ size_t 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
+ * @a 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 @a bytes_to_write will be
+ * written to the <socket>. If you want to send the entire file,
+ * let @a bytes_to_write = 0. @a 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,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 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.
+ size_t 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.
+ size_t 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 @c this to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Read_Dgram factory.
+ ACE_WIN32_Asynch_Read_Dgram_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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);
+
+ /// Proactor will call this method when the read completes.
+ virtual void complete (size_t 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.
+ size_t 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 @a 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);
+
+ /// Destructor.
+ 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
+ * @a message_block. @a 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 @a 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 @a message_block's
+ * <wr_ptr>'s will be updated to reflect the added bytes for each
+ * @a 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 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.
+ size_t 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.
+ size_t 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 @c this to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ /// Constructor is protected since creation is limited to
+ /// ACE_Asynch_Write_Stream factory.
+ ACE_WIN32_Asynch_Write_Dgram_Result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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);
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (size_t 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.
+ size_t 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 @a 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);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Write_Dgram (void);
+
+ /** This starts off an asynchronous send. Upto
+ * <message_block->total_length()> will be sent. @a 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 @a 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
+ * @a message_block's <rd_ptr>'s will be updated to reflect the bytes sent
+ * from each @a 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 @a handler to get the
+ * correct handle.
+ */
+ int open (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WIN32_OVERLAPPED_IO && ACE_HAS_WINSOCK2 */
+#include /**/ "ace/post.h"
+#endif /* ACE_WIN32_ASYNCH_IO_H */
diff --git a/ACE/ace/WIN32_Proactor.cpp b/ACE/ace/WIN32_Proactor.cpp
new file mode 100644
index 00000000000..18064da3272
--- /dev/null
+++ b/ACE/ace/WIN32_Proactor.cpp
@@ -0,0 +1,804 @@
+// $Id$
+
+// ACE_RCSID(ace, Proactor, "$Id$")
+
+#include "ace/WIN32_Proactor.h"
+
+#if defined (ACE_WIN32) && defined (ACE_HAS_WIN32_OVERLAPPED_IO)
+// WIN implemenatation of the Proactor.
+
+#include "ace/Log_Msg.h"
+#include "ace/Object_Manager.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_WIN32_Wakeup_Completion
+ *
+ * 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.
+ */
+class ACE_WIN32_Wakeup_Completion : public ACE_WIN32_Asynch_Result
+{
+
+public:
+ /// Constructor.
+ ACE_WIN32_Wakeup_Completion (ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void *act = 0,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Wakeup_Completion (void);
+
+ /// This method calls the <handler>'s <handle_wakeup> method.
+ virtual void complete (size_t bytes_transferred = 0,
+ int success = 1,
+ const void *completion_key = 0,
+ u_long error = 0);
+};
+
+ACE_WIN32_Proactor::ACE_WIN32_Proactor (size_t number_of_threads,
+ bool used_with_reactor_event_loop)
+ : completion_port_ (0),
+ // This *MUST* be 0, *NOT* ACE_INVALID_HANDLE !!!
+ number_of_threads_ (static_cast<DWORD> (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_TEXT ("%p\n"),
+ ACE_TEXT ("CreateIoCompletionPort")));
+
+ this->get_asynch_pseudo_task ().start ();
+}
+
+ACE_WIN32_Proactor::~ACE_WIN32_Proactor (void)
+{
+ this->get_asynch_pseudo_task ().stop ();
+
+ this->close ();
+}
+
+ACE_Asynch_Pseudo_Task &
+ACE_WIN32_Proactor::get_asynch_pseudo_task ()
+{
+ return this->pseudo_task_;
+}
+
+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;
+ ULONG_PTR 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 || res == FALSE)
+ 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)
+{
+ ULONG_PTR comp_key (reinterpret_cast<ULONG_PTR> (completion_key));
+
+ // No locking is needed here as no state changes.
+ ACE_HANDLE cp = ::CreateIoCompletionPort (handle,
+ this->completion_port_,
+ comp_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_TEXT ("%p\n"),
+ ACE_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_Connect_Impl *
+ACE_WIN32_Proactor::create_asynch_connect (void)
+{
+ ACE_Asynch_Connect_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Connect (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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t 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_proxy,
+ listen_handle,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Connect_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_connect_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Connect_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Connect_Result (handler_proxy,
+ connect_handle,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Transmit_File_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_transmit_file_result
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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_proxy,
+ 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy,
+ 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 != 1)
+ 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;
+ ULONG_PTR 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 ();
+
+ switch (errno)
+ {
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ return 0;
+
+ case ERROR_SUCCESS:
+ // Calling GetQueuedCompletionStatus with timeout value 0
+ // returns FALSE with extended errno "ERROR_SUCCESS" errno =
+ // ETIME; ?? I don't know if this has to be done !!
+ return 0;
+
+ default:
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("GetQueuedCompletionStatus")));
+ return -1;
+ }
+ }
+ else if (overlapped != 0)
+ {
+ // 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,
+ static_cast<size_t> (bytes_transferred),
+ (void *) completion_key,
+ result_err);
+ }
+ return 1;
+}
+
+void
+ACE_WIN32_Proactor::application_specific_code (ACE_WIN32_Asynch_Result *asynch_result,
+ size_t bytes_transferred,
+ const void *completion_key,
+ u_long error)
+{
+ ACE_SEH_TRY
+ {
+ // Call completion hook
+ asynch_result->complete (bytes_transferred,
+ error ? 0 : 1,
+ (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 ();
+
+ // pass
+ // bytes_transferred
+ // completion_key
+ // to the ::PostQueuedCompletionStatus()
+ // error will be extracted later in handle_events()
+
+ DWORD bytes_transferred = 0;
+ const void * completion_key = 0 ;
+
+ if (result != 0)
+ {
+ // This cast is ok since the original API calls restricted the transfer
+ // counts to DWORD range.
+ bytes_transferred = static_cast<DWORD> (result->bytes_transferred ());
+ completion_key = result->completion_key();
+ }
+
+ ULONG_PTR comp_key (reinterpret_cast<ULONG_PTR> (completion_key));
+
+ // Post a completion
+ if (::PostQueuedCompletionStatus (this->completion_port_, // completion port
+ bytes_transferred, // xfer count
+ comp_key, // completion key
+ result // overlapped
+ ) == FALSE)
+ {
+ delete result;
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("PostQueuedCompletionStatus failed")));
+ }
+ return -1;
+ }
+
+ // If Proactor event is valid, signal it
+ if (handle != ACE_INVALID_HANDLE
+ && handle != 0)
+ ACE_OS::event_signal (&handle);
+
+ 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_.proxy ()),
+ -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 static_cast<size_t> (this->number_of_threads_);
+}
+
+void
+ACE_WIN32_Proactor::number_of_threads (size_t threads)
+{
+ this->number_of_threads_ = static_cast<DWORD> (threads);
+}
+
+ACE_WIN32_Asynch_Timer::ACE_WIN32_Asynch_Timer
+ (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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_proxy, act, event, 0, 0, priority,
+ signal_number),
+ time_ (tv)
+{
+}
+
+void
+ACE_WIN32_Asynch_Timer::complete (size_t,
+ int,
+ const void *,
+ u_long)
+{
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_time_out (this->time_, this->act ());
+}
+
+ACE_WIN32_Wakeup_Completion::ACE_WIN32_Wakeup_Completion
+ (ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_WIN32_Asynch_Result
+ (handler_proxy, act, event, 0, 0, priority, signal_number)
+{
+}
+
+ACE_WIN32_Wakeup_Completion::~ACE_WIN32_Wakeup_Completion (void)
+{
+}
+
+void
+ACE_WIN32_Wakeup_Completion::complete (size_t /* bytes_transferred */,
+ int /* success */,
+ const void * /* completion_key */,
+ u_long /* error */)
+{
+ ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
+ if (handler != 0)
+ handler->handle_wakeup ();
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 */
diff --git a/ACE/ace/WIN32_Proactor.h b/ACE/ace/WIN32_Proactor.h
new file mode 100644
index 00000000000..521a78448bc
--- /dev/null
+++ b/ACE/ace/WIN32_Proactor.h
@@ -0,0 +1,325 @@
+// -*- 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>
+ * @author Alexander Libman <alibman@ihug.com.au>
+ */
+//=============================================================================
+
+#ifndef ACE_WIN32_PROACTOR_H
+#define ACE_WIN32_PROACTOR_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_HAS_WIN32_OVERLAPPED_IO)
+// WIN32 implementation of the Proactor.
+
+#include "ace/WIN32_Asynch_IO.h"
+#include "ace/Event_Handler.h"
+
+#include "ace/Proactor_Impl.h"
+#include "ace/Asynch_Pseudo_Task.h"
+#include "ace/Auto_Event.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+class ACE_WIN32_Asynch_Result;
+class ACE_WIN32_Proactor_Timer_Handler;
+
+/**
+ * @class ACE_WIN32_Proactor
+ *
+ * @brief A manager for asynchronous event demultiplexing on Win32.
+ *
+ * See the Proactor pattern description at
+ * http://www.cs.wustl.edu/~schmidt/PDF/proactor.pdf for more
+ * details.
+ */
+class ACE_Export ACE_WIN32_Proactor : public ACE_Proactor_Impl
+{
+ friend class ACE_WIN32_Asynch_Connect;
+
+public:
+ /// A do nothing constructor.
+ ACE_WIN32_Proactor (size_t number_of_threads = 0,
+ bool used_with_reactor_event_loop = false);
+
+ /// Virtual destruction.
+ virtual ~ACE_WIN32_Proactor (void);
+
+ /// Close the IO completion port.
+ virtual int close (void);
+
+ /// This method adds the @a 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 @a 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. 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);
+
+ /// Get number of thread used as a parameter to @c CreateIoCompletionPort.
+ size_t number_of_threads (void) const;
+
+ /// Set number of thread used as a parameter to @c CreateIoCompletionPort.
+ 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_Connect_Impl *create_asynch_connect (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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ size_t bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ virtual ACE_Asynch_Connect_Result_Impl *create_asynch_connect_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE connect_handle,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+
+ virtual ACE_Asynch_Transmit_File_Result_Impl *create_asynch_transmit_file_result (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ size_t bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ size_t 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+protected:
+ /// Task to process pseudo-asynchronous operations
+ ACE_Asynch_Pseudo_Task & get_asynch_pseudo_task (void);
+
+ /// 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 @a 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,
+ size_t bytes_transferred,
+ const void *completion_key,
+ u_long error);
+
+ /**
+ * Post @a 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 @c CreateIOCompletionPort system
+ /// call.
+ DWORD 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.
+ bool const 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_;
+
+ /// Pseudo-task for asynch connect ( NT/2000)
+ /// In future should removed in XP with ConnectEx support
+ ACE_Asynch_Pseudo_Task pseudo_task_;
+};
+
+/**
+ * @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 @a handler's handle_timeout method will be
+ * called.
+ */
+class 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 (const ACE_Handler::Proxy_Ptr &handler_proxy,
+ 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 @a handler's handle_timeout method.
+ virtual void complete (size_t bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error = 0);
+
+ /// Time value requested by caller
+ ACE_Time_Value time_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_WIN32 */
+#include /**/ "ace/post.h"
+#endif /* ACE_PROACTOR_H */
diff --git a/ACE/ace/XML_Svc_Conf.cpp b/ACE/ace/XML_Svc_Conf.cpp
new file mode 100644
index 00000000000..b81c9162076
--- /dev/null
+++ b/ACE/ace/XML_Svc_Conf.cpp
@@ -0,0 +1,15 @@
+// $Id$
+
+#include "ace/XML_Svc_Conf.h"
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 0)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_XML_Svc_Conf::~ACE_XML_Svc_Conf (void)
+{
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */
diff --git a/ACE/ace/XML_Svc_Conf.h b/ACE/ace/XML_Svc_Conf.h
new file mode 100644
index 00000000000..182d554805b
--- /dev/null
+++ b/ACE/ace/XML_Svc_Conf.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file XML_Svc_Conf.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_XML_SVC_CONF_H
+#define ACE_XML_SVC_CONF_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/ACE_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_USES_CLASSIC_SVC_CONF==0)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_XML_Svc_Conf
+ *
+ * @brief This abstract class defines the common operations
+ * ACE_Service_Config expects when using the XML Service Config Parser.
+ *
+ * When implementing a concret XML_Svc_Conf class, be sure to overload
+ * the new/delete function so the dynamically created concret XML_Svc_Conf
+ * instance can be deleted from the original heap in the DLL/SO. The
+ * concret XML_Svc_Conf implementation will be put into a DLL/SO that
+ * ACE applications can link to dynamically using the ACE_DLL class.
+ * This DLL should include an operation as follow:
+ *
+ * extern "C" ACE_XML_Svc_Conf_Parser * _ACEXML_create_XML_Svc_Conf_Object (void);
+ *
+ *
+ */
+
+class ACE_Export ACE_XML_Svc_Conf
+{
+public:
+ typedef ACE_XML_Svc_Conf *(*Factory)(void);
+
+ virtual ~ACE_XML_Svc_Conf (void) = 0;
+
+ virtual int parse_file (const ACE_TCHAR file[]) = 0;
+
+ virtual int parse_string (const ACE_TCHAR str[]) = 0;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_XML_SVC_CONF_H */
diff --git a/ACE/ace/XTI_ATM_Mcast.cpp b/ACE/ace/XTI_ATM_Mcast.cpp
new file mode 100644
index 00000000000..854e2a36489
--- /dev/null
+++ b/ACE/ace/XTI_ATM_Mcast.cpp
@@ -0,0 +1,70 @@
+// $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.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_XTI_ATM_Mcast)
+
+void
+ACE_XTI_ATM_Mcast::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_XTI_ATM_Mcast::dump");
+#endif /* ACE_HAS_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 const 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_XTI_ATM */
diff --git a/ACE/ace/XTI_ATM_Mcast.h b/ACE/ace/XTI_ATM_Mcast.h
new file mode 100644
index 00000000000..360becbaa63
--- /dev/null
+++ b/ACE/ace/XTI_ATM_Mcast.h
@@ -0,0 +1,137 @@
+// -*- 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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_XTI_ATM)
+
+#include "ace/TLI_Connector.h"
+#include "ace/ATM_Addr.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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 @a new_stream if things go well.
+ * The @a remote_sap is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a 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 @a new_stream if things go well.
+ * The @a remote_sap is the address that we are trying to connect
+ * with. The @a 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 @c 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 @c errno == ETIME. The
+ * @a 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 @a 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 @a remote_sap is the address of the leaf that we
+ * are trying to add. The @a 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 @c 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 @c 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;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/XTI_ATM_Mcast.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_XTI_ATM */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_XTI_ATM_MCAST_H */
diff --git a/ACE/ace/XTI_ATM_Mcast.inl b/ACE/ace/XTI_ATM_Mcast.inl
new file mode 100644
index 00000000000..7cdfbbf6160
--- /dev/null
+++ b/ACE/ace/XTI_ATM_Mcast.inl
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 rw_flag,
+ struct netbuf *udata,
+ struct 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, rw_flag,
+ udata, opt) == ACE_INVALID_HANDLE
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_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,
+ struct netbuf *udata,
+ struct 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);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/XtReactor/ACE_XtReactor.pc.in b/ACE/ace/XtReactor/ACE_XtReactor.pc.in
new file mode 100644
index 00000000000..118c61c5632
--- /dev/null
+++ b/ACE/ace/XtReactor/ACE_XtReactor.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE_XtReactor
+Description: ACE XtReactor Library
+Requires: ACE
+Version: @VERSION@
+Libs: -L${libdir} -lACE_XtReactor
+Cflags: -I${includedir}
diff --git a/ACE/ace/XtReactor/ACE_XtReactor_export.h b/ACE/ace/XtReactor/ACE_XtReactor_export.h
new file mode 100644
index 00000000000..3d9049cb7af
--- /dev/null
+++ b/ACE/ace/XtReactor/ACE_XtReactor_export.h
@@ -0,0 +1,58 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl -s ACE_XtReactor
+// ------------------------------
+#ifndef ACE_XTREACTOR_EXPORT_H
+#define ACE_XTREACTOR_EXPORT_H
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_XTREACTOR_HAS_DLL)
+# define ACE_XTREACTOR_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ACE_XTREACTOR_HAS_DLL */
+
+#if !defined (ACE_XTREACTOR_HAS_DLL)
+# define ACE_XTREACTOR_HAS_DLL 1
+#endif /* ! ACE_XTREACTOR_HAS_DLL */
+
+#if defined (ACE_XTREACTOR_HAS_DLL) && (ACE_XTREACTOR_HAS_DLL == 1)
+# if defined (ACE_XTREACTOR_BUILD_DLL)
+# define ACE_XtReactor_Export ACE_Proper_Export_Flag
+# define ACE_XTREACTOR_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define ACE_XTREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* ACE_XTREACTOR_BUILD_DLL */
+# define ACE_XtReactor_Export ACE_Proper_Import_Flag
+# define ACE_XTREACTOR_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define ACE_XTREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ACE_XTREACTOR_BUILD_DLL */
+#else /* ACE_XTREACTOR_HAS_DLL == 1 */
+# define ACE_XtReactor_Export
+# define ACE_XTREACTOR_SINGLETON_DECLARATION(T)
+# define ACE_XTREACTOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* ACE_XTREACTOR_HAS_DLL == 1 */
+
+// Set ACE_XTREACTOR_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (ACE_XTREACTOR_NTRACE)
+# if (ACE_NTRACE == 1)
+# define ACE_XTREACTOR_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define ACE_XTREACTOR_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !ACE_XTREACTOR_NTRACE */
+
+#if (ACE_XTREACTOR_NTRACE == 1)
+# define ACE_XTREACTOR_TRACE(X)
+#else /* (ACE_XTREACTOR_NTRACE == 1) */
+# if !defined (ACE_HAS_TRACE)
+# define ACE_HAS_TRACE
+# endif /* ACE_HAS_TRACE */
+# define ACE_XTREACTOR_TRACE(X) ACE_TRACE_IMPL(X)
+# include "ace/Trace.h"
+#endif /* (ACE_XTREACTOR_NTRACE == 1) */
+
+#endif /* ACE_XTREACTOR_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/XtReactor/XtReactor.cpp b/ACE/ace/XtReactor/XtReactor.cpp
new file mode 100644
index 00000000000..7bdef11b936
--- /dev/null
+++ b/ACE/ace/XtReactor/XtReactor.cpp
@@ -0,0 +1,450 @@
+// $Id$
+
+#include "ace/XtReactor/XtReactor.h"
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+
+ACE_RCSID(ace, XtReactor, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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 const 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 *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ 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 const result = ACE_Select_Reactor::schedule_timer (event_handler,
+ arg,
+ delay,
+ 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;
+ }
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/XtReactor/XtReactor.h b/ACE/ace/XtReactor/XtReactor.h
new file mode 100644
index 00000000000..ee1aa882710
--- /dev/null
+++ b/ACE/ace/XtReactor/XtReactor.h
@@ -0,0 +1,138 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file XtReactor.h
+ *
+ * $Id$
+ *
+ * @author Eric C. Newton <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/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+#include "ace/XtReactor/ACE_XtReactor_export.h"
+#include "ace/Select_Reactor.h"
+
+#include /**/ <X11/Intrinsic.h>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @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_XtReactor_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_XtReactor_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 *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ 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 @a 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 @a handler associated with this @a 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 &);
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_XTREACTOR_H */
diff --git a/ACE/ace/ace.mpc b/ACE/ace/ace.mpc
new file mode 100644
index 00000000000..3a8a1609054
--- /dev/null
+++ b/ACE/ace/ace.mpc
@@ -0,0 +1,464 @@
+// -*- MPC -*- now wouldn't this be cool...
+// $Id$
+
+project(ACE) : acedefaults, install, other, codecs, token, svcconf, uuid, filecache, versioned_namespace, pkgconfig, support_ostream {
+ avoids = ace_for_tao
+ libout = $(ACE_ROOT)/lib
+ sharedname = ACE
+ dynamicflags = ACE_BUILD_DLL
+
+ Source_Files(ACE_COMPONENTS) {
+ ACE.cpp
+ ACE_crc_ccitt.cpp
+ ACE_crc32.cpp
+ ace_wchar.cpp
+ Activation_Queue.cpp
+ Active_Map_Manager.cpp
+ Addr.cpp
+ Argv_Type_Converter.cpp
+ Assert.cpp
+ Asynch_IO.cpp
+ Asynch_IO_Impl.cpp
+ Asynch_Pseudo_Task.cpp
+ ATM_Acceptor.cpp
+ ATM_Addr.cpp
+ ATM_Connector.cpp
+ ATM_Params.cpp
+ ATM_QoS.cpp
+ ATM_Stream.cpp
+ Atomic_Op.cpp
+ Atomic_Op_Sparc.c
+ Auto_Event.cpp
+ Barrier.cpp
+ Base_Thread_Adapter.cpp
+ Based_Pointer_Repository.cpp
+ Basic_Stats.cpp
+ Basic_Types.cpp
+ Capabilities.cpp
+ CDR_Base.cpp
+ CDR_Stream.cpp
+ CDR_Size.cpp
+ Cleanup.cpp
+ Codeset_IBM1047.cpp
+ Codeset_Registry.cpp
+ Codeset_Registry_db.cpp
+ Condition_Recursive_Thread_Mutex.cpp
+ Condition_Thread_Mutex.cpp
+ Configuration.cpp
+ Configuration_Import_Export.cpp
+ Connection_Recycling_Strategy.cpp
+ Containers.cpp
+ Copy_Disabled.cpp
+ Countdown_Time.cpp
+ Date_Time.cpp
+ DEV.cpp
+ DEV_Addr.cpp
+ DEV_Connector.cpp
+ DEV_IO.cpp
+ DLL_Manager.cpp
+ Dev_Poll_Reactor.cpp
+ Dirent.cpp
+ Dirent_Selector.cpp
+ Dump.cpp
+ Dynamic.cpp
+ Dynamic_Message_Strategy.cpp
+ Event.cpp
+ Event_Handler.cpp
+ FIFO.cpp
+ FIFO_Recv.cpp
+ FIFO_Recv_Msg.cpp
+ FIFO_Send.cpp
+ FIFO_Send_Msg.cpp
+ FILE.cpp
+ FILE_Addr.cpp
+ FILE_Connector.cpp
+ FILE_IO.cpp
+ File_Lock.cpp
+ Flag_Manip.cpp
+ Framework_Component.cpp
+ Functor.cpp
+ Functor_String.cpp
+ Get_Opt.cpp
+ gethrtime.cpp
+ Handle_Ops.cpp
+ Handle_Set.cpp
+ Hashable.cpp
+ High_Res_Timer.cpp
+ ICMP_Socket.cpp
+ INET_Addr.cpp
+ Init_ACE.cpp
+ IO_SAP.cpp
+ IO_Cntl_Msg.cpp
+ IOStream.cpp
+ IPC_SAP.cpp
+ Lib_Find.cpp
+ Local_Memory_Pool.cpp
+ Lock.cpp
+ Log_Msg.cpp
+ Log_Msg_Backend.cpp
+ Log_Msg_Callback.cpp
+ Log_Msg_IPC.cpp
+ Log_Msg_NT_Event_Log.cpp
+ Log_Msg_UNIX_Syslog.cpp
+ Log_Record.cpp
+ Logging_Strategy.cpp
+ LSOCK.cpp
+ LSOCK_Acceptor.cpp
+ LSOCK_CODgram.cpp
+ LSOCK_Connector.cpp
+ LSOCK_Dgram.cpp
+ LSOCK_Stream.cpp
+ Malloc.cpp
+ Malloc_Allocator.cpp
+ Manual_Event.cpp
+ MEM_Acceptor.cpp
+ MEM_Addr.cpp
+ MEM_Connector.cpp
+ MEM_IO.cpp
+ Mem_Map.cpp
+ MEM_SAP.cpp
+ MEM_Stream.cpp
+ Message_Block.cpp
+ Message_Queue.cpp
+ Message_Queue_NT.cpp
+ Message_Queue_Vx.cpp
+ Method_Request.cpp
+ MMAP_Memory_Pool.cpp
+ Msg_WFMO_Reactor.cpp
+ Multihomed_INET_Addr.cpp
+ Mutex.cpp
+ Netlink_Addr.cpp
+ Notification_Strategy.cpp
+ Notification_Queue.cpp
+ Obchunk.cpp
+ Object_Manager.cpp
+ Object_Manager_Base.cpp
+ OS_Errno.cpp
+ OS_Log_Msg_Attributes.cpp
+ OS_main.cpp
+ OS_NS_arpa_inet.cpp
+ OS_NS_ctype.cpp
+ OS_NS_dirent.cpp
+ OS_NS_dlfcn.cpp
+ OS_NS_errno.cpp
+ OS_NS_fcntl.cpp
+ OS_NS_math.cpp
+ OS_NS_netdb.cpp
+ OS_NS_poll.cpp
+ OS_NS_pwd.cpp
+ OS_NS_regex.cpp
+ OS_NS_signal.cpp
+ OS_NS_stdio.cpp
+ OS_NS_stdlib.cpp
+ OS_NS_string.cpp
+ OS_NS_strings.cpp
+ OS_NS_stropts.cpp
+ OS_NS_sys_mman.cpp
+ OS_NS_sys_msg.cpp
+ OS_NS_sys_resource.cpp
+ OS_NS_sys_select.cpp
+ OS_NS_sys_sendfile.cpp
+ OS_NS_sys_shm.cpp
+ OS_NS_sys_socket.cpp
+ OS_NS_sys_stat.cpp
+ OS_NS_sys_time.cpp
+ OS_NS_sys_uio.cpp
+ OS_NS_sys_utsname.cpp
+ OS_NS_sys_wait.cpp
+ OS_NS_Thread.cpp
+ OS_NS_time.cpp
+ OS_NS_unistd.cpp
+ OS_NS_wchar.cpp
+ OS_QoS.cpp
+ OS_Thread_Adapter.cpp
+ OS_TLI.cpp
+ Pagefile_Memory_Pool.cpp
+ Parse_Node.cpp
+ PI_Malloc.cpp
+ Ping_Socket.cpp
+ Pipe.cpp
+ POSIX_Asynch_IO.cpp
+ POSIX_CB_Proactor.cpp
+ POSIX_Proactor.cpp
+ Priority_Reactor.cpp
+ Proactor.cpp
+ Proactor_Impl.cpp
+ Process.cpp
+ Process_Manager.cpp
+ Process_Mutex.cpp
+ Process_Semaphore.cpp
+ Profile_Timer.cpp
+ Reactor.cpp
+ Reactor_Impl.cpp
+ Reactor_Notification_Strategy.cpp
+ Reactor_Timer_Interface.cpp
+ Read_Buffer.cpp
+ Recursive_Thread_Mutex.cpp
+ Recyclable.cpp
+ Refcountable.cpp
+ Registry.cpp
+ Rtems_init.c
+ RW_Mutex.cpp
+ RW_Process_Mutex.cpp
+ RW_Thread_Mutex.cpp
+ Sample_History.cpp
+ Sbrk_Memory_Pool.cpp
+ Sched_Params.cpp
+ Select_Reactor_Base.cpp
+ Semaphore.cpp
+ Shared_Memory.cpp
+ Shared_Memory_MM.cpp
+ Shared_Memory_Pool.cpp
+ Shared_Memory_SV.cpp
+ Sig_Adapter.cpp
+ Sig_Handler.cpp
+ Signal.cpp
+ SOCK.cpp
+ SOCK_Acceptor.cpp
+ SOCK_CODgram.cpp
+ Sock_Connect.cpp
+ SOCK_Connector.cpp
+ SOCK_Dgram.cpp
+ SOCK_Dgram_Bcast.cpp
+ SOCK_Dgram_Mcast.cpp
+ SOCK_IO.cpp
+ SOCK_Netlink.cpp
+ SOCK_SEQPACK_Acceptor.cpp
+ SOCK_SEQPACK_Association.cpp
+ SOCK_SEQPACK_Connector.cpp
+ SOCK_Stream.cpp
+ SPIPE.cpp
+ SPIPE_Acceptor.cpp
+ SPIPE_Addr.cpp
+ SPIPE_Connector.cpp
+ SPIPE_Stream.cpp
+ SString.cpp
+ Stats.cpp
+ String_Base_Const.cpp
+ SUN_Proactor.cpp
+ SV_Message.cpp
+ SV_Message_Queue.cpp
+ SV_Semaphore_Complex.cpp
+ SV_Semaphore_Simple.cpp
+ SV_Shared_Memory.cpp
+ Synch_Options.cpp
+ System_Time.cpp
+ Task.cpp
+ Thread.cpp
+ Thread_Adapter.cpp
+ Thread_Control.cpp
+ Thread_Exit.cpp
+ Thread_Hook.cpp
+ Thread_Manager.cpp
+ Thread_Mutex.cpp
+ Thread_Semaphore.cpp
+ Throughput_Stats.cpp
+ Time_Value.cpp
+ Timeprobe.cpp
+ TLI.cpp
+ TLI_Acceptor.cpp
+ TLI_Connector.cpp
+ TLI_Stream.cpp
+ Token.cpp
+ TP_Reactor.cpp
+ Trace.cpp
+ TSS_Adapter.cpp
+ TTY_IO.cpp
+ UNIX_Addr.cpp
+ UPIPE_Acceptor.cpp
+ UPIPE_Connector.cpp
+ UPIPE_Stream.cpp
+ WFMO_Reactor.cpp
+ WIN32_Asynch_IO.cpp
+ WIN32_Proactor.cpp
+ XTI_ATM_Mcast.cpp
+ }
+
+ Template_Files {
+ Acceptor.cpp
+ Active_Map_Manager_T.cpp
+ ARGV.cpp
+ Arg_Shifter.cpp
+ Array_Base.cpp
+ Array_Map.cpp
+ Asynch_Acceptor.cpp
+ Asynch_Connector.cpp
+ Atomic_Op_T.cpp
+ Auto_Functor.cpp
+ Auto_IncDec_T.cpp
+ Auto_Ptr.cpp
+ Based_Pointer_T.cpp
+ Cache_Map_Manager_T.cpp
+ Cached_Connect_Strategy_T.cpp
+ Caching_Strategies_T.cpp
+ Caching_Utility_T.cpp
+ Cleanup_Strategies_T.cpp
+ Condition_T.cpp
+ Connector.cpp
+ Containers_T.cpp
+ Dump_T.cpp
+ Dynamic_Service.cpp
+ Env_Value_T.cpp
+ Event_Handler_T.cpp
+ Framework_Component_T.cpp
+ Free_List.cpp
+ Functor_T.cpp
+ Future.cpp
+ Future_Set.cpp
+ Guard_T.cpp
+ Hash_Cache_Map_Manager_T.cpp
+ Hash_Map_Manager_T.cpp
+ Hash_Multi_Map_Manager_T.cpp
+ Hash_Map_With_Allocator_T.cpp
+ IOStream_T.cpp
+ Intrusive_List.cpp
+ Intrusive_List_Node.cpp
+ LOCK_SOCK_Acceptor.cpp
+ Local_Name_Space_T.cpp
+ Lock_Adapter_T.cpp
+ Malloc_T.cpp
+ Managed_Object.cpp
+ Map_Manager.cpp
+ Map_T.cpp
+ Message_Block_T.cpp
+ Message_Queue_T.cpp
+ Module.cpp
+ Node.cpp
+ Obstack_T.cpp
+ Pair_T.cpp
+ RB_Tree.cpp
+ Reactor_Token_T.cpp
+ Refcounted_Auto_Ptr.cpp
+ Reverse_Lock_T.cpp
+ Select_Reactor_T.cpp
+ Singleton.cpp
+ Strategies_T.cpp
+ Stream.cpp
+ Stream_Modules.cpp
+ String_Base.cpp
+ Svc_Handler.cpp
+ Synch_T.cpp
+ TSS_T.cpp
+ Task_Ex_T.cpp
+ Task_T.cpp
+ Test_and_Set.cpp
+ Timeprobe_T.cpp
+ Timer_Hash_T.cpp
+ Timer_Heap_T.cpp
+ Timer_List_T.cpp
+ Timer_Queue_Adapters.cpp
+ Timer_Queue_T.cpp
+ Timer_Wheel_T.cpp
+ Typed_SV_Message.cpp
+ Typed_SV_Message_Queue.cpp
+ Unbounded_Queue.cpp
+ Unbounded_Set.cpp
+ Vector_T.cpp
+ }
+
+ Inline_Files {
+ Bound_Ptr.inl
+ Condition_T.inl
+ Guard_T.inl
+ Handle_Gobbler.inl
+ Lock_Adapter_T.inl
+ Refcounted_Auto_Ptr.inl
+ Reverse_Lock_T.inl
+ TSS_T.inl
+ ace_wchar.inl
+ OS.inl
+ }
+
+ Header_Files {
+ ACE_export.h
+ Array.h
+ Bound_Ptr.h
+ CORBA_macros.h
+ Condition_T.h
+ Default_Constants.h
+ Exception_Macros.h
+ Global_Macros.h
+ Guard_T.h
+ Hash_Map_Manager.h
+ Handle_Gobbler.h
+ If_Then_Else.h
+ IO_Cntl_Msg.h
+ Lock_Adapter_T.h
+ Log_Priority.h
+ Malloc_Base.h
+ Method_Object.h
+ Memory_Pool.h
+ Min_Max.h
+ Netlink_Addr.h
+ Null_Barrier.h
+ Null_Condition.h
+ Null_Mutex.h
+ Null_Semaphore.h
+ Numeric_Limits.h
+ OS.h
+ OS_Dirent.h
+ OS_Memory.h
+ OS_NS_macros.h
+ OS_String.h
+ OS_Thread_Adapter.h
+ Object_Manager_Base.h
+ Pair.h
+ Proactor_Impl.h
+ Reactor_Impl.h
+ Reactor_Timer_Interface.h
+ Refcounted_Auto_Ptr.h
+ Reverse_Lock_T.h
+ Select_Reactor.h
+ SOCK_Netlink.h
+ SStringfwd.h
+ Static_Object_Lock.h
+ Strategies.h
+ String_Base_Const.h
+ Svc_Conf.h
+ Svc_Conf_Tokens.h
+ Synch.h
+ Synch_Traits.h
+ TSS_T.h
+ Timer_Queuefwd.h
+ Truncate.h
+ UPIPE_Addr.h
+ Value_Ptr.h
+ Version.h
+ Versioned_Namespace.h
+ ace_wchar.h
+ checked_iterator.h
+ config-WinCE.h
+ config-all.h
+ config-borland-common.h
+ config-lite.h
+ config-macros.h
+ config-minimal.h
+ config-win32-borland.h
+ config-win32-common.h
+ config-win32-ghs.h
+ config-win32-msvc-7.h
+ config-win32-msvc-8.h
+ config-win32-msvc.h
+ config-win32.h
+ config.h
+ iosfwd.h
+ os_include
+ os_include/arpa
+ os_include/net
+ os_include/netinet
+ os_include/sys
+ post.h
+ pre.h
+ streams.h
+ svc_export.h
+ }
+
+ Documentation_Files {
+ README
+ ../VERSION
+ }
+
+ Pkgconfig_Files {
+ ACE.pc.in
+ }
+}
diff --git a/ACE/ace/ace.mwc b/ACE/ace/ace.mwc
new file mode 100644
index 00000000000..60eecba03e4
--- /dev/null
+++ b/ACE/ace/ace.mwc
@@ -0,0 +1,14 @@
+// -*- MPC -*-
+//
+// $Id$
+
+workspace {
+ ace.mpc
+ ace_for_tao.mpc
+ ace_flreactor.mpc
+ ace_qtreactor.mpc
+ ace_tkreactor.mpc
+ ace_xtreactor.mpc
+ QoS
+ SSL
+}
diff --git a/ACE/ace/ace.rc b/ACE/ace/ace.rc
new file mode 100644
index 00000000000..54792491900
--- /dev/null
+++ b/ACE/ace/ace.rc
@@ -0,0 +1,38 @@
+#include "Version.h"
+
+1 VERSIONINFO
+ FILEVERSION ACE_MAJOR_VERSION,ACE_MINOR_VERSION,ACE_BETA_VERSION,0
+ PRODUCTVERSION ACE_MAJOR_VERSION,ACE_MINOR_VERSION,ACE_BETA_VERSION,0
+ FILEFLAGSMASK 0x3fL
+ FILEFLAGS 0x0L
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "FileDescription", "ACE\0"
+ VALUE "FileVersion", ACE_VERSION "\0"
+ VALUE "InternalName", "ACEDLL\0"
+ VALUE "LegalCopyright", "\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "ACE.DLL\0"
+ VALUE "ProductName", "ACE\0"
+ VALUE "ProductVersion", ACE_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+/*
+ * The following resource is used by the ACE logger to write messages
+ * to the NT event log. If you are statically linking to the ACE
+ * library, and you wish to use the NT event log, you should copy this
+ * message table to your application's resource script.
+ */
+1 MESSAGETABLE ace_message_table.bin
diff --git a/ACE/ace/ace_ce_dll.cfg b/ACE/ace/ace_ce_dll.cfg
new file mode 100644
index 00000000000..80c479b3205
--- /dev/null
+++ b/ACE/ace/ace_ce_dll.cfg
@@ -0,0 +1 @@
+WCE_CFG=WCE200; \ No newline at end of file
diff --git a/ACE/ace/ace_flreactor.mpc b/ACE/ace/ace_flreactor.mpc
new file mode 100644
index 00000000000..435e816148a
--- /dev/null
+++ b/ACE/ace/ace_flreactor.mpc
@@ -0,0 +1,32 @@
+// -*- MPC -*- now wouldn't this be cool...
+// $Id$
+
+project(ACE_FlReactor) : acedefaults, install, acelib, ace_output, ace_fl{
+
+ sharedname = ACE_FlReactor
+ dynamicflags = ACE_FLREACTOR_BUILD_DLL
+
+ Source_Files {
+ FlReactor
+ }
+
+ Header_Files {
+ FlReactor
+ }
+
+ Inline_Files {
+ FlReactor
+ }
+
+ Template_Files {
+ FlReactor
+ }
+
+ Resource_Files {
+ FlReactor
+ }
+
+ Pkgconfig_Files {
+ FlReactor/ACE_FlReactor.pc.in
+ }
+}
diff --git a/ACE/ace/ace_for_tao.mpc b/ACE/ace/ace_for_tao.mpc
new file mode 100644
index 00000000000..2d8bd62faf3
--- /dev/null
+++ b/ACE/ace/ace_for_tao.mpc
@@ -0,0 +1,377 @@
+// -*- MPC -*-
+//
+// $Id$
+
+// The ACE_FOR_TAO subset is designed primarily for use with the
+// TAO CosNotification service. It is not intended to be used
+// for some of other TAO features and services, such as the TAO
+// Strategies library, the CosNaming service, etc.
+//
+// Avoid adding source files simply to get some ACE/TAO-based code to
+// link. This ACE_FOR_TAO subset library must remain as small as
+// possible.
+
+project(ACE_FOR_TAO) : acedefaults, install, svcconf, uuid, versioned_namespace, pkgconfig {
+ macros += ACE_LACKS_ACE_TOKEN
+ requires = ace_for_tao ace_svcconf
+ libout = $(ACE_ROOT)/lib
+ sharedname = ACE_FOR_TAO
+ dynamicflags = ACE_BUILD_DLL
+
+ Source_Files(ACE_COMPONENTS) {
+ ACE.cpp
+ Active_Map_Manager.cpp
+ Addr.cpp
+ Argv_Type_Converter.cpp
+ Assert.cpp
+ Atomic_Op.cpp
+ Auto_Event.cpp
+ Barrier.cpp // Required by orbsvcs/tests/Notify/lib
+ Base_Thread_Adapter.cpp
+ Based_Pointer_Repository.cpp
+ Basic_Stats.cpp // Required by ace/Stats
+ Basic_Types.cpp
+ Capabilities.cpp // Required by TAO/orbsvcs/examples/ImR/Advanced
+ CDR_Base.cpp
+ CDR_Stream.cpp
+ CDR_Size.cpp
+ Cleanup.cpp
+ Codeset_IBM1047.cpp
+ Codeset_Registry.cpp
+ Codeset_Registry_db.cpp
+ Condition_Recursive_Thread_Mutex.cpp
+ Condition_Thread_Mutex.cpp
+ Countdown_Time.cpp
+ Copy_Disabled.cpp
+ DLL_Manager.cpp
+ Dirent.cpp // Required by TAO_IDL
+ Dirent_Selector.cpp
+ Dump.cpp
+ Dynamic.cpp
+ Dynamic_Message_Strategy.cpp
+ Event.cpp
+ Event_Handler.cpp
+ FILE.cpp
+ FILE_Addr.cpp
+ Flag_Manip.cpp
+ Framework_Component.cpp
+ Functor.cpp
+ Functor_String.cpp
+ Get_Opt.cpp
+ Handle_Ops.cpp
+ Handle_Set.cpp
+ Hashable.cpp
+ High_Res_Timer.cpp // Required by orbsvcs/tests/Notify/lib
+ INET_Addr.cpp
+ Init_ACE.cpp
+ IO_SAP.cpp
+ IO_Cntl_Msg.cpp
+ IOStream.cpp
+ IPC_SAP.cpp
+ Lib_Find.cpp
+ Local_Memory_Pool.cpp
+ Lock.cpp
+ Log_Msg.cpp
+ Log_Msg_Backend.cpp
+ Log_Msg_Callback.cpp
+ Log_Msg_IPC.cpp
+ Log_Msg_NT_Event_Log.cpp
+ Log_Msg_UNIX_Syslog.cpp
+ Log_Record.cpp
+ Logging_Strategy.cpp
+ Malloc.cpp
+ Malloc_Allocator.cpp
+ Manual_Event.cpp
+ Mem_Map.cpp
+ Message_Block.cpp
+ Message_Queue.cpp
+ MMAP_Memory_Pool.cpp
+ Mutex.cpp
+ Notification_Strategy.cpp
+ Notification_Queue.cpp
+ Obchunk.cpp
+ Object_Manager.cpp
+ Object_Manager_Base.cpp
+ OS_Errno.cpp
+ OS_Log_Msg_Attributes.cpp
+ OS_main.cpp
+ OS_NS_arpa_inet.cpp
+ OS_NS_ctype.cpp
+ OS_NS_dirent.cpp
+ OS_NS_dlfcn.cpp
+ OS_NS_errno.cpp
+ OS_NS_fcntl.cpp
+ OS_NS_math.cpp
+ OS_NS_netdb.cpp
+ OS_NS_poll.cpp
+ OS_NS_pwd.cpp
+ OS_NS_regex.cpp
+ OS_NS_signal.cpp
+ OS_NS_stdio.cpp
+ OS_NS_stdlib.cpp
+ OS_NS_string.cpp
+ OS_NS_strings.cpp
+ OS_NS_stropts.cpp
+ OS_NS_sys_mman.cpp
+ OS_NS_sys_msg.cpp
+ OS_NS_sys_resource.cpp
+ OS_NS_sys_select.cpp
+ OS_NS_sys_sendfile.cpp
+ OS_NS_sys_shm.cpp
+ OS_NS_sys_socket.cpp
+ OS_NS_sys_stat.cpp
+ OS_NS_sys_time.cpp
+ OS_NS_sys_uio.cpp
+ OS_NS_sys_utsname.cpp
+ OS_NS_sys_wait.cpp
+ OS_NS_Thread.cpp
+ OS_NS_time.cpp
+ OS_NS_unistd.cpp
+ OS_NS_wchar.cpp
+ OS_QoS.cpp
+ OS_Thread_Adapter.cpp
+ OS_TLI.cpp
+ Parse_Node.cpp
+ Pipe.cpp
+ Process.cpp
+ Reactor.cpp
+ Reactor_Impl.cpp
+ Reactor_Notification_Strategy.cpp
+ Reactor_Timer_Interface.cpp
+ Read_Buffer.cpp
+ Recursive_Thread_Mutex.cpp
+ Refcountable.cpp
+ Rtems_init.c
+ RW_Mutex.cpp
+ RW_Thread_Mutex.cpp
+ Sched_Params.cpp
+ Select_Reactor_Base.cpp
+ Signal.cpp
+ Sig_Handler.cpp
+ Sig_Adapter.cpp
+ SOCK.cpp
+ SOCK_Acceptor.cpp
+ Sock_Connect.cpp
+ SOCK_Connector.cpp
+ SOCK_Dgram.cpp
+ SOCK_Dgram_Mcast.cpp
+ SOCK_IO.cpp
+ SOCK_Stream.cpp
+ SPIPE.cpp
+ SPIPE_Acceptor.cpp
+ SPIPE_Connector.cpp
+ SPIPE_Addr.cpp
+ SPIPE_Stream.cpp
+ SString.cpp
+ Stats.cpp // Required by orbsvcs/tests/Notify
+ String_Base_Const.cpp
+ Synch_Options.cpp
+ Task.cpp
+ Thread.cpp
+ Thread_Adapter.cpp
+ Thread_Control.cpp
+ Thread_Exit.cpp
+ Thread_Hook.cpp
+ Thread_Manager.cpp
+ Thread_Mutex.cpp
+ Throughput_Stats.cpp
+ Time_Value.cpp
+ Timeprobe.cpp
+ Token.cpp
+ TP_Reactor.cpp
+ Trace.cpp
+ TSS_Adapter.cpp
+
+ // Dev_Poll_Reactor isn't available on Windows.
+ conditional(automake,make,gnuace) {
+ Dev_Poll_Reactor.cpp
+ }
+
+ // ACE_Token implementation uses semaphores on Windows and VxWorks.
+ conditional(vc6,vc71,vc8,vc9,nmake,bmake,borland) {
+ NT_Service.cpp // Required by ace_for_tao sponsors
+ Semaphore.cpp
+ Process_Mutex.cpp
+ WFMO_Reactor.cpp
+ }
+ }
+
+ Template_Files {
+ Acceptor.cpp
+ Active_Map_Manager_T.cpp
+ Array_Base.cpp
+ Array_Map.cpp
+ Arg_Shifter.cpp
+ ARGV.cpp
+ Atomic_Op_T.cpp
+ Auto_Functor.cpp
+ Auto_IncDec_T.cpp
+ Auto_Ptr.cpp
+ Based_Pointer_T.cpp
+ Cache_Map_Manager_T.cpp
+ Cached_Connect_Strategy_T.cpp
+ Caching_Strategies_T.cpp
+ Caching_Utility_T.cpp
+ Cleanup_Strategies_T.cpp
+ Condition_T.cpp
+ Connector.cpp
+ Containers_T.cpp
+ Dump_T.cpp
+ Dynamic_Service.cpp
+ Env_Value_T.cpp
+ Event_Handler_T.cpp
+ Framework_Component_T.cpp
+ Free_List.cpp
+ Functor_T.cpp
+ Guard_T.cpp
+ Hash_Cache_Map_Manager_T.cpp
+ Hash_Map_Manager_T.cpp
+ Hash_Map_With_Allocator_T.cpp
+ IOStream_T.cpp
+ Intrusive_List.cpp
+ Intrusive_List_Node.cpp
+ Lock_Adapter_T.cpp
+ Malloc_T.cpp
+ Managed_Object.cpp
+ Map_Manager.cpp
+ Map_T.cpp
+ Message_Block_T.cpp
+ Message_Queue_T.cpp
+ Module.cpp
+ Node.cpp
+ Obstack_T.cpp
+ Pair_T.cpp
+ RB_Tree.cpp
+ Reactor_Token_T.cpp
+ Refcounted_Auto_Ptr.cpp
+ Reverse_Lock_T.cpp
+ Select_Reactor_T.cpp
+ Singleton.cpp
+ Strategies_T.cpp
+ Stream.cpp
+ Stream_Modules.cpp
+ String_Base.cpp
+ Svc_Handler.cpp
+ Synch_T.cpp
+ TSS_T.cpp
+ Task_Ex_T.cpp
+ Task_T.cpp
+ Timeprobe_T.cpp
+ Timer_Hash_T.cpp
+ Timer_Heap_T.cpp
+ Timer_List_T.cpp
+ Timer_Queue_Adapters.cpp
+ Timer_Queue_T.cpp
+ Timer_Wheel_T.cpp
+ Typed_SV_Message.cpp
+ Typed_SV_Message_Queue.cpp
+ Unbounded_Queue.cpp
+ Unbounded_Set.cpp
+ Vector_T.cpp
+ }
+
+ Inline_Files {
+ Bound_Ptr.inl
+ Condition_T.inl
+ Guard_T.inl
+ Handle_Gobbler.inl
+ Lock_Adapter_T.inl
+ OS.inl
+ OS_Memory.inl
+ OS_String.inl
+ Refcounted_Auto_Ptr.inl
+ Reverse_Lock_T.inl
+ TSS_T.inl
+ ace_wchar.inl
+ MMAP_Memory_Pool.inl
+ Mem_Map.inl
+ }
+
+ Header_Files {
+ ACE_export.h
+ Array.h
+ Based_Pointer_Repository.h
+ Bound_Ptr.h
+ CORBA_macros.h
+ Condition_T.h
+ Default_Constants.h
+ Exception_Macros.h
+ Global_Macros.h
+ Guard_T.h
+ Handle_Gobbler.h
+ If_Then_Else.h
+ IO_Cntl_Msg.h
+ Lock_Adapter_T.h
+ Log_Priority.h
+ Malloc_Base.h
+ MMAP_Memory_Pool.h
+ Memory_Pool.h
+ Mem_Map.h
+ Min_Max.h
+ Null_Barrier.h
+ Null_Condition.h
+ Null_Mutex.h
+ Null_Semaphore.h
+ Numeric_Limits.h
+ OS.h
+ OS_Dirent.h
+ OS_Memory.h
+ OS_NS_macros.h
+ OS_String.h
+ OS_Thread_Adapter.h
+ Object_Manager_Base.h
+ Pair.h
+ Reactor_Impl.h
+ Reactor_Timer_Interface.h
+ Refcounted_Auto_Ptr.h
+ Reverse_Lock_T.h
+ Select_Reactor.h
+ SStringfwd.h
+ Static_Object_Lock.h
+ Strategies.h
+ String_Base_Const.h
+ Svc_Conf.h
+ Svc_Conf_Tokens.h
+ Synch.h
+ Synch_Traits.h
+ TSS_T.h
+ Timer_Queuefwd.h
+ Truncate.h
+ Value_Ptr.h
+ Version.h
+ ace_wchar.h
+ checked_iterator.h
+ config-WinCE.h
+ config-all.h
+ config-borland-common.h
+ config-lite.h
+ config-minimal.h
+ config-win32-borland.h
+ config-win32-common.h
+ config-win32-ghs.h
+ config-win32-msvc-6.h
+ config-win32-msvc-7.h
+ config-win32-msvc.h
+ config-win32.h
+ config.h
+ iosfwd.h
+ os_include
+ os_include/arpa
+ os_include/net
+ os_include/netinet
+ os_include/sys
+ post.h
+ pre.h
+ streams.h
+ svc_export.h
+ }
+
+ Documentation_Files {
+ README
+ ../VERSION
+ }
+
+ Pkgconfig_Files {
+ ACE_FOR_TAO.pc.in
+ }
+}
diff --git a/ACE/ace/ace_foxreactor.mpc b/ACE/ace/ace_foxreactor.mpc
new file mode 100644
index 00000000000..ac11c3b70ad
--- /dev/null
+++ b/ACE/ace/ace_foxreactor.mpc
@@ -0,0 +1,32 @@
+// -*- MPC -*- now wouldn't this be cool...
+// $Id$
+
+project(ACE_FoxReactor) : acedefaults, install, acelib, ace_output, ace_fox {
+
+ sharedname = ACE_FoxReactor
+ dynamicflags = ACE_FOXREACTOR_BUILD_DLL
+
+ Source_Files {
+ FoxReactor
+ }
+
+ Header_Files {
+ FoxReactor
+ }
+
+ Inline_Files {
+ FoxReactor
+ }
+
+ Template_Files {
+ FoxReactor
+ }
+
+ Resource_Files {
+ FoxReactor
+ }
+
+ Pkgconfig_Files {
+ FoxReactor/ACE_FoxReactor.pc.in
+ }
+}
diff --git a/ACE/ace/ace_message_table.bin b/ACE/ace/ace_message_table.bin
new file mode 100644
index 00000000000..6ac08e5dc69
--- /dev/null
+++ b/ACE/ace/ace_message_table.bin
Binary files differ
diff --git a/ACE/ace/ace_qtreactor.mpc b/ACE/ace/ace_qtreactor.mpc
new file mode 100644
index 00000000000..08585347575
--- /dev/null
+++ b/ACE/ace/ace_qtreactor.mpc
@@ -0,0 +1,38 @@
+// -*- MPC -*- now wouldn't this be cool...
+// $Id$
+
+project(ACE_QtReactor) : acedefaults, install, acelib, ace_output, ace_qt {
+
+ sharedname = ACE_QtReactor
+ dynamicflags = ACE_QTREACTOR_BUILD_DLL
+
+ MOC_Files {
+ QtReactor
+ }
+
+ Source_Files {
+
+ QtReactor/QtReactor_moc.cpp
+ QtReactor
+ }
+
+ Header_Files {
+ QtReactor
+ }
+
+ Inline_Files {
+ QtReactor
+ }
+
+ Template_Files {
+ QtReactor
+ }
+
+ Resource_Files {
+ QtReactor
+ }
+
+ Pkgconfig_Files {
+ QtReactor/ACE_QtReactor.pc.in
+ }
+}
diff --git a/ACE/ace/ace_tkreactor.mpc b/ACE/ace/ace_tkreactor.mpc
new file mode 100644
index 00000000000..78fe7e79f30
--- /dev/null
+++ b/ACE/ace/ace_tkreactor.mpc
@@ -0,0 +1,32 @@
+// -*- MPC -*- now wouldn't this be cool...
+// $Id$
+
+project(ACE_TkReactor) : acedefaults, install, acelib, ace_output, ace_tk {
+
+ sharedname = ACE_TkReactor
+ dynamicflags = ACE_TKREACTOR_BUILD_DLL
+
+ Source_Files {
+ TkReactor
+ }
+
+ Header_Files {
+ TkReactor
+ }
+
+ Inline_Files {
+ TkReactor
+ }
+
+ Template_Files {
+ TkReactor
+ }
+
+ Resource_Files {
+ TkReactor
+ }
+
+ Pkgconfig_Files {
+ TkReactor/ACE_TkReactor.pc.in
+ }
+}
diff --git a/ACE/ace/ace_wchar.cpp b/ACE/ace/ace_wchar.cpp
new file mode 100644
index 00000000000..654b648a7dc
--- /dev/null
+++ b/ACE/ace/ace_wchar.cpp
@@ -0,0 +1,17 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/config-macros.h"
+#include "ace/ace_wchar.h"
+
+ACE_RCSID(ace, ace_wchar, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#if defined(ACE_HAS_ICONV)
+iconv_t ACE_Wide_To_Ascii::ACE_Wide_To_Ascii_iconv_env = 0;
+iconv_t ACE_Ascii_To_Wide::ACE_Ascii_To_Wide_iconv_env = 0;
+#endif
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/ace_wchar.h b/ACE/ace/ace_wchar.h
new file mode 100644
index 00000000000..2f5f2df5e68
--- /dev/null
+++ b/ACE/ace/ace_wchar.h
@@ -0,0 +1,377 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file ace_wchar.h
+ *
+ * $Id$
+ *
+ * @author Darrell Brunsch <brunsch@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_WCHAR_H
+#define ACE_WCHAR_H
+
+#include "ace/config-macros.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// These macros have been deprecated and should be replaced by their
+// ACE_TEXT_* equivalents. These macros are just hacks and may not
+// completely provide the old functionality.
+#if defined (ACE_LEGACY_MODE)
+// Convert the old unicode indicators
+# if defined (ACE_HAS_MOSTLY_UNICODE_APIS)
+# define ACE_USES_WCHAR
+# endif /* ACE_HAS_MOSTLY_UNICODE_APIS */
+# if defined (ACE_HAS_UNICODE)
+# define ACE_HAS_WCHAR
+# endif /* ACE_HAS_UNICODE */
+
+// These are defined to get older stuff to compile
+// FUZZ: disable check_for_tchar
+# define ASYS_TCHAR ACE_TCHAR
+# define ASYS_TEXT ACE_TEXT
+# define ASYS_ONLY_MULTIBYTE_STRING ACE_TEXT_ALWAYS_CHAR
+# define ASYS_MULTIBYTE_STRING ACE_TEXT_CHAR_TO_TCHAR
+# define ASYS_WIDE_STRING ACE_TEXT_CHAR_TO_TCHAR
+# define ACE_WIDE_STRING ACE_TEXT_CHAR_TO_TCHAR
+
+# if defined (ACE_USES_WCHAR)
+# define ASYS_ONLY_WIDE_STRING(STRING) STRING
+# else /* ACE_USES_WCHAR */
+# define ASYS_ONLY_WIDE_STRING(STRING) \
+ ACE_Ascii_To_Wide (STRING).wchar_rep ()
+# endif /* ACE_USES_WCHAR */
+
+# define ACE_TEXT_STRING ACE_TString
+
+#endif /* ACE_LEGACY_MODE */
+
+#if defined (ACE_HAS_XPG4_MULTIBYTE_CHAR)
+# if !defined (ACE_HAS_WCHAR)
+# define ACE_HAS_WCHAR
+# endif
+# include /**/ <wchar.h>
+#endif /* ACE_HAS_XPG4_MULTIBYTE_CHAR */
+
+#if defined (ACE_HAS_WCHAR)
+# if defined (ACE_VXWORKS)
+# include /**/ <types/vxTypes.h> /* For wchar_t */
+# include /**/ <stdlib.h> /* For mbstowcs, etc. */
+# include /**/ <string.h> /* For strlen */
+# if !defined (__RTP__)
+# define wint_t unsigned int /* VxWorks has wchar_t but not wint_t */
+# else
+# include /**/ <wchar.h>
+# include /**/ <wctype.h>
+# endif
+# elif defined (ACE_OPENVMS)
+# include /**/ <wchar.h>
+# include /**/ <wctype.h>
+# elif defined (ACE_HAS_STANDARD_CPP_LIBRARY) && \
+ (ACE_HAS_STANDARD_CPP_LIBRARY != 0)
+# include /**/ <cwchar>
+# include /**/ <cwctype>
+# elif defined (ACE_HAS_WINCE)
+# include /**/ <wtypes.h>
+# elif !defined (__BORLANDC__)
+# include /**/ <wchar.h>
+# endif /* ACE_HAS_STANDARD_CPP_LIBRARY */
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_HAS_ICONV)
+# include /**/ <iconv.h>
+# if !defined (ACE_MAX_ICONV_BUFFER)
+# define ACE_MAX_ICONV_BUFFER 16*1024
+# endif
+#endif /* ACE_HAS_ICONV */
+
+#if defined (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB) && \
+ (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB != 0)
+using std::size_t;
+#endif /* ACE_USES_STD_NAMESPACE_FOR_STDC_LIB */
+
+// This makes the somewhat dubious assumption that if a platform lacks
+// a native wchar_t type, then it will typedef it as unsigned short.
+#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_NATIVE_WCHAR_T)
+# if !defined (ACE_WSTRING_HAS_USHORT_SUPPORT)
+# define ACE_WSTRING_HAS_USHORT_SUPPORT
+# endif /* ACE_WSTRING_HAS_USHORT_SUPPORT */
+#endif /* ACE_HAS_WCHAR && !ACE_LACKS_NATIVE_WCHAR_T */
+
+// Set the default behaviour for ACE_TEXT_WIDE to use the L-prefix
+#if !defined (ACE_USES_L_PREFIX)
+# define ACE_USES_L_PREFIX 1
+#endif /* ACE_USES_L_PREFIX */
+
+// Define the unicode/wchar related macros correctly
+
+# if !defined (ACE_TEXT_WIDE)
+# if (ACE_USES_L_PREFIX == 1)
+# define ACE_TEXT_WIDE_I(STRING) L##STRING
+# else /* ACE_USES_L_PREFIX */
+# define ACE_TEXT_WIDE_I(STRING) STRING
+# endif /* ACE_USES_L_PREFIX */
+# define ACE_TEXT_WIDE(STRING) ACE_TEXT_WIDE_I (STRING)
+# endif /* ACE_TEXT_WIDE */
+
+#if defined (ACE_USES_WCHAR)
+typedef wchar_t ACE_TCHAR;
+typedef char ACE_ANTI_TCHAR;
+# define ACE_TEXT(STRING) ACE_TEXT_WIDE (STRING)
+# if !defined (ACE_LACKS_DEPRECATED_MACROS)
+# define ACE_LIB_TEXT(STRING) ACE_TEXT_WIDE (STRING)
+# endif
+# define ACE_TEXT_ALWAYS_CHAR(STRING) ACE_Wide_To_Ascii (STRING).char_rep ()
+# define ACE_TEXT_ALWAYS_WCHAR(STRING) STRING
+# define ACE_TEXT_CHAR_TO_TCHAR(STRING) ACE_Ascii_To_Wide (STRING).wchar_rep ()
+# define ACE_TEXT_WCHAR_TO_TCHAR(STRING) STRING
+# define ACE_TEXT_ANTI_TO_TCHAR(STRING) ACE_Ascii_To_Wide (STRING).wchar_rep ()
+#else /* ACE_USES_WCHAR */
+typedef char ACE_TCHAR;
+typedef wchar_t ACE_ANTI_TCHAR;
+# define ACE_TEXT(STRING) STRING
+# if !defined (ACE_LACKS_DEPRECATED_MACROS)
+# define ACE_LIB_TEXT(STRING) STRING
+# endif
+# define ACE_TEXT_ALWAYS_CHAR(STRING) STRING
+# define ACE_TEXT_ALWAYS_WCHAR(STRING) ACE_Ascii_To_Wide (STRING).wchar_rep ()
+# define ACE_TEXT_CHAR_TO_TCHAR(STRING) STRING
+# define ACE_TEXT_WCHAR_TO_TCHAR(STRING) ACE_Wide_To_Ascii (STRING).char_rep ()
+# define ACE_TEXT_ANTI_TO_TCHAR(STRING) ACE_Wide_To_Ascii (STRING).char_rep ()
+#endif /* ACE_USES_WCHAR */
+
+// The OS_String module defines some wide-char functions that are not
+// universally available. In particular, they're not part of the
+// XPG4 Worldwide Portability Interface wide-character string handling
+// functions. So, if ACE_HAS_XPG4_MULTIBYTE_CHAR is defined, note that
+// these functions are missing.
+#if defined (ACE_HAS_XPG4_MULTIBYTE_CHAR)
+
+# if !defined (ACE_LACKS_ITOW)
+# define ACE_LACKS_ITOW
+# endif
+
+# if !defined (ACE_LACKS_WCSICMP)
+# define ACE_LACKS_WCSICMP
+# endif
+
+# if !defined (ACE_LACKS_WCSNICMP)
+# define ACE_LACKS_WCSNICMP
+# endif
+
+# if !defined (ACE_LACKS_WCSDUP)
+# define ACE_LACKS_WCSDUP
+# endif
+
+#endif /* ACE_HAS_XPG4_MULTIBYTE_CHAR */
+
+#if defined ACE_HAS_WCHAR
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Wide_To_Ascii
+ *
+ * @brief A lightweight wchar* to char* string conversion class.
+ *
+ * The purpose of this class is to perform conversion from
+ * wchar* to char* strings. It is not intended for general
+ * purpose use.
+ */
+class ACE_Wide_To_Ascii
+{
+public:
+ /// Ctor must take a wchar string.
+ ACE_Wide_To_Ascii (const wchar_t *s);
+
+ /// Dtor will free up the memory.
+ ~ACE_Wide_To_Ascii (void);
+
+ /// Return the internal char* representation.
+ char *char_rep (void);
+
+ /// Converts an wchar_t string to ascii and returns a new string.
+ static char *convert (const wchar_t *wstr);
+
+private:
+ /// Internal pointer to the converted string.
+ char *s_;
+
+#if defined (ACE_HAS_ICONV)
+ static iconv_t ACE_Wide_To_Ascii_iconv_env;
+#endif /* ACE_HAS_ICONV */
+
+ /// Disallow these operation.
+ ACE_Wide_To_Ascii (void);
+ ACE_Wide_To_Ascii (ACE_Wide_To_Ascii &);
+ ACE_Wide_To_Ascii& operator= (ACE_Wide_To_Ascii &);
+};
+
+/**
+ * @class ACE_Ascii_To_Wide
+ *
+ * @brief A lightweight char* to wchar* string conversion class.
+ *
+ * The purpose of this class is to perform conversion from
+ * char* to wchar* strings. It is not intended for general
+ * purpose use.
+ */
+class ACE_Ascii_To_Wide
+{
+public:
+ /// Ctor must take a wchar string.
+ ACE_Ascii_To_Wide (const char *s);
+
+ /// Dtor will free up the memory.
+ ~ACE_Ascii_To_Wide (void);
+
+ /// Return the internal wchar* representation.
+ wchar_t *wchar_rep (void);
+
+ /// Converts an char string to unicode/wide and returns a new string.
+ static wchar_t *convert (const char *str);
+
+private:
+ /// Internal pointer to the converted string.
+ wchar_t *s_;
+
+#if defined (ACE_HAS_ICONV)
+ static iconv_t ACE_Ascii_To_Wide_iconv_env;
+#endif /* ACE_HAS_ICONV */
+
+ /// Disallow these operation.
+ ACE_Ascii_To_Wide (void);
+ ACE_Ascii_To_Wide (ACE_Ascii_To_Wide &);
+ ACE_Ascii_To_Wide operator= (ACE_Ascii_To_Wide &);
+};
+
+#if defined (ACE_LEGACY_MODE)
+typedef ACE_Ascii_To_Wide ACE_OS_CString;
+typedef ACE_Wide_To_Ascii ACE_OS_WString;
+#endif /* ACE_LEGACY_MODE */
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WCHAR */
+
+#if defined (ACE_WIN32)
+#if defined (ACE_USES_WCHAR)
+#define ACE_TEXT_SERVICE_TABLE_ENTRY SERVICE_TABLE_ENTRYW
+#define ACE_TEXT_STARTUPINFO STARTUPINFOW
+#define ACE_TEXT_WIN32_FIND_DATA WIN32_FIND_DATAW
+#define ACE_TEXT_OSVERSIONINFO OSVERSIONINFOW
+#define ACE_TEXT_EXPLICIT_ACCESS EXPLICIT_ACCESS_W
+
+#define ACE_TEXT_CreateEvent ::CreateEventW
+#define ACE_TEXT_CreateFile ::CreateFileW
+#define ACE_TEXT_CreateFileMapping ::CreateFileMappingW
+#define ACE_TEXT_CreateMutex ::CreateMutexW
+#define ACE_TEXT_CreateProcess ::CreateProcessW
+#define ACE_TEXT_CreateSemaphore ::CreateSemaphoreW
+#define ACE_TEXT_CreateService ::CreateServiceW
+#define ACE_TEXT_ExpandEnvironmentStrings ::ExpandEnvironmentStringsW
+#define ACE_TEXT_FindFirstChangeNotification ::FindFirstChangeNotificationW
+#define ACE_TEXT_FindFirstFile ::FindFirstFileW
+#define ACE_TEXT_FindNextFile ::FindNextFileW
+#define ACE_TEXT_FormatMessage ::FormatMessageW
+#define ACE_TEXT_FreeEnvironmentStrings ::FreeEnvironmentStringsW
+#define ACE_TEXT_GetComputerName ::GetComputerNameW
+#define ACE_TEXT_GetEnvironmentStrings ::GetEnvironmentStringsW
+#define ACE_TEXT_GetFileAttributes ::GetFileAttributesW
+#define ACE_TEXT_GetModuleFileName ::GetModuleFileNameW
+#define ACE_TEXT_GetTempPath ::GetTempPathW
+#define ACE_TEXT_GetUserName ::GetUserNameW
+#define ACE_TEXT_GetUserNameEx ::GetUserNameExW
+#define ACE_TEXT_GetVersionEx ::GetVersionExW
+#define ACE_TEXT_LoadLibrary ::LoadLibraryW
+#define ACE_TEXT_MoveFileEx ::MoveFileExW
+#define ACE_TEXT_WaitNamedPipe ::WaitNamedPipeW
+#define ACE_TEXT_OpenFileMapping ::OpenFileMappingW
+#define ACE_TEXT_OpenSCManager ::OpenSCManagerW
+#define ACE_TEXT_OpenService ::OpenServiceW
+#define ACE_TEXT_OutputDebugString ::OutputDebugStringW
+#define ACE_TEXT_RegisterEventSource ::RegisterEventSourceW
+#define ACE_TEXT_RegisterServiceCtrlHandler ::RegisterServiceCtrlHandlerW
+#define ACE_TEXT_RegConnectRegistry ::RegConnectRegistryW
+#define ACE_TEXT_RegCreateKeyEx ::RegCreateKeyExW
+#define ACE_TEXT_RegDeleteKey ::RegDeleteKeyW
+#define ACE_TEXT_RegDeleteValue ::RegDeleteValueW
+#define ACE_TEXT_RegEnumKeyEx ::RegEnumKeyExW
+#define ACE_TEXT_RegEnumValue ::RegEnumValueW
+#define ACE_TEXT_RegCreateKey ::RegCreateKeyW
+#define ACE_TEXT_RegOpenKey ::RegOpenKeyW
+#define ACE_TEXT_RegOpenKeyEx ::RegOpenKeyExW
+#define ACE_TEXT_RegQueryValueEx ::RegQueryValueExW
+#define ACE_TEXT_RegSetValueEx ::RegSetValueExW
+#define ACE_TEXT_ReportEvent ::ReportEventW
+#define ACE_TEXT_SearchPath ::SearchPathW
+#define ACE_TEXT_StartService ::StartServiceW
+#define ACE_TEXT_StartServiceCtrlDispatcher ::StartServiceCtrlDispatcherW
+#define ACE_TEXT_SetFileSecurity ::SetFileSecurityW
+#define ACE_TEXT_SetEntriesInAcl ::SetEntriesInAclW
+
+#else /* ACE_USES_WCHAR */
+#define ACE_TEXT_SERVICE_TABLE_ENTRY SERVICE_TABLE_ENTRYA
+#define ACE_TEXT_STARTUPINFO STARTUPINFOA
+#define ACE_TEXT_WIN32_FIND_DATA WIN32_FIND_DATAA
+#define ACE_TEXT_OSVERSIONINFO OSVERSIONINFOA
+#define ACE_TEXT_EXPLICIT_ACCESS EXPLICIT_ACCESS_A
+
+#define ACE_TEXT_CreateEvent ::CreateEventA
+#define ACE_TEXT_CreateFile ::CreateFileA
+#define ACE_TEXT_CreateFileMapping ::CreateFileMappingA
+#define ACE_TEXT_CreateMutex ::CreateMutexA
+#define ACE_TEXT_CreateProcess ::CreateProcessA
+#define ACE_TEXT_CreateSemaphore ::CreateSemaphoreA
+#define ACE_TEXT_CreateService ::CreateServiceA
+#define ACE_TEXT_ExpandEnvironmentStrings ::ExpandEnvironmentStringsA
+#define ACE_TEXT_FindFirstChangeNotification ::FindFirstChangeNotificationA
+#define ACE_TEXT_FindFirstFile ::FindFirstFileA
+#define ACE_TEXT_FindNextFile ::FindNextFileA
+#define ACE_TEXT_FormatMessage ::FormatMessageA
+#define ACE_TEXT_FreeEnvironmentStrings ::FreeEnvironmentStringsA
+#define ACE_TEXT_GetComputerName ::GetComputerNameA
+#define ACE_TEXT_GetEnvironmentStrings ::GetEnvironmentStringsA
+#define ACE_TEXT_GetFileAttributes ::GetFileAttributesA
+#define ACE_TEXT_GetModuleFileName ::GetModuleFileNameA
+#define ACE_TEXT_GetTempPath ::GetTempPathA
+#define ACE_TEXT_GetUserName ::GetUserNameA
+#define ACE_TEXT_GetUserNameEx ::GetUserNameExA
+#define ACE_TEXT_GetVersionEx ::GetVersionExA
+#define ACE_TEXT_LoadLibrary ::LoadLibraryA
+#define ACE_TEXT_MoveFileEx ::MoveFileExA
+#define ACE_TEXT_WaitNamedPipe ::WaitNamedPipeA
+#define ACE_TEXT_OpenFileMapping ::OpenFileMappingA
+#define ACE_TEXT_OpenSCManager ::OpenSCManagerA
+#define ACE_TEXT_OpenService ::OpenServiceA
+#define ACE_TEXT_OutputDebugString ::OutputDebugStringA
+#define ACE_TEXT_RegisterEventSource ::RegisterEventSourceA
+#define ACE_TEXT_RegisterServiceCtrlHandler ::RegisterServiceCtrlHandlerA
+#define ACE_TEXT_RegConnectRegistry ::RegConnectRegistryA
+#define ACE_TEXT_RegCreateKeyEx ::RegCreateKeyExA
+#define ACE_TEXT_RegDeleteKey ::RegDeleteKeyA
+#define ACE_TEXT_RegDeleteValue ::RegDeleteValueA
+#define ACE_TEXT_RegEnumKeyEx ::RegEnumKeyExA
+#define ACE_TEXT_RegEnumValue ::RegEnumValueA
+#define ACE_TEXT_RegCreateKey ::RegCreateKeyA
+#define ACE_TEXT_RegOpenKey ::RegOpenKeyA
+#define ACE_TEXT_RegOpenKeyEx ::RegOpenKeyExA
+#define ACE_TEXT_RegQueryValueEx ::RegQueryValueExA
+#define ACE_TEXT_RegSetValueEx ::RegSetValueExA
+#define ACE_TEXT_ReportEvent ::ReportEventA
+#define ACE_TEXT_SearchPath ::SearchPathA
+#define ACE_TEXT_StartService ::StartServiceA
+#define ACE_TEXT_StartServiceCtrlDispatcher ::StartServiceCtrlDispatcherA
+#define ACE_TEXT_SetFileSecurity ::SetFileSecurityA
+#define ACE_TEXT_SetEntriesInAcl ::SetEntriesInAclA
+#endif /* ACE_USES_WCHAR */
+#endif /* ACE_WIN32 */
+
+#include "ace/ace_wchar.inl"
+
+#endif /* ACE_WCHAR_H */
diff --git a/ACE/ace/ace_wchar.inl b/ACE/ace/ace_wchar.inl
new file mode 100644
index 00000000000..86182f9ec0e
--- /dev/null
+++ b/ACE/ace/ace_wchar.inl
@@ -0,0 +1,183 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// These are always inlined
+// FUZZ: disable check_for_inline
+
+#if defined (ACE_HAS_WCHAR)
+
+#if !defined (ACE_WIN32)
+# include /**/ <string.h> // Need to see strlen()
+#endif /* ACE_WIN32 */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+inline
+ACE_Wide_To_Ascii::~ACE_Wide_To_Ascii (void)
+{
+ delete [] this->s_;
+}
+
+inline char *
+ACE_Wide_To_Ascii::char_rep (void)
+{
+ return this->s_;
+}
+
+inline char *
+ACE_Wide_To_Ascii::convert (const wchar_t *wstr)
+{
+ // Short circuit null pointer case
+ if (wstr == 0)
+ return 0;
+
+# if defined (ACE_WIN32)
+ UINT const cp = GetACP (); // Codepage
+ int const len = ::WideCharToMultiByte (cp,
+ 0,
+ wstr,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0);
+# elif defined (ACE_LACKS_WCSLEN)
+ const wchar_t * wtemp = wstr;
+ while ((*wtemp) != 0) // Hopefully the string is null terminated!
+ ++wtemp;
+
+ int const len = wtemp - wstr + 1;
+# else /* ACE_WIN32 */
+ size_t const len = ::wcslen (wstr) + 1;
+# endif /* ACE_WIN32 */
+
+#if !defined (ACE_HAS_ICONV)
+ char *str = new char[len];
+#endif
+
+# if defined (ACE_WIN32)
+ ::WideCharToMultiByte (cp, 0, wstr, -1, str, len, 0, 0);
+# elif defined (ACE_VXWORKS)
+ ::wcstombs (str, wstr, len);
+# elif defined (ACE_HAS_ICONV)
+ wchar_t * wstri = const_cast<wchar_t*> (wstr);
+ size_t lensi = ACE_MAX_ICONV_BUFFER;
+ size_t lenwi = len * sizeof(wchar_t);
+ char buf[ACE_MAX_ICONV_BUFFER];
+ char *stri = buf;
+
+ size_t hr = iconv (ACE_Wide_To_Ascii_iconv_env, (char**)&wstri, &lenwi, &stri, &lensi);
+ if ((hr==size_t(-1))||(lensi==ACE_MAX_ICONV_BUFFER))
+ {
+ char *str=new char[len];
+ for (size_t i = 0; i < len; i++)
+ {
+ wchar_t *t = const_cast <wchar_t *> (wstr);
+ str[i] = static_cast<char> (*(t + i));
+ }
+
+ return str;
+ }
+ char *str = new char[ACE_MAX_ICONV_BUFFER-lensi];
+ ::memcpy(str, buf, ACE_MAX_ICONV_BUFFER-lensi);
+# else /* ACE_HAS_ICONV */
+ for (size_t i = 0; i < len; ++i)
+ {
+ wchar_t *t = const_cast <wchar_t *> (wstr);
+ str[i] = static_cast<char> (*(t + i));
+ }
+# endif /* ACE_WIN32 */
+ return str;
+}
+
+inline
+ACE_Wide_To_Ascii::ACE_Wide_To_Ascii (const wchar_t *s)
+{
+#if defined(ACE_HAS_ICONV)
+ if (ACE_Wide_To_Ascii_iconv_env == 0)
+ {
+ ACE_Wide_To_Ascii_iconv_env = iconv_open("", "WCHAR_T");
+ }
+#endif
+ s_ = ACE_Wide_To_Ascii::convert (s);
+}
+
+inline
+ACE_Ascii_To_Wide::~ACE_Ascii_To_Wide (void)
+{
+ delete [] this->s_;
+}
+
+inline wchar_t *
+ACE_Ascii_To_Wide::wchar_rep (void)
+{
+ return this->s_;
+}
+
+inline wchar_t *
+ACE_Ascii_To_Wide::convert (const char *str)
+{
+ // Short circuit null pointer case
+ if (str == 0)
+ return 0;
+
+# if defined (ACE_WIN32)
+ UINT const cp = GetACP (); // Codepage
+ int const len = ::MultiByteToWideChar (cp, 0, str, -1, 0, 0);
+# else /* ACE_WIN32 */
+ size_t const len = strlen (str) + 1;
+# endif /* ACE_WIN32 */
+
+#if !defined (ACE_HAS_ICONV)
+ wchar_t *wstr = new wchar_t[len];
+#endif
+
+# if defined (ACE_WIN32)
+ ::MultiByteToWideChar (cp, 0, str, -1, wstr, len);
+# elif defined (ACE_VXWORKS)
+ ::mbstowcs (wstr, str, len);
+# elif defined (ACE_HAS_ICONV) /* ACE_VXWORKS */
+ char *stri = const_cast<char*>(str);
+ size_t lensi = len;
+ size_t lenwi = ACE_MAX_ICONV_BUFFER;
+ wchar_t buf[ACE_MAX_ICONV_BUFFER/sizeof(wchar_t)];
+ wchar_t *wstri=buf;
+
+ size_t hr=iconv(ACE_Ascii_To_Wide_iconv_env, &stri, &lensi, (char**)&wstri, &lenwi);
+ if((hr==size_t(-1))||(lenwi==ACE_MAX_ICONV_BUFFER)){
+ wchar_t *wstr=new wchar_t[len*sizeof(wchar_t)];
+ for (size_t i = 0; i < len; i++){
+ char *t = const_cast<char *> (str);
+ wstr[i] = static_cast<wchar_t> (*((unsigned char*)t + i));
+ }
+
+ return wstr;
+ }
+ wchar_t *wstr=new wchar_t[(ACE_MAX_ICONV_BUFFER-lenwi)/sizeof(wchar_t)];
+ ::memcpy(wstr,buf,ACE_MAX_ICONV_BUFFER-lenwi);
+# else /* ACE_HAS_ICONV */
+ for (size_t i = 0; i < len; ++i)
+ {
+ char *t = const_cast<char *> (str);
+ wstr[i] = static_cast<wchar_t> (*((unsigned char*)(t + i)));
+ }
+# endif /* ACE_WIN32 */
+ return wstr;
+}
+
+inline
+ACE_Ascii_To_Wide::ACE_Ascii_To_Wide (const char *s)
+{
+#if defined(ACE_HAS_ICONV)
+ if (ACE_Ascii_To_Wide_iconv_env == 0)
+ {
+ ACE_Ascii_To_Wide_iconv_env = iconv_open("WCHAR_T", "");
+ }
+#endif
+ s_ = ACE_Ascii_To_Wide::convert (s);
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_HAS_WCHAR */
diff --git a/ACE/ace/ace_xtreactor.mpc b/ACE/ace/ace_xtreactor.mpc
new file mode 100644
index 00000000000..0e2f3185883
--- /dev/null
+++ b/ACE/ace/ace_xtreactor.mpc
@@ -0,0 +1,32 @@
+// -*- MPC -*- now wouldn't this be cool...
+// $Id$
+
+project(ACE_XtReactor) : acedefaults, install, acelib, ace_output, ace_xt {
+
+ sharedname = ACE_XtReactor
+ dynamicflags = ACE_XTREACTOR_BUILD_DLL
+
+ Source_Files {
+ XtReactor
+ }
+
+ Header_Files {
+ XtReactor
+ }
+
+ Inline_Files {
+ XtReactor
+ }
+
+ Template_Files {
+ XtReactor
+ }
+
+ Resource_Files {
+ XtReactor
+ }
+
+ Pkgconfig_Files {
+ XtReactor/ACE_XtReactor.pc.in
+ }
+}
diff --git a/ACE/ace/checked_iterator.h b/ACE/ace/checked_iterator.h
new file mode 100644
index 00000000000..ac5e44f6dfc
--- /dev/null
+++ b/ACE/ace/checked_iterator.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+
+#ifndef ACE_CHECKED_ITERATOR_H
+#define ACE_CHECKED_ITERATOR_H
+
+/**
+ * @file checked_iterator.h
+ *
+ * @brief Checked iterator factory function.
+ *
+ * Some compilers (e.g. MSVC++ >= 8) issue security related
+ * diagnostics if algorithms such as std::copy() are used in an unsafe
+ * way. Normally this isn't an issue if STL container iterators are
+ * used in conjuction with the standard algorithms. However, in cases
+ * where application-specific iterators are use with standard
+ * algorithms that could potentially overrun a buffer, extra care must
+ * be taken to prevent such an overrun. If supported, checked
+ * iterators can be used to address the potential destination buffer
+ * overrun.
+ *
+ * This header provides function templates that generate the
+ * appropriate checked iterator. In cases where checked iterators are
+ * not supported, the pointer passed to the function is returned
+ * instead.
+ *
+ * $Id$
+ *
+ * @internal The functions and types in this header are meant for
+ * internal use. They may change at any point between
+ * releases.
+ *
+ * @author Ossama Othman
+ */
+
+# if defined (_MSC_VER) && (_MSC_FULL_VER >= 140050000)
+// Checked iterators are currently only supported in MSVC++ 8 or better.
+# include <iterator>
+# endif /* _MSC_VER >= 1400 */
+
+# if defined (_MSC_VER) && (_MSC_FULL_VER >= 140050000)
+template <typename PTR>
+stdext::checked_array_iterator<PTR>
+ACE_make_checked_array_iterator (PTR buf, size_t len)
+{
+ return stdext::checked_array_iterator<PTR> (buf, len);
+}
+# else
+template <typename PTR>
+PTR
+ACE_make_checked_array_iterator (PTR buf, size_t /* len */)
+{
+ // Checked iterators are unsupported. Just return the pointer to
+ // the buffer itself.
+ return buf;
+}
+# endif /* _MSC_VER >= 1400 */
+
+#endif /* ACE_CHECKED_ITERATOR_H */
diff --git a/ACE/ace/codecs.mpb b/ACE/ace/codecs.mpb
new file mode 100644
index 00000000000..d8c85fffddb
--- /dev/null
+++ b/ACE/ace/codecs.mpb
@@ -0,0 +1,8 @@
+// -*- MPC -*-
+// $Id$
+
+feature(ace_codecs) {
+ Source_Files(ACE_COMPONENTS) {
+ Codecs.cpp
+ }
+}
diff --git a/ACE/ace/config-WinCE.h b/ACE/ace/config-WinCE.h
new file mode 100644
index 00000000000..e46c9931cdc
--- /dev/null
+++ b/ACE/ace/config-WinCE.h
@@ -0,0 +1,238 @@
+// $Id$
+
+// Note: For WinCE build, simply use: #include "ace/config-win32.h"
+// It is same as config.h for Windows NT/2k so that you can
+// share same files and directories for both WinCE and NT/2k
+// builds, unless you add additional definition(s) for each
+// specific build or change the output directory.
+
+#ifndef ACE_CONFIG_WINCE_H
+#define ACE_CONFIG_WINCE_H
+
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+# error Use config-win32.h in config.h instead of this header
+#endif // ACE_CONFIG_WIN32_H
+
+#if !defined (UNDER_CE)
+# error Define UNDER_CE to version (i.e. 300 = 3.0)
+#endif // UNDER_CE
+
+#if (UNDER_CE < 300)
+# error ACE requires Windows CE 3.0 and later.
+#endif // UNDER_CE
+
+#if (UNDER_CE < 400)
+// CE 3 doesn't have Winsock 2, but CE 4 does.
+# if !defined (ACE_HAS_WINSOCK2)
+# define ACE_HAS_WINSOCK2 0
+# endif
+# define ACE_LACKS_ASSERT_H
+# define ACE_LACKS_SEARCH_H
+# define ACE_LACKS_WCHAR_H
+# define ACE_LACKS_WCTYPE_H
+# define ACE_LACKS_STDDEF_H
+# define ACE_LACKS_PTRDIFF_T
+#endif /* UNDER_CE < 400 */
+
+#if !defined (ACE_HAS_WINCE)
+# define ACE_HAS_WINCE 1
+#endif
+
+#if defined (_MSC_VER) && (_MSC_VER < 1400)
+// WinCE prior to Visual Studio 2005 integration doesn't have most of
+// the standard C library time functions. It also doesn't define struct tm.
+// SYSTEMTIME has pretty much the same info though, so we can map it when
+// needed. Define struct tm here and use it when needed. This is taken
+// from the standard C library.
+# define ACE_LACKS_STRUCT_TM
+#endif
+
+// We need these libraries to build:
+#pragma comment(lib,"corelibc.lib")
+#pragma comment(linker, "/nodefaultlib:oldnames.lib")
+
+// Only DLL version is supported on CE.
+//#if defined (ACE_HAS_DLL)
+//# undef ACE_HAS_DLL
+//#endif // ACE_HAS_DLL
+//#define ACE_HAS_DLL 1
+
+// Need to define LD search path explicitly on CE because
+// CE doesn't have environment variables and we can't get
+// the information using getenv.
+#define ACE_DEFAULT_LD_SEARCH_PATH ACE_TEXT (".\\;\\windows")
+
+#define ACE_LACKS_FCNTL_H
+#define ACE_LACKS_SYS_TYPES_H
+#define ACE_LACKS_GETCWD
+#define ACE_LACKS_ASCTIME
+#define ACE_LACKS_ASCTIME_R
+#define ACE_LACKS_GMTIME
+#define ACE_LACKS_GMTIME_R
+#define ACE_LACKS_LOCALTIME
+#define ACE_LACKS_PERROR
+#define ACE_LACKS_STRFTIME
+#define ACE_LACKS_WIN32_SETFILEPOINTEREX
+#define ACE_LACKS_WIN32_SERVICES
+#define ACE_LACKS_WIN32_SECURITY_DESCRIPTORS
+#define ACE_LACKS_GETPROCESSTIMES
+
+#define ACE_HAS_POSITION_INDEPENDENT_POINTERS 1
+
+#define ACE_LACKS_MSG_WFMO
+#define ACE_LACKS_UMASK
+
+// WinCE only supports the UNICODE API
+#if !defined (ACE_USES_WCHAR)
+# define ACE_USES_WCHAR
+#endif /* ACE_USES_WCHAR */
+
+#define ACE_USES_WINCE_SEMA_SIMULATION
+
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER 1
+
+// FILE stuff isn't always defined in CE
+#if (_MSC_VER < 1400) && !defined (_FILE_DEFINED)
+ typedef void FILE;
+# define _FILE_DEFINED
+#endif /* _MSC_VER < 1400 && !_FILE_DEFINED */
+
+// This was defined in previous versions of CE, but not 2.11
+#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION
+
+#define ACE_MAIN WINAPI WinMain
+
+// SH3 cross-compiler can't handle inline functions correctly
+// (along with other bugs.)
+#if defined (SH3)
+# define ACE_LACKS_INLINE_FUNCTIONS
+#endif // SH3 && _DEBUG
+
+#ifndef ACE_DEFAULT_SERVER_HOST
+# define ACE_DEFAULT_SERVER_HOST ACE_TEXT("localhost")
+#endif // ACE_DEFAULT_SERVER_HOST
+
+// @@ Need to remap every function that uses any of these flags to
+// Win32 API. These are for ANSI styled function and are not
+// available on WinCE.
+
+#define _O_RDONLY 0x0000 // open for reading only
+#define _O_WRONLY 0x0001 // open for writing only
+#define _O_RDWR 0x0002 // open for reading and writing
+#define _O_APPEND 0x0008 // writes done at eof
+
+#define _O_CREAT 0x0100 // create and open file
+#define _O_TRUNC 0x0200 // open and truncate
+#define _O_EXCL 0x0400 // open only if file doesn't already exist
+
+// O_TEXT files have <cr><lf> sequences translated to <lf> on read()'s,
+// and <lf> sequences translated to <cr><lf> on write()'s
+#define _O_TEXT 0x4000 // file mode is text (translated)
+#define _O_BINARY 0x8000 // file mode is binary (untranslated)
+
+// macro to translate the C 2.0 name used to force binary mode for files
+//#define _O_RAW _O_BINARY
+
+// Open handle inherit bit
+//#define _O_NOINHERIT 0x0080 // child process doesn't inherit file
+
+// Temporary file bit - file is deleted when last handle is closed
+#define _O_TEMPORARY 0x0040 // temporary file bit
+
+// temporary access hint
+//#define _O_SHORT_LIVED 0x1000 // temporary storage file, try not to flush
+
+// sequential/random access hints
+//#define _O_SEQUENTIAL 0x0020 // file access is primarily sequential
+//#define _O_RANDOM 0x0010 // file access is primarily random
+
+
+// Non-ANSI names
+#define O_RDONLY _O_RDONLY
+#define O_WRONLY _O_WRONLY
+#define O_RDWR _O_RDWR
+#define O_APPEND _O_APPEND
+#define O_CREAT _O_CREAT
+#define O_TRUNC _O_TRUNC
+#define O_EXCL _O_EXCL
+#define O_TEXT _O_TEXT
+#define O_BINARY _O_BINARY
+#define O_TEMPORARY _O_TEMPORARY
+//#define O_RAW _O_BINARY
+//#define O_NOINHERIT _O_NOINHERIT
+//#define O_SEQUENTIAL _O_SEQUENTIAL
+//#define O_RANDOM _O_RANDOM
+
+
+// @@ NSIG value. This is definitely not correct.
+#define NSIG 23
+
+
+// @@ For some reason, WinCE forgot to define this.
+// Need to find out what it is. (Used in MapViewOfFile ().)
+#define FILE_MAP_COPY 0
+
+
+#define ACE_LACKS_STRCASECMP // WinCE doesn't support _stricmp
+#define ACE_LACKS_GETSERVBYNAME
+#define ACE_LACKS_ACCESS
+#define ACE_LACKS_FILELOCKS
+#define ACE_LACKS_EXEC
+#define ACE_LACKS_MKTEMP
+#define ACE_LACKS_STRRCHR
+#define ACE_LACKS_BSEARCH
+#define ACE_LACKS_SOCKET_BUFSIZ
+#define ACE_LACKS_ISATTY
+#define ACE_LACKS_STRERROR
+#define ACE_LACKS_SYSTEM
+#define ACE_LACKS_SIGACTION
+#define ACE_LACKS_PIPE
+
+//#define ACE_LACKS_CUSERID
+//#define ACE_LACKS_CHDIR
+#define ACE_LACKS_ENV
+#define ACE_LACKS_HOSTNAME
+#define ACE_LACKS_REALPATH
+#define ACE_LACKS_READLINK
+#define ACE_LACKS_SWAB
+#define ACE_LACKS_TEMPNAM
+#define ACE_LACKS_GETPROTOBYNUMBER
+#define ACE_LACKS_GETPROTOBYNAME
+
+#if defined (_WIN32_WCE_EMULATION)
+// @@ For some reason, qsort isn't defined correctly (_stdcall vs _cdecl)
+// under emulation. So for right now, exclude it.
+# define ACE_LACKS_QSORT
+#endif // _WIN32_WCE_EMULATION
+
+#if !defined (BUFSIZ)
+# define BUFSIZ 1024
+#endif
+
+typedef void (__cdecl * __sighandler_t)(int); // keep Signal compilation happy
+typedef long off_t;
+
+#define ACE_LACKS_MALLOC_H // We do have malloc.h, but don't use it.
+
+#define ACE_HAS_WINCE_BROKEN_ERRNO
+
+#define ACE_HAS_STRDUP_EMULATION
+
+// WinCE can't do fixed addresses for memory-mapped files.
+#if defined (ACE_DEFAULT_BASE_ADDR)
+# undef ACE_DEFAULT_BASE_ADDR
+#endif
+#define ACE_DEFAULT_BASE_ADDR 0
+
+#define ACE_HAS_TSS_EMULATION
+
+// This is still true up thru VC8...
+#define ACE_LACKS_ERRNO_H
+#define ACE_LACKS_SIGNAL_H
+#define ACE_LACKS_SYS_STAT_H
+
+#include /**/ "ace/post.h"
+
+#endif // ACE_CONFIG_WINCE_H
diff --git a/ACE/ace/config-aix-5.x.h b/ACE/ace/config-aix-5.x.h
new file mode 100644
index 00000000000..8068829fd2a
--- /dev/null
+++ b/ACE/ace/config-aix-5.x.h
@@ -0,0 +1,333 @@
+// $Id$
+//
+// Config file for AIX 5.1 and higher.
+
+#ifndef ACE_CONFIG_AIX_5_X_H
+#define ACE_CONFIG_AIX_5_X_H
+
+// This define is needed for building with Visual Age C++ 5 in incremental
+// mode. In the batch mode build, platform_aix_ibm.GNU sets it. The incremental
+// mode compiler won't be supported after ACE 5.3, so this will also go away
+// in that timeframe, so don't worry about future AIX versions.
+#if !defined (ACE_AIX_VERS)
+# define ACE_AIX_VERS 501
+#endif
+
+// AIX 5.1 has AIO, but it doesn't have the same API as other POSIX
+// systems, and the semantics of operations are a bit different. Will take
+// some real work to get this going.
+// AIX 5.2, however, has the POSIX API implemented. However, the libc functions
+// to implement it aren't exported by default. You need to use smit to enable
+// them. So, leave AIO disabled unless the user explicitly enables it.
+// config-aix-4.x.h will set ACE_HAS_AIO_CALLS if config-posix.h senses the
+// feature-test macros, so set up _ACE_DISABLE_AIO_CALLS_ if the user didn't
+// set it. Then check for it after including config-aix-4.x.h and remove
+// ACE_HAS_AIO_CALLS if so.
+#if !defined (ACE_HAS_AIO_CALLS)
+# define _ACE_DISABLE_AIO_CALLS_
+#endif
+
+// Both IBM and g++ compilers set _THREAD_SAFE if compiler is asked to compile
+// threaded code (xlC_r, as opposed to xlC; and g++ -pthread)
+#if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_THREADS)
+# undef ACE_HAS_THREADS
+# endif
+# if defined (_THREAD_SAFE)
+# define ACE_HAS_THREADS 1
+// # else
+// # define ACE_HAS_THREADS 0
+# endif /* _THREAD_SAFE */
+#endif /* !ACE_MT_SAFE || (ACE_MT_SAFE != 0) */
+
+#if defined (__xlC__) || defined (__IBMCPP__)
+ // AIX xlC, IBM C/C++, and Visual Age C++ compilers
+ //********************************************************************
+ //
+
+// Compiler does this with a builtin - it's not in libc.
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//# define ACE_HAS_ALLOCA
+
+// Compiler supports the ssize_t typedef.
+# define ACE_HAS_SSIZE_T
+
+ // Keep an eye on this as the compiler and standards converge...
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+# define ACE_LACKS_PRAGMA_ONCE
+
+ // C Set++ 3.1, IBM C/C++ 3.6, and Visual Age C++ 5 batch (__xlC__)
+# if defined (__xlC__)
+# if (__xlC__ < 0x0500)
+# define ACE_LACKS_PLACEMENT_OPERATOR_DELETE
+# endif /* __xlC__ < 0x0500 */
+# endif
+
+ // These are for Visual Age C++ only
+# if defined (__IBMCPP__) && (__IBMCPP__ >= 600)
+# define ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS
+ // When using -qtempinc, we don't need to see template implementation
+ // source (though we do need a pragma to find the correct source file).
+ // However, without -qtempinc (either -qnotempinc or -qtemplateregistry)
+ // we do need to see the source.
+# if defined (__TEMPINC__)
+# if !defined ACE_TEMPLATES_REQUIRE_PRAGMA
+# define ACE_TEMPLATES_REQUIRE_PRAGMA
+# endif
+# else
+# if !defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+# define ACE_TEMPLATES_REQUIRE_SOURCE
+# endif
+# endif /* __TEMPINC__ */
+
+# undef WIFEXITED
+# undef WEXITSTATUS
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+
+# if (__IBMCPP__ >= 600) /* Visual Age 6 and XL C/C++ 7 and up */
+# define ACE_HAS_TEMPLATE_TYPEDEFS
+# define ACE_HAS_CUSTOM_EXPORT_MACROS
+# define ACE_Proper_Export_Flag
+# define ACE_Proper_Import_Flag
+# define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) extern template class SINGLETON_TYPE < CLASS, LOCK >;
+# endif /* __IBMCPP__ >= 600 */
+# endif /* __IBMCPP__ */
+
+#elif defined (__GNUG__)
+ // config-g++-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+ // this must appear before its #include.
+# define ACE_HAS_STRING_CLASS
+
+# include "ace/config-g++-common.h"
+ // Denotes that GNU has cstring.h as standard, to redefine memchr().
+# define ACE_HAS_GNU_CSTRING_H
+# define ACE_HAS_SSIZE_T
+
+# if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0))
+// We have to explicitly instantiate static template members prior to g++ 4.1
+# define ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION
+#endif /* g++ prior to 4.1 */
+
+# if !defined (ACE_MT_SAFE) || ACE_MT_SAFE != 0
+ // ACE_MT_SAFE is #defined below, for all compilers.
+# if !defined (_REENTRANT)
+# define _REENTRANT
+# endif /* _REENTRANT */
+# endif /* !ACE_MT_SAFE */
+
+#else /* ! __xlC__ && ! __GNUG__ */
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler in ace/config-aix-5.x.h
+# endif /* __cplusplus */
+#endif /* ! __xlC__ && ! __GNUG__ */
+
+// Compiling for AIX.
+#ifndef AIX
+# define AIX
+#endif /* AIX */
+
+// Pick up all the detectable settings.
+#include "ace/config-posix.h"
+
+// Regardless of what config-posix.h may indicate, AIX 5.3 is the first
+// to support sem_timedwait(). Prior to that, use the emulation.
+#if defined (ACE_HAS_POSIX_SEM_TIMEOUT) && \
+ (defined (ACE_AIX_VERS) && (ACE_AIX_VERS < 503))
+# undef ACE_HAS_POSIX_SEM_TIMEOUT
+#endif /* ACE_HAS_POSIX_SEM_TIMEOUT && ACE_AIX_VERS < 503 */
+
+#if defined (ACE_DLL_SUFFIX)
+# undef ACE_DLL_SUFFIX
+#endif
+#define ACE_DLL_SUFFIX ".so"
+
+#define ACE_DEFAULT_BASE_ADDR ((char *) 0x80000000)
+
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+
+#define ACE_HAS_SOCKLEN_T
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+
+// AIX has AIO, but the functions don't match those of other AIO-enabled
+// platforms. If this is to work, it'll require some significant work,
+// maybe moving the OS-abstraction stuff to an OS_AIO or some such thing.
+//# define ACE_HAS_AIO_CALLS
+
+#define ACE_HAS_AIX_HI_RES_TIMER
+
+// Compiler/platform has correctly prototyped header files.
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Prototypes for both signal() and struct sigaction are consistent.
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// OS has readdir and friends.
+#define ACE_HAS_DIRENT
+
+// OS supports the getrusage() system call
+#define ACE_HAS_GETRUSAGE
+
+#define ACE_HAS_GPERF
+
+#define ACE_HAS_H_ERRNO
+
+#define ACE_LACKS_STDINT_H
+#define ACE_LACKS_SYS_SYSCTL_H
+
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_IP_MULTICAST
+
+// Lacks perfect filtering, must bind group address.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
+#define ACE_HAS_MSG
+
+// Compiler/platform supports poll().
+#define ACE_HAS_POLL
+
+// Platform supports POSIX O_NONBLOCK semantics.
+#define ACE_HAS_POSIX_NONBLOCK
+
+#define ACE_HAS_POSIX_TIME
+// ... but needs to include another header for it on 4.2+
+# define ACE_HAS_BROKEN_POSIX_TIME
+// ... and needs another typedef
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_HAS_SELECT_H
+
+#define ACE_HAS_REENTRANT_FUNCTIONS
+
+// Compiler/platform defines the sig_atomic_t typedef
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SIGINFO_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_HAS_P_READ_WRITE
+
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_STRBUF_T
+
+// Compiler supports stropts.h
+#define ACE_HAS_STREAMS
+// #define ACE_HAS_STREAM_PIPES
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// AIX bzero()
+#define ACE_HAS_STRINGS
+
+#define ACE_HAS_STRUCT_NETDB_DATA
+
+// Dynamic linking is in good shape on newer OS/patch levels. If you have
+// trouble with the dynamic linking parts of ACE, and can't patch your OS
+// up to latest levels, comment this out.
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+// This is tightly related to dynamic linking...
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+#define ACE_HAS_SVR4_GETTIMEOFDAY
+
+#define ACE_HAS_SYSV_IPC
+#define ACE_HAS_TIMOD_H
+#define ACE_HAS_XTI
+#define ACE_HAS_BROKEN_T_ERROR
+#define ACE_TLI_TCP_DEVICE "/dev/xti/tcp"
+
+#define ACE_HAS_UALARM
+
+#define ACE_HAS_UCONTEXT_T
+
+#define ACE_HAS_UTIME
+
+// Platform has XPG4 wide character type and functions. However, the size
+// of wchar_t changes for 32- vs. 64-bit builds (unsigned short vs. unsigned
+// int, respectively).
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+#ifdef __64BIT__
+# define ACE_SIZEOF_WCHAR 4
+#else
+# define ACE_SIZEOF_WCHAR 2
+#endif /* __64BIT__ */
+
+#define ACE_LACKS_NETINET_TCP_H
+
+// AIX uses LIBPATH to search for libraries
+#define ACE_LD_SEARCH_PATH "LIBPATH"
+
+// Defines the page size of the system.
+#define ACE_PAGE_SIZE 4096
+
+//**************************************************************
+//
+// Threads related definitions.
+//
+// The threads on AIX are generally POSIX P1003.1c (ACE_HAS_PTHREADS).
+// However, there is also a kernel thread ID (tid_t) that is used in
+// ACE_Log_Msg (printing the thread ID). The tid_t is not the same as
+// pthread_t, and can't derive one from the other - thread_self() gets
+// the tid_t (kernel thread ID) if called from a thread.
+// Thanks very much to Chris Lahey for straightening this out.
+
+#if defined (ACE_HAS_THREADS)
+# if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+# endif
+
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_PTHREADS_UNIX98_EXT
+# define ACE_HAS_PTHREAD_CONTINUE_NP
+# define ACE_HAS_PTHREAD_SUSPEND_NP
+# define ACE_HAS_RECURSIVE_MUTEXES
+# define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+# define ACE_HAS_SIGTHREADMASK
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+# define ACE_LACKS_THREAD_PROCESS_SCOPING
+#else
+# undef ACE_HAS_THREADS
+#endif /* ACE_HAS_THREADS != 0 */
+
+#define ACE_MALLOC_ALIGN 8
+
+#if (defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 500) && !defined(_UNIX95)
+# define ACE_HAS_3_PARAM_WCSTOK
+#endif /* (_XOPEN_SOURCE -0) >= 500 && !_UNIX95 */
+
+#if defined (_ACE_DISABLE_AIO_CALLS_)
+# if defined (ACE_HAS_AIO_CALLS)
+# undef ACE_HAS_AIO_CALLS
+# endif
+# undef _ACE_DISABLE_AIO_CALLS_
+#endif
+
+// AIX's /usr/include/unistd.h sets _POSIX_SEMAPHORE to indicate the system
+// supplies such a facility, but the headers don't enable it unless
+// _XOPEN_SOURCE >= 500. So disable semaphores here if _XOPEN_SOURCE isn't
+// up to snuff.
+#if defined (ACE_HAS_POSIX_SEM) && \
+ (!defined (_XOPEN_SOURCE) || (_XOPEN_SOURCE-0 < 500))
+# undef ACE_HAS_POSIX_SEM
+#endif
+
+// I think this is correct, but needs to be verified... -Steve Huston
+#define ACE_HAS_SIGTIMEDWAIT
+
+// AIX 5.1 has netinet/tcp.h
+#undef ACE_LACKS_NETINET_TCP_H
+
+#define ACE_HAS_3_PARAM_READDIR_R
+#define ACE_HAS_POSIX_GETPWNAM_R
+#define ACE_HAS_SCANDIR
+#define ACE_SCANDIR_CMP_USES_VOIDPTR
+#define ACE_SCANDIR_SEL_LACKS_CONST
+#define ACE_HAS_SIGSUSPEND
+#define ACE_HAS_TIMEZONE /* Call tzset() to set timezone */
+
+#endif /* ACE_CONFIG_AIX_5_X_H */
diff --git a/ACE/ace/config-all.h b/ACE/ace/config-all.h
new file mode 100644
index 00000000000..395330e7795
--- /dev/null
+++ b/ACE/ace/config-all.h
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file config-all.h
+ *
+ * $Id$
+ *
+ * @author (Originally in OS.h)Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ */
+//==========================================================================
+
+#ifndef ACE_CONFIG_ALL_H
+#define ACE_CONFIG_ALL_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// This is used to indicate that a platform doesn't support a
+// particular feature.
+#if defined ACE_HAS_VERBOSE_NOTSUP
+ // Print a console message with the file and line number of the
+ // unsupported function.
+# include "ace/OS_NS_stdio.h"
+# define ACE_NOTSUP_RETURN(FAILVALUE) do { errno = ENOTSUP; ACE_OS::fprintf (stderr, ACE_TEXT ("ACE_NOTSUP: %s, line %d\n"), __FILE__, __LINE__); return FAILVALUE; } while (0)
+# define ACE_NOTSUP do { errno = ENOTSUP; ACE_OS::fprintf (stderr, ACE_TEXT ("ACE_NOTSUP: %s, line %d\n"), __FILE__, __LINE__); return; } while (0)
+#else /* ! ACE_HAS_VERBOSE_NOTSUP */
+# define ACE_NOTSUP_RETURN(FAILVALUE) do { errno = ENOTSUP ; return FAILVALUE; } while (0)
+# define ACE_NOTSUP do { errno = ENOTSUP; return; } while (0)
+#endif /* ! ACE_HAS_VERBOSE_NOTSUP */
+
+// ----------------------------------------------------------------
+
+# define ACE_TRACE_IMPL(X) ACE_Trace ____ (ACE_TEXT (X), __LINE__, ACE_TEXT (__FILE__))
+
+// By default tracing is turned off.
+#if !defined (ACE_NTRACE)
+# define ACE_NTRACE 1
+#endif /* ACE_NTRACE */
+
+#if (ACE_NTRACE == 1)
+# define ACE_TRACE(X)
+#else
+# if !defined (ACE_HAS_TRACE)
+# define ACE_HAS_TRACE
+# endif /* ACE_HAS_TRACE */
+# define ACE_TRACE(X) ACE_TRACE_IMPL(X)
+# include "ace/Trace.h"
+#endif /* ACE_NTRACE */
+
+// By default we perform no tracing on the OS layer, otherwise the
+// coupling between the OS layer and Log_Msg is too tight. But the
+// application can override the default if they wish to.
+#if !defined (ACE_OS_NTRACE)
+# define ACE_OS_NTRACE 1
+#endif /* ACE_OS_NTRACE */
+
+#if (ACE_OS_NTRACE == 1)
+# define ACE_OS_TRACE(X)
+#else
+# if !defined (ACE_HAS_TRACE)
+# define ACE_HAS_TRACE
+# endif /* ACE_HAS_TRACE */
+# define ACE_OS_TRACE(X) ACE_TRACE_IMPL(X)
+# include "ace/Trace.h"
+#endif /* ACE_OS_NTRACE */
+
+// These includes are here to avoid circular dependencies.
+// Keep this at the bottom of the file. It contains the main macros.
+#include "ace/OS_main.h"
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONFIG_ALL_H */
diff --git a/ACE/ace/config-borland-common.h b/ACE/ace/config-borland-common.h
new file mode 100644
index 00000000000..58e00d7d144
--- /dev/null
+++ b/ACE/ace/config-borland-common.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+//$Id$
+
+// The following configuration file contains defines for Borland compilers.
+
+#ifndef ACE_CONFIG_BORLAND_COMMON_H
+#define ACE_CONFIG_BORLAND_COMMON_H
+#include /**/ "ace/pre.h"
+
+#define ACE_HAS_CUSTOM_EXPORT_MACROS
+#define ACE_Proper_Export_Flag __declspec (dllexport)
+#define ACE_Proper_Import_Flag __declspec (dllimport)
+#define ACE_EXPORT_SINGLETON_DECLARATION(T) template class __declspec (dllexport) T
+#define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class __declspec (dllexport) SINGLETON_TYPE<CLASS, LOCK>;
+#define ACE_IMPORT_SINGLETON_DECLARATION(T) template class __declspec (dllimport) T
+#define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class __declspec (dllimport) SINGLETON_TYPE <CLASS, LOCK>;
+
+# if (__BORLANDC__ == 0x540)
+// The linker in C++Builder 4 has trouble with the large number of DLL
+// function exports created when you compile without inline functions.
+// Therefore we will always use inline functions with this version of
+// the compiler.
+# if defined (__ACE_INLINE__)
+# undef __ACE_INLINE__
+# endif /* __ACE_INLINE__ */
+# define __ACE_INLINE__ 1
+# else /* __BORLANDC__ == 0x540 */
+// In later versions of C++Builder we will prefer inline functions by
+// default. The debug configuration of ACE is built with functions
+// out-of-line, so when linking your application against a debug ACE
+// build, you can choose to use the out-of-line functions by adding
+// ACE_NO_INLINE=1 to your project settings.
+# if !defined (__ACE_INLINE__)
+# define __ACE_INLINE__ 1
+# endif /* __ACE_INLINE__ */
+# endif /* __BORLANDC__ == 0x540 */
+
+# define ACE_CC_NAME ACE_TEXT ("Borland C++ Builder")
+# define ACE_CC_MAJOR_VERSION (__BORLANDC__ / 0x100)
+# define ACE_CC_MINOR_VERSION (__BORLANDC__ % 0x100)
+# define ACE_CC_BETA_VERSION (0)
+# define ACE_CC_PREPROCESSOR_ARGS "-q -P- -o%s"
+
+# define ACE_EXPORT_NESTED_CLASSES 1
+# define ACE_HAS_CPLUSPLUS_HEADERS 1
+# define ACE_HAS_EXCEPTIONS
+# define ACE_HAS_GNU_CSTRING_H 1
+# define ACE_HAS_NONCONST_SELECT_TIMEVAL
+# define ACE_HAS_SIG_ATOMIC_T
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_HAS_STDCPP_STL_INCLUDES 1
+# define ACE_HAS_STRERROR
+# define ACE_HAS_STRING_CLASS 1
+# define ACE_HAS_TEMPLATE_SPECIALIZATION 1
+# define ACE_HAS_TEMPLATE_TYPEDEFS 1
+# define ACE_HAS_USER_MODE_MASKS 1
+# define ACE_LACKS_ACE_IOSTREAM 1
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF 1
+# define ACE_LACKS_STRPTIME 1
+# if (__BORLANDC__ < 0x590)
+# define ACE_LACKS_PLACEMENT_OPERATOR_DELETE 1
+# endif
+# define ACE_LACKS_PRAGMA_ONCE 1
+# define ACE_HAS_NEW_NOTHROW
+# define ACE_TEMPLATES_REQUIRE_SOURCE 1
+# define ACE_SIZEOF_LONG_DOUBLE 10
+# define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%Lu")
+# define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%Ld")
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# define ACE_USES_STD_NAMESPACE_FOR_STDC_LIB 0
+# define ACE_ENDTHREADEX(STATUS) ::_endthreadex ((DWORD) STATUS)
+# define ACE_LACKS_SWAB
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_BORLAND_COMMON_H */
diff --git a/ACE/ace/config-cray.h b/ACE/ace/config-cray.h
new file mode 100644
index 00000000000..c50cc9f903e
--- /dev/null
+++ b/ACE/ace/config-cray.h
@@ -0,0 +1,215 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_CONFIG_CRAY_H
+#define ACE_CONFIG_CRAY_H
+#include /**/ "ace/pre.h"
+
+/*
+ The following predefined macros are used within ACE ifdefs.
+ These are defined when using the Cray compilers. _CRAYMPP
+ is defined, for example, if you are running on a Cray T3E
+ massively parallel machine. Moreover, in the case of the T3E,
+ _CRAYT3E will be defined. This is used to determine the
+ ACE_SIZEOF defines for primitive types.
+
+ _UNICOS is defined as either the major version of UNICOS being run,
+ e.g. 9 or 10 on the vector machines (e.g. C90, T90, J90, YMP, ...)
+ or the major+minor+level UNICOS/mk version, e.g. 2.0.3 => 203,
+ being run on an MPP machine.
+
+ Summary:
+
+ _CRAYMPP (defined only if running on MPP machine, e.g. T3E, UNICOS/mk)
+ _CRAYT3E (defined specifically if compiling on a Cray T3E)
+ _UNICOS (defined if running UNICOS or UNICOS/mk)
+
+ Tested on UNICOS 10.0.0.5, UNICOS/mk 2.0.4.57
+ Compiles on UNICOS 9.0.2.8, but some tests deadlock
+
+ Contributed by Doug Anderson <dla@home.com>
+*/
+
+#if defined (_UNICOS) && !defined (MAXPATHLEN)
+#define MAXPATHLEN 1023
+#endif /* _UNICOS */
+
+#define ACE_DEFAULT_CLOSE_ALL_HANDLES 0
+
+// Defines the page size of the system.
+#define ACE_PAGE_SIZE 4096
+
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+
+#define ACE_HAS_SSIZE_T
+
+#define ACE_HAS_SYSV_IPC
+
+#define ACE_MT_SAFE 1
+
+#define ACE_HAS_THREADS
+
+#define ACE_HAS_PTHREADS
+
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+#define ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP
+
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+
+#define ACE_HAS_POSIX_TIME
+
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+#define ACE_HAS_DIRENT
+
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+#define ACE_HAS_IP_MULTICAST
+
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+#define ACE_HAS_NONCONST_READLINK
+
+#define ACE_HAS_CHARPTR_SOCKOPT
+
+#define ACE_HAS_NONCONST_GETBY
+
+// has man pages, but links with missing symbols and I can't find lib yet
+/* #define ACE_HAS_REGEX */
+
+#define ACE_HAS_SIG_MACROS
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+#if _UNICOS > 9
+# define ACE_HAS_SIGWAIT
+#endif
+
+#define ACE_HAS_SIG_ATOMIC_T
+
+#define ACE_HAS_SIGISMEMBER_BUG
+
+#define ACE_HAS_MSG
+
+#define ACE_HAS_STRERROR
+
+#define ACE_HAS_GPERF
+
+// Special modifications that apply to UNICOS/mk
+#if defined(_CRAYMPP)
+
+# define ACE_HAS_SIGINFO_T
+# define ACE_HAS_UCONTEXT_T
+
+#endif
+
+// The Cray T90 supposedly supports SYSV SHMEM, but I was unable to get it
+// working. Of course, all other Cray PVP and MPP systems do NOT support it,
+// so it's probably good to just define like this for consistency
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_MMAP
+#define ACE_LACKS_CONST_TIMESPEC_PTR
+#define ACE_LACKS_SYSCALL
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+#define ACE_LACKS_PTHREAD_CLEANUP
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+
+#if !defined(_CRAYMPP)
+
+#define ACE_LACKS_PTHREAD_CANCEL
+#define ACE_LACKS_PTHREAD_KILL
+
+#endif
+
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_PRI_T
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_MPROTECT
+#define ACE_LACKS_MSYNC
+#define ACE_LACKS_READV
+#define ACE_LACKS_RLIMIT
+
+// we probably want to fake not having this, since Cray memory mgmt is different
+#define ACE_LACKS_SBRK
+
+#define ACE_LACKS_SETSCHED
+
+#define ACE_LACKS_SIGINFO_H
+
+#define ACE_LACKS_TIMESPEC_T
+
+#define ACE_LACKS_WRITEV
+
+// Cray vector machines are "word" oriented, and modern ones are hard 64-bit.
+// "char" is somewhat of a special case. Most problems arise when code thinks
+// it can address 32-bit quantities and the like. MPP crays are typically
+// byte oriented, e.g. T3E uses Alpha processors, so we don't need as much
+// special treatment.
+
+#ifndef _CRAYMPP
+
+# define ACE_SIZEOF_CHAR 1
+# define ACE_SIZEOF_SHORT 8
+# define ACE_SIZEOF_INT 8
+# define ACE_SIZEOF_LONG 8
+# define ACE_SIZEOF_LONG_LONG 8
+# define ACE_SIZEOF_FLOAT 8
+# define ACE_SIZEOF_DOUBLE 8
+# define ACE_SIZEOF_LONG_DOUBLE 16
+# define ACE_SIZEOF_VOID_P 8
+
+#elif defined(_CRAYT3E)
+
+# define ACE_SIZEOF_CHAR 1
+# define ACE_SIZEOF_SHORT 4
+# define ACE_SIZEOF_INT 8
+# define ACE_SIZEOF_LONG 8
+# define ACE_SIZEOF_LONG_LONG 8
+# define ACE_SIZEOF_FLOAT 4
+# define ACE_SIZEOF_DOUBLE 8
+# define ACE_SIZEOF_LONG_DOUBLE 8
+# define ACE_SIZEOF_VOID_P 8
+
+#endif
+
+// Ones to check out at some point
+
+/* #define ACE_HAS_SYS_SIGLIST */
+
+// C++ Compiler stuff to verify
+/* #define ACE_NEW_THROWS_EXCEPTIONS */
+/* #define ACE_HAS_TEMPLATE_TYPEDEFS */
+
+// thread issues to check out
+/* #define ACE_LACKS_TIMEDWAIT_PROTOTYPES */
+
+// Cray does seem to support it, in -lnsl and has tiuser.h header
+/* #define ACE_HAS_TLI */
+/* #define ACE_HAS_TIUSER_H */
+/* #define ACE_HAS_TLI_PROTOTYPES */
+/* #define ACE_LACKS_T_ERRNO */
+
+/* #define ACE_LACKS_NAMED_POSIX_SEM */
+
+/* #define ACE_HAS_SYS_ERRLIST */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_CRAY_H */
diff --git a/ACE/ace/config-cxx-common.h b/ACE/ace/config-cxx-common.h
new file mode 100644
index 00000000000..41be414fba6
--- /dev/null
+++ b/ACE/ace/config-cxx-common.h
@@ -0,0 +1,87 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifndef ACE_CXX_COMMON_H
+#define ACE_CXX_COMMON_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_CONFIG_INCLUDE_CXX_COMMON)
+# error ace/config-cxx-common.h: ACE configuration error! Do not #include this file directly!
+#endif
+
+#if defined (__DECCXX)
+# if !defined (linux)
+# define ACE_HAS_STRING_CLASS
+# if (__DECCXX_VER >= 60090010)
+# define ACE_HAS_STDCPP_STL_INCLUDES
+# endif /* __DECCXX_VER < 60090010 */
+# endif /* ! linux */
+
+# define DEC_CXX
+# define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+# define ACE_LACKS_SIGNED_CHAR
+# define ACE_HAS_CPLUSPLUS_HEADERS
+# define ACE_TEMPLATES_REQUIRE_SOURCE
+# if (__DECCXX_VER >= 60090010)
+ // DEC CXX 6.0 supports exceptions, etc., by default. Exceptions
+ // are enabled by platform_osf1_4.x.GNU/wrapper_macros.GNU.
+# if defined (ACE_HAS_EXCEPTIONS)
+# define ACE_NEW_THROWS_EXCEPTIONS
+# endif /* ACE_HAS_EXCEPTIONS */
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_HAS_TEMPLATE_SPECIALIZATION
+# define ACE_HAS_TEMPLATE_TYPEDEFS
+
+# define ACE_ENDLESS_LOOP \
+ unsigned int ace_endless_loop____ = 0; if (ace_endless_loop____) break;
+
+# if defined (__USE_STD_IOSTREAM)
+# define ACE_LACKS_CHAR_RIGHT_SHIFTS
+# define ACE_LACKS_IOSTREAM_FX
+# define ACE_LACKS_UNBUFFERED_STREAMBUF
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# else /* ! __USE_STD_IOSTREAM */
+# define ACE_USES_OLD_IOSTREAMS
+# endif /* ! __USE_STD_IOSTREAM */
+
+// 9: nested comment not allowed. (/usr/include/pdsc.h!) (nestcomment)
+// 177: variable was declared but never referenced (declbutnotref)
+// 193: zero used for undefined preprocessing identifier (undpreid)
+// 236: controlling expression is constant (boolexprconst)
+// 401: base_class_with_nonvirtual_dtor (basclsnondto)
+// 1016: expected type is incompatible with declared type of int (incint)
+// 1136: conversion to smaller size integer could lose data (intconlosbit)
+
+# pragma message disable basclsnondto
+# pragma message disable boolexprconst
+# pragma message disable undpreid
+# pragma message disable notusetmpfunprm
+# pragma message disable bltinclnk
+
+# if (__DECCXX_VER >= 60190029)
+ // 6.1-029 and later support msg 1136. Disable it because it
+ // causes warnings from ACE and/or TAO.
+# pragma message disable intconlosbit
+# endif /* __DECCXX_VER >= 60190029 */
+
+# if (__DECCXX_VER == 60190027)
+ // Seems that this version of cxx doesn't have reset
+# define ACE_AUTO_PTR_LACKS_RESET
+# endif /* __DECCXX_VER == 60190027 */
+
+# if defined (DIGITAL_UNIX) && DIGITAL_UNIX >= 0x40D
+ // variable "PTHREAD_THIS_CATCH_NP" was declared but never referenced
+# pragma message disable declbutnotref
+# endif /* DIGITAL_UNIX >= 4.0f */
+
+# else /* __DECCXX_VER < 60090010 */
+# define ACE_LACKS_PRAGMA_ONCE
+# endif /* __DECCXX_VER < 60090010 */
+#else /* ! __DECCXX */
+# error ace/config-cxx-common.h can only be used with Compaq CXX!
+#endif /* ! __DECCXX */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CXX_COMMON_H */
diff --git a/ACE/ace/config-cygwin32.h b/ACE/ace/config-cygwin32.h
new file mode 100644
index 00000000000..99b709e4c49
--- /dev/null
+++ b/ACE/ace/config-cygwin32.h
@@ -0,0 +1,204 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for CygWin
+// platforms using GNU C++.
+
+#ifndef ACE_CONFIG_CYGWIN32_H
+#define ACE_CONFIG_CYGWIN32_H
+
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_MT_SAFE)
+#define ACE_MT_SAFE 1
+#endif
+
+#define CYGWIN32
+
+// We trust this file will get included before <sys/types.h>
+#if !defined(FD_SETSIZE)
+# define FD_SETSIZE 1024
+#endif
+
+#if !defined (ACE_IOV_MAX)
+# define ACE_IOV_MAX 64
+#endif /* ACE_IOV_MAX */
+
+// Define custom export macros for export/import of symbols from/of dll's
+#define ACE_HAS_CUSTOM_EXPORT_MACROS
+#define ACE_Proper_Export_Flag __declspec (dllexport)
+#define ACE_Proper_Import_Flag __declspec (dllimport)
+#define ACE_EXPORT_SINGLETON_DECLARATION(T) template class __declspec (dllexport) T
+#define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class __declspec (dllexport) SINGLETON_TYPE<CLASS, LOCK>;
+#define ACE_IMPORT_SINGLETON_DECLARATION(T) extern template class T
+#define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) extern template class SINGLETON_TYPE <CLASS, LOCK>;
+
+#define ACE_HAS_SELECT_H
+
+#define ACE_LACKS_PRAGMA_ONCE
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#include /**/ <cygwin/version.h>
+
+// Needed to differentiate between libc 5 and libc 6 (aka glibc).
+// It's there on all libc 5 systems I checked.
+#include /**/ <features.h>
+
+// config-g++-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+// this must appear before its #include.
+#define ACE_HAS_STRING_CLASS
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#else
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler in ace/config-cygwin32.h
+# endif /* __cplusplus */
+#endif /* __GNUG__ */
+
+#define ACE_HAS_VOIDPTR_SOCKOPT 1
+#define ACE_HAS_UALARM 1
+#define ACE_HAS_SYS_ERRLIST 1
+#define ACE_HAS_STRNLEN 1
+#define ACE_HAS_POSIX_GETPWNAM_R 1
+#define ACE_HAS_POSIX_NONBLOCK 1
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_CLOCK_GETTIME 1
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+#define ACE_HAS_MSG
+#define ACE_DEFAULT_BASE_ADDR ((char *) 0x8000000)
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+//#define ACE_HAS_SYSV_IPC
+#define ACE_HAS_VOIDPTR_MMAP
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_POLL
+#define ACE_HAS_POSITION_INDEPENDENT_POINTERS 1
+#define ACE_HAS_SOCKADDR_MSG_NAME 1
+#define ACE_LACKS_PRI_T 1
+#define ACE_HAS_3_PARAM_READDIR_R
+
+// Compiler/platform supports alloca().
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you want ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+#define ACE_HAS_IP_MULTICAST
+
+#define ACE_HAS_BIG_FD_SET
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+#define ACE_DEFAULT_MAX_SOCKET_BUFSIZ 65535
+
+#define ACE_DEFAULT_SELECT_REACTOR_SIZE 256
+
+#define ACE_HAS_GETPAGESIZE
+
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+#define ACE_HAS_SOCKLEN_T 1
+
+#define ACE_HAS_GPERF
+
+#define ACE_HAS_DIRENT
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+
+#define ACE_LACKS_MKFIFO
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_FGETWC 1
+#define ACE_LACKS_NAMED_POSIX_SEM
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_GETPGID_PROTOTYPE
+#define ACE_LACKS_GETHOSTENT
+#define ACE_LACKS_ITOW 1
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF 1
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS 1
+#define ACE_LACKS_RLIMIT
+#define ACE_LACKS_RWLOCK_T 1
+#define ACE_LACKS_SUSECONDS_T
+#define ACE_LACKS_SYS_SYSCTL_H
+
+#define ACE_LACKS_FGETWS 1
+#define ACE_LACKS_FPUTWS 1
+
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGACTION_CONSTP2
+#define ACE_HAS_SIGSUSPEND
+#define ACE_HAS_SIG_C_FUNC 1
+#define ACE_HAS_SIG_ATOMIC_T
+
+#define ACE_HAS_POSIX_SEM
+
+#define ACE_HAS_P_READ_WRITE
+
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+
+// Cygwin DLL suffix is .dll
+#define ACE_DLL_SUFFIX ACE_TEXT (".dll")
+
+// Cygwin runs on Windows, so we have to get the environment variable PATH and
+// not LD_LIBRARY_PATH which is the default in ACE
+#define ACE_LD_SEARCH_PATH ACE_TEXT ("PATH")
+
+#if ACE_MT_SAFE
+// Yes, we do have threads.
+# define ACE_HAS_THREADS
+// And they're even POSIX pthreads (LinuxThreads implementation)
+# define ACE_HAS_PTHREADS
+
+# define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+
+// Compiler/platform has thread-specific storage
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+# define ACE_HAS_PTHREADS_UNIX98_EXT
+# define ACE_HAS_PTHREAD_CONTINUE 1
+# define ACE_HAS_PTHREAD_SUSPEND 1
+
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR
+// Cygwin (see pthread.h): Not supported or implemented.
+# define ACE_LACKS_SETSCHED
+# define ACE_LACKS_SETDETACH
+# define ACE_LACKS_PTHREAD_CANCEL
+# define ACE_LACKS_THREAD_PROCESS_SCOPING
+# define ACE_LACKS_MUTEXATTR_PSHARED
+# define ACE_LACKS_RWLOCKATTR_PSHARED
+# define ACE_LACKS_PTHREAD_THR_SIGSETMASK 1
+# define ACE_LACKS_PTHREAD_YIELD 1
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACK
+
+// In the 1.5.9 release of Cygwin the pthread_kill gives an access violation
+// so for the time being we say Cygwin doesn't support pthread_kill.
+# define ACE_LACKS_PTHREAD_KILL
+
+#endif /* ACE_MT_SAFE */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONFIG_CYGWIN32_H */
diff --git a/ACE/ace/config-doxygen.h b/ACE/ace/config-doxygen.h
new file mode 100644
index 00000000000..054345f5998
--- /dev/null
+++ b/ACE/ace/config-doxygen.h
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+
+/**
+ * This is a configuration file to define all the macros that Doxygen
+ * needs
+ *
+ * @file config-doxygen.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ * @author Darrell Brunsch <brunsch@uci.edu>
+ *
+ */
+#ifndef ACE_CONFIG_DOXYGEN_H
+#define ACE_CONFIG_DOXYGEN_H
+
+/// Make sure that we always turn inlining on.
+#define __ACE_INLINE__
+
+/// Make the wchar_t interfaces available.
+#define ACE_HAS_WCHAR
+
+/// Make all the emulation versions of string operations visible
+// #define ACE_LACKS_WCSTOK
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_STRCASECMP
+#define ACE_LACKS_STRRCHR
+#define ACE_LACKS_WCSCAT
+#define ACE_LACKS_WCSCHR
+#define ACE_LACKS_WCSCMP
+#define ACE_LACKS_WCSCPY
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSLEN
+#define ACE_LACKS_WCSNCAT
+#define ACE_LACKS_WCSNCMP
+#define ACE_LACKS_WCSNCPY
+#define ACE_LACKS_WCSNICMP
+#define ACE_LACKS_WCSPBRK
+#define ACE_LACKS_WCSRCHR
+#define ACE_LACKS_WCSCSPN
+#define ACE_LACKS_WCSSPN
+#define ACE_LACKS_WCSSTR
+
+/// Support for threads enables several important classes
+#define ACE_HAS_THREADS
+
+/// Support for Win32 enables the WFMO_Reactor and several Async I/O
+/// classes
+#define ACE_WIN32
+
+/// Enable support for POSIX Asynchronous I/O calls
+#define ACE_HAS_AIO_CALLS
+
+/// Enable support for TLI interfaces
+#define ACE_HAS_TLI
+
+/// Enable support for the SSL wrappers
+#define ACE_HAS_SSL 1
+
+/// Enable exceptions
+#define ACE_HAS_EXCEPTIONS
+
+/// Enable timeprobes
+#define ACE_COMPILE_TIMEPROBES
+
+/// Enable unicode to generate ACE_Registry_Name_Space
+#define UNICODE
+
+/// These defines make sure that Svc_Conf_y.cpp and Svc_Conf_l.cpp are correctly
+/// parsed
+#define __cplusplus
+#define ACE_YY_USE_PROTOS
+
+/// TAO features that should be documented too
+#define TAO_HAS_RT_CORBA 1
+#define TAO_HAS_MINIMUM_CORBA 0
+#define TAO_HAS_AMI 1
+#define TAO_HAS_INTERCEPTORS 1
+#define TAO_HAS_SCIOP 1
+#define TAO_HAS_COIOP 1
+#define TAO_HAS_TRANSPORT_CURRENT 1
+
+/// Generate token library documentation
+#define ACE_HAS_TOKENS_LIBRARY
+
+/// Generate ACE ATM classes documentation
+#define ACE_HAS_ATM
+
+/// Generate ACE XTI ATM class documentation
+#define ACE_HAS_XTI_ATM
+
+/// Generate ACE_Dev_Poll_Reactor documentation
+#define ACE_HAS_DEV_POLL
+
+/// Generate ACE_Event_Handler_T documentation
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+
+/// Generate ACE_Log_Msg_NT_Event_Log documentation
+#define ACE_HAS_LOG_MSG_NT_EVENT_LOG
+
+/// Generate icmp documentation
+#define ACE_HAS_ICMP_SUPPORT 1
+
+/// Don't expand ACE_RCSID macro
+#define ACE_USE_RCSID 0
+
+/// Parse some ACE_SSL classes that depend on recent versions of
+/// OpenSSL.
+#define OPENSSL_VERSION_NUMBER 0x00905820L
+
+/// Enable IPv6
+#define ACE_HAS_IPV6
+
+/// Enable netlink socket support
+#define ACE_HAS_NETLINK
+
+#define ACE_HAS_IP_MULTICAST
+
+#endif /* ACE_CONFIG_DOXYGEN_H */
diff --git a/ACE/ace/config-freebsd.h b/ACE/ace/config-freebsd.h
new file mode 100644
index 00000000000..db0cee84bef
--- /dev/null
+++ b/ACE/ace/config-freebsd.h
@@ -0,0 +1,284 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for FreeBSD
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+#if ACE_MT_SAFE
+ // Yes, we do have threads.
+# define ACE_HAS_THREADS 1
+#else
+ // Set to 0 since that's what config-posix.h checks for.
+# define ACE_HAS_THREADS 0
+#endif /* ACE_MT_SAFE */
+
+#include "ace/config-posix.h"
+
+#include <osreldate.h>
+// Make sure we source in the OS version.
+
+#if ! defined (__ACE_INLINE__)
+#define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#if (__FreeBSD_version < 220000)
+#if defined (ACE_HAS_THREADS)
+#error Threads are not supported.
+#endif /* ACE_HAS_THREADS */
+#endif /* __FreeBSD_version < 220000 */
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#endif /* __GNUG__ */
+
+#if defined (ACE_HAS_PENTIUM)
+# undef ACE_HAS_PENTIUM
+#endif /* ACE_HAS_PENTIUM */
+
+// Platform specific directives
+// gcc defines __FreeBSD__ automatically for us.
+#ifdef ACE_HAS_THREADS
+#if !defined (_THREAD_SAFE)
+#define _THREAD_SAFE
+#endif /* _THREAD_SAFE */
+#endif
+
+#define ACE_HAS_GPERF
+
+#if (__FreeBSD_version < 420000)
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_PTHREAD_CANCEL
+#endif /* __FreeBSD_version < 420000 */
+
+#define ACE_HAS_ALT_CUSERID
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+#define ACE_HAS_SIG_MACROS
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_CHARPTR_DL
+
+#if (__FreeBSD_version < 400000)
+#define ACE_LACKS_SIGSET
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_READDIR_R
+#define ACE_LACKS_SETSCHED
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_RAND_REENTRANT_FUNCTIONS
+#endif
+
+#define ACE_NEEDS_SCHED_H
+
+#if (__FreeBSD_version < 400000)
+enum schedparam_policy {
+ SCHED_RR,
+ SCHED_IO,
+ SCHED_FIFO,
+ SCHED_OTHER
+};
+#endif
+
+// Use of <malloc.h> is deprecated.
+#define ACE_LACKS_MALLOC_H
+
+
+// This won't be necessary after it is fixed in the system include headers.
+extern "C" { char * cuserid (char *s); }
+
+// Platform supports POSIX timers via struct timespec.
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_UALARM
+
+// Platform defines struct timespec but not timespec_t
+#define ACE_LACKS_TIMESPEC_T
+
+#if (__FreeBSD_version < 501000)
+#define ACE_LACKS_STDINT_H
+#endif
+
+#define ACE_HAS_SYSCTL
+#define ACE_LACKS_STRRECVFD
+
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+#if (__FreeBSD_version >= 220000)
+#define ACE_HAS_VASPRINTF
+#endif
+
+#if (__FreeBSD_version >= 300000)
+#define ACE_HAS_SIGINFO_T
+#endif /* __FreeBSD_version >= 300000 */
+
+#if (__FreeBSD_version >= 320000)
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+#endif /* __FreeBSD_version >= 320000 */
+
+#if (__FreeBSD_version >= 440000)
+#define ACE_HAS_GETPROGNAME
+#define ACE_HAS_SETPROGNAME
+#endif
+
+#if (__FreeBSD_version < 501000)
+#define ACE_LACKS_PWD_REENTRANT_FUNCTIONS
+#endif
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_LOG2
+#define ACE_LACKS_SI_ADDR
+
+// Compiler/platform supports SVR4 signal typedef
+#define ACE_HAS_SVR4_SIGNAL_T
+
+// Compiler/platform supports alloca().
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform supports SVR4 dynamic linking semantics..
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Explicit dynamic linking permits "lazy" symbol resolution
+#define ACE_HAS_RTLD_LAZY_V
+
+// platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+
+// Lacks perfect filtering, must bind group address.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
+// Compiler/platform has <alloca.h>
+//#define ACE_HAS_ALLOCA_H
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Compiler/platform supports sys_siglist array.
+// *** This refers to (_sys_siglist) instead of (sys_siglist)
+// #define ACE_HAS_SYS_SIGLIST
+
+// Compiler/platform defines a union semun for SysV shared memory.
+#define ACE_HAS_SEMUN
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Defines the page size of the system.
+#define ACE_PAGE_SIZE 4096
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Platform/compiler supports timezone * as second parameter to gettimeofday().
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+#define ACE_HAS_MSG
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+
+#if (__FreeBSD_version < 500100)
+# define ACE_HAS_NONCONST_MSGSND
+#endif
+
+// Thread specific settings
+// Yes, we do have threads.
+#ifdef ACE_HAS_THREADS
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif /* ! ACE_MT_SAFE */
+#endif /* ACE_HAS_THREADS */
+
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#define ACE_HAS_DIRENT
+
+#define ACE_HAS_SIGWAIT
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+#if (__FreeBSD_version > 400000)
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_SOCKLEN_T
+#define ACE_HAS_GETIFADDRS
+#define ACE_HAS_PTHREADS_UNIX98_EXT
+#endif
+
+// Note, on FreeBSD 5, POSIX aio is now an optional kernel module which
+// must be loaded.
+// Read the aio(4) man page for what to do, otherwise any aio_* call
+// will coredump.
+
+// By default use Proactor which does not use POSIX Real-time Signals.
+#ifdef ACE_HAS_AIO_CALLS
+# ifndef ACE_POSIX_AIOCB_PROACTOR
+# define ACE_POSIX_AIOCB_PROACTOR
+# endif /* ACE_POSIX_AIOCB_PROACTOR */
+#endif /* ACE_HAS_AIO_CALLS */
+
+#define ACE_LACKS_STROPTS_H
+
+// Needed when ACE_HAS_WCHAR is defined.
+#define ACE_LACKS_WCSNICMP
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSDUP
+#define ACE_LACKS_ITOW
+#define ACE_HAS_3_PARAM_WCSTOK
+#define ACE_HAS_3_PARAM_READDIR_R
+
+#if (__FreeBSD_version >= 501000)
+# define ACE_HAS_PTHREAD_SETSTACK
+#endif
+
+#if (__FreeBSD_version < 700007)
+# define ACE_HAS_SIGVAL_SIGVAL_INT
+# define ACE_HAS_BROKEN_SIGEVENT_STRUCT
+#endif
+
+#if (__FreeBSD_version >= 700028)
+# define ACE_HAS_SCTP
+# define ACE_HAS_LKSCTP
+#endif
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-g++-common.h b/ACE/ace/config-g++-common.h
new file mode 100644
index 00000000000..72899831941
--- /dev/null
+++ b/ACE/ace/config-g++-common.h
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// This configuration file is designed to be included by another,
+// specific configuration file. It provides config information common
+// to all g++ platforms, including egcs.
+
+#ifndef ACE_GNUG_COMMON_H
+#define ACE_GNUG_COMMON_H
+#include /**/ "ace/pre.h"
+
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_STDCPP_STL_INCLUDES
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+#define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+
+#if ( __GNUC__ == 2 && __GNUC_MINOR__ < 97 )
+ // gcc 2.97 and lower use old iostreams
+# define ACE_USES_OLD_IOSTREAMS
+#endif /* __GNUC__ >= 2.97 */
+
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+# define ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS
+#endif /* __GNUC__ >= 3.4 */
+
+#if (__GNUC__ < 3)
+# define ACE_LACKS_MEMBER_TEMPLATES
+#endif /* __GNUC__ < 3 */
+
+// __EXCEPTIONS is defined with -fexceptions, the egcs default. It
+// is not defined with -fno-exceptions, the ACE default for g++.
+// ACE_HAS_EXCEPTIONS is defined in
+// include/makeinclude/wrapper_macros.GNU, so this really isn't
+// necessary. Just in case . . .
+#if defined (__EXCEPTIONS) && !defined (ACE_HAS_EXCEPTIONS)
+# define ACE_HAS_EXCEPTIONS
+#endif /* __EXCEPTIONS && ! ACE_HAS_EXCEPTIONS */
+
+#if defined (ACE_HAS_EXCEPTIONS)
+# define ACE_NEW_THROWS_EXCEPTIONS
+# if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
+// Versions of g++ prior to 3.3 had a buggy operator // new(nothrow)[]().
+# define ACE_HAS_NEW_NOTHROW
+# endif /* __GNUC__ >= 3.3 */
+#endif /* ACE_HAS_EXCEPTIONS */
+
+#if (defined (i386) || defined (__i386__)) && !defined (ACE_SIZEOF_LONG_DOUBLE)
+# define ACE_SIZEOF_LONG_DOUBLE 12
+#endif /* i386 */
+
+#if !defined (__MINGW32__) && (defined (i386) || defined (__i386__))
+ // If running an Intel, assume that it's a Pentium so that
+ // ACE_OS::gethrtime () can use the RDTSC instruction. If running a
+ // 486 or lower, be sure to comment this out. (If not running an
+ // Intel CPU, this #define will not be seen because of the i386
+ // protection, so it can be ignored.)
+# define ACE_HAS_PENTIUM
+#endif /* i386 */
+
+#if (defined (ACE_HAS_PENTIUM) || defined (__amd64__) || defined (__x86_64__))
+# define ACE_HAS_INTEL_ASSEMBLY
+#endif
+
+// GNU g++ >= 4.x implements "#pragma once".
+#if (__GNUC__ < 4) && !defined (ACE_LACKS_PRAGMA_ONCE)
+// We define it with a -D with make depend.
+# define ACE_LACKS_PRAGMA_ONCE
+#endif /* ! ACE_LACKS_PRAGMA_ONCE */
+
+// Take advantage of G++ (>= 4.x) visibility attributes to generate
+// improved shared library binaries.
+#if (__GNUC__ >= 4) && !defined (__MINGW32__)
+
+# if defined (ACE_HAS_CUSTOM_EXPORT_MACROS) && ACE_HAS_CUSTOM_EXPORT_MACROS == 0
+# undef ACE_HAS_CUSTOM_EXPORT_MACROS
+# if defined (ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS)
+# undef ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS
+# endif /* ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS */
+# define ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS 0
+# else
+# ifndef ACE_HAS_CUSTOM_EXPORT_MACROS
+# define ACE_HAS_CUSTOM_EXPORT_MACROS
+# endif /* !ACE_HAS_CUSTOM_EXPORT_MACROS */
+# define ACE_Proper_Export_Flag __attribute__ ((visibility("default")))
+# define ACE_Proper_Import_Flag __attribute__ ((visibility("default")))
+
+# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
+// Sadly, G++ 4.x silently ignores visibility attributes on
+// template instantiations, which breaks singletons.
+// As a workaround, we use the GCC visibility pragmas.
+// And to make them fit in a macro, we use C99's _Pragma()
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17470
+// This has been fixed in GCC 4.1.1 with FC6 but not with SuSE 10.2
+// that gets shipped with GCC 4.1.2 so we assume that with GCC 4.2
+// this will be fixed on the head. With FC6 just set this define yourself
+# ifndef ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS
+# define ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS 1
+# endif
+# endif
+
+# if defined (ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS) && ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS == 1
+# define ACE_EXPORT_SINGLETON_DECLARATION(T) template class ACE_Proper_Export_Flag T
+# define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class ACE_Proper_Export_Flag SINGLETON_TYPE <CLASS, LOCK>;
+# else /* ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS */
+# define ACE_EXPORT_SINGLETON_DECLARATION(T) \
+ _Pragma ("GCC visibility push(default)") \
+ template class T \
+ _Pragma ("GCC visibility pop")
+# define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) \
+ _Pragma ("GCC visibility push(default)") \
+ template class SINGLETON_TYPE<CLASS, LOCK>; \
+ _Pragma ("GCC visibility pop")
+# endif /* ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS */
+
+// Note that the "__extension__" is needed to prevent g++ from issuing
+// an error when using its "-pedantic" command line flag.
+# define ACE_IMPORT_SINGLETON_DECLARATION(T) __extension__ extern template class T
+# define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) __extension__ extern template class SINGLETON_TYPE<CLASS, LOCK>;
+
+# endif /* ACE_HAS_CUSTOM_EXPORT_MACROS == 0 */
+#endif /* __GNU__ >= 4 */
+
+#if defined (ACE_HAS_GNU_REPO)
+ // -frepo causes unresolved symbols of basic_string left- and
+ // right-shift operators with ACE_HAS_STRING_CLASS.
+# if defined (ACE_HAS_STRING_CLASS)
+# undef ACE_HAS_STRING_CLASS
+# endif /* ACE_HAS_STRING_CLASS */
+#endif /* ! ACE_HAS_GNU_REPO */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_GNUG_COMMON_H */
diff --git a/ACE/ace/config-ghs-common.h b/ACE/ace/config-ghs-common.h
new file mode 100644
index 00000000000..8ffa331d8fd
--- /dev/null
+++ b/ACE/ace/config-ghs-common.h
@@ -0,0 +1,43 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file is designed to be included by another,
+// specific configuration file. It provides config information common
+// to all Green Hills platforms.
+
+#ifndef ACE_GHS_COMMON_H
+#define ACE_GHS_COMMON_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_CONFIG_INCLUDE_GHS_COMMON)
+# error ace/config-ghs-common.h: ACE configuration error! Do not #include this file directly!
+#endif
+
+#if defined (ghs)
+
+# if defined (sun)
+ // Need nonstatic Object_Manager on Solaris to prevent seg fault
+ // on startup.
+# define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+# endif /* sun */
+
+# if defined (__STANDARD_CXX)
+ // Green Hills 1.8.9, but not 1.8.8.
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_LACKS_AUTO_PTR
+# define ACE_LACKS_CHAR_RIGHT_SHIFTS
+# define ACE_LACKS_UNBUFFERED_STREAMBUF
+# else
+# define ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA
+# endif /* __STANDARD_CXX */
+
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+# define ACE_LACKS_LONGLONG_T
+# define ACE_LACKS_SIGNED_CHAR
+
+#else /* ! ghs */
+# error ace/config-ghs-common.h can only be used with Green Hills compilers!
+#endif /* ! ghs */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_GHS_COMMON_H */
diff --git a/ACE/ace/config-hpux-11.00.h b/ACE/ace/config-hpux-11.00.h
new file mode 100644
index 00000000000..ae83149b845
--- /dev/null
+++ b/ACE/ace/config-hpux-11.00.h
@@ -0,0 +1,446 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for HP
+// platforms running HP-UX 11.00 using aC++ or gcc (2.95 and up).
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#define ACE_LACKS_STDINT_H
+#define ACE_LACKS_SYS_SELECT_H
+
+#if defined (__GNUG__)
+
+// config-g++-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+// this must appear before its #include.
+# define ACE_HAS_STRING_CLASS
+
+# include "ace/config-g++-common.h"
+
+#else
+
+// aC++...
+
+// Precompiler needs extra flags to ignore "invalid #pragma directive"
+# define ACE_CC_PREPROCESSOR_ARGS "-E +W 67"
+
+// Compiler supports C++ exception handling. It's on by default. If the
+// +noeh compiler option is used to disable exceptions, the compiler defines
+// __HPACC_NOEH.
+# if !defined (__HPACC_NOEH)
+# define ACE_HAS_EXCEPTIONS 1
+# endif
+
+// If the -AA compile option is used, the compiler defines _HP_NAMESPACE_STD.
+// The -AA option enables the 2.0 standard C++ library. If not used, then
+// we have the old, 1.2.1 C++ library.
+# if defined (_HP_NAMESPACE_STD)
+# if defined (ACE_HAS_STANDARD_CPP_LIBRARY)
+# undef ACE_HAS_STANDARD_CPP_LIBRARY
+# endif
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+# undef ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB
+# endif
+# if defined (RWSTD_NO_NAMESPACE)
+ namespace std {} using namespace std;
+# else
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# endif /* RWSTD_NO_NAMESPACE */
+# else
+# define ACE_USES_OLD_IOSTREAMS
+ // There's no support in ACE's use of numeric_limits for those that
+ // aren't in std::
+# define ACE_LACKS_NUMERIC_LIMITS
+# endif /* _HP_NAMESPACE_STD */
+
+// Compiler implements templates that support typedefs inside of classes
+// used as formal arguments to a template class.
+# define ACE_HAS_TEMPLATE_TYPEDEFS
+
+# define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+
+// Platform lacks streambuf "linebuffered ()".
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF 1
+
+// Lack of (and broken) support for placement operator delete is a known
+// bug by HP, up until aC++ A.03.55.02.
+# if (__HP_aCC < 35502)
+# define ACE_LACKS_PLACEMENT_OPERATOR_DELETE
+# endif /* __HP_aCC < 35502 */
+
+// Compiler's 'new' throws exceptions on failure, regardless of whether or
+// not exception handling is enabled in the compiler options. Fortunately,
+// new(nothrow_t) is offered.
+# define ACE_NEW_THROWS_EXCEPTIONS
+# define ACE_HAS_NEW_NOTHROW
+# define ACE_HAS_NEW_NO_H 1
+
+// Compiler's template mechanism must see source code (i.e., .C files).
+# define ACE_TEMPLATES_REQUIRE_SOURCE
+
+// Compiler supports template specialization.
+# define ACE_HAS_TEMPLATE_SPECIALIZATION
+
+// Compiler doesn't handle 'signed char' correctly (used in ace/IOStream.h)
+# define ACE_LACKS_SIGNED_CHAR
+
+#endif /* __GNUG__, HP */
+
+//*********************************************************************
+//
+// From here down is the compiler-INdependent OS settings.
+//
+//*********************************************************************
+
+// Compiling for HPUX.
+#if !defined (HPUX)
+#define HPUX
+#endif /* HPUX */
+#define HPUX_11
+
+#ifndef _HPUX_SOURCE
+#define _HPUX_SOURCE
+#endif
+
+#include /**/ <sys/stdsyms.h>
+
+// HP-UX is a POSIX-compliant system - see what's available.
+#include "ace/config-posix.h"
+
+// config-posix.h sets up ACE_HAS_AIO_CALLS if the headers define the
+// proper things. In HP-UX 11's case, the AIOCB Proactor works the best
+// overall. If the user hasn't overridden it, select AIOCB.
+#if defined (ACE_HAS_AIO_CALLS)
+# if !defined (ACE_POSIX_AIOCB_PROACTOR) && !defined (ACE_POSIX_SIG_PROACTOR)
+# define ACE_POSIX_AIOCB_PROACTOR
+# endif /* !ACE_HAS_POSIX_AIOCB_PROACTOR && !ACE_POSIX_SIG_PROACTOR */
+#endif /* ACE_HAS_AIO_CALLS */
+
+////////////////////////////////////////////////////////////////////////////
+//
+// General OS information - see README for more details on what they mean
+//
+///////////////////////////////////////////////////////////////////////////
+
+// HP/UX needs to have these addresses in a special range.
+// If this is on a 64-bit model, the default is to use 64-bit addressing.
+// It can also be set so that the mapped region is shareable with 32-bit
+// programs. To enable the 32/64 sharing, comment out the first definition
+// of ACE_DEFAULT_BASE_ADDR and uncomment the two lines after it.
+#if defined (__LP64__)
+# define ACE_DEFAULT_BASE_ADDR ((char *) 0x0000001100000000)
+//# define ACE_DEFAULT_BASE_ADDR ((char *) 0x80000000)
+//# define ACE_OS_EXTRA_MMAP_FLAGS MAP_ADDR32
+
+# define ACE_DEFAULT_BASE_ADDRL (0x0000001100000000)
+//# define ACE_DEFAULT_BASE_ADDRL (0x80000000)
+#else
+# define ACE_DEFAULT_BASE_ADDR ((char *) 0x80000000)
+#endif /* __LP64__ */
+
+// Preprocessor needs some help with data types
+#if defined (__LP64__)
+# define ACE_SIZEOF_LONG 8
+#else
+# define ACE_SIZEOF_LONG 4
+#endif
+
+// Platform can do async I/O (aio_*) (set up in config-posix.h)
+// ... but seems to require this in order to keep from hanging. Needs some
+// investigation, maybe with HP. John Mulhern determined this value
+// empirically. YMMV. If it does vary, set it up in your own config.h which
+// then includes the ACE-supplied config.
+#if !defined (ACE_INFINITE)
+# define ACE_INFINITE 10000000
+#endif
+
+/* Compiler/platform correctly calls init()/fini() for shared libraries. */
+#define ACE_HAS_AUTOMATIC_INIT_FINI 1
+
+// Manually tweak the malloc control block paddings to properly align
+// things.
+#define ACE_MALLOC_PADDING 16
+#define ACE_MALLOC_ALIGN 8
+#define ACE_PI_CONTROL_BLOCK_ALIGN_LONGS 3
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+#define ACE_HAS_SYS_PSTAT_H
+
+// But doesn't have a prototype for syscall()
+#define ACE_LACKS_SYSCALL
+
+// Platform supports POSIX.1b clock_gettime ()
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+
+// Prototypes for both signal() and struct sigaction are consistent.
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Compiler/platform has correctly prototyped header files.
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Compiler/platform has Dirent iterator functions.
+#define ACE_HAS_DIRENT
+
+#define ACE_HAS_VSWPRINTF
+
+// Platform supports getpagesize() call
+#define ACE_HAS_GETPAGESIZE
+// But we define this just to be safe
+#define ACE_PAGE_SIZE 4096
+
+// Can run gperf on this platform (needed for TAO)
+# define ACE_HAS_GPERF
+
+// Optimize ACE_Handle_Set for select().
+# define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// Platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+// At least for 11iv2, lacks perfect filtering.
+#if (HPUX_VERS >= 1123) && !defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING)
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif
+
+/* Platform defines MAP_FAILED as a long constant. */
+#define ACE_HAS_LONG_MAP_FAILED 1
+
+// Platform supports recvmsg and sendmsg.
+#define ACE_HAS_MSG
+
+// Platform's select() has non-const timeval argument
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+// Compiler/platform supports poll().
+#define ACE_HAS_POLL
+
+/* Platform supports "position-independent" features provided by
+ ACE_Based_Pointer<>. */
+#define ACE_HAS_POSITION_INDEPENDENT_POINTERS 1
+
+/* Platform supports POSIX getpwnam_r() function */
+#define ACE_HAS_POSIX_GETPWNAM_R 1
+
+// Platform supports POSIX O_NONBLOCK semantics.
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Platform supports the POSIX struct timespec type
+#define ACE_HAS_POSIX_TIME
+
+/* Platform has pread() and pwrite() support. */
+#define ACE_HAS_P_READ_WRITE 1
+
+/* Platform will recurse infinitely on thread exits from TSS cleanup routines
+ (e.g., AIX) */
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS 1
+
+// Platform supports reentrant functions (all the POSIX *_r functions).
+#define ACE_HAS_REENTRANT_FUNCTIONS
+// ctime_r and asctime_r conform to POSIX.1c (2 param version)
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+
+// Platform offers scandir(), and requires no adjustments for its API.
+#define ACE_HAS_SCANDIR
+
+// HP-UX 11 has reentrant netdb functions. The catch is that the old
+// functions (gethostbyname, etc.) are thread-safe and the _r versions are
+// not used and will be removed at some point. So, define things so
+// the _r versions are not used. This will slow things down a bit due to
+// the extra mutex lock in the ACE_NETDBCALL_RETURN macro, and will be fixed
+// in the future (problem ID P64).
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+
+/* Platform lacks pri_t (e.g., Tandem NonStop UNIX). */
+#define ACE_LACKS_PRI_T 1
+
+// Platform has shm_open
+#define ACE_HAS_SHM_OPEN
+
+// Compiler/platform defines the sig_atomic_t typedef
+#define ACE_HAS_SIG_ATOMIC_T
+
+/* Compiler requires extern "C" functions for signals. */
+#define ACE_HAS_SIG_C_FUNC 1
+
+// Platform's sigaction() function takes const sigaction* as 2nd parameter.
+#define ACE_HAS_SIGACTION_CONSTP2
+
+#define ACE_HAS_SSIZE_T
+
+// Platform supports SVR4 extended signals
+#define ACE_HAS_SIGINFO_T
+
+/* Define to 1 if platform has sigsuspend(). */
+#define ACE_HAS_SIGSUSPEND 1
+
+// Platform doesn't detect a signal out of range unless it's way out of range.
+#define ACE_HAS_SIGISMEMBER_BUG
+
+/* Platform provides socklen_t type, such as Linux with glibc2. */
+#define ACE_HAS_SOCKLEN_T 1
+
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+/* Platform/compiler supports _sys_errlist symbol */
+#define ACE_HAS_SYS_ERRLIST 1
+
+#define ACE_HAS_UALARM
+
+// Platform supports ucontext_t (which is used in the extended signal API).
+#define ACE_HAS_UCONTEXT_T
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Platform/compiler supports void * as second parameter to gettimeofday().
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY
+
+/* Platform requires void * for mmap(). */
+#define ACE_HAS_VOIDPTR_MMAP 1
+
+/* OS/compiler uses void * arg 4 setsockopt() rather than const char * */
+#define ACE_HAS_VOIDPTR_SOCKOPT 1
+
+// Platform supports SVR4 dynamic linking semantics.
+// When used, this requires -ldl on the ACE library link line.
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+// Platform supports the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+/* Define to 1 if platform has the declaration of getrusage(). */
+#define ACE_HAS_GETRUSAGE_PROTOTYPE 1
+
+// Platform has the sigwait function in a header file
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIGTIMEDWAIT
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// accept() is thread-safe
+#define ACE_HAS_THREAD_SAFE_ACCEPT
+
+// Platform lacks a typedef for timespec_t, but has struct timespec
+#define ACE_LACKS_TIMESPEC_T
+
+// dlopen() takes a char* instead of const char*
+#define ACE_HAS_CHARPTR_DL
+
+// lacks setegid and seteuid
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETEUID
+
+#define ACE_LACKS_SUSECONDS_T
+#define ACE_LACKS_SYS_SYSCTL_H
+
+// Shared library name/path components
+#if defined (__ia64)
+# define ACE_DLL_SUFFIX ACE_TEXT (".so")
+#else
+# define ACE_DLL_SUFFIX ACE_TEXT (".sl")
+#endif /* __ia64 */
+#if defined (__LP64__)
+# define ACE_LD_SEARCH_PATH ACE_TEXT ("LD_LIBRARY_PATH")
+#else
+# define ACE_LD_SEARCH_PATH ACE_TEXT ("SHLIB_PATH")
+#endif /* __LP64__ */
+
+#if defined (_INCLUDE__STDC_A1_SOURCE)
+# define ACE_HAS_3_PARAM_WCSTOK
+#endif
+
+#define ACE_HAS_3_PARAM_READDIR_R
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// STREAMS information
+//
+//////////////////////////////////////////////////////////////////////////
+
+// Platform supports STREAMS
+#define ACE_HAS_STREAMS
+// Compiler/platform supports struct strbuf.
+#define ACE_HAS_STRBUF_T
+// But the putmsg signature doesn't have it as const...
+// Well, it really does, but it depends on preprocessor defines.
+#define ACE_LACKS_CONST_STRBUF_PTR
+/* Platform supports TLI timod STREAMS module */
+#define ACE_HAS_TIMOD_H 1
+
+// Platform supports STREAM pipes
+// This is possible, but not by default - need to rebuild the kernel to
+// get them enabled - see pipe(2) and "STREAMS/UX for the HP 9000"
+// #define ACE_HAS_STREAM_PIPES
+
+/////////////////////////////////////////////////////////////////////////
+//
+// TLI/XTI information
+//
+////////////////////////////////////////////////////////////////////////
+
+// Platform supports XTI (includes TLI).
+#define ACE_HAS_XTI
+// HP-UX 11 conforms to the XPG4 spec, which ACE calls broken for the
+// errmsg not being const...
+#define ACE_HAS_BROKEN_T_ERROR
+// The definitions of TCP_NODELAY and TCP_MAXSEG conflict between
+// sys/xti.h and netinet/tcp.h.
+#define ACE_HAS_CONFLICTING_XTI_MACROS
+/* Platform provides <sys/xti.h> header */
+#define ACE_HAS_SYS_XTI_H 1
+
+/////////////////////////////////////////////////////////////////////////
+//
+// Threads information.
+//
+// Use of threads is controlled by the 'threads' argument to make. See
+// include/makeinclude/platform_hpux_aCC.GNU for details. If it's not set,
+// the default is to enable it, since kernel threads are always available
+// on HP-UX 11, as opposed to 10.x where it was optional software.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if defined (ACE_HAS_THREADS)
+# if (ACE_HAS_THREADS == 0)
+# undef ACE_HAS_THREADS
+# endif /* ACE_HAS_THREADS == 0 */
+#else
+# define ACE_HAS_THREADS
+#endif /* ACE_HAS_THREADS */
+
+#if defined (ACE_HAS_THREADS)
+
+# if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+# endif
+
+// HP-UX doesn't define _POSIX_THREADS since it doesn't implement all
+// features (lacks thread priority inheritance and protection), so
+// config-posix.h doesn't get this one...
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_PTHREADS_UNIX98_EXT
+# define ACE_HAS_PTHREAD_CONTINUE
+# define ACE_HAS_PTHREAD_RESUME_NP
+# define ACE_HAS_PTHREAD_SUSPEND
+# define ACE_HAS_RECURSIVE_MUTEXES
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACK
+#endif /* ACE_HAS_THREADS */
+
+#define ACE_HAS_POSIX_SEM
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+// gethostbyaddr does not handle IPv6-mapped-IPv4 addresses
+#define ACE_HAS_BROKEN_GETHOSTBYADDR_V4MAPPED
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-icc-common.h b/ACE/ace/config-icc-common.h
new file mode 100644
index 00000000000..d8e4a856c8c
--- /dev/null
+++ b/ACE/ace/config-icc-common.h
@@ -0,0 +1,114 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifndef ACE_LINUX_ICC_COMMON_H
+#define ACE_LINUX_ICC_COMMON_H
+#include /**/ "ace/pre.h"
+
+# define ACE_HAS_CPLUSPLUS_HEADERS
+# define ACE_HAS_STDCPP_STL_INCLUDES
+# define ACE_HAS_TEMPLATE_TYPEDEFS
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_HAS_TEMPLATE_SPECIALIZATION
+# define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# define ACE_HAS_STRING_CLASS
+
+#if defined (ACE_HAS_CUSTOM_EXPORT_MACROS) && ACE_HAS_CUSTOM_EXPORT_MACROS == 0
+# undef ACE_HAS_CUSTOM_EXPORT_MACROS
+# if defined (ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS)
+# undef ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS
+# endif /* ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS */
+# define ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS 0
+#else
+# ifndef ACE_HAS_CUSTOM_EXPORT_MACROS
+# define ACE_HAS_CUSTOM_EXPORT_MACROS
+# endif /* !ACE_HAS_CUSTOM_EXPORT_MACROS */
+# define ACE_Proper_Export_Flag __attribute__ ((visibility("default")))
+# define ACE_Proper_Import_Flag __attribute__ ((visibility("default")))
+
+# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
+// Sadly, G++ 4.x silently ignores visibility attributes on
+// template instantiations, which breaks singletons.
+// As a workaround, we use the GCC visibility pragmas.
+// And to make them fit in a macro, we use C99's _Pragma()
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17470
+// This has been fixed in GCC 4.1.1 with FC6 but not with SuSE 10.2
+// that gets shipped with GCC 4.1.2 so we assume that with GCC 4.2
+// this will be fixed on the head. With FC6 just set this define yourself
+# ifndef ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS
+# define ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS 1
+# endif
+# endif
+
+# if defined (ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS) && ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS == 1
+# define ACE_EXPORT_SINGLETON_DECLARATION(T) template class ACE_Proper_Export_Flag T
+# define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class ACE_Proper_Export_Flag SINGLETON_TYPE <CLASS, LOCK>;
+# else /* ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS */
+# define ACE_EXPORT_SINGLETON_DECLARATION(T) \
+ _Pragma ("GCC visibility push(default)") \
+ template class T \
+ _Pragma ("GCC visibility pop")
+# define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) \
+ _Pragma ("GCC visibility push(default)") \
+ template class SINGLETON_TYPE<CLASS, LOCK>; \
+ _Pragma ("GCC visibility pop")
+# endif /* ACE_GCC_HAS_TEMPLATE_INSTANTIATION_VISIBILITY_ATTRS */
+
+// Note that the "__extension__" is needed to prevent g++ from issuing
+// an error when using its "-pedantic" command line flag.
+# define ACE_IMPORT_SINGLETON_DECLARATION(T) __extension__ extern template class T
+# define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) __extension__ extern template class SINGLETON_TYPE<CLASS, LOCK>;
+#endif /* ACE_HAS_CUSTOM_EXPORT_MACROS == 0 */
+
+// __EXCEPTIONS is defined with -fexceptions, the egcs default. It
+// is not defined with -fno-exceptions, the ACE default for g++.
+// ACE_HAS_EXCEPTIONS is defined in
+// include/makeinclude/wrapper_macros.GNU, so this really isn't
+// necessary. Just in case . . .
+# if defined (__EXCEPTIONS) && !defined (ACE_HAS_EXCEPTIONS)
+# define ACE_HAS_EXCEPTIONS
+# endif /* __EXCEPTIONS && ! ACE_HAS_EXCEPTIONS */
+
+# if defined (ACE_HAS_EXCEPTIONS)
+# define ACE_NEW_THROWS_EXCEPTIONS
+# endif /* ACE_HAS_EXCEPTIONS */
+
+#if (defined (i386) || defined (__i386__)) && !defined (ACE_SIZEOF_LONG_DOUBLE)
+# define ACE_SIZEOF_LONG_DOUBLE 12
+#endif /* i386 */
+
+#if !defined (__MINGW32__) && (defined (i386) || defined (__i386__))
+ // If running an Intel, assume that it's a Pentium so that
+ // ACE_OS::gethrtime () can use the RDTSC instruction. If running a
+ // 486 or lower, be sure to comment this out. (If not running an
+ // Intel CPU, this #define will not be seen because of the i386
+ // protection, so it can be ignored.)
+# define ACE_HAS_PENTIUM
+#endif /* i386 */
+
+#if (defined (ACE_HAS_PENTIUM) || defined (__amd64__) || defined (__x86_64__))
+# define ACE_HAS_INTEL_ASSEMBLY
+#endif
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+ // We define it with a -D with make depend.
+# define ACE_LACKS_PRAGMA_ONCE
+#endif /* ! ACE_LACKS_PRAGMA_ONCE */
+
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+
+#if (__INTEL_COMPILER >= 910)
+# define ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS
+#endif
+
+#if defined (__ia64)
+# define ACE_HAS_IA64INTRIN_H
+# define ACE_HAS_INTRINSIC_INTERLOCKED
+#else
+# define ACE_HAS_IA32INTRIN_H
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_LINUX_ICC_COMMON_H */
diff --git a/ACE/ace/config-integritySCA.h b/ACE/ace/config-integritySCA.h
new file mode 100644
index 00000000000..5c0a356c46f
--- /dev/null
+++ b/ACE/ace/config-integritySCA.h
@@ -0,0 +1,234 @@
+// -*- C++ -*-
+
+#ifndef ACE_INT_CONFIG_H
+#define ACE_INT_CONFIG_H
+
+/*
+ * This config.h file is for version 4.0.x of the
+ * Integrity RTOS with SCA from Green Hills Software
+ * http://www.ghs.com/products/rtos/integrity.html
+ *
+ * $Id$
+ */
+
+#define ghs
+/* compilation defines */
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETSID
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETUID
+#define ACE_LACKS_SETEUID
+#define ACE_LACKS_GETEUID
+#define ACE_LACKS_GETUID
+#define ACE_LACKS_GETEGID
+#define ACE_LACKS_GETGID
+
+#ifndef ACE_HAS_EXCEPTIONS
+ #define ACE_HAS_EXCEPTIONS
+#endif
+#define ACE_NEW_THROWS_EXCEPTIONS
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+#define ACE_TEMPLATES_REQUIRE_SOURCE 1
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+#define TAO_USE_SEQUENCE_TEMPLATES
+#define ACE_NEEDS_FUNC_DEFINITIONS
+#define _REENTRANT
+#define ACE_MT_SAFE 1
+
+// Compiler/platform has correctly prototyped header files.
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+#define ACE_HAS_SHM_OPEN
+
+/***** Operating System Defines *****/
+
+/***** ANSI defines *****/
+#define ACE_LACKS_TEMPNAM /* believe it or not, this is ANSI C */
+#define ACE_HAS_STRERROR
+
+
+#define ACE_LACKS_SENDMSG
+
+/***** End Stack Defines *****/
+
+
+/* SCA STUFF */
+#if defined(INTEGRITY_VERSION) && (INTEGRITY_VERSION >= 40108)
+#define ACE_HAS_SIG_ATOMIC_T
+#endif /* INTEGRITY_VERSION */
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIGACTION
+#define ACE_HAS_SIGINFO_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_HAS_SIG_C_FUNC
+#define ACE_LACKS_SI_ADDR
+#define ACE_HAS_AIO_CALLS
+
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_DIRENT
+
+#define ACE_HAS_THREADS
+
+#define ACE_HAS_PTHREADS
+/***** End Threading Defines *****/
+
+/***** Hardware Defines *****/
+#define ACE_PAGE_SIZE 4096
+/***** End Hardware Defines *****/
+
+/****** SYSV_IPC STUFF *****/
+#define ACE_LACKS_KEY_T
+
+/****** Posix Defines *****/
+#define ACE_LACKS_WAIT
+#define ACE_LACKS_WAITPID
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_POSIX_SEM
+#define ACE_HAS_STRDUP_EMULATION
+#define ACE_HAS_MSG
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_EXEC
+#define ACE_LACKS_FORK
+#define ACE_LACKS_MKFIFO
+#define ACE_LACKS_MKTEMP
+#define ACE_LACKS_MKSTEMP
+#define ACE_LACKS_MPROTECT
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_LACKS_PIPE
+#define ACE_LACKS_RLIMIT
+#define ACE_LACKS_RECVMSG
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SEMBUF_T
+#define ACE_LACKS_UNIX_DOMAIN_SOCKETS
+#define ACE_LACKS_USER
+#define ACE_LACKS_FILE_FCNTL
+#define ACE_LACKS_FCNTL
+#define ACE_LACKS_UMASK
+#define ACE_LACKS_SEEK
+#define ACE_LACKS_SHARED_MEMORY
+#define ACE_LACKS_MSYNC
+#define ACE_LACKS_PID_STUFF
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_IPC_H
+#define ACE_LACKS_SETGID
+#define ACE_LACKS_PIPE
+#define ACE_LACKS_SYS_PARAM_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_UTSNAME_T
+#define ACE_LACKS_UNAME
+#define ACE_LACKS_UMASK
+#define ACE_LACKS_ISATTY
+#define ACE_LACKS_GETOPT
+#define ACE_LACKS_STRCASECMP
+#define ACE_LACKS_TRUNCATE
+#define ACE_LACKS_PWD_FUNCTIONS
+#define ACE_LACKS_UNIX_SIGNALS
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_PUTENV
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+#define ACE_LACKS_SETSCHED
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_WRITEV
+#define ACE_LACKS_READV
+#define ACE_LACKS_SYSCONF
+#define ACE_LACKS_GETOPT
+/* below refers to fcntl style locking */
+#define ACE_LACKS_FILELOCKS
+
+#define ACE_LACKS_REALPATH
+#define ACE_HAS_CONST_CHAR_SWAB
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+/***** Not tied to standards AFAIK ****/
+#define ACE_LACKS_MADVISE /* paging optimization not needed with INTEGRITY */
+#define ACE_LACKS_MALLOC_H /* netbsd's just includes stdlib.h */
+#define ACE_LACKS_MEMORY_H /* netbsd's just includes string.h */
+#define ACE_LACKS_INTTYPES_H
+#define ACE_LACKS_SYS_RESOURCE_H
+#define ACE_LACKS_SYS_WAIT_H
+#define ACE_LACKS_SEARCH_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_PWD_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_DLFCN_H
+#define ACE_LACKS_REGEX_H
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_TERMIOS_H
+
+/***** STUFF INTEGRITY 4.0.8 APPEARS TO SUPPORT ****/
+/* note, possibly untested with ace */
+
+/***** TAO STUFF ****/
+#define TAO_USE_DOTTED_DECIMAL_ADDRESSES 1
+
+#include <INTEGRITY.h>
+
+#include <time.h>
+
+typedef void (*__sighandler_t)(int);
+
+extern "C"
+{
+ inline int isatty(int) { return 0; }
+}
+
+#ifdef ppc
+#define ACE_HAS_POWERPC_TIMER
+#endif
+
+/* MIKEC Addtions */
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#include <sys/uio.h> // needed to define iovec
+#define ACE_LACKS_READLINK
+#define ACE_LACKS_GETPPID
+#define NSIG (SIGRTMAX+1)
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#define ACE_USE_RCSID 0
+#define ACE_LACKS_CUSERID
+#define ACE_NEEDS_HUGE_THREAD_STACKSIZE 0x5000
+#define fileno(file) ((file)->io_channel) //Hack to get Svc_Conf_l.cpp compiled
+#define ACE_DEFAULT_THREAD_PRIORITY 127
+#define PRI_FIFO_MIN 1
+#define PRI_FIFO_MAX 127
+#define ACE_THR_PRI_FIFO_DEF 127
+#define PRI_RR_MIN 1
+#define PRI_RR_MAX 127
+#define ACE_THR_PRI_RR_DEF 127
+#define PRI_OTHER_MIN 1
+#define PRI_OTHER_MAX 127
+#define ACE_THR_PRI_OTHER_DEF 127
+#define ACE_PTHREAD_RETURN_ON_EXIT
+#undef ACE_LACKS_UNLINK
+
+#define ACE_HAS_TIMED_MESSAGE_BLOCKS
+
+extern "C" {
+int unlink(const char *);
+}
+
+#define ACE_LACKS_SETSID
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY
+#define ACE_LACKS_UNIX_SYSLOG
+#define ACE_LACKS_TELLDIR
+#define ACE_LACKS_SEEKDIR
+#define ACE_LACKS_GETHOSTENT
+
+
+/* end MIKEC Addtions */
+
+// Hack to avoid ensure that things defined in ind_io.h
+// have the right linkage
+#include <unistd.h>
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-irix6.5.x-sgic++.h b/ACE/ace/config-irix6.5.x-sgic++.h
new file mode 100644
index 00000000000..d3fada546a2
--- /dev/null
+++ b/ACE/ace/config-irix6.5.x-sgic++.h
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+// $Id$
+
+// Use this file for IRIX 6.5.x
+
+#ifndef ACE_CONFIG_IRIX65X_H
+#define ACE_CONFIG_IRIX65X_H
+#include /**/ "ace/pre.h"
+
+// Include IRIX 6.[234] configuration
+#include "ace/config-irix6.x-sgic++.h"
+
+// Irix 6.5 man pages show that they exist
+#undef ACE_LACKS_CONDATTR_PSHARED
+#undef ACE_LACKS_MUTEXATTR_PSHARED
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_IRIX65X_H */
diff --git a/ACE/ace/config-irix6.x-common.h b/ACE/ace/config-irix6.x-common.h
new file mode 100644
index 00000000000..72629881ec7
--- /dev/null
+++ b/ACE/ace/config-irix6.x-common.h
@@ -0,0 +1,256 @@
+/* -*- C++ -*- */
+//
+// $Id$
+//
+// This file contains the common configuration options for both
+// SGI/MIPSPro C++ and g++ under IRIX 6.X
+//
+// For IRIX 6.2 there are several patches that should be applied to
+// get reliable operation with multi-threading and exceptions.
+// Specifically you should get a reasonable current IRIX, Compiler
+// and POSIX patch-sets.
+
+// For IRIX 6.[34] it's less critical, but it's still recommended
+// that you apply the applicable patch-sets (IRIX and Compiler I believe).
+
+// These patches are updated frequently, so you should ask your support
+// contact or search SGI's web site (http://www.sgi.com) for the latest
+// version.
+
+// Use this file for IRIX 6.[234] if you have the pthreads patches
+// installed.
+
+#ifndef ACE_CONFIG_IRIX6X_COMMON_H
+
+#ifndef IRIX6
+# define IRIX6
+#endif
+
+#if ! defined(ACE_CONFIG_H)
+#error "This file may only be included by config-irix6.x-sgic++.h, config-irix6.x-kcc.h or config-irix6.x-g++.h"
+#endif
+
+// The Irix 6.x float.h doesn't allow us to distinguish between a
+// double and a long double. So, we have to hard-code this. Thanks
+// to Bob Laferriere <laferrie@gsao.med.ge.com> for figuring it out.
+#if defined (_MIPS_SIM) /* 6.X System */
+# include <sgidefs.h>
+# if defined (__GNUC__)
+# define ACE_SIZEOF_LONG_DOUBLE 16
+# elif defined (_MIPS_SIM_NABI32) && (_MIPS_SIM == _MIPS_SIM_NABI32)
+# define ACE_SIZEOF_LONG_DOUBLE 16
+# elif defined (_MIPS_SIM_ABI32) && (_MIPS_SIM == _MIPS_SIM_ABI32)
+# define ACE_SIZEOF_LONG_DOUBLE 8
+# elif defined (_MIPS_SIM_ABI64) && (_MIPS_SIM == _MIPS_SIM_ABI64)
+# define ACE_SIZEOF_LONG_DOUBLE 16
+# elif !defined (ACE_SIZEOF_LONG_DOUBLE)
+# define ACE_SIZEOF_LONG_DOUBLE 8
+# endif
+#else
+# define ACE_SIZEOF_LONG_DOUBLE 8 /* 5.3 System */
+#endif
+
+// petern, Next part of it:
+
+// Platform supports getpagesize() call.
+#define ACE_HAS_GETPAGESIZE
+
+// Platform has no implementation of pthread_condattr_setpshared(),
+// even though it supports pthreads! (like Irix 6.2)
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_MUTEXATTR_PSHARED
+
+#define ACE_LACKS_SUSECONDS_T
+
+// Platform/compiler has the sigwait(2) prototype
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Platform requires void * for mmap().
+#define ACE_HAS_VOIDPTR_MMAP
+
+// Platform supports recvmsg and sendmsg.
+#define ACE_HAS_MSG
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+// Compiler/platform supports alloca()
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform has <alloca.h>
+#define ACE_HAS_ALLOCA_H
+
+// Irix needs to define bzero() in this odd file <bstring.h>
+#define ACE_HAS_BSTRING
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+// Platform supports POSIX O_NONBLOCK semantics.
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Compiler/platform has correctly prototyped header files.
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Platform contains <poll.h>.
+#define ACE_HAS_POLL
+
+// Platform supports the /proc file system.
+#define ACE_HAS_PROC_FS
+
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Platform supports SVR4 extended signals.
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_UCONTEXT_T
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Platform supports STREAMS.
+#define ACE_HAS_STREAMS
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform supports struct strbuf.
+#define ACE_HAS_STRBUF_T
+
+// Compiler/platform supports SVR4 dynamic linking semantics.
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Compiler/platform defines a union semun for SysV shared memory.
+#define ACE_HAS_SEMUN
+
+// Platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+#ifdef ACE_LACKS_PERFECT_MULTICAST_FILTERING
+ #undef ACE_LACKS_PERFECT_MULTICAST_FILTERING
+#endif
+#define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+
+//**************************************************************
+// Not so sure how next lines should look like
+
+// Platform supports POSIX timers via timestruc_t.
+#define ACE_HAS_POSIX_TIME
+
+//**************************************************************
+
+// IRIX 6.4 and below do not support reentrant netdb functions
+// (getprotobyname_r, getprotobynumber_r, gethostbyaddr_r,
+// gethostbyname_r, getservbyname_r).
+#if (ACE_IRIX_VERS <= 64) && !defined (ACE_HAS_NETDB_REENTRANT_FUNCTIONS)
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#endif /* ACE_HAS_NETDB_REENTRANT_FUNCTIONS */
+
+#define ACE_HAS_DIRENT
+// Unless the thread enabled version is used the readdir_r interface
+// does not get defined in IRIX 6.2
+#define ACE_LACKS_READDIR_R
+#define ACE_LACKS_RWLOCK_T
+
+#define ACE_HAS_GPERF
+
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_BROKEN_DGRAM_SENDV
+
+#define ACE_LACKS_PLACEMENT_OPERATOR_DELETE
+#define ACE_PI_CONTROL_BLOCK_ALIGN_LONGS 2
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+// IRIX 6.5 supports AIO
+#define ACE_HAS_AIO_CALLS
+#define ACE_POSIX_AIOCB_PROACTOR
+#define ACE_HAS_SGIDLADD
+#define ACE_HAS_P_READ_WRITE
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+#define ACE_LACKS_STDINT_H
+#define ACE_HAS_SYSENT_H
+#define ACE_HAS_SYSINFO
+
+// Platform has support for multi-byte character support compliant
+// with the XPG4 Worldwide Portability Interface wide-character
+// classification.
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+// We need to setup a very high address or Naming_Test won't run.
+#define ACE_DEFAULT_BASE_ADDR ((char *) (1024U * 1024 * 1024))
+
+#define ACE_LACKS_SIGNED_CHAR
+
+// Platform supports reentrant functions (i.e., all the POSIX *_r
+// functions).
+#define ACE_HAS_REENTRANT_FUNCTIONS
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// Platform does not support reentrant password file accessor functiions.
+#define ACE_LACKS_PWD_REENTRANT_FUNCTIONS
+
+// uses ctime_r & asctime_r with only two parameters vs. three
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+
+// Prototypes for both signal() and struct sigaction are consistent.
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+#define ACE_HAS_UALARM
+
+// Scheduling functions are declared in <sched.h>
+#define ACE_NEEDS_SCHED_H
+
+// Compile using multi-thread libraries by default
+#if !defined (ACE_MT_SAFE)
+ #define ACE_MT_SAFE 1
+#endif /* ACE_MT_SAFE */
+
+#if (ACE_MT_SAFE != 0)
+
+// Add threading support
+
+#define ACE_HAS_IRIX62_THREADS
+
+// Needed for the threading stuff?
+#include /**/ <task.h>
+#define PTHREAD_MIN_PRIORITY PX_PRIO_MIN
+#define PTHREAD_MAX_PRIORITY PX_PRIO_MAX
+
+// ACE supports threads.
+#define ACE_HAS_THREADS
+
+// Platform has no implementation of pthread_condattr_setpshared(),
+// even though it supports pthreads! (like Irix 6.2)
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_MUTEXATTR_PSHARED
+
+// IRIX 6.2 supports a variant of POSIX Pthreads, supposedly POSIX 1c
+#define ACE_HAS_PTHREADS
+
+// Compiler/platform has thread-specific storage
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+// The pthread_cond_timedwait call does not reset the timer.
+#define ACE_LACKS_COND_TIMEDWAIT_RESET 1
+
+// When threads are enabled READDIR_R is supported on IRIX.
+#undef ACE_LACKS_READDIR_R
+
+#endif /* (ACE_MT_SAFE == 0) */
+
+
+#endif /* ACE_CONFIG_IRIX6X_COMMON_H */
diff --git a/ACE/ace/config-irix6.x-g++.h b/ACE/ace/config-irix6.x-g++.h
new file mode 100644
index 00000000000..69455f27120
--- /dev/null
+++ b/ACE/ace/config-irix6.x-g++.h
@@ -0,0 +1,23 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for the SGI
+// Indigo2EX running Irix 6.2 platform using the GNU C++ Compiler
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+// config-g++-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+// this must appear before its #include.
+#define ACE_HAS_STRING_CLASS
+
+#include "ace/config-g++-common.h"
+#include "ace/config-irix6.x-common.h"
+
+// Denotes that GNU has cstring.h as standard
+// which redefines memchr()
+#define ACE_HAS_GNU_CSTRING_H
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-irix6.x-sgic++.h b/ACE/ace/config-irix6.x-sgic++.h
new file mode 100644
index 00000000000..12dccafd5d5
--- /dev/null
+++ b/ACE/ace/config-irix6.x-sgic++.h
@@ -0,0 +1,38 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Use this file for IRIX 6.[234] if you have the pthreads patches
+// installed.
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#include "ace/config-irix6.x-common.h"
+
+// This is the config file for IRIX 6.2, 6.4 and hopefully 6.3, using
+// the SGI C++ compiler (7.1 or higher).
+
+// The following three should be enabled/disabled together.
+#if _COMPILER_VERSION >= 720
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+#else
+#define ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA
+#endif /* _COMPILER_VERSION >= 720 */
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+#define ACE_NEEDS_FUNC_DEFINITIONS
+
+// Platform supports STREAM pipes (note that this is disabled by
+// default, see the manual page on pipe(2) to find out how to enable
+// it).
+// #define ACE_HAS_STREAM_PIPES
+
+#if defined (_COMPILER_VERSION)
+# define ACE_CC_NAME ACE_TEXT ("SGI/MIPSPro")
+# define ACE_CC_MAJOR_VERSION (_COMPILER_VERSION / 100)
+# define ACE_CC_MINOR_VERSION (_COMPILER_VERSION % 100)
+# define ACE_CC_BETA_VERSION (0)
+#endif /* _COMPILER_VERSION */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-linux-common.h b/ACE/ace/config-linux-common.h
new file mode 100644
index 00000000000..19943bb21e7
--- /dev/null
+++ b/ACE/ace/config-linux-common.h
@@ -0,0 +1,442 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Do not use this configuration file directly since it's designed to
+// be included by another, specific configuration file, such as
+// config-linux.h. It provides config information common to all Linux
+// platforms. It automatically determines the CPU architecture,
+// compiler (g++ or egcs), and libc (libc5 or glibc), and configures
+// based on those.
+
+#ifndef ACE_LINUX_COMMON_H
+#define ACE_LINUX_COMMON_H
+#include /**/ "ace/pre.h"
+
+#define ACE_HAS_BYTESEX_H
+
+#if ! defined (__ACE_INLINE__)
+#define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// Needed to differentiate between libc 5 and libc 6 (aka glibc).
+#include <features.h>
+
+#if (defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 500)
+# define ACE_HAS_PTHREADS_UNIX98_EXT
+#endif /* _XOPEN_SOURCE - 0 >= 500 */
+
+#if !defined (ACE_LACKS_LINUX_NPTL)
+
+# include "ace/config-posix.h"
+
+ // Temporary fix because NPTL kernels do have shm_open but there is a problem
+ // with shm_open/shm_unlink pairing in ACE which needs to be fixed when I have time.
+# if defined (ACE_HAS_SHM_OPEN)
+# undef ACE_HAS_SHM_OPEN
+# endif /* ACE_HAS_SHM_OPEN */
+
+# if defined (ACE_USES_FIFO_SEM)
+ // Don't use this for Linux NPTL since this has complete
+ // POSIX semaphores which are more efficient
+# undef ACE_USES_FIFO_SEM
+# endif /* ACE_USES_FIFO_SEM */
+
+# if defined (ACE_HAS_POSIX_SEM)
+ // Linux NPTL may not define the right POSIX macro
+ // but they have the actual runtime support for this stuff
+# if !defined (ACE_HAS_POSIX_SEM_TIMEOUT) && (((_POSIX_C_SOURCE - 0) >= 200112L) || (_XOPEN_SOURCE >= 600))
+# define ACE_HAS_POSIX_SEM_TIMEOUT
+# endif /* !ACE_HAS_POSIX_SEM_TIMEOUT && (((_POSIX_C_SOURCE - 0) >= 200112L) || (_XOPEN_SOURCE >= 600)) */
+# endif /* ACE_HAS_POSIX_SEM */
+#endif /* !ACE_LACKS_LINUX_NPTL */
+
+// First the machine specific part
+
+#if defined (__powerpc__)
+# if !defined (ACE_DEFAULT_BASE_ADDR)
+# define ACE_DEFAULT_BASE_ADDR ((char *) 0x40000000)
+# endif /* ! ACE_DEFAULT_BASE_ADDR */
+#elif defined (__ia64) || defined (__x86_64__)
+# if !defined (ACE_DEFAULT_BASE_ADDR)
+// Zero base address should work fine for Linux of IA-64: it just lets
+// the kernel to choose the right value.
+# define ACE_DEFAULT_BASE_ADDR ((char *) 0x0000000000000000)
+# endif /* ! ACE_DEFAULT_BASE_ADDR */
+#endif /* ! __powerpc__ && ! __ia64 */
+
+// Then glibc/libc5 specific parts
+
+#if defined(__GLIBC__)
+# if (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
+# define ACE_HAS_NONCONST_SETRLIMIT
+# endif
+# if (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 3)
+# define ACE_HAS_RUSAGE_WHO_ENUM enum __rusage_who
+# define ACE_HAS_RLIMIT_RESOURCE_ENUM enum __rlimit_resource
+# endif
+# define ACE_HAS_SOCKLEN_T
+# define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+
+ // glibc defines both of these, used in OS_String.
+# if defined (_GNU_SOURCE)
+# define ACE_HAS_STRNLEN
+# define ACE_HAS_WCSNLEN
+
+ // This is probably not a 100%-sure-fire check... Red Hat Linux 9
+ // and Enterprise Linux 3 and up have a new kernel that can send signals
+ // across threads. This was not possible prior because there was no real
+ // difference between a process and a thread. With this, the
+ // ACE_POSIX_SIG_Proactor is the only chance of getting asynch I/O working.
+ // There are restrictions, such as all socket operations being silently
+ // converted to synchronous by the kernel, that make aio a non-starter
+ // for most Linux platforms at this time. But we'll start to crawl...
+# define ACE_POSIX_SIG_PROACTOR
+# endif
+
+ // To avoid the strangeness with Linux's ::select (), which modifies
+ // its timeout argument, use ::poll () instead.
+# define ACE_HAS_POLL
+
+// Don't define _XOPEN_SOURCE and _XOPEN_SOURCE_EXTENDED in ACE to make
+// getpgid() prototype visible. ACE shouldn't depend on feature test
+// macros to make prototypes visible.
+# define ACE_LACKS_GETPGID_PROTOTYPE
+
+// @note the following defines are necessary with glibc 2.0 (0.961212-5)
+// on Alpha. I assume that they're necessary on Intel as well,
+// but that may depend on the version of glibc that is used.
+//# define ACE_HAS_DLFCN_H_BROKEN_EXTERN_C
+# define ACE_HAS_VOIDPTR_SOCKOPT
+
+// Don't define _POSIX_SOURCE in ACE to make strtok() prototype
+// visible. ACE shouldn't depend on feature test macros to make
+// prototypes visible.
+# define ACE_LACKS_STRTOK_R_PROTOTYPE
+// @note end of glibc 2.0 (0.961212-5)-specific configuration.
+
+# if __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1
+ // These were suggested by Robert Hanzlik <robi@codalan.cz> to get
+ // ACE to compile on Linux using glibc 2.1 and libg++/gcc 2.8.
+# undef ACE_HAS_BYTESEX_H
+# define ACE_HAS_SIGINFO_T
+# define ACE_LACKS_SIGINFO_H
+# define ACE_HAS_UCONTEXT_T
+
+ // Pre-glibc (RedHat 5.2) doesn't have sigtimedwait.
+# define ACE_HAS_SIGTIMEDWAIT
+# endif /* __GLIBC__ 2.1+ */
+#else /* ! __GLIBC__ */
+ // Fixes a problem with some non-glibc versions of Linux...
+# define ACE_LACKS_MADVISE
+# define ACE_LACKS_MSG_ACCRIGHTS
+#endif /* ! __GLIBC__ */
+
+// Don't define _LARGEFILE64_SOURCE in ACE to make llseek() or
+// lseek64() prototype visible. ACE shouldn't depend on feature test
+// macros to make prototypes visible.
+#if __GLIBC__ > 1
+# if __GLIBC_MINOR__ == 0
+# define ACE_HAS_LLSEEK
+# define ACE_LACKS_LLSEEK_PROTOTYPE
+# else /* __GLIBC_MINOR__ > 0 */
+# define ACE_HAS_LSEEK64
+# define ACE_LACKS_LSEEK64_PROTOTYPE
+# endif
+#endif /* __GLIBC__ > 1 */
+
+#if __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1
+# define ACE_HAS_P_READ_WRITE
+# define ACE_LACKS_PREAD_PROTOTYPE
+// Use ACE's alternate cuserid() implementation since the use of the
+// system cuserid() is discouraged.
+# define ACE_HAS_ALT_CUSERID
+#endif /* __GLIBC__ > 1 && __GLIBC_MINOR__ >= 0 */
+
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
+# define ACE_HAS_ISASTREAM_PROTOTYPE
+# define ACE_HAS_PTHREAD_SIGMASK_PROTOTYPE
+# define ACE_HAS_CPU_SET_T
+#endif /* __GLIBC__ > 2 || __GLIBC__ === 2 && __GLIBC_MINOR__ >= 3) */
+
+// Then the compiler specific parts
+
+#if defined (__INTEL_COMPILER)
+# include "ace/config-icc-common.h"
+#elif defined (__GNUG__)
+ // config-g++-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+ // this must appear before its #include.
+# define ACE_HAS_STRING_CLASS
+# include "ace/config-g++-common.h"
+#define ACE_CC_NAME ACE_TEXT ("g++")
+#define ACE_CC_MAJOR_VERSION __GNUC__
+#define ACE_CC_MINOR_VERSION __GNUC_MINOR__
+//#define ACE_CC_BETA_VERSION 0 /* ??? */
+#elif defined (__DECCXX)
+# define ACE_CONFIG_INCLUDE_CXX_COMMON
+# include "ace/config-cxx-common.h"
+#elif defined (__BORLANDC__)
+# undef ACE_HAS_LLSEEK
+# undef ACE_HAS_LSEEK64
+# undef ACE_LACKS_LLSEEK_PROTOTYPE
+# undef ACE_LACKS_LSEEK64_PROTOTYPE
+# include "ace/config-borland-common.h"
+#elif defined (__SUNCC_PRO)
+# include "ace/config-suncc-common.h"
+#elif defined (__PGI)
+// Portable group compiler
+# define ACE_HAS_CPLUSPLUS_HEADERS
+# define ACE_HAS_STDCPP_STL_INCLUDES
+# define ACE_HAS_TEMPLATE_TYPEDEFS
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# define ACE_LACKS_SWAB
+#elif defined (__GNUC__)
+/**
+ * GNU C compiler.
+ *
+ * We need to recognize the GNU C compiler since TAO has at least one
+ * C source header and file
+ * (TAO/orbsvcs/orbsvcs/SSLIOP/params_dup.{h,c}) that may indirectly
+ * include this
+ */
+#else /* ! __GNUG__ && !__DECCXX && !__INTEL_COMPILER && !__BORLANDC__ && !__PGI */
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler in ace/config-linux-common.h
+# endif /* __cplusplus */
+#endif /* ! __GNUG__*/
+
+// Completely common part :-)
+
+// Platform/compiler has the sigwait(2) prototype
+# define ACE_HAS_SIGWAIT
+
+# define ACE_HAS_SIGSUSPEND
+
+# define ACE_HAS_UALARM
+
+#if __GLIBC__ >= 2
+#ifndef ACE_HAS_POSIX_REALTIME_SIGNALS
+#define ACE_HAS_POSIX_REALTIME_SIGNALS
+#endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
+
+#ifndef ACE_HAS_AIO_CALLS
+#define ACE_HAS_AIO_CALLS
+#endif /* ACE_HAS_AIO_CALLS */
+#endif
+
+#if __GLIBC__ >= 2
+// glibc 2 and higher has wchar support
+# define ACE_HAS_XPG4_MULTIBYTE_CHAR
+# define ACE_HAS_VFWPRINTF
+#endif
+
+#if __GLIBC__ < 2
+// These are present in glibc 2 and higher
+# define ACE_LACKS_WCSTOK
+# define ACE_LACKS_WCSDUP_PROTOTYPE
+#endif /* __GLIBC__ < 2 */
+
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+
+#if __GLIBC__ >= 2
+# define ACE_HAS_3_PARAM_WCSTOK
+#endif
+
+#define ACE_HAS_3_PARAM_READDIR_R
+
+#if !defined (ACE_DEFAULT_BASE_ADDR)
+# define ACE_DEFAULT_BASE_ADDR ((char *) 0x80000000)
+#endif /* ! ACE_DEFAULT_BASE_ADDR */
+
+// Compiler/platform supports alloca().
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform has <alloca.h>
+#define ACE_HAS_ALLOCA_H
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+#define ACE_HAS_GETRUSAGE_PROTOTYPE
+
+#define ACE_HAS_BYTESWAP_H
+#define ACE_HAS_BSWAP_16
+#define ACE_HAS_BSWAP_32
+
+#if defined __GNUC__ && __GNUC__ >= 2
+# define ACE_HAS_BSWAP_64
+#endif
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// ONLY define this if you have config'd multicast into a 2.0.34 or
+// prior kernel. It is enabled by default in 2.0.35 kernels.
+#if !defined (ACE_HAS_IP_MULTICAST)
+# define ACE_HAS_IP_MULTICAST
+#endif /* ! ACE_HAS_IP_MULTICAST */
+
+// At least for IPv4, Linux lacks perfect filtering.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
+#define ACE_HAS_BIG_FD_SET
+
+// Linux defines struct msghdr in /usr/include/socket.h
+#define ACE_HAS_MSG
+
+// Linux "improved" the interface to select() so that it modifies
+// the struct timeval to reflect the amount of time not slept
+// (see NOTES in Linux's select(2) man page).
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+#define ACE_DEFAULT_MAX_SOCKET_BUFSIZ 65535
+
+#define ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE 1
+
+#define ACE_HAS_GETPAGESIZE 1
+
+#if (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2)
+// glibc supports wchar, but lacks fgetwc and ungetwc
+# define ACE_LACKS_FGETWC
+# define ACE_HAS_NONCONST_MSGSND
+# define ACE_LACKS_STRNLEN_PROTOTYPE
+#endif
+
+// glibc requires _XOPEN_SOURCE_EXTENDED to make this prototype
+// visible, so force ACE to declare one. Yuk!
+#ifndef _XOPEN_SOURCE_EXTENDED
+# define ACE_LACKS_MKSTEMP_PROTOTYPE
+#endif /* !_XOPEN_SOURCE_EXTENDED */
+
+// Platform defines struct timespec but not timespec_t
+#define ACE_LACKS_TIMESPEC_T
+
+// Platform supplies scandir()
+#define ACE_HAS_SCANDIR
+// Although the scandir man page says otherwise, this setting is correct.
+#define ACE_SCANDIR_CMP_USES_CONST_VOIDPTR
+
+#define ACE_HAS_STRBUF_T
+
+// A conflict appears when including both <ucontext.h> and
+// <sys/procfs.h> with recent glibc headers.
+//#define ACE_HAS_PROC_FS
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+// Platform/compiler supports global timezone variable.
+#define ACE_HAS_TIMEZONE
+
+// Platform/compiler supports void * as second parameter to gettimeofday().
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Don't define _XOPEN_SOURCE in ACE to make strptime() prototype
+// visible. ACE shouldn't depend on feature test macros to make
+// prototypes visible.
+#define ACE_LACKS_STRPTIME_PROTOTYPE
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Compiler/platform defines a union semun for SysV shared memory.
+#define ACE_HAS_SEMUN
+
+#define ACE_HAS_POSIX_TIME
+
+#define ACE_HAS_GPERF
+
+#define ACE_HAS_DIRENT
+
+#if defined (__ia64) || defined(__alpha) || defined (__x86_64__)
+// On 64 bit platforms, the "long" type is 64-bits. Override the
+// default 32-bit platform-specific format specifiers appropriately.
+# define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+# define ACE_SSIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%ld")
+# define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+#endif /* __ia64 */
+
+#define ACE_SIZEOF_WCHAR 4
+
+#define ACE_LACKS_GETIPNODEBYADDR
+#define ACE_LACKS_GETIPNODEBYNAME
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+// Linux implements sendfile().
+#define ACE_HAS_SENDFILE
+
+#define ACE_HAS_VOIDPTR_MMAP
+
+#if !defined (ACE_AS_STATIC_LIBS)
+# define ACE_HAS_BROKEN_THREAD_KEYFREE
+#endif
+
+#if defined (ACE_LACKS_NETWORKING)
+# include "ace/config-posix-nonetworking.h"
+#else
+# define ACE_HAS_NETLINK
+# define ACE_HAS_GETIFADDRS
+#endif
+
+#if !defined (ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO)
+// Detect if getsockname() and getpeername() returns random values in
+// the sockaddr_in::sin_zero field by evaluation of the kernel
+// version. Since version 2.5.47 this problem is fixed.
+# if !defined (ACE_LACKS_LINUX_VERSION_H)
+# include <linux/version.h>
+# endif /* !ACE_LACKS_LINUX_VERSION_H */
+# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,47))
+# define ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO 0
+# else
+# define ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO 1
+# endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,47)) */
+#endif /* ACE_GETNAME_RETURNS_RANDOM_SIN_ZERO */
+
+#if defined (ACE_HAS_EVENT_POLL)
+// The sys_epoll interface was introduced in Linux kernel 2.5.45.
+// Don't support backported versions since they appear to be buggy.
+// The obsolete ioctl()-based interface is no longer supported.
+#if 0
+// linux/version.h may not be accurate. It's not for Fedora Core 2...
+# if !defined (ACE_LACKS_LINUX_VERSION_H)
+# include <linux/version.h>
+# endif /* !ACE_LACKS_LINUX_VERSION_H */
+# if (LINUX_VERSION_CODE < KERNEL_VERSION (2,5,45))
+# undef ACE_HAS_EVENT_POLL
+# error Disabling Linux epoll support. Kernel used in C library is too old.
+# error Linux kernel 2.5.45 or better is required.
+# endif /* LINUX_VERSION_CODE < KERNEL_VERSION (2,5,45) */
+#endif /* ACE_HAS_EVENT_POLL */
+#endif
+
+#if !defined (ACE_HAS_EVENT_POLL) && !defined (ACE_HAS_DEV_POLL)
+# if !defined (ACE_LACKS_LINUX_VERSION_H)
+# include <linux/version.h>
+# endif /* !ACE_LACKS_LINUX_VERSION_H */
+# if (LINUX_VERSION_CODE > KERNEL_VERSION (2,6,0))
+# define ACE_HAS_EVENT_POLL
+# endif
+#endif
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_LINUX_COMMON_H */
diff --git a/ACE/ace/config-linux.h b/ACE/ace/config-linux.h
new file mode 100644
index 00000000000..7f6510f7d05
--- /dev/null
+++ b/ACE/ace/config-linux.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// The following configuration file is designed to work for Linux
+// platforms using GNU C++.
+
+#ifndef ACE_CONFIG_LINUX_H
+#define ACE_CONFIG_LINUX_H
+#include /**/ "ace/pre.h"
+
+#define ACE_PLATFORM_CONFIG config-linux.h
+
+#include "ace/config-linux-common.h"
+
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+#define ACE_HAS_DLSYM_SEGFAULT_ON_INVALID_HANDLE
+
+#if !defined (ACE_MT_SAFE)
+#define ACE_MT_SAFE 1 // JCEJ 12/22/96 #1
+#endif
+
+#if ACE_MT_SAFE
+// Yes, we do have threads.
+#define ACE_HAS_THREADS
+// And they're even POSIX pthreads (LinuxThreads implementation)
+#define ACE_HAS_PTHREADS
+
+// On linux this is part of pthreads
+# if (defined _POSIX_C_SOURCE && (_POSIX_C_SOURCE - 0) >= 199309L)
+# if !defined (ACE_HAS_CLOCK_GETTIME)
+# if !defined(__PGI)
+# define ACE_HAS_CLOCK_GETTIME
+# endif /* __PGI */
+# define ACE_HAS_CLOCK_SETTIME
+# endif /* !ACE_HAS_CLOCK_GETTIME */
+# endif /* _POSIX_C_SOURCE >= 199309L */
+
+#if !defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+# define ACE_LACKS_RWLOCK_T
+#else
+# define ACE_HAS_RECURSIVE_MUTEXES
+#endif /* !ACE_HAS_PTHREADS_UNIX98_EXT */
+
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE // jcej 12/22/96 #2
+
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS // JCEJ 1/7-8/96
+
+#if defined(__GLIBC__)
+// Platform supports reentrant functions (i.e., all the POSIX *_r
+// functions).
+#define ACE_HAS_REENTRANT_FUNCTIONS
+
+#if (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
+ // Older versions of glibc lacked reentrant netdb functions
+# define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+
+ // glibc < 2.1 lacks pthread_attr_setstacksize()
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE
+#endif /* (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1) */
+
+// uses ctime_r & asctime_r with only two parameters vs. three
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+#endif
+
+#else
+// AIO support pulls in the rt library, which pulls in the pthread
+// library. Disable AIO in single-threaded builds.
+# undef ACE_HAS_AIO_CALLS
+#endif /* ACE_MT_SAFE */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONFIG_LINUX_H */
diff --git a/ACE/ace/config-lite.h b/ACE/ace/config-lite.h
new file mode 100644
index 00000000000..0835426e27c
--- /dev/null
+++ b/ACE/ace/config-lite.h
@@ -0,0 +1,164 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file config-lite.h
+ *
+ * $Id$
+ *
+ * @author (Originally in OS.h)Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * This file contains the contents of the old config-all.h in order to
+ * avoid a circular dependency problem caused by some of the new
+ * includes added to config-all.h, e.g., OS_main.h.
+ */
+//==========================================================================
+
+#ifndef ACE_CONFIG_LITE_H
+#define ACE_CONFIG_LITE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-macros.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Empty ACE_OS namespace to help identify compiler errors more
+// easily. -- @@ Do we really need this?
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+namespace ACE_OS {}
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// ============================================================================
+// UNICODE macros (to be added later)
+// ============================================================================
+
+// Get the unicode (i.e. ACE_TCHAR) defines
+# include "ace/ace_wchar.h"
+
+// ============================================================================
+// at_exit declarations
+// ============================================================================
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Marker for cleanup, used by ACE_Exit_Info.
+extern int ace_exit_hook_marker;
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// For use by <ACE_OS::exit>.
+extern "C"
+{
+ typedef void (*ACE_EXIT_HOOK) (void);
+}
+
+// Signature for registering a cleanup function that is used by the
+// ACE_Object_Manager and the ACE_Thread_Manager.
+# if defined (ACE_HAS_SIG_C_FUNC)
+extern "C" {
+# endif /* ACE_HAS_SIG_C_FUNC */
+typedef void (*ACE_CLEANUP_FUNC)(void *object, void *param) /* throw () */;
+# if defined (ACE_HAS_SIG_C_FUNC)
+}
+# endif /* ACE_HAS_SIG_C_FUNC */
+
+// ============================================================================
+// log_msg declarations
+// ============================================================================
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+typedef int (*ACE_SEH_EXCEPT_HANDLER)(void *);
+// Prototype of win32 structured exception handler functions.
+// They are used to get the exception handling expression or
+// as exception handlers.
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+class ACE_OS_Thread_Descriptor;
+class ACE_OS_Log_Msg_Attributes;
+typedef void (*ACE_INIT_LOG_MSG_HOOK) (ACE_OS_Log_Msg_Attributes &attr
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , ACE_SEH_EXCEPT_HANDLER selector
+ , ACE_SEH_EXCEPT_HANDLER handler
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ );
+typedef void (*ACE_INHERIT_LOG_MSG_HOOK) (ACE_OS_Thread_Descriptor*,
+ ACE_OS_Log_Msg_Attributes &);
+
+typedef void (*ACE_CLOSE_LOG_MSG_HOOK) (void);
+
+typedef void (*ACE_SYNC_LOG_MSG_HOOK) (const ACE_TCHAR *prog_name);
+
+typedef ACE_OS_Thread_Descriptor *(*ACE_THR_DESC_LOG_MSG_HOOK) (void);
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @deprecated ACE_DECLARE_STL_REVERSE_ITERATORS is a crutch to be
+ * used until all C++ compiler supported by ACE support
+ * the standard reverse_iterator adapters.
+ * @internal ACE_DECLARE_STL_REVERSE_ITERATORS is not meant for use
+ * outside of ACE.
+ */
+// STL reverse_iterator declaration generator
+// Make sure you include <iterator> in the file you're using this
+// generator, and that the following traits are available:
+//
+// iterator
+// const_iterator
+// value_type
+// reference
+// pointer
+// const_reference
+// const_pointer
+// difference_type
+//
+// Once all C++ compilers support the standard reverse_iterator
+// adapters, we can drop this generator macro or at least drop the
+// MSVC++ or Sun Studio preprocessor conditional blocks.
+#if defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x590 \
+ && !defined (_STLPORT_VERSION)
+ // If we're not using the stlport4 C++ library (which has standard
+ // iterators), we need to ensure this is included in order to test
+ // the _RWSTD_NO_CLASS_PARTIAL_SPEC feature test macro below.
+# include <Cstd/stdcomp.h>
+#endif /* __SUNPRO_CC <= 0x580 */
+#if (defined (_MSC_VER) && (_MSC_VER <= 1310) && defined (_WIN64)) \
+ || defined (ACE_HAS_BROKEN_STD_REVERSE_ITERATOR)
+ // VC 7.1 and the latest 64-bit platform SDK still don't define a standard
+ // compliant reverse_iterator adapter.
+# define ACE_DECLARE_STL_REVERSE_ITERATORS \
+ typedef std::reverse_iterator<iterator, value_type> reverse_iterator; \
+ typedef std::reverse_iterator<const_iterator, \
+ value_type const> const_reverse_iterator;
+#elif defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x590 \
+ && defined (_RWSTD_NO_CLASS_PARTIAL_SPEC)
+# define ACE_DECLARE_STL_REVERSE_ITERATORS \
+ typedef std::reverse_iterator<iterator, \
+ std::input_iterator_tag, \
+ value_type, \
+ reference, \
+ pointer, \
+ difference_type> reverse_iterator; \
+ typedef std::reverse_iterator<const_iterator, \
+ std::input_iterator_tag, \
+ value_type const, \
+ const_reference, \
+ const_pointer, \
+ difference_type> const_reverse_iterator;
+#else
+# define ACE_DECLARE_STL_REVERSE_ITERATORS \
+ typedef std::reverse_iterator<iterator> reverse_iterator; \
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+#endif /* _MSC_VER && _WIN64 */
+
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONFIG_LITE_H */
diff --git a/ACE/ace/config-lynxos.h b/ACE/ace/config-lynxos.h
new file mode 100644
index 00000000000..73558e51bd9
--- /dev/null
+++ b/ACE/ace/config-lynxos.h
@@ -0,0 +1,159 @@
+// $Id$
+
+// The following configuration file is designed to work for LynxOS,
+// version 4.0.0 and later, using the GNU g++ compiler.
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#endif /* __GNUG__ */
+
+// Compile using multi-thread libraries.
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+#include "ace/config-posix.h"
+
+#if defined (__x86__)
+# define ACE_HAS_PENTIUM
+#elif defined (__powerpc__)
+ // It looks like the default stack size is 15000.
+ // ACE's Recursive_Mutex_Test needs more.
+# define ACE_NEEDS_HUGE_THREAD_STACKSIZE 65536
+ // This doesn't work on LynxOS 3.0.0, because it resets the TimeBaseRegister.
+ // # define ACE_HAS_POWERPC_TIMER
+#endif /* __x86__ || __powerpc__ */
+
+#define ACE_DEFAULT_BASE_ADDR ((char *) 0)
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_ALLOCA
+#define ACE_HAS_ALLOCA_H
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+#define ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK 1
+#define ACE_HAS_BROKEN_SIGEVENT_STRUCT
+#define ACE_HAS_CHARPTR_SHMAT
+#define ACE_HAS_CHARPTR_SHMDT
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_DIRENT
+#define ACE_HAS_GETPAGESIZE
+#define ACE_HAS_GETRUSAGE
+#define ACE_HAS_GNU_CSTRING_H
+#define ACE_HAS_GPERF
+#define ACE_HAS_ICMP_SUPPORT 1
+#define ACE_HAS_IP_MULTICAST
+#define ACE_HAS_LYNXOS_SIGNALS
+#define ACE_HAS_MSG
+#define ACE_HAS_NONCONST_CLOCK_SETTIME
+#define ACE_HAS_NONCONST_MSGSND
+#define ACE_HAS_NONCONST_READV
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONCONST_SETRLIMIT
+#define ACE_HAS_NONCONST_WRITEV
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+#define ACE_HAS_SCANDIR
+#define ACE_HAS_SEMUN
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_STRBUF_T
+#define ACE_HAS_STREAMS
+#define ACE_HAS_STRERROR
+#define ACE_HAS_SYSV_IPC
+#define ACE_HAS_SYS_SIGLIST
+#define ACE_HAS_SYS_SOCKIO_H
+#define ACE_HAS_TERMIOS
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+#define ACE_LACKS_ALPHASORT_PROTOTYPE
+#define ACE_LACKS_CONST_TIMESPEC_PTR
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MKSTEMP_PROTOTYPE
+#define ACE_LACKS_MKTEMP_PROTOTYPE
+#define ACE_LACKS_PUTENV_PROTOTYPE
+#define ACE_LACKS_REALPATH
+#define ACE_LACKS_RLIMIT_NOFILE
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SCANDIR_PROTOTYPE
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETEUID
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_STRPTIME
+#define ACE_LACKS_SUSECONDS_T
+#define ACE_LACKS_SWAB_PROTOTYPE
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_USECONDS_T
+#define ACE_LACKS_VSNPRINTF
+#define ACE_LACKS_WCHAR_H
+#define ACE_MALLOC_ALIGN 8
+#define ACE_PAGE_SIZE 4096
+#define ACE_POSIX_SIG_PROACTOR
+#define ACE_SCANDIR_CMP_USES_CONST_VOIDPTR
+
+#if ACE_MT_SAFE == 1
+ // Platform supports threads.
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+# define ACE_LACKS_NULL_PTHREAD_STATUS
+# define ACE_LACKS_THREAD_PROCESS_SCOPING
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACK
+# if ACE_LYNXOS_MAJOR == 4 && ACE_LYNXOS_MINOR == 0
+# define ACE_LACKS_SETDETACH
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR
+# endif
+#endif /* ACE_MT_SAFE */
+
+#if __GNUC__ < 3
+# define ACE_LACKS_NUMERIC_LIMITS
+#endif /* __GNUC__ < 3 */
+
+// By default, don't include RCS Id strings in object code.
+#if !defined (ACE_USE_RCSID)
+# define ACE_USE_RCSID 0
+#endif /* ! ACE_USE_RCSID */
+
+// System include files are not in sys/, this gets rid of warning.
+#define __NO_INCLUDE_WARN__
+
+// "changes signedness" error (OS.i and many other files)
+#define ACE_HAS_SOCKLEN_T
+// LSOCK.cpp uses a macro from param.h, not included
+#define ALIGNBYTES (sizeof(int) - 1)
+#define ALIGN(p) (((unsigned)p + ALIGNBYTES) & ~ALIGNBYTES)
+
+#if ACE_LYNXOS_MAJOR == 4 && ACE_LYNXOS_MINOR == 0
+# define ACE_LACKS_GETOPT_PROTOTYPE
+# define ACE_LACKS_INET_ATON_PROTOTYPE
+# define ACE_LACKS_REGEX_H
+# define ACE_LACKS_STRCASECMP_PROTOTYPE
+# define ACE_LACKS_STRNCASECMP_PROTOTYPE
+# define ACE_LACKS_SYS_SELECT_H
+# define ACE_HAS_NONCONST_GETBY
+#endif
+
+#if (ACE_LYNXOS_MAJOR > 4) || (ACE_LYNXOS_MAJOR == 4 && ACE_LYNXOS_MINOR >= 2)
+// LynxOS 4.2 additons
+# define ACE_HAS_POSIX_SEM_TIMEOUT
+# define ACE_HAS_MUTEX_TIMEOUTS
+#endif
+
+#if defined (ACE_HAS_SVR4_DYNAMIC_LINKING)
+# define ACE_HAS_BROKEN_THREAD_KEYFREE
+#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-macosx-leopard.h b/ACE/ace/config-macosx-leopard.h
new file mode 100644
index 00000000000..8ea95948ea7
--- /dev/null
+++ b/ACE/ace/config-macosx-leopard.h
@@ -0,0 +1,224 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file is designed to work with the MacOS X operating system.
+
+#ifndef ACE_CONFIG_MACOSX_LEOPARD_H
+#define ACE_CONFIG_MACOSX_LEOPARD_H
+
+#if ! defined (__ACE_INLINE__)
+#define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#if !defined (ACE_SIZEOF_LONG_DOUBLE)
+# if (__GNUC__ == 3 && __GNUC_MINOR__ == 3)
+ // Size of long double in GCC 3.3 is 8.
+# define ACE_SIZEOF_LONG_DOUBLE 8
+# else // Else, the compiler is GCC4
+ // For GCC4, the size is 16.
+# define ACE_SIZEOF_LONG_DOUBLE 16
+# endif // GCC 3.3
+#endif // ACE_SIZEOF_LONG_DOUBLE
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#endif /* __GNUG__ */
+
+#ifndef ACE_HAS_NONCONST_FD_ISSET
+#define ACE_HAS_NONCONST_FD_ISSET
+#endif
+
+#define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+
+#define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+
+#if !defined (__i386__)
+# if defined (ACE_HAS_PENTIUM)
+# undef ACE_HAS_PENTIUM
+# endif /* ACE_HAS_PENTIUM */
+#else // __i386__
+# define ACE_HAS_PENTIUM
+#endif //__i386__
+
+#if !defined (_THREAD_SAFE)
+#define _THREAD_SAFE
+#endif /* _THREAD_SAFE */
+
+#define ACE_HAS_GPERF
+#define ACE_HAS_POSIX_SEM
+
+#define ACE_HAS_SUNOS4_GETTIMEOFDAY
+
+#define ACE_LACKS_STROPTS_H
+
+// Wcharness....
+#define ACE_HAS_WCHAR
+#define ACE_SIZEOF_WCHAR 4
+
+
+#define ACE_HAS_3_PARAM_WCSTOK
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+#define ACE_LACKS_WCSDUP
+
+// Mac lacks the following pthread features
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_LACKS_CONDATTR_PSHARED
+//
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Compiler/platform supports SVR4 signal typedef
+#define ACE_HAS_SVR4_SIGNAL_T
+
+//Platform/compiler has the sigwait(2) prototype
+#define ACE_HAS_SIGWAIT
+
+#define ACE_HAS_AIO_CALLS
+
+//Platform supports sigsuspend()
+#define ACE_HAS_SIGSUSPEND
+
+//Platform/compiler has macros for sig{empty,fill,add,del}set (e.g., SCO and FreeBSD)
+#define ACE_HAS_SIG_MACROS
+
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_RWLOCK_T
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+//?
+#define ACE_LACKS_SIGSET
+
+#define ACE_NEEDS_SCHED_H
+
+// Use of <malloc.h> is deprecated.
+#define ACE_LACKS_MALLOC_H
+
+#define ACE_HAS_ALT_CUSERID
+
+// Platform supports POSIX timers via struct timespec.
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_UALARM
+
+// Platform defines struct timespec but not timespec_t
+#define ACE_LACKS_TIMESPEC_T
+
+#define ACE_LACKS_STRRECVFD
+
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Compiler/platform supports alloca().
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+#define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Compiler/platform provides the socklen_t type.
+#define ACE_HAS_SOCKLEN_T
+
+// Defines the page size of the system.
+#define ACE_HAS_GETPAGESIZE
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Platform/compiler supports timezone * as second parameter to gettimeofday().
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_SYSV_MSQ_PROTOS
+#define ACE_HAS_MSG
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_NONCONST_MSGSND
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+#if ACE_MT_SAFE == 1
+// Yes, we do have threads.
+# define ACE_HAS_THREADS
+// And they're even POSIX pthreads
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_PTHREADS_STD
+# define ACE_HAS_PTHREAD_SCHEDPARAM
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#endif /* ACE_MT_SAFE == 1 */
+
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+
+#define ACE_HAS_DIRENT
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_SEARCH_H
+
+#define ACE_LACKS_SETSCHED
+//#define ACE_HAS_RECURSIVE_MUTEXES
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+#define ACE_HAS_SEMUN
+#define ACE_HAS_SIGINFO_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_GETIFADDRS
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+#define ACE_LACKS_UNNAMED_SEMAPHORE
+
+// dlcompat package (not part of base Darwin) is needed for dlopen().
+// You may download directly from sourceforge and install or use fink
+// Fink installer puts libraries in /sw/lib and headers in /sw/include
+// In order to install dlcompat do the following:
+// - download fink from http://fink.sf.net
+// - type:
+// fink install dlcompat
+// as of Dec 2002, if you use fink you will need to uncomment the next line
+// #define ACE_NEEDS_DL_UNDERSCORE
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_LD_SEARCH_PATH ACE_TEXT ("DYLD_LIBRARY_PATH")
+#define ACE_DLL_SUFFIX ACE_TEXT (".dylib")
+//#define ACE_LACKS_DLCLOSE
+
+// gperf seems to need this
+//#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+
+#if defined(__APPLE_CC__) && (__APPLE_CC__ < 1173)
+#error "Compiler must be upgraded, see http://developer.apple.com"
+#endif /* __APPLE_CC__ */
+
+#endif /* ACE_CONFIG_MACOSX_TIGER_H */
diff --git a/ACE/ace/config-macosx-panther.h b/ACE/ace/config-macosx-panther.h
new file mode 100644
index 00000000000..1c7361fd416
--- /dev/null
+++ b/ACE/ace/config-macosx-panther.h
@@ -0,0 +1,191 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file is designed to work with the MacOS X operating system.
+
+#ifndef ACE_CONFIG_MACOSX_H
+#define ACE_CONFIG_MACOSX_H
+
+#if ! defined (__ACE_INLINE__)
+#define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#endif /* __GNUG__ */
+
+#define ACE_LACKS_SUSECONDS_T
+#define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+
+#if defined (ACE_HAS_PENTIUM)
+# undef ACE_HAS_PENTIUM
+#endif /* ACE_HAS_PENTIUM */
+
+#if !defined (_THREAD_SAFE)
+#define _THREAD_SAFE
+#endif /* _THREAD_SAFE */
+
+#define ACE_HAS_GPERF
+#define ACE_HAS_POSIX_SEM
+
+//#define ACE_HAS_SVR4_TLI
+
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_WCHAR_H
+
+//
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Compiler/platform supports SVR4 signal typedef
+#define ACE_HAS_SVR4_SIGNAL_T
+
+//Platform/compiler has the sigwait(2) prototype
+#define ACE_HAS_SIGWAIT
+
+//Platform supports sigsuspend()
+#define ACE_HAS_SIGSUSPEND
+
+//Platform/compiler has macros for sig{empty,fill,add,del}set (e.g., SCO and FreeBSD)
+#define ACE_HAS_SIG_MACROS
+
+//#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_RWLOCK_T
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+//?
+#define ACE_LACKS_SIGSET
+
+#define ACE_NEEDS_SCHED_H
+
+// Use of <malloc.h> is deprecated.
+#define ACE_LACKS_MALLOC_H
+
+#define ACE_HAS_ALT_CUSERID
+
+// Platform supports POSIX timers via struct timespec.
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_UALARM
+
+// Platform defines struct timespec but not timespec_t
+#define ACE_LACKS_TIMESPEC_T
+
+#define ACE_LACKS_STRRECVFD
+
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Compiler/platform supports alloca().
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Explicit dynamic linking permits "lazy" symbol resolution
+//#define ACE_HAS_RTLD_LAZY_V
+
+// platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+#define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Defines the page size of the system.
+#define ACE_HAS_GETPAGESIZE
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Platform/compiler supports timezone * as second parameter to gettimeofday().
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_SYSV_MSQ_PROTOS
+#define ACE_HAS_MSG
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_NONCONST_MSGSND
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+#if ACE_MT_SAFE == 1
+// Yes, we do have threads.
+# define ACE_HAS_THREADS
+// And they're even POSIX pthreads
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_PTHREAD_SCHEDPARAM
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#endif /* ACE_MT_SAFE == 1 */
+
+# define ACE_LACKS_THREAD_PROCESS_SCOPING
+
+#define ACE_HAS_DIRENT
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_SEARCH_H
+
+#define ACE_LACKS_SETSCHED
+//#define ACE_HAS_RECURSIVE_MUTEXES
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+#define ACE_HAS_SEMUN
+#define ACE_HAS_SIGINFO_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_GETIFADDRS
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+#define ACE_LACKS_UNNAMED_SEMAPHORE
+
+// dlcompat package (not part of base Darwin) is needed for dlopen().
+// You may download directly from sourceforge and install or use fink
+// Fink installer puts libraries in /sw/lib and headers in /sw/include
+// In order to install dlcompat do the following:
+// - download fink from http://fink.sf.net
+// - type:
+// fink install dlcompat
+// as of Dec 2002, if you use fink you will need to uncomment the next line
+//#define ACE_NEEDS_DL_UNDERSCORE
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_LD_SEARCH_PATH ACE_TEXT ("DYLD_LIBRARY_PATH")
+#define ACE_DLL_SUFFIX ACE_TEXT (".dylib")
+//#define ACE_LACKS_DLCLOSE
+
+// gperf seems to need this
+//#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+
+#if defined(__APPLE_CC__) && (__APPLE_CC__ < 1173)
+#error "Compiler must be upgraded, see http://developer.apple.com"
+#endif /* __APPLE_CC__ */
+
+#endif /* ACE_CONFIG_MACOSX_H */
diff --git a/ACE/ace/config-macosx-tiger.h b/ACE/ace/config-macosx-tiger.h
new file mode 100644
index 00000000000..906509818ab
--- /dev/null
+++ b/ACE/ace/config-macosx-tiger.h
@@ -0,0 +1,219 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file is designed to work with the MacOS X operating system.
+
+#ifndef ACE_CONFIG_MACOSX_TIGER_H
+#define ACE_CONFIG_MACOSX_TIGER_H
+
+#if ! defined (__ACE_INLINE__)
+#define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#endif /* __GNUG__ */
+
+#define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+
+#define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+
+#if !defined (ACE_SIZEOF_LONG_DOUBLE)
+# if (__GNUC__ == 3 && __GNUC_MINOR__ == 3)
+ // Size of long double in GCC 3.3 is 8.
+# define ACE_SIZEOF_LONG_DOUBLE 8
+# else // Else, the compiler is GCC4
+ // For GCC4, the size is 16.
+# define ACE_SIZEOF_LONG_DOUBLE 16
+# endif // GCC 3.3
+#endif // ACE_SIZEOF_LONG_DOUBLE
+
+#if !defined (__i386__)
+# if defined (ACE_HAS_PENTIUM)
+# undef ACE_HAS_PENTIUM
+# endif /* ACE_HAS_PENTIUM */
+#else // __i386__
+# define ACE_HAS_PENTIUM
+#endif //__i386__
+
+#if !defined (_THREAD_SAFE)
+#define _THREAD_SAFE
+#endif /* _THREAD_SAFE */
+
+#define ACE_HAS_GPERF
+#define ACE_HAS_POSIX_SEM
+
+#define ACE_HAS_SUNOS4_GETTIMEOFDAY
+
+#define ACE_LACKS_STROPTS_H
+
+// Wcharness....
+#define ACE_HAS_WCHAR
+#define ACE_SIZEOF_WCHAR 4
+
+
+#define ACE_HAS_3_PARAM_WCSTOK
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+#define ACE_LACKS_WCSDUP
+
+// Mac lacks the following pthread features
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_LACKS_CONDATTR_PSHARED
+//
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Compiler/platform supports SVR4 signal typedef
+#define ACE_HAS_SVR4_SIGNAL_T
+
+//Platform/compiler has the sigwait(2) prototype
+#define ACE_HAS_SIGWAIT
+
+#define ACE_HAS_AIO_CALLS
+
+//Platform supports sigsuspend()
+#define ACE_HAS_SIGSUSPEND
+
+//Platform/compiler has macros for sig{empty,fill,add,del}set (e.g., SCO and FreeBSD)
+#define ACE_HAS_SIG_MACROS
+
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_RWLOCK_T
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+//?
+#define ACE_LACKS_SIGSET
+
+#define ACE_NEEDS_SCHED_H
+
+// Use of <malloc.h> is deprecated.
+#define ACE_LACKS_MALLOC_H
+
+#define ACE_HAS_ALT_CUSERID
+
+// Platform supports POSIX timers via struct timespec.
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_UALARM
+
+// Platform defines struct timespec but not timespec_t
+#define ACE_LACKS_TIMESPEC_T
+
+#define ACE_LACKS_STRRECVFD
+
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Compiler/platform supports alloca().
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+#define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Compiler/platform provides the socklen_t type.
+#define ACE_HAS_SOCKLEN_T
+
+// Defines the page size of the system.
+#define ACE_HAS_GETPAGESIZE
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Platform/compiler supports timezone * as second parameter to gettimeofday().
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_SYSV_MSQ_PROTOS
+#define ACE_HAS_MSG
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_NONCONST_MSGSND
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+#if ACE_MT_SAFE == 1
+// Yes, we do have threads.
+# define ACE_HAS_THREADS
+// And they're even POSIX pthreads
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_PTHREAD_SCHEDPARAM
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#endif /* ACE_MT_SAFE == 1 */
+
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+
+#define ACE_HAS_DIRENT
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_SEARCH_H
+
+#define ACE_LACKS_SETSCHED
+//#define ACE_HAS_RECURSIVE_MUTEXES
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+#define ACE_HAS_SEMUN
+#define ACE_HAS_SIGINFO_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_GETIFADDRS
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+#define ACE_LACKS_UNNAMED_SEMAPHORE
+
+// dlcompat package (not part of base Darwin) is needed for dlopen().
+// You may download directly from sourceforge and install or use fink
+// Fink installer puts libraries in /sw/lib and headers in /sw/include
+// In order to install dlcompat do the following:
+// - download fink from http://fink.sf.net
+// - type:
+// fink install dlcompat
+// as of Dec 2002, if you use fink you will need to uncomment the next line
+// #define ACE_NEEDS_DL_UNDERSCORE
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_LD_SEARCH_PATH ACE_TEXT ("DYLD_LIBRARY_PATH")
+#define ACE_DLL_SUFFIX ACE_TEXT (".dylib")
+//#define ACE_LACKS_DLCLOSE
+
+// gperf seems to need this
+//#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+
+#if defined(__APPLE_CC__) && (__APPLE_CC__ < 1173)
+#error "Compiler must be upgraded, see http://developer.apple.com"
+#endif /* __APPLE_CC__ */
+
+#endif /* ACE_CONFIG_MACOSX_TIGER_H */
diff --git a/ACE/ace/config-macosx.h b/ACE/ace/config-macosx.h
new file mode 100644
index 00000000000..c721353ca48
--- /dev/null
+++ b/ACE/ace/config-macosx.h
@@ -0,0 +1,191 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file is designed to work with the MacOS X operating system, version 10.2 (Jaguar).
+
+#ifndef ACE_CONFIG_MACOSX_H
+#define ACE_CONFIG_MACOSX_H
+
+#if ! defined (__ACE_INLINE__)
+#define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#endif /* __GNUG__ */
+
+#define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+
+#if defined (ACE_HAS_PENTIUM)
+# undef ACE_HAS_PENTIUM
+#endif /* ACE_HAS_PENTIUM */
+
+#if !defined (_THREAD_SAFE)
+#define _THREAD_SAFE
+#endif /* _THREAD_SAFE */
+
+#define ACE_HAS_GPERF
+#define ACE_HAS_POSIX_SEM
+
+//#define ACE_HAS_SVR4_TLI
+
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_WCHAR_H
+
+#define ACE_SYS_SELECT_NEEDS_UNISTD_H
+
+//
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Compiler/platform supports SVR4 signal typedef
+#define ACE_HAS_SVR4_SIGNAL_T
+
+//Platform/compiler has the sigwait(2) prototype
+#define ACE_HAS_SIGWAIT
+
+//Platform supports sigsuspend()
+#define ACE_HAS_SIGSUSPEND
+
+//Platform/compiler has macros for sig{empty,fill,add,del}set (e.g., SCO and FreeBSD)
+#define ACE_HAS_SIG_MACROS
+
+//#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_RWLOCK_T
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+#define ACE_HAS_SYSCTL
+
+//?
+#define ACE_LACKS_SIGSET
+
+#define ACE_NEEDS_SCHED_H
+
+// Use of <malloc.h> is deprecated.
+#define ACE_LACKS_MALLOC_H
+
+#define ACE_HAS_ALT_CUSERID
+
+// Platform supports POSIX timers via struct timespec.
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_UALARM
+
+// Platform defines struct timespec but not timespec_t
+#define ACE_LACKS_TIMESPEC_T
+
+#define ACE_LACKS_STRRECVFD
+
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+//#define ACE_HAS_SYSV_IPC
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Compiler/platform supports alloca().
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Explicit dynamic linking permits "lazy" symbol resolution
+//#define ACE_HAS_RTLD_LAZY_V
+
+// platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+#define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Defines the page size of the system.
+#define ACE_HAS_GETPAGESIZE
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Platform/compiler supports timezone * as second parameter to gettimeofday().
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_SYSV_MSQ_PROTOS
+#define ACE_HAS_MSG
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_NONCONST_MSGSND
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+#if ACE_MT_SAFE == 1
+// Yes, we do have threads.
+# define ACE_HAS_THREADS
+// And they're even POSIX pthreads
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+# define ACE_LACKS_THREAD_PROCESS_SCOPING
+#endif /* ACE_MT_SAFE == 1 */
+
+#define ACE_HAS_DIRENT
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_SEARCH_H
+
+#define ACE_LACKS_SETSCHED
+//#define ACE_HAS_RECURSIVE_MUTEXES
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+#define ACE_HAS_SEMUN
+#define ACE_HAS_SIGINFO_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_GETIFADDRS
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+#define ACE_LACKS_UNNAMED_SEMAPHORE
+
+// dlcompat package (not part of base Darwin) is needed for dlopen().
+// You may download directly from sourceforge and install or use fink
+// Fink installer puts libraries in /sw/lib and headers in /sw/include
+// In order to install dlcompat do the following:
+// - download fink from http://fink.sf.net
+// - type:
+// fink install dlcompat
+// as of Dec 2002, if you use fink you will need to uncomment the next line
+//#define ACE_NEEDS_DL_UNDERSCORE
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_LD_SEARCH_PATH ACE_TEXT ("DYLD_LIBRARY_PATH")
+#define ACE_DLL_SUFFIX ACE_TEXT (".dylib")
+#define ACE_LACKS_DLCLOSE
+
+// gperf seems to need this
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+
+#if defined(__APPLE_CC__) && (__APPLE_CC__ < 1173)
+#error "Compiler must be upgraded, see http://developer.apple.com"
+#endif /* __APPLE_CC__ */
+
+#endif /* ACE_CONFIG_MACOSX_H */
diff --git a/ACE/ace/config-macros.h b/ACE/ace/config-macros.h
new file mode 100644
index 00000000000..4e029522779
--- /dev/null
+++ b/ACE/ace/config-macros.h
@@ -0,0 +1,639 @@
+// -*- C++ -*-
+
+//==========================================================================
+/**
+ * @file config-macros.h
+ *
+ * $Id$
+ *
+ * @author (Originally in OS.h)Doug Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * This file contains the contents of the old config-lite.h header
+ * without C++ code (except for C++ code in macros). Specifically,
+ * only macros or C language constructs are found in this header.
+ * Allows configuration values and macros to be used by some C
+ * language sources.
+ */
+//==========================================================================
+
+#ifndef ACE_CONFIG_MACROS_H
+#define ACE_CONFIG_MACROS_H
+
+#include "ace/config.h"
+
+#include "ace/Version.h"
+#include "ace/Versioned_Namespace.h"
+
+// ACE_HAS_TLI is used to decide whether to try any XTI/TLI functionality
+// so if it isn't set, set it. Capabilities and differences between
+// XTI and TLI favor XTI, but when deciding to do anything, as opposed to
+// ACE_NOTSUP_RETURN for example, ACE_HAS_TLI is the deciding factor.
+#if !defined (ACE_HAS_TLI)
+# if defined (ACE_HAS_XTI)
+# define ACE_HAS_TLI
+# endif /* ACE_HAS_XTI */
+#endif /* ACE_HAS_TLI */
+
+#define ACE_BITS_PER_ULONG (8 * sizeof (u_long))
+
+#if !defined (ACE_OSTREAM_TYPE)
+# if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+# define ACE_OSTREAM_TYPE FILE
+# else /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+# define ACE_OSTREAM_TYPE ostream
+# endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+#endif /* ! ACE_OSTREAM_TYPE */
+
+#if !defined (ACE_DEFAULT_LOG_STREAM)
+# if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+# define ACE_DEFAULT_LOG_STREAM 0
+# else /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+# define ACE_DEFAULT_LOG_STREAM (&cerr)
+# endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+#endif /* ! ACE_DEFAULT_LOG_STREAM */
+
+// These two are only for backward compatibility. You should avoid
+// using them if not necessary.
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+/**
+ * @deprecated The ACE_SYNCH_1 macro is deprecated
+ */
+# define ACE_SYNCH_1 ACE_SYNCH_DECL
+/**
+ * @deprecated The ACE_SYNCH_2 macro is deprecated
+ */
+# define ACE_SYNCH_2 ACE_SYNCH_USE
+#endif
+
+// For Win32 compatibility...
+# if !defined (ACE_WSOCK_VERSION)
+# define ACE_WSOCK_VERSION 0, 0
+# endif /* ACE_WSOCK_VERSION */
+
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# define ACE_MT(X) X
+# if !defined (_REENTRANT)
+# define _REENTRANT
+# endif /* _REENTRANT */
+# else
+# define ACE_MT(X)
+# endif /* ACE_MT_SAFE */
+
+# if defined (ACE_HAS_PURIFY)
+# define ACE_INITIALIZE_MEMORY_BEFORE_USE
+# endif /* ACE_HAS_PURIFY */
+
+# if defined (ACE_HAS_VALGRIND)
+# define ACE_INITIALIZE_MEMORY_BEFORE_USE
+# endif /* ACE_HAS_VALGRIND */
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+/**
+ * @deprecated The @c ACE_HAS_USING macros are deprecated
+ */
+# define ACE_USING using
+#endif /* !ACE_LACKS_DEPRECATED_MACROS */
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+/**
+ * @deprecated The @c ACE_TYPENAME macros is deprecated. Use standard
+ * C++ keyword typename instead.
+ */
+# define ACE_TYPENAME typename
+#endif /* !ACE_LACKS_DEPRECATED_MACROS */
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+/**
+ * @deprecated The @c ACE_TEMPLATE_SPECIALIZATION and
+ * @c ACE_TEMPLATE_CLASS_MEMBER_SPECIALIZATION macros are
+ * deprecated. Use standard C++ template specialization
+ * syntax instead.
+ */
+# define ACE_TEMPLATE_SPECIALIZATION template<>
+# define ACE_TEMPLATE_CLASS_MEMBER_SPECIALIZATION
+#endif /* !ACE_LACKS_DEPRECATED_MACROS */
+
+// =========================================================================
+// Perfect Multicast filting refers to RFC 3376, where a socket is only
+// delivered dgrams for groups joined even if it didn't bind the group
+// address. We turn this option off by default, although most OS's
+// except for Windows and Solaris probably lack perfect filtering.
+// =========================================================================
+
+# if !defined (ACE_LACKS_PERFECT_MULTICAST_FILTERING)
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 0
+# endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
+// =========================================================================
+// Enable/Disable Features By Default
+// =========================================================================
+
+# if !defined (ACE_HAS_POSITION_INDEPENDENT_POINTERS)
+# define ACE_HAS_POSITION_INDEPENDENT_POINTERS 1
+# endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS */
+
+# if !defined (ACE_HAS_PROCESS_SPAWN)
+# if !defined (ACE_LACKS_FORK) || defined (ACE_WIN32) || defined (ACE_WINCE) || defined (ACE_OPENVMS)
+# define ACE_HAS_PROCESS_SPAWN 1
+# endif
+# endif /* ACE_HAS_PROCESS_SPAWN */
+
+# if !defined (ACE_HAS_DYNAMIC_LINKING)
+# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) || defined (ACE_WIN32) || defined (ACE_VXWORKS) || defined (__hpux)
+# define ACE_HAS_DYNAMIC_LINKING 1
+# endif
+# endif /* ACE_HAS_DYNAMIC_LINKING */
+
+# if defined (ACE_USES_FIFO_SEM)
+# if defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_MKFIFO) || defined (ACE_LACKS_FCNTL)
+# undef ACE_USES_FIFO_SEM
+# endif
+# endif /* ACE_USES_FIFO_SEM */
+
+// =========================================================================
+// RCSID Macros
+// =========================================================================
+
+// By default, DO NOT include RCS Id strings in object code.
+#if ! defined (ACE_USE_RCSID)
+# define ACE_USE_RCSID 0
+#endif /* #if ! defined (ACE_USE_RCSID) */
+
+#if (defined (ACE_USE_RCSID) && (ACE_USE_RCSID != 0))
+# if ! defined (ACE_RCSID)
+
+ // This hack has the following purposes:
+ // 1. To define the RCS id string variable as a static char*, so
+ // that there won't be any duplicate extern symbols at link
+ // time.
+ // 2. To have a RCS id string variable with a unique name for each
+ // file.
+ // 3. To avoid warnings of the type "variable declared and never
+ // used".
+
+# define ACE_RCSID(path, file, id) \
+ static inline const char* get_rcsid_ ## path ## _ ## file (const char*) \
+ { \
+ return id ; \
+ } \
+ static const char* rcsid_ ## path ## _ ## file = \
+ get_rcsid_ ## path ## _ ## file ( rcsid_ ## path ## _ ## file ) ;
+
+# endif /* #if ! defined (ACE_RCSID) */
+#else
+
+ // RCS id strings are not wanted.
+# if defined (ACE_RCSID)
+# undef ACE_RCSID
+# endif /* #if defined (ACE_RCSID) */
+# define ACE_RCSID(path, file, id) /* noop */
+#endif /* #if (defined (ACE_USE_RCSID) && (ACE_USE_RCSID != 0)) */
+
+// =========================================================================
+// INLINE macros
+//
+// These macros handle all the inlining of code via the .i or .inl files
+// =========================================================================
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS) && !defined (ACE_NO_INLINE)
+# define ACE_NO_INLINE
+#endif /* defined (ACE_LACKS_INLINE_FUNCTIONS) && !defined (ACE_NO_INLINE) */
+
+// ACE inlining has been explicitly disabled. Implement
+// internally within ACE by undefining __ACE_INLINE__.
+#if defined (ACE_NO_INLINE)
+# undef __ACE_INLINE__
+#endif /* ! ACE_NO_INLINE */
+
+#if defined (__ACE_INLINE__)
+# define ACE_INLINE inline
+# if !defined (ACE_HAS_INLINED_OSCALLS)
+# define ACE_HAS_INLINED_OSCALLS
+# endif /* !ACE_HAS_INLINED_OSCALLS */
+#else
+# define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+ // =========================================================================
+ // EXPLICIT macro
+ // =========================================================================
+
+ /**
+ * @deprecated explicit is deprecated. ACE requires C++
+ * "explicit" keyword support.
+ */
+ # define ACE_EXPLICIT explicit
+#endif /* ACE_LACKS_DEPRECATED_MACROS */
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+ // =========================================================================
+ // MUTABLE macro
+ // =========================================================================
+
+ /**
+ * @deprecated ACE_MUTABLE is deprecated. ACE requires C++ "mutable"
+ * keyword support.
+ */
+ # define ACE_MUTABLE mutable
+ # define ACE_CONST_WHEN_MUTABLE const
+#endif /* ACE_LACKS_DEPRECATED_MACROS */
+
+// ============================================================================
+// EXPORT macros
+//
+// Since Win32 DLL's do not export all symbols by default, they must be
+// explicitly exported (which is done by *_Export macros).
+// ============================================================================
+
+// Win32 should have already defined the macros in config-win32-common.h
+#if !defined (ACE_HAS_CUSTOM_EXPORT_MACROS)
+# define ACE_Proper_Export_Flag
+# define ACE_Proper_Import_Flag
+# define ACE_EXPORT_SINGLETON_DECLARATION(T)
+# define ACE_IMPORT_SINGLETON_DECLARATION(T)
+# define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#else
+// An export macro should at the very least have been defined.
+
+# ifndef ACE_Proper_Import_Flag
+# define ACE_Proper_Import_Flag
+# endif /* !ACE_Proper_Import_Flag */
+
+# ifndef ACE_EXPORT_SINGLETON_DECLARATION
+# define ACE_EXPORT_SINGLETON_DECLARATION(T)
+# endif /* !ACE_EXPORT_SINGLETON_DECLARATION */
+
+# ifndef ACE_IMPORT_SINGLETON_DECLARATION
+# define ACE_IMPORT_SINGLETON_DECLARATION(T)
+# endif /* !ACE_IMPORT_SINGLETON_DECLARATION */
+
+# ifndef ACE_EXPORT_SINGLETON_DECLARE
+# define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* !ACE_EXPORT_SINGLETON_DECLARE */
+
+# ifndef ACE_IMPORT_SINGLETON_DECLARE
+# define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* !ACE_IMPORT_SINGLETON_DECLARE */
+
+#endif /* !ACE_HAS_CUSTOM_EXPORT_MACROS */
+
+// This is a whim of mine -- that instead of annotating a class with
+// ACE_Export in its declaration, we make the declaration near the TOP
+// of the file with ACE_DECLARE_EXPORT.
+// TS = type specifier (e.g., class, struct, int, etc.)
+// ID = identifier
+// So, how do you use it? Most of the time, just use ...
+// ACE_DECLARE_EXPORT(class, someobject);
+// If there are global functions to be exported, then use ...
+// ACE_DECLARE_EXPORT(void, globalfunction) (int, ...);
+// Someday, when template libraries are supported, we made need ...
+// ACE_DECLARE_EXPORT(template class, sometemplate) <class TYPE, class LOCK>;
+# define ACE_DECLARE_EXPORT(TS,ID) TS ACE_Export ID
+
+// ============================================================================
+// Cast macros
+//
+// These macros are used to choose between the old cast style and the new
+// *_cast<> operators
+// ============================================================================
+
+# define ACE_sap_any_cast(TYPE) reinterpret_cast<TYPE> (const_cast<ACE_Addr &> (ACE_Addr::sap_any))
+
+#if !defined (ACE_LACKS_DEPRECATED_MACROS)
+ /**
+ * @deprecated ACE_{static,reinterpret,dynamic,const}_cast@<@> is
+ * deprecated. Directly use standard C++ casts instead.
+ */
+ # define ACE_static_cast(TYPE, EXPR) static_cast<TYPE> (EXPR)
+ # define ACE_static_cast_1_ptr(TYPE, T1, EXPR) static_cast<TYPE<T1> *> (EXPR)
+ # define ACE_static_cast_2_ptr(TYPE, T1, T2, EXPR) static_cast<TYPE<T1, T2> *> (EXPR)
+ # define ACE_static_cast_3_ptr(TYPE, T1, T2, T3, EXPR) static_cast<TYPE<T1, T2, T3> *> (EXPR)
+ # define ACE_static_cast_4_ptr(TYPE, T1, T2, T3, T4, EXPR) static_cast<TYPE<T1, T2, T3, T4> *> (EXPR)
+ # define ACE_static_cast_5_ptr(TYPE, T1, T2, T3, T4, T5, EXPR) static_cast<TYPE<T1, T2, T3, T4, T5> *> (EXPR)
+ # define ACE_static_cast_1_ref(TYPE, T1, EXPR) static_cast<TYPE<T1> &> (EXPR)
+ # define ACE_static_cast_2_ref(TYPE, T1, T2, EXPR) static_cast<TYPE<T1, T2> &> (EXPR)
+ # define ACE_static_cast_3_ref(TYPE, T1, T2, T3, EXPR) static_cast<TYPE<T1, T2, T3> &> (EXPR)
+ # define ACE_static_cast_4_ref(TYPE, T1, T2, T3, T4, EXPR) static_cast<TYPE<T1, T2, T3, T4> &> (EXPR)
+ # define ACE_static_cast_5_ref(TYPE, T1, T2, T3, T4, T5, EXPR) static_cast<TYPE<T1, T2, T3, T4, T5> &> (EXPR)
+
+ # define ACE_const_cast(TYPE, EXPR) const_cast<TYPE> (EXPR)
+ # define ACE_const_cast_1_ptr(TYPE, T1, EXPR) const_cast<TYPE<T1> *> (EXPR)
+ # define ACE_const_cast_2_ptr(TYPE, T1, T2, EXPR) const_cast<TYPE<T1, T2> *> (EXPR)
+ # define ACE_const_cast_3_ptr(TYPE, T1, T2, T3, EXPR) const_cast<TYPE<T1, T2, T3> *> (EXPR)
+ # define ACE_const_cast_4_ptr(TYPE, T1, T2, T3, T4, EXPR) const_cast<TYPE<T1, T2, T3, T4> *> (EXPR)
+ # define ACE_const_cast_5_ptr(TYPE, T1, T2, T3, T4, T5, EXPR) const_cast<TYPE<T1, T2, T3, T4, T5> *> (EXPR)
+ # define ACE_const_cast_1_ref(TYPE, T1, EXPR) const_cast<TYPE<T1> &> (EXPR)
+ # define ACE_const_cast_2_ref(TYPE, T1, T2, EXPR) const_cast<TYPE<T1, T2> &> (EXPR)
+ # define ACE_const_cast_3_ref(TYPE, T1, T2, T3, EXPR) const_cast<TYPE<T1, T2, T3> &> (EXPR)
+ # define ACE_const_cast_4_ref(TYPE, T1, T2, T3, T4, EXPR) const_cast<TYPE<T1, T2, T3, T4> &> (EXPR)
+ # define ACE_const_cast_5_ref(TYPE, T1, T2, T3, T4, T5, EXPR) const_cast<TYPE<T1, T2, T3, T4, T5> &> (EXPR)
+
+ # define ACE_reinterpret_cast(TYPE, EXPR) reinterpret_cast<TYPE> (EXPR)
+ # define ACE_reinterpret_cast_1_ptr(TYPE, T1, EXPR) reinterpret_cast<TYPE<T1> *> (EXPR)
+ # define ACE_reinterpret_cast_2_ptr(TYPE, T1, T2, EXPR) reinterpret_cast<TYPE<T1, T2> *> (EXPR)
+ # define ACE_reinterpret_cast_3_ptr(TYPE, T1, T2, T3, EXPR) reinterpret_cast<TYPE<T1, T2, T3> *> (EXPR)
+ # define ACE_reinterpret_cast_4_ptr(TYPE, T1, T2, T3, T4, EXPR) reinterpret_cast<TYPE<T1, T2, T3, T4> *> (EXPR)
+ # define ACE_reinterpret_cast_5_ptr(TYPE, T1, T2, T3, T4, T5, EXPR) reinterpret_cast<TYPE<T1, T2, T3, T4, T5> *> (EXPR)
+ # define ACE_reinterpret_cast_1_ref(TYPE, T1, EXPR) reinterpret_cast<TYPE<T1> &> (EXPR)
+ # define ACE_reinterpret_cast_2_ref(TYPE, T1, T2, EXPR) reinterpret_cast<TYPE<T1, T2> &> (EXPR)
+ # define ACE_reinterpret_cast_3_ref(TYPE, T1, T2, T3, EXPR) reinterpret_cast<TYPE<T1, T2, T3> &> (EXPR)
+ # define ACE_reinterpret_cast_4_ref(TYPE, T1, T2, T3, T4, EXPR) reinterpret_cast<TYPE<T1, T2, T3, T4> &> (EXPR)
+ # define ACE_reinterpret_cast_5_ref(TYPE, T1, T2, T3, T4, T5, EXPR) reinterpret_cast<TYPE<T1, T2, T3, T4, T5> &> (EXPR)
+
+ # define ACE_dynamic_cast(TYPE, EXPR) dynamic_cast<TYPE> (EXPR)
+ # define ACE_dynamic_cast_1_ptr(TYPE, T1, EXPR) dynamic_cast<TYPE<T1> *> (EXPR)
+ # define ACE_dynamic_cast_2_ptr(TYPE, T1, T2, EXPR) dynamic_cast<TYPE<T1, T2> *> (EXPR)
+ # define ACE_dynamic_cast_3_ptr(TYPE, T1, T2, T3, EXPR) dynamic_cast<TYPE<T1, T2, T3> *> (EXPR)
+ # define ACE_dynamic_cast_4_ptr(TYPE, T1, T2, T3, T4, EXPR) dynamic_cast<TYPE<T1, T2, T3, T4> *> (EXPR)
+ # define ACE_dynamic_cast_5_ptr(TYPE, T1, T2, T3, T4, T5, EXPR) dynamic_cast<TYPE<T1, T2, T3, T4, T5> *> (EXPR)
+ # define ACE_dynamic_cast_1_ref(TYPE, T1, EXPR) dynamic_cast<TYPE<T1> &> (EXPR)
+ # define ACE_dynamic_cast_2_ref(TYPE, T1, T2, EXPR) dynamic_cast<TYPE<T1, T2> &> (EXPR)
+ # define ACE_dynamic_cast_3_ref(TYPE, T1, T2, T3, EXPR) dynamic_cast<TYPE<T1, T2, T3> &> (EXPR)
+ # define ACE_dynamic_cast_4_ref(TYPE, T1, T2, T3, T4, EXPR) dynamic_cast<TYPE<T1, T2, T3, T4> &> (EXPR)
+ # define ACE_dynamic_cast_5_ref(TYPE, T1, T2, T3, T4, T5, EXPR) dynamic_cast<TYPE<T1, T2, T3, T4, T5> &> (EXPR)
+#endif /* ACE_LACKS_DEPRECATED_MACROS */
+
+# if !defined (ACE_CAST_CONST)
+ // Sun CC 4.2, for example, requires const in reinterpret casts of
+ // data members in const member functions. But, other compilers
+ // complain about the useless const. This keeps everyone happy.
+# if defined (__SUNPRO_CC)
+# define ACE_CAST_CONST const
+# else /* ! __SUNPRO_CC */
+# define ACE_CAST_CONST
+# endif /* ! __SUNPRO_CC */
+# endif /* ! ACE_CAST_CONST */
+
+// ============================================================================
+// Compiler Silencing macros
+//
+// Some compilers complain about parameters that are not used. This macro
+// should keep them quiet.
+// ============================================================================
+
+#if defined (ghs) || defined (__GNUC__) || defined (__hpux) || defined (__sgi) || defined (__DECCXX) || defined (__rational__) || defined (__USLC__) || defined (ACE_RM544) || defined (__DCC__) || defined (__PGI) || defined (__TANDEM)
+// Some compilers complain about "statement with no effect" with (a).
+// This eliminates the warnings, and no code is generated for the null
+// conditional statement. @note that may only be true if -O is enabled,
+// such as with GreenHills (ghs) 1.8.8.
+# define ACE_UNUSED_ARG(a) do {/* null */} while (&a == 0)
+#elif defined (__DMC__)
+ #define ACE_UNUSED_ID(identifier)
+ template <class T>
+ inline void ACE_UNUSED_ARG(const T& ACE_UNUSED_ID(t)) { }
+#else /* ghs || __GNUC__ || ..... */
+# define ACE_UNUSED_ARG(a) (a)
+#endif /* ghs || __GNUC__ || ..... */
+
+#if defined (_MSC_VER) || defined(__sgi) || defined (ghs) || defined (__DECCXX) || defined(__BORLANDC__) || defined (ACE_RM544) || defined (__USLC__) || defined (__DCC__) || defined (__PGI) || defined (__TANDEM) || (defined (__HP_aCC) && (__HP_aCC >= 60500))
+# define ACE_NOTREACHED(a)
+#else /* __sgi || ghs || ..... */
+# define ACE_NOTREACHED(a) a
+#endif /* __sgi || ghs || ..... */
+
+// ============================================================================
+// ACE_ALLOC_HOOK* macros
+//
+// Macros to declare and define class-specific allocation operators.
+// ============================================================================
+
+# if defined (ACE_HAS_ALLOC_HOOKS)
+# define ACE_ALLOC_HOOK_DECLARE \
+ void *operator new (size_t bytes); \
+ void operator delete (void *ptr);
+
+ // Note that these are just place holders for now. Some day they
+ // may be be replaced by <ACE_Malloc>.
+# define ACE_ALLOC_HOOK_DEFINE(CLASS) \
+ void *CLASS::operator new (size_t bytes) { return ::new char[bytes]; } \
+ void CLASS::operator delete (void *ptr) { delete [] ((char *) ptr); }
+# else
+# define ACE_ALLOC_HOOK_DECLARE struct __Ace {} /* Just need a dummy... */
+# define ACE_ALLOC_HOOK_DEFINE(CLASS)
+# endif /* ACE_HAS_ALLOC_HOOKS */
+
+// ============================================================================
+/**
+ * ACE_OSCALL* macros
+ *
+ * @deprecated ACE_OSCALL_RETURN and ACE_OSCALL should not be used.
+ * Please restart system calls in your application code.
+ * See the @c sigaction(2) man page for documentation
+ * regarding enabling restartable system calls across
+ * signals via the @c SA_RESTART flag.
+ *
+ * The following two macros used ensure that system calls are properly
+ * restarted (if necessary) when interrupts occur. However, that
+ * capability was never enabled by any of our supported platforms.
+ * In fact, some parts of ACE would not function properly when that
+ * ability was enabled. Furthermore, they assumed that ability to
+ * restart system calls was determined statically. That assumption
+ * does not hold for modern platforms, where that ability is
+ * determined dynamically at run-time.
+ */
+// ============================================================================
+
+#define ACE_OSCALL_RETURN(X,TYPE,FAILVALUE) \
+ do \
+ return (TYPE) (X); \
+ while (0)
+#define ACE_OSCALL(X,TYPE,FAILVALUE,RESULT) \
+ do \
+ RESULT = (TYPE) (X); \
+ while (0)
+
+#if defined (ACE_WIN32)
+# if defined (__BORLANDC__) && (__BORLANDC__ <= 0x550)
+# define ACE_WIN32CALL_RETURN(X,TYPE,FAILVALUE) \
+ do { \
+ TYPE ace_result_; \
+ TYPE ace_local_result_ = (TYPE) X; \
+ ace_result_ = ace_local_result_; \
+ if (ace_result_ == FAILVALUE) \
+ ACE_OS::set_errno_to_last_error (); \
+ return ace_result_; \
+ } while (0)
+# else
+# define ACE_WIN32CALL_RETURN(X,TYPE,FAILVALUE) \
+ do { \
+ TYPE ace_result_ = (TYPE) X; \
+ if (ace_result_ == FAILVALUE) \
+ ACE_OS::set_errno_to_last_error (); \
+ return ace_result_; \
+ } while (0)
+# endif /* defined (__BORLANDC__) && (__BORLANDC__ <= 0x550) */
+# define ACE_WIN32CALL(X,TYPE,FAILVALUE,RESULT) \
+ do { \
+ RESULT = (TYPE) X; \
+ if (RESULT == FAILVALUE) \
+ ACE_OS::set_errno_to_last_error (); \
+ } while (0)
+
+#endif /* ACE_WIN32 */
+
+// The C99 security-improved run-time returns an error value on failure;
+// 0 on success.
+#if defined (ACE_HAS_TR24731_2005_CRT)
+# define ACE_SECURECRTCALL(X,TYPE,FAILVALUE,RESULT) \
+ do { \
+ errno_t ___ = X; \
+ if (___ != 0) { errno = ___; RESULT = FAILVALUE; } \
+ } while (0)
+#endif /* ACE_HAS_TR24731_2005_CRT */
+
+// ============================================================================
+// Fundamental types
+// ============================================================================
+
+#if defined (ACE_WIN32)
+
+typedef HANDLE ACE_HANDLE;
+typedef SOCKET ACE_SOCKET;
+# define ACE_INVALID_HANDLE INVALID_HANDLE_VALUE
+
+#else /* ! ACE_WIN32 */
+
+typedef int ACE_HANDLE;
+typedef ACE_HANDLE ACE_SOCKET;
+# define ACE_INVALID_HANDLE -1
+
+#endif /* ACE_WIN32 */
+
+// Define the type that's returned from the platform's native thread
+// functions. ACE_THR_FUNC_RETURN is the type defined as the thread
+// function's return type, except when the thread function doesn't return
+// anything (pSoS). The ACE_THR_FUNC_NO_RETURN_VAL macro is used to
+// indicate that the actual thread function doesn't return anything. The
+// rest of ACE uses a real type so there's no a ton of conditional code
+// everywhere to deal with the possibility of no return type.
+# if defined (ACE_VXWORKS) && !defined (ACE_HAS_PTHREADS)
+# include /**/ <taskLib.h>
+typedef int ACE_THR_FUNC_RETURN;
+#define ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN
+# elif defined (ACE_WIN32)
+typedef DWORD ACE_THR_FUNC_RETURN;
+#define ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN
+# else
+typedef void* ACE_THR_FUNC_RETURN;
+# endif /* ACE_VXWORKS */
+typedef ACE_THR_FUNC_RETURN (*ACE_THR_FUNC)(void *);
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+typedef void (*ACE_THR_C_DEST)(void *);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+typedef void (*ACE_THR_DEST)(void *);
+
+// Now some platforms have special requirements...
+# if defined (ACE_VXWORKS) && !defined (ACE_HAS_PTHREADS)
+typedef FUNCPTR ACE_THR_FUNC_INTERNAL; // where typedef int (*FUNCPTR) (...)
+# else
+typedef ACE_THR_FUNC ACE_THR_FUNC_INTERNAL;
+# endif /* ACE_VXWORKS */
+
+# ifdef __cplusplus
+extern "C"
+{
+# endif /* __cplusplus */
+# if defined (ACE_VXWORKS) && !defined (ACE_HAS_PTHREADS)
+typedef FUNCPTR ACE_THR_C_FUNC; // where typedef int (*FUNCPTR) (...)
+# else
+typedef ACE_THR_FUNC_RETURN (*ACE_THR_C_FUNC)(void *);
+# endif /* ACE_VXWORKS */
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+
+// ============================================================================
+// Macros for controlling the lifetimes of dlls loaded by ACE_DLL--including
+// all dlls loaded via the ACE Service Config framework.
+//
+// Please don't change these values or add new ones wantonly, since we use
+// the ACE_BIT_ENABLED, etc..., macros to test them.
+// ============================================================================
+
+// Per-process policy that unloads dlls eagerly.
+#define ACE_DLL_UNLOAD_POLICY_PER_PROCESS 0
+// Apply policy on a per-dll basis. If the dll doesn't use one of the macros
+// below, the current per-process policy will be used.
+#define ACE_DLL_UNLOAD_POLICY_PER_DLL 1
+// Don't unload dll when refcount reaches zero, i.e., wait for either an
+// explicit unload request or program exit.
+#define ACE_DLL_UNLOAD_POLICY_LAZY 2
+// Default policy allows dlls to control their own destinies, but will
+// unload those that don't make a choice eagerly.
+#define ACE_DLL_UNLOAD_POLICY_DEFAULT ACE_DLL_UNLOAD_POLICY_PER_DLL
+
+// Add this macro you one of your cpp file in your dll. X should
+// be either ACE_DLL_UNLOAD_POLICY_DEFAULT or ACE_DLL_UNLOAD_POLICY_LAZY.
+#define ACE_DLL_UNLOAD_POLICY(CLS,X) \
+extern "C" u_long CLS##_Export _get_dll_unload_policy (void) \
+ { return X;}
+
+// ============================================================================
+// ACE_USES_CLASSIC_SVC_CONF macro
+// ============================================================================
+
+// For now, default is to use the classic svc.conf format.
+#if !defined (ACE_USES_CLASSIC_SVC_CONF)
+# if defined (ACE_HAS_CLASSIC_SVC_CONF) && defined (ACE_HAS_XML_SVC_CONF)
+# error You can only use either CLASSIC or XML svc.conf, not both.
+# endif
+// Change the ACE_HAS_XML_SVC_CONF to ACE_HAS_CLASSIC_SVC_CONF when
+// we switch ACE to use XML svc.conf as default format.
+# if defined (ACE_HAS_XML_SVC_CONF)
+# define ACE_USES_CLASSIC_SVC_CONF 0
+# else
+# define ACE_USES_CLASSIC_SVC_CONF 1
+# endif /* ACE_HAS_XML_SVC_CONF */
+#endif /* ACE_USES_CLASSIC_SVC_CONF */
+
+// ============================================================================
+// Default svc.conf file extension.
+// ============================================================================
+#if defined (ACE_USES_CLASSIC_SVC_CONF) && (ACE_USES_CLASSIC_SVC_CONF == 1)
+# define ACE_DEFAULT_SVC_CONF_EXT ".conf"
+#else
+# define ACE_DEFAULT_SVC_CONF_EXT ".conf.xml"
+#endif /* ACE_USES_CLASSIC_SVC_CONF && ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+// ============================================================================
+// Miscellaneous macros
+// ============================================================================
+
+#if defined (ACE_USES_EXPLICIT_STD_NAMESPACE)
+# define ACE_STD_NAMESPACE std
+#else
+# define ACE_STD_NAMESPACE
+#endif
+
+#if !defined (ACE_OS_String)
+# define ACE_OS_String ACE_OS
+#endif /* ACE_OS_String */
+#if !defined (ACE_OS_Memory)
+# define ACE_OS_Memory ACE_OS
+#endif /* ACE_OS_Memory */
+#if !defined (ACE_OS_Dirent)
+# define ACE_OS_Dirent ACE_OS
+#endif /* ACE_OS_Dirent */
+#if !defined (ACE_OS_TLI)
+# define ACE_OS_TLI ACE_OS
+#endif /* ACE_OS_TLI */
+
+// -------------------------------------------------------------------
+// Preprocessor symbols will not be expanded if they are
+// concatenated. Force the preprocessor to expand them during the
+// argument prescan by calling a macro that itself calls another that
+// performs the actual concatenation.
+#define ACE_PREPROC_CONCATENATE_IMPL(A,B) A ## B
+#define ACE_PREPROC_CONCATENATE(A,B) ACE_PREPROC_CONCATENATE_IMPL(A,B)
+// -------------------------------------------------------------------
+
+#endif /* ACE_CONFIG_MACROS_H */
diff --git a/ACE/ace/config-minimal.h b/ACE/ace/config-minimal.h
new file mode 100644
index 00000000000..e7937690ee5
--- /dev/null
+++ b/ACE/ace/config-minimal.h
@@ -0,0 +1,39 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file is designed to build only the minimal
+// ACE_OS adaptation layer.
+
+#ifndef ACE_CONFIG_MINIMAL_H
+#define ACE_CONFIG_MINIMAL_H
+#include /**/ "ace/pre.h"
+
+#define ACE_HAS_MINIMAL_ACE_OS
+
+// Only instantiate the ACE_OS_Object_Manager.
+#define ACE_MAIN_OBJECT_MANAGER \
+ ACE_OS_Object_Manager ace_os_object_manager;
+
+#if !defined(ACE_USE_THREAD_MANAGER_ADAPTER)
+ // To prevent use of ACE_Thread_Exit functions in
+ // ACE_Thread_Adapter::invoke ().
+# define ACE_USE_THREAD_MANAGER_ADAPTER
+#endif /* ! ACE_USE_THREAD_MANAGER_ADAPTER */
+
+#if defined (ACE_ASSERT)
+# undef ACE_ASSERT
+#endif /* ACE_ASSERT */
+#define ACE_ASSERT(x)
+
+#if defined (ACE_DEBUG)
+# undef ACE_DEBUG
+#endif /* ACE_DEBUG */
+#define ACE_DEBUG(x)
+
+#if defined (ACE_ERROR)
+# undef ACE_ERROR
+#endif /* ACE_ERROR */
+#define ACE_ERROR(x)
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_MINIMAL_H */
diff --git a/ACE/ace/config-mvs.h b/ACE/ace/config-mvs.h
new file mode 100644
index 00000000000..3572bae3cde
--- /dev/null
+++ b/ACE/ace/config-mvs.h
@@ -0,0 +1,130 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Config file for MVS with OpenEdition
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+// The following #defines are hacks to get around things
+// that seem to be missing or different in MVS land
+#define MAXPATHLEN 1024 /* sys/param.h not on MVS */
+#define NSIG 44 /* missing from Signal.h */
+#define MAXHOSTNAMELEN 256 /* missing form netdb.h */
+#define howmany __howmany /* MVS uses different names than most others */
+#define fd_mask __fd_mask
+#define MAXNAMLEN __DIR_NAME_MAX
+#if defined (log) /* log is a macro in math.h */
+# undef log /* conflicts with log function in ACE */
+#endif /* log */
+
+#define ACE_MVS
+
+// Preprocesor requires an extra argument
+#define ACE_CC_PREPROCESSOR_ARGS "-+ -E"
+
+// See the README file in this directory
+// for a description of the following ACE_ macros
+
+#if __COMPILER_VER__ >= 0x21020000 /* OS/390 r2 or higher */
+# define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+# define ACE_HAS_UCONTEXT_T
+#else /* __COMPILER_VER__ < 0x21020000 */
+# define ACE_LACKS_UCONTEXT_H
+#endif /* __COMPILER_VER__ < 0x21020000 */
+
+#if __COMPILER_VER__ < 0x22060000 /* before OS/390 r2.6 */
+# define ACE_LACKS_LONGLONG_T
+#endif /* __COMPILER_VER__ < 0x22060000 */
+
+#define ERRMAX __sys_nerr
+
+#define ACE_HAS_3_PARAM_WCSTOK
+#define ACE_HAS_BROKEN_CTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_DIRENT
+#define ACE_HAS_GETPAGESIZE
+#define ACE_HAS_GETRUSAGE
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_LIMITED_RUSAGE_T
+#define ACE_HAS_MSG
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONSCALAR_THREAD_KEY_T
+#define ACE_HAS_POLL
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_PTHREADS
+#define ACE_HAS_PTHREAD_CONDATTR_SETKIND_NP
+#define ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SIG_C_FUNC
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SIZET_SOCKET_LEN
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_STRERROR
+#define ACE_HAS_STRBUF_T
+#define ACE_HAS_STRINGS
+#define ACE_HAS_SYSV_IPC
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+#define ACE_HAS_THREADS
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#define ACE_HAS_THR_C_DEST
+#define ACE_HAS_THR_C_FUNC
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+#define ACE_HAS_UALARM
+#define ACE_HAS_UTIME
+#define ACE_HAS_VOIDPTR_MMAP
+#define ACE_HAS_VOIDPTR_SOCKOPT
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_INET_ATON
+#define ACE_LACKS_MSGBUF_T
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_LACKS_IOSTREAM_FX
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MALLOC_H
+#define ACE_LACKS_PARAM_H
+#define ACE_LACKS_SYS_PARAM_H
+#define ACE_LACKS_PLACEMENT_OPERATOR_DELETE
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK
+#define ACE_LACKS_READDIR_R
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SCHED_H
+#define ACE_LACKS_SETSCHED
+#define ACE_LACKS_SEMAPHORE_H
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_STDINT_H
+#define ACE_LACKS_SYS_NERR
+#define ACE_LACKS_SYS_SELECT_H
+#define ACE_LACKS_SYS_SYSCTL_H
+#define ACE_LACKS_SYSTIME_H
+#define ACE_LACKS_NETINET_TCP_H
+#define ACE_LACKS_TCP_H
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+#define ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR
+#define ACE_LACKS_TIMESPEC_T
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+#define ACE_NEEDS_DEV_IO_CONVERSION
+
+#define ACE_SIZEOF_FLOAT 4
+#define ACE_SIZEOF_DOUBLE 8
+#define ACE_SIZEOF_LONG_DOUBLE 16
+#define ACE_HAS_EBCDIC
+
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+
+#define IN_CLASSD(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xe0000000)
+#define IN_MULTICAST(a) IN_CLASSD(a)
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-netbsd.h b/ACE/ace/config-netbsd.h
new file mode 100644
index 00000000000..7c25423fe4c
--- /dev/null
+++ b/ACE/ace/config-netbsd.h
@@ -0,0 +1,167 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+
+#ifndef ACE_MT_SAFE
+#define ACE_MT_SAFE 1
+#endif
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#endif /* __GNUG__ */
+
+#if defined(ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# define ACE_HAS_THREADS 1
+# define ACE_HAS_PTHREADS 1
+# define ACE_HAS_PTHREADS_UNIX98_EXT 1
+# define ACE_HAS_PTHREAD_RESUME_NP 1
+# define ACE_HAS_PTHREAD_SUSPEND_NP 1
+# define ACE_LACKS_PTHREAD_THR_SIGSETMASK 1
+# define ACE_LACKS_PTHREAD_YIELD 1
+#endif /* ACE_MT_SAFE */
+
+#define ACE_HAS_CLOCK_SETTIME 1
+#define ACE_HAS_CLOCK_GETTIME 1
+#define ACE_HAS_SETTIMEOFDAY 1
+#define ACE_HAS_GETTIMEOFDAY 1
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R 1
+#define ACE_HAS_3_PARAM_WCSTOK 1
+#define ACE_HAS_3_PARAM_READDIR_R 1
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG 1
+#define ACE_HAS_ALT_CUSERID 1
+#define ACE_HAS_AUTOMATIC_INIT_FINI 1
+#define ACE_HAS_CLOCK_GETTIME 1
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES 1
+#define ACE_HAS_DIRENT 1
+#define ACE_HAS_EXCEPTIONS 1
+#define ACE_HAS_GETIFADDRS 1
+#define ACE_HAS_GETPAGESIZE 1
+#define ACE_HAS_GETPROGNAME 1
+#define ACE_HAS_GETRUSAGE 1
+#define ACE_HAS_GETRUSAGE_PROTOTYPE 1
+#define ACE_HAS_GNU_CSTRING_H 1
+#define ACE_HAS_GPERF 1
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT 1
+#define ACE_HAS_IP_MULTICAST 1
+#define ACE_HAS_MSG 1
+#define ACE_HAS_NEW_NO_H 1
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL 1
+#define ACE_HAS_ONLY_SCHED_OTHER 1
+#define ACE_HAS_POLL 1
+#define ACE_HAS_POSITION_INDEPENDENT_POINTERS 1
+#define ACE_HAS_POSIX_NONBLOCK 1
+#define ACE_HAS_POSIX_TIME 1
+#define ACE_HAS_P_READ_WRITE 1
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS 1
+#define ACE_HAS_REENTRANT_FUNCTIONS 1
+#define ACE_HAS_SCANDIR 1
+#define ACE_HAS_SETPROGNAME 1
+#define ACE_HAS_SIGACTION_CONSTP2 1
+#define ACE_HAS_SIGINFO_T 1
+#define ACE_HAS_SIGSUSPEND 1
+#define ACE_HAS_SIGTIMEDWAIT 1
+#define ACE_HAS_SIGWAIT 1
+#define ACE_HAS_SIG_ATOMIC_T 1
+#define ACE_HAS_SIG_C_FUNC 1
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN 1
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN 1
+#define ACE_HAS_SOCKADDR_MSG_NAME 1
+#define ACE_HAS_SOCKLEN_T 1
+#define ACE_HAS_SSIZE_T 1
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+#define ACE_HAS_STDEXCEPT_NO_H 1
+#define ACE_HAS_STRERROR 1
+#define ACE_HAS_STRINGS 1
+#define ACE_HAS_STRING_CLASS 1
+#define ACE_HAS_SVR4_DYNAMIC_LINKING 1
+#define ACE_HAS_SYSV_IPC 1
+#define ACE_HAS_SYS_ERRLIST 1
+#define ACE_HAS_SYS_FILIO_H 1
+#define ACE_HAS_SYS_SIGLIST 1
+#define ACE_HAS_SYS_SOCKIO_H 1
+#define ACE_HAS_SYS_SYSCALL_H 1
+#define ACE_HAS_SYSCTL
+#define ACE_HAS_TERMIOS 1
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE 1
+#define ACE_HAS_TIMEZONE 1
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY 1
+#define ACE_HAS_UALARM 1
+#define ACE_HAS_UCONTEXT_T 1
+#define ACE_HAS_VOIDPTR_MMAP 1
+#define ACE_HAS_VOIDPTR_SOCKOPT 1
+#define ACE_HAS_WCHAR 1
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR 1
+#define ACE_IOCTL_TYPE_ARG2 u_long
+#define ACE_LACKS_CONDATTR_PSHARED 1
+#define ACE_LACKS_GETHOSTENT 1
+#define ACE_LACKS_GETIPNODEBYADDR 1
+#define ACE_LACKS_GETIPNODEBYNAME 1
+#define ACE_LACKS_IOSTREAM_FX 1
+#define ACE_LACKS_ITOW 1
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF 1
+#define ACE_LACKS_LOG2 1
+#define ACE_LACKS_MSG_ACCRIGHTS 1
+#define ACE_LACKS_MUTEXATTR_PSHARED 1
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS 1
+#define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#define ACE_LACKS_PRI_T 1
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK 1
+#define ACE_LACKS_PTHREAD_YIELD 1
+#define ACE_LACKS_PWD_REENTRANT_FUNCTIONS 1
+#define ACE_LACKS_RWLOCKATTR_PSHARED 1
+#define ACE_LACKS_RWLOCK_T 1
+#define ACE_LACKS_SETSCHED 1
+#define ACE_LACKS_SIGINFO_H 1
+#define ACE_LACKS_STROPTS_H 1
+#define ACE_LACKS_STRRECVFD 1
+#define ACE_LACKS_TIMEDWAIT_PROTOTYPES 1
+#define ACE_LACKS_TIMESPEC_T 1
+#define ACE_LACKS_UNBUFFERED_STREAMBUF 1
+#define ACE_LACKS_WCSDUP 1
+#define ACE_LACKS_WCSICMP 1
+#define ACE_LACKS_WCSNICMP 1
+#define ACE_SCANDIR_CMP_USES_CONST_VOIDPTR 1
+
+#if defined(__x86_64__)
+#define ACE_SIZEOF_DOUBLE 8
+#define ACE_SIZEOF_FLOAT 4
+#define ACE_SIZEOF_INT 4
+#define ACE_SIZEOF_LONG 8
+#define ACE_SIZEOF_LONG_DOUBLE 16
+#define ACE_SIZEOF_LONG_LONG 8
+#define ACE_SIZEOF_SHORT 2
+#define ACE_SIZEOF_VOID_P 8
+#define ACE_SIZEOF_WCHAR 4
+
+typedef unsigned long ACE_UINT64;
+typedef signed long ACE_INT64;
+
+#define ACE_SSIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%ld")
+#define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%lu")
+
+#elif defined(__i386__)
+
+#define ACE_SIZEOF_DOUBLE 8
+#define ACE_SIZEOF_FLOAT 4
+#define ACE_SIZEOF_INT 4
+#define ACE_SIZEOF_LONG 4
+#define ACE_SIZEOF_LONG_DOUBLE 12
+#define ACE_SIZEOF_LONG_LONG 8
+#define ACE_SIZEOF_SHORT 2
+#define ACE_SIZEOF_VOID_P 4
+#define ACE_SIZEOF_WCHAR 4
+
+typedef unsigned long long ACE_UINT64;
+typedef signed long long ACE_INT64;
+
+#else
+# error unknown CPU architecture
+#endif
+
+#endif /* ACE_CONFIG_H */
+
+// Local Variables:
+// mode:C++
+// End:
diff --git a/ACE/ace/config-openbsd.h b/ACE/ace/config-openbsd.h
new file mode 100644
index 00000000000..2ee50da19c8
--- /dev/null
+++ b/ACE/ace/config-openbsd.h
@@ -0,0 +1,235 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for OpenBSD
+// platforms using GNU g++.
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#if defined (ACE_HAS_THREADS)
+#include /**/ <pthread.h>
+#endif /* ACE_HAS_THREADS */
+
+#include "ace/config-posix.h"
+
+#if ! defined (__ACE_INLINE__)
+#define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#define ACE_SIZEOF_LONG_DOUBLE 12
+
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+#endif /* __GNUG__ */
+
+// Platform specific directives
+// gcc defines __OpenBSD__ automatically for us.
+#include <sys/param.h>
+
+#if defined (ACE_HAS_THREADS)
+#if !defined (_THREAD_SAFE)
+#define _THREAD_SAFE
+#endif /* _THREAD_SAFE */
+
+// Check if pthreads and native exceptions are being used together.
+// This causes SEGVs to tbe thrown somewhat randomly for some
+// reason. According to newsgroup postings, it appears to be an
+// OpenBSD or gcc bug.
+#if defined (ACE_USES_NATIVE_EXCEPTIONS)
+#error "OpenBSD pthreads and native exceptions currently do not work. See OpenBSD bug #1750"
+#endif /* ACE_USES_NATIVE_EXCEPTIONS */
+
+#endif /* ACE_HAS_THREADS */
+
+#define ACE_HAS_GPERF
+
+// Platform specific directives
+/* Are the following true? */
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREUID
+
+#define ACE_HAS_ALT_CUSERID
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+
+#define ACE_LACKS_RWLOCK_T
+#define ACE_HAS_SIG_MACROS
+#define ACE_HAS_CHARPTR_DL
+#define ACE_HAS_DIRENT
+
+// OpenBSD 3.6
+#if (OpenBSD < 200411)
+# define ACE_USES_ASM_SYMBOL_IN_DLSYM
+#endif
+
+#define ACE_LACKS_UCONTEXT_H
+
+// ucontext_t is in OpenBSD 3.5 and later.
+#if (OpenBSD >= 200405)
+# define ACE_HAS_UCONTEXT_T
+#endif /* OpenBSD >= 200405 */
+
+
+// OpenBSD has sigwait defined
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIGINFO_T
+
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_PWD_REENTRANT_FUNCTIONS
+#define ACE_LACKS_RAND_REENTRANT_FUNCTIONS
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+
+#define ACE_HAS_SOCKLEN_T
+
+#define ACE_HAS_POLL
+
+// Use of <malloc.h> is deprecated.
+#define ACE_LACKS_MALLOC_H
+
+// NetBSD appears to have a sigset_t type.
+// #define ACE_LACKS_SIGSET
+
+// Platform supports POSIX timers via struct timespec.
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_UALARM
+
+// Platform defines struct timespec but not timespec_t
+#define ACE_LACKS_TIMESPEC_T
+
+#define ACE_LACKS_STDINT_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_WCHAR_H
+
+#define ACE_LACKS_STRRECVFD
+
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+// OpenBSD supports the getifaddrs interface
+#define ACE_HAS_GETIFADDRS
+
+// Compiler/platform supports SVR4 signal typedef
+#define ACE_HAS_SVR4_SIGNAL_T
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Compiler/platform supports alloca().
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform supports SVR4 dynamic linking semantics..
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Explicit dynamic linking permits "lazy" symbol resolution
+#define ACE_HAS_RTLD_LAZY_V
+
+// platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+
+// Lacks perfect filtering, must bind group address.
+#if !defined ACE_LACKS_PERFECT_MULTICAST_FILTERING
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_LACKS_PERFECT_MULTICAST_FILTERING */
+
+// Compiler/platform has <alloca.h>
+//#define ACE_HAS_ALLOCA_H
+
+// Compiler/platform has the getrusage() system call.
+#define ACE_HAS_GETRUSAGE
+
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Compiler/platform defines a union semun for SysV shared memory.
+#define ACE_HAS_SEMUN
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Defines the page size of the system.
+#define ACE_PAGE_SIZE 4096
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+#define ACE_HAS_SYSCTL
+
+// Platform/compiler supports timezone * as second parameter to gettimeofday().
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+// OpenBSD's dlsym call segfaults when passed an invalid handle.
+// It seems as if most other OSs detect this and just report an
+// error.
+#define ACE_HAS_DLSYM_SEGFAULT_ON_INVALID_HANDLE
+
+#define ACE_HAS_MSG
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_NONCONST_MSGSND
+
+#ifdef ACE_HAS_THREADS
+// Thread specific settings
+
+// And they're even POSIX pthreads
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif /* ! ACE_MT_SAFE */
+#endif /* ACE_HAS_THREADS */
+
+#define ACE_HAS_SIGWAIT
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#define ACE_HAS_DIRENT
+
+#if !defined (ACE_HAS_THREADS)
+// OpenBSD really has readdir_r () in single threaded mode,
+// but the #ifdefs in OS.i select one with the wrong parameter
+// sets if the ACE_HAS_POSIX_STD isn't defined (which is defined
+// when ACE_HAS_THREADS is defined.)
+
+#define ACE_LACKS_READDIR_R
+
+#endif /* ! ACE_HAD_THREADS */
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+// OpenBSD 3.2 lacks sched_setscheduler (see /usr/src/lib/libc_r/TODO)
+#define ACE_LACKS_SETSCHED
+
+// OpenBSD supports IPv6 by default, but ACE IPv6 code
+// has compile errors.
+//#define ACE_HAS_IPV6
+
+#define ACE_HAS_3_PARAM_READDIR_R
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-openvms.h b/ACE/ace/config-openvms.h
new file mode 100644
index 00000000000..efb8af7ca4b
--- /dev/null
+++ b/ACE/ace/config-openvms.h
@@ -0,0 +1,198 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for OpenVMS 7.3-2
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+
+#if !defined (ACE_USE_RCSID)
+# define ACE_USE_RCSID 0
+#endif
+
+#ifdef __cplusplus
+#pragma message disable CODCAUUNR
+#pragma message disable CODEUNREACHABLE
+//#pragma message disable DOLLARID
+//#pragma message disable NOSIMPINT
+//#pragma message disable NOSTDLONGLONG
+#pragma message disable NARROWPTR
+//#pragma message disable LONGEXTERN
+#pragma message disable UNSCOMZER
+#endif
+
+// Use a signed int to match POSIX
+#define __SIGNED_INT_TIME_T
+
+#define ACE_OPENVMS __VMS_VER
+
+#define ACE_DLL_SUFFIX ACE_TEXT("")
+
+#define ACE_HAS_DUMP 1
+
+// need this includes to ensure proper sequence of definitions so that
+// f.i. HP C/C++ does not '#define ' memcpy, memmove etc.
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#undef clearerr
+#undef memset
+#undef memcpy
+#undef memmove
+
+#if defined(__ia64__)
+ // on OpenVMS IA64 we need this get the singleton exported since we build
+ // ACE/TAO with the NOTEMPLATES export option which prohibits exporting
+ // of any template symbols unless explicitly exported
+ #define ACE_HAS_CUSTOM_EXPORT_MACROS
+ #define ACE_Proper_Export_Flag
+ #define ACE_Proper_Import_Flag
+ #define ACE_EXPORT_SINGLETON_DECLARATION(T) template class __declspec (dllexport) T
+ #define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class __declspec (dllexport) SINGLETON_TYPE<CLASS, LOCK>;
+#else
+ #define ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION
+#endif
+
+#define ACE_DEFAULT_BASE_ADDR ((char*)(0x30000000))
+
+#define ACE_MAX_UDP_PACKET_SIZE 65535
+
+#define ACE_HAS_STDCPP_STL_INCLUDES 1
+
+/* missing system headers */
+#define ACE_LACKS_STDINT_H 1
+#define ACE_LACKS_SYS_IPC_H 1
+#define ACE_LACKS_SYS_SEM_H 1
+#define ACE_LACKS_SEMAPHORE_H 1
+#define ACE_LACKS_SYS_SELECT_H 1
+#define ACE_LACKS_TERMIOS_H 1
+#define ACE_LACKS_SYS_SHM_H 1
+#define ACE_LACKS_SYS_MSG_H 1
+#define ACE_LACKS_REGEX_H 1
+#define ACE_LACKS_SEARCH_H 1
+#define ACE_LACKS_SCHED_H 1
+#define ACE_LACKS_SYS_SYSCTL_H 1
+#define ACE_LACKS_MALLOC_H 1
+#define ACE_LACKS_SYS_PARAM_H 1
+#define ACE_LACKS_SIGINFO_H 1
+#define ACE_LACKS_UCONTEXT_H 1
+
+/* missing rtl functions */
+#define ACE_LACKS_SETPGID 1
+#define ACE_LACKS_SETREUID 1
+#define ACE_LACKS_SETREGID 1
+#define ACE_LACKS_FORK 1
+#define ACE_LACKS_GETPGID 1
+#define ACE_LACKS_SETSID 1
+#define ACE_LACKS_FCNTL 1
+#define ACE_LACKS_SETEGID 1
+#define ACE_LACKS_SETEUID 1
+
+#define ACE_LACKS_REALPATH 1
+
+#define ACE_LACKS_SYMLINKS 1
+
+#define ACE_LACKS_PWD_REENTRANT_FUNCTIONS 1
+#define ACE_LACKS_RAND_REENTRANT_FUNCTIONS 1
+
+#define ACE_HAS_P_READ_WRITE
+#define ACE_HAS_CHARPTR_DL 1
+#define ACE_HAS_CLOCK_GETTIME 1
+#define ACE_HAS_CLOCK_SETTIME 1
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY 1
+#define ACE_HAS_DIRENT 1
+#define ACE_HAS_GETPAGESIZE 1
+#define ACE_HAS_MSG
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL 1
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R 1
+#define ACE_HAS_3_PARAM_WCSTOK 1
+#define ACE_HAS_SIGSUSPEND 1
+#define ACE_HAS_SIG_MACROS 1
+#define ACE_HAS_SIGWAIT 1
+#define ACE_HAS_SIGTIMEDWAIT 1
+
+#define ACE_HAS_SIG_C_FUNC 1
+#define ACE_HAS_SIGISMEMBER_BUG
+#define ACE_HAS_STRNLEN 1
+#define ACE_HAS_STREAMS 1
+#define ACE_HAS_STRERROR 1
+#define ACE_HAS_UALARM 1
+#define ACE_HAS_VOIDPTR_MMAP 1
+#define ACE_HAS_VOIDPTR_SOCKOPT 1
+#define ACE_LACKS_LSTAT 1
+#define ACE_LACKS_MADVISE 1
+#define ACE_LACKS_MKFIFO 1
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS 1
+#define ACE_LACKS_READLINK 1
+#define ACE_LACKS_RLIMIT 1
+#define ACE_LACKS_RLIMIT_PROTOTYPE 1
+#define ACE_LACKS_SETSCHED
+#define ACE_LACKS_SYSCALL 1
+
+/* (missing) standard data types */
+#define ACE_LACKS_CONST_TIMESPEC_PTR 1
+#define ACE_LACKS_SUSECONDS_T 1
+#define ACE_HAS_IDTYPE_T 1
+#define ACE_HAS_SIGINFO_T 1
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR 1
+#define ACE_HAS_SIZET_SOCKET_LEN 1
+#define ACE_HAS_SSIZE_T 1
+#define ACE_LACKS_PRI_T 1
+#define ACE_LACKS_SEMBUF_T 1
+#define ACE_LACKS_STRRECVFD 1
+#define ACE_LACKS_T_ERRNO 1
+
+/* POSIX threads ompatibilities */
+#define ACE_LACKS_RWLOCK_T 1
+#define ACE_LACKS_PTHREAD_KILL 1
+#define ACE_LACKS_THREAD_PROCESS_SCOPING 1
+
+#define ACE_HAS_PTHREADS 1
+#define ACE_HAS_PTHREAD_PROCESS_ENUM 1
+#define ACE_LACKS_UNNAMED_SEMAPHORE 1
+#define ACE_MT_SAFE 1
+#define ACE_HAS_THREADS 1
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE 1
+#define ACE_HAS_THR_C_DEST 1
+#define ACE_HAS_THR_C_FUNC 1
+#define ACE_LACKS_PTHREAD_SIGMASK 1
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK 1
+#define ACE_NEEDS_HUGE_THREAD_STACKSIZE (64U*1024)
+#define ACE_HAS_PTHREAD_SETCONCURRENCY 1
+#define ACE_HAS_PTHREAD_GETCONCURRENCY 1
+#define ACE_HAS_PTHREAD_SCHEDPARAM 1
+
+/* language/platform conformance */
+#define ACE_NEW_THROWS_EXCEPTIONS 1
+#define ACE_TEMPLATES_REQUIRE_SOURCE 1
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#define ACE_HAS_AUTOMATIC_INIT_FINI 1
+#define ACE_LACKS_UNIX_SIGNALS 1
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES 1
+#define ACE_HAS_CPLUSPLUS_HEADERS 1
+#define ACE_HAS_EXCEPTIONS 1
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF 1
+
+#define ACE_HAS_GPERF 1
+#define ACE_HAS_IP_MULTICAST 1
+#define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#define ACE_HAS_POSIX_NONBLOCK 1
+#define ACE_HAS_POSIX_TIME 1
+#define ACE_HAS_BROKEN_POSIX_TIME 1
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+#define ACE_HAS_STRING_CLASS 1
+#define ACE_HAS_SVR4_DYNAMIC_LINKING 1
+#define ACE_HAS_TEMPLATE_SPECIALIZATION 1
+
+#define ACE_HAS_TEMPLATE_TYPEDEFS 1
+#define ACE_LACKS_NAMED_POSIX_SEM 1
+#define ACE_LACKS_SYSV_SHMEM 1
+#define ACE_LACKS_UNIX_DOMAIN_SOCKETS 1
+#define ACE_LACKS_UNIX_SYSLOG 1
+#define ACE_LACKS_ALPHASORT 1
+
+#define ACE_HAS_SOCK_BUF_SIZE_MAX
+#define ACE_HAS_SOCK_BUF_SIZE_MAX_VALUE 65535
+
+#endif
diff --git a/ACE/ace/config-pharlap.h b/ACE/ace/config-pharlap.h
new file mode 100644
index 00000000000..83d2eb9b5b0
--- /dev/null
+++ b/ACE/ace/config-pharlap.h
@@ -0,0 +1,86 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file is for use with the PharLap Realtime ETS Kernel.
+// It has been tested with PharLap TNT Embedded ToolSuite version 9.1.
+
+#ifndef ACE_CONFIG_PHARLAP_H
+#define ACE_CONFIG_PHARLAP_H
+#include /**/ "ace/pre.h"
+
+#define ACE_HAS_PHARLAP
+// Some features are only available with the Realtime edition of ETS.
+// Assume that if using ACE, the realtime version is also being used, but
+// allow it to be turned off as well.
+#ifndef ACE_HAS_PHARLAP_RT
+# define ACE_HAS_PHARLAP_RT
+#else
+# if (ACE_HAS_PHARLAP_RT == 0)
+# undef ACE_HAS_PHARLAP_RT
+# endif
+#endif
+
+// Fortunately, PharLap ETS offers much of the Win32 API. But it's still on
+// Winsock 1.1
+#define ACE_HAS_WINSOCK2 0
+
+// The TSS implementation doesn't pass muster on the TSS_Test, but it works
+// well with ACE's TSS emulation.
+#define ACE_HAS_TSS_EMULATION
+
+#define ACE_LACKS_MMAP
+#define ACE_LACKS_MPROTECT
+#define ACE_LACKS_MSYNC
+#define ACE_LACKS_TCP_NODELAY
+#define ACE_LACKS_MSG_WFMO
+#define ACE_LACKS_WIN32_MOVEFILEEX
+#define ACE_LACKS_WIN32_REGISTRY
+#define ACE_LACKS_WIN32_SECURITY_DESCRIPTORS
+#define ACE_LACKS_WIN32_SERVICES
+#define ACE_LACKS_WIN32_SETFILEPOINTEREX
+
+// There's no host table, by default. So using "localhost" won't work.
+// If your system does have the ability to use "localhost" and you want to,
+// define it before including this file.
+#if !defined (ACE_LOCALHOST)
+# define ACE_LOCALHOST "127.0.0.1"
+#endif /* ACE_LOCALHOST */
+
+// The normal Windows default stack size doesn't hold for ETS. Set what you
+// want explicitly.
+#if !defined (ACE_DEFAULT_THREAD_STACKSIZE)
+# define ACE_DEFAULT_THREAD_STACKSIZE (1024*1024)
+#endif /* ACE_DEFAULT_THREAD_STACKSIZE */
+
+// Don't know how to get the page size at execution time. This is most likely
+// the correct value.
+#define ACE_PAGE_SIZE 4096
+
+#if defined (ACE_HAS_PHARLAP_RT)
+# define ACE_HAS_IP_MULTICAST
+ // ETS winsock doesn't define IP level socket options
+//# define IP_TOS 8
+#endif /* ACE_HAS_PHARLAP_RT */
+
+// Let the config-win32.h file do its thing
+#undef ACE_CONFIG_H
+#include "ace/config-win32.h"
+// Now remove things that desktop/server Windows has but Pharlap ETS doesn't.
+#undef ACE_HAS_INTERLOCKED_EXCHANGEADD
+#undef ACE_HAS_WCHAR
+
+#include /**/ <embkern.h>
+#if defined (ACE_HAS_PHARLAP_RT)
+# include /**/ <embtcpip.h>
+#define ACE_LACKS_IP_ADD_MEMBERSHIP
+#endif /* ACE_HAS_PHARLAP_RT */
+
+// Although IN_CLASSD is defined in both winsock.h and winsock2.h, it ends
+// up undefined for Pharlap ETS builds. If this is the case, set things up
+// so nothing looks like class D.
+#if !defined (IN_CLASSD)
+# define IN_CLASSD(i) (0)
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_PHARLAP_H */
diff --git a/ACE/ace/config-posix-nonetworking.h b/ACE/ace/config-posix-nonetworking.h
new file mode 100644
index 00000000000..d87b20c340b
--- /dev/null
+++ b/ACE/ace/config-posix-nonetworking.h
@@ -0,0 +1,86 @@
+/* -*- C -*- */
+// $Id$
+
+/* The following configuration file is designed to work for RTEMS
+ platforms using GNU C.
+*/
+
+#ifndef ACE_CONFIG_POSIX_NONETWORKING_H
+#define ACE_CONFIG_POSIX_NONETWORKING_H
+
+// Missing header files
+# define ACE_LACKS_SYS_UIO_H
+# define ACE_LACKS_SYS_SOCKET_H
+# define ACE_LACKS_NETINET_IN_H
+# define ACE_LACKS_NETDB_H
+# define ACE_LACKS_ARPA_INET_H
+# define ACE_LACKS_SYS_SELECT_H
+# define ACE_LACKS_NET_IF_H
+# define ACE_LACKS_SYSLOG_H
+# define ACE_LACKS_SYS_UN_H
+# define ACE_LACKS_MEMORY_H
+# define ACE_LACKS_SYS_SYSCTL_H
+# define ACE_LACKS_NETINET_TCP_H
+
+// Missing types
+# define ACE_LACKS_IOVEC
+# define ACE_LACKS_IN_ADDR
+# define ACE_LACKS_SOCKADDR_IN
+# define ACE_LACKS_SOCKADDR_UN
+# define ACE_LACKS_HOSTENT
+# define ACE_LACKS_SOCKADDR
+# define ACE_LACKS_IP_MREQ
+# define ACE_LACKS_PROTOENT
+# define ACE_LACKS_SERVENT
+# define ACE_LACKS_IFREQ
+# define ACE_LACKS_IFCONF
+# define ACE_LACKS_LINGER
+
+// Missing methods
+# define ACE_LACKS_GETHOSTBYADDR
+# define ACE_LACKS_GETHOSTBYNAME
+# define ACE_LACKS_GETIPNODEBYADDR
+# define ACE_LACKS_LISTEN
+# define ACE_LACKS_BIND
+# define ACE_LACKS_NTOHL
+# define ACE_LACKS_HTONL
+# define ACE_LACKS_HTONS
+# define ACE_LACKS_NTOHS
+# define ACE_LACKS_SELECT
+# define ACE_LACKS_SOCKET
+# define ACE_LACKS_SHUTDOWN
+# define ACE_LACKS_SETSOCKOPT
+# define ACE_LACKS_INET_ATON
+# define ACE_LACKS_INET_ADDR
+# define ACE_LACKS_INET_NTOA
+# define ACE_LACKS_GET_BCAST_ADDR
+# define ACE_LACKS_GETHOSTENT
+# define ACE_LACKS_GETSERVBYNAME
+# define ACE_LACKS_ACCEPT
+# define ACE_LACKS_CONNECT
+# define ACE_LACKS_GETPEERNAME
+# define ACE_LACKS_GETSOCKNAME
+# define ACE_LACKS_GETSOCKOPT
+# define ACE_LACKS_RECV
+# define ACE_LACKS_SEND
+# define ACE_LACKS_SENDTO
+# define ACE_LACKS_RECVFROM
+# define ACE_LACKS_RECVMSG
+# define ACE_LACKS_SENDMSG
+# define ACE_LACKS_GETHOSTBYADDR_R
+# define ACE_LACKS_GETPROTOBYNAME
+# define ACE_LACKS_GETPROTOBYNUMBER
+# define ACE_LACKS_GETSERVBYNAME
+# define ACE_LACKS_READV
+# define ACE_LACKS_WRITEV
+# define ACE_LACKS_SOCKETPAIR
+# undef ACE_HAS_MSG
+
+// Missing OS features
+# define ACE_LACKS_UNIX_SYSLOG
+# define ACE_LACKS_TCP_NODELAY
+
+// Missing ACE features
+# define ACE_DISABLE_NOTIFY_PIPE_DEFAULT 1
+
+#endif /* ACE_CONFIG_POSIX_NONETWORKING_H */
diff --git a/ACE/ace/config-posix.h b/ACE/ace/config-posix.h
new file mode 100644
index 00000000000..482e2b91d10
--- /dev/null
+++ b/ACE/ace/config-posix.h
@@ -0,0 +1,72 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_CONFIG_POSIX_H
+#define ACE_CONFIG_POSIX_H
+
+#include <unistd.h>
+
+/* The following POSIX constants are defined after <unistd.h> is
+ * included. They are documented in:
+ * http://www.opengroup.org/onlinepubs/007904975/basedefs/unistd.h.html
+ */
+#if defined(_POSIX_REALTIME_SIGNALS) && (_POSIX_REALTIME_SIGNALS-0 != -1 )
+# if !defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
+# define ACE_HAS_POSIX_REALTIME_SIGNALS
+# endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
+#endif /* _POSIX_REALTIME_SIGNALS */
+
+#if defined(_POSIX_ASYNCHRONOUS_IO) && (_POSIX_ASYNCHRONOUS_IO-0 != -1 )
+# if !defined(ACE_HAS_AIO_CALLS)
+# define ACE_HAS_AIO_CALLS
+# endif /* ACE_HAS_AIO_CALLS */
+#endif /* _POSIX_ASYNCHRONOUS_IO */
+
+#if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE != 0)
+# if defined(_POSIX_SEMAPHORES) && (_POSIX_SEMAPHORES-0 != -1 )
+# if !defined(ACE_HAS_POSIX_SEM)
+# define ACE_HAS_POSIX_SEM
+# endif /* ACE_HAS_POSIX_SEM */
+# if defined(ACE_HAS_POSIX_SEM)
+# if !defined (ACE_HAS_POSIX_SEM_TIMEOUT) && defined (_POSIX_TIMEOUTS)
+# define ACE_HAS_POSIX_SEM_TIMEOUT
+# endif /* ACE_HAS_POSIX_SEM_TIMEOUT && _POSIX_TIMEOUTS */
+# endif /* ACE_HAS_POSIX_SEM */
+# endif /* ACE_HAS_POSIX_SEM */
+#endif /* !ACE_MT_SAFE */
+
+#if defined(_POSIX_SHARED_MEMORY_OBJECTS) && (_POSIX_SHARED_MEMORY_OBJECTS-0 != -1 )
+# if !defined(ACE_HAS_SHM_OPEN)
+# define ACE_HAS_SHM_OPEN
+# endif /* ACE_HAS_SHM_OPEN */
+#endif /* _POSIX_SHARED_MEMORY_OBJECTS */
+
+// Check if threading enabled/disable through platform_macros
+#if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE != 0)
+// Allow the user to disable use of threads by setting ACE_HAS_THREADS to 0
+// before including this file. The platform config (not macros) file can
+// often detect that the compiler was invoked with or without threads support
+// and set this accordingly.
+# if defined (ACE_HAS_THREADS) && (ACE_HAS_THREADS == 0)
+# undef ACE_HAS_THREADS
+# else
+# if defined(_POSIX_THREADS) && (_POSIX_THREADS-0 != -1 )
+# if !defined(ACE_HAS_THREADS)
+# define ACE_HAS_THREADS
+# endif /* ACE_HAS_THREADS */
+
+# if !defined(ACE_HAS_PTHREADS)
+# define ACE_HAS_PTHREADS
+# endif /* ACE_HAS_PTHREADS */
+
+# endif /* _POSIX_THREADS */
+# endif /* ACE_HAS_THREADS */
+#endif /* !ACE_MT_SAFE */
+
+#if defined(_POSIX_MESSAGE_PASSING) && (_POSIX_MESSAGE_PASSING-0 != -1 )
+# if !defined(ACE_HAS_POSIX_MESSAGE_PASSING)
+# define ACE_HAS_POSIX_MESSAGE_PASSING
+# endif /* ACE_HAS_POSIX_MESSAGE_PASSING */
+#endif /* _POSIX_MESSAGE_PASSING */
+
+#endif /* ACE_CONFIG_POSIX_H */
diff --git a/ACE/ace/config-qnx-neutrino.h b/ACE/ace/config-qnx-neutrino.h
new file mode 100644
index 00000000000..ba53271f0b5
--- /dev/null
+++ b/ACE/ace/config-qnx-neutrino.h
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+// $Id$
+// The following configuration file is designed to work for Neutrino
+// 2.0 (Beta) with GNU C++ and the POSIX (pthread) threads package.
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#define _POSIX_C_SOURCE 199506
+#define _QNX_SOURCE
+
+// These constants are in i386-nto/include/limits.h, but egcs
+// picks up its own limits.h instead:
+#define _POSIX_NAME_MAX 14 /* Max bytes in a filename */
+#define _POSIX_PATH_MAX 256 /* Num. bytes in pathname (excl. NULL) */
+
+#if defined(__OPTIMIZE__)
+# if defined(__X86__)
+ // string.h can't be used by ACE with __OPTIMIZE__.
+# undef __OPTIMIZE__
+# include <string.h>
+# define __OPTIMIZE__
+# endif /* __X86__ */
+#endif /* __OPTIMIZE__ */
+
+#include "ace/config-g++-common.h"
+
+// The following defines the Neutrino compiler.
+// gcc should know to call g++ as necessary
+#ifdef __GNUC__
+# define ACE_CC_NAME ACE_TEXT ("gcc")
+#else
+# define ACE_CC_NAME ACE_TEXT ("NTO compiler ??")
+#endif
+
+// /usr/nto/include/float.h defines
+// FLT_MAX_EXP 127
+// DBL_MAX_EXP 1023
+// ace expects 128 & 1024 respectively
+// to set the following macros in ace/Basic_Types.h
+// These macros are:
+// #define ACE_SIZEOF_DOUBLE 8
+// #define ACE_SIZEOF_FLOAT 4
+
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+#define ACE_HAS_ALLOCA_H
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_DIRENT
+#define ACE_HAS_GETPAGESIZE
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#define ACE_HAS_INLINED_OSCALLS
+#define ACE_HAS_IP_MULTICAST
+#define ACE_HAS_MSG
+#define ACE_HAS_MT_SAFE_MKTIME
+#define ACE_HAS_MUTEX_TIMEOUTS
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONCONST_SWAB
+#define ACE_HAS_POSIX_SEM
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_PTHREADS
+#define ACE_HAS_P_READ_WRITE
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_HAS_SELECT_H
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGISMEMBER_BUG
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SIG_MACROS
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_STRERROR
+#define ACE_HAS_STRINGS
+#define ACE_HAS_SVR4_GETTIMEOFDAY
+#define ACE_HAS_TERMIOS
+#define ACE_HAS_THREADS
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#define ACE_HAS_THR_C_DEST
+#define ACE_HAS_THR_C_FUNC
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+#define ACE_HAS_UALARM
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_VOIDPTR_MMAP
+#define ACE_HAS_VOIDPTR_SOCKOPT
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_CONST_TIMESPEC_PTR
+#define ACE_LACKS_CUSERID
+#define ACE_LACKS_FORK
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_LACKS_NAMED_POSIX_SEM
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SBRK
+#define ACE_LACKS_SEEKDIR
+#define ACE_LACKS_SOCKET_BUFSIZ
+#define ACE_LACKS_SOCKETPAIR
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_STREAM_MODULES
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SYSCALL
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_TCP_NODELAY
+#define ACE_LACKS_TELLDIR
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_TRUNCATE
+#define ACE_LACKS_T_ERRNO
+#define ACE_LACKS_UALARM_PROTOTYPE
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_UNIX_DOMAIN_SOCKETS
+#define ACE_LACKS_U_LONGLONG_T
+#define ACE_MT_SAFE 1
+#define ACE_NEEDS_FUNC_DEFINITIONS
+#define ACE_NEEDS_HUGE_THREAD_STACKSIZE 65536
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+#define ACE_THR_PRI_FIFO_DEF 10
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-qnx-rtp-62x.h b/ACE/ace/config-qnx-rtp-62x.h
new file mode 100644
index 00000000000..6ccea40af39
--- /dev/null
+++ b/ACE/ace/config-qnx-rtp-62x.h
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+// $Id$
+// The following configuration file is designed to work for QNX RTP 621
+// GNU C++ and the POSIX (pthread) threads package. You can get QNX
+// RTP at http://get.qnx.com
+#ifndef ACE_CONFIG_QNX_RTP_62x_H
+#define ACE_CONFIG_QNX_RTP_62x_H
+#include /**/ "ace/pre.h"
+#include /**/ "ace/config-qnx-rtp-common.h"
+
+/////////////////////////////////////////////////////////////////
+// Definition of the features that are available.
+//
+// ACE_HAS Section
+/////////////////////////////////////////////////////////////////
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+#define ACE_HAS_3_PARAM_WCSTOK
+#define ACE_HAS_3_PARAM_READDIR_R
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+#define ACE_HAS_ALLOCA_H
+#define ACE_HAS_ALT_CUSERID
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_DIRENT
+#define ACE_HAS_GETPAGESIZE
+#define ACE_HAS_GETIFADDRS
+// Enable gperf, this is a hosted configuration.
+#define ACE_HAS_GPERF
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+//#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#define ACE_HAS_IP_MULTICAST
+#define ACE_HAS_MSG
+#define ACE_HAS_MT_SAFE_MKTIME
+#define ACE_HAS_MUTEX_TIMEOUTS
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONCONST_SWAB
+#define ACE_HAS_POSIX_SEM
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_PTHREADS
+#define ACE_HAS_P_READ_WRITE
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_HAS_SELECT_H
+#define ACE_HAS_SHM_OPEN
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGISMEMBER_BUG
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SIG_MACROS
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SOCKLEN_T
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_STRERROR
+#define ACE_HAS_STRINGS
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_HAS_SVR4_GETTIMEOFDAY
+#define ACE_HAS_TERMIOS
+#define ACE_HAS_THREADS
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#define ACE_HAS_THR_C_DEST
+#define ACE_HAS_THR_C_FUNC
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+#define ACE_HAS_UALARM
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_VOIDPTR_MMAP
+#define ACE_HAS_VOIDPTR_SOCKOPT
+
+/////////////////////////////////////////////////////////////////
+// Definition of the features that are not available.
+//
+// ACE_LACKS Section
+/////////////////////////////////////////////////////////////////
+#define ACE_LACKS_CONST_TIMESPEC_PTR
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+#define ACE_LACKS_MADVISE
+// lacks mqueue mgr or speed-up named sem by shm emulation
+#define ACE_LACKS_NAMED_POSIX_SEM
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+// Multicast_Tests reports for NTO 621 frames from unsubscribed groups
+#define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SOCKET_BUFSIZ
+#define ACE_LACKS_STREAM_MODULES
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_STRPTIME
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SYSCALL
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_T_ERRNO
+#define ACE_LACKS_U_LONGLONG_T
+#define ACE_LACKS_ALPHASORT
+
+#define ACE_LACKS_RLIMIT // QNX rlimit syscalls don't work properly with ACE.
+
+#define ACE_MT_SAFE 1
+#define ACE_NEEDS_FUNC_DEFINITIONS
+#define ACE_NEEDS_HUGE_THREAD_STACKSIZE 64000
+#define ACE_THR_PRI_FIFO_DEF 10
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+
+#define ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK 1
+
+#define ACE_SIZEOF_WCHAR 4
+
+// No prototypes
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+#define ACE_LACKS_WCSDUP
+// The default value of FD_SETSIZE is 32, but actually x86 NTO
+// supports by default at least 1000 descriptors in fd_set.
+#if defined( FD_SETSIZE )
+#undef FD_SETSIZE
+#endif
+#define FD_SETSIZE 1000
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_QNX_RTP_62x_H*/
diff --git a/ACE/ace/config-qnx-rtp-common.h b/ACE/ace/config-qnx-rtp-common.h
new file mode 100644
index 00000000000..66879685763
--- /dev/null
+++ b/ACE/ace/config-qnx-rtp-common.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+// $Id$
+// several macros common to various qnx neutrino version.
+
+#ifndef ACE_CONFIG_QNX_RTP_COMMON_H
+#define ACE_CONFIG_QNX_RTP_COMMON_H
+#include /**/ "ace/pre.h"
+
+#define _POSIX_C_SOURCE 199506
+#define _QNX_SOURCE
+
+// These constants are in i386-nto/include/limits.h, but egcs
+// picks up its own limits.h instead:
+#define _POSIX_NAME_MAX 14 /* Max bytes in a filename */
+#define _POSIX_PATH_MAX 256 /* Num. bytes in pathname (excl. NULL) */
+
+#if defined(__OPTIMIZE__)
+# if defined(__X86__)
+ // string.h can't be used by ACE with __OPTIMIZE__.
+# undef __OPTIMIZE__
+# include <string.h>
+# define __OPTIMIZE__
+# endif /* __X86__ */
+#endif /* __OPTIMIZE__ */
+
+#include "ace/config-g++-common.h"
+
+// The following defines the Neutrino compiler.
+// gcc should know to call g++ as necessary
+#ifdef __GNUC__
+# define ACE_CC_NAME ACE_TEXT ("gcc")
+#else
+# define ACE_CC_NAME ACE_TEXT ("QNX-RTP compiler ??")
+#endif
+
+// /usr/nto/include/float.h defines
+// FLT_MAX_EXP 127
+// DBL_MAX_EXP 1023
+// ace expects 128 & 1024 respectively
+// to set the following macros in ace/Basic_Types.h
+// These macros are:
+#define ACE_SIZEOF_DOUBLE 8
+#define ACE_SIZEOF_FLOAT 4
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_QNX_RTP_COMMON_H */
diff --git a/ACE/ace/config-qnx-rtp-pre62x.h b/ACE/ace/config-qnx-rtp-pre62x.h
new file mode 100644
index 00000000000..00ad0166f18
--- /dev/null
+++ b/ACE/ace/config-qnx-rtp-pre62x.h
@@ -0,0 +1,151 @@
+// -*- C++ -*-
+// $Id$
+// The following configuration file is designed to work for QNX RTP
+// GNU C++ and the POSIX (pthread) threads package. You can get QNX
+// RTP at http://get.qnx.com
+
+#ifndef ACE_CONFIG_RTP_PRE62x_H
+#define ACE_CONFIG_RTP_PRE62x_H
+#include /**/ "ace/pre.h"
+#include /**/ "ace/config-qnx-rtp-common.h"
+
+/////////////////////////////////////////////////////////////////
+// Definition of the features that are available.
+//
+// ACE_HAS Section
+/////////////////////////////////////////////////////////////////
+
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+#define ACE_HAS_ALLOCA_H
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_DIRENT
+#define ACE_HAS_GETPAGESIZE
+// Enable gperf, this is a hosted configuration.
+#define ACE_HAS_GPERF
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+//#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#define ACE_HAS_INLINED_OSCALLS
+#define ACE_HAS_IP_MULTICAST
+#define ACE_HAS_MSG
+#define ACE_HAS_MT_SAFE_MKTIME
+#define ACE_HAS_MUTEX_TIMEOUTS
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_POSIX_SEM
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_PTHREADS
+#define ACE_HAS_P_READ_WRITE
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_HAS_SELECT_H
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGISMEMBER_BUG
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SIG_MACROS
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+// #define ACE_HAS_SIZET_SOCKET_LEN
+#define ACE_HAS_SOCKLEN_T
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_STRERROR
+#define ACE_HAS_STRINGS
+#define ACE_HAS_SVR4_GETTIMEOFDAY
+#define ACE_HAS_TERMIOS
+#define ACE_HAS_THREADS
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#define ACE_HAS_THR_C_DEST
+#define ACE_HAS_THR_C_FUNC
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+#define ACE_HAS_UALARM
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_VOIDPTR_MMAP
+#define ACE_HAS_VOIDPTR_SOCKOPT
+
+/////////////////////////////////////////////////////////////////
+// Definition of the features that are not available.
+//
+// ACE_LACKS Section
+/////////////////////////////////////////////////////////////////
+#define ACE_LACKS_CONDATTR_PSHARED
+#define ACE_LACKS_CONST_TIMESPEC_PTR
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MUTEXATTR_PSHARED
+#define ACE_LACKS_NAMED_POSIX_SEM
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SBRK
+#define ACE_LACKS_SEEKDIR
+#define ACE_LACKS_SOCKET_BUFSIZ
+#define ACE_LACKS_SOCKETPAIR
+// Even if the QNX RTP docs says that socket pair are
+// available, there is actually no implementation of
+// soket-pairs.
+#define ACE_LACKS_STREAM_MODULES
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SYSCALL
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_ALPHASORT
+//#define ACE_LACKS_TCP_NODELAY // Based on the QNX RTP documentation, this option seems to
+ // to be supported.
+#define ACE_LACKS_TELLDIR
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_TRUNCATE
+#define ACE_LACKS_T_ERRNO
+#define ACE_LACKS_UALARM_PROTOTYPE
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_UNIX_DOMAIN_SOCKETS
+#define ACE_LACKS_U_LONGLONG_T
+
+#define ACE_LACKS_RLIMIT // QNX rlimit syscalls don't work properly with ACE.
+
+#define ACE_MT_SAFE 1
+#define ACE_NEEDS_FUNC_DEFINITIONS
+#define ACE_NEEDS_HUGE_THREAD_STACKSIZE 64000
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+#define ACE_THR_PRI_FIFO_DEF 10
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+
+#define ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK 1
+
+#define ACE_SIZEOF_WCHAR 4
+
+// Not really, but the prototype returns wchar_t instead of wchar_t *
+#define ACE_LACKS_WCSSTR
+
+// No prototypes
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+#define ACE_LACKS_WCSDUP
+
+// And these have prototypes but no implementation
+#define ACE_LACKS_WCSLEN
+#define ACE_LACKS_WCSNCMP
+#define ACE_LACKS_WCSCPY
+#define ACE_LACKS_WCSNCPY
+#define ACE_LACKS_TOWLOWER
+#define ACE_LACKS_TOWUPPER
+#define ACE_LACKS_WCSCMP
+#define ACE_LACKS_WCSCAT
+#define ACE_LACKS_WCSNCAT
+#define ACE_LACKS_WCSSPN
+#define ACE_LACKS_WCSCHR
+#define ACE_LACKS_WCSPBRK
+#define ACE_LACKS_WCSRCHR
+
+#define ACE_LACKS_ACE_IOSTREAM
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_RTP_PRE62x_H */
diff --git a/ACE/ace/config-qnx-rtp.h b/ACE/ace/config-qnx-rtp.h
new file mode 100644
index 00000000000..513d6eb1b00
--- /dev/null
+++ b/ACE/ace/config-qnx-rtp.h
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+// $Id$
+// The following configuration file is designed to work for QNX RTP
+// GNU C++ and the POSIX (pthread) threads package. You can get QNX
+// RTP at http://get.qnx.com.
+// This header is intended to switch between configuration for
+// various NTO versions.
+#ifndef ACE_CONFIG_QNX_RTP_H
+#define ACE_CONFIG_QNX_RTP_H
+#include /**/ "ace/pre.h"
+
+#include <sys/neutrino.h>
+#if !defined(_NTO_VERSION)
+# error "Could not detect QNX version from macro _NTO_VERSION"
+#else
+# define ACE_NTO_VERS _NTO_VERSION
+# if ACE_NTO_VERS < 620
+# include /**/ "ace/config-qnx-rtp-pre62x.h"
+# else
+# include /**/ "ace/config-qnx-rtp-62x.h"
+# endif
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_QNX_RTP_H */
diff --git a/ACE/ace/config-rtems.h b/ACE/ace/config-rtems.h
new file mode 100644
index 00000000000..b32fbb8c15a
--- /dev/null
+++ b/ACE/ace/config-rtems.h
@@ -0,0 +1,165 @@
+/* -*- C -*- */
+// $Id$
+
+/* The following configuration file is designed to work for RTEMS
+ platforms using GNU C.
+*/
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+
+#if ! defined (__ACE_INLINE__)
+#define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// Needed to make some prototypes visible.
+// #if ! defined (_GNU_SOURCE)
+// #define _GNU_SOURCE
+// #endif /* ! _GNU_SOURCE */
+
+// First the machine specific part
+// There are no known port specific issues with the RTEMS port of ACE.
+// XXX Pentium and PowerPC have high res timer support in ACE.
+
+// Then the compiler specific parts
+#if defined (__GNUG__)
+ // config-g-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+ // this must appear before its #include.
+# define ACE_HAS_STRING_CLASS
+# include "ace/config-g++-common.h"
+#else /* ! __GNUG__ */
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler in ace/config-rtems.h
+# endif /* __cplusplus */
+#endif /* ! __GNUG__ */
+
+#include "ace/config-posix.h"
+
+// Completely common part :-)
+
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+
+#define ACE_LACKS_ALPHASORT
+#define ACE_LACKS_REGEX_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_DLFCN_H
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_STRINGS_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETEUID
+#define ACE_LACKS_POLL_H
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_LACKS_STRCASECMP
+#define ACE_LACKS_MKSTEMP
+#define ACE_LACKS_STRDUP
+#define ACE_LACKS_STRTOK_R
+#define ACE_LACKS_RAND_REENTRANT_FUNCTIONS
+#define ACE_LACKS_REALPATH
+#define ACE_LACKS_TEMPNAM
+
+// Temporarily, enabling this results in compile errors with
+// rtems 4.6.6.
+#define ACE_LACKS_WCHAR_H
+
+#if !defined (ACE_MT_SAFE)
+#define ACE_MT_SAFE 1
+#endif
+
+#if ACE_MT_SAFE
+# define ACE_HAS_THREADS
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+# define ACE_HAS_PTHREAD_SCHEDPARAM
+# define ACE_LACKS_THREAD_PROCESS_SCOPING
+#else
+# define ACE_HAS_POSIX_GETPWNAM_R
+# define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+#endif
+
+#define ACE_HAS_ALT_CUSERID
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_3_PARAM_READDIR_R
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_DIRENT
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_MSG
+#define ACE_HAS_MT_SAFE_MKTIME
+#define ACE_HAS_NONCONST_READV
+#define ACE_HAS_GETPAGESIZE
+#define ACE_HAS_POSIX_SEM
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_HAS_SIGACTION_CONSTP2
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGSUSPEND
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_STRERROR
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY
+#define ACE_HAS_SYS_ERRLIST
+#define ACE_HAS_SYS_FILIO_H
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+#define ACE_LACKS_EXEC
+#define ACE_LACKS_FILELOCKS
+#define ACE_LACKS_FORK
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MMAP
+#define ACE_LACKS_MPROTECT
+#define ACE_LACKS_MSYNC
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK
+#define ACE_LACKS_READDIR_R
+#define ACE_LACKS_READLINK
+#define ACE_LACKS_READV
+#define ACE_LACKS_RLIMIT
+#define ACE_LACKS_RLIMIT_PROTOTYPE
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SBRK
+#define ACE_LACKS_SEMBUF_T
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_SETREUID_PROTOTYPE
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREGID_PROTOTYPE
+#define ACE_LACKS_STRPTIME
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SI_ADDR
+#define ACE_LACKS_SOCKETPAIR
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_SYSCALL
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_HAS_NONCONST_WRITEV
+#define ACE_LACKS_WRITEV
+#define ACE_NEEDS_HUGE_THREAD_STACKSIZE 65536
+#define ACE_NEEDS_SCHED_H
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_TERMIOS
+
+// rtems 4.7 or higher
+#if (__RTEMS_MAJOR__ > 4) || (__RTEMS_MAJOR__ == 4 && __RTEMS_MINOR__ > 6)
+# define ACE_HAS_UALARM
+#else
+# define ACE_HAS_NOTSUP_SC_PAGESIZE
+# define ACE_LACKS_SUSECONDS_T
+# define ACE_LACKS_INTPTR_T
+# undef ACE_HAS_SHM_OPEN
+# undef ACE_HAS_AIO_CALLS
+#endif
+
+// __RTEMS_REVISION__ could also be used but this is broken according
+// to the rtems people
+
+#if !defined (_POSIX_REALTIME_SIGNALS)
+# define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#endif
+
+#if defined (ACE_LACKS_NETWORKING)
+# include "ace/config-posix-nonetworking.h"
+#endif
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sco-5.0.0-nothread.h b/ACE/ace/config-sco-5.0.0-nothread.h
new file mode 100644
index 00000000000..5c7b0b06c0f
--- /dev/null
+++ b/ACE/ace/config-sco-5.0.0-nothread.h
@@ -0,0 +1,14 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#include "ace/config-g++-common.h"
+#include "ace/config-sco-5.0.0.h"
+
+#define ACE_HAS_GNU_CSTRING_H
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sco-5.0.0.h b/ACE/ace/config-sco-5.0.0.h
new file mode 100644
index 00000000000..519b74a2ead
--- /dev/null
+++ b/ACE/ace/config-sco-5.0.0.h
@@ -0,0 +1,97 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_CONFIG_SCO_5_0_0_H
+#define ACE_CONFIG_SCO_5_0_0_H
+#include /**/ "ace/pre.h"
+
+// Compiling for SCO.
+#if !defined (SCO)
+#define SCO
+#endif /* SCO */
+
+#if defined (SCO) && !defined (MAXPATHLEN)
+#define MAXPATHLEN 1023
+#endif /* SCO */
+
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_SIG_MACROS
+#define ACE_LACKS_CONST_TIMESPEC_PTR
+#define ACE_LACKS_SYSCALL
+#define ACE_LACKS_STRRECVFD
+#define ACE_NEEDS_FTRUNCATE
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+
+#define ACE_DEFAULT_CLOSE_ALL_HANDLES 0
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+#define ACE_HAS_NONCONST_MSGSND
+#define ACE_HAS_BIG_FD_SET
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+// Compiler/platform contains the <sys/syscall.h> file.
+//#define ACE_HAS_SYS_SYSCALL_H
+
+// Fixes a problem with HP/UX not wrapping the mmap(2) header files
+// with extern "C".
+//#define ACE_HAS_BROKEN_MMAP_H
+
+// Prototypes for both signal() and struct sigaction are consistent.
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Compiler/platform has correctly prototyped header files.
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Header files lack t_errno for ACE_TLI.
+//#define ACE_LACKS_T_ERRNO
+
+// Compiler/platform supports poll().
+// #define ACE_HAS_POLL
+
+// Platform supports POSIX O_NONBLOCK semantics.
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Compiler/platform defines the sig_atomic_t typedef
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Compiler supports the ssize_t typedef.
+//#define ACE_HAS_SSIZE_T
+
+// Defines the page size of the system.
+#define ACE_PAGE_SIZE 4096
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+// Note, this only works if the flag is set above!
+//#define ACE_HAS_GETRUSAGE
+
+// Platform uses int for select() rather than fd_set.
+#define ACE_HAS_SELECT_H
+
+// Platform has prototypes for ACE_TLI.
+#define ACE_HAS_TLI_PROTOTYPES
+// Platform has the XLI version of ACE_TLI.
+// #define ACE_HAS_XLI
+
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_UCONTEXT_T
+
+#define ACE_LACKS_STRCASECMP
+
+// #define ACE_HAS_POSIX_TIME
+#define ACE_HAS_IP_MULTICAST
+#define ACE_HAS_DIRENT
+#define ACE_LACKS_READDIR_R
+#define ACE_HAS_GPERF
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_SCO_5_0_0_H */
diff --git a/ACE/ace/config-suncc-common.h b/ACE/ace/config-suncc-common.h
new file mode 100644
index 00000000000..953b04fd2a0
--- /dev/null
+++ b/ACE/ace/config-suncc-common.h
@@ -0,0 +1,68 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifndef ACE_SUNCC_COMMON_H
+#define ACE_SUNCC_COMMON_H
+#include /**/ "ace/pre.h"
+
+# define ACE_HAS_CPLUSPLUS_HEADERS
+# define ACE_HAS_STDCPP_STL_INCLUDES
+# define ACE_HAS_TEMPLATE_TYPEDEFS
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_HAS_TEMPLATE_SPECIALIZATION
+# define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# define ACE_HAS_STRING_CLASS
+# define ACE_EXPLICIT_TEMPLATE_DESTRUCTOR_TAKES_ARGS
+# define ACE_HAS_THR_C_DEST 1
+# define ACE_LACKS_SWAB
+#if defined (ACE_HAS_CUSTOM_EXPORT_MACROS) && ACE_HAS_CUSTOM_EXPORT_MACROS == 0
+# undef ACE_HAS_CUSTOM_EXPORT_MACROS
+#else
+# ifndef ACE_HAS_CUSTOM_EXPORT_MACROS
+# define ACE_HAS_CUSTOM_EXPORT_MACROS
+# endif /* !ACE_HAS_CUSTOM_EXPORT_MACROS */
+# define ACE_Proper_Export_Flag __attribute__ ((visibility("default")))
+# define ACE_Proper_Import_Flag
+# define ACE_EXPORT_SINGLETON_DECLARATION(T) template class ACE_Proper_Export_Flag T
+# define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class ACE_Proper_Export_Flag SINGLETON_TYPE <CLASS, LOCK>;
+# define ACE_IMPORT_SINGLETON_DECLARATION(T) __extension__ extern template class T
+# define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) __extension__ extern template class SINGLETON_TYPE<CLASS, LOCK>;
+#endif /* ACE_HAS_CUSTOM_EXPORT_MACROS == 0 */
+
+// __EXCEPTIONS is defined with -fexceptions, the egcs default. It
+// is not defined with -fno-exceptions, the ACE default for g++.
+// ACE_HAS_EXCEPTIONS is defined in
+// include/makeinclude/wrapper_macros.GNU, so this really isn't
+// necessary. Just in case . . .
+# if defined (__EXCEPTIONS) && !defined (ACE_HAS_EXCEPTIONS)
+# define ACE_HAS_EXCEPTIONS
+# endif /* __EXCEPTIONS && ! ACE_HAS_EXCEPTIONS */
+
+# if defined (ACE_HAS_EXCEPTIONS)
+# define ACE_NEW_THROWS_EXCEPTIONS
+# endif /* ACE_HAS_EXCEPTIONS */
+
+#if (defined (i386) || defined (__i386__)) && !defined (ACE_SIZEOF_LONG_DOUBLE)
+# define ACE_SIZEOF_LONG_DOUBLE 12
+#endif /* i386 */
+
+#if defined (i386) || defined (__i386__)
+ // If running an Intel, assume that it's a Pentium so that
+ // ACE_OS::gethrtime () can use the RDTSC instruction. If running a
+ // 486 or lower, be sure to comment this out. (If not running an
+ // Intel CPU, this #define will not be seen because of the i386
+ // protection, so it can be ignored.)
+# define ACE_HAS_PENTIUM
+#endif /* i386 */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+ // We define it with a -D with make depend.
+# define ACE_LACKS_PRAGMA_ONCE
+#endif /* ! ACE_LACKS_PRAGMA_ONCE */
+
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+
+#include /**/ "ace/post.h"
+#endif /* ACE_SUNCC_COMMON_H */
diff --git a/ACE/ace/config-sunos5.10.h b/ACE/ace/config-sunos5.10.h
new file mode 100644
index 00000000000..fd29f1076aa
--- /dev/null
+++ b/ACE/ace/config-sunos5.10.h
@@ -0,0 +1,46 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for SunOS 5.10
+// (Solaris 10) platforms using the SunC++ 5.x (Sun Studio 8-10), or g++
+// compilers.
+
+#ifndef ACE_CONFIG_H
+
+// ACE_CONFIG_H is defined by one of the following #included headers.
+
+// #include the SunOS 5.9 config, then add any SunOS 5.10 updates below.
+#include "ace/config-sunos5.9.h"
+
+// Solaris 10 can do sem_timedwait() (see ACE_OS::sema_wait).
+#define ACE_HAS_POSIX_SEM_TIMEOUT
+
+#define ACE_HAS_SCANDIR
+
+// Solaris 10 offers a useable alphasort() unlike previous Solaris versions.
+#if defined (ACE_LACKS_ALPHASORT)
+# undef ACE_LACKS_ALPHASORT
+#endif
+
+// Solaris 10 offers a useable log2() unlike previous Solaris versions.
+#if defined (ACE_LACKS_LOG2)
+# undef ACE_LACKS_LOG2
+#endif
+
+// Solaris 10 delivers pthread_attr_setstack
+#if defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
+# undef ACE_LACKS_PTHREAD_ATTR_SETSTACK
+#endif
+
+// Solaris 10 introduced printf() modifiers for [s]size_t types.
+#if defined (ACE_SSIZE_T_FORMAT_SPECIFIER)
+# undef ACE_SSIZE_T_FORMAT_SPECIFIER
+# define ACE_SSIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%zd")
+#endif /* ACE_SSIZE_T_FORMAT_SPECIFIER */
+
+#if defined (ACE_SIZE_T_FORMAT_SPECIFIER)
+# undef ACE_SIZE_T_FORMAT_SPECIFIER
+# define ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("%zu")
+#endif /* ACE_SIZE_T_FORMAT_SPECIFIER */
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sunos5.11.h b/ACE/ace/config-sunos5.11.h
new file mode 100644
index 00000000000..d42497a7b63
--- /dev/null
+++ b/ACE/ace/config-sunos5.11.h
@@ -0,0 +1,15 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for SunOS 5.11
+// (Solaris 11) platforms using the SunC++ 5.x (Sun Studio 10-12), or g++
+// compilers.
+
+#ifndef ACE_CONFIG_H
+
+// ACE_CONFIG_H is defined by one of the following #included headers.
+
+// #include the SunOS 5.10 config, then add any SunOS 5.11 updates below.
+#include "ace/config-sunos5.10.h"
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sunos5.4-g++.h b/ACE/ace/config-sunos5.4-g++.h
new file mode 100644
index 00000000000..002ea42ed86
--- /dev/null
+++ b/ACE/ace/config-sunos5.4-g++.h
@@ -0,0 +1,180 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for SunOS 5.4
+// platforms using the GNU g++ compiler.
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// config-g++-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+// this must appear before its #include.
+#define ACE_HAS_STRING_CLASS
+
+#include "ace/config-g++-common.h"
+#define ACE_HAS_GNU_CSTRING_H
+
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// Platform supports pread() and pwrite()
+#define ACE_HAS_P_READ_WRITE
+
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Sun has the wrong prototype for sendmsg.
+#define ACE_HAS_NONCONST_SENDMSG
+
+// The SunOS 5.x version of rand_r is inconsistent with the header files...
+#define ACE_HAS_BROKEN_RANDR
+
+// Platform supports system configuration information.
+#define ACE_HAS_SYSINFO
+
+// Platform supports the POSIX regular expression library
+#define ACE_HAS_REGEX
+
+// Platform supports recvmsg and sendmsg.
+#define ACE_HAS_MSG
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Platform supports POSIX O_NONBLOCK semantics.
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Compiler/platform has correctly prototyped header files.
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Compiler/platform supports SunOS high resolution timers.
+#define ACE_HAS_HI_RES_TIMER
+
+// Platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+
+// Compiler/platform supports alloca()
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform has <alloca.h>
+#define ACE_HAS_ALLOCA_H
+
+// Platform contains <poll.h>.
+#define ACE_HAS_POLL
+
+// Platform supports POSIX timers via timestruc_t.
+#define ACE_HAS_POSIX_TIME
+
+// Platform supports the /proc file system.
+#define ACE_HAS_PROC_FS
+
+// Platform supports the prusage_t struct.
+#define ACE_HAS_PRUSAGE_T
+
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Platform supports SVR4 extended signals.
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_UCONTEXT_T
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Platform supports STREAMS.
+#define ACE_HAS_STREAMS
+
+// Platform supports STREAM pipes.
+#define ACE_HAS_STREAM_PIPES
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform supports struct strbuf.
+#define ACE_HAS_STRBUF_T
+
+// Compiler/platform supports SVR4 dynamic linking semantics.
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+// Compiler/platform supports SVR4 gettimeofday() prototype.
+#define ACE_HAS_SVR4_GETTIMEOFDAY
+
+// Platform lacks pthread_sigaction
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK
+
+// Compiler/platform supports SVR4 TLI (in particular, T_GETNAME stuff)...
+#define ACE_HAS_SVR4_TLI
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Compiler/platform supports sys_siglist array.
+#define ACE_HAS_SYS_SIGLIST
+
+/* Turn off the following defines if you want to disable threading. */
+// Compile using multi-thread libraries.
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+# if !defined (_REENTRANT)
+# define _REENTRANT
+# endif /* _REENTRANT */
+#endif /* !ACE_MT_SAFE */
+
+// Platform supports Solaris threads.
+#define ACE_HAS_STHREADS
+
+// Platform supports threads.
+#define ACE_HAS_THREADS
+
+// Compiler/platform has thread-specific storage
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+// Platform supports reentrant functions (i.e., all the POSIX *_r functions).
+#define ACE_HAS_REENTRANT_FUNCTIONS
+
+/* end threading defines */
+
+#define ACE_HAS_PRIOCNTL
+#define ACE_NEEDS_LWP_PRIO_SET
+
+// Platform supports TLI timod STREAMS module.
+#define ACE_HAS_TIMOD_H
+
+// Platform supports TLI tiuser header.
+#define ACE_HAS_TIUSER_H
+
+// Platform provides TLI function prototypes.
+#define ACE_HAS_TLI_PROTOTYPES
+
+// Platform supports TLI.
+#define ACE_HAS_TLI
+
+// Use the poll() event demultiplexor rather than select().
+//#define ACE_USE_POLL
+
+// Defines the page size of the system.
+#define ACE_PAGE_SIZE 4096
+#define ACE_HAS_IDTYPE_T
+#define ACE_HAS_GPERF
+#define ACE_HAS_DIRENT
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sunos5.4-sunc++-4.x.h b/ACE/ace/config-sunos5.4-sunc++-4.x.h
new file mode 100644
index 00000000000..882307aab64
--- /dev/null
+++ b/ACE/ace/config-sunos5.4-sunc++-4.x.h
@@ -0,0 +1,191 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for SunOS 5.4
+// platforms using the SunC++ 4.0.x compiler.
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// Platform supports pread() and pwrite()
+#define ACE_HAS_P_READ_WRITE
+
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// Sun has the wrong prototype for sendmsg.
+#define ACE_HAS_NONCONST_SENDMSG
+
+// The SunOS 5.x version of rand_r is inconsistent with the header files...
+#define ACE_HAS_BROKEN_RANDR
+
+// Platform supports system configuration information.
+#define ACE_HAS_SYSINFO
+
+// Platform supports the POSIX regular expression library.
+#define ACE_HAS_REGEX
+
+// Platform supports recvmsg and sendmsg.
+#define ACE_HAS_MSG
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Platform supports POSIX O_NONBLOCK semantics.
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Compiler/platform has correctly prototyped header files.
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Compiler/platform supports SunOS high resolution timers.
+#define ACE_HAS_HI_RES_TIMER
+
+// Platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+
+// Compiler/platform supports alloca()
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform has <alloca.h>
+#define ACE_HAS_ALLOCA_H
+
+// Platform contains <poll.h>.
+#define ACE_HAS_POLL
+
+// Platform supports POSIX timers via timestruc_t.
+#define ACE_HAS_POSIX_TIME
+
+// Platform supports the /proc file system.
+#define ACE_HAS_PROC_FS
+
+// Platform supports the prusage_t struct.
+#define ACE_HAS_PRUSAGE_T
+
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Platform supports SVR4 extended signals.
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_UCONTEXT_T
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Platform supports STREAMS.
+#define ACE_HAS_STREAMS
+
+// Platform supports STREAM pipes.
+#define ACE_HAS_STREAM_PIPES
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform supports struct strbuf.
+#define ACE_HAS_STRBUF_T
+
+// Compiler/platform supports SVR4 dynamic linking semantics.
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+// Compiler/platform supports SVR4 gettimeofday() prototype.
+#define ACE_HAS_SVR4_GETTIMEOFDAY
+
+// Compiler/platform supports SVR4 signal typedef.
+#define ACE_HAS_SVR4_SIGNAL_T
+
+// Platform lacks pthread_sigaction
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK
+
+// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)...
+#define ACE_HAS_SVR4_TLI
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Compiler/platform supports sys_siglist array.
+#define ACE_HAS_SYS_SIGLIST
+
+/* Turn off the following defines if you want to disable threading. */
+// Compile using multi-thread libraries.
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+// Platform supports Solaris threads.
+#define ACE_HAS_STHREADS
+
+// Platform supports threads.
+#define ACE_HAS_THREADS
+
+// Compiler/platform has thread-specific storage
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+// Platform supports reentrant functions (i.e., all the POSIX *_r functions).
+#define ACE_HAS_REENTRANT_FUNCTIONS
+
+/* end threading defines */
+
+#define ACE_HAS_PRIOCNTL
+#define ACE_NEEDS_LWP_PRIO_SET
+
+// Reactor detects deadlock
+// #define ACE_REACTOR_HAS_DEADLOCK_DETECTION
+
+// Platform supports ACE_TLI timod STREAMS module.
+#define ACE_HAS_TIMOD_H
+
+// Platform supports ACE_TLI tiuser header.
+#define ACE_HAS_TIUSER_H
+
+// Platform provides ACE_TLI function prototypes.
+#define ACE_HAS_TLI_PROTOTYPES
+
+// Platform supports ACE_TLI.
+#define ACE_HAS_TLI
+
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+#define ACE_LACKS_SIGNED_CHAR
+
+// Use the poll() event demultiplexor rather than select().
+//#define ACE_USE_POLL
+
+#define ACE_NEEDS_DEV_IO_CONVERSION
+
+// Defines the page size of the system.
+#define ACE_PAGE_SIZE 4096
+#define ACE_HAS_IDTYPE_T
+
+#define ACE_HAS_GPERF
+#define ACE_HAS_DIRENT
+
+# if defined (ACE_HAS_EXCEPTIONS)
+ // If exceptions are enabled and we are using Sun/CC then
+ // <operator new> throws an exception instead of returning 0.
+# define ACE_NEW_THROWS_EXCEPTIONS
+# endif /* ACE_HAS_EXCEPTIONS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sunos5.5.h b/ACE/ace/config-sunos5.5.h
new file mode 100644
index 00000000000..8666932642c
--- /dev/null
+++ b/ACE/ace/config-sunos5.5.h
@@ -0,0 +1,414 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file is designed to work for SunOS 5.5 platforms
+// using the following compilers:
+// * Sun C++ 4.2 and later (including 5.x), patched as noted below
+// * g++ 2.7.2 and later, including egcs
+// * Green Hills 1.8.8 and later
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#define ACE_LACKS_STDINT_H
+
+// alphasort() is present on earlier Solaris versions but is marked as not for
+// use on non-BSD systems and not supported for use in applications that use
+// system libraries or with multiple threads. So it's mostly useless.
+#define ACE_LACKS_ALPHASORT
+
+// Solaris doesn't support log2()
+#define ACE_LACKS_LOG2
+
+// SunOS 5.5 does not provide getloadavg()
+#define ACE_LACKS_GETLOADAVG
+
+// Before we do anything, we should include <sys/feature_tests.h> to
+// ensure that things are set up properly.
+#include <sys/feature_tests.h>
+
+// Sun has the posix defines so let this file sort out what Sun delivers
+#include "ace/config-posix.h"
+
+// Compiler version-specific settings:
+#if defined (__SUNPRO_CC)
+# if (__SUNPRO_CC < 0x410)
+ // The following might not be necessary, but I can't tell: my build
+ // with Sun C++ 4.0.1 never completes.
+# define ACE_NEEDS_DEV_IO_CONVERSION
+# elif (__SUNPRO_CC >= 0x420)
+# if (__SUNPRO_CC >= 0x500)
+ // string.h and memory.h conflict for memchr definitions
+# define ACE_LACKS_MEMORY_H
+ // If -compat=4 is turned on, the old 4.2 settings for iostreams are used,
+ // but the newer, explicit instantiation is used (above)
+# if (__SUNPRO_CC_COMPAT >= 5)
+# define ACE_HAS_TEMPLATE_TYPEDEFS
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# define ACE_HAS_THR_C_DEST
+# endif /* __SUNPRO_CC_COMPAT >= 5 */
+# if defined (ACE_HAS_EXCEPTIONS)
+# define ACE_HAS_NEW_NOTHROW
+# else
+ // See /opt/SUNWspro_5.0/SC5.0/include/CC/stdcomp.h:
+# define _RWSTD_NO_EXCEPTIONS 1
+# endif /* ! ACE_HAS_EXCEPTIONS */
+# elif (__SUNPRO_CC == 0x420) || (__SUNPRO_CC == 0x410)
+# define ACE_LACKS_PLACEMENT_OPERATOR_DELETE
+# endif /* __SUNPRO_CC >= 0x500 */
+# endif /* __SUNPRO_CC >= 0x420 */
+
+# define ACE_CAST_CONST const
+# define ACE_HAS_HI_RES_TIMER
+# define ACE_HAS_SIG_C_FUNC /* Sun CC 5.0 needs this, 4.2 doesn't mind. */
+# define ACE_HAS_TEMPLATE_SPECIALIZATION
+# define ACE_HAS_XPG4_MULTIBYTE_CHAR
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+# define ACE_LACKS_SIGNED_CHAR
+
+ // ACE_HAS_EXCEPTIONS precludes -noex in
+ // include/makeinclude/platform_macros.GNU. But beware, we have
+ // seen problems with exception handling on multiprocessor
+ // UltraSparcs: threaded executables core dump when threads exit.
+ // This problem does not seem to appear on single-processor UltraSparcs.
+ // And, it is solved with the application of patch
+ // 104631-02 "C++ 4.2: Jumbo Patch for C++ 4.2 on Solaris SPARC"
+ // to Sun C++ 4.2.
+ // To provide optimum performance, ACE_HAS_EXCEPTIONS is disabled by
+ // default. It can be enabled by adding "exceptions=1" to the "make"
+ // invocation. See include/makeinclude/platform_sunos5_sunc++.GNU
+ // for details.
+
+# if defined (ACE_HAS_EXCEPTIONS)
+ // If exceptions are enabled and we are using Sun/CC then
+ // <operator new> throws an exception instead of returning 0.
+# define ACE_NEW_THROWS_EXCEPTIONS
+# endif /* ACE_HAS_EXCEPTIONS */
+
+ /* If you want to disable threading with Sun CC, remove -mt
+ from your CFLAGS, e.g., using make threads=0. */
+
+
+// Take advantage of Sun Studio 8 (Sun C++ 5.5) or better symbol
+// visibility to generate improved shared library binaries.
+# if (__SUNPRO_CC > 0x540)
+
+# if defined (ACE_HAS_CUSTOM_EXPORT_MACROS) && ACE_HAS_CUSTOM_EXPORT_MACROS == 0
+# undef ACE_HAS_CUSTOM_EXPORT_MACROS
+# else
+# ifndef ACE_HAS_CUSTOM_EXPORT_MACROS
+# define ACE_HAS_CUSTOM_EXPORT_MACROS
+# endif /* !ACE_HAS_CUSTOM_EXPORT_MACROS */
+# define ACE_Proper_Export_Flag __symbolic
+# define ACE_Proper_Import_Flag __global
+
+# define ACE_EXPORT_SINGLETON_DECLARATION(T) template class ACE_Proper_Export_Flag T
+# define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class ACE_Proper_Export_Flag SINGLETON_TYPE <CLASS, LOCK>;
+
+// # define ACE_IMPORT_SINGLETON_DECLARATION(T) extern template class T
+// # define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) extern template class SINGLETON_TYPE<CLASS, LOCK>;
+
+# endif /* ACE_HAS_CUSTOM_EXPORT_MACROS == 0 */
+# endif /* __SUNPRO_CC > 0x540 (> Sun C++ 5.4) */
+
+#elif defined (__GNUG__)
+ // config-g++-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+ // this must appear before its #include.
+# define ACE_HAS_STRING_CLASS
+# include "ace/config-g++-common.h"
+# define ACE_HAS_HI_RES_TIMER
+ // Denotes that GNU has cstring.h as standard, to redefine memchr().
+# define ACE_HAS_GNU_CSTRING_H
+# define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+# if !defined (ACE_MT_SAFE) || ACE_MT_SAFE != 0
+ // ACE_MT_SAFE is #defined below, for all compilers.
+# if !defined (_REENTRANT)
+ /* If you want to disable threading, comment out the following
+ line. Or, add -DACE_MT_SAFE=0 to your CFLAGS, e.g., using
+ make threads=0. */
+# define _REENTRANT
+# endif /* _REENTRANT */
+# endif /* !ACE_MT_SAFE */
+
+#elif defined (ghs)
+
+# if !defined (ACE_MT_SAFE) || ACE_MT_SAFE != 0
+ // ACE_MT_SAFE is #defined below, for all compilers.
+# if !defined (_REENTRANT)
+ /* If you want to disable threading, comment out the following
+ line. Or, add -DACE_MT_SAFE=0 to your CFLAGS, e.g., using
+ make threads=0. */
+# define _REENTRANT
+# endif /* _REENTRANT */
+# endif /* !ACE_MT_SAFE */
+
+# define ACE_CONFIG_INCLUDE_GHS_COMMON
+# include "ace/config-ghs-common.h"
+
+ // To avoid warning about inconsistent declaration between Sun's
+ // stdlib.h and Green Hills' ctype.h.
+# include <stdlib.h>
+
+ // IOStream_Test never halts with Green Hills 1.8.9.
+# define ACE_LACKS_ACE_IOSTREAM
+
+#else /* ! __SUNPRO_CC && ! __GNUG__ && ! ghs */
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler in ace/config-sunos5.5.h
+# endif /* __cplusplus */
+#endif /* ! __SUNPRO_CC && ! __GNUG__ && ! ghs */
+
+#if !defined (__ACE_INLINE__)
+// @note If you have link problems with undefined inline template
+// functions with Sun C++, be sure that the #define of __ACE_INLINE__
+// below is not commented out.
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// Platform supports the POSIX regular expression library.
+// @note Please comment out the ACE_HAS_REGEX #define if you
+// have link problems with g++ or egcs on SunOS 5.5.
+#define ACE_HAS_REGEX
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// select()'s timeval arg is not declared as const and may be modified
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+// Platform supports pread() and pwrite()
+#define ACE_HAS_P_READ_WRITE
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+#define ACE_HAS_UALARM
+#define ACE_LACKS_UALARM_PROTOTYPE
+
+// Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Platform supports system configuration information.
+#define ACE_HAS_SYSINFO
+
+// Platform supports recvmsg and sendmsg.
+#define ACE_HAS_MSG
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+// Compiler/platform correctly calls init()/fini() for shared libraries.
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Platform supports POSIX O_NONBLOCK semantics.
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Compiler/platform has correctly prototyped header files.
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+
+// This setting was determined by running the autoconf tests. If it doesn't
+// work uniformly, will need some tweaking, possibly based on other
+// XPG feature-test macros.
+#define ACE_HAS_CONST_CHAR_SWAB
+
+// Compiler/platform supports alloca()
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+// Compiler/platform has <alloca.h>
+#define ACE_HAS_ALLOCA_H
+
+// Platform contains <poll.h>.
+#define ACE_HAS_POLL
+
+// Platform supports POSIX timers via timestruc_t.
+#define ACE_HAS_POSIX_TIME
+
+// ACE_HAS_CLOCK_GETTIME requires linking with -lposix4.
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+
+// Platform supports the /proc file system.
+#define ACE_HAS_PROC_FS
+
+// Platform supports the prusage_t struct.
+#define ACE_HAS_PRUSAGE_T
+#define ACE_HAS_GETRUSAGE
+
+// Compiler/platform defines the sig_atomic_t typedef.
+#define ACE_HAS_SIG_ATOMIC_T
+
+// Platform supports SVR4 extended signals.
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_UCONTEXT_T
+
+// Compiler/platform provides the sockio.h file.
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Compiler supports the ssize_t typedef.
+#define ACE_HAS_SSIZE_T
+
+// Platform supports STREAMS.
+#define ACE_HAS_STREAMS
+
+// Platform supports STREAM pipes.
+#define ACE_HAS_STREAM_PIPES
+
+// Compiler/platform supports strerror ().
+#define ACE_HAS_STRERROR
+
+// Compiler/platform supports struct strbuf.
+#define ACE_HAS_STRBUF_T
+
+// Compiler/platform supports SVR4 dynamic linking semantics.
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+// Compiler/platform supports SVR4 gettimeofday() prototype.
+#define ACE_HAS_SVR4_GETTIMEOFDAY
+
+// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)...
+#define ACE_HAS_SVR4_TLI
+
+// Platform provides <sys/filio.h> header.
+#define ACE_HAS_SYS_FILIO_H
+
+// Compiler/platform supports sys_siglist array.
+#define ACE_HAS_SYS_SIGLIST
+
+// SunOS 5.5.x does not support mkstemp
+#define ACE_LACKS_MKSTEMP
+#define ACE_LACKS_SYS_SYSCTL_H
+
+#if !(defined(_XOPEN_SOURCE) && (_XOPEN_VERSION - 0 >= 4))
+# define ACE_HAS_CHARPTR_SHMDT
+#endif
+
+// Platform has posix getpwnam_r
+#if (defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE - 0 >= 199506L) || \
+ defined(_POSIX_PTHREAD_SEMANTICS)
+# define ACE_HAS_POSIX_GETPWNAM_R
+#endif /* _POSIX_C_SOURCE || _POSIX_PTHREAD_SEMANTICS */
+
+#if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE == 1)
+#if defined (_REENTRANT) || \
+ (defined (_POSIX_C_SOURCE) && (_POSIX_C_SOURCE - 0 >= 199506L)) || \
+ defined (_POSIX_PTHREAD_SEMANTICS)
+ // Compile using multi-thread libraries.
+# define ACE_HAS_THREADS
+
+# if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+# endif /* ACE_MT_SAFE */
+
+ // Platform supports POSIX pthreads *and* Solaris threads, by
+ // default! If you only want to use POSIX pthreads, add
+ // -D_POSIX_PTHREAD_SEMANTICS to your CFLAGS. Or, #define it right
+ // here. See the Intro (3) man page for information on
+ // -D_POSIX_PTHREAD_SEMANTICS.
+# if defined (_POSIX_PTHREAD_SEMANTICS)
+# define ACE_LACKS_RWLOCK_T
+# else
+# define ACE_HAS_STHREADS
+# endif /* ! _POSIX_PTHREAD_SEMANTICS */
+
+# define ACE_HAS_PTHREADS
+ // . . . but only supports SCHED_OTHER scheduling policy
+# define ACE_HAS_ONLY_SCHED_OTHER
+# define ACE_HAS_SIGWAIT
+# define ACE_HAS_SIGTIMEDWAIT
+# define ACE_HAS_SIGSUSPEND
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACK
+
+ // Compiler/platform has thread-specific storage
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+ // Platform supports reentrant functions (i.e., all the POSIX *_r functions).
+# define ACE_HAS_REENTRANT_FUNCTIONS
+
+# define ACE_NEEDS_LWP_PRIO_SET
+# define ACE_HAS_THR_YIELD
+# define ACE_LACKS_PTHREAD_YIELD
+#endif /* _REENTRANT || _POSIX_C_SOURCE >= 199506L || \
+ _POSIX_PTHREAD_SEMANTICS */
+#endif /* !ACE_MT_SAFE || ACE_MT_SAFE == 1 */
+
+# define ACE_HAS_PRIOCNTL
+
+// Platform supports ACE_TLI timod STREAMS module.
+#define ACE_HAS_TIMOD_H
+
+// Platform supports ACE_TLI tiuser header.
+#define ACE_HAS_TIUSER_H
+
+// Platform provides ACE_TLI function prototypes.
+#define ACE_HAS_TLI_PROTOTYPES
+
+// Platform has broken t_error() prototype.
+#define ACE_HAS_BROKEN_T_ERROR
+
+// Platform supports ACE_TLI.
+#define ACE_HAS_TLI
+
+#define ACE_HAS_GETPAGESIZE 1
+
+#define ACE_HAS_STL_MAP_CONFLICT
+
+#define ACE_HAS_IDTYPE_T
+
+#define ACE_HAS_GPERF
+#define ACE_HAS_DIRENT
+
+#if defined (__SUNPRO_CC)
+# define ACE_CC_NAME ACE_TEXT ("SunPro C++")
+# define ACE_CC_MAJOR_VERSION (__SUNPRO_CC >> 8)
+# define ACE_CC_MINOR_VERSION (__SUNPRO_CC & 0x00ff)
+# define ACE_CC_BETA_VERSION (0)
+#elif defined (__GNUG__)
+# define ACE_CC_MAJOR_VERSION __GNUC__
+# define ACE_CC_MINOR_VERSION __GNUC_MINOR__
+# define ACE_CC_BETA_VERSION (0)
+# if __GNUC_MINOR__ >= 90
+# define ACE_CC_NAME ACE_TEXT ("egcs")
+# else
+# define ACE_CC_NAME ACE_TEXT ("g++")
+# endif /* __GNUC_MINOR__ */
+#endif /* __GNUG__ */
+
+#if defined (i386) && (_FILE_OFFSET_BITS==32)
+# define ACE_HAS_X86_STAT_MACROS
+#endif /* i386 && _FILE_OFFSET_BITS==32 */
+
+#define ACE_MALLOC_ALIGN ((size_t)8)
+#define ACE_LACKS_SETREUID_PROTOTYPE
+#define ACE_LACKS_SETREGID_PROTOTYPE
+
+// Solaris does indeed implement the inet_aton() function, but it is
+// found in `libresolv.*'. It doesn't seem worth it to link another
+// library just for that function. Just use the emulation in ACE that
+// has been used for years.
+#define ACE_LACKS_INET_ATON
+
+#if defined (_LARGEFILE_SOURCE) || (_FILE_OFFSET_BITS==64)
+#undef ACE_HAS_PROC_FS
+#undef ACE_HAS_PRUSAGE_T
+#endif /* (_LARGEFILE_SOURCE) || (_FILE_OFFSET_BITS==64) */
+
+#if defined (_POSIX_PTHREAD_SEMANTICS) || (_FILE_OFFSET_BITS == 64) || (_POSIX_C_SOURCE - 0 >= 199506L)
+# define ACE_HAS_3_PARAM_READDIR_R
+#endif
+
+// Sum of the iov_len values can't be larger then SSIZE_MAX
+#define ACE_HAS_SOCK_BUF_SIZE_MAX
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sunos5.6.h b/ACE/ace/config-sunos5.6.h
new file mode 100644
index 00000000000..15b1ea097a1
--- /dev/null
+++ b/ACE/ace/config-sunos5.6.h
@@ -0,0 +1,129 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for SunOS 5.6
+// platforms using the SunC++ 4.x or g++ compilers.
+
+#ifndef ACE_CONFIG_H
+
+// ACE_CONFIG_H is defined by one of the following #included headers.
+
+// #include the SunOS 5.5 config file, then add SunOS 5.6 updates below.
+
+#include "ace/config-sunos5.5.h"
+
+#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE > 2) || \
+ defined (__EXTENSIONS__)
+// The asctime_r/ctime_r parameters change at POSIX.1c-1995
+# if (defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L)
+# define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+# endif /* POSIX_C_SOURCE >= 199506L */
+# define ACE_HAS_SIGWAIT
+// Hack 'cuz _POSIX_C_SOURCE > 2 and -DEXTENSIONS hides this.
+# define ACE_LACKS_MADVISE_PROTOTYPE
+#endif /* _POSIX_C_SOURCE > 2 || __EXTENSIONS__ */
+
+// Support for the SunC++ 5.2 compiler.
+// Do not undefine for compat mode < 5
+#if defined (__SUNPRO_CC) && __SUNPRO_CC > 0x510
+#if defined (__SUNPRO_CC_COMPAT) && (__SUNPRO_CC_COMPAT >= 5)
+#ifdef ACE_LACKS_ACE_IOSTREAM
+#undef ACE_LACKS_ACE_IOSTREAM
+#endif /* ACE_LACKS_ACE_IOSTREAM */
+#endif /* defined (__SUNPRO_CC_COMPAT) && (__SUNPRO_CC_COMPAT >= 5) */
+
+#ifndef ACE_LACKS_UNBUFFERED_STREAMBUF
+#define ACE_LACKS_UNBUFFERED_STREAMBUF 1
+#endif /* ACE_LACKS_UNBUFFERED_STREAMBUF */
+#ifndef ACE_TEMPLATES_REQUIRE_SOURCE
+#define ACE_TEMPLATES_REQUIRE_SOURCE 1
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+#ifndef ACE_HAS_TEMPLATE_TYPEDEFS
+#define ACE_HAS_TEMPLATE_TYPEDEFS 1
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+// Forte 7 seems to botch this one...
+#if __SUNPRO_CC == 0x540
+#undef ACE_HAS_TEMPLATE_TYPEDEFS
+#endif
+#ifndef ACE_HAS_THR_C_DEST
+#define ACE_HAS_THR_C_DEST 1
+#endif /* ACE_HAS_THR_C_DEST */
+#ifndef ACE_HAS_THR_C_FUNC
+#define ACE_HAS_THR_C_FUNC 1
+#endif /* ACE_HAS_THR_C_FUNC */
+#ifndef ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES 1
+#endif /* ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES */
+#ifndef ACE_HAS_SIG_C_FUNC
+#define ACE_HAS_SIG_C_FUNC 1
+#endif /* ACE_HAS_SIG_C_FUNC */
+#ifndef ACE_HAS_STDCPP_STL_INCLUDES
+#define ACE_HAS_STDCPP_STL_INCLUDES 1
+#endif /* ACE_HAS_STDCPP_STL_INCLUDES */
+#ifndef ACE_HAS_STRING_CLASS
+#define ACE_HAS_STRING_CLASS 1
+#endif /* ACE_HAS_STRING_CLASS */
+#ifndef ACE_HAS_STANDARD_CPP_LIBRARY
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+#endif /* ACE_HAS_STANDARD_CPP_LIBRARY */
+#ifndef ACE_HAS_STDCPP_STL_INCLUDES
+#define ACE_HAS_STDCPP_STL_INCLUDES 1
+#endif /* ACE_HAS_STDCPP_STL_INCLUDES */
+#ifndef ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+#ifndef ACE_HAS_TEMPLATE_SPECIALIZATION
+#define ACE_HAS_TEMPLATE_SPECIALIZATION 1
+#endif /* ACE_HAS_TEMPLATE_SPECIALIZATION */
+#ifndef ACE_LACKS_IOSTREAM_FX
+#define ACE_LACKS_IOSTREAM_FX 1
+#endif /* ACE_LACKS_IOSTREAM_FX */
+#ifndef ACE_LACKS_LINEBUFFERED_STREAMBUF
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF 1
+#endif /* ACE_LACKS_LINEBUFFERED_STREAMBUF */
+
+#endif /* defined (__SUNPRO_CC) && __SUNPRO_CC > 0x510 */
+
+// SunOS 5.6 and above support mkstemp
+#undef ACE_LACKS_MKSTEMP
+
+
+// SunOS 5.6 has AIO calls.
+#if !defined (ACE_HAS_AIO_CALLS)
+#define ACE_HAS_AIO_CALLS
+#endif /* ACE_HAS_AIO_CALLS */
+
+#if !defined (ACE_HAS_POSIX_REALTIME_SIGNALS)
+#define ACE_HAS_POSIX_REALTIME_SIGNALS
+#endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
+
+#if !defined (ACE_HAS_POSIX_MESSAGE_PASSING)
+#define ACE_HAS_POSIX_MESSAGE_PASSING
+#endif /* ACE_HAS_POSIX_MESSAGE_PASSING */
+
+#if !defined (ACE_HAS_POSIX_SEM)
+#define ACE_HAS_POSIX_SEM
+#endif /* ACE_HAS_POSIX_SEM */
+
+// Sunos 5.6's aio_* with RT signals is broken.
+#if !defined (ACE_POSIX_AIOCB_PROACTOR)
+#define ACE_POSIX_AIOCB_PROACTOR
+#endif /* ACE_POSIX_AIOCB_PROACTOR */
+
+// SunOS 5.6 has a buggy select
+#define ACE_HAS_LIMITED_SELECT
+
+// SunOS 5.6 introduced shm_open, but need to turn on POSIX.1b or higher
+// to pick it up.
+#if defined (_POSIX_C_SOURCE) && (_POSIX_C_SOURCE > 2)
+# define ACE_HAS_SHM_OPEN
+#else
+# undef ACE_HAS_SHM_OPEN
+#endif /* _POSIX_C_SOURCE > 2 */
+
+// The struct msghdr is conditional on SunOS 5.6 based on _XPG4_2
+#if defined(_XPG4_2)
+# define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#endif /* _XPG4_2 */
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sunos5.7.h b/ACE/ace/config-sunos5.7.h
new file mode 100644
index 00000000000..7a48cf4afbc
--- /dev/null
+++ b/ACE/ace/config-sunos5.7.h
@@ -0,0 +1,78 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for SunOS 5.7
+// (Solaris 7) platforms using the SunC++ 4.x, 5.x, or g++ compilers.
+
+#ifndef ACE_CONFIG_H
+
+// ACE_CONFIG_H is defined by one of the following #included headers.
+
+// #include the SunOS 5.6 config file, then add SunOS 5.7 updates below.
+
+#include "ace/config-sunos5.6.h"
+
+// This may be true for earlier Solaris versions, but I can only verify
+// it for Solaris 7 and later.
+#define ACE_HAS_VFWPRINTF
+#if defined (ACE_HAS_SHM_OPEN)
+# define ACE_SHM_OPEN_REQUIRES_ONE_SLASH
+#endif
+
+// Sun began distributing <sys/loadavg.h> with SunOS 5.7
+#define ACE_HAS_SYS_LOADAVG_H
+
+// SunOS 5.7 has getloadavg()
+#undef ACE_LACKS_GETLOADAVG
+
+#if defined (ghs)
+ // SunOS 5.7's /usr/include/sys/procfs_isa.h needs uint64_t,
+ // but /usr/include/sys/int_types.h doesn't #define it because
+ // _NO_LONGLONG is #
+# undef ACE_HAS_PROC_FS
+# undef ACE_HAS_PRUSAGE_T
+
+#elif defined (__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
+ // Wide character methods are in std:: when using SunCC 5.3
+# define ACE_WCHAR_IN_STD_NAMESPACE
+#endif /* __GNUG__ || ghs */
+
+// SunOS 5.7 supports SCHED_FIFO and SCHED_RR, as well as SCHED_OTHER.
+#undef ACE_HAS_ONLY_SCHED_OTHER
+
+// SunOS 5.7 gets this right . . .
+#undef ACE_HAS_BROKEN_T_ERROR
+
+// And doesn't need to set LWP priorities, as shown by
+// performance-tests/Misc/preempt.
+#undef ACE_NEEDS_LWP_PRIO_SET
+
+// SunOS 5.7 can support Real-Time Signals and POSIX4 AIO operations
+// are supported.
+
+#if !defined (ACE_HAS_AIO_CALLS)
+#define ACE_HAS_AIO_CALLS
+#endif /* !ACE_HAS_AIO_CALLS */
+
+#ifdef ACE_HAS_LIMITED_SELECT
+#undef ACE_HAS_LIMITED_SELECT
+#endif /* ACE_HAS_LIMITED_SELECT */
+
+// SunOS 5.7 has socklen_t
+#define ACE_HAS_SOCKLEN_T
+
+#if defined (__sparcv9)
+#define _LP64
+#define ACE_SIZEOF_LONG 8 /* Needed to circumvent compiler bug #4294969 */
+#endif /* __sparcv9 */
+
+#if (defined(_XOPEN_SOURCE) && (_XOPEN_VERSION - 0 == 4)) /* XPG4 or XPG4v2 */
+// 2 parameter wcstok()
+#else /* XPG4 or XPG4v2 */
+# define ACE_HAS_3_PARAM_WCSTOK
+#endif
+
+// Solaris 7 started to support /dev/poll
+#define ACE_HAS_DEV_POLL
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sunos5.8.h b/ACE/ace/config-sunos5.8.h
new file mode 100644
index 00000000000..abd9ee8f091
--- /dev/null
+++ b/ACE/ace/config-sunos5.8.h
@@ -0,0 +1,39 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for SunOS 5.8
+// (Solaris 8) platforms using the SunC++ 4.x, 5.x, 6.x, or g++ compilers.
+
+#ifndef ACE_CONFIG_H
+
+// ACE_CONFIG_H is defined by one of the following #included headers.
+
+// #include the SunOS 5.7 config, then add any SunOS 5.8 updates below.
+#include "ace/config-sunos5.7.h"
+
+#undef ACE_WCHAR_IN_STD_NAMESPACE
+
+// This may be true for versions prior to Solaris 8 as well, but I don't
+// have any to try it on.
+#if !defined (ACE_HAS_TIMEZONE)
+# define ACE_HAS_TIMEZONE
+#endif
+
+// The range of thread priorities for 5.8 differs from 5.7 in the
+// minimum priority for the SCHED_OTHER policy (i.e.,
+// ACE_THR_PRI_OTHER_MIN)
+# define ACE_THR_PRI_OTHER_MIN (long) -20
+
+# if defined (_POSIX_PTHREAD_SEMANTICS)
+# ifdef ACE_LACKS_RWLOCK_T
+# undef ACE_LACKS_RWLOCK_T
+# endif /* ACE_LACKS_RWLOCK_T */
+# endif /* _POSIX_PTHREAD_SEMANTICS */
+
+// This is no longer the case for Sun 5.9 onwards
+# undef ACE_HAS_X86_STAT_MACROS
+
+// gethostbyaddr does not handle IPv6-mapped-IPv4 addresses
+#define ACE_HAS_BROKEN_GETHOSTBYADDR_V4MAPPED
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-sunos5.9.h b/ACE/ace/config-sunos5.9.h
new file mode 100644
index 00000000000..42043928fec
--- /dev/null
+++ b/ACE/ace/config-sunos5.9.h
@@ -0,0 +1,18 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for SunOS 5.9
+// (Solaris 9) platforms using the SunC++ 5.x (Forte 6 and 7), or g++
+// compilers.
+
+#ifndef ACE_CONFIG_H
+
+// ACE_CONFIG_H is defined by one of the following #included headers.
+
+// #include the SunOS 5.8 config, then add any SunOS 5.9 updates below.
+#include "ace/config-sunos5.8.h"
+
+#define ACE_HAS_SENDFILE
+#define ACE_LACKS_THR_CONCURRENCY_FUNCS
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-tandem-nsk-mips-v2.h b/ACE/ace/config-tandem-nsk-mips-v2.h
new file mode 100644
index 00000000000..3dee75016c0
--- /dev/null
+++ b/ACE/ace/config-tandem-nsk-mips-v2.h
@@ -0,0 +1,404 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifndef ACE_CONFIG_NSK_H
+#define ACE_CONFIG_NSK_H
+
+#include /**/ "ace/pre.h"
+
+// The following configuration file contains defines for Tandem NSK
+// platform, MIPS processor, version 2 C++ compiler.
+
+
+//=========================================================================
+// Tandem NSK specific parts
+//=========================================================================
+
+
+// Disable pthread renaming of symbols such as "open" and "close"
+#define _CMA_NOWRAPPERS_ 1
+
+// Get Handle_Set.cpp to generate correct bit operations for NSK platform
+#define ACE_TANDEM_NSK_BIT_ORDER
+
+// Use facilities provided by T1248 version of pthreads.
+// (If not defined, will use old version of pthreads.)
+#define ACE_TANDEM_T1248_PTHREADS
+
+// Use all available T1248 thread aware wrapper functions for providing
+// non-blocking I/O.
+// [@note this causes a significant performance degradation]
+//#define ACE_TANDEM_T1248_PTHREADS_ALL_IO_WRAPPERS
+
+
+// Need this include here because some symbols defined by pthreads
+// (e.g. timespec_t) are needed before spthread.h is normally included
+// by ACE
+#ifdef ACE_TANDEM_T1248_PTHREADS
+#include <spthread.h>
+#else
+#include "pthread.h"
+#include "dce/cma_dispatch_coop.h"
+#endif
+
+// The following #defines are hacks to get around things
+// that seem to be missing or different in Tandem land
+#define NSIG 32 // missing from Signal.h
+ // note: on nsk TNS/R there is room in
+ // sigset_t for 128 signals but those
+ // above 31 are not valid.
+typedef long fd_mask; // should be in select.h but no such file
+#define NBBY 8 // must be consistent with value in sys/types.h
+#define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */
+#define MAXNAMLEN 248 // missing from dirent.h
+#define ERRMAX 4218 // from errno.h
+
+// Following seems to be missing from G06.20 version of standard
+// pthreads includes (it appeared in older version of standard pthreads)
+// (SCHED_FIFO (aka cma_c_sched_fifo) used in Dynamic_Priority_Test)
+#ifdef ACE_TANDEM_T1248_PTHREADS
+typedef enum CMA_T_SCHED_POLICY {
+ cma_c_sched_fifo = 0,
+ cma_c_sched_rr = 1,
+ cma_c_sched_throughput = 2,
+ cma_c_sched_background = 3,
+ cma_c_sched_ada_low = 4
+ } cma_t_sched_policy;
+#endif
+
+// T1248 doesn't define these constants. They're defined in spt/cma.h
+// (formerly dce/cma.h), but this header is not included or provided
+// by T1248 G07-AAL.
+#define cma_c_prio_fifo_min 16
+#define cma_c_prio_fifo_mid 24
+#define cma_c_prio_fifo_max 31
+#define cma_c_prio_rr_min 16
+#define cma_c_prio_rr_mid 24
+#define cma_c_prio_rr_max 31
+#define cma_c_prio_through_min 8
+#define cma_c_prio_through_mid 12
+#define cma_c_prio_through_max 15
+#define cma_c_prio_back_min 1
+#define cma_c_prio_back_mid 4
+#define cma_c_prio_back_max 7
+
+// Enable NSK Pluggable Protocols
+#define TAO_HAS_NSKPW 1
+#define TAO_HAS_NSKFS 1
+
+//=========================================================================
+// Platform specific parts
+//=========================================================================
+
+// Platform lacks getpwnam_r() methods (e.g., SGI 6.2).
+#define ACE_LACKS_PWD_REENTRANT_FUNCTIONS
+
+// Platform/compiler lacks {get,set}rlimit() function
+#define ACE_LACKS_RLIMIT
+
+// The platform doesn't have mmap(2)
+#define ACE_LACKS_MMAP
+
+// Platform lacks streambuf "linebuffered ()". [C++ iostream]
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+// Platform supports recvmsg and sendmsg
+#define ACE_HAS_MSG
+
+// Platform defines ACE_HAS_MSG, but lacks msg_accrights{,len}.
+#define ACE_LACKS_MSG_ACCRIGHTS
+
+// Platform supports sigsuspend()
+#define ACE_HAS_SIGSUSPEND
+
+// Platform/compiler has the sigwait(2) prototype
+#define ACE_HAS_SIGWAIT
+
+// Compiler/platform defines the sig_atomic_t typedef
+#define ACE_HAS_SIG_ATOMIC_T
+
+// OS/compiler uses size_t * rather than int * for socket lengths
+#define ACE_HAS_SIZET_SOCKET_LEN
+
+// OS/compiler uses void * arg 4 setsockopt() rather than const char *
+#define ACE_HAS_VOIDPTR_SOCKOPT
+
+// The platform doesn't have mprotect(2)
+#define ACE_LACKS_MPROTECT
+
+// Platform lacks msync()
+#define ACE_LACKS_MSYNC
+
+// Platform does not support reentrant netdb functions (getprotobyname_r,
+// getprotobynumber_r, gethostbyaddr_r, gethostbyname_r, getservbyname_r).
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS Platform does not support
+
+// Platform lacks madvise()
+#define ACE_LACKS_MADVISE
+
+// Platform lacks pri_t
+#define ACE_LACKS_PRI_T
+
+// Platform lacks a working sbrk()
+#define ACE_LACKS_SBRK
+
+// Platform doesn't have syscall() prototype
+#define ACE_LACKS_SYSCALL
+
+// Platform lacks the inet_aton() function.
+#define ACE_LACKS_INET_ATON
+
+// Compiler/platform has Dirent iterator functions
+#define ACE_HAS_DIRENT
+
+// Platform uses ACE_HAS_DIRENT but does not have readdir_r()
+#define ACE_LACKS_READDIR_R
+
+// Platform supports getpagesize() call (otherwise,
+// ACE_PAGE_SIZE must be defined)
+#define ACE_HAS_GETPAGESIZE
+
+// Platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+
+// Platform's select() uses non-const timeval*
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+// Platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Platform lacks named POSIX semaphores
+#define ACE_LACKS_NAMED_POSIX_SEM
+
+// Platform has support for multi-byte character support compliant
+// with the XPG4 Worldwide Portability Interface wide-character
+// classification.
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+// No wcsstr function available for this compiler
+#define ACE_LACKS_WCSSTR
+
+// No wctype.h available for this compiler
+#define ACE_LACKS_WCTYPE_H
+
+// Platform supports the POSIX regular expression library.
+// [Note Tandem NSK platform does have regular expresson support but it
+// does not follow the assumptions made by ACE. To use it would need
+// to make some ACE modifications.]
+//#define ACE_HAS_REGEX
+
+// Compiler/platform supports strerror ()
+#define ACE_HAS_STRERROR
+
+// Platform doesn't have truncate()
+#define ACE_LACKS_TRUNCATE
+
+// Platform lacks readers/writer locks.
+#define ACE_LACKS_RWLOCK_T
+
+// Compiler's 'new' throws exception on failure (ANSI C++ behavior).
+#define ACE_NEW_THROWS_EXCEPTIONS
+
+// Optimize ACE_Handle_Set::count_bits for select() operations (common
+// case)
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// Platform lacks setreuid()
+#define ACE_LACKS_SETREUID
+
+// Platform lacks setregid()
+#define ACE_LACKS_SETREGID
+
+// Compile using multi-thread libraries
+#define ACE_MT_SAFE 1
+
+
+
+// Platform supports System V IPC
+#define ACE_HAS_SYSV_IPC
+
+// Platform lacks the socketpair() call
+// [Needed due to failure of Pipe_Test. even though nsk platform
+// has socketpair(), Pipe.cpp tries to set socket buf size but this
+// is not allowed for AF_UNIX protocol on nsk.]
+#define ACE_LACKS_SOCKET_BUFSIZ
+
+// Platform lacks the socketpair() call
+#define ACE_LACKS_SOCKETPAIR
+
+// Platform limits the maximum socket message size.
+#define ACE_HAS_SOCK_BUF_SIZE_MAX
+
+// hrtime_t is a basic type that doesn't require ACE_U64_TO_U32 conversion
+#define ACE_HRTIME_T_IS_BASIC_TYPE
+
+// printf format specifiers for 64 bit integers
+# define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%Ld")
+# define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%Ld")
+
+//=========================================================================
+// Threads specific parts
+//=========================================================================
+
+// Platform supports threads
+#define ACE_HAS_THREADS
+
+// Platform supports POSIX Pthreads, of one form or another. This
+// macro says the platform has a pthreads variety - should also define
+// one of the below to say which one. Also may need some
+// ACE_HAS_... thing for extensions.
+#define ACE_HAS_PTHREADS
+
+// Standard pthreads supports only SCHED_FIFO
+#define ACE_HAS_ONLY_SCHED_FIFO
+
+// Compiler/platform has thread-specific storage
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+// Platform has no implementation of pthread_condattr_setpshared(),
+// even though it supports pthreads!
+#define ACE_LACKS_CONDATTR_PSHARED
+
+// pthread_cond_timedwait does *not* reset the time argument when the
+// lock is acquired.
+#define ACE_LACKS_COND_TIMEDWAIT_RESET
+
+// Platform lacks pthread_attr_setsched()
+#define ACE_LACKS_SETSCHED
+
+// Platform has pthread_mutexattr_setkind_np().
+#define ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP
+
+// Platform lacks pthread_mutexattr_setpshared().
+#define ACE_LACKS_MUTEXATTR_PSHARED
+
+// Platform lacks pthread_attr_setscope()
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+
+// Platform lacks pthread_attr_setstackaddr
+#define ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR
+
+// Defining ACE_HAS_UCONTEXT_T since G06.21 version of spthreads has
+// a definition for it.
+#ifdef ACE_TANDEM_T1248_PTHREADS
+#define ACE_HAS_UCONTEXT_T
+#endif
+
+//=========================================================================
+// Include file characteristics
+//=========================================================================
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+// Platform lacks malloc.h
+#define ACE_LACKS_MALLOC_H
+
+// Platform lacks the siginfo.h include file
+#define ACE_LACKS_SIGINFO_H
+
+// Platform doesn't define struct strrecvfd.
+#define ACE_LACKS_STRRECVFD
+
+// Platform lacks the ucontext.h file
+#define ACE_LACKS_UCONTEXT_H
+
+// Prototypes for both signal() and struct sigaction are consistent.
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Platform supports the POSIX struct timespec type
+#define ACE_HAS_POSIX_TIME
+
+// Platform/compiler supports timezone * as second parameter to gettimeofday()
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+// Platform has <strings.h> (which contains bzero() prototype)
+#define ACE_HAS_STRINGS 1
+
+
+// OS/compiler omits the const from the iovec parameter in the
+// writev() prototype.
+#define ACE_HAS_NONCONST_WRITEV
+
+// Platform lacks <stdint.h>
+#define ACE_LACKS_STDINT_H
+
+// Platform lacks <inttypes.h>
+#define ACE_LACKS_INTTYPES_H
+
+// Platform lacks <sys/select.h>
+#define ACE_LACKS_SYS_SELECT_H
+
+// Platform lacks <dlfcn.h>
+#define ACE_LACKS_DLFCN_H
+
+// Platform lacks <semaphore.h>
+#define ACE_LACKS_SEMAPHORE_H
+
+// Platform lacks <poll.h>
+#define ACE_LACKS_POLL_H
+
+//=========================================================================
+// Compiler specific parts
+//=========================================================================
+
+// Compiler supports C++ exception handling
+#define ACE_HAS_EXCEPTIONS
+
+// Compiler/platform has correctly prototyped header files
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Compiler/platform does not support the unsigned long long datatype.
+#define ACE_LACKS_LONGLONG_T
+
+// Compiler supports the ssize_t typedef
+#define ACE_HAS_SSIZE_T
+
+// Platform/compiler supports Standard C++ Library
+#define ACE_HAS_STANDARD_CPP_LIBRARY 0
+
+// Compiler's template mechanism must see source code (i.e.,
+// .cpp files).
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+
+// Compiler implements template specialization
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+
+// Compiler implements templates that support typedefs inside
+// of classes used as formal arguments to a template class.
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+
+// Platform has its standard c++ library in the namespace std.
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+
+// Compiler doesn't support static data member templates
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+
+// Platform lacks "signed char" type (broken!)
+// Following will not be needed if use standard c library (G06.20 and later)
+#define ACE_LACKS_SIGNED_CHAR
+
+//=========================================================================
+// Build options
+//=========================================================================
+
+// Disable the inclusion of RCS ids in the generated code.
+#define ACE_USE_RCSID 0
+
+// For debugging problems in os calls (but this doesn't work too well
+// since output is not interleaved properly with output from ACE_TRACE
+//# define ACE_OS_TRACE(X) ::printf(X)
+
+// Uncomment the following if timed message blocks are needed (e.g.
+// for Dynamic_Priority_Test. Otherwise leave this disabled because
+// enabling it adds overhead to message blocks and timed message blocks
+// are "rarely used."
+//#define ACE_HAS_TIMED_MESSAGE_BLOCKS
+
+// Uncomment the following if tokens library is needed.
+//#define ACE_HAS_TOKENS_LIBRARY
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONFIG_NSK_H */
diff --git a/ACE/ace/config-tandem-nsk-mips-v3.h b/ACE/ace/config-tandem-nsk-mips-v3.h
new file mode 100644
index 00000000000..80fdb49becd
--- /dev/null
+++ b/ACE/ace/config-tandem-nsk-mips-v3.h
@@ -0,0 +1,474 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#ifndef ACE_CONFIG_NSK_H
+#define ACE_CONFIG_NSK_H
+
+#include /**/ "ace/pre.h"
+
+// The following configuration file contains defines for Tandem NSK
+// platform, MIPS processor, version 3 C++ compiler.
+
+
+//=========================================================================
+// Tandem NSK specific parts
+//=========================================================================
+
+
+// Disable pthread renaming of symbols such as "open" and "close"
+#define _CMA_NOWRAPPERS_ 1
+
+// Get Handle_Set.cpp to generate correct bit operations for NSK platform
+#define ACE_TANDEM_NSK_BIT_ORDER
+
+// Use facilities provided by T1248 version of pthreads.
+// (If not defined, will use old version of pthreads.)
+#define ACE_TANDEM_T1248_PTHREADS
+
+// Use all available T1248 thread aware wrapper functions for providing
+// non-blocking I/O.
+// [Note: this causes a significant performance degradation]
+//#define ACE_TANDEM_T1248_PTHREADS_ALL_IO_WRAPPERS
+
+
+// Need this include here because some symbols defined by pthreads
+// (e.g. timespec_t) are needed before spthread.h is normally included
+// by ACE
+#ifdef ACE_TANDEM_T1248_PTHREADS
+#include <spthread.h>
+#else
+#include "pthread.h"
+#include "dce/cma_dispatch_coop.h"
+#endif
+
+// The following #defines are hacks to get around things
+// that seem to be missing or different in Tandem land
+#define NSIG 32 // missing from Signal.h
+ // note: on nsk TNS/R there is room in
+ // sigset_t for 128 signals but those
+ // above 31 are not valid.
+typedef long fd_mask; // should be in select.h but no such file
+#define NBBY 8 // must be consistent with value in sys/types.h
+#define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */
+#define MAXNAMLEN 248 // missing from dirent.h
+#define ERRMAX 4218 // from errno.h
+
+// Following seems to be missing from G06.20 version of standard
+// pthreads includes (it appeared in older version of standard pthreads)
+// (SCHED_FIFO (aka cma_c_sched_fifo) used in Dynamic_Priority_Test)
+#ifdef ACE_TANDEM_T1248_PTHREADS
+typedef enum CMA_T_SCHED_POLICY {
+ cma_c_sched_fifo = 0,
+ cma_c_sched_rr = 1,
+ cma_c_sched_throughput = 2,
+ cma_c_sched_background = 3,
+ cma_c_sched_ada_low = 4
+ } cma_t_sched_policy;
+#endif
+
+// T1248 doesn't define these constants. They're defined in spt/cma.h
+// (formerly dce/cma.h), but this header is not included or provided
+// by T1248 G07-AAL.
+#define cma_c_prio_fifo_min 16
+#define cma_c_prio_fifo_mid 24
+#define cma_c_prio_fifo_max 31
+#define cma_c_prio_rr_min 16
+#define cma_c_prio_rr_mid 24
+#define cma_c_prio_rr_max 31
+#define cma_c_prio_through_min 8
+#define cma_c_prio_through_mid 12
+#define cma_c_prio_through_max 15
+#define cma_c_prio_back_min 1
+#define cma_c_prio_back_mid 4
+#define cma_c_prio_back_max 7
+
+// Enable NSK Pluggable Protocols
+#define TAO_HAS_NSKPW 1
+#define TAO_HAS_NSKFS 1
+
+//=========================================================================
+// Platform specific parts
+//=========================================================================
+
+// Platform lacks getpwnam_r() methods (e.g., SGI 6.2).
+#define ACE_LACKS_PWD_REENTRANT_FUNCTIONS
+
+// Platform/compiler lacks {get,set}rlimit() function
+#define ACE_LACKS_RLIMIT
+
+// The platform doesn't have mmap(2)
+#define ACE_LACKS_MMAP
+
+// Platform lacks streambuf "linebuffered ()". [C++ iostream]
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+// Platform supports recvmsg and sendmsg
+#define ACE_HAS_MSG
+
+// Platform defines ACE_HAS_MSG, but lacks msg_accrights{,len}.
+#define ACE_LACKS_MSG_ACCRIGHTS
+
+// Platform supports sigsuspend()
+#define ACE_HAS_SIGSUSPEND
+
+// Platform/compiler has the sigwait(2) prototype
+#define ACE_HAS_SIGWAIT
+
+// Compiler/platform defines the sig_atomic_t typedef
+#define ACE_HAS_SIG_ATOMIC_T
+
+// OS/compiler uses size_t * rather than int * for socket lengths
+#define ACE_HAS_SIZET_SOCKET_LEN
+
+// OS/compiler uses void * arg 4 setsockopt() rather than const char *
+#define ACE_HAS_VOIDPTR_SOCKOPT
+
+// The platform doesn't have mprotect(2)
+#define ACE_LACKS_MPROTECT
+
+// Platform lacks msync()
+#define ACE_LACKS_MSYNC
+
+// Platform does not support reentrant netdb functions (getprotobyname_r,
+// getprotobynumber_r, gethostbyaddr_r, gethostbyname_r, getservbyname_r).
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS Platform does not support
+
+// Platform lacks madvise()
+#define ACE_LACKS_MADVISE
+
+// Platform lacks pri_t
+#define ACE_LACKS_PRI_T
+
+// Platform lacks a working sbrk()
+#define ACE_LACKS_SBRK
+
+// Platform doesn't have syscall() prototype
+#define ACE_LACKS_SYSCALL
+
+// Platform lacks the inet_aton() function.
+#define ACE_LACKS_INET_ATON
+
+// Compiler/platform has Dirent iterator functions
+#define ACE_HAS_DIRENT
+
+// Platform uses ACE_HAS_DIRENT but does not have readdir_r()
+#define ACE_LACKS_READDIR_R
+
+// Platform supports getpagesize() call (otherwise,
+// ACE_PAGE_SIZE must be defined)
+#define ACE_HAS_GETPAGESIZE
+
+// Platform supports IP multicast
+#define ACE_HAS_IP_MULTICAST
+
+// Platform's select() uses non-const timeval*
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+// Platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Platform lacks named POSIX semaphores
+#define ACE_LACKS_NAMED_POSIX_SEM
+
+// Platform has support for multi-byte character support compliant
+// with the XPG4 Worldwide Portability Interface wide-character
+// classification.
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+// No wcsstr function available for this compiler
+#define ACE_LACKS_WCSSTR
+
+// No wctype.h available for this compiler
+#define ACE_LACKS_WCTYPE_H
+
+// Platform supports the POSIX regular expression library.
+// [Note Tandem NSK platform does have regular expresson support but it
+// does not follow the assumptions made by ACE. To use it would need
+// to make some ACE modifications.]
+//#define ACE_HAS_REGEX
+
+// Compiler/platform supports strerror ()
+#define ACE_HAS_STRERROR
+
+// Platform doesn't have truncate()
+#define ACE_LACKS_TRUNCATE
+
+// Platform lacks readers/writer locks.
+#define ACE_LACKS_RWLOCK_T
+
+// Compiler's 'new' throws exception on failure (ANSI C++ behavior).
+#define ACE_NEW_THROWS_EXCEPTIONS
+
+// Optimize ACE_Handle_Set::count_bits for select() operations (common
+// case)
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// Platform lacks setreuid()
+#define ACE_LACKS_SETREUID
+
+// Platform lacks setregid()
+#define ACE_LACKS_SETREGID
+
+// Compile using multi-thread libraries
+#define ACE_MT_SAFE 1
+
+
+
+// Platform supports System V IPC
+#define ACE_HAS_SYSV_IPC
+
+// Platform lacks the socketpair() call
+// [Needed due to failure of Pipe_Test. even though nsk platform
+// has socketpair(), Pipe.cpp tries to set socket buf size but this
+// is not allowed for AF_UNIX protocol on nsk.]
+#define ACE_LACKS_SOCKET_BUFSIZ
+
+// Platform lacks the socketpair() call
+#define ACE_LACKS_SOCKETPAIR
+
+// Platform limits the maximum socket message size.
+#define ACE_HAS_SOCK_BUF_SIZE_MAX
+
+// hrtime_t is a basic type that doesn't require ACE_U64_TO_U32 conversion
+#define ACE_HRTIME_T_IS_BASIC_TYPE
+
+// printf format specifiers for 64 bit integers
+# define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%Ld")
+# define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%Ld")
+
+// Use larger default buffer size for ease of interoperability
+#define ACE_DEFAULT_CDR_BUFSIZE 4096
+
+// Size of a wchar
+#define ACE_SIZEOF_WCHAR 2
+
+// Platform lacks time typedefs
+#define ACE_LACKS_SUSECONDS_T
+#define ACE_LACKS_USECONDS_T
+
+// Platform lacks setegid() and seteuid()
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETEUID
+
+// Platform lacks vsnprintf()
+#define ACE_LACKS_VSNPRINTF
+
+// Platform lacks log2()
+#define ACE_LACKS_LOG2
+
+// Platform lacks alphasort()
+#define ACE_LACKS_ALPHASORT
+
+
+//=========================================================================
+// Threads specific parts
+//=========================================================================
+
+// Platform supports threads
+#define ACE_HAS_THREADS
+
+// Platform supports POSIX Pthreads, of one form or another. This
+// macro says the platform has a pthreads variety - should also define
+// one of the below to say which one. Also may need some
+// ACE_HAS_... thing for extensions.
+#define ACE_HAS_PTHREADS
+
+// Standard pthreads supports only SCHED_FIFO
+#define ACE_HAS_ONLY_SCHED_FIFO
+
+// Compiler/platform has thread-specific storage
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+// Platform has no implementation of pthread_condattr_setpshared(),
+// even though it supports pthreads!
+#define ACE_LACKS_CONDATTR_PSHARED
+
+// pthread_cond_timedwait does *not* reset the time argument when the
+// lock is acquired.
+#define ACE_LACKS_COND_TIMEDWAIT_RESET
+
+// Platform lacks pthread_attr_setsched()
+#define ACE_LACKS_SETSCHED
+
+// Platform has pthread_getschedparam and pthread_setschedparam
+// even when ACE_LACKS_SETSCHED is defined.
+#define ACE_HAS_PTHREAD_SCHEDPARAM
+
+// Platform has pthread_mutexattr_setkind_np().
+#define ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP
+
+// Platform lacks pthread_mutexattr_setpshared().
+#define ACE_LACKS_MUTEXATTR_PSHARED
+
+// Platform lacks pthread_attr_setscope()
+#define ACE_LACKS_THREAD_PROCESS_SCOPING
+
+// Platform lacks pthread_attr_setstackaddr
+#define ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR
+
+// Platform lacks pthread_attr_setstack
+#define ACE_LACKS_PTHREAD_ATTR_SETSTACK
+
+// Defining ACE_HAS_UCONTEXT_T since G06.21 version of spthreads has
+// a definition for it.
+#ifdef ACE_TANDEM_T1248_PTHREADS
+#define ACE_HAS_UCONTEXT_T
+#endif
+
+//=========================================================================
+// Include file characteristics
+//=========================================================================
+
+// Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+// Platform lacks malloc.h
+#define ACE_LACKS_MALLOC_H
+
+// Platform lacks the siginfo.h include file
+#define ACE_LACKS_SIGINFO_H
+
+// Platform doesn't define struct strrecvfd.
+#define ACE_LACKS_STRRECVFD
+
+// Platform lacks the ucontext.h file
+#define ACE_LACKS_UCONTEXT_H
+
+// Prototypes for both signal() and struct sigaction are consistent.
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+
+// Platform supports the POSIX struct timespec type
+#define ACE_HAS_POSIX_TIME
+
+// Platform/compiler supports timezone * as second parameter to gettimeofday()
+#define ACE_HAS_TIMEZONE_GETTIMEOFDAY
+
+// Platform has <strings.h> (which contains bzero() prototype)
+#define ACE_HAS_STRINGS 1
+
+
+// OS/compiler omits the const from the iovec parameter in the
+// writev() prototype.
+#define ACE_HAS_NONCONST_WRITEV
+
+// Platform lacks <stdint.h>
+#define ACE_LACKS_STDINT_H
+
+// Platform lacks <inttypes.h>
+#define ACE_LACKS_INTTYPES_H
+
+// Platform lacks <sys/select.h>
+#define ACE_LACKS_SYS_SELECT_H
+
+// Platform lacks <dlfcn.h>
+#define ACE_LACKS_DLFCN_H
+
+// Platform lacks <semaphore.h>
+#define ACE_LACKS_SEMAPHORE_H
+
+// Platform lacks <poll.h>
+#define ACE_LACKS_POLL_H
+
+// Platform lacks <sys/sysctl.h>
+#define ACE_LACKS_SYS_SYSCTL_H
+
+//=========================================================================
+// Compiler specific parts
+//=========================================================================
+
+// Compiler supports C++ exception handling
+#define ACE_HAS_EXCEPTIONS 1
+
+// Compiler/platform has correctly prototyped header files
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+// Compiler/platform does not support the unsigned long long datatype.
+#define ACE_LACKS_UNSIGNEDLONGLONG_T
+
+// Compiler supports the ssize_t typedef
+#define ACE_HAS_SSIZE_T
+
+// Platform/compiler supports Standard C++ Library
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+
+// Compiler's template mechanism must see source code (i.e.,
+// .cpp files).
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+
+// Compiler implements template specialization
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+
+// Compiler implements templates that support typedefs inside
+// of classes used as formal arguments to a template class.
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+
+// Platform/Compiler supports a String class
+#define ACE_HAS_STRING_CLASS
+#define ACE_HAS_STDCPP_STL_INCLUDES
+
+// Platform has its standard c++ library in the namespace std.
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+
+// Compiler doesn't support static data member templates
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+
+// Platform lacks "signed char" type (broken!)
+// Following will not be needed if use standard c library (G06.20 and later)
+#define ACE_LACKS_SIGNED_CHAR
+
+// Compiler can handle any operators in namespace
+#define ACE_ANY_OPS_USE_NAMESPACE
+
+// Platform lacks intptr_t typedef
+#define ACE_LACKS_INTPTR_T
+
+//=========================================================================
+// C++ version3 import/export macros
+//=========================================================================
+
+// Define the export macros needed to export symbols outside a DLL
+// The ACE_IMPORT_SINGLETON_DECLARE macro has been modified to not explicitly
+// instantiate the class template.
+#if defined(USE_EXPLICIT_EXPORT)
+#define ACE_LACKS_INLINE_FUNCTIONS
+
+#define ACE_HAS_CUSTOM_EXPORT_MACROS
+#define ACE_Proper_Export_Flag export$
+#define ACE_Proper_Import_Flag import$
+#define ACE_EXPORT_SINGLETON_DECLARATION(T) template class export$ T
+#define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class export$ SINGLETON_TYPE<CLASS, LOCK>;
+#define ACE_IMPORT_SINGLETON_DECLARATION(T) template class import$ T
+#define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class import$ SINGLETON_TYPE <CLASS, LOCK>;
+#endif
+
+
+//=========================================================================
+// Build options
+//=========================================================================
+
+// Disable the inclusion of RCS ids in the generated code.
+#define ACE_USE_RCSID 0
+
+// For debugging problems in os calls (but this doesn't work too well
+// since output is not interleaved properly with output from ACE_TRACE
+//# define ACE_OS_TRACE(X) ::printf(X)
+
+// Uncomment the following if timed message blocks are needed (e.g.
+// for Dynamic_Priority_Test. Otherwise leave this disabled because
+// enabling it adds overhead to message blocks and timed message blocks
+// are "rarely used."
+//#define ACE_HAS_TIMED_MESSAGE_BLOCKS
+
+// Uncomment the following if tokens library is needed.
+//#define ACE_HAS_TOKENS_LIBRARY
+
+// NonStop CORBA uses the XML Service Configurator
+#define ACE_HAS_XML_SVC_CONF
+
+#define ACE_LD_SEARCH_PATH "_RLD_LIB_PATH"
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_CONFIG_NSK_H */
diff --git a/ACE/ace/config-tandem.h b/ACE/ace/config-tandem.h
new file mode 100644
index 00000000000..7b2867a0fda
--- /dev/null
+++ b/ACE/ace/config-tandem.h
@@ -0,0 +1,192 @@
+/* -*- C++ -*- */
+// Testing TANDEM
+// $Id$
+
+// The following configuration file is designed to work for Tandems NonStop-UX
+// 4.2MP platforms using the NCC 3.20 compiler.
+
+// Note this is a test version it might include several errors I
+// have done a test and set/unset until I errors disappered.
+// Some of the options that should be set aren't because of the simple fact
+// that i haven't the time to check what is wrong.
+// e.g. widecharacter are supported but a wcstok which only take 2 parameters
+// are included by the compiler, to get the correct wcstok that takes 3 params
+// we must set _XOPEN_SOURCE and we get ALOT of errors and warnings.
+// So this config is done to get things to start to work it isn't finished.
+// Janne (Jan.Perman@osd.Ericsson.se)
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+#define ACE_HAS_IDTYPE_T
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// Tandem doesn't include this although they are defined
+// in sys/time.h and sys/resource.h
+#define ACE_LACKS_RLIMIT_PROTOTYPE // jjpp
+// Tandem has a function to set t_errno (set_t_errno)
+#define ACE_HAS_SET_T_ERRNO // jjpp
+
+//Platform supports System V IPC (most versions of UNIX, but not Win32)
+#define ACE_HAS_SYSV_IPC
+
+// OS/compiler omits the const from the sendmsg() prototype.
+#define ACE_HAS_NONCONST_SENDMSG
+
+//Platform supports system configuration information
+#define ACE_HAS_SYSINFO
+
+//Platform supports the POSIX regular expression library
+#define ACE_HAS_REGEX
+
+// Platform supports recvmsg and sendmsg
+#define ACE_HAS_MSG
+
+//Compiler/platform contains the <sys/syscall.h> file.
+#define ACE_HAS_SYS_SYSCALL_H
+
+//Platform provides <sysent.h> header
+#define ACE_HAS_SYSENT_H
+
+// Platform has POSIX terminal interface.
+#define ACE_HAS_TERMIOS
+
+//Platform supports POSIX O_NONBLOCK semantics
+#define ACE_HAS_POSIX_NONBLOCK
+
+// Compiler/platform has correctly prototyped header files
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+//Compiler/platform supports alloca()
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA
+
+//Compiler/platform has <alloca.h>
+#define ACE_HAS_ALLOCA_H
+
+//Platform contains <poll.h>
+#define ACE_HAS_POLL
+
+// Platform supports the POSIX struct timespec type
+#define ACE_HAS_POSIX_TIME // As i understand it, but i'm in deep water
+//Platform supports the SVR4 timestruc_t type
+
+// To get this to work a patch in sys/signal must be made
+// typedef void SIG_FUNC_TYPE(int);
+//#if defined (__cplusplus)
+// void (*sa_handler)(int);
+//#else
+// ...
+//#endif
+//#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_TANDEM_SIGNALS
+//Compiler/platform defines the sig_atomic_t typedef
+#define ACE_HAS_SIG_ATOMIC_T
+//Platform supports SVR4 extended signals
+#define ACE_HAS_SIGINFO_T
+//Platform supports ucontext_t (which is used in the extended signal API).
+#define ACE_HAS_UCONTEXT_T
+
+// Platform/compiler has the sigwait(2) prototype
+#define ACE_HAS_SIGWAIT
+
+//Compiler/platform provides the sockio.h file
+#define ACE_HAS_SYS_SOCKIO_H
+
+// Compiler supports the ssize_t typedef
+#define ACE_HAS_SSIZE_T // Limits.h must be included
+
+//Platform supports STREAMS
+#define ACE_HAS_STREAMS
+
+#define ACE_HAS_STREAM_PIPES
+//Platform supports STREAM pipes
+
+//Compiler/platform supports strerror ()
+#define ACE_HAS_STRERROR
+
+//Compiler/platform supports struct strbuf
+#define ACE_HAS_STRBUF_T
+
+//Compiler/platform supports SVR4 dynamic linking semantics
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+//Compiler/platform supports SVR4 TLI (in particular, T_GETNAME stuff)...
+#define ACE_HAS_SVR4_TLI
+
+//Platform provides <sys/filio.h> header
+#define ACE_HAS_SYS_FILIO_H
+
+//Platform supports TLI timod STREAMS module
+#define ACE_HAS_TIMOD_H
+//Platform supports TLI tiuser header
+#define ACE_HAS_TIUSER_H
+
+//Platform supports TLI
+#define ACE_HAS_TLI
+//Platform provides TLI function prototypes
+#define ACE_HAS_TLI_PROTOTYPES
+
+//Platform lacks streambuf "linebuffered ()".
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+// Platform lacks "signed char" type (broken!)
+#define ACE_LACKS_SIGNED_CHAR
+
+
+#define ACE_PAGE_SIZE 4096
+// Defines the page size of the system (not used on Win32 or
+// with ACE_HAS_GETPAGESIZE).
+
+/****** THREAD SPECIFIC **********/
+/* If you want to remove threading then comment out the following four #defines .*/
+#if !defined (ACE_MT_SAFE)
+ #define ACE_MT_SAFE 1 //Compile using multi-thread libraries
+#endif
+#define ACE_HAS_THREADS //Platform supports threads
+#define ACE_HAS_STHREADS //Platform supports Solaris threads
+
+// Compiler/platform has threadspecific storage
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+//Platform supports thr_keydelete (e.g,. UNIXWARE)
+
+#define ACE_HAS_THR_MINSTACK // Tandem uses thr_minstack instead of thr_min_stack
+#define ACE_LACKS_PRI_T // Tandem lacks pri_t
+#define ACE_HAS_THR_KEYDELETE
+
+//*************************************
+
+/*********************************/
+
+/******* SIGNAL STUFF *******/
+
+//Platform uses non-const char * in calls to gethostbyaddr, gethostbyname,
+// getservbyname
+#define ACE_HAS_NONCONST_GETBY
+// Platform's select() uses non-const timeval* (only found on Linux right now)
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+// And on Tandem :-)
+//Uses ctime_r & asctime_r with only two parameters vs. three.
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+//Platform has special header for select().
+#define ACE_HAS_SELECT_H
+// Platform/compiler supports Standard C++ Library
+#define ACE_HAS_STANDARD_CPP_LIBRARY
+//Platform lacks madvise() (e.g., Linux)
+#define ACE_LACKS_MADVISE
+//Compiler/platform lacks strcasecmp() (e.g., DG/UX, UNIXWARE, VXWORKS)
+#define ACE_LACKS_STRCASECMP
+
+// Defines the page size of the system.
+#define ACE_PAGE_SIZE 4096
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-tru64.h b/ACE/ace/config-tru64.h
new file mode 100644
index 00000000000..1877af703bb
--- /dev/null
+++ b/ACE/ace/config-tru64.h
@@ -0,0 +1,155 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for the
+// Digital UNIX V4.0a and later platforms. It relies on
+// config-osf1-4.0.h, and adds deltas for newer platforms.
+
+#ifndef ACE_CONFIG_TRU64_H
+#define ACE_CONFIG_TRU64_H
+#include /**/ "ace/pre.h"
+
+#if !defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// Compile using multi-thread libraries.
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif /* ! ACE_MT_SAFE */
+
+/*clearerr is not defined when _REENTRANT is not defined*/
+#if ACE_MT_SAFE == 0
+#define ACE_LACKS_CLEARERR
+#endif /* ACE_MT_SAFE == 0 */
+
+#include "ace/config-posix.h"
+
+// Configuration-specific #defines:
+// 1) g++ or cxx
+// 2) pthreads or DCE threads
+#if defined (__GNUG__)
+ // g++ with pthreads
+
+ // config-g++-common.h undef's ACE_HAS_STRING_CLASS with -frepo, so
+ // this must appear before its #include.
+# define ACE_HAS_STRING_CLASS
+
+# include "ace/config-g++-common.h"
+
+# define ACE_HAS_GNU_CSTRING_H
+# define ACE_HAS_REENTRANT_FUNCTIONS
+#elif defined (__DECCXX)
+
+# define ACE_CONFIG_INCLUDE_CXX_COMMON
+# include "ace/config-cxx-common.h"
+
+#elif defined (__rational__)
+# define ACE_HAS_REENTRANT_FUNCTIONS
+# define ACE_HAS_STRING_CLASS
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+# define ACE_LACKS_SIGNED_CHAR
+
+ // Exceptions are enabled by platform_osf1_4.0_rcc.GNU.
+# define ACE_HAS_STDCPP_STL_INCLUDES
+# define ACE_HAS_TEMPLATE_SPECIALIZATION
+#else
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler on Digital Unix
+# endif /* __cplusplus */
+#endif /* ! __GNUG__ && ! __DECCXX && ! __rational__ */
+
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+#define ACE_HAS_BROKEN_IF_HEADER
+#define ACE_HAS_BROKEN_R_ROUTINES
+#if (ACE_MT_SAFE != 0)
+# define ACE_HAS_PTHREADS
+# define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+#endif /* ACE_MT_SAFE != 0 */
+#define ACE_LACKS_T_ERRNO
+#if !defined (DIGITAL_UNIX)
+# define DIGITAL_UNIX 0x400
+#endif /* ! DIGITAL_UNIX */
+
+#define ACE_SIZEOF_LONG 8
+
+#define ACE_DEFAULT_BASE_ADDR ((char *) 0x80000000)
+#define ACE_HAS_AUTOMATIC_INIT_FINI
+#define ACE_HAS_NONCONST_SETRLIMIT
+#define ACE_HAS_BROKEN_T_ERROR
+#define ACE_HAS_NONCONST_WRITEV
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_DIRENT
+#define ACE_HAS_GETRUSAGE
+#define ACE_HAS_GPERF
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_IP_MULTICAST
+#define ACE_HAS_LLSEEK
+#define ACE_HAS_LONG_MAP_FAILED
+#define ACE_HAS_MSG
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONCONST_SENDMSG
+#define ACE_HAS_OSF1_GETTIMEOFDAY
+#define ACE_HAS_OSF_TIMOD_H
+#define ACE_HAS_POLL
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_PRIOCNTL
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_STRBUF_T
+#define ACE_HAS_STREAMS
+#define ACE_HAS_STRERROR
+#define ACE_HAS_STRPTIME
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_HAS_SVR4_SIGNAL_T
+#define ACE_HAS_SYS_SYSCALL_H
+#define ACE_HAS_SYSV_IPC
+#if (ACE_MT_SAFE == 0)
+// clearerr is not defined when _REENTRANT is not defined
+#define ACE_LACKS_CLEARERR
+#else /* ACE_MT_SAFE != 0 */
+#define ACE_HAS_THREADS
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+#define ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR
+#endif /* ACE_MT_SAFE != 0 */
+#define ACE_HAS_TIUSER_H
+#define ACE_HAS_XTI
+#define ACE_HAS_TLI_PROTOTYPES
+#define ACE_HAS_UALARM
+#define ACE_HAS_UCONTEXT_T
+#define ACE_LACKS_PRI_T
+#define ACE_LACKS_RWLOCK_T
+#define ACE_PAGE_SIZE 8192
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+
+// DJT 6/10/96 All these broken macro's can now be removed with the
+// approporiate ordering of the include files. The Platinum release
+// now temporarily supports both forms. Platform's implementation of
+// sendmsg() has a non-const msgheader parameter.
+#define ACE_HAS_NONCONST_SENDMSG
+#define ACE_HAS_IDTYPE_T
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+
+#if DIGITAL_UNIX >= 0x500
+# define ACE_HAS_XPG4_MULTIBYTE_CHAR 1
+#endif /* DIGITAL_UNIX >= 0x500 */
+
+#if DIGITAL_UNIX >= 0x40E
+# define ACE_LACKS_STDINT_H
+#endif /* DIGITAL_UNIX >= 0x40E */
+
+#if (DIGITAL_UNIX >= 0x400) && (DIGITAL_UNIX < 0x500)
+#define ACE_LACKS_PREAD_PROTOTYPE
+#endif /* (DIGITAL_UNIX >= 0x400) && (DIGITAL_UNIX < 0x500) */
+
+// gethostbyaddr does not handle IPv6-mapped-IPv4 addresses
+#define ACE_HAS_BROKEN_GETHOSTBYADDR_V4MAPPED
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_TRU64_H */
diff --git a/ACE/ace/config-unixware-7.1.0.h b/ACE/ace/config-unixware-7.1.0.h
new file mode 100644
index 00000000000..53f42f3a1b1
--- /dev/null
+++ b/ACE/ace/config-unixware-7.1.0.h
@@ -0,0 +1,414 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+
+/* ACE configuration header file */
+
+/* Include the commong gnu config file */
+#include "config-g++-common.h"
+
+/* For unixware 7.1 && g++ 2.91.57, see if this fixes my problem */
+#ifndef UNIXWARE_7_1
+#define UNIXWARE_7_1
+#endif
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define _REENTRANT if reentrant functions should be used. */
+#ifndef _REENTRANT
+# define _REENTRANT 1
+#endif
+
+#define ACE_HAS_NEW_NO_H 1
+#define ACE_HAS_STDEXCEPT_NO_H 1
+
+#define ACE_THREAD_MIN_PRIORITY 0
+#if defined (ACE_THREAD_MIN_PRIORITY)
+# define PTHREAD_MIN_PRIORITY ACE_THREAD_MIN_PRIORITY
+#endif /* #if defined (ACE_THREAD_MIN_PRIORITY) */
+
+#define ACE_THREAD_MAX_PRIORITY 99
+#if defined (ACE_THREAD_MAX_PRIORITY)
+# define PTHREAD_MAX_PRIORITY ACE_THREAD_MAX_PRIORITY
+#endif /* #if defined (ACE_THREAD_MAX_PRIORITY) */
+
+/* Specify sizes of given built-in types. If a size isn't defined here,
+ then ace/Basic_Types.h will attempt to deduce the size. */
+/* #undef ACE_SIZEOF_CHAR */
+#define ACE_SIZEOF_SHORT 2
+#define ACE_SIZEOF_INT 4
+#define ACE_SIZEOF_LONG 4
+#define ACE_SIZEOF_LONG_LONG 8
+#define ACE_SIZEOF_VOID_P 4
+#define ACE_SIZEOF_FLOAT 4
+#define ACE_SIZEOF_DOUBLE 8
+#define ACE_SIZEOF_LONG_DOUBLE 12
+
+/* Enable ACE inlining */
+#define __ACE_INLINE__ 1
+
+/* OS has priocntl (2) */
+#define ACE_HAS_PRIOCNTL 1
+
+/* Platform has pread() and pwrite() support */
+#define ACE_HAS_P_READ_WRITE 1
+
+/* Compiler/platform supports alloca() */
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA 1
+
+/* Compiler/platform correctly calls init()/fini() for shared libraries */
+#define ACE_HAS_AUTOMATIC_INIT_FINI 1
+
+/* Platform doesn't cast MAP_FAILED to a (void *). */
+/* #undef ACE_HAS_BROKEN_MAP_FAILED */
+/* Staller: oh yes, let's do this! */
+#define ACE_HAS_BROKEN_MAP_FAILED
+
+/* Prototypes for both signal() and struct sigaction are consistent. */
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES 1
+
+/* Platform supports operations on directories via struct dirent,
+ readdir_r, etc. */
+#define ACE_HAS_DIRENT 1
+
+/* Compiler supports C++ exception handling */
+// MM-Graz if ! defined inserted, to prevent warnings, because it is already
+// defined in config-g++common.h
+# if !defined (ACE_HAS_EXCEPTIONS)
+#define ACE_HAS_EXCEPTIONS 1
+# endif
+
+/* Platform supports getpagesize() call (otherwise, ACE_PAGE_SIZE must be
+ defined, except on Win32) */
+#define ACE_HAS_GETPAGESIZE 1
+
+/* Platform supports the getrusage() system call. */
+#define ACE_HAS_GETRUSAGE 1
+
+/* Platform has a getrusage () prototype in sys/resource.h that differs from
+ the one in ace/OS.i. */
+#define ACE_HAS_GETRUSAGE_PROTOTYPE 1
+
+/* Denotes that GNU has cstring.h as standard which redefines memchr() */
+#define ACE_HAS_GNU_CSTRING_H
+
+/* The GPERF utility is compiled for this platform */
+#define ACE_HAS_GPERF 1
+
+/* Optimize ACE_Handle_Set::count_bits for select() operations (common case) */
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT 1
+
+/* Compiler/platform supports idtype_t. */
+#define ACE_HAS_IDTYPE_T 1
+
+/* Platform supports IP multicast */
+#define ACE_HAS_IP_MULTICAST 1
+
+/* Platform supports thr_keydelete (e.g,. UNIXWARE) */
+#define ACE_HAS_THR_KEYDELETE 1
+
+/* Platform calls thr_minstack() rather than thr_min_stack() (e.g., Tandem). */
+#define ACE_HAS_THR_MINSTACK 1
+
+/* Platform supports recvmsg and sendmsg */
+#define ACE_HAS_MSG 1
+
+/* Platform's select() uses non-const timeval* (only found on Linux right
+ now) */
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL 1
+
+/* Uses ctime_r & asctime_r with only two parameters vs. three. */
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R 1
+
+/* Platform is an Intel Pentium microprocessor. */
+/* There is a problem with the gethrtime() because of (apparently) a problem
+ with the inline assembly instruction. Hopefully there is a way to resolve
+ that with an improvement to the assembler
+*/
+#ifdef ACE_HAS_PENTIUM
+#undef ACE_HAS_PENTIUM
+#endif /* ACE_HAS_PENTIUM */
+
+
+/* Platform contains <poll.h> */
+#define ACE_HAS_POLL 1
+
+/* Platform supports POSIX O_NONBLOCK semantics */
+#define ACE_HAS_POSIX_NONBLOCK 1
+
+/* Platform supports the POSIX struct timespec type */
+#define ACE_HAS_POSIX_TIME 1
+
+/* Platform supports the /proc file system and defines tid_t
+ in <sys/procfs.h> */
+#define ACE_HAS_PROC_FS 1
+
+/* Platform supports POSIX Threads */
+#define ACE_HAS_PTHREADS 1
+
+/* pthread.h declares an enum with PTHREAD_PROCESS_PRIVATE and
+ PTHREAD_PROCESS_SHARED values */
+#define ACE_HAS_PTHREAD_PROCESS_ENUM 1
+
+/* Platform will recurse infinitely on thread exits from TSS cleanup routines
+ (e.g., AIX) */
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS 1
+
+/* Platform supports reentrant functions (i.e., all the POSIX *_r
+ functions). */
+#define ACE_HAS_REENTRANT_FUNCTIONS 1
+
+/* Platform has support for multi-byte character support compliant with the
+ XPG4 Worldwide Portability Interface wide-character classification. */
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR 1
+
+/* Platform does not support reentrant netdb functions (getprotobyname_r,
+ getprotobynumber_r, gethostbyaddr_r, gethostbyname_r, getservbyname_r). */
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS 1
+
+/* Platform supports the POSIX regular expression library */
+#define ACE_HAS_REGEX 1
+
+/* Platform has special header for select(). */
+#define ACE_HAS_SELECT_H 1
+
+/* Platform has a function to set t_errno (e.g., Tandem). */
+#define ACE_HAS_SET_T_ERRNO 1
+
+/* Platform supports SVR4 extended signals */
+#define ACE_HAS_SIGINFO_T 1
+
+/* Platform/compiler has the sigwait(2) prototype */
+#define ACE_HAS_SIGWAIT 1
+
+/* Compiler/platform defines the sig_atomic_t typedef */
+#define ACE_HAS_SIG_ATOMIC_T 1
+
+/* Platform supports new BSD inet_addr len field. */
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN 1
+
+/* OS/compiler uses size_t * rather than int * for socket lengths */
+#define ACE_HAS_SIZET_SOCKET_LEN 1
+
+/* Compiler/platform provides the sys/sockio.h file */
+#define ACE_HAS_SYS_SOCKIO_H 1
+
+/* Compiler supports the ssize_t typedef */
+#define ACE_HAS_SSIZE_T 1
+
+/* Platform supports UNIX International Threads */
+#define ACE_HAS_STHREADS 1
+
+/* Platform has thr_yield() */
+#define ACE_HAS_THR_YIELD 1
+
+/* Compiler/platform supports struct strbuf */
+#define ACE_HAS_STRBUF_T 1
+
+/* Platform supports STREAMS */
+#define ACE_HAS_STREAMS 1
+
+/* Platform supports STREAM pipes */
+#define ACE_HAS_STREAM_PIPES 1
+
+/* Compiler/platform supports strerror () */
+#define ACE_HAS_STRERROR 1
+
+/* Platform/Compiler supports a String class (e.g., GNU or Win32). */
+#define ACE_HAS_STRING_CLASS 1
+
+/* Platform has <strings.h> (which contains bzero() prototype) */
+#define ACE_HAS_STRINGS 1
+
+/* Platform/compiler supports void * as second parameter to gettimeofday(). */
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY 1
+
+/* Compiler/platform supports SVR4 dynamic linking semantics */
+#define ACE_HAS_SVR4_DYNAMIC_LINKING 1
+
+/* Compiler/platform supports SVR4 TLI (in particular, T_GETNAME stuff)... */
+#define ACE_HAS_SVR4_TLI 1
+
+/* Compiler/platform contains the <sys/syscall.h> file. */
+#define ACE_HAS_SYS_SYSCALL_H 1
+
+/* Platform supports system configuration information */
+#define ACE_HAS_SYSINFO 1
+
+/* Platform supports System V IPC (most versions of UNIX, but not Win32) */
+#define ACE_HAS_SYSV_IPC 1
+
+/* Platform provides <sys/filio.h> header */
+#define ACE_HAS_SYS_FILIO_H 1
+
+/* Platform provides <sys/xti.h> header */
+#define ACE_HAS_SYS_XTI_H 1
+
+/* Platform has POSIX terminal interface. */
+#define ACE_HAS_TERMIOS 1
+
+/* Platform supports threads */
+#define ACE_HAS_THREADS 1
+
+/* Compiler/platform has thread-specific storage */
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE 1
+
+/* Platform supports TLI timod STREAMS module */
+#define ACE_HAS_TIMOD_H 1
+
+/* Platform supports TLI tiuser header */
+#define ACE_HAS_TIUSER_H 1
+
+/* Platform supports TLI. Also see ACE_TLI_TCP_DEVICE. */
+#define ACE_HAS_TLI 1
+
+/* Platform provides TLI function prototypes */
+#define ACE_HAS_TLI_PROTOTYPES 1
+
+/* Platform supports ualarm() */
+#define ACE_HAS_UALARM 1
+
+/* Platform supports ucontext_t (which is used in the extended signal API). */
+#define ACE_HAS_UCONTEXT_T 1
+
+/* Platform has <utime.h> header file */
+#define ACE_HAS_UTIME 1
+
+/* Platform requires void * for mmap(). */
+#define ACE_HAS_VOIDPTR_MMAP 1
+
+/* Platform has XTI (X/Open-standardized superset of TLI). Implies
+ ACE_HAS_TLI but uses a different header file. */
+#define ACE_HAS_XTI 1
+
+/* Platform can not build ace/IOStream{,_T}.cpp. This does not necessarily
+ mean that the platform does not support iostreams. */
+#define ACE_LACKS_ACE_IOSTREAM 1
+
+/* Platform does not have u_longlong_t typedef */
+#define ACE_LACKS_U_LONGLONG_T 1
+
+/* Platform lacks madvise() (e.g., Linux) */
+#define ACE_LACKS_MADVISE 1
+
+/* Platform lacks pri_t (e.g., Tandem NonStop UNIX). */
+#define ACE_LACKS_PRI_T 1
+
+/* Platform lacks pthread_thr_sigsetmask (e.g., MVS, HP/UX, and OSF/1 3.2) */
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK 1
+
+/* Platfrom lack pthread_yield() support. */
+#define ACE_LACKS_PTHREAD_YIELD 1
+
+/* Platform lacks readers/writer locks. */
+#define ACE_LACKS_RWLOCK_T 1
+
+/* MIT pthreads platform lacks the timedwait prototypes */
+#define ACE_LACKS_TIMEDWAIT_PROTOTYPES 1
+
+/* Platform does not define timepec_t as a typedef for struct timespec. */
+#define ACE_LACKS_TIMESPEC_T 1
+
+/* Compile using multi-thread libraries */
+#define ACE_MT_SAFE 1
+
+/* Platform needs regexpr.h for regular expression support */
+#define ACE_NEEDS_REGEXPR_H 1
+
+/* Platform needs to #include <sched.h> to get thread scheduling defs. */
+#define ACE_NEEDS_SCHED_H 1
+
+/*********************************************************************/
+/* Compiler's template mechanim must see source code (i.e., .cpp files). This
+ is used for GNU G++. */
+/* Staller -> make 0 */
+// #undef ACE_TEMPLATES_REQUIRE_SOURCE
+
+/*********************************************************************/
+
+/* The OS/platform supports the poll() event demultiplexor */
+#define ACE_USE_POLL 1
+
+/* Platform has its standard c++ library in the namespace std. */
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+
+/* The number of bytes in a double. */
+#define SIZEOF_DOUBLE 8
+
+/* The number of bytes in a float. */
+#define SIZEOF_FLOAT 4
+
+/* The number of bytes in a int. */
+#define SIZEOF_INT 4
+
+/* The number of bytes in a long. */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in a long double. */
+#define SIZEOF_LONG_DOUBLE 12
+
+/* The number of bytes in a long long. */
+#define SIZEOF_LONG_LONG 8
+
+/* The number of bytes in a short. */
+#define SIZEOF_SHORT 2
+
+/* The number of bytes in a signed char. */
+#define SIZEOF_SIGNED_CHAR 1
+
+/* The number of bytes in a void *. */
+#define SIZEOF_VOID_P 4
+
+/* Define if you have the execv function. */
+#define HAVE_EXECV 1
+
+/* Define if you have the execve function. */
+#define HAVE_EXECVE 1
+
+/* Define if you have the execvp function. */
+#define HAVE_EXECVP 1
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <fstream> header file. */
+#define HAVE_FSTREAM 1
+
+/* Define if you have the <iomanip> header file. */
+#define HAVE_IOMANIP 1
+
+/* Define if you have the <iostream> header file. */
+#define HAVE_IOSTREAM 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Name of package */
+#define PACKAGE "ace"
+
+/* Added by Staller */
+#define ENUM_BOOLEAN // See file /usr/local/lib/gcc-lib/i486-pc-sysv5/egcs-2.91.60/include/sys/types.h
+#define howmany(x, y) (((x)+((y)-1))/(y))
+#define ACE_HAS_BROKEN_T_ERROR // make a nasty warning disappear in OS.i
+#define __USLC__ 1
+#define __IOCTL_VERSIONED__ // By Carlo!
+
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-unixware-7.1.0.udk.h b/ACE/ace/config-unixware-7.1.0.udk.h
new file mode 100644
index 00000000000..0ba282a4e51
--- /dev/null
+++ b/ACE/ace/config-unixware-7.1.0.udk.h
@@ -0,0 +1,465 @@
+/* -*- C++ -*- */
+#ifndef ACE_CONFIG_UNIXWARE_UDK_H
+#define ACE_CONFIG_UNIXWARE_UDK_H
+
+// $Id$
+
+// Configuration for the unixware UDK compiler. derived from the unixware/g++ config
+// which was itself derived from an autoconfig run.
+
+/* ACE configuration header file */
+
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+
+#ifndef UNIXWARE_7_1
+#define UNIXWARE_7_1
+#endif
+
+#define ACE_LACKS_PLACEMENT_OPERATOR_DELETE
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define _REENTRANT if reentrant functions should be used. */
+#ifndef _REENTRANT
+# define _REENTRANT 1
+#endif
+
+#define ACE_HAS_NEW_NO_H 1
+#define ACE_HAS_STDEXCEPT_NO_H 1
+
+/*
+ * TODO: These two next #defines have an #undef before them, in
+ * case the variable being defined already had a value.
+ * The #undefs are being picked up by configure, and are commented out!
+ */
+#define ACE_THREAD_MIN_PRIORITY 0
+#if defined (ACE_THREAD_MIN_PRIORITY)
+/* # undef PTHREAD_MIN_PRIORITY */
+# define PTHREAD_MIN_PRIORITY ACE_THREAD_MIN_PRIORITY
+#endif /* #if defined (ACE_THREAD_MIN_PRIORITY) */
+
+#define ACE_THREAD_MAX_PRIORITY 99
+#if defined (ACE_THREAD_MAX_PRIORITY)
+/* # undef PTHREAD_MAX_PRIORITY */
+# define PTHREAD_MAX_PRIORITY ACE_THREAD_MAX_PRIORITY
+#endif /* #if defined (ACE_THREAD_MAX_PRIORITY) */
+
+
+
+/* UnixWare specific configuration parameters */
+/* #undef UNIXWARE */
+/* #undef UNIXWARE_2_0 */
+/* #undef UNIXWARE_2_1 */
+
+/* Specify sizes of given built-in types. If a size isn't defined here,
+ then ace/Basic_Types.h will attempt to deduce the size. */
+/* #undef ACE_SIZEOF_CHAR */
+#define ACE_SIZEOF_SHORT 2
+#define ACE_SIZEOF_INT 4
+#define ACE_SIZEOF_LONG 4
+#define ACE_SIZEOF_LONG_LONG 8
+#define ACE_SIZEOF_VOID_P 4
+#define ACE_SIZEOF_FLOAT 4
+#define ACE_SIZEOF_DOUBLE 8
+#define ACE_SIZEOF_LONG_DOUBLE 12
+
+/* Enable ACE inlining */
+#define __ACE_INLINE__ 1
+
+/* Platform supports Asynchronous IO calls */
+/* #define ACE_HAS_AIO_CALLS */
+
+/* Specify this if you don't want threads to inherit parent thread's
+ ACE_Log_Msg properties. */
+/* #undef ACE_THREADS_DONT_INHERIT_LOG_MSG */
+
+/* OS has priocntl (2) */
+#define ACE_HAS_PRIOCNTL 1
+
+/* Platform has pread() and pwrite() support */
+#define ACE_HAS_P_READ_WRITE 1
+
+/* Compiler/platform correctly calls init()/fini() for shared libraries */
+#define ACE_HAS_AUTOMATIC_INIT_FINI 1
+
+/* Compiler handles explicit calling of template destructor correctly.
+ See "ace/OS.h" for details. */
+/* Staller: already defined by config-g++-common.h
+#define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR 1
+*/
+
+/* Platform doesn't cast MAP_FAILED to a (void *). */
+/* #undef ACE_HAS_BROKEN_MAP_FAILED */
+/* Staller: oh yes, let's do this! */
+#define ACE_HAS_BROKEN_MAP_FAILED
+
+
+/* Prototypes for both signal() and struct sigaction are consistent. */
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES 1
+
+/* Compiler/platform has correctly prototyped header files */
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+/* Platform supports operations on directories via struct dirent,
+ readdir_r, etc. */
+#define ACE_HAS_DIRENT
+
+/* Compiler supports C++ exception handling */
+# if !defined (ACE_HAS_EXCEPTIONS)
+#define ACE_HAS_EXCEPTIONS
+# endif
+
+/* Platform supports getpagesize() call (otherwise, ACE_PAGE_SIZE must be
+ defined, except on Win32) */
+#define ACE_HAS_GETPAGESIZE
+
+/* Platform supports the getrusage() system call. */
+#define ACE_HAS_GETRUSAGE
+
+/* Platform has a getrusage () prototype in sys/resource.h that differs from
+ the one in ace/OS.i. */
+#define ACE_HAS_GETRUSAGE_PROTOTYPE
+
+/* The GPERF utility is compiled for this platform */
+#define ACE_HAS_GPERF
+
+/* Optimize ACE_Handle_Set::count_bits for select() operations (common case) */
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT 1
+
+/* Compiler/platform supports SunOS high resolution timers */
+/* #undef ACE_HAS_HI_RES_TIMER */
+
+/* Compiler/platform supports idtype_t. */
+#define ACE_HAS_IDTYPE_T
+
+/* Inline all the static class OS methods to remove call overhead */
+/* Note: This gets defined by OS.h if __ACE_INLINE__ is defined */
+/* #undef ACE_HAS_INLINED_OSCALLS */
+
+/* Platform supports IP multicast */
+#define ACE_HAS_IP_MULTICAST
+
+/* Platform supports thr_keydelete (e.g,. UNIXWARE) */
+#define ACE_HAS_THR_KEYDELETE
+
+/* Platform calls thr_minstack() rather than thr_min_stack() (e.g., Tandem). */
+#define ACE_HAS_THR_MINSTACK
+
+/* Some files, such as ace/streams.h, want to include new style C++ stream
+ headers. These headers are iomanip, ios, iostream, istream, ostream,
+ fstream and streambuf. If _all_ of these headers aren't available, then
+ assume that only iostream.h and fstream.h are available. */
+/* #define ACE_USES_OLD_IOSTREAMS */
+
+/* Platform supports recvmsg and sendmsg */
+#define ACE_HAS_MSG
+
+/* Platform's select() uses non-const timeval* (only found on Linux right
+ now) */
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+
+/* Uses ctime_r & asctime_r with only two parameters vs. three. */
+#define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+
+
+/* Platform is an Intel Pentium microprocessor. */
+/* There is a problem with the gethrtime() because of (apparently) a problem
+ with the inline assembly instruction. Hopefully there is a way to resolve
+ that with an improvement to the assembler
+*/
+#ifdef ACE_HAS_PENTIUM
+//#undef ACE_HAS_PENTIUM
+#endif /* ACE_HAS_PENTIUM */
+
+
+/* Platform contains <poll.h> */
+#define ACE_HAS_POLL
+
+/* Platform supports POSIX O_NONBLOCK semantics */
+#define ACE_HAS_POSIX_NONBLOCK
+
+/* Platform supports the POSIX struct timespec type */
+#define ACE_HAS_POSIX_TIME
+
+/* Platform supports the /proc file system and defines tid_t
+ in <sys/procfs.h> */
+#define ACE_HAS_PROC_FS
+
+/* Platform supports POSIX Threads */
+#define ACE_HAS_PTHREADS
+
+/* pthread.h declares an enum with PTHREAD_PROCESS_PRIVATE and
+ PTHREAD_PROCESS_SHARED values */
+#define ACE_HAS_PTHREAD_PROCESS_ENUM
+
+/* Platform will recurse infinitely on thread exits from TSS cleanup routines
+ (e.g., AIX) */
+#define ACE_HAS_RECURSIVE_THR_EXIT_SEMANTICS
+
+/* Platform supports reentrant functions (i.e., all the POSIX *_r
+ functions). */
+#define ACE_HAS_REENTRANT_FUNCTIONS
+
+/* Platform has support for multi-byte character support compliant with the
+ XPG4 Worldwide Portability Interface wide-character classification. */
+#define ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+/* Platform does not support reentrant netdb functions (getprotobyname_r,
+ getprotobynumber_r, gethostbyaddr_r, gethostbyname_r, getservbyname_r). */
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+
+/* Platform supports the POSIX regular expression library */
+#define ACE_HAS_REGEX
+
+/* Platform has special header for select(). */
+#define ACE_HAS_SELECT_H
+
+/* Platform has a function to set t_errno (e.g., Tandem). */
+#define ACE_HAS_SET_T_ERRNO
+
+/* Platform supports SVR4 extended signals */
+#define ACE_HAS_SIGINFO_T
+
+/* Platform/compiler has the sigwait(2) prototype */
+#define ACE_HAS_SIGWAIT
+
+/* Compiler/platform defines the sig_atomic_t typedef */
+#define ACE_HAS_SIG_ATOMIC_T
+
+/* Platform supports new BSD inet_addr len field. */
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+
+/* OS/compiler uses size_t * rather than int * for socket lengths */
+#define ACE_HAS_SIZET_SOCKET_LEN
+
+/* Compiler/platform provides the sys/sockio.h file */
+#define ACE_HAS_SYS_SOCKIO_H
+
+/* Compiler supports the ssize_t typedef */
+#define ACE_HAS_SSIZE_T
+
+/* Platform supports UNIX International Threads */
+#define ACE_HAS_STHREADS
+
+/* Platform has thr_yield() */
+#define ACE_HAS_THR_YIELD
+
+/* Platform/compiler supports Standard C++ Library */
+/* It seems that UDK provides std-like declarations for only portions
+ such as <exception>
+*/
+#define ACE_HAS_STANDARD_CPP_LIBRARY 0
+
+/* Compiler/platform supports struct strbuf */
+#define ACE_HAS_STRBUF_T
+
+/* Platform supports STREAMS */
+#define ACE_HAS_STREAMS
+
+/* Platform supports STREAM pipes */
+#define ACE_HAS_STREAM_PIPES
+
+/* Compiler/platform supports strerror () */
+#define ACE_HAS_STRERROR
+
+/* Platform/Compiler supports a String class (e.g., GNU or Win32). */
+#define ACE_HAS_STRING_CLASS
+
+/* Platform has <strings.h> (which contains bzero() prototype) */
+#define ACE_HAS_STRINGS
+
+/* Platform/compiler supports void * as second parameter to gettimeofday(). */
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY
+
+/* Compiler/platform supports SVR4 dynamic linking semantics */
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+
+/* Compiler/platform supports SVR4 TLI (in particular, T_GETNAME stuff)... */
+#define ACE_HAS_SVR4_TLI
+
+/* Compiler/platform contains the <sys/syscall.h> file. */
+#define ACE_HAS_SYS_SYSCALL_H
+
+/* Platform supports system configuration information */
+#define ACE_HAS_SYSINFO 1
+
+/* Platform supports System V IPC (most versions of UNIX, but not Win32) */
+#define ACE_HAS_SYSV_IPC 1
+
+/* Platform provides <sys/filio.h> header */
+#define ACE_HAS_SYS_FILIO_H 1
+
+/* Platform provides <sys/xti.h> header */
+#define ACE_HAS_SYS_XTI_H 1
+
+/* Compiler implements template specialization */
+#define ACE_HAS_TEMPLATE_SPECIALIZATION 1
+
+/* Compiler implements templates that support typedefs inside of classes used
+ as formal arguments to a template class. */
+#define ACE_HAS_TEMPLATE_TYPEDEFS 1
+
+/* Platform has POSIX terminal interface. */
+#define ACE_HAS_TERMIOS 1
+
+/* Platform supports threads */
+#define ACE_HAS_THREADS 1
+
+/* Compiler/platform has thread-specific storage */
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE 1
+
+/* Platform supports TLI timod STREAMS module */
+#define ACE_HAS_TIMOD_H 1
+
+/* Platform supports TLI tiuser header */
+#define ACE_HAS_TIUSER_H 1
+
+/* Platform supports TLI. Also see ACE_TLI_TCP_DEVICE. */
+#define ACE_HAS_TLI 1
+
+/* Platform provides TLI function prototypes */
+#define ACE_HAS_TLI_PROTOTYPES 1
+
+/* Platform supports ualarm() */
+#define ACE_HAS_UALARM 1
+
+/* Platform supports ucontext_t (which is used in the extended signal API). */
+#define ACE_HAS_UCONTEXT_T 1
+
+/* Platform has <utime.h> header file */
+#define ACE_HAS_UTIME 1
+
+/* Prints out console message in ACE_NOTSUP. Useful for tracking down origin
+ of ACE_NOTSUP. */
+/* #undef ACE_HAS_VERBOSE_NOTSUP */
+
+/* Platform requires void * for mmap(). */
+#define ACE_HAS_VOIDPTR_MMAP 1
+
+/* Platform has XTI (X/Open-standardized superset of TLI). Implies
+ ACE_HAS_TLI but uses a different header file. */
+#define ACE_HAS_XTI 1
+
+/* Platform can not build ace/IOStream{,_T}.cpp. This does not necessarily
+ mean that the platform does not support iostreams. */
+#define ACE_LACKS_ACE_IOSTREAM 1
+
+/* Platform does not have u_longlong_t typedef */
+#define ACE_LACKS_U_LONGLONG_T 1
+
+/* Platform lacks madvise() (e.g., Linux) */
+#define ACE_LACKS_MADVISE 1
+
+/* Platform lacks pri_t (e.g., Tandem NonStop UNIX). */
+#define ACE_LACKS_PRI_T 1
+
+/* Platform lacks pthread_thr_sigsetmask (e.g., MVS, HP/UX, and OSF/1 3.2) */
+#define ACE_LACKS_PTHREAD_THR_SIGSETMASK 1
+
+/* Platfrom lack pthread_yield() support. */
+#define ACE_LACKS_PTHREAD_YIELD 1
+
+/* Platform lacks readers/writer locks. */
+#define ACE_LACKS_RWLOCK_T 1
+
+/* MIT pthreads platform lacks the timedwait prototypes */
+#define ACE_LACKS_TIMEDWAIT_PROTOTYPES 1
+
+/* Platform does not define timepec_t as a typedef for struct timespec. */
+#define ACE_LACKS_TIMESPEC_T 1
+
+/* Compile using multi-thread libraries */
+#define ACE_MT_SAFE 1
+
+/* Platform needs regexpr.h for regular expression support */
+#define ACE_NEEDS_REGEXPR_H 1
+
+/* Platform needs to #include <sched.h> to get thread scheduling defs. */
+#define ACE_NEEDS_SCHED_H 1
+
+/* The OS/platform supports the poll() event demultiplexor */
+#define ACE_USE_POLL 1
+
+/* Platform has its standard c++ library in the namespace std. */
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+
+/* The number of bytes in a double. */
+#define SIZEOF_DOUBLE 8
+
+/* The number of bytes in a float. */
+#define SIZEOF_FLOAT 4
+
+/* The number of bytes in a int. */
+#define SIZEOF_INT 4
+
+/* The number of bytes in a long. */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in a long double. */
+#define SIZEOF_LONG_DOUBLE 12
+
+/* The number of bytes in a long long. */
+#define SIZEOF_LONG_LONG 8
+
+/* The number of bytes in a short. */
+#define SIZEOF_SHORT 2
+
+/* The number of bytes in a signed char. */
+#define SIZEOF_SIGNED_CHAR 1
+
+/* The number of bytes in a void *. */
+#define SIZEOF_VOID_P 4
+
+/* Define if you have the execv function. */
+#define HAVE_EXECV 1
+
+/* Define if you have the execve function. */
+#define HAVE_EXECVE 1
+
+/* Define if you have the execvp function. */
+#define HAVE_EXECVP 1
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <fstream> header file. */
+#define HAVE_FSTREAM 1
+
+/* Define if you have the <iomanip> header file. */
+#define HAVE_IOMANIP 1
+
+/* Define if you have the <iostream> header file. */
+#define HAVE_IOSTREAM 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Name of package */
+#define PACKAGE "ace"
+
+/* Version number of package */
+#define VERSION "4.6.37"
+
+/* Added by Staller */
+#define ENUM_BOOLEAN // See file /usr/local/lib/gcc-lib/i486-pc-sysv5/egcs-2.91.60/include/sys/types.h
+/* Hat nix gebracht
+#define ACE_DEFAULT_SELECT_REACTOR_SIZE 256 // this is like in linux config fileto avoid another error
+*/
+#define howmany(x, y) (((x)+((y)-1))/(y))
+#define ACE_HAS_BROKEN_T_ERROR // let disappear a nasty warning from OS.i
+#if !defined (__USLC__)
+# define __USLC__ 1
+#endif
+
+#define __IOCTL_VERSIONED__ // By Carlo!
+#endif /* ACE_UNIXWARE_UDK_H */
diff --git a/ACE/ace/config-visualage.h b/ACE/ace/config-visualage.h
new file mode 100644
index 00000000000..f4613f39c8f
--- /dev/null
+++ b/ACE/ace/config-visualage.h
@@ -0,0 +1,20 @@
+/* -*- C++ -*- */
+// $Id$
+
+// This configuration file automatically includes the proper
+// configurations for IBM's VisualAge C++ compiler on Win32 and AIX.
+
+#ifndef CONFIG_VISUALAGE_H
+#define CONFIG_VISUALAGE_H
+#include /**/ "ace/pre.h"
+
+#ifdef __TOS_WIN__
+ #include "ace/config-win32.h"
+#elif __TOS_AIX__
+ #include "ace/config-aix-4.x.h"
+#else
+ #include "PLATFORM NOT SPECIFIED"
+#endif /* __TOS_WIN__ */
+
+#include /**/ "ace/post.h"
+#endif //CONFIG_VISUALAGE_H
diff --git a/ACE/ace/config-vxworks.h b/ACE/ace/config-vxworks.h
new file mode 100644
index 00000000000..4ee9e5a20da
--- /dev/null
+++ b/ACE/ace/config-vxworks.h
@@ -0,0 +1,33 @@
+//* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for VxWorks
+// Based on ACE_VXWORKS it will select the correct config file
+
+#ifndef ACE_CONFIG_VXWORKS_H
+#define ACE_CONFIG_VXWORKS_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_VXWORKS)
+# error You must define ACE_VXWORKS
+#endif /* ! ACE_VXWORKS */
+
+#if (ACE_VXWORKS == 0x551)
+# include "ace/config-vxworks5.x.h"
+#elif (ACE_VXWORKS == 0x620)
+# include "ace/config-vxworks6.2.h"
+#elif (ACE_VXWORKS == 0x630)
+# include "ace/config-vxworks6.3.h"
+#elif (ACE_VXWORKS == 0x640)
+# include "ace/config-vxworks6.4.h"
+#elif (ACE_VXWORKS == 0x650)
+# include "ace/config-vxworks6.5.h"
+#elif (ACE_VXWORKS == 0x660)
+# include "ace/config-vxworks6.6.h"
+#else
+#error Unknown VxWorks version
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_VXWORKS_H */
+
diff --git a/ACE/ace/config-vxworks5.x.h b/ACE/ace/config-vxworks5.x.h
new file mode 100644
index 00000000000..ca2cc9f9e25
--- /dev/null
+++ b/ACE/ace/config-vxworks5.x.h
@@ -0,0 +1,334 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for VxWorks
+// 5.5.x platforms using one of these compilers:
+// 1) The GNU g++ compiler that is shipped with Tornado 2.2 or newer.
+// 2) The Green Hills 1.8.8 and newer 1.8.9 compilers (not tested
+// already for a long time)
+// 3) The WindRiver Compiler (formerly known as Diab)
+
+#ifndef ACE_CONFIG_H
+#define ACE_CONFIG_H
+#include /**/ "ace/pre.h"
+
+#if ! defined (VXWORKS)
+# define VXWORKS
+#endif /* ! VXWORKS */
+
+#if ! defined (ACE_VXWORKS)
+# define ACE_VXWORKS 0x551
+#endif /* ! ACE_VXWORKS */
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// Compiler-specific configuration.
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+
+# define ACE_LACKS_IOSTREAM_FX
+
+# if !defined (ACE_MAIN)
+# define ACE_MAIN ace_main
+# endif /* ! ACE_MAIN */
+
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+# if (__GNUC__ == 2)
+# define ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE 1
+# endif
+
+# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
+ // GNU 3.3+ toolchain supports long long types but fails to define this so STL
+ // skips some definitions
+# if !defined (_GLIBCPP_USE_LONG_LONG)
+# define _GLIBCPP_USE_LONG_LONG
+# endif
+# endif /* (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) */
+
+#elif defined (ghs)
+ // Processor type, if necessary. Green Hills defines "ppc".
+# if defined (ppc)
+# define ACE_HAS_POWERPC_TIMER
+# define ACE_LACKS_CLEARERR
+# endif /* ppc */
+
+# define ACE_CONFIG_INCLUDE_GHS_COMMON
+# include "ace/config-ghs-common.h"
+
+# define ACE_LACKS_UNISTD_H
+# define ACE_LACKS_IOSTREAM_TOTALLY
+
+// Short-circuit the include of <arpa/inet.h>
+// Green Hills has a problem with multiply defined functions
+// with different parameters.
+# define __INCineth
+
+#elif defined (__DCPLUSPLUS__) || defined (__DCC__)
+ // Diab 4.2a or later.
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+ // We define it with a -D with make depend.
+# define ACE_LACKS_PRAGMA_ONCE
+# endif /* ! ACE_LACKS_PRAGMA_ONCE */
+
+ // Diab doesn't support VxWorks' iostream libraries.
+# define ACE_LACKS_IOSTREAM_TOTALLY
+# define ACE_LACKS_ACE_IOSTREAM
+
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 0
+
+# define ACE_TEMPLATES_REQUIRE_SOURCE
+
+#else /* ! __GNUG__ && ! ghs && !__DCC__ */
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler on VxWorks
+# endif /* __cplusplus */
+#endif /* ! __GNUG__ && ! ghs */
+
+// OS-specific configuration
+#define ACE_HAS_SIZET_PTR_ASCTIME_R_AND_CTIME_R
+#define ACE_MKDIR_LACKS_MODE
+#define ACE_HAS_NONCONST_GETBY
+#define ACE_HAS_NONCONST_STAT
+#define ACE_HAS_NONCONST_SWAB
+#define ACE_HAS_NONCONST_READV
+#define ACE_HAS_NONCONST_CHDIR
+#define ACE_HAS_NONCONST_UNLINK
+#define ACE_HAS_NONCONST_OPENDIR
+#define ACE_LACKS_UNIX_SYSLOG
+#define ACE_DEFAULT_MAX_SOCKET_BUFSIZ 32768
+#define ACE_DEFAULT_THREAD_KEYS 16
+#define ACE_HAS_BROKEN_ACCEPT_ADDR
+#define ACE_HAS_NONCONST_SENDMSG
+#define ACE_HAS_NONCONST_WRITEV
+#define ACE_HAS_CHARPTR_DL
+#define ACE_HAS_CHARPTR_SOCKOPT
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_DIRENT
+#define ACE_HAS_DLL 0
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_IOCTL_INT_3_PARAM
+#define ACE_HAS_MSG
+#define ACE_HAS_NONCONST_READV
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+#define ACE_HAS_STRDUP_EMULATION
+#define ACE_HAS_STRERROR
+#define ACE_HAS_THREADS
+#define ACE_LACKS_ALPHASORT
+#define ACE_LACKS_ACCESS
+#define ACE_LACKS_EXEC
+#define ACE_LACKS_FCNTL
+#define ACE_LACKS_FILELOCKS
+#define ACE_LACKS_FORK
+#define ACE_LACKS_FSYNC
+#define ACE_LACKS_GETHOSTENT
+#define ACE_LACKS_GETOPT
+#define ACE_LACKS_GETPID
+#define ACE_LACKS_GETPPID
+#define ACE_LACKS_GETSERVBYNAME
+#define ACE_LACKS_KEY_T
+#define ACE_LACKS_LSTAT
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MALLOC_H
+#define ACE_LACKS_MEMORY_H
+#define ACE_LACKS_MKFIFO
+#define ACE_LACKS_MKTEMP
+#define ACE_LACKS_MKSTEMP
+#define ACE_LACKS_MMAP
+#define ACE_LACKS_MPROTECT
+#define ACE_LACKS_MSYNC
+#define ACE_LACKS_NUMERIC_LIMITS
+#define ACE_LACKS_GETPROTOBYNAME
+#define ACE_LACKS_GETPROTOBYNUMBER
+#define ACE_LACKS_GETHOSTBYADDR
+#define ACE_LACKS_GETHOSTBYNAME
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_SYS_PARAM_H
+#define ACE_LACKS_PWD_FUNCTIONS
+#define ACE_LACKS_RAND_REENTRANT_FUNCTIONS
+#define ACE_LACKS_READDIR_R
+#define ACE_LACKS_READLINK
+#define ACE_LACKS_REALPATH
+#define ACE_LACKS_RLIMIT
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SBRK
+#define ACE_LACKS_SEEKDIR
+#define ACE_LACKS_SEMBUF_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_SI_ADDR
+#define ACE_LACKS_SOCKETPAIR
+#define ACE_LACKS_STRCASECMP
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SYSCALL
+#define ACE_LACKS_SYSCONF
+#define ACE_LACKS_SYS_SYSCTL_H
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_TELLDIR
+#define ACE_LACKS_TEMPNAM
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_TRUNCATE
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_UMASK
+#define ACE_LACKS_UTSNAME_T
+#define ACE_LACKS_UNAME
+#define ACE_LACKS_STRPTIME
+#define ACE_LACKS_VSNPRINTF
+#define ACE_LACKS_WAIT
+#define ACE_LACKS_WAITPID
+#define ACE_LACKS_DUP2
+#define ACE_LACKS_DUP
+#define ACE_LACKS_SUSECONDS_T
+#define ACE_LACKS_USECONDS_T
+#define ACE_LACKS_INTPTR_T
+#define ACE_PAGE_SIZE 4096
+#define ACE_THR_PRI_FIFO_DEF 101
+#define ACE_THR_PRI_OTHER_DEF ACE_THR_PRI_FIFO_DEF
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+#if !defined (ACE_VXWORKS_SPARE)
+# define ACE_VXWORKS_SPARE spare4
+#endif /* ! ACE_VXWORKS_SPARE */
+
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_SETSID
+#define ACE_LACKS_SETUID
+#define ACE_LACKS_SETEUID
+#define ACE_LACKS_GETEGID
+#define ACE_LACKS_GETGID
+#define ACE_LACKS_GETEUID
+#define ACE_LACKS_GETUID
+#define ACE_LACKS_SETGID
+#define ACE_LACKS_GETPGID
+
+#define ACE_LACKS_PIPE
+#define ACE_LACKS_STDINT_H
+#define ACE_LACKS_INTTYPES_H
+#define ACE_LACKS_UNISTD_H
+#define ACE_LACKS_SYS_SELECT_H
+#define ACE_LACKS_SYS_TIME_H
+#define ACE_LACKS_SYS_RESOURCE_H
+#define ACE_LACKS_DLFCN_H
+#define ACE_LACKS_SYS_UIO_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_WCHAR_H
+#define ACE_LACKS_PWD_H
+#define ACE_LACKS_SEARCH_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_STRINGS_H
+#define ACE_LACKS_TERMIOS_H
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_WCTYPE_H
+
+// Not sure if these should always be defined.
+#define ACE_LACKS_SYS_UN_H
+
+// Some string things
+#define ACE_LACKS_WCSCAT
+#define ACE_LACKS_WCSCHR
+#define ACE_LACKS_WCSCMP
+#define ACE_LACKS_WCSCPY
+#define ACE_LACKS_WCSCSPN
+#define ACE_LACKS_WCSLEN
+#define ACE_LACKS_WCSNCAT
+#define ACE_LACKS_WCSNCMP
+#define ACE_LACKS_WCSNCPY
+#define ACE_LACKS_WCSPBRK
+#define ACE_LACKS_WCSRCHR
+#define ACE_LACKS_WCSSPN
+#define ACE_LACKS_WCSSTR
+#define ACE_LACKS_WCSTOK
+#define ACE_LACKS_TOWLOWER
+#define ACE_LACKS_TOWUPPER
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+#define ACE_LACKS_WCSTOD
+#define ACE_LACKS_WCSTOL
+#define ACE_LACKS_WCSTOUL
+#define ACE_LACKS_WCSDUP
+
+#define ACE_LACKS_SYMLINKS
+#define ACE_LACKS_FGETWC
+#define ACE_LACKS_FGETWS
+#define ACE_LACKS_FPUTWS
+
+// It is possible to enable pthread support with VxWorks, when the user decides
+// to use this, we need some more defines
+#if defined ACE_HAS_PTHREADS
+# define ACE_LACKS_CONDATTR_PSHARED
+# define ACE_LACKS_MUTEXATTR_PSHARED
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+# define ACE_HAS_POSIX_SEM
+// Include this file, the sys/stat.h file shipped with VxWorks has old types
+// and without this include we get a lot of compile errors. A TSR has been filed
+// so that hopefully in the future we can zap this include
+#include "types/vxTypesOld.h"
+#else
+# define ACE_HAS_VXTHREADS
+# define ACE_LACKS_PTHREAD_H
+# define ACE_LACKS_COND_T
+// VxWorks has no recursive mutexes. This was set in the past but it doesn't
+// work with the pthread support, so only set it for the time being when pthread
+// is disabled
+# define ACE_HAS_RECURSIVE_MUTEXES
+// VxWorks does not have the pthread_mutex_timedlock operation, but there is
+// an emulation for this when not using the pthread mapping
+#define ACE_HAS_MUTEX_TIMEOUTS
+#define ACE_HAS_TSS_EMULATION
+#endif
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+// Needed include to get all VxWorks CPU types
+#include "types/vxCpu.h"
+#if (CPU == PENTIUM || CPU == PENTIUM2 || CPU == PENTIUM3 || CPU == PENTIUM4)
+// If running an Intel Pentium the
+// ACE_OS::gethrtime () can use the RDTSC instruction.
+# define ACE_HAS_PENTIUM
+#endif
+
+# if defined (TOOL) && (TOOL == gnu)
+# if defined (CPU) && (CPU == PPC85XX || CPU == PPC604 || CPU == PPC603)
+// These PPC's do lack log2
+# define ACE_LACKS_LOG2
+# endif
+# endif
+
+#if !defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
+# define ACE_NEEDS_HUGE_THREAD_STACKSIZE 65536
+#endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
+
+#if !defined (ACE_NTRACE)
+# define ACE_NTRACE 1
+#endif /* ACE_NTRACE */
+
+// By default, don't include RCS Id strings in object code.
+#if !defined (ACE_USE_RCSID)
+#define ACE_USE_RCSID 0
+#endif /* !ACE_USE_RCSID */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_H */
diff --git a/ACE/ace/config-vxworks6.2.h b/ACE/ace/config-vxworks6.2.h
new file mode 100644
index 00000000000..ff78628b15b
--- /dev/null
+++ b/ACE/ace/config-vxworks6.2.h
@@ -0,0 +1,332 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for VxWorks
+// 6.2 platforms using one of these compilers:
+// 1) The GNU g++ compiler that is shipped with VxWorks 6.2
+
+#ifndef ACE_CONFIG_VXWORKS_6_2_H
+#define ACE_CONFIG_VXWORKS_6_2_H
+#include /**/ "ace/pre.h"
+
+#if ! defined (VXWORKS)
+# define VXWORKS
+#endif /* ! VXWORKS */
+
+#if ! defined (ACE_VXWORKS)
+# define ACE_VXWORKS 0x620
+#endif /* ! ACE_VXWORKS */
+
+#if defined __RTP__
+ // Fix wrong typedef in unistd.h (unsigned short)
+ #define _SUSECONDS_T
+ typedef long suseconds_t;
+#endif
+#include <unistd.h>
+
+// Fix for including right typedef for pid_t in VxTypes.h (int)
+#include <vxWorksCommon.h>
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// Compiler-specific configuration.
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+
+# define ACE_LACKS_IOSTREAM_FX
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
+ // GNU 3.3+ toolchain supports long long types but fails to define this so STL
+ // skips some definitions
+# if !defined (_GLIBCPP_USE_LONG_LONG)
+# define _GLIBCPP_USE_LONG_LONG
+# endif
+# endif /* (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) */
+
+# if defined (__RTP__) && !defined (_HAS_C9X)
+// Workaround for the fact that under RTP the log2 method can't be used
+// without this define set, see TSR560446
+# define _C99
+# endif
+
+#elif defined (__DCPLUSPLUS__) || defined (__DCC__)
+ // Diab 4.2a or later.
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+ // We define it with a -D with make depend.
+# define ACE_LACKS_PRAGMA_ONCE
+# endif /* ! ACE_LACKS_PRAGMA_ONCE */
+
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# define ACE_TEMPLATES_REQUIRE_SOURCE
+
+#else /* ! __GNUG__ && ! ghs && !__DCC__ */
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler on VxWorks
+# endif /* __cplusplus */
+#endif /* ! __GNUG__ && ! ghs */
+
+#if !defined __RTP__
+# if defined (TOOL) && (TOOL == gnu)
+# if defined (CPU) && (CPU == PPC85XX || CPU == PPC604 || CPU == PPC603)
+// These PPC's do lack log2 in kernel mode
+# define ACE_LACKS_LOG2
+# endif
+# endif
+#endif
+
+// OS-specific configuration
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_NONCONST_GETBY
+#define ACE_HAS_NONCONST_SWAB
+#define ACE_HAS_NONCONST_READV
+#define ACE_LACKS_UNIX_SYSLOG
+#define ACE_DEFAULT_MAX_SOCKET_BUFSIZ 32768
+#define ACE_DEFAULT_THREAD_KEYS 16
+#define ACE_HAS_BROKEN_ACCEPT_ADDR
+#define ACE_HAS_NONCONST_SENDMSG
+#define ACE_HAS_NONCONST_WRITEV
+#define ACE_HAS_CHARPTR_DL
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_DIRENT
+#define ACE_HAS_DLL 0
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_IOCTL_INT_3_PARAM
+#define ACE_HAS_MSG
+#define ACE_HAS_NONCONST_READV
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_HAS_SIGACTION_CONSTP2
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+#define ACE_HAS_STRERROR
+#define ACE_HAS_THREADS
+#define ACE_HAS_SYSCTL
+#define ACE_LACKS_ALPHASORT
+#define ACE_LACKS_EXEC
+#define ACE_LACKS_FILELOCKS
+#define ACE_LACKS_FORK
+#define ACE_LACKS_GETHOSTENT
+#define ACE_LACKS_GETSERVBYNAME
+#define ACE_LACKS_GETPROTOBYNAME
+#define ACE_LACKS_GETPROTOBYNUMBER
+#define ACE_LACKS_KEY_T
+#define ACE_LACKS_LSTAT
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MALLOC_H
+#define ACE_LACKS_MEMORY_H
+#define ACE_LACKS_MKFIFO
+#define ACE_LACKS_MKTEMP
+#define ACE_LACKS_MKSTEMP
+#define ACE_LACKS_MMAP
+#define ACE_LACKS_MPROTECT
+#define ACE_LACKS_MSYNC
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_SYS_PARAM_H
+#define ACE_LACKS_PWD_FUNCTIONS
+#define ACE_LACKS_READDIR_R
+#define ACE_LACKS_READLINK
+#define ACE_LACKS_REALPATH
+#define ACE_LACKS_PIPE
+#define ACE_LACKS_RLIMIT
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SBRK
+#define ACE_LACKS_SEEKDIR
+#define ACE_LACKS_SEMBUF_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_SI_ADDR
+#define ACE_LACKS_SOCKETPAIR
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_TELLDIR
+#define ACE_LACKS_TEMPNAM
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_TRUNCATE
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_USECONDS_T
+#define ACE_LACKS_UMASK
+#define ACE_LACKS_STRPTIME
+#define ACE_PAGE_SIZE 4096
+#define ACE_THR_PRI_FIFO_DEF 101
+#define ACE_THR_PRI_OTHER_DEF ACE_THR_PRI_FIFO_DEF
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+#if !defined (ACE_VXWORKS_SPARE)
+# define ACE_VXWORKS_SPARE spare4
+#endif /* ! ACE_VXWORKS_SPARE */
+#define ACE_HAS_GETIFADDRS
+
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_SETSID
+#define ACE_LACKS_SETUID
+#define ACE_LACKS_SETEUID
+#define ACE_LACKS_GETEUID
+#define ACE_LACKS_GETUID
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_GETEGID
+#define ACE_LACKS_GETGID
+#define ACE_LACKS_SETGID
+
+#define ACE_LACKS_SYS_UIO_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_PWD_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_TERMIOS_H
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_FCNTL
+
+// Some string things
+#define ACE_LACKS_STRCASECMP
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSDUP
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+
+#define ACE_HAS_CHARPTR_SOCKOPT
+#define ACE_LACKS_SYMLINKS
+
+#if defined __RTP__
+ // We are building for RTP mode
+ #if !defined (ACE_AS_STATIC_LIBS)
+ # define ACE_HAS_SVR4_DYNAMIC_LINKING
+ #endif
+ #define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+ #define ACE_LACKS_REGEX_H
+ #define ACE_LACKS_PUTENV
+ #define ACE_HAS_SETENV
+ #define ACE_HAS_3_PARAM_WCSTOK
+ #define ACE_HAS_WCHAR
+ #define ACE_HAS_VFWPRINTF
+ #define ACE_SIZEOF_WCHAR 2
+#else
+ // We are building for kernel mode
+ #define ACE_LACKS_INTPTR_T
+ #define ACE_LACKS_SUSECONDS_T
+ #define ACE_LACKS_INTTYPES_H
+ #define ACE_LACKS_STDINT_H
+ #define ACE_LACKS_UNAME
+ #define ACE_LACKS_UTSNAME_T
+ #define ACE_LACKS_RAND_REENTRANT_FUNCTIONS
+ #define ACE_LACKS_DLFCN_H
+ #define ACE_LACKS_WAIT
+ #define ACE_LACKS_WAITPID
+ #define ACE_LACKS_SYS_TIME_H
+ #define ACE_LACKS_SYS_SELECT_H
+ #define ACE_LACKS_STRINGS_H
+ #define ACE_MKDIR_LACKS_MODE
+ #define ACE_HAS_SIZET_PTR_ASCTIME_R_AND_CTIME_R
+ #define ACE_LACKS_SEARCH_H
+ #define ACE_LACKS_SYSCONF
+ #define ACE_LACKS_GETPID
+ #define ACE_LACKS_GETPPID
+ #define ACE_LACKS_WCHAR_H
+ #define ACE_LACKS_WCTYPE_H
+ #define ACE_LACKS_WCSCAT
+ #define ACE_LACKS_WCSCHR
+ #define ACE_LACKS_WCSCMP
+ #define ACE_LACKS_WCSCPY
+ #define ACE_LACKS_WCSCSPN
+ #define ACE_LACKS_WCSLEN
+ #define ACE_LACKS_WCSNCAT
+ #define ACE_LACKS_WCSNCMP
+ #define ACE_LACKS_WCSNCPY
+ #define ACE_LACKS_WCSPBRK
+ #define ACE_LACKS_WCSRCHR
+ #define ACE_LACKS_WCSSPN
+ #define ACE_LACKS_WCSSTR
+ #define ACE_LACKS_WCSTOK
+ #define ACE_LACKS_TOWLOWER
+ #define ACE_LACKS_TOWUPPER
+ #define ACE_LACKS_WCSTOD
+ #define ACE_LACKS_WCSTOL
+ #define ACE_LACKS_WCSTOUL
+ #define ACE_LACKS_FGETWC
+ #define ACE_LACKS_FGETWS
+ #define ACE_LACKS_FPUTWS
+ #if !defined (ACE_MAIN)
+ # define ACE_MAIN ace_main
+ #endif /* ! ACE_MAIN */
+#endif
+
+// It is possible to enable pthread support with VxWorks, when the user decides
+// to use this, we need some more defines
+#if defined ACE_HAS_PTHREADS
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+# define ACE_HAS_POSIX_SEM
+# define ACE_LACKS_MUTEXATTR_PSHARED
+# define ACE_LACKS_CONDATTR_PSHARED
+// Include this file, the sys/stat.h file shipped with VxWorks has old types
+// and without this include we get a lot of compile errors. A TSR has been filed
+// so that hopefully in the future we can zap this include
+#include "types/vxTypesOld.h"
+#else
+# define ACE_LACKS_PTHREAD_H
+# define ACE_HAS_VXTHREADS
+# if !defined __RTP__
+// Only when building for kernel mode we can use TSS emulation, in rtp mode
+// we can't use the WIND_TCB struct anymore
+# define ACE_HAS_TSS_EMULATION
+# endif
+// VxWorks has no recursive mutexes. This was set in the past but it doesn't
+// work with the pthread support, so only set it for the time being when pthread
+// is disabled
+# define ACE_HAS_RECURSIVE_MUTEXES
+# define ACE_LACKS_COND_T
+# define ACE_HAS_MUTEX_TIMEOUTS
+#endif
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+// Needed include to get all VxWorks CPU types
+#include "types/vxCpu.h"
+#if (CPU == PENTIUM || CPU == PENTIUM2 || CPU == PENTIUM3 || CPU == PENTIUM4)
+// If running an Intel Pentium the
+// ACE_OS::gethrtime () can use the RDTSC instruction.
+# define ACE_HAS_PENTIUM
+#endif
+
+// VxWorks defines the CPU define MAP, undef it to prevent problems with
+// application code
+#if defined (MAP)
+#undef MAP
+#endif /* MAP */
+
+#if !defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
+# define ACE_NEEDS_HUGE_THREAD_STACKSIZE 65536
+#endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
+
+#if !defined (ACE_NTRACE)
+# define ACE_NTRACE 1
+#endif /* ACE_NTRACE */
+
+// By default, don't include RCS Id strings in object code.
+#if !defined (ACE_USE_RCSID)
+#define ACE_USE_RCSID 0
+#endif /* !ACE_USE_RCSID */
+
+#if defined (ACE_HAS_IP_MULTICAST)
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_HAS_IP_MULTICAST */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_VXWORKS_6_2_H */
diff --git a/ACE/ace/config-vxworks6.3.h b/ACE/ace/config-vxworks6.3.h
new file mode 100644
index 00000000000..b855b301793
--- /dev/null
+++ b/ACE/ace/config-vxworks6.3.h
@@ -0,0 +1,322 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for VxWorks
+// 6.3 platforms using one of these compilers:
+// 1) The GNU g++ compiler that is shipped with VxWorks 6.3
+
+#ifndef ACE_CONFIG_VXWORKS_6_3_H
+#define ACE_CONFIG_VXWORKS_6_3_H
+#include /**/ "ace/pre.h"
+
+#if ! defined (VXWORKS)
+# define VXWORKS
+#endif /* ! VXWORKS */
+
+#if ! defined (ACE_VXWORKS)
+# define ACE_VXWORKS 0x630
+#endif /* ! ACE_VXWORKS */
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// Compiler-specific configuration.
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+
+# define ACE_LACKS_IOSTREAM_FX
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
+ // GNU 3.3+ toolchain supports long long types but fails to define this so STL
+ // skips some definitions
+# if !defined (_GLIBCPP_USE_LONG_LONG)
+# define _GLIBCPP_USE_LONG_LONG
+# endif
+# endif /* (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) */
+
+# if defined (__RTP__) && !defined (_HAS_C9X)
+// Workaround for the fact that under RTP the log2 method can't be used
+// without this define set, see TSR560446
+# define _C99
+# endif
+
+#elif defined (__DCC__)
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_TEMPLATES_REQUIRE_SOURCE
+#else /* ! __GNUG__ && ! ghs && !__DCC__ */
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler on VxWorks
+# endif /* __cplusplus */
+#endif /* ! __GNUG__ && ! ghs */
+
+#if !defined __RTP__
+# if defined (TOOL) && (TOOL == gnu)
+# if defined (CPU) && (CPU == PPC85XX || CPU == PPC604 || CPU == PPC603)
+// These PPC's do lack log2 in kernel mode
+# define ACE_LACKS_LOG2
+# endif
+# endif
+#endif
+
+// OS-specific configuration
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_NONCONST_GETBY
+#define ACE_HAS_NONCONST_SWAB
+#define ACE_LACKS_UNIX_SYSLOG
+#define ACE_DEFAULT_MAX_SOCKET_BUFSIZ 32768
+#define ACE_DEFAULT_THREAD_KEYS 16
+#define ACE_HAS_BROKEN_ACCEPT_ADDR
+#define ACE_HAS_NONCONST_SENDMSG
+#define ACE_HAS_NONCONST_WRITEV
+#define ACE_HAS_CHARPTR_DL
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_DIRENT
+#define ACE_HAS_DLL 0
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_MSG
+#define ACE_HAS_NONCONST_READV
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_HAS_SIGACTION_CONSTP2
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+#define ACE_HAS_STRERROR
+#define ACE_HAS_THREADS
+#define ACE_HAS_SYSCTL
+#define ACE_LACKS_ALPHASORT
+#define ACE_LACKS_EXEC
+#define ACE_LACKS_FILELOCKS
+#define ACE_LACKS_FORK
+#define ACE_LACKS_GETHOSTENT
+#define ACE_LACKS_GETSERVBYNAME
+#define ACE_LACKS_GETPROTOBYNAME
+#define ACE_LACKS_GETPROTOBYNUMBER
+#define ACE_LACKS_GETIPNODEBYADDR
+#define ACE_LACKS_GETIPNODEBYNAME_IPV6
+#define ACE_LACKS_LSTAT
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MALLOC_H
+#define ACE_LACKS_MEMORY_H
+#define ACE_LACKS_MKFIFO
+#define ACE_LACKS_MKTEMP
+#define ACE_LACKS_MKSTEMP
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_SYS_PARAM_H
+#define ACE_LACKS_PWD_FUNCTIONS
+#define ACE_LACKS_READDIR_R
+#define ACE_LACKS_READLINK
+#define ACE_LACKS_REALPATH
+#define ACE_LACKS_PIPE
+#define ACE_LACKS_RLIMIT
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SBRK
+#define ACE_LACKS_SEEKDIR
+#define ACE_LACKS_SEMBUF_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_SI_ADDR
+#define ACE_LACKS_SOCKETPAIR
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_TELLDIR
+#define ACE_LACKS_TEMPNAM
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_TRUNCATE
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_USECONDS_T
+#define ACE_LACKS_UMASK
+#define ACE_LACKS_STRPTIME
+#define ACE_PAGE_SIZE 4096
+#define ACE_THR_PRI_FIFO_DEF 101
+#define ACE_THR_PRI_OTHER_DEF ACE_THR_PRI_FIFO_DEF
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+#define ACE_HAS_GETIFADDRS
+
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_SETSID
+#define ACE_LACKS_SETUID
+#define ACE_LACKS_SETEUID
+#define ACE_LACKS_GETEUID
+#define ACE_LACKS_GETUID
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_GETEGID
+#define ACE_LACKS_GETGID
+#define ACE_LACKS_SETGID
+
+#define ACE_LACKS_SYS_UIO_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_PWD_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_TERMIOS_H
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_FCNTL
+
+// Some string things
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSDUP
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+
+#define ACE_HAS_CHARPTR_SOCKOPT
+#define ACE_LACKS_SYMLINKS
+
+#if defined __RTP__
+ // We are building for RTP mode
+ #if !defined (ACE_AS_STATIC_LIBS)
+ # define ACE_HAS_SVR4_DYNAMIC_LINKING
+ #endif
+ #define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+ #define ACE_LACKS_REGEX_H
+ #define ACE_LACKS_PUTENV
+ #define ACE_HAS_SETENV
+ #define ACE_HAS_3_PARAM_WCSTOK
+ #define ACE_HAS_WCHAR
+ #define ACE_HAS_VFWPRINTF
+ #define ACE_SIZEOF_WCHAR 2
+ #define ACE_HAS_SHM_OPEN
+ #if defined (ACE_AS_STATIC_LIBS)
+ # define ACE_HAS_AIO_CALLS
+ #endif
+ #define ACE_LACKS_STRCASECMP
+ // VxWorks seems to either not define this or define as zero up till now
+ #if !defined (IOV_MAX) || (IOV_MAX == 0)
+ #define ACE_IOV_MAX 16
+ #endif
+#else
+ // We are building for kernel mode
+ #define ACE_LACKS_SUSECONDS_T
+ #define ACE_LACKS_INTPTR_T
+ #define ACE_LACKS_INTTYPES_H
+ #define ACE_LACKS_STDINT_H
+ #define ACE_LACKS_UNAME
+ #define ACE_LACKS_UTSNAME_T
+ #define ACE_LACKS_RAND_REENTRANT_FUNCTIONS
+ #define ACE_LACKS_DLFCN_H
+ #define ACE_LACKS_WAIT
+ #define ACE_LACKS_WAITPID
+ #define ACE_LACKS_SYS_TIME_H
+ #define ACE_LACKS_SYS_SELECT_H
+ #define ACE_MKDIR_LACKS_MODE
+ #define ACE_HAS_SIZET_PTR_ASCTIME_R_AND_CTIME_R
+ #define ACE_LACKS_SEARCH_H
+ #define ACE_LACKS_SYSCONF
+ #define ACE_LACKS_GETPID
+ #define ACE_LACKS_GETPPID
+ #define ACE_LACKS_WCHAR_H
+ #define ACE_LACKS_WCTYPE_H
+ #define ACE_LACKS_WCSCAT
+ #define ACE_LACKS_WCSCHR
+ #define ACE_LACKS_WCSCMP
+ #define ACE_LACKS_WCSCPY
+ #define ACE_LACKS_WCSCSPN
+ #define ACE_LACKS_WCSLEN
+ #define ACE_LACKS_WCSNCAT
+ #define ACE_LACKS_WCSNCMP
+ #define ACE_LACKS_WCSNCPY
+ #define ACE_LACKS_WCSPBRK
+ #define ACE_LACKS_WCSRCHR
+ #define ACE_LACKS_WCSSPN
+ #define ACE_LACKS_WCSSTR
+ #define ACE_LACKS_WCSTOK
+ #define ACE_LACKS_TOWLOWER
+ #define ACE_LACKS_TOWUPPER
+ #define ACE_LACKS_WCSTOD
+ #define ACE_LACKS_WCSTOL
+ #define ACE_LACKS_WCSTOUL
+ #define ACE_LACKS_FGETWC
+ #define ACE_LACKS_FGETWS
+ #define ACE_LACKS_FPUTWS
+ #define ACE_HAS_IOCTL_INT_3_PARAM
+ #define ACE_LACKS_MMAP
+ #define ACE_LACKS_MSYNC
+ #define ACE_LACKS_MPROTECT
+ #if !defined (ACE_MAIN)
+ # define ACE_MAIN ace_main
+ #endif /* ! ACE_MAIN */
+#endif
+
+// It is possible to enable pthread support with VxWorks, when the user decides
+// to use this, we need some more defines
+#if defined ACE_HAS_PTHREADS
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+# define ACE_HAS_POSIX_SEM
+# define ACE_LACKS_MUTEXATTR_PSHARED
+# define ACE_LACKS_CONDATTR_PSHARED
+// Include this file, the sys/stat.h file shipped with VxWorks has old types
+// and without this include we get a lot of compile errors. A TSR has been filed
+// so that hopefully in the future we can zap this include
+#include "types/vxTypesOld.h"
+#else
+# define ACE_LACKS_PTHREAD_H
+# define ACE_HAS_VXTHREADS
+# if !defined __RTP__
+// Only when building for kernel mode we can use TSS emulation, in rtp mode
+// we can't use the WIND_TCB struct anymore
+# define ACE_HAS_TSS_EMULATION
+# if !defined (ACE_VXWORKS_SPARE)
+# define ACE_VXWORKS_SPARE spare4
+# endif /* ! ACE_VXWORKS_SPARE */
+# endif
+// VxWorks has no recursive mutexes. This was set in the past but it doesn't
+// work with the pthread support, so only set it for the time being when pthread
+// is disabled
+# define ACE_HAS_RECURSIVE_MUTEXES
+# define ACE_LACKS_COND_T
+# define ACE_HAS_MUTEX_TIMEOUTS
+#endif
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+// Needed include to get all VxWorks CPU types
+#include "types/vxCpu.h"
+#if defined (CPU) && (CPU == PENTIUM || CPU == PENTIUM2 || CPU == PENTIUM3 || CPU == PENTIUM4)
+ // If running an Intel Pentium the
+ // ACE_OS::gethrtime () can use the RDTSC instruction.
+ # define ACE_HAS_PENTIUM
+#endif
+
+// VxWorks defines the CPU define MAP, undef it to prevent problems with
+// application code
+#if defined (MAP)
+#undef MAP
+#endif /* MAP */
+
+#if !defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
+# define ACE_NEEDS_HUGE_THREAD_STACKSIZE 65536
+#endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
+
+#if !defined (ACE_NTRACE)
+# define ACE_NTRACE 1
+#endif /* ACE_NTRACE */
+
+// By default, don't include RCS Id strings in object code.
+#if !defined (ACE_USE_RCSID)
+#define ACE_USE_RCSID 0
+#endif /* !ACE_USE_RCSID */
+
+#if defined (ACE_HAS_IP_MULTICAST)
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_HAS_IP_MULTICAST */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_VXWORKS_6_3_H */
+
diff --git a/ACE/ace/config-vxworks6.4.h b/ACE/ace/config-vxworks6.4.h
new file mode 100644
index 00000000000..37b13ef7dd1
--- /dev/null
+++ b/ACE/ace/config-vxworks6.4.h
@@ -0,0 +1,345 @@
+//* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for VxWorks
+// 6.4 platforms using one of these compilers:
+// 1) The GNU g++ compiler that is shipped with VxWorks 6.4
+// 2) The Diab compiler that is shipped with VxWorks 6.4
+
+#ifndef ACE_CONFIG_VXWORKS_6_4_H
+#define ACE_CONFIG_VXWORKS_6_4_H
+#include /**/ "ace/pre.h"
+
+#if ! defined (VXWORKS)
+# define VXWORKS
+#endif /* ! VXWORKS */
+
+#if ! defined (ACE_VXWORKS)
+# define ACE_VXWORKS 0x640
+#endif /* ! ACE_VXWORKS */
+
+#if !defined (__RTP__)
+ // Fix for wrong typedef of time_t in kernel mode
+ #ifndef _TIME_T
+ #define _TIME_T
+ typedef long time_t;
+ #endif
+#endif
+
+#if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__
+#endif /* ! __ACE_INLINE__ */
+
+// Compiler-specific configuration.
+#if defined (__GNUG__)
+# include "ace/config-g++-common.h"
+
+# define ACE_LACKS_IOSTREAM_FX
+# define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
+ // GNU 3.3+ toolchain supports long long types but fails to define this so STL
+ // skips some definitions
+# if !defined (_GLIBCPP_USE_LONG_LONG)
+# define _GLIBCPP_USE_LONG_LONG
+# endif
+# endif /* (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) */
+
+# if defined (__RTP__) && !defined (_HAS_C9X)
+// Workaround for the fact that under RTP the log2 method can't be used
+// without this define set, see TSR560446
+# define _C99
+# endif
+
+#elif defined (__DCC__)
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_TEMPLATES_REQUIRE_SOURCE
+#else /* ! __GNUG__ && ! ghs && !__DCC__ */
+# ifdef __cplusplus /* Let it slide for C compilers. */
+# error unsupported compiler on VxWorks
+# endif /* __cplusplus */
+#endif /* ! __GNUG__ && ! ghs */
+
+// Needed include to get all VxWorks CPU types
+#include "types/vxCpu.h"
+#if defined __RTP__
+ #if defined (_VX_CPU) && (_VX_CPU == _VX_PENTIUM || _VX_CPU == _VX_PENTIUM2 || _VX_CPU == _VX_PENTIUM3 || _VX_CPU == _VX_PENTIUM4)
+ // If running an Intel Pentium the
+ // ACE_OS::gethrtime () can use the RDTSC instruction.
+ # define ACE_HAS_PENTIUM
+ #endif
+#else
+ #if defined (CPU) && (CPU == PENTIUM || CPU == PENTIUM2 || CPU == PENTIUM3 || CPU == PENTIUM4)
+ // If running an Intel Pentium the
+ // ACE_OS::gethrtime () can use the RDTSC instruction.
+ # define ACE_HAS_PENTIUM
+ #endif
+#endif
+
+#if !defined __RTP__
+# if defined (TOOL) && (TOOL == gnu)
+# if defined (CPU) && (CPU == PPC85XX || CPU == PPC604 || CPU == PPC603)
+// These PPC's do lack log2 in kernel mode
+# define ACE_LACKS_LOG2
+# endif
+# endif
+#endif
+
+// OS-specific configuration
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+#define ACE_HAS_3_PARAM_READDIR_R
+#define ACE_HAS_NONCONST_GETBY
+#define ACE_HAS_NONCONST_SWAB
+#define ACE_LACKS_UNIX_SYSLOG
+#define ACE_DEFAULT_MAX_SOCKET_BUFSIZ 32768
+#define ACE_DEFAULT_THREAD_KEYS 16
+#define ACE_HAS_BROKEN_ACCEPT_ADDR
+#define ACE_HAS_NONCONST_SENDMSG
+#define ACE_HAS_NONCONST_WRITEV
+#define ACE_HAS_CHARPTR_DL
+#define ACE_HAS_CLOCK_GETTIME
+#define ACE_HAS_CLOCK_SETTIME
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_CPLUSPLUS_HEADERS
+#define ACE_HAS_DIRENT
+#define ACE_HAS_DLL 0
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+#define ACE_HAS_MSG
+#define ACE_HAS_NONCONST_READV
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_POSIX_TIME
+#define ACE_HAS_REENTRANT_FUNCTIONS
+#define ACE_HAS_SIGACTION_CONSTP2
+#define ACE_HAS_SIGINFO_T
+#define ACE_HAS_SIGWAIT
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_SOCKADDR_IN6_SIN6_LEN
+#define ACE_HAS_STRERROR
+#define ACE_HAS_THREADS
+#define ACE_HAS_SYSCTL
+#define ACE_LACKS_ALPHASORT
+#define ACE_LACKS_EXEC
+#define ACE_LACKS_RLIMIT
+#define ACE_LACKS_FILELOCKS
+#define ACE_LACKS_FORK
+#define ACE_LACKS_GETHOSTENT
+#define ACE_LACKS_GETSERVBYNAME
+#define ACE_LACKS_GETPROTOBYNAME
+#define ACE_LACKS_GETPROTOBYNUMBER
+#define ACE_LACKS_GETIPNODEBYADDR
+#define ACE_LACKS_GETIPNODEBYNAME_IPV6
+#define ACE_LACKS_LSTAT
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MALLOC_H
+#define ACE_LACKS_MEMORY_H
+#define ACE_LACKS_MKFIFO
+#define ACE_LACKS_MKSTEMP
+#define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS
+#define ACE_LACKS_SYS_PARAM_H
+#define ACE_LACKS_PWD_FUNCTIONS
+#define ACE_LACKS_READLINK
+#define ACE_LACKS_REALPATH
+#define ACE_LACKS_PIPE
+#define ACE_LACKS_RWLOCK_T
+#define ACE_LACKS_SBRK
+#define ACE_LACKS_SEEKDIR
+#define ACE_LACKS_SEMBUF_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_LACKS_SI_ADDR
+#define ACE_LACKS_SOCKETPAIR
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_TELLDIR
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_LACKS_TRUNCATE
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_USECONDS_T
+#define ACE_LACKS_UMASK
+#define ACE_LACKS_STRPTIME
+#define ACE_LACKS_MKTEMP
+#define ACE_LACKS_TEMPNAM
+#define ACE_PAGE_SIZE 4096
+#define ACE_THR_PRI_FIFO_DEF 101
+#define ACE_THR_PRI_OTHER_DEF ACE_THR_PRI_FIFO_DEF
+#define ACE_HAS_SIGTIMEDWAIT
+#define ACE_HAS_SIGSUSPEND
+#define ACE_HAS_GETIFADDRS
+
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_SETSID
+#define ACE_LACKS_SETUID
+#define ACE_LACKS_SETEUID
+#define ACE_LACKS_GETEUID
+#define ACE_LACKS_GETUID
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_GETEGID
+#define ACE_LACKS_GETGID
+#define ACE_LACKS_SETGID
+
+#define ACE_LACKS_SYS_UIO_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_PWD_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_TERMIOS_H
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_FCNTL
+
+// Some string things
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSDUP
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+
+#define ACE_HAS_CHARPTR_SOCKOPT
+#define ACE_LACKS_SYMLINKS
+
+#if defined __RTP__
+ // We are building for RTP mode
+ #if !defined (ACE_AS_STATIC_LIBS)
+ # define ACE_HAS_SVR4_DYNAMIC_LINKING
+ #endif
+ #define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+ #define ACE_LACKS_REGEX_H
+ #if defined ACE_HAS_PENTIUM
+ // Bug to workaround VxWorks 6.4 x86
+ # define ACE_LACKS_PUTENV
+ #endif
+ #define ACE_HAS_SETENV
+ #define ACE_LACKS_STRCASECMP
+ #define ACE_HAS_3_PARAM_WCSTOK
+ #define ACE_HAS_WCHAR
+ #define ACE_HAS_VFWPRINTF
+ #define ACE_SIZEOF_WCHAR 2
+ #define ACE_HAS_SHM_OPEN
+ #if defined (ACE_AS_STATIC_LIBS)
+ # define ACE_HAS_AIO_CALLS
+ #endif
+ // VxWorks seems to either not define this or define as zero up till now
+ #if !defined (IOV_MAX) || (IOV_MAX == 0)
+ #define ACE_IOV_MAX 16
+ #endif
+#else
+ // We are building for kernel mode
+ #define ACE_LACKS_SUSECONDS_T
+ #define ACE_LACKS_INTPTR_T
+ #define ACE_LACKS_INTTYPES_H
+ #define ACE_LACKS_STDINT_H
+ #define ACE_LACKS_UNAME
+ #define ACE_LACKS_UTSNAME_T
+ #define ACE_LACKS_RAND_REENTRANT_FUNCTIONS
+ #define ACE_LACKS_DLFCN_H
+ #define ACE_LACKS_WAIT
+ #define ACE_LACKS_WAITPID
+ #define ACE_LACKS_SYS_TIME_H
+ #define ACE_LACKS_SYS_SELECT_H
+ #define ACE_MKDIR_LACKS_MODE
+ #define ACE_HAS_SIZET_PTR_ASCTIME_R_AND_CTIME_R
+ #define ACE_LACKS_SEARCH_H
+ #define ACE_LACKS_SYSCONF
+ #define ACE_LACKS_GETPPID
+ #define ACE_LACKS_WCHAR_H
+ #define ACE_LACKS_WCTYPE_H
+ #define ACE_LACKS_WCSCAT
+ #define ACE_LACKS_WCSCHR
+ #define ACE_LACKS_WCSCMP
+ #define ACE_LACKS_WCSCPY
+ #define ACE_LACKS_WCSCSPN
+ #define ACE_LACKS_WCSLEN
+ #define ACE_LACKS_WCSNCAT
+ #define ACE_LACKS_WCSNCMP
+ #define ACE_LACKS_WCSNCPY
+ #define ACE_LACKS_WCSPBRK
+ #define ACE_LACKS_WCSRCHR
+ #define ACE_LACKS_WCSSPN
+ #define ACE_LACKS_WCSSTR
+ #define ACE_LACKS_WCSTOK
+ #define ACE_LACKS_TOWLOWER
+ #define ACE_LACKS_TOWUPPER
+ #define ACE_LACKS_WCSTOD
+ #define ACE_LACKS_WCSTOL
+ #define ACE_LACKS_WCSTOUL
+ #define ACE_LACKS_FGETWC
+ #define ACE_LACKS_FGETWS
+ #define ACE_LACKS_FPUTWS
+ #define ACE_HAS_IOCTL_INT_3_PARAM
+ #define ACE_LACKS_MMAP
+ #define ACE_LACKS_MSYNC
+ #define ACE_LACKS_MPROTECT
+ #if !defined (ACE_MAIN)
+ # define ACE_MAIN ace_main
+ #endif /* ! ACE_MAIN */
+#endif
+
+// It is possible to enable pthread support with VxWorks, when the user decides
+// to use this, we need some more defines
+#if defined ACE_HAS_PTHREADS
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+# if !defined __RTP__
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACK
+# endif
+# define ACE_HAS_PTHREAD_ATTR_SETNAME
+# define ACE_HAS_POSIX_SEM
+# define ACE_LACKS_MUTEXATTR_PSHARED
+# define ACE_LACKS_CONDATTR_PSHARED
+// Include this file, the sys/stat.h file shipped with VxWorks has old types
+// and without this include we get a lot of compile errors. A TSR has been filed
+// so that hopefully in the future we can zap this include
+#include "types/vxTypesOld.h"
+#else
+# define ACE_LACKS_PTHREAD_H
+# define ACE_HAS_VXTHREADS
+# if !defined __RTP__
+// Only when building for kernel mode we can use TSS emulation, in rtp mode
+// we can't use the WIND_TCB struct anymore
+# define ACE_HAS_TSS_EMULATION
+# if !defined (ACE_VXWORKS_SPARE)
+# define ACE_VXWORKS_SPARE spare4
+# endif /* ! ACE_VXWORKS_SPARE */
+# endif
+// VxWorks has no recursive mutexes. This was set in the past but it doesn't
+// work with the pthread support, so only set it for the time being when pthread
+// is disabled
+# define ACE_HAS_RECURSIVE_MUTEXES
+# define ACE_LACKS_COND_T
+# define ACE_HAS_MUTEX_TIMEOUTS
+#endif
+
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+// VxWorks defines the CPU define MAP, undef it to prevent problems with
+// application code
+#if defined (MAP)
+#undef MAP
+#endif /* MAP */
+
+#if !defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
+# define ACE_NEEDS_HUGE_THREAD_STACKSIZE 65536
+#endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
+
+#if !defined (ACE_NTRACE)
+# define ACE_NTRACE 1
+#endif /* ACE_NTRACE */
+
+// By default, don't include RCS Id strings in object code.
+#if !defined (ACE_USE_RCSID)
+#define ACE_USE_RCSID 0
+#endif /* !ACE_USE_RCSID */
+
+#if defined (ACE_HAS_IP_MULTICAST)
+# define ACE_LACKS_PERFECT_MULTICAST_FILTERING 1
+#endif /* ACE_HAS_IP_MULTICAST */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_VXWORKS_6_4_H */
+
diff --git a/ACE/ace/config-vxworks6.5.h b/ACE/ace/config-vxworks6.5.h
new file mode 100644
index 00000000000..1af14a9d13c
--- /dev/null
+++ b/ACE/ace/config-vxworks6.5.h
@@ -0,0 +1,25 @@
+//* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for VxWorks
+// 6.5 platforms using one of these compilers:
+// 1) The GNU g++ compiler that is shipped with VxWorks 6.5
+// 2) The Diab compiler that is shipped with VxWorks 6.5
+
+#ifndef ACE_CONFIG_VXWORKS_6_5_H
+#define ACE_CONFIG_VXWORKS_6_5_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_VXWORKS)
+# define ACE_VXWORKS 0x650
+#endif /* ! ACE_VXWORKS */
+
+#include "ace/config-vxworks6.4.h"
+
+#if defined (__RTP__)
+# undef ACE_HAS_GETIFADDRS
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_VXWORKS_6_5_H */
+
diff --git a/ACE/ace/config-vxworks6.6.h b/ACE/ace/config-vxworks6.6.h
new file mode 100644
index 00000000000..04da8aa983e
--- /dev/null
+++ b/ACE/ace/config-vxworks6.6.h
@@ -0,0 +1,29 @@
+//* -*- C++ -*- */
+// $Id$
+
+// The following configuration file is designed to work for VxWorks
+// 6.6 platforms using one of these compilers:
+// 1) The GNU g++ compiler that is shipped with VxWorks 6.6
+// 2) The Diab compiler that is shipped with VxWorks 6.6
+
+#ifndef ACE_CONFIG_VXWORKS_6_6_H
+#define ACE_CONFIG_VXWORKS_6_6_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_VXWORKS)
+# define ACE_VXWORKS 0x660
+#endif /* ! ACE_VXWORKS */
+
+#include "ace/config-vxworks6.5.h"
+
+#if defined (ACE_HAS_PENTIUM)
+# define ACE_LACKS_LOG2
+#endif
+
+#if !defined (__RTP__)
+# undef ACE_HAS_IOCTL_INT_3_PARAM
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_VXWORKS_6_6_H */
+
diff --git a/ACE/ace/config-win32-borland.h b/ACE/ace/config-win32-borland.h
new file mode 100644
index 00000000000..37a958327ac
--- /dev/null
+++ b/ACE/ace/config-win32-borland.h
@@ -0,0 +1,121 @@
+// -*- C++ -*-
+//$Id$
+
+// The following configuration file contains defines for Borland compilers.
+
+#ifndef ACE_CONFIG_WIN32_BORLAND_H
+#define ACE_CONFIG_WIN32_BORLAND_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+#error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+#include "config-borland-common.h"
+
+// Automatically define WIN32 macro if the compiler tells us it is our
+// target platform.
+# if defined (__WIN32__) && !defined (WIN32)
+# define WIN32 1
+# endif
+
+// When building a VCL application, the main VCL header file should be
+// included before anything else. You can define ACE_HAS_VCL=1 in your
+// project settings to have this file included for you automatically.
+# if defined (ACE_HAS_VCL) && (ACE_HAS_VCL != 0)
+# include /**/ <vcl.h>
+# endif
+
+# define ACE_CC_PREPROCESSOR "CPP32.EXE"
+
+# include "ace/config-win32-common.h"
+
+// Borland on win32 has swab
+# undef ACE_LACKS_SWAB
+
+# define ACE_WSTRING_HAS_USHORT_SUPPORT 1
+# define ACE_HAS_DIRENT
+
+#ifdef ACE_USES_STD_NAMESPACE_FOR_STDC_LIB
+#undef ACE_USES_STD_NAMESPACE_FOR_STDC_LIB
+#define ACE_USES_STD_NAMESPACE_FOR_STDC_LIB 1
+#endif
+
+#define ACE_NEEDS_DL_UNDERSCORE
+
+#define ACE_LACKS_TERMIOS_H
+#define ACE_LACKS_NETINET_TCP_H
+#define ACE_LACKS_REGEX_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_PWD_H
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_STRINGS_H
+#define ACE_LACKS_SEMAPHORE_H
+#define ACE_LACKS_INTTYPES_H
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_SYS_SELECT_H
+#define ACE_LACKS_SYS_TIME_H
+#define ACE_LACKS_SYS_RESOURCE_H
+#define ACE_LACKS_SYS_WAIT_H
+#define ACE_LACKS_DLFCN_H
+#define ACE_LACKS_SYS_MMAN_H
+#define ACE_LACKS_SYS_UIO_H
+#define ACE_LACKS_SYS_SOCKET_H
+#define ACE_LACKS_NETINET_IN_H
+#define ACE_LACKS_NETDB_H
+#define ACE_LACKS_NET_IF_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_SYS_IOCTL_H
+#define ACE_LACKS_STROPTS_H
+
+#undef ACE_LACKS_STRUCT_DIR
+#undef ACE_LACKS_CLOSEDIR
+#undef ACE_LACKS_OPENDIR
+#undef ACE_LACKS_READDIR
+#undef ACE_LACKS_REWINDDIR
+
+#define ACE_HAS_WOPENDIR
+#define ACE_HAS_WCLOSEDIR
+#define ACE_HAS_WREADDIR
+#define ACE_HAS_WREWINDDIR
+
+#define ACE_LACKS_STRRECVFD
+#define ACE_USES_EXPLICIT_STD_NAMESPACE
+
+#if defined(ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+// must have _MT defined to include multithreading
+// features from win32 headers
+# if !defined(__MT__)
+// *** DO NOT *** defeat this error message by defining __MT__ yourself.
+// You must link with the multi threaded libraries. Add -tWM to your
+// compiler options
+# error You must link against multi-threaded libraries when using ACE (check your project settings)
+# endif /* !_MT && !ACE_HAS_WINCE */
+#endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+
+#if (__BORLANDC__ < 0x580)
+# define ACE_LACKS_INTPTR_T
+# define ACE_HAS_NONCONST_SWAB
+# define ACE_HAS_NONCONST_FDOPEN
+#endif
+
+#define ACE_HAS_NONCONST_TEMPNAM
+
+#if (__BORLANDC__ <= 0x593)
+// Older Borland compilers can't handle assembly in inline methods or
+// templates (E2211). When we build for pentium optimized and we are inlining
+// then we disable inline assembly
+# if defined (ACE_HAS_PENTIUM) && defined(__ACE_INLINE__)
+# define ACE_LACKS_INLINE_ASSEMBLY
+# endif
+#endif
+
+#define ACE_WCSDUP_EQUIVALENT ::_wcsdup
+#define ACE_STRCASECMP_EQUIVALENT ::stricmp
+#define ACE_STRNCASECMP_EQUIVALENT ::strnicmp
+#define ACE_HAS_ITOA 1
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_BORLAND_H */
diff --git a/ACE/ace/config-win32-common.h b/ACE/ace/config-win32-common.h
new file mode 100644
index 00000000000..b15856dff36
--- /dev/null
+++ b/ACE/ace/config-win32-common.h
@@ -0,0 +1,660 @@
+/* -*- C++ -*- */
+// $Id$
+
+
+#ifndef ACE_CONFIG_WIN32_COMMON_H
+#define ACE_CONFIG_WIN32_COMMON_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+#error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+
+// Windows Mobile (CE) stuff is primarily further restrictions to what's
+// in the rest of this file. Also, it defined ACE_HAS_WINCE, which is used
+// in this file.
+#if defined (_WIN32_WCE)
+# include "ace/config-WinCE.h"
+#endif /* _WIN32_WCE */
+
+// Complain if WIN32 is not already defined.
+#if !defined (WIN32) && !defined (ACE_HAS_WINCE)
+# error Please define WIN32 in your project settings.
+#endif
+
+#define ACE_WIN32
+#if defined (_WIN64) || defined (WIN64)
+# define ACE_WIN64
+
+// Use 64-bit file offsets by default in the WIN64 case, similar to
+// what 64-bit UNIX systems do.
+//
+// Note that _FILE_OFFSET_BITS is not recognized by Windows. It is,
+// however, recognized by ACE.
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif /* !_FILE_OFFSET_BITS */
+#endif /* _WIN64 || WIN64 */
+
+#if !defined (_WIN32_WINNT)
+# define _WIN32_WINNT 0x0400 // pretend it's at least WinNT 4.0
+#endif
+
+// If the invoking procedure turned off debugging by setting NDEBUG, then
+// also set ACE_NDEBUG, unless the user has already set it.
+#if defined (NDEBUG)
+# if !defined (ACE_NDEBUG)
+# define ACE_NDEBUG
+# endif /* ACE_NDEBUG */
+#endif /* NDEBUG */
+
+// Define ACE_HAS_MFC to 1, if you want ACE to use CWinThread. This should
+// be defined, if your application uses MFC.
+// Setting applies to : building ACE
+// Runtime restrictions: MFC DLLs must be installed
+// Additonal notes : If both ACE_HAS_MFC and ACE_MT_SAFE are
+// defined, the MFC DLL (not the static lib)
+// will be used from ACE.
+#if !defined (ACE_HAS_MFC)
+# define ACE_HAS_MFC 0
+#endif
+
+// ACE_USES_STATIC_MFC always implies ACE_HAS_MFC
+#if defined (ACE_USES_STATIC_MFC)
+# if defined (ACE_HAS_MFC)
+# undef ACE_HAS_MFC
+# endif
+# define ACE_HAS_MFC 1
+#endif /* ACE_USES_STATIC_MFC */
+
+// Define ACE_HAS_STRICT to 1 in your config.h file if you want to use
+// STRICT type checking. It is disabled by default because it will
+// break existing application code. However, if ACE_HAS_MFC is turned on,
+// ACE_HAS_STRICT is required by MFC.
+// Setting applies to : building ACE, linking with ACE
+// Runtime restrictions: -
+#if !defined (ACE_HAS_STRICT)
+# define ACE_HAS_STRICT 0
+#endif
+
+// MFC itself defines STRICT.
+#if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+# undef ACE_HAS_STRICT
+# define ACE_HAS_STRICT 1
+#endif
+
+// Turn off the following define if you want to disable threading.
+// Compile using multi-thread libraries.
+// Setting applies to : building ACE, linking with ACE
+// Runtime restrictions: multithreaded runtime DLL must be installed
+#if !defined (ACE_MT_SAFE)
+# define ACE_MT_SAFE 1
+#endif
+
+// Build ACE services as DLLs. If you write a library and want it to
+// use ACE_Svc_Export, this will cause those macros to build dlls. If
+// you want your ACE service to be a static library, comment out this
+// line. As far as I know, the only reason to have a library be an
+// ACE "service" is to leverage the ACE_Svc_Export macros. It's just
+// as easy to define your own export macros.
+// #if !defined (ACE_SVC_HAS_DLL)
+// # define ACE_SVC_HAS_DLL 1
+// #endif
+
+// Define the special export macros needed to export symbols outside a dll
+#if !defined(__BORLANDC__)
+#define ACE_HAS_CUSTOM_EXPORT_MACROS 1
+#define ACE_Proper_Export_Flag __declspec (dllexport)
+#define ACE_Proper_Import_Flag __declspec (dllimport)
+#define ACE_EXPORT_SINGLETON_DECLARATION(T) template class __declspec (dllexport) T
+#define ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) template class __declspec (dllexport) SINGLETON_TYPE<CLASS, LOCK>;
+#define ACE_IMPORT_SINGLETON_DECLARATION(T) extern template class T
+#define ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) extern template class SINGLETON_TYPE <CLASS, LOCK>;
+#endif /* !__BORLANDC__ */
+
+// Define ACE_HAS_WINSOCK2 to 0 in your config.h file if you do *not*
+// want to compile with WinSock 2.0.
+// Setting applies to : building ACE
+// Runtime restrictions: winsock2 must be installed.
+// #define ACE_HAS_WINSOCK2 0
+
+// By default, we use non-static object manager on Win32. That is,
+// the object manager is allocated in main's stack memory. If this
+// does not suit your need, i.e., if your programs depend on the use
+// of static object manager, you neet to disable the behavior by adding
+//
+// #undef ACE_HAS_NONSTATIC_OBJECT_MANAGER
+//
+// in the config.h after including config-win32.h
+//
+// MFC users: the main function is defined within a MFC library and
+// therefore, ACE won't be able to meddle with main function and
+// instantiate the non-static object manager for you. To solve the
+// problem, you'll need to instantiate the ACE_Object_Manager by
+// either:
+//
+// 1. Using static object manager (as described above), however, using
+// the non-static object manager is prefered, therefore,
+// 2. Instantiate the non-static object manager yourself by either 1)
+// call ACE::init () at the beginning and ACE::fini () at the end,
+// _or_ 2) instantiate the ACE_Object_Manager in your CWinApp
+// derived class.
+//
+// Optionally, you can #define
+// ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER in your
+// ace/config.h and always take care of the business by yourself.
+// ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER has no effect when
+// using static object managers.
+#if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
+# define ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#elif (ACE_HAS_NONSTATIC_OBJECT_MANAGER == 0)
+# undef ACE_HAS_NONSTATIC_OBJECT_MANAGER
+#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */
+
+#define ACE_HAS_GPERF
+
+// By default, don't include RCS Id strings in object code.
+#if !defined (ACE_USE_RCSID)
+# define ACE_USE_RCSID 0
+#endif /* ! ACE_USE_RCSID */
+
+// ---------------- platform features or lack of them -------------
+
+// By default WIN32 has FD_SETSIZE of 64, which places the limit
+// between 61 and 64 on the number of clients a server using the
+// Select Reactor can support at the same time (i.e., 64 - standard in,
+// out, error). Here we raise the limit to 1024. Adjust the definition
+// below if you need to raise or lower it.
+
+#if !defined (FD_SETSIZE)
+#define FD_SETSIZE 1024
+#endif /* FD_SETSIZE */
+
+
+// Windows doesn't like 65536 ;-) If 65536 is specified, it is
+// silently ignored by the OS, i.e., setsockopt does not fail, and you
+// get stuck with the default size of 8k.
+#define ACE_DEFAULT_MAX_SOCKET_BUFSIZ 65535
+
+// It seems like Win32 does not have a limit on the number of buffers
+// that can be transferred by the scatter/gather type of I/O
+// functions, e.g., WSASend and WSARecv. We are setting this to be 64
+// for now. The typically use case is to create an I/O vector array
+// of size ACE_IOV_MAX on the stack and then filled in. Note that we
+// probably don't want too big a value for ACE_IOV_MAX since it may
+// mostly go to waste or the size of the activation record may become
+// excessively large.
+#if !defined (ACE_IOV_MAX)
+# define ACE_IOV_MAX 64
+#endif /* ACE_IOV_MAX */
+
+#if !defined (ACE_HAS_WINCE)
+// Platform supports pread() and pwrite()
+# define ACE_HAS_P_READ_WRITE
+#endif /* ! ACE_HAS_WINCE */
+
+#if !defined (__MINGW32__)
+# define ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS
+#endif /* __MINGW32__ */
+
+#define ACE_DEFAULT_THREAD_PRIORITY 0
+
+#define ACE_HAS_DIRENT
+#define ACE_HAS_MSG
+#define ACE_HAS_RECURSIVE_MUTEXES
+#define ACE_HAS_SOCKADDR_MSG_NAME
+#define ACE_HAS_THREAD_SAFE_ACCEPT
+
+/* LACKS dir-related facilities */
+#define ACE_LACKS_READDIR_R
+#define ACE_LACKS_REWINDDIR
+#define ACE_LACKS_SEEKDIR
+#define ACE_LACKS_TELLDIR
+
+/* LACKS gid/pid/sid/uid facilities */
+#define ACE_LACKS_GETPGID
+#define ACE_LACKS_GETPPID
+#define ACE_LACKS_SETPGID
+#define ACE_LACKS_SETREGID
+#define ACE_LACKS_SETREUID
+#define ACE_LACKS_SETSID
+#define ACE_LACKS_SETEGID
+#define ACE_LACKS_SETUID
+#define ACE_LACKS_SETEUID
+#define ACE_LACKS_GETGID
+#define ACE_LACKS_GETEGID
+#define ACE_LACKS_GETUID
+#define ACE_LACKS_GETEUID
+#define ACE_LACKS_SETGID
+
+/* LACKS miscellaneous */
+#define ACE_LACKS_ALARM
+#define ACE_LACKS_ARPA_INET_H
+#define ACE_LACKS_DUP2
+#define ACE_LACKS_FORK
+#define ACE_LACKS_GETHOSTENT
+#define ACE_LACKS_GETOPT
+#define ACE_LACKS_GETIPNODEBYNAME_IPV6
+#define ACE_LACKS_KILL
+#define ACE_LACKS_INET_ATON
+#define ACE_LACKS_MADVISE
+#define ACE_LACKS_MKFIFO
+#define ACE_LACKS_MODE_MASKS
+#define ACE_LACKS_PTHREAD_H
+#define ACE_LACKS_PWD_FUNCTIONS
+#define ACE_LACKS_READLINK
+#define ACE_LACKS_RLIMIT
+#define ACE_LACKS_SBRK
+#define ACE_LACKS_SCHED_H
+#define ACE_LACKS_SEMBUF_T
+#define ACE_LACKS_SIGACTION
+#define ACE_LACKS_SIGSET
+#define ACE_LACKS_SOCKETPAIR
+#define ACE_LACKS_SUSECONDS_T
+#define ACE_LACKS_USECONDS_T
+#define ACE_LACKS_SYS_PARAM_H
+#define ACE_LACKS_SYS_SYSCTL_H
+#define ACE_LACKS_SYSCONF
+#define ACE_LACKS_SYSV_SHMEM
+#define ACE_LACKS_UNISTD_H
+#define ACE_LACKS_UNIX_SIGNALS
+#define ACE_LACKS_UNIX_SYSLOG
+#define ACE_LACKS_UTSNAME_T
+#define ACE_LACKS_UNAME
+#define ACE_LACKS_WAIT
+#define ACE_LACKS_IOVEC
+#define ACE_LACKS_LOG2
+
+#define ACE_HAS_VFWPRINTF
+
+#define ACE_MKDIR_LACKS_MODE
+
+#define ACE_SIZEOF_LONG_LONG 8
+// Green Hills Native x86 does not support __int64 keyword
+// Neither does mingw32.
+#if !defined (ACE_LACKS_LONGLONG_T) && !defined (__MINGW32__)
+#define ACE_INT64_TYPE signed __int64
+#define ACE_UINT64_TYPE unsigned __int64
+#endif /* (ghs) */
+
+#if defined (__MINGW32__)
+#define ACE_INT64_TYPE signed long long
+#define ACE_UINT64_TYPE unsigned long long
+#endif
+
+// Optimize ACE_Handle_Set for select().
+#define ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT
+
+// Win32 has wide-char support. Use of the compiler-defined wchar_t type
+// is controlled in compiler configs since it's a compiler switch.
+#define ACE_HAS_WCHAR
+
+// Compiler/platform correctly calls init()/fini() for shared
+// libraries. - applied for DLLs ?
+//define ACE_HAS_AUTOMATIC_INIT_FINI
+
+// Platform supports POSIX O_NONBLOCK semantics.
+//define ACE_HAS_POSIX_NONBLOCK
+
+// Platform contains <poll.h>.
+//define ACE_HAS_POLL
+
+// Platform supports the /proc file system.
+//define ACE_HAS_PROC_FS
+
+// Platform supports the rusage struct.
+#define ACE_HAS_GETRUSAGE
+
+// Compiler/platform supports SVR4 signal typedef.
+//define ACE_HAS_SVR4_SIGNAL_T
+
+// Platform provides <sys/filio.h> header.
+//define ACE_HAS_SYS_FILIO_H
+
+// Compiler/platform supports sys_siglist array.
+//define ACE_HAS_SYS_SIGLIST
+
+// Platform supports ACE_TLI timod STREAMS module.
+//define ACE_HAS_TIMOD_H
+
+// Platform supports ACE_TLI tiuser header.
+//define ACE_HAS_TIUSER_H
+
+// Platform provides ACE_TLI function prototypes.
+// For Win32, this is not really true, but saves a lot of hassle!
+#define ACE_HAS_TLI_PROTOTYPES
+
+// Platform supports ACE_TLI.
+//define ACE_HAS_TLI
+
+// I'm pretty sure NT lacks these
+#define ACE_LACKS_UNIX_DOMAIN_SOCKETS
+
+// Windows NT needs readv() and writev()
+#define ACE_LACKS_WRITEV
+#define ACE_LACKS_READV
+
+#define ACE_LACKS_COND_T
+#define ACE_LACKS_RWLOCK_T
+
+#define ACE_LACKS_KEY_T
+
+// No system support for replacing any previous mappings.
+#define ACE_LACKS_AUTO_MMAP_REPLACEMENT
+
+// ACE_HAS_PENTIUM is used to optimize some CDR operations; it's used for
+// some other time-related things using g++, but not for VC. Current VC
+// compilers set _M_IX86 > 400 by default so if you're not using a Pentium
+// class CPU, set the project code generation options appropriately.
+#if !defined(ACE_HAS_PENTIUM) && (_M_IX86 > 400)
+# define ACE_HAS_PENTIUM
+#endif
+
+#if defined(ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+// Platform supports threads.
+# define ACE_HAS_THREADS
+
+// Platform supports Windows32 threads.
+# define ACE_HAS_WTHREADS
+
+// Compiler/platform has thread-specific storage
+# define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+// Win32 doesn't have fcntl
+#define ACE_LACKS_FCNTL
+
+#endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+
+#if !defined(_DEBUG)
+// If we are making a release, and the user has not specified
+// inline directives, we will default to inline
+# if ! defined (__ACE_INLINE__)
+# define __ACE_INLINE__ 1
+# endif /* __ACE_INLINE__ */
+#endif
+
+// If __ACE_INLINE__ is defined to be 0, we will undefine it
+#if defined (__ACE_INLINE__) && (__ACE_INLINE__ == 0)
+# undef __ACE_INLINE__
+#endif /* __ACE_INLINE__ */
+
+// We are build ACE and want to use MFC (multithreaded)
+#if defined(ACE_HAS_MFC) && (ACE_HAS_MFC != 0) && defined (_MT)
+# if (ACE_HAS_DLL != 0) && defined(ACE_BUILD_DLL) && !defined (_WINDLL)
+// force multithreaded MFC DLL
+# define _WINDLL
+# endif /* _AFXDLL */
+# if !defined (_AFXDLL) && !defined (ACE_USES_STATIC_MFC)
+# define _AFXDLL
+# endif /* _AFXDLL */
+#endif
+
+// <windows.h> and MFC's <afxwin.h> are mutually
+// incompatible. <windows.h> is brain-dead about MFC; it doesn't check
+// to see whether MFC stuff is anticipated or already in progress
+// before doing its thing. ACE needs (practically always) <winsock.h>,
+// and winsock in turn needs support either from windows.h or from
+// afxwin.h. One or the other, not both.
+//
+// The MSVC++ V4.0 environment defines preprocessor macros that
+// indicate the programmer has chosen something from the
+// Build-->Settings-->General-->MFC combo-box. <afxwin.h> defines a
+// macro itself to protect against double inclusion. We'll take
+// advantage of all this to select the proper support for winsock. -
+// trl 26-July-1996
+
+// This is necessary since MFC users apparently can't #include
+// <windows.h> directly.
+#if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
+# include /**/ <afxwin.h> /* He is doing MFC */
+// Windows.h will be included via afxwin.h->afx.h->afx_ver_.h->afxv_w32.h
+// #define _INC_WINDOWS // Prevent winsock.h from including windows.h
+#elif defined (ACE_HAS_WINCE)
+# include /**/ <windows.h>
+#endif
+
+#if !defined (_INC_WINDOWS) /* Already include windows.h ? */
+// Must define strict before including windows.h !
+# if defined (ACE_HAS_STRICT) && (ACE_HAS_STRICT != 0) && !defined (STRICT)
+# define STRICT 1
+# endif /* ACE_HAS_STRICT */
+
+# if !defined (WIN32_LEAN_AND_MEAN) && !defined (ACE_NO_WIN32_LEAN_AND_MEAN)
+# define WIN32_LEAN_AND_MEAN
+# endif /* WIN32_LEAN_AND_MEAN */
+
+#endif /* !defined (_INC_WINDOWS) */
+
+// Always use WS2 when available
+#if !defined(ACE_HAS_WINSOCK2)
+# define ACE_HAS_WINSOCK2 1
+#endif /* !defined(ACE_HAS_WINSOCK2) */
+
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+# if !defined (_WINSOCK2API_)
+// will also include windows.h, if not present
+# include /**/ <winsock2.h>
+// WinCE 4 doesn't define the Exxx values without the WSA prefix, so do that
+// here. This is all lifted from the #if 0'd out part of winsock2.h.
+# if defined (UNDER_CE)
+# define EWOULDBLOCK WSAEWOULDBLOCK
+# define EINPROGRESS WSAEINPROGRESS
+# define EALREADY WSAEALREADY
+# define ENOTSOCK WSAENOTSOCK
+# define EDESTADDRREQ WSAEDESTADDRREQ
+# define EMSGSIZE WSAEMSGSIZE
+# define EPROTOTYPE WSAEPROTOTYPE
+# define ENOPROTOOPT WSAENOPROTOOPT
+# define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+# define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+# define EOPNOTSUPP WSAEOPNOTSUPP
+# define EPFNOSUPPORT WSAEPFNOSUPPORT
+# define EAFNOSUPPORT WSAEAFNOSUPPORT
+# define EADDRINUSE WSAEADDRINUSE
+# define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+# define ENETDOWN WSAENETDOWN
+# define ENETUNREACH WSAENETUNREACH
+# define ENETRESET WSAENETRESET
+# define ECONNABORTED WSAECONNABORTED
+# define ECONNRESET WSAECONNRESET
+# define ENOBUFS WSAENOBUFS
+# define EISCONN WSAEISCONN
+# define ENOTCONN WSAENOTCONN
+# define ESHUTDOWN WSAESHUTDOWN
+# define ETOOMANYREFS WSAETOOMANYREFS
+# define ETIMEDOUT WSAETIMEDOUT
+# define ECONNREFUSED WSAECONNREFUSED
+# define ELOOP WSAELOOP
+# define ENAMETOOLONG WSAENAMETOOLONG
+# define EHOSTDOWN WSAEHOSTDOWN
+# define EHOSTUNREACH WSAEHOSTUNREACH
+# define ENOTEMPTY WSAENOTEMPTY
+# define EPROCLIM WSAEPROCLIM
+# define EUSERS WSAEUSERS
+# define EDQUOT WSAEDQUOT
+# define ESTALE WSAESTALE
+# define EREMOTE WSAEREMOTE
+# endif /* UNDER_CE */
+# endif /* _WINSOCK2API */
+
+# if defined (ACE_HAS_FORE_ATM_WS2)
+# include /**/ <ws2atm.h>
+# endif /*ACE_HAS_FORE_ATM_WS2 */
+
+// CE doesn't have Microsoft Winsock 2 extensions
+# if !defined _MSWSOCK_ && !defined (ACE_HAS_WINCE)
+# include /**/ <mswsock.h>
+# endif /* _MSWSOCK_ */
+
+# if defined (_MSC_VER)
+# if defined (ACE_HAS_WINCE)
+# pragma comment(lib, "ws2.lib")
+# else
+# pragma comment(lib, "ws2_32.lib")
+# pragma comment(lib, "mswsock.lib")
+# endif /* ACE_HAS_WINCE */
+# endif /* _MSC_VER */
+
+# define ACE_WSOCK_VERSION 2, 0
+#else
+# if !defined (_WINSOCKAPI_)
+ // will also include windows.h, if not present
+# include /**/ <winsock.h>
+# endif /* _WINSOCKAPI */
+
+// PharLap ETS has its own winsock lib, so don't grab the one
+// supplied with the OS.
+# if defined (_MSC_VER) && !defined (UNDER_CE) && !defined (ACE_HAS_PHARLAP)
+# pragma comment(lib, "wsock32.lib")
+# endif /* _MSC_VER */
+
+// We can't use recvmsg and sendmsg unless WinSock 2 is available
+# define ACE_LACKS_RECVMSG
+# define ACE_LACKS_SENDMSG
+
+// Version 1.1 of WinSock
+# define ACE_WSOCK_VERSION 1, 1
+#endif /* ACE_HAS_WINSOCK2 */
+
+// Platform supports IP multicast on Winsock 2
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+# define ACE_HAS_IP_MULTICAST
+#endif /* ACE_HAS_WINSOCK2 */
+
+#if !defined (ACE_HAS_WINCE) || defined (PPC) /* CE only on some CPUs */
+# define ACE_HAS_INTERLOCKED_EXCHANGEADD
+#endif
+#define ACE_HAS_WIN32_TRYLOCK
+
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP)
+# define ACE_HAS_SIGNAL_OBJECT_AND_WAIT
+
+// If CancelIO is undefined get the updated sp2-sdk from MS
+# define ACE_HAS_CANCEL_IO
+# define ACE_HAS_WIN32_OVERLAPPED_IO
+# define ACE_HAS_WIN32_NAMED_PIPES
+#endif /* !defined (ACE_USES_WINCE_SEMA_SIMULATION) && !ACE_HAS_PHARLAP */
+
+#if !defined (ACE_SEH_DEFAULT_EXCEPTION_HANDLING_ACTION)
+# define ACE_SEH_DEFAULT_EXCEPTION_HANDLING_ACTION EXCEPTION_CONTINUE_SEARCH
+#endif /* ACE_SEH_DEFAULT_EXCEPTION_HANDLING_ACTION */
+
+// ACE_HAS_QOS is defined in the qos.mpb base project.
+// If qos=1 in default.features, then this macro will be defined.
+#if defined (ACE_HAS_QOS) && !defined (ACE_HAS_WINSOCK2_GQOS)
+# if defined (WINSOCK_VERSION)
+# define ACE_HAS_WINSOCK2_GQOS 1
+# endif /* WINSOCK_VERSION */
+#endif /* ACE_HAS_WINSOCK2_GQOS */
+
+// These are the defaults and can be overridden by a user's config.h
+#if !defined (ACE_DEFAULT_FILE_PERMS)
+# define ACE_DEFAULT_FILE_PERMS (FILE_SHARE_READ | FILE_SHARE_WRITE | \
+ FILE_SHARE_DELETE)
+// This alternate used to be used for pre-NT4 systems; may still be needed
+// by knock-offs such as CE and Pharlap.
+//# define ACE_DEFAULT_FILE_PERMS (FILE_SHARE_READ | FILE_SHARE_WRITE)
+#endif /* !defined (ACE_DEFAULT_FILE_PERMS) */
+
+#define ACE_SIZEOF_WCHAR 2
+#define ACE_HAS_MUTEX_TIMEOUTS
+#define ACE_LACKS_STRUCT_DIR
+#define ACE_LACKS_OPENDIR
+#define ACE_LACKS_CLOSEDIR
+#define ACE_LACKS_READDIR
+#define ACE_LACKS_ALPHASORT
+#define ACE_LACKS_MKSTEMP
+#define ACE_LACKS_LSTAT
+// Looks like Win32 has a non-const swab function
+#define ACE_HAS_NONCONST_SWAB
+
+// If we are using winsock2 then the SO_REUSEADDR feature is broken
+// SO_REUSEADDR=1 behaves like SO_REUSEPORT=1. (SO_REUSEPORT is an
+// extension to sockets on some platforms)
+// We define SO_REUSEPORT here so that ACE_OS::setsockopt() can still
+// allow the user to specify that a socketaddr can *always* be reused.
+#if defined (ACE_HAS_WINSOCK2) && ACE_HAS_WINSOCK2 != 0 && ! defined(SO_REUSEPORT)
+#define SO_REUSEPORT 0x0400 // We just have to pick a value that won't conflict
+#endif
+
+#if defined (ACE_WIN64)
+// Data must be aligned on 8-byte boundaries, at a minimum.
+# define ACE_MALLOC_ALIGN 8
+// Void pointers are 8 bytes
+# define ACE_SIZEOF_VOID_P 8
+#endif /* ACE_WIN64 */
+
+#if !defined (ACE_DISABLES_THREAD_LIBRARY_CALLS)
+# define ACE_DISABLES_THREAD_LIBRARY_CALLS 0
+#endif /* ACE_DISABLES_THREAD_LIBRARY_CALLS */
+
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP)
+# define ACE_HAS_LOG_MSG_NT_EVENT_LOG
+#endif /* !ACE_HAS_WINCE && !ACE_HAS_PHARLAP */
+
+#if !defined (ACE_HAS_WINCE)
+# define ACE_HAS_LLSEEK
+#endif /* !ACE_HAS_WINCE */
+
+// Needed for obtaining the MAC address
+// I dont believe this will work under CE, notice the
+// check for ACE_HAS_WINCE.
+# if !defined (ACE_HAS_WINCE)
+# include <nb30.h>
+# if defined (_MSC_VER)
+# pragma comment(lib, "netapi32.lib") // needed for obtaing MACaddress
+# endif
+# endif /* !ACE_HAS_WINCE */
+
+#if !defined (WINVER)
+# define WINVER 0x0400 // pretend it's at least WinNT 4.0
+#endif
+
+///////////////////////////////////////
+// windows version-specific definitions
+// see: http://msdn2.microsoft.com/en-us/library/aa383745.aspx
+//
+// For TSS information
+// see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/thread_local_storage.asp
+
+#if (WINVER>=0x0600)
+// Windows Server 2008 definitions go here
+// Windows Vista defintions go here
+# if ! defined(ACE_DEFAULT_THREAD_KEYS)
+# define ACE_DEFAULT_THREAD_KEYS 1088
+# endif // ! defined(ACE_DEFAULT_THREAD_KEYS)
+#elif (WINVER>=0x0502)
+ // Windows Server 2003 SP1 definitions go here
+# if ! defined(ACE_DEFAULT_THREAD_KEYS)
+# define ACE_DEFAULT_THREAD_KEYS 1088
+# endif // ! defined(ACE_DEFAULT_THREAD_KEYS)
+#elif (WINVER>=0x0501)
+// Windows XP definitions go here
+# if ! defined(ACE_DEFAULT_THREAD_KEYS)
+# define ACE_DEFAULT_THREAD_KEYS 1088
+# endif // ! defined(ACE_DEFAULT_THREAD_KEYS)
+#elif (WINVER>=0x0500)
+// Windows 2000 definitions go here
+# if ! defined(ACE_DEFAULT_THREAD_KEYS)
+# define ACE_DEFAULT_THREAD_KEYS 1088
+# endif // ! defined(ACE_DEFAULT_THREAD_KEYS)
+#elif (WINVER>=0x0410)
+// Windows 98 definitions go here
+# if ! defined(ACE_DEFAULT_THREAD_KEYS)
+# define ACE_DEFAULT_THREAD_KEYS 80
+# endif // ! defined(ACE_DEFAULT_THREAD_KEYS)
+#else
+// antique windows
+# if ! defined(ACE_DEFAULT_THREAD_KEYS)
+# define ACE_DEFAULT_THREAD_KEYS 64
+# endif // ! defined(ACE_DEFAULT_THREAD_KEYS)
+#endif
+
+#if !defined (ACE_DEFAULT_BACKLOG)
+# define ACE_DEFAULT_BACKLOG SOMAXCONN
+#endif /* ACE_DEFAULT_BACKLOG */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_COMMON_H */
diff --git a/ACE/ace/config-win32-dmc.h b/ACE/ace/config-win32-dmc.h
new file mode 100644
index 00000000000..32de3ece103
--- /dev/null
+++ b/ACE/ace/config-win32-dmc.h
@@ -0,0 +1,109 @@
+// -*- C++ -*-
+// $Id$
+
+// The following configuration file contains defines for Digital Mars compilers.
+
+#ifndef ACE_CONFIG_WIN32_DMC_H
+#define ACE_CONFIG_WIN32_DMC_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+#error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+#ifndef WIN32
+# define WIN32
+#endif /* WIN32 */
+
+#undef _M_IX86
+// This turns on ACE_HAS_PENTIUM
+#define _M_IX86 500
+
+#if defined ACE_LACKS_STRUCT_DIR
+# undef ACE_LACKS_STRUCT_DIR
+#endif
+
+// Changed ACE_TEXT to ACE_TEXT in the following line
+# define ACE_CC_NAME ACE_TEXT ("Digital Mars")
+# define ACE_CC_MAJOR_VERSION (1)
+# define ACE_CC_MINOR_VERSION (8)
+# define ACE_CC_BETA_VERSION (9)
+# define ACE_CC_PREPROCESSOR "DMC.EXE"
+# define ACE_CC_PREPROCESSOR_ARGS "-E"
+
+// Microsoft's standard cpp library auto_ptr doesn't have reset ().
+# define ACE_AUTO_PTR_LACKS_RESET
+
+#define ACE_ENDTHREADEX(STATUS) ::_endthreadex ((DWORD) STATUS)
+
+// This section below was extracted from config-win32-msvc
+#define ACE_HAS_ITOA
+#define ACE_ITOA_EQUIVALENT ::_itoa
+#define ACE_STRCASECMP_EQUIVALENT ::_stricmp
+#define ACE_STRNCASECMP_EQUIVALENT ::_strnicmp
+#define ACE_WCSDUP_EQUIVALENT ::_wcsdup
+// This section above was extracted from config-win32-msvc
+
+# define ACE_EXPORT_NESTED_CLASSES 1
+# define ACE_HAS_CPLUSPLUS_HEADERS 1
+//# define ACE_HAS_EXCEPTIONS 1
+# define ACE_HAS_GNU_CSTRING_H 1
+# define ACE_HAS_NONCONST_SELECT_TIMEVAL 1
+# define ACE_HAS_SIG_ATOMIC_T 1
+# define ACE_HAS_STANDARD_CPP_LIBRARY 0
+# define ACE_HAS_STDCPP_STL_INCLUDES 1
+# define ACE_HAS_STRERROR 1
+# define ACE_HAS_STRING_CLASS 1
+# define ACE_HAS_TEMPLATE_SPECIALIZATION 1
+# define ACE_HAS_TEMPLATE_TYPEDEFS 1
+# define ACE_HAS_USER_MODE_MASKS 1
+//# define ACE_LACKS_LINEBUFFERED_STREAMBUF 1
+# define ACE_LACKS_STRPTIME 1
+//# define ACE_LACKS_PRAGMA_ONCE 1
+//# define ACE_NEW_THROWS_EXCEPTIONS 1
+# define ACE_SIZEOF_LONG_DOUBLE 10
+# define ACE_TEMPLATES_REQUIRE_SOURCE 1
+// Changed ACE_TEXT to ACE_TEXT in the following two lines
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# define ACE_HAS_STRBUF_T
+#define ACE_HAS_3_PARAM_WCSTOK
+#define ACE_USES_OLD_IOSTREAMS
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_SYS_RESOURCE_H
+#define ACE_LACKS_SYS_WAIT_H
+#define ACE_LACKS_STRINGS_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_SEMAPHORE_H
+#define ACE_LACKS_SYS_MMAN_H
+#define ACE_LACKS_SYS_UIO_H
+#define ACE_LACKS_SYS_SOCKET_H
+#define ACE_LACKS_NETINET_IN_H
+#define ACE_LACKS_SYS_IOCTL_H
+#define ACE_LACKS_SYS_SELECT_H
+#define ACE_LACKS_NET_IF_H
+#define ACE_LACKS_DLFCN_H
+#define ACE_LACKS_NETDB_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_REGEX_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_NETINET_TCP_H
+#define ACE_LACKS_UNISTD_H
+#define ACE_LACKS_TERMIOS_H
+#define ACE_LACKS_ACE_IOSTREAM
+#define ACE_HAS_NONCONST_TEMPNAM
+
+// Typedefs which we expect DMC to do, but they don't do that
+typedef long o_uid_t;
+typedef long o_gid_t;
+
+#include "io.h"
+#undef umask;
+#undef tell;
+
+# if !defined (ACE_LD_DECORATOR_STR) && defined (_DEBUG)
+# define ACE_LD_DECORATOR_STR ACE_TEXT ("d")
+# endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_DMC_H */
diff --git a/ACE/ace/config-win32-ghs.h b/ACE/ace/config-win32-ghs.h
new file mode 100644
index 00000000000..f90f42c62e4
--- /dev/null
+++ b/ACE/ace/config-win32-ghs.h
@@ -0,0 +1,95 @@
+// -*- C++ -*-
+// $Id$
+
+// The following configuration file contains defines for Green Hills compilers.
+
+#ifndef ACE_CONFIG_WIN32_GHS_H
+#define ACE_CONFIG_WIN32_GHS_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+#error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+#ifndef WIN32
+# define WIN32
+#endif /* WIN32 */
+
+#undef _M_IX86
+// This turns on ACE_HAS_PENTIUM
+#define _M_IX86 500
+// GHS does not provide DLL support
+#define ACE_HAS_DLL 0
+#define TAO_HAS_DLL 0
+#undef _DLL
+
+//Green Hills Native x86 does not support structural exceptions
+# undef ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS
+# undef ACE_HAS_WCHAR
+# define ACE_CONFIG_INCLUDE_GHS_COMMON
+# include "ace/config-ghs-common.h"
+
+// Changed ACE_TEXT to ACE_TEXT in the following line
+# define ACE_CC_NAME ACE_TEXT ("Green Hills C++")
+# define ACE_CC_MAJOR_VERSION (1)
+# define ACE_CC_MINOR_VERSION (8)
+# define ACE_CC_BETA_VERSION (9)
+# define ACE_CC_PREPROCESSOR "GCX.EXE"
+# define ACE_CC_PREPROCESSOR_ARGS "-E"
+
+// GHS uses Microsoft's standard cpp library, which has auto_ptr.
+# undef ACE_LACKS_AUTO_PTR
+// Microsoft's standard cpp library auto_ptr doesn't have reset ().
+# define ACE_AUTO_PTR_LACKS_RESET
+
+#define ACE_ENDTHREADEX(STATUS) ::_endthreadex ((DWORD) STATUS)
+
+// This section below was extracted from config-win32-msvc
+#define ACE_HAS_ITOA
+#define ACE_ITOA_EQUIVALENT ::_itoa
+#define ACE_STRCASECMP_EQUIVALENT ::_stricmp
+#define ACE_STRNCASECMP_EQUIVALENT ::_strnicmp
+#define ACE_WCSDUP_EQUIVALENT ::_wcsdup
+// This section above was extracted from config-win32-msvc
+
+# define ACE_EXPORT_NESTED_CLASSES 1
+# define ACE_HAS_CPLUSPLUS_HEADERS 1
+//# define ACE_HAS_EXCEPTIONS 1
+# define ACE_HAS_GNU_CSTRING_H 1
+# define ACE_HAS_NONCONST_SELECT_TIMEVAL 1
+# define ACE_HAS_SIG_ATOMIC_T 1
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_HAS_STDCPP_STL_INCLUDES 1
+# define ACE_HAS_STRERROR 1
+# define ACE_HAS_STRING_CLASS 1
+# define ACE_HAS_TEMPLATE_SPECIALIZATION 1
+# define ACE_HAS_TEMPLATE_TYPEDEFS 1
+# define ACE_HAS_USER_MODE_MASKS 1
+# define ACE_LACKS_ACE_IOSTREAM 1
+//# define ACE_LACKS_LINEBUFFERED_STREAMBUF 1
+# define ACE_LACKS_STRPTIME 1
+//# define ACE_LACKS_PRAGMA_ONCE 1
+# define ACE_LACKS_STRRECVFD 1
+//# define ACE_NEW_THROWS_EXCEPTIONS 1
+# define ACE_SIZEOF_LONG_DOUBLE 10
+# define ACE_TEMPLATES_REQUIRE_SOURCE 1
+// Changed ACE_TEXT to ACE_TEXT in the following two lines
+# define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%I64u")
+# define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%I64d")
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+// Set the following to zero to placate SString.h ACE_WString CTOR
+# undef ACE_WSTRING_HAS_USHORT_SUPPORT
+
+// Green Hills Native x86 does not support __int64 keyword
+# define ACE_LACKS_LONGLONG_T
+
+/* need to ensure these are included before <iomanip> */
+# include <time.h>
+# include <stdlib.h>
+
+# if !defined (ACE_LD_DECORATOR_STR) && defined (_DEBUG)
+# define ACE_LD_DECORATOR_STR ACE_TEXT ("d")
+# endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_GHS_H */
diff --git a/ACE/ace/config-win32-interix.h b/ACE/ace/config-win32-interix.h
new file mode 100644
index 00000000000..19cb586aa8f
--- /dev/null
+++ b/ACE/ace/config-win32-interix.h
@@ -0,0 +1,100 @@
+// -*- C++ -*-
+// $Id$
+
+// The following configuration file is designed to work for Interix
+// platforms using GNU g++ (Interix == Microsoft's Services for Unix)
+
+#ifndef ACE_CONFIG_WIN32_INTERIX_H
+#define ACE_CONFIG_WIN32_INTERIX_H
+#include /**/ "ace/pre.h"
+#include <arpa/inet.h>
+
+# define ACE_LACKS_SENDMSG
+# define ACE_LACKS_RECVMSG
+# define ACE_LACKS_STDINT_H
+# define ACE_LACKS_INTTYPES_H
+# define ACE_LACKS_PRAGMA_ONCE
+# define ACE_LACKS_RWLOCK_T
+# define ACE_LACKS_GETPGID // Don't have getpgid(), have setpgid() though...
+# define ACE_LACKS_UCONTEXT_H
+# define ACE_HAS_REENTRANT_FUNCTIONS
+# define ACE_LACKS_NETDB_REENTRANT_FUNCTIONS // Don't have gethostbyaddr_r and friends.
+# define ACE_HAS_DIRENT
+# define ACE_HAS_STDCPP_STL_INCLUDES
+# define ACE_HAS_STANDARD_CPP_LIBRARY 1
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# define ACE_HAS_NONCONST_SELECT_TIMEVAL
+# define ACE_HAS_SIGWAIT
+# define ACE_HAS_SIGINFO_T
+
+#include "ace/config-g++-common.h"
+
+#define ACE_HAS_NEW_NOTHROW // Need to know 'new's failure semantics.
+
+#if defined (ACE_HAS_THREADS)
+#define ACE_HAS_THREADS
+#define ACE_HAS_PTHREADS
+#define _THREAD_SAFE
+#define ACE_MTSAFE 1
+#define ACE_MT_SAFE 1
+#define ACE_LACKS_PTHREAD_YIELD
+#define ACE_HAS_MUTEX_TIMEOUTS
+#else
+ error "You need to enable threads for this Interix port."
+#endif /* ACE_HAS_THREADS */
+
+// INTERIX has the following, just an issue with porting for the moment
+#define ACE_LACKS_ACCESS
+// END INTERIX has the following....
+
+#define ACE_SIZEOF_LONG_DOUBLE 12
+#define ACE_PAGE_SIZE 4096
+
+#define ACE_HAS_SYSV_IPC
+#define ACE_HAS_SVR4_SIGNAL_T
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_SVR4_DYNAMIC_LINKING
+#define ACE_HAS_POSIX_TIME // Supports POSIX timers via struct timespec.
+#define ACE_LACKS_TIMESPEC_T // Defines struct timespec but not timespec_t.
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_SETSCHED
+#define ACE_HAS_SOCKADDR_IN_SIN_LEN
+#define ACE_HAS_RTLD_LAZY_V
+#define ACE_HAS_POSIX_NONBLOCK
+#define ACE_HAS_GETRUSAGE
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_HAS_SEMUN
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_STRERROR
+#define ACE_HAS_SVR4_GETTIMEOFDAY
+#define ACE_HAS_UALARM
+#define ACE_HAS_TERMIOS
+#define ACE_HAS_SIGWAIT
+
+// Turns off the tracing feature.
+#if !defined (ACE_NTRACE)
+#define ACE_NTRACE 1
+#endif /* ACE_NTRACE */
+
+// NOTE: In debugging some of the test apps they would all memory fault in using
+// ACE_Errno_Guard. Upon inspection of that code it uses TSS to save ERRNO in
+// a TSS pointer. Access to that pointer caused the fault. The work around here
+// is to tell ACE we have TSS and use emulation. More investigation is needed to
+// determine whether Interix TSS is broken or the correct semantics for usage under
+// Interix simply need to be ported.
+// To get around the issue ACE_HAS_TSS_EMULATION is defined to use TSS emulation
+// however while many test programs that use TSS pass the TSS_Test program fails.
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE // We need thread specific storage even though...
+#define ACE_HAS_TSS_EMULATION // It would appear to be broken in Interix!
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_INTERIX_H */
+
+/*
+The following tests do not run.
+Dynamic_Priority_Test.log ACE_HAS_TIMED_MESSAGE_BLOCKS
+Enum_Interfaces_Test.log
+IOStream_Test.log ACE_IOSTREAM not supported on this platform
+*/
+
+
diff --git a/ACE/ace/config-win32-mingw.h b/ACE/ace/config-win32-mingw.h
new file mode 100644
index 00000000000..737311b0462
--- /dev/null
+++ b/ACE/ace/config-win32-mingw.h
@@ -0,0 +1,98 @@
+// -*- C++ -*-
+// $Id$
+
+//
+// The following configuration file is designed to work for win32
+// platforms using gcc/g++ with mingw32 (http://www.mingw.org).
+//
+
+#ifndef ACE_CONFIG_WIN32_MINGW_H
+#define ACE_CONFIG_WIN32_MINGW_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+# error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+#define ACE_CC_NAME ACE_TEXT ("g++")
+#define ACE_CC_PREPROCESSOR "cpp"
+#define ACE_CC_PREPROCESOR_ARGS ""
+
+// Why all this is not in config-g++-common.h?
+#define ACE_CC_MAJOR_VERSION __GNUC__
+#define ACE_CC_MINOR_VERSION __GNUC_MINOR__
+#define ACE_CC_BETA_VERSION (0)
+
+#if !defined(__MINGW32__)
+# error You do not seem to be using mingw32
+#endif
+
+#include "ace/config-g++-common.h"
+
+#include /**/ <_mingw.h>
+#include /**/ <w32api.h>
+
+#define ACE_HAS_USER_MODE_MASKS
+
+#if (__MINGW32_MAJOR_VERSION < 2)
+# error You need a newer version (>= 2.0) of mingw32/w32api
+#endif
+
+#if (__MINGW32_MAJOR_VERSION >= 3)
+# define ACE_HAS_SSIZE_T
+# undef ACE_LACKS_STRUCT_DIR
+# undef ACE_LACKS_OPENDIR
+# undef ACE_LACKS_CLOSEDIR
+# undef ACE_LACKS_READDIR
+# undef ACE_LACKS_TELLDIR
+# undef ACE_LACKS_SEEKDIR
+# undef ACE_LACKS_REWINDDIR
+#else
+# define ACE_LACKS_DIRENT_H
+#endif
+
+#undef ACE_LACKS_SIGSET
+
+#define ACE_LACKS_SIGSET_DEFINITIONS
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_TERMIOS_H
+#define ACE_LACKS_NETINET_TCP_H
+#define ACE_LACKS_STRRECVFD
+#define ACE_LACKS_STRPTIME
+#define ACE_HAS_STRERROR
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_REGEX_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_PWD_H
+#define ACE_LACKS_SEMAPHORE_H
+#define ACE_LACKS_UCONTEXT_H
+#define ACE_LACKS_SYS_SELECT_H
+#define ACE_LACKS_SYS_RESOURCE_H
+#define ACE_LACKS_SYS_WAIT_H
+#define ACE_LACKS_DLFCN_H
+#define ACE_LACKS_SYS_MMAN_H
+#define ACE_LACKS_SYS_UIO_H
+#define ACE_LACKS_SYS_SOCKET_H
+#define ACE_LACKS_NETINET_IN_H
+#define ACE_LACKS_NETDB_H
+#define ACE_LACKS_NET_IF_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_SYS_IOCTL_H
+#define ACE_HAS_NONCONST_WCSDUP
+#define ACE_HAS_WINSOCK2_GQOS
+
+// We trust the user: He must have used -mpentiumpro or -mpentium
+// if that is what he wants.
+#if defined(pentiumpro) || defined(pentium)
+# define ACE_HAS_PENTIUM
+#endif
+
+#define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%I64d")
+#define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%I64u")
+
+#define ACE_ENDTHREADEX(STATUS) ::_endthreadex ((DWORD) (STATUS))
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_MINGW_H */
diff --git a/ACE/ace/config-win32-msvc-7.h b/ACE/ace/config-win32-msvc-7.h
new file mode 100644
index 00000000000..a0ef9bffee7
--- /dev/null
+++ b/ACE/ace/config-win32-msvc-7.h
@@ -0,0 +1,126 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file config-win32-msvc-7.h
+ *
+ * $Id$
+ *
+ * @brief Microsoft Visual C++ 7.0 configuration file.
+ *
+ * This file is the ACE configuration file for Microsoft Visual C++ version 7.
+ *
+ * @note Do not include this file directly, include config-win32.h instead.
+ *
+ * @author Darrell Brunsch <brunsch@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CONFIG_WIN32_MSVC_7_H
+#define ACE_CONFIG_WIN32_MSVC_7_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+#error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+// Visual C++ 7.0 (.NET) deprecated the old iostreams
+#if !defined (ACE_HAS_STANDARD_CPP_LIBRARY)
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+#endif
+
+#if !defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#endif
+
+// Win64 SDK compiler claims std::auto_ptr<>::reset not available.
+#if defined (_WIN64) || defined (WIN64)
+#define ACE_AUTO_PTR_LACKS_RESET
+#endif
+
+#define ACE_HAS_ITOA
+#define ACE_HAS_HEADER_ALLOCATED_CLASS_STATIC_CONST_INT_STOREAGE
+#define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+
+#define ACE_ITOA_EQUIVALENT ::_itoa
+#define ACE_STRCASECMP_EQUIVALENT ::_stricmp
+#define ACE_STRNCASECMP_EQUIVALENT ::_strnicmp
+#define ACE_WCSDUP_EQUIVALENT ::_wcsdup
+
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_EXCEPTIONS)
+#define ACE_HAS_EXCEPTIONS
+#endif /* ACE_HAS_WINCE */
+
+#define ACE_HAS_STRERROR
+#define ACE_LACKS_STRPTIME
+
+#define ACE_HAS_SIG_ATOMIC_T
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+#define ACE_LACKS_STRRECVFD
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+
+// Platform provides ACE_TLI function prototypes.
+// For Win32, this is not really true, but saves a lot of hassle!
+#define ACE_HAS_TLI_PROTOTYPES
+
+// Platform support linebuffered streaming is broken
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+#if !defined (ACE_HAS_WINCE) && !(defined (__INTEL_COMPILER) && (__INTEL_COMPILER == 900))
+# define ACE_HAS_INTRINSIC_INTERLOCKED
+# define ACE_HAS_INTRINSIC_BYTESWAP
+#endif
+
+#if defined (ACE_HAS_STANDARD_CPP_LIBRARY) && (ACE_HAS_STANDARD_CPP_LIBRARY != 0)
+
+// Platform has its Standard C++ library in the namespace std
+# if !defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+
+// ace/iostream.h does not work with the standard cpp library (yet).
+# if !defined (ACE_USES_OLD_IOSTREAMS)
+# define ACE_LACKS_ACE_IOSTREAM
+# endif /* ! ACE_USES_OLD_IOSTREAMS */
+
+// Starting with MSVC 7.1, std::new throws std::bad_alloc on out-of-memory.
+// Since we don't support MSVC 7.0, don't test for it.
+# define ACE_NEW_THROWS_EXCEPTIONS
+# define ACE_HAS_NEW_NOTHROW
+
+#else
+
+// iostream header lacks ipfx (), isfx (), etc., declarations
+# define ACE_LACKS_IOSTREAM_FX
+
+#endif
+
+// There are too many instances of this warning to fix it right now.
+// Maybe in the future.
+// 'this' : used in base member initializer list
+#pragma warning(disable:4355)
+
+// 'class1' : inherits 'class2::member' via dominance
+#pragma warning(disable:4250)
+
+// C++ Exception Specification ignored
+#pragma warning(disable:4290)
+
+// Disable warning of using Microsoft Extension.
+#pragma warning(disable:4231)
+
+// 'function' : unreferenced local function has been removed
+# pragma warning(disable:4505)
+
+// A template can not be exported. Only an instantiation may be exported.
+#define ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT
+
+// At least for ACE_UNIMPLEMENTED_FUNC in class templates, this is needed to
+// explicitly instantiate a template that has ACE_UNIMPLEMENTED_FUNC.
+# define ACE_NEEDS_FUNC_DEFINITIONS
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_MSVC_7_H */
diff --git a/ACE/ace/config-win32-msvc-8.h b/ACE/ace/config-win32-msvc-8.h
new file mode 100644
index 00000000000..201a554a06c
--- /dev/null
+++ b/ACE/ace/config-win32-msvc-8.h
@@ -0,0 +1,149 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file config-win32-msvc-8.h
+ *
+ * $Id$
+ *
+ * @brief Microsoft Visual C++ 8.0 configuration file.
+ *
+ * This file is the ACE configuration file for Microsoft Visual C++ version 8.
+ *
+ * @note Do not include this file directly, include config-win32.h instead.
+ *
+ * @author Darrell Brunsch <brunsch@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CONFIG_WIN32_MSVC_8_H
+#define ACE_CONFIG_WIN32_MSVC_8_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+#error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+#ifndef ACE_WIN32_VC8
+# define ACE_WIN32_VC8
+#endif
+
+// Visual C++ 8.0 (.NET) deprecated the old iostreams
+#if !defined (ACE_HAS_STANDARD_CPP_LIBRARY)
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+#endif
+
+#if !defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#endif
+
+// Windows' timeval is non-conformant (defined in terms of long instead of
+// time_t) and VC8 (on desktop, not CE) changed time_t to a 64-bit value
+// even when compiling a 32-bit application. Therefore, ace/Time_Value
+// needs to rearrange a few things for this compiler. See Time_Value.h
+// for complete details.
+#if !defined (ACE_HAS_WINCE)
+# define ACE_HAS_TIME_T_LONG_MISMATCH
+#endif
+
+#define ACE_HAS_ITOA
+#define ACE_HAS_HEADER_ALLOCATED_CLASS_STATIC_CONST_INT_STOREAGE
+#define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+
+#define ACE_ITOA_EQUIVALENT ::_itoa
+#define ACE_STRCASECMP_EQUIVALENT ::_stricmp
+#define ACE_STRNCASECMP_EQUIVALENT ::_strnicmp
+#define ACE_WCSDUP_EQUIVALENT ::_wcsdup
+
+#define ACE_HAS_EXCEPTIONS
+
+// Windows Mobile 5 doesn't do sig_atomic_t, but maybe future versions will.
+# if !defined (_WIN32_WCE) || (_WIN32_WCE > 0x501)
+# define ACE_HAS_SIG_ATOMIC_T
+# endif /* !Win CE 5.0 or less */
+
+#define ACE_HAS_STRERROR
+#define ACE_LACKS_STRPTIME
+
+#if !defined (ACE_HAS_WINCE)
+# define ACE_HAS_INTRIN_H
+# define ACE_HAS_INTRINSIC_INTERLOCKED
+#endif
+
+#if !defined (_WIN32_WCE) || (_WIN32_WCE >= 0x501)
+# define ACE_HAS_INTRINSIC_BYTESWAP
+#endif
+
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+#define ACE_LACKS_STRRECVFD
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+
+// Platform provides ACE_TLI function prototypes.
+// For Win32, this is not really true, but saves a lot of hassle!
+#define ACE_HAS_TLI_PROTOTYPES
+
+// Platform support linebuffered streaming is broken
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+#if defined (ACE_HAS_STANDARD_CPP_LIBRARY) && (ACE_HAS_STANDARD_CPP_LIBRARY != 0)
+
+// Platform has its Standard C++ library in the namespace std
+# if !defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+
+// ace/iostream.h does not work with the standard cpp library (yet).
+# if !defined (ACE_USES_OLD_IOSTREAMS)
+# define ACE_LACKS_ACE_IOSTREAM
+# endif /* ! ACE_USES_OLD_IOSTREAMS */
+
+// Starting with MSVC 7.1, std::new throws std::bad_alloc on out-of-memory.
+#define ACE_NEW_THROWS_EXCEPTIONS
+#define ACE_HAS_NEW_NOTHROW
+
+#else
+
+// iostream header lacks ipfx (), isfx (), etc., declarations
+# define ACE_LACKS_IOSTREAM_FX
+
+#endif
+
+// There are too many instances of this warning to fix it right now.
+// Maybe in the future.
+
+// Disable warning of using Microsoft Extension.
+# pragma warning(disable:4231)
+
+// CE (at least thru Windows Mobile 5) doesn't have the new, secure CRT.
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_TR24731_2005_CRT)
+# define ACE_HAS_TR24731_2005_CRT
+#endif
+
+//Detect Platform SDK 64-bit (AMD64) compiler using _MSC_FULL_VER
+#if (defined (_WIN64) || defined (WIN64)) && _MSC_FULL_VER < 140050000
+# define ACE_AUTO_PTR_LACKS_RESET
+# define ACE_MSVC_USES_DOUBLE_UNDERSCORE_STAT64
+# define ACE_HAS_BROKEN_STD_REVERSE_ITERATOR
+# define ACE_LACKS_NUMERIC_LIMITS_64_BIT_TYPES
+# undef ACE_HAS_TR24731_2005_CRT
+# undef ACE_HAS_INTRIN_H
+#endif
+
+// On CE w/o MFC config-WinCE.h needs to declare a placement new. This
+// triggers a warning that there's no placement delete, which can be ignored.
+#if defined (ACE_HAS_WINCE) && !defined (ACE_HAS_MFC)
+# pragma warning(disable:4291)
+#endif
+
+// A template can not be exported. Only an instantiation may be exported.
+#define ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT
+
+// At least for ACE_UNIMPLEMENTED_FUNC in class templates, this is needed to
+// explicitly instantiate a template that has ACE_UNIMPLEMENTED_FUNC.
+# define ACE_NEEDS_FUNC_DEFINITIONS
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_MSVC_8_H */
diff --git a/ACE/ace/config-win32-msvc-9.h b/ACE/ace/config-win32-msvc-9.h
new file mode 100644
index 00000000000..a8c9ec3ff2e
--- /dev/null
+++ b/ACE/ace/config-win32-msvc-9.h
@@ -0,0 +1,141 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file config-win32-msvc-9.h
+ *
+ * $Id$
+ *
+ * @brief Microsoft Visual C++ 9.0 configuration file.
+ *
+ * This file is the ACE configuration file for Microsoft Visual C++ version 9.
+ *
+ * @note Do not include this file directly, include config-win32.h instead.
+ */
+//=============================================================================
+
+#ifndef ACE_CONFIG_WIN32_MSVC_9_H
+#define ACE_CONFIG_WIN32_MSVC_9_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+#error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+#ifndef ACE_WIN32_VC9
+# define ACE_WIN32_VC9
+#endif
+
+// Visual C++ 9.0 (.NET) deprecated the old iostreams
+#if !defined (ACE_HAS_STANDARD_CPP_LIBRARY)
+#define ACE_HAS_STANDARD_CPP_LIBRARY 1
+#endif
+
+#if !defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+#define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+#endif
+
+// Windows' timeval is non-conformant (defined in terms of long instead of
+// time_t) and VC9 (on desktop, not CE) changed time_t to a 64-bit value
+// even when compiling a 32-bit application. Therefore, ace/Time_Value
+// needs to rearrange a few things for this compiler. See Time_Value.h
+// for complete details.
+#if !defined (ACE_HAS_WINCE)
+# define ACE_HAS_TIME_T_LONG_MISMATCH
+#endif
+
+#define ACE_HAS_ITOA
+#define ACE_HAS_HEADER_ALLOCATED_CLASS_STATIC_CONST_INT_STOREAGE
+#define ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR
+
+#define ACE_ITOA_EQUIVALENT ::_itoa
+#define ACE_STRCASECMP_EQUIVALENT ::_stricmp
+#define ACE_STRNCASECMP_EQUIVALENT ::_strnicmp
+#define ACE_WCSDUP_EQUIVALENT ::_wcsdup
+
+#define ACE_HAS_EXCEPTIONS
+
+// Windows Mobile 5 doesn't do sig_atomic_t, but maybe future versions will.
+# if !defined (_WIN32_WCE) || (_WIN32_WCE > 0x501)
+# define ACE_HAS_SIG_ATOMIC_T
+# endif /* !Win CE 5.0 or less */
+
+#define ACE_HAS_STRERROR
+#define ACE_LACKS_STRPTIME
+
+// Evaluate this with a WinCE build; maybe things have improved since VC8.
+//#if !defined (ACE_HAS_WINCE)
+# define ACE_HAS_INTRIN_H
+# define ACE_HAS_INTRINSIC_INTERLOCKED
+//#endif
+
+#if !defined (_WIN32_WCE) || (_WIN32_WCE >= 0x501)
+# define ACE_HAS_INTRINSIC_BYTESWAP
+#endif
+
+#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES
+#define ACE_LACKS_STRRECVFD
+#define ACE_HAS_CPLUSPLUS_HEADERS
+
+#define ACE_HAS_TEMPLATE_TYPEDEFS
+#define ACE_TEMPLATES_REQUIRE_SOURCE
+#define ACE_HAS_TEMPLATE_SPECIALIZATION
+
+// Platform provides ACE_TLI function prototypes.
+// For Win32, this is not really true, but saves a lot of hassle!
+#define ACE_HAS_TLI_PROTOTYPES
+
+// Platform support linebuffered streaming is broken
+#define ACE_LACKS_LINEBUFFERED_STREAMBUF
+
+#if defined (ACE_HAS_STANDARD_CPP_LIBRARY) && (ACE_HAS_STANDARD_CPP_LIBRARY != 0)
+
+// Platform has its Standard C++ library in the namespace std
+# if !defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+# define ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB 1
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+
+// ace/iostream.h does not work with the standard cpp library (yet).
+# if !defined (ACE_USES_OLD_IOSTREAMS)
+# define ACE_LACKS_ACE_IOSTREAM
+# endif /* ! ACE_USES_OLD_IOSTREAMS */
+
+// Starting with MSVC 7.1, std::new throws std::bad_alloc on out-of-memory.
+#define ACE_NEW_THROWS_EXCEPTIONS
+#define ACE_HAS_NEW_NOTHROW
+
+#else
+
+// iostream header lacks ipfx (), isfx (), etc., declarations
+# define ACE_LACKS_IOSTREAM_FX
+
+#endif
+
+// There are too many instances of this warning to fix it right now.
+// Maybe in the future.
+
+// Disable warning of using Microsoft Extension.
+# pragma warning(disable:4231)
+
+// 'class1' : inherits 'class2::member' via dominance
+#pragma warning(disable:4250)
+
+// CE (at least thru Windows Mobile 5) doesn't have the new, secure CRT.
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_TR24731_2005_CRT)
+# define ACE_HAS_TR24731_2005_CRT
+#endif
+
+// On CE w/o MFC config-WinCE.h needs to declare a placement new. This
+// triggers a warning that there's no placement delete, which can be ignored.
+#if defined (ACE_HAS_WINCE) && !defined (ACE_HAS_MFC)
+# pragma warning(disable:4291)
+#endif
+
+// A template can not be exported. Only an instantiation may be exported.
+#define ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT
+
+// At least for ACE_UNIMPLEMENTED_FUNC in class templates, this is needed to
+// explicitly instantiate a template that has ACE_UNIMPLEMENTED_FUNC.
+# define ACE_NEEDS_FUNC_DEFINITIONS
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_MSVC_9_H */
diff --git a/ACE/ace/config-win32-msvc.h b/ACE/ace/config-win32-msvc.h
new file mode 100644
index 00000000000..537d5f99336
--- /dev/null
+++ b/ACE/ace/config-win32-msvc.h
@@ -0,0 +1,164 @@
+//=============================================================================
+/**
+ * @file config-win32-msvc.h
+ *
+ * $Id$
+ *
+ * @brief Microsoft Visual C++ configuration file.
+ *
+ * This file is the ACE configuration file for Microsoft Visual C++ versions
+ * 5.0, 6.0, and 7.0 (.NET)
+ *
+ * @author Darrell Brunsch <brunsch@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CONFIG_WIN32_MSVC_H
+#define ACE_CONFIG_WIN32_MSVC_H
+#include /**/ "ace/pre.h"
+
+#ifndef ACE_CONFIG_WIN32_H
+#error Use config-win32.h in config.h instead of this header
+#endif /* ACE_CONFIG_WIN32_H */
+
+#define ACE_CC_NAME ACE_TEXT ("Visual C++")
+#define ACE_CC_PREPROCESSOR "CL.EXE"
+#define ACE_CC_PREPROCESSOR_ARGS "-nologo -E"
+
+#define ACE_CC_MAJOR_VERSION (_MSC_VER / 100 - 6)
+#define ACE_CC_MINOR_VERSION (_MSC_VER % 100)
+#define ACE_CC_BETA_VERSION (0)
+
+#if !defined (ACE_LD_DECORATOR_STR)
+# if defined (_DEBUG)
+# define ACE_LD_DECORATOR_STR ACE_TEXT ("d")
+# endif /* _DEBUG */
+#endif /* ACE_LD_DECORATOR_STR */
+
+#if !defined(_NATIVE_WCHAR_T_DEFINED)
+ #define ACE_LACKS_NATIVE_WCHAR_T
+#endif
+
+// Win Mobile still does thread exits differently than PC Windows.
+#if defined (_WIN32_WCE)
+# define ACE_ENDTHREADEX(STATUS) ExitThread ((DWORD) STATUS)
+#else
+# define ACE_ENDTHREADEX(STATUS) ::_endthreadex ((DWORD) STATUS)
+#endif /* _WIN32_WCE */
+
+#if (_MSC_VER >= 1500)
+# include "ace/config-win32-msvc-9.h"
+#elif (_MSC_VER >= 1400)
+# include "ace/config-win32-msvc-8.h"
+#elif (_MSC_VER >= 1310)
+# include "ace/config-win32-msvc-7.h"
+#else
+# error This version of Microsoft Visual C++ is not supported.
+#endif
+
+// MFC changes the behavior of operator new at all MSVC versions from 6 up
+// by throwing a static CMemoryException* instead of std::bad_alloc
+// (see ace/OS_Memory.h). This MFC exception object needs to be cleaned up
+// by calling its Delete() method.
+#if defined (ACE_HAS_MFC) && (ACE_HAS_MFC == 1)
+# if !defined (ACE_NEW_THROWS_EXCEPTIONS)
+# define ACE_NEW_THROWS_EXCEPTIONS
+# endif
+# if defined (ACE_bad_alloc)
+# undef ACE_bad_alloc
+# endif
+# define ACE_bad_alloc CMemoryException *e
+# if defined (ACE_del_bad_alloc)
+# undef ACE_del_bad_alloc
+# endif
+# define ACE_del_bad_alloc e->Delete();
+#endif /* ACE_HAS_MFC && ACE_HAS_MFC==1 */
+
+#if defined(ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+// must have _MT defined to include multithreading
+// features from win32 headers
+# if !defined(_MT) && !defined (ACE_HAS_WINCE)
+// *** DO NOT *** defeat this error message by defining _MT yourself.
+// On MSVC, this is changed by selecting the Multithreaded
+// DLL or Debug Multithreaded DLL in the Project Settings
+// under C++ Code Generation.
+# error You must link against multi-threaded libraries when using ACE (check your project settings)
+# endif /* !_MT && !ACE_HAS_WINCE */
+#endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+
+#include <malloc.h>
+// Although ACE does have alloca() on this compiler/platform combination, it is
+// disabled by default since it can be dangerous. Uncomment the following line
+// if you ACE to use it.
+//#define ACE_HAS_ALLOCA 1
+
+#define ACE_LACKS_DIRENT_H
+#define ACE_LACKS_DLFCN_H
+#define ACE_LACKS_INTTYPES_H
+#define ACE_LACKS_NETDB_H
+#define ACE_LACKS_NET_IF_H
+#define ACE_LACKS_NETINET_IN_H
+#define ACE_LACKS_STDINT_H
+#define ACE_LACKS_STROPTS_H
+#define ACE_LACKS_SYS_IOCTL_H
+#define ACE_LACKS_SYS_IPC_H
+#define ACE_LACKS_SYS_MMAN_H
+#define ACE_LACKS_SYS_RESOURCE_H
+#define ACE_LACKS_SYS_SELECT_H
+#define ACE_LACKS_SYS_SEM_H
+#define ACE_LACKS_SYS_SOCKET_H
+#define ACE_LACKS_SYS_TIME_H
+#define ACE_LACKS_SYS_UIO_H
+#define ACE_LACKS_SYS_WAIT_H
+#define ACE_LACKS_UCONTEXT_H
+
+#define ACE_LACKS_SEMAPHORE_H
+#define ACE_LACKS_STRINGS_H
+#define ACE_LACKS_PWD_H
+#define ACE_LACKS_POLL_H
+#define ACE_LACKS_SYS_SHM_H
+#define ACE_LACKS_SYS_MSG_H
+#define ACE_LACKS_NETINET_TCP_H
+#define ACE_LACKS_TERMIOS_H
+#define ACE_LACKS_REGEX_H
+
+#define ACE_INT64_FORMAT_SPECIFIER ACE_TEXT ("%I64d")
+#define ACE_UINT64_FORMAT_SPECIFIER ACE_TEXT ("%I64u")
+
+// Turn off warnings for /W4
+// To resume any of these warning: #pragma warning(default: 4xxx)
+// which should be placed after these defines
+
+#if !defined (ALL_WARNINGS) && defined(_MSC_VER) && !defined(ghs) && !defined(__MINGW32__)
+# pragma warning(disable: 4127) /* constant expression for TRACE/ASSERT */
+# pragma warning(disable: 4134) /* message map member fxn casts */
+# pragma warning(disable: 4511) /* private copy constructors are good to have */
+# pragma warning(disable: 4512) /* private operator= are good to have */
+# pragma warning(disable: 4514) /* unreferenced inlines are common */
+# pragma warning(disable: 4710) /* private constructors are disallowed */
+# pragma warning(disable: 4705) /* statement has no effect in optimized code */
+# pragma warning(disable: 4791) /* loss of debugging info in retail version */
+# pragma warning(disable: 4275) /* deriving exported class from non-exported */
+# pragma warning(disable: 4251) /* using non-exported as public in exported */
+# pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */
+# pragma warning(disable: 4097) /* typedef-name used as synonym for class-name */
+# pragma warning(disable: 4800) /* converting int to boolean */
+# if defined (__INTEL_COMPILER)
+# pragma warning(disable: 1744) /* field of class type without a DLL interface used in a class with a DLL interface */
+# pragma warning(disable: 1738)
+# endif
+#endif /* !ALL_WARNINGS && _MSV_VER && !ghs && !__MINGW32__ */
+
+// STRICT type checking in WINDOWS.H enhances type safety for Windows
+// programs by using distinct types to represent all the different
+// HANDLES in Windows. So for example, STRICT prevents you from
+// mistakenly passing an HPEN to a routine expecting an HBITMAP.
+// Note that we only use this if we
+# if defined (ACE_HAS_STRICT) && (ACE_HAS_STRICT != 0)
+# if !defined (STRICT) /* may already be defined */
+# define STRICT
+# endif /* !STRICT */
+# endif /* ACE_HAS_STRICT */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_MSVC_H */
diff --git a/ACE/ace/config-win32.h b/ACE/ace/config-win32.h
new file mode 100644
index 00000000000..37cfb683519
--- /dev/null
+++ b/ACE/ace/config-win32.h
@@ -0,0 +1,53 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file config-win32.h
+ *
+ * $Id$
+ *
+ * @brief Microsoft Windows configuration file.
+ *
+ * This file is the ACE configuration file for all of Microsoft Windows
+ * platforms that ACE runs on. Based on preprocessor definitions, it
+ * includes other more specific configuration files.
+ *
+ * @author Darrell Brunsch <brunsch@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CONFIG_WIN32_H
+#define ACE_CONFIG_WIN32_H
+#include /**/ "ace/pre.h"
+
+// NOTE: Please do not add anything besides #include's here. Put other stuff
+// (definitions, etc.) in the included headers
+
+// We need to ensure that for Borland vcl.h can be included before
+// windows.h. So we will not include config-win32-common.h from here,
+// but instead let it be included at the appropriate place in
+// config-win32-borland.h.
+#if !defined (__BORLANDC__)
+# include "ace/config-win32-common.h"
+#endif /* !__BORLANDC__ */
+
+// Include the config-win32-* file specific to the compiler
+#if defined (__BORLANDC__)
+# include "ace/config-win32-borland.h"
+#elif defined (_MSC_VER)
+# include "ace/config-win32-msvc.h"
+#elif defined (ghs)
+# include "ace/config-win32-ghs.h"
+#elif defined (__MINGW32__)
+# include "ace/config-win32-mingw.h"
+#elif defined (__DMC__)
+# include "ace/config-win32-dmc.h"
+#else
+# error Compiler is not supported
+#endif
+
+// gethostbyaddr does not handle IPv6-mapped-IPv4 addresses
+#define ACE_HAS_BROKEN_GETHOSTBYADDR_V4MAPPED
+
+#include /**/ "ace/post.h"
+#endif /* ACE_CONFIG_WIN32_H */
+
diff --git a/ACE/ace/filecache.mpb b/ACE/ace/filecache.mpb
new file mode 100644
index 00000000000..f5da84a3314
--- /dev/null
+++ b/ACE/ace/filecache.mpb
@@ -0,0 +1,8 @@
+// -*- MPC -*-
+// $Id$
+
+feature(ace_filecache) {
+ Source_Files(ACE_COMPONENTS) {
+ Filecache.cpp
+ }
+}
diff --git a/ACE/ace/gethrtime.cpp b/ACE/ace/gethrtime.cpp
new file mode 100644
index 00000000000..9fa33423aff
--- /dev/null
+++ b/ACE/ace/gethrtime.cpp
@@ -0,0 +1,60 @@
+// $Id$
+//
+// Build this file with g++. It can be linked in to a ACE application
+// that was compiled with GreenHills. It wouldn't be necessary if I
+// knew a way to correctly move values from registers to a 64-bit
+// variable in GHS asm code. That's easy with g++ asm.
+
+#include "ace/config-all.h"
+
+ACE_RCSID(ace, gethrtime, "$Id$")
+
+#if defined (ghs) && (defined (i386) || defined(__i386__))
+
+#include "ace/OS_NS_time.h"
+
+extern "C"
+ACE_hrtime_t
+ACE_GETHRTIME_NAME (void)
+{
+#if defined (ACE_HAS_PENTIUM)
+ // ACE_TRACE ("ACE_GETHRTIME_NAME");
+
+#if defined (ACE_LACKS_LONGLONG_T)
+ double now;
+#else /* ! ACE_LACKS_LONGLONG_T */
+ ACE_hrtime_t now;
+#endif /* ! ACE_LACKS_LONGLONG_T */
+
+ // Read the high-res tick counter directly into memory variable
+ // "now". The A constraint signifies a 64-bit int.
+#if defined (__GNUG__)
+ asm volatile ("rdtsc" : "=A" (now) : : "memory");
+// #elif defined (ghs)
+// The following doesn't work. For now, this file must be compile with g++.
+// asm ("rdtsc");
+// asm ("movl %edx,-16(%ebp)");
+// asm ("movl %eax,-12(%ebp)");
+#else
+# error unsupported compiler
+#endif
+
+#if defined (ACE_LACKS_LONGLONG_T)
+ // ACE_U_LongLong doesn't have the same layout as now, so construct
+ // it "properly".
+ ACE_UINT32 least, most;
+ ACE_OS::memcpy (&least, &now, sizeof (ACE_UINT32));
+ ACE_OS::memcpy (&most, (unsigned char *) &now + sizeof (ACE_UINT32),
+ sizeof (ACE_UINT32));
+
+ const ACE_hrtime_t ret (least, most);
+ return ret;
+#else /* ! ACE_LACKS_LONGLONG_T */
+ return now;
+#endif /* ! ACE_LACKS_LONGLONG_T */
+
+#else /* ! ACE_HAS_PENTIUM */
+# error This file can _only_ be compiled with ACE_HAS_PENTIUM.
+#endif /* ! ACE_HAS_PENTIUM */
+}
+#endif /* ghs */
diff --git a/ACE/ace/iosfwd.h b/ACE/ace/iosfwd.h
new file mode 100644
index 00000000000..d255a75241c
--- /dev/null
+++ b/ACE/ace/iosfwd.h
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file iosfwd.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali
+ *
+ * This file contains the portability ugliness for the Standard C++
+ * Library. As implementations of the "standard" emerge, this file
+ * will need to be updated.
+ *
+ * This files deals with forward declaration for the stream
+ * classes. Remember that since the new Standard C++ Library code
+ * for streams uses templates, simple forward declaration will not
+ * work.
+ */
+//=============================================================================
+
+
+#ifndef ACE_IOSFWD_H
+#define ACE_IOSFWD_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_LACKS_IOSTREAM_TOTALLY)
+
+#if defined (__APPLE_CC__)
+// Should this really be here? dhinton
+// FUZZ: disable check_for_streams_include
+# include "ace/streams.h"
+#endif
+
+#if defined (ACE_HAS_STANDARD_CPP_LIBRARY) && \
+ (ACE_HAS_STANDARD_CPP_LIBRARY != 0)
+
+# if !defined (ACE_USES_OLD_IOSTREAMS)
+# include /**/ <iosfwd>
+# else
+ // @note If these forward declarations don't work (e.g. aren't
+ // portable), we may have to include "ace/streams.h" as a last
+ // resort. Doing so would defeat the purpose of this header,
+ // unfortunately.
+ class ios;
+ class streambuf;
+ class istream;
+ class ostream;
+ class iostream;
+ class filebuf;
+ class ifstream;
+ class ofstream;
+ class fstream;
+# endif /* ! ACE_USES_OLD_IOSTREAMS */
+
+# if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB) && \
+ (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB != 0)
+
+# if !defined (ACE_USES_OLD_IOSTREAMS)
+ // Make these available in the global name space
+ using std::ios;
+ using std::streambuf;
+ using std::istream;
+ using std::ostream;
+ using std::iostream;
+ using std::filebuf;
+ using std::ifstream;
+ using std::ofstream;
+ using std::fstream;
+# endif /* ! ACE_USES_OLD_IOSTREAMS */
+
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+
+#else /* ! ACE_HAS_STANDARD_CPP_LIBRARY */
+
+ class ios;
+ class streambuf;
+ class istream;
+ class ostream;
+ class iostream;
+ class filebuf;
+ class ifstream;
+ class ofstream;
+ class fstream;
+
+# endif /* ! ACE_HAS_STANDARD_CPP_LIBRARY */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+
+#endif /* ACE_IOSFWD_H */
diff --git a/ACE/ace/os_include/arpa/os_inet.h b/ACE/ace/os_include/arpa/os_inet.h
new file mode 100644
index 00000000000..f3b0a9e3e37
--- /dev/null
+++ b/ACE/ace/os_include/arpa/os_inet.h
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_inet.h
+ *
+ * definitions for internet operations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_ARPA_OS_INET_H
+#define ACE_OS_INCLUDE_ARPA_OS_INET_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/os_include/netinet/os_in.h"
+
+#if !defined (ACE_LACKS_ARPA_INET_H)
+ extern "C" {
+# include /**/ <arpa/inet.h>
+ }
+#endif /* !ACE_LACKS_ARPA_INET_H */
+
+#if defined (ACE_VXWORKS)
+# include /**/ <inetLib.h>
+#endif /* ACE_VXWORKS */
+
+/**
+ * In some environments it is useful to swap the bytes on write, for
+ * instance: a fast server can be feeding a lot of slow clients that
+ * happen to have the wrong byte order.
+ * Because this is a rarely used feature we disable it by default to
+ * minimize footprint.
+ * This macro enables the functionality, but we still need a way to
+ * activate it on a per-connection basis.
+ */
+// #define ACE_ENABLE_SWAP_ON_WRITE
+
+/**
+ * In some environements we never need to swap bytes when reading, for
+ * instance embebbed systems (such as avionics) or homogenous
+ * networks.
+ * Setting this macro disables the capabilities to demarshall streams
+ * in the wrong byte order.
+ */
+// #define ACE_DISABLE_SWAP_ON_READ
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_INET_ATON_PROTOTYPE)
+ int inet_aton (const char *, struct in_addr *);
+#endif /* ACE_LACKS_INET_ATON_PROTOTYPE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_ARPA_OS_INET_H */
diff --git a/ACE/ace/os_include/net/os_if.h b/ACE/ace/os_include/net/os_if.h
new file mode 100644
index 00000000000..bb44c58504c
--- /dev/null
+++ b/ACE/ace/os_include/net/os_if.h
@@ -0,0 +1,119 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_if.h
+ *
+ * sockets local interfaces
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_NET_OS_IF_H
+#define ACE_OS_INCLUDE_NET_OS_IF_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_LACKS_NET_IF_H)
+ // This part if to avoid STL name conflict with the map structure
+ // in net/if.h.
+# if defined (ACE_HAS_STL_MAP_CONFLICT)
+# define map _Resource_Allocation_Map_
+# endif /* ACE_HAS_STL_MAP_CONFLICT */
+ extern "C" {
+# include /**/ <net/if.h>
+ }
+# if defined (ACE_HAS_STL_MAP_CONFLICT)
+# undef map
+# endif /* ACE_HAS_STL_MAP_CONFLICT */
+# if defined (HPUX) && defined (IOR)
+ /* HP-UX 11.11 defines IOR in /usr/include/pa/inline.h
+ and we don't want that definition. See IOP_IORC.h.
+ Thanks to Torsten Kopper <tkue_0931@fastmail.fm> for this patch.*/
+# undef IOR
+# endif /* HPUX && IOR */
+#endif /* !ACE_LACKS_NET_IF_H */
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+# include /**/ <ws2tcpip.h>
+#endif /* ACE_HAS_WINSOCK2 */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_HAS_BROKEN_IF_HEADER)
+ struct ifafilt;
+#endif /* ACE_HAS_BROKEN_IF_HEADER */
+
+#if defined (ACE_LACKS_IFREQ)
+struct ifreq {
+#define IFNAMSIZ 16
+ char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ short ifru_flags;
+ int ifru_metric;
+ int ifru_mtu;
+ int ifru_phys;
+ int ifru_media;
+ caddr_t ifru_data;
+ int (*ifru_tap)(struct ifnet *, struct ether_header *, struct mbuf *);
+ } ifr_ifru;
+#define ifr_addr ifr_ifru.ifru_addr /* address */
+#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_metric ifr_ifru.ifru_metric /* metric */
+#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+#define ifr_phys ifr_ifru.ifru_phys /* physical wire */
+#define ifr_media ifr_ifru.ifru_media /* physical media */
+#define ifr_data ifr_ifru.ifru_data /* for use by interface */
+#define ifr_tap ifr_ifru.ifru_tap /* tap function */
+};
+#endif /* ACE_LACKS_IFREQ */
+
+#if defined (ACE_LACKS_IFCONF)
+struct ifconf {
+ int ifc_len;
+ union {
+ caddr_t ifcu_buf;
+ struct ifreq *ifcu_req;
+ } ifc_ifcu;
+#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
+#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
+ };
+#endif /* ACE_LACKS_IFCONF */
+
+#if !defined (IFF_UP)
+# define IFF_UP 0x1
+#endif /* IFF_UP */
+
+#if !defined (IFF_LOOPBACK)
+# define IFF_LOOPBACK 0x8
+#endif /* IFF_LOOPBACK */
+
+#if !defined (IFF_BROADCAST)
+# define IFF_BROADCAST 0x2
+#endif /* IFF_BROADCAST */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_NET_OS_IF_H */
diff --git a/ACE/ace/os_include/netinet/os_in.h b/ACE/ace/os_include/netinet/os_in.h
new file mode 100644
index 00000000000..f8af16f84fb
--- /dev/null
+++ b/ACE/ace/os_include/netinet/os_in.h
@@ -0,0 +1,185 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_in.h
+ *
+ * Internet address family
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_NETINET_OS_IN_H
+#define ACE_OS_INCLUDE_NETINET_OS_IN_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/os_include/os_inttypes.h"
+#include "ace/os_include/sys/os_socket.h"
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+# include /**/ <ws2tcpip.h>
+#endif /* ACE_HAS_WINSOCK2 */
+
+#if !defined (ACE_LACKS_NETINET_IN_H)
+# if defined (ACE_HAS_STL_QUEUE_CONFLICT)
+# define queue _Queue_
+# endif /* ACE_HAS_STL_QUEUE_CONFLICT */
+ extern "C" {
+# include /**/ <netinet/in.h>
+ }
+# if defined (ACE_HAS_STL_QUEUE_CONFLICT)
+# undef queue
+# endif /* ACE_HAS_STL_QUEUE_CONFLICT */
+#endif /* !ACE_LACKS_NETINET_IN_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+# if defined (ACE_HAS_PHARLAP_RT)
+# define ACE_IPPROTO_TCP SOL_SOCKET
+# else
+# define ACE_IPPROTO_TCP IPPROTO_TCP
+# endif /* ACE_HAS_PHARLAP_RT */
+
+# if !defined (ACE_HAS_IP_MULTICAST) && defined (ACE_LACKS_IP_ADD_MEMBERSHIP)
+ // Even if ACE_HAS_IP_MULTICAST is not defined, if IP_ADD_MEMBERSHIP
+ // is defined, assume that the ip_mreq struct is also defined
+ // (presumably in netinet/in.h).
+ struct ip_mreq
+ {
+ /// IP multicast address of group
+ struct in_addr imr_multiaddr;
+ /// Local IP address of interface
+ struct in_addr imr_interface;
+ };
+# endif /* ! ACE_HAS_IP_MULTICAST && ACE_LACKS_IP_ADD_MEMBERSHIP */
+
+# if defined (ACE_LACKS_IN_ADDR)
+ struct in_addr
+ {
+ u_long s_addr;
+ };
+# endif /* ACE_LACKS_IN_ADDR */
+
+# if defined (ACE_LACKS_SOCKADDR_IN)
+ struct sockaddr_in
+ {
+ short sin_family; // e.g. AF_INET
+ unsigned short sin_port; // e.g. htons(3490)
+ struct in_addr sin_addr; // see struct in_addr, below
+ char sin_zero[8]; // zero this if you want to
+ };
+# endif /* ACE_LACKS_SOCKADDR_IN */
+
+# if defined (ACE_LACKS_SOCKADDR_UN)
+ struct sockaddr_un {
+ u_char sun_len; /* sockaddr len including null */
+ u_char sun_family; /* AF_UNIX */
+ char sun_path[104]; /* path name (gag) */
+ };
+#endif /* ACE_LACKS_SOCKADDR_UN */
+
+# if defined (ACE_LACKS_IP_MREQ)
+ struct ip_mreq
+ {
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+ };
+# endif /* ACE_LACKS_IP_MREQ */
+
+#if !defined (IPPORT_RESERVED)
+# define IPPORT_RESERVED 1024
+#endif /* !IPPORT_RESERVED */
+
+#if !defined (IPPORT_USERRESERVED)
+# define IPPORT_USERRESERVED 5000
+#endif /* !IPPORT_USERRESERVED */
+
+// Define INET loopback address constant if it hasn't been defined
+// Dotted Decimal 127.0.0.1 == Hexidecimal 0x7f000001
+#if !defined (INADDR_LOOPBACK)
+# define INADDR_LOOPBACK ((ACE_UINT32) 0x7f000001)
+#endif /* INADDR_LOOPBACK */
+
+// The INADDR_NONE address is generally 255.255.255.255.
+#if !defined (INADDR_NONE)
+# define INADDR_NONE ((ACE_UINT32) 0xffffffff)
+#endif /* INADDR_NONE */
+
+// Define INET string length constants if they haven't been defined
+//
+// for IPv4 dotted-decimal
+#if !defined (INET_ADDRSTRLEN)
+# define INET_ADDRSTRLEN 16
+#endif /* INET_ADDRSTRLEN */
+//
+// for IPv6 hex string
+#if !defined (INET6_ADDRSTRLEN)
+# define INET6_ADDRSTRLEN 46
+#endif /* INET6_ADDRSTRLEN */
+
+# if !defined (IP_DROP_MEMBERSHIP)
+# define IP_DROP_MEMBERSHIP 0
+# endif /* IP_DROP_MEMBERSHIP */
+
+# if !defined (IP_ADD_MEMBERSHIP)
+# define IP_ADD_MEMBERSHIP 0
+# define ACE_LACKS_IP_ADD_MEMBERSHIP
+# endif /* IP_ADD_MEMBERSHIP */
+
+# if !defined (IP_DEFAULT_MULTICAST_TTL)
+# define IP_DEFAULT_MULTICAST_TTL 0
+# endif /* IP_DEFAULT_MULTICAST_TTL */
+
+# if !defined (IP_DEFAULT_MULTICAST_LOOP)
+# define IP_DEFAULT_MULTICAST_LOOP 0
+# endif /* IP_DEFAULT_MULTICAST_LOOP */
+
+# if !defined (IP_MULTICAST_IF)
+# define IP_MULTICAST_IF 0
+# endif /* IP_MULTICAST_IF */
+
+# if !defined (IP_MULTICAST_TTL)
+# define IP_MULTICAST_TTL 1
+# endif /* IP_MULTICAST_TTL */
+
+# if !defined (IP_MULTICAST_LOOP)
+# define IP_MULTICAST_LOOP 2
+# endif /* IP_MULTICAST_LOOP */
+
+# if !defined (IP_MAX_MEMBERSHIPS)
+# define IP_MAX_MEMBERSHIPS 0
+# endif /* IP_MAX_MEMBERSHIP */
+
+# if !defined (IPPROTO_IP)
+# define IPPROTO_IP 0
+# endif /* IPPROTO_IP */
+
+# if !defined (IPPROTO_TCP)
+# define IPPROTO_TCP 6
+# endif /* IPPROTO_TCP */
+
+# if !defined (INADDR_ANY)
+# define INADDR_ANY (u_long)0x00000000
+# endif /* INADDR_ANY */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_NETINET_OS_IN_H */
diff --git a/ACE/ace/os_include/netinet/os_tcp.h b/ACE/ace/os_include/netinet/os_tcp.h
new file mode 100644
index 00000000000..e0d6c4124d6
--- /dev/null
+++ b/ACE/ace/os_include/netinet/os_tcp.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_tcp.h
+ *
+ * definitions for the Internet Transmission Control Protocol (TCP)
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_NETINET_OS_TCP_H
+#define ACE_OS_INCLUDE_NETINET_OS_TCP_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_LACKS_NETINET_TCP_H)
+# include /**/ <netinet/tcp.h>
+#endif /* !ACE_LACKS_NETIINET_TCP_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+# if !defined (TCP_NODELAY)
+# define TCP_NODELAY 0x01
+# endif /* TCP_NODELAY */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_NETINET_OS_TCP_H */
diff --git a/ACE/ace/os_include/os_aio.h b/ACE/ace/os_include/os_aio.h
new file mode 100644
index 00000000000..1716f53d36e
--- /dev/null
+++ b/ACE/ace/os_include/os_aio.h
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_aio.h
+ *
+ * asynchronous input and output (REALTIME)
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_AIO_H
+#define ACE_OS_INCLUDE_OS_AIO_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Inclusion of the <aio.h> header may make visible symbols defined in
+// the headers <fcntl.h>, <signal.h>, <sys/types.h>, and <time.h>.
+
+#include "ace/os_include/os_signal.h" // for sigevent
+
+#if !defined (ACE_LACKS_AIO_H)
+# include /**/ <aio.h>
+#endif /* !ACE_LACKS_AIO_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_AIO_H */
diff --git a/ACE/ace/os_include/os_assert.h b/ACE/ace/os_include/os_assert.h
new file mode 100644
index 00000000000..39d9e7c831a
--- /dev/null
+++ b/ACE/ace/os_include/os_assert.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_assert.h
+ *
+ * verify program assertion
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_ASSERT_H
+#define ACE_OS_INCLUDE_OS_ASSERT_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_LACKS_ASSERT_H)
+# include /**/ <assert.h>
+#endif /* !ACE_LACKS_ASSERT_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_ASSERT_MACRO)
+# define assert(expr)
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_ASSERT_H */
diff --git a/ACE/ace/os_include/os_byteswap.h b/ACE/ace/os_include/os_byteswap.h
new file mode 100644
index 00000000000..f4bcd4978e8
--- /dev/null
+++ b/ACE/ace/os_include/os_byteswap.h
@@ -0,0 +1,41 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_byteswap.h
+ *
+ * Byteswap methods
+ *
+ * $Id$
+ *
+ * @author Johnny Willemsen <jwillemsen@remedy.nl>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_BYTESWAP_H
+#define ACE_OS_INCLUDE_OS_BYTESWAP_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_HAS_BYTESWAP_H)
+# include /**/ <byteswap.h>
+#endif /* !ACE_HAS_INTRIN_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_BYTESWAP_H */
diff --git a/ACE/ace/os_include/os_complex.h b/ACE/ace/os_include/os_complex.h
new file mode 100644
index 00000000000..836e52dd65b
--- /dev/null
+++ b/ACE/ace/os_include/os_complex.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_complex.h
+ *
+ * complex arithmetic
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_COMPLEX_H
+#define ACE_OS_INCLUDE_OS_COMPLEX_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_LACKS_COMPLEX_H)
+# include /**/ <complex.h>
+#endif /* !ACE_LACKS_COMPLEX_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_COMPLEX_H */
diff --git a/ACE/ace/os_include/os_cpio.h b/ACE/ace/os_include/os_cpio.h
new file mode 100644
index 00000000000..f7c10b34d13
--- /dev/null
+++ b/ACE/ace/os_include/os_cpio.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_cpio.h
+ *
+ * cpio archive values
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_CPIO_H
+#define ACE_OS_INCLUDE_OS_CPIO_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_LACKS_CPIO_H)
+# include /**/ <cpio.h>
+#endif /* !ACE_LACKS_CPIO_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_CPIO_H */
diff --git a/ACE/ace/os_include/os_ctype.h b/ACE/ace/os_include/os_ctype.h
new file mode 100644
index 00000000000..e1f5f1842af
--- /dev/null
+++ b/ACE/ace/os_include/os_ctype.h
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_ctype.h
+ *
+ * character types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_CTYPE_H
+#define ACE_OS_INCLUDE_OS_CTYPE_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_LACKS_CTYPE_H)
+# include /**/ <ctype.h>
+#endif /* !ACE_LACKS_CTYPE_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+// @todo move the is* and is* emulation methods in ACE_OS here
+// and let ACE_OS just call them.
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_CTYPE_H */
diff --git a/ACE/ace/os_include/os_dirent.h b/ACE/ace/os_include/os_dirent.h
new file mode 100644
index 00000000000..751e229879a
--- /dev/null
+++ b/ACE/ace/os_include/os_dirent.h
@@ -0,0 +1,108 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_dirent.h
+ *
+ * format of directory entries
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_DIRENT_H
+#define ACE_OS_INCLUDE_OS_DIRENT_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/os_include/sys/os_types.h"
+#include "ace/os_include/os_limits.h"
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x620)
+# include "ace/os_include/os_unistd.h" // VxWorks needs this to compile
+#endif /* ACE_VXWORKS */
+
+#if !defined (ACE_LACKS_DIRENT_H)
+# include /**/ <dirent.h>
+#endif /* !ACE_LACKS_DIRENT_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if !defined (MAXNAMLEN)
+# define MAXNAMLEN NAME_MAX
+#endif /* !MAXNAMLEN */
+
+// At least compile on some of the platforms without <ACE_DIR> info yet.
+#if !defined (ACE_HAS_DIRENT)
+typedef int ACE_DIR;
+struct dirent {
+};
+#endif /* ACE_HAS_DIRENT */
+
+#if defined (ACE_LACKS_STRUCT_DIR)
+struct dirent {
+ unsigned short d_ino;
+ unsigned short d_off;
+ unsigned short d_reclen;
+ // This must be a ACE_TCHAR * and not a one element
+ // ACE_TCHAR array. It causes problems on wide
+ // character builds with Visual C++ 6.0.
+ ACE_TCHAR *d_name;
+};
+
+#define ACE_DIRENT dirent
+
+struct ACE_DIR {
+ /// The name of the directory we are looking into
+ ACE_TCHAR *directory_name_;
+
+ /// Remember the handle between calls.
+ HANDLE current_handle_;
+
+ /// The struct for the results
+ ACE_DIRENT *dirent_;
+
+ /// The struct for intermediate results.
+ ACE_TEXT_WIN32_FIND_DATA fdata_;
+
+ /// A flag to remember if we started reading already.
+ int started_reading_;
+};
+#elif defined (ACE_WIN32) && (__BORLANDC__) && defined (ACE_USES_WCHAR)
+#define ACE_DIRENT wdirent
+typedef wDIR ACE_DIR;
+#else
+#define ACE_DIRENT dirent
+typedef DIR ACE_DIR;
+#endif /* ACE_LACKS_STRUCT_DIR */
+
+#if defined (ACE_LACKS_SCANDIR_PROTOTYPE)
+int scandir (const char *,
+ struct dirent ***,
+ int (*) (const struct dirent *),
+ int (*) (const void *, const void *));
+#endif /* ACE_LACKS_SCANDIR_PROTOTYPE */
+
+#if defined (ACE_LACKS_ALPHASORT_PROTOTYPE)
+int alphasort (const void *, const void *);
+#endif /* ACE_LACKS_ALPHASORT_PROTOTYPE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_DIRENT_H */
diff --git a/ACE/ace/os_include/os_dlfcn.h b/ACE/ace/os_include/os_dlfcn.h
new file mode 100644
index 00000000000..6f50551a8af
--- /dev/null
+++ b/ACE/ace/os_include/os_dlfcn.h
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_dlfcn.h
+ *
+ * dynamic linking
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_DLFCN_H
+#define ACE_OS_INCLUDE_OS_DLFCN_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_LACKS_DLFCN_H)
+# if defined (ACE_HAS_DLFCN_H_BROKEN_EXTERN_C)
+ extern "C" {
+# endif /* ACE_HAS_DLFCN_H_BROKEN_EXTERN_C */
+# include /**/ <dlfcn.h>
+# if defined (ACE_HAS_DLFCN_H_BROKEN_EXTERN_C)
+ }
+# endif /* ACE_HAS_DLFCN_H_BROKEN_EXTERN_C */
+#endif /* !ACE_LACKS_DLFCN_H */
+
+#if defined (__hpux)
+# if defined(__GNUC__) || __cplusplus >= 199707L
+# include /**/ <dl.h>
+# else
+# include /**/ <cxxdl.h>
+# endif /* (g++ || HP aC++) vs. HP C++ */
+#endif /* __hpux */
+
+#if defined (ACE_VXWORKS) && !defined (__RTP__)
+# include /**/ <loadLib.h> /* for module load */
+# include /**/ <unldLib.h> /* for module unload */
+# include /**/ <symLib.h> /* for findSymbol */
+# include /**/ <sysSymTbl.h> /* for global symbol table */
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (_M_UNIX)
+ int _dlclose (void *);
+ char *_dlerror (void);
+ void *_dlopen (const char *, int);
+ void * _dlsym (void *, const char *);
+#endif /* _M_UNIX */
+
+/* Set the proper handle type for dynamically-loaded libraries. */
+/* Also define a default 'mode' for loading a library - the names and values */
+/* differ between OSes, so if you write code that uses the mode, be careful */
+/* of the platform differences. */
+#if defined (ACE_WIN32)
+ // Dynamic loading-related types - used for dlopen and family.
+ typedef HINSTANCE ACE_SHLIB_HANDLE;
+# define ACE_SHLIB_INVALID_HANDLE 0
+# define ACE_DEFAULT_SHLIB_MODE 0
+#elif defined (ACE_HAS_SVR4_DYNAMIC_LINKING)
+ typedef void *ACE_SHLIB_HANDLE;
+# define ACE_SHLIB_INVALID_HANDLE 0
+ // This is needed to for dynamic_cast to work properly on objects passed to
+ // libraries.
+# define ACE_DEFAULT_SHLIB_MODE RTLD_LAZY | RTLD_GLOBAL
+#elif defined (__hpux)
+ typedef shl_t ACE_SHLIB_HANDLE;
+# define ACE_SHLIB_INVALID_HANDLE 0
+# define ACE_DEFAULT_SHLIB_MODE BIND_DEFERRED | DYNAMIC_PATH
+#else /* !ACE_WIN32 && !ACE_HAS_SVR4_DYNAMIC_LINKING && !__hpux */
+ typedef void *ACE_SHLIB_HANDLE;
+# define ACE_SHLIB_INVALID_HANDLE 0
+# define ACE_DEFAULT_SHLIB_MODE RTLD_LAZY
+#endif /* ACE_WIN32 */
+
+#if !defined (RTLD_LAZY)
+#define RTLD_LAZY 1
+#endif /* !RTLD_LAZY */
+
+#if !defined (RTLD_NOW)
+#define RTLD_NOW 2
+#endif /* !RTLD_NOW */
+
+#if !defined (RTLD_GLOBAL)
+#define RTLD_GLOBAL 3
+#endif /* !RTLD_GLOBAL */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_DLFCN_H */
diff --git a/ACE/ace/os_include/os_errno.h b/ACE/ace/os_include/os_errno.h
new file mode 100644
index 00000000000..6d2656dba16
--- /dev/null
+++ b/ACE/ace/os_include/os_errno.h
@@ -0,0 +1,153 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_errno.h
+ *
+ * system error numbers
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_ERRNO_H
+#define ACE_OS_INCLUDE_OS_ERRNO_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_ERRNO_H)
+# include /**/ <errno.h>
+#endif /* !ACE_LACKS_ERRNO_H */
+
+#if defined (ACE_VXWORKS)
+// Needed for VxWorks to pickup errnoSet()
+#include /**/ <errnoLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_WIN32)
+ // error code mapping for windows
+# define ETIME ERROR_SEM_TIMEOUT
+# define EWOULDBLOCK WSAEWOULDBLOCK
+# define EINPROGRESS WSAEINPROGRESS
+# define EALREADY WSAEALREADY
+# define ENOTSOCK WSAENOTSOCK
+# define EDESTADDRREQ WSAEDESTADDRREQ
+# define EMSGSIZE WSAEMSGSIZE
+# define EPROTOTYPE WSAEPROTOTYPE
+# define ENOPROTOOPT WSAENOPROTOOPT
+# define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+# define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+# define EOPNOTSUPP WSAEOPNOTSUPP
+# define EPFNOSUPPORT WSAEPFNOSUPPORT
+# define EAFNOSUPPORT WSAEAFNOSUPPORT
+# define EADDRINUSE WSAEADDRINUSE
+# define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+# define ENETDOWN WSAENETDOWN
+# define ENETUNREACH WSAENETUNREACH
+# define ENETRESET WSAENETRESET
+# define ECONNABORTED WSAECONNABORTED
+# define ECONNRESET WSAECONNRESET
+# define ENOBUFS WSAENOBUFS
+# define EISCONN WSAEISCONN
+# define ENOTCONN WSAENOTCONN
+# define ESHUTDOWN WSAESHUTDOWN
+# define ETOOMANYREFS WSAETOOMANYREFS
+# define ETIMEDOUT WSAETIMEDOUT
+# define ECONNREFUSED WSAECONNREFUSED
+# define ELOOP WSAELOOP
+# define EHOSTDOWN WSAEHOSTDOWN
+# define EHOSTUNREACH WSAEHOSTUNREACH
+# define EPROCLIM WSAEPROCLIM
+# define EUSERS WSAEUSERS
+# define EDQUOT WSAEDQUOT
+# define ESTALE WSAESTALE
+# define EREMOTE WSAEREMOTE
+ // Grrr! ENAMETOOLONG and ENOTEMPTY are already defined by the horrible
+ // 'standard' library.
+ // #define ENAMETOOLONG WSAENAMETOOLONG
+# define EADDRINUSE WSAEADDRINUSE
+
+ // CE needs this...
+# if !defined (EPERM)
+# define EPERM ERROR_ACCESS_DENIED
+# endif
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_HAS_H_ERRNO)
+void herror (const char *str);
+#endif /* ACE_HAS_H_ERRNO */
+
+#if !defined (ACE_WIN32) && defined (ACE_LACKS_T_ERRNO)
+extern int t_errno;
+#endif /* ACE_WIN32 && ACE_LACKS_T_ERRNO */
+
+#if !defined (ENOSYS)
+# define ENOSYS EFAULT /* Operation not supported or unknown error. */
+#endif /* !ENOSYS */
+
+#if !defined (ENOTSUP)
+# define ENOTSUP ENOSYS /* Operation not supported. */
+#endif /* !ENOTSUP */
+
+#if !defined (ESUCCESS)
+# define ESUCCESS 0
+#endif /* !ESUCCESS */
+
+#if !defined (EIDRM)
+# define EIDRM 0
+#endif /* !EIDRM */
+
+#if !defined (ENFILE)
+# define ENFILE EMFILE /* No more socket descriptors are available. */
+#endif /* !ENFILE */
+
+#if !defined (ECOMM)
+ // Not the same, but ECONNABORTED is provided on NT.
+# define ECOMM ECONNABORTED
+#endif /* ECOMM */
+
+#if !defined (EDEADLK)
+# define EDEADLK 1000 /* Some large number.... */
+#endif /* !EDEADLK */
+
+#if !defined (ENXIO) /* Needed in SOCK_Dgram_Mcast */
+# define ENXIO 6
+#endif /* ENXIO */
+
+#if !defined (ETIMEDOUT) && defined (ETIME)
+# define ETIMEDOUT ETIME
+#endif /* ETIMEDOUT */
+
+#if !defined (ETIME) && defined (ETIMEDOUT)
+# define ETIME ETIMEDOUT
+#endif /* ETIMED */
+
+#if !defined (EBUSY)
+# define EBUSY ETIME
+#endif /* EBUSY */
+
+#if !defined (ECANCELED)
+# define ECANCELED 125
+#endif /* ECANCELED */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_ERRNO_H */
diff --git a/ACE/ace/os_include/os_fcntl.h b/ACE/ace/os_include/os_fcntl.h
new file mode 100644
index 00000000000..f86da548716
--- /dev/null
+++ b/ACE/ace/os_include/os_fcntl.h
@@ -0,0 +1,106 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_fcntl.h
+ *
+ * file control options
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_FCNTL_H
+#define ACE_OS_INCLUDE_OS_FCNTL_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/os_include/sys/os_stat.h"
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_FCNTL_H)
+# include /**/ <fcntl.h>
+#endif /* !ACE_LACKS_FCNTL_H */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x620)
+// for creat(), open()
+# include /**/ <ioLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (__BORLANDC__)
+# define _O_CREAT O_CREAT
+# define _O_EXCL O_EXCL
+# define _O_TRUNC O_TRUNC
+ // 0x0800 is used for O_APPEND. 0x08 looks free.
+# define _O_TEMPORARY 0x08 /* see fcntl.h */
+# define _O_RDWR O_RDWR
+# define _O_WRONLY O_WRONLY
+# define _O_RDONLY O_RDONLY
+# define _O_APPEND O_APPEND
+# define _O_BINARY O_BINARY
+# define _O_TEXT O_TEXT
+#endif /* __BORLANDC__ */
+
+#if defined (__DMC__)
+# define _O_TEMPORARY 0x08 /* see fcntl.h */
+#endif /* __DMC__ */
+
+// defined Win32 specific macros for UNIX platforms
+#if !defined (O_BINARY)
+# define O_BINARY 0
+#endif /* O_BINARY */
+#if !defined (_O_BINARY)
+# define _O_BINARY O_BINARY
+#endif /* _O_BINARY */
+#if !defined (O_TEXT)
+# define O_TEXT 0
+#endif /* O_TEXT */
+#if !defined (_O_TEXT)
+# define _O_TEXT O_TEXT
+#endif /* _O_TEXT */
+#if !defined (O_RAW)
+# define O_RAW 0
+#endif /* O_RAW */
+#if !defined (_O_RAW)
+# define _O_RAW O_RAW
+#endif /* _O_RAW */
+
+#if defined (ACE_WIN32)
+# define O_NDELAY 1
+#endif /* ACE_WIN32 */
+
+# if !defined (O_NONBLOCK)
+# define O_NONBLOCK 1
+# endif /* O_NONBLOCK */
+
+#if defined (ACE_HAS_POSIX_NONBLOCK)
+# define ACE_NONBLOCK O_NONBLOCK
+#else
+# define ACE_NONBLOCK O_NDELAY
+#endif /* ACE_HAS_POSIX_NONBLOCK */
+
+# if !defined (F_GETFL)
+# define F_GETFL 0
+# endif /* F_GETFL */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_FCNTL_H */
diff --git a/ACE/ace/os_include/os_fenv.h b/ACE/ace/os_include/os_fenv.h
new file mode 100644
index 00000000000..328acef9cfa
--- /dev/null
+++ b/ACE/ace/os_include/os_fenv.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_fenv.h
+ *
+ * floating-point environment
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_FENV_H
+#define ACE_OS_INCLUDE_OS_FENV_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_LACKS_FENV_H)
+# include /**/ <fenv.h>
+#endif /* !ACE_LACKS_FENV_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_FENV_H */
diff --git a/ACE/ace/os_include/os_float.h b/ACE/ace/os_include/os_float.h
new file mode 100644
index 00000000000..94cfb3dc5ef
--- /dev/null
+++ b/ACE/ace/os_include/os_float.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_float.h
+ *
+ * floating types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_FLOAT_H
+#define ACE_OS_INCLUDE_OS_FLOAT_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_FLOAT_H)
+# include /**/ <float.h>
+#endif /* !ACE_LACKS_FLOAT_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_FLOAT_H */
diff --git a/ACE/ace/os_include/os_fmtmsg.h b/ACE/ace/os_include/os_fmtmsg.h
new file mode 100644
index 00000000000..28ba9755b86
--- /dev/null
+++ b/ACE/ace/os_include/os_fmtmsg.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_fmtmsg.h
+ *
+ * message display structures
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_FMTMSG_H
+#define ACE_OS_INCLUDE_OS_FMTMSG_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_LACKS_FMTMSG_H)
+# include /**/ <fmtmsg.h>
+#endif /* !ACE_LACKS_FMTMSG_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_FMTMSG_H */
diff --git a/ACE/ace/os_include/os_fnmatch.h b/ACE/ace/os_include/os_fnmatch.h
new file mode 100644
index 00000000000..976e8332e0d
--- /dev/null
+++ b/ACE/ace/os_include/os_fnmatch.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_fnmatch.h
+ *
+ * filename-matching types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_FNMATCH_H
+#define ACE_OS_INCLUDE_OS_FNMATCH_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_LACKS_FNMATCH_H)
+# include /**/ <fnmatch.h>
+#endif /* !ACE_LACKS_FNMATCH_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_FNMATCH_H */
diff --git a/ACE/ace/os_include/os_ftw.h b/ACE/ace/os_include/os_ftw.h
new file mode 100644
index 00000000000..38bc8329956
--- /dev/null
+++ b/ACE/ace/os_include/os_ftw.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_ftw.h
+ *
+ * file tree traversal
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_FTW_H
+#define ACE_OS_INCLUDE_OS_FTW_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/os_include/sys/os_stat.h"
+
+#if !defined (ACE_LACKS_FTW_H)
+# include /**/ <ftw.h>
+#endif /* !ACE_LACKS_FTW_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_FTW_H */
diff --git a/ACE/ace/os_include/os_glob.h b/ACE/ace/os_include/os_glob.h
new file mode 100644
index 00000000000..f95019ec34b
--- /dev/null
+++ b/ACE/ace/os_include/os_glob.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_glob.h
+ *
+ * pathname pattern-matching types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_GLOB_H
+#define ACE_OS_INCLUDE_OS_GLOB_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_GLOB_H)
+# include /**/ <glob.h>
+#endif /* !ACE_LACKS_GLOB_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_GLOB_H */
diff --git a/ACE/ace/os_include/os_grp.h b/ACE/ace/os_include/os_grp.h
new file mode 100644
index 00000000000..e4d93a53ce1
--- /dev/null
+++ b/ACE/ace/os_include/os_grp.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_grp.h
+ *
+ * group structure
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_GRP_H
+#define ACE_OS_INCLUDE_OS_GRP_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/os_include/sys/os_types.h" // for gid_t
+
+#if !defined (ACE_LACKS_GRP_H)
+# include /**/ <grp.h>
+#endif /* !ACE_LACKS_GRP_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_GRP_H */
diff --git a/ACE/ace/os_include/os_iconv.h b/ACE/ace/os_include/os_iconv.h
new file mode 100644
index 00000000000..0dc6160e7d3
--- /dev/null
+++ b/ACE/ace/os_include/os_iconv.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_iconv.h
+ *
+ * codeset conversion facility
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_ICONV_H
+#define ACE_OS_INCLUDE_OS_ICONV_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_ICONV_H)
+# include /**/ <iconv.h>
+#endif /* !ACE_LACKS_ICONV_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_ICONV_H */
diff --git a/ACE/ace/os_include/os_intrin.h b/ACE/ace/os_include/os_intrin.h
new file mode 100644
index 00000000000..cc4d4237aba
--- /dev/null
+++ b/ACE/ace/os_include/os_intrin.h
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_intrin.h
+ *
+ * Intrinsic methods
+ *
+ * $Id$
+ *
+ * @author Johnny Willemsen <jwillemsen@remedy.nl>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_INTRIN_H
+#define ACE_OS_INCLUDE_OS_INTRIN_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_HAS_INTRIN_H)
+# include /**/ <intrin.h>
+#endif /* !ACE_HAS_INTRIN_H */
+
+#if defined (ACE_HAS_IA64INTRIN_H)
+# include /**/ <ia64intrin.h>
+#endif /* !ACE_HAS_IA64INTRIN_H */
+
+#if defined (ACE_HAS_IA32INTRIN_H)
+# include /**/ <ia32intrin.h>
+#endif /* !ACE_HAS_IA32INTRIN_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (_MSC_VER) && (_MSC_VER < 1400) && !(defined (__INTEL_COMPILER) && (__INTEL_COMPILER == 900))
+// See http://msdn2.microsoft.com/en-us/library/f24ya7ct(VS.71).aspx
+LONG __cdecl _InterlockedIncrement (LONG volatile *Addend);
+LONG __cdecl _InterlockedDecrement (LONG volatile *Addend);
+LONG __cdecl _InterlockedExchange (LONG volatile *Target, LONG Value);
+LONG __cdecl _InterlockedExchangeAdd (LONG volatile *Addend, LONG Value);
+#endif //_MSC_VER
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_INTRIN_H */
diff --git a/ACE/ace/os_include/os_inttypes.h b/ACE/ace/os_include/os_inttypes.h
new file mode 100644
index 00000000000..12ce23d9b8c
--- /dev/null
+++ b/ACE/ace/os_include/os_inttypes.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_inttypes.h
+ *
+ * fixed size integer types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_INTTYPES_H
+#define ACE_OS_INCLUDE_OS_INTTYPES_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_stdint.h"
+
+#if !defined (ACE_LACKS_INTTYPES_H)
+# include /**/ <inttypes.h>
+#endif /* !ACE_LACKS_INTTYPES_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+// @todo if needbe, we can define the macros if they aren't available.
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_INTTYPES_H */
diff --git a/ACE/ace/os_include/os_iso646.h b/ACE/ace/os_include/os_iso646.h
new file mode 100644
index 00000000000..59ed5e9a4cb
--- /dev/null
+++ b/ACE/ace/os_include/os_iso646.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_iso646.h
+ *
+ * alternative spellings
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_ISO646_H
+#define ACE_OS_INCLUDE_OS_ISO646_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_LACKS_ISO646_H)
+# include /**/ <iso646.h>
+#endif /* !ACE_LACKS_ISO646_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_ISO646_H */
diff --git a/ACE/ace/os_include/os_langinfo.h b/ACE/ace/os_include/os_langinfo.h
new file mode 100644
index 00000000000..01a2c00d78f
--- /dev/null
+++ b/ACE/ace/os_include/os_langinfo.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_langinfo.h
+ *
+ * language information constants
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystem.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_LANGINFO_H
+#define ACE_OS_INCLUDE_OS_LANGINFO_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/os_include/os_nl_types.h"
+
+#if !defined (ACE_LACKS_LANGINFO_H)
+# include /**/ <langinfo.h>
+#endif /* !ACE_LACKS_LANGINFO_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_LANGINFO_H */
diff --git a/ACE/ace/os_include/os_libgen.h b/ACE/ace/os_include/os_libgen.h
new file mode 100644
index 00000000000..146d939b135
--- /dev/null
+++ b/ACE/ace/os_include/os_libgen.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_libgen.h
+ *
+ * definitions for pattern matching functions
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_LIBGEN_H
+#define ACE_OS_INCLUDE_OS_LIBGEN_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_LACKS_LIBGEN_H)
+# include /**/ <libgen.h>
+#endif /* !ACE_LACKS_LIBGEN_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_LIBGEN_H */
diff --git a/ACE/ace/os_include/os_limits.h b/ACE/ace/os_include/os_limits.h
new file mode 100644
index 00000000000..a7f6e9e0fb2
--- /dev/null
+++ b/ACE/ace/os_include/os_limits.h
@@ -0,0 +1,143 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_limits.h
+ *
+ * implementation-defined constants
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_LIMITS_H
+#define ACE_OS_INCLUDE_OS_LIMITS_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_unistd.h"
+#include "ace/os_include/os_stdio.h" // for FILENAME_MAX on Windows
+
+#if !defined (ACE_LACKS_LIMITS_H)
+# include /**/ <limits.h>
+#endif /* !ACE_LACKS_LIMITS_H */
+
+#if !defined (ACE_LACKS_SYS_PARAM_H)
+# include /**/ <sys/param.h>
+#endif /* ACE_LACKS_SYS_PARAM_H */
+
+// On VxWorks 5.5.1 _POSIX_TIMER_MAX is defined in time.h
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x620)
+# include /**/ <time.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if ! defined (howmany)
+# define howmany(x, y) (((x)+((y)-1))/(y))
+#endif /* howmany */
+
+#if !defined (NAME_MAX)
+# if defined (MAXNAMLEN)
+# define NAME_MAX MAXNAMLEN
+# elif defined (MAXNAMELEN)
+# define NAME_MAX MAXNAMELEN
+# elif defined (FILENAME_MAX)
+# define NAME_MAX FILENAME_MAX
+# elif defined (_MAX_FNAME)
+# define NAME_MAX _MAX_FNAME
+# else /* _MAX_FNAME */
+# define NAME_MAX 256
+# endif /* MAXNAMLEN */
+#endif /* !NAME_MAX */
+
+#if !defined (MAXNAMELEN)
+# define MAXNAMELEN NAME_MAX
+#endif /* MAXNAMELEN */
+
+#if !defined (HOST_NAME_MAX)
+# define HOST_NAME_MAX 256
+#endif /* !HOST_NAME_MAX */
+
+// Note that we are using PATH_MAX instead of _POSIX_PATH_MAX, since
+// _POSIX_PATH_MAX is the *minimun* maximum value for PATH_MAX and is
+// defined by POSIX as 256.
+#if !defined (PATH_MAX)
+# if defined (_MAX_PATH)
+# define PATH_MAX _MAX_PATH
+# elif defined (MAX_PATH)
+# define PATH_MAX MAX_PATH
+# else /* !_MAX_PATH */
+# define PATH_MAX 1024
+# endif /* _MAX_PATH */
+#endif /* !PATH_MAX */
+
+// Leaving this for backward compatibility, but PATH_MAX should always be
+// used directly.
+#if !defined (MAXPATHLEN)
+# define MAXPATHLEN PATH_MAX
+#endif /* !MAXPATHLEN */
+
+// This is defined by XOPEN to be a minimum of 16. POSIX.1g
+// also defines this value. platform-specific config.h can
+// override this if need be.
+#if !defined (IOV_MAX)
+# define IOV_MAX 16
+#endif /* IOV_MAX */
+
+#if !defined (ACE_IOV_MAX)
+# define ACE_IOV_MAX IOV_MAX
+#endif /* ACE_IOV_MAX */
+
+#if defined (ACE_VXWORKS) && ((ACE_VXWORKS >= 0x620) && (ACE_VXWORKS <= 0x660)) && !defined (__RTP__)
+# if defined (PIPE_BUF) && (PIPE_BUF == -1)
+# undef PIPE_BUF
+# endif
+#endif /* ACE_VXWORKS */
+
+#if !defined (PIPE_BUF)
+# define PIPE_BUF 5120
+#endif /* PIPE_BUF */
+
+#if defined (ACE_HAS_POSIX_REALTIME_SIGNALS)
+ // = Giving unique ACE scoped names for some important
+ // RTSignal-Related constants. Becuase sometimes, different
+ // platforms use different names for these constants.
+
+ // Number of realtime signals provided in the system.
+ // _POSIX_RTSIG_MAX is the upper limit on the number of real time
+ // signals supported in a posix-4 compliant system.
+# if defined (_POSIX_RTSIG_MAX)
+# define ACE_RTSIG_MAX _POSIX_RTSIG_MAX
+# else /* not _POSIX_RTSIG_MAX */
+ // POSIX-4 compilant system has to provide atleast 8 RT signals.
+ // @@ Make sure the platform does *not* define this constant with
+ // some other name. If yes, use that instead of 8.
+# define ACE_RTSIG_MAX 8
+# endif /* _POSIX_RTSIG_MAX */
+#endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
+
+ // The maximum number of concurrent timers per process.
+# if !defined (_POSIX_TIMER_MAX)
+# define _POSIX_TIMER_MAX 44
+# endif /* _POSIX_TIMER_MAX */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_LIMITS_H */
diff --git a/ACE/ace/os_include/os_local.h b/ACE/ace/os_include/os_local.h
new file mode 100644
index 00000000000..84dcc067932
--- /dev/null
+++ b/ACE/ace/os_include/os_local.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_local.h
+ *
+ * category macros
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_LOCAL_H
+#define ACE_OS_INCLUDE_OS_LOCAL_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/os_include/os_stddef.h"
+
+#if !defined (ACE_LACKS_LOCAL_H)
+# include /**/ <local.h>
+#endif /* !ACE_LACKS_LOCAL_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_LOCAL_H */
diff --git a/ACE/ace/os_include/os_math.h b/ACE/ace/os_include/os_math.h
new file mode 100644
index 00000000000..ba6c6426d8a
--- /dev/null
+++ b/ACE/ace/os_include/os_math.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_math.h
+ *
+ * mathematical declarations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_MATH_H
+#define ACE_OS_INCLUDE_OS_MATH_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// FUZZ: disable check_for_math_include
+
+#if !defined (ACE_LACKS_MATH_H)
+# include /**/ <math.h>
+#endif /* !ACE_LACKS_MATH_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_MATH_H */
diff --git a/ACE/ace/os_include/os_monetary.h b/ACE/ace/os_include/os_monetary.h
new file mode 100644
index 00000000000..7c0c990d5ec
--- /dev/null
+++ b/ACE/ace/os_include/os_monetary.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_monetary.h
+ *
+ * monetary types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_MONETARY_H
+#define ACE_OS_INCLUDE_OS_MONETARY_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_MONETARY_H)
+# include /**/ <monetary.h>
+#endif /* !ACE_LACKS_MONETARY_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_MONETARY_H */
diff --git a/ACE/ace/os_include/os_mqueue.h b/ACE/ace/os_include/os_mqueue.h
new file mode 100644
index 00000000000..000aa714c5e
--- /dev/null
+++ b/ACE/ace/os_include/os_mqueue.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_mqueue.h
+ *
+ * message queues (REALTIME)
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_MQUEUE_H
+#define ACE_OS_INCLUDE_OS_MQUEUE_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/os_include/os_signal.h"
+
+#if !defined (ACE_LACKS_MQUEUE_H)
+# include /**/ <mqueue.h>
+#endif /* !ACE_LACKS_MQUEUE_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_MQUEUE_H */
diff --git a/ACE/ace/os_include/os_ndbm.h b/ACE/ace/os_include/os_ndbm.h
new file mode 100644
index 00000000000..c80594945e8
--- /dev/null
+++ b/ACE/ace/os_include/os_ndbm.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_ndbm.h
+ *
+ * definitions for ndbm database operations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_NDBM_H
+#define ACE_OS_INCLUDE_OS_NDBM_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_NDBM_H)
+# include /**/ <ndbm.h>
+#endif /* !ACE_LACKS_NDBM_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_NDBM_H */
diff --git a/ACE/ace/os_include/os_netdb.h b/ACE/ace/os_include/os_netdb.h
new file mode 100644
index 00000000000..e69a3c78cf0
--- /dev/null
+++ b/ACE/ace/os_include/os_netdb.h
@@ -0,0 +1,108 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_netdb.h
+ *
+ * definitions for network database operations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_NETDB_H
+#define ACE_OS_INCLUDE_OS_NETDB_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/os_include/netinet/os_in.h"
+#include "ace/os_include/os_limits.h"
+
+#if !defined (ACE_LACKS_NETDB_H)
+# if defined (ACE_HAS_STL_QUEUE_CONFLICT)
+# define queue _Queue_
+# endif /* ACE_HAS_STL_QUEUE_CONFLICT */
+ extern "C" {
+# include /**/ <netdb.h>
+ }
+# if defined (ACE_HAS_STL_QUEUE_CONFLICT)
+# undef queue
+# endif /* ACE_HAS_STL_QUEUE_CONFLICT */
+#endif /* !ACE_LACKS_NETDB_H */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x620)
+# include /**/ <hostLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_HOSTENT)
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+};
+#endif /* ACE_LACKS_HOSTENT */
+
+#if defined (ACE_LACKS_PROTOENT)
+struct protoent {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol # */
+};
+#endif /* ACE_LACKS_PROTOENT */
+
+#if defined (ACE_LACKS_SERVENT)
+struct servent {
+ char *s_name; /* official service name */
+ char **s_aliases; /* alias list */
+ int s_port; /* port # */
+ char *s_proto; /* protocol to use */
+};
+#endif /* ACE_LACKS_SERVENT */
+
+#if defined (ACE_HAS_STRUCT_NETDB_DATA)
+ typedef char ACE_HOSTENT_DATA[sizeof(struct hostent_data)];
+ typedef char ACE_SERVENT_DATA[sizeof(struct servent_data)];
+ typedef char ACE_PROTOENT_DATA[sizeof(struct protoent_data)];
+#else
+# if !defined ACE_HOSTENT_DATA_SIZE
+# define ACE_HOSTENT_DATA_SIZE (4*1024)
+# endif /*ACE_HOSTENT_DATA_SIZE */
+# if !defined ACE_SERVENT_DATA_SIZE
+# define ACE_SERVENT_DATA_SIZE (4*1024)
+# endif /*ACE_SERVENT_DATA_SIZE */
+# if !defined ACE_PROTOENT_DATA_SIZE
+# define ACE_PROTOENT_DATA_SIZE (2*1024)
+# endif /*ACE_PROTOENT_DATA_SIZE */
+ typedef char ACE_HOSTENT_DATA[ACE_HOSTENT_DATA_SIZE];
+ typedef char ACE_SERVENT_DATA[ACE_SERVENT_DATA_SIZE];
+ typedef char ACE_PROTOENT_DATA[ACE_PROTOENT_DATA_SIZE];
+#endif /* ACE_HAS_STRUCT_NETDB_DATA */
+
+# if !defined(MAXHOSTNAMELEN)
+# define MAXHOSTNAMELEN HOST_NAME_MAX
+# endif /* MAXHOSTNAMELEN */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_NETDB_H */
diff --git a/ACE/ace/os_include/os_nl_types.h b/ACE/ace/os_include/os_nl_types.h
new file mode 100644
index 00000000000..f1832882ea6
--- /dev/null
+++ b/ACE/ace/os_include/os_nl_types.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_nl_types.h
+ *
+ * data types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_NL_TYPES_H
+#define ACE_OS_INCLUDE_OS_NL_TYPES_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_LACKS_NL_TYPES_H)
+# include /**/ <nl_types.h>
+#endif /* !ACE_LACKS_nl_types_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_NL_TYPES_H */
diff --git a/ACE/ace/os_include/os_poll.h b/ACE/ace/os_include/os_poll.h
new file mode 100644
index 00000000000..2aa41a972ac
--- /dev/null
+++ b/ACE/ace/os_include/os_poll.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_poll.h
+ *
+ * definitions for the poll() function
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_POLL_H
+#define ACE_OS_INCLUDE_OS_POLL_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_LACKS_POLL_H)
+# include /**/ <poll.h>
+#endif /* !ACE_LACKS_POLL_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_POLL_H */
diff --git a/ACE/ace/os_include/os_pthread.h b/ACE/ace/os_include/os_pthread.h
new file mode 100644
index 00000000000..9ae6427079b
--- /dev/null
+++ b/ACE/ace/os_include/os_pthread.h
@@ -0,0 +1,424 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_pthread.h
+ *
+ * threads
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_PTHREAD_H
+#define ACE_OS_INCLUDE_OS_PTHREAD_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_HAS_PRIOCNTL)
+ // Need to #include thread.h before #defining THR_BOUND, etc.,
+ // when building without threads on SunOS 5.x.
+# if defined (sun)
+# include /**/ <thread.h>
+# endif /* sun */
+
+ // Need to #include these before #defining USYNC_PROCESS on SunOS 5.x.
+# include /**/ <sys/rtpriocntl.h>
+# include /**/ <sys/tspriocntl.h>
+#endif /* ACE_HAS_PRIOCNTL */
+
+#include "ace/os_include/sys/os_types.h"
+
+// This needs to go here *first* to avoid problems with AIX.
+# if defined (ACE_HAS_PTHREADS)
+# define ACE_DONT_INCLUDE_ACE_SIGNAL_H
+# include "ace/os_include/os_signal.h"
+# undef ACE_DONT_INCLUDE_ACE_SIGNAL_H
+# if defined (DIGITAL_UNIX)
+# define pthread_self __pthread_self
+extern "C" pthread_t pthread_self (void);
+# endif /* DIGITAL_UNIX */
+# endif /* ACE_HAS_PTHREADS */
+
+
+#if !defined (ACE_LACKS_PTHREAD_H)
+ extern "C" {
+# if defined (ACE_TANDEM_T1248_PTHREADS)
+# include /**/ <spthread.h>
+# else
+# include /**/ <pthread.h>
+# endif
+ }
+#endif /* !ACE_LACKS_PTHREAD_H */
+
+#if defined (ACE_HAS_PTHREAD_NP_H)
+// FreeBSD declares _np (non-portable) pthread extensions in <pthread_np.h>
+# include /**/ <pthread_np.h>
+#endif
+
+// @todo: need to reoganize to put includes at the top and the rest of the
+// code at the bottom. Also, move the classes out of this file.
+#if defined (ACE_HAS_PTHREADS)
+# define ACE_SCHED_OTHER SCHED_OTHER
+# define ACE_SCHED_FIFO SCHED_FIFO
+# define ACE_SCHED_RR SCHED_RR
+
+// Definitions for THREAD- and PROCESS-LEVEL priorities...some
+// implementations define these while others don't. In order to
+// further complicate matters, we don't redefine the default (*_DEF)
+// values if they've already been defined, which allows individual
+// programs to have their own ACE-wide "default".
+
+// PROCESS-level values
+# if (defined (_POSIX_PRIORITY_SCHEDULING) || defined (ACE_TANDEM_T1248_PTHREADS)) \
+ && !defined(_UNICOS) && !defined(UNIXWARE_7_1)
+# define ACE_PROC_PRI_FIFO_MIN (sched_get_priority_min(SCHED_FIFO))
+# define ACE_PROC_PRI_RR_MIN (sched_get_priority_min(SCHED_RR))
+# if defined (HPUX)
+ // HP-UX's other is the SCHED_HPUX class, which uses historical
+ // values that have reverse semantics from POSIX (low value is
+ // more important priority). To use these in pthreads calls,
+ // the values need to be converted. The other scheduling classes
+ // don't need this special treatment.
+# define ACE_PROC_PRI_OTHER_MIN \
+ (sched_get_priority_min(SCHED_OTHER))
+# else
+# define ACE_PROC_PRI_OTHER_MIN (sched_get_priority_min(SCHED_OTHER))
+# endif /* HPUX */
+# else /* UNICOS is missing a sched_get_priority_min() implementation,
+ SCO too */
+# define ACE_PROC_PRI_FIFO_MIN 0
+# define ACE_PROC_PRI_RR_MIN 0
+# define ACE_PROC_PRI_OTHER_MIN 0
+# endif
+
+# if defined (_POSIX_PRIORITY_SCHEDULING) && !defined(UNIXWARE_7_1)
+# define ACE_PROC_PRI_FIFO_MAX (sched_get_priority_max(SCHED_FIFO))
+# define ACE_PROC_PRI_RR_MAX (sched_get_priority_max(SCHED_RR))
+# if defined (HPUX)
+# define ACE_PROC_PRI_OTHER_MAX \
+ (sched_get_priority_max(SCHED_OTHER))
+# else
+# define ACE_PROC_PRI_OTHER_MAX (sched_get_priority_max(SCHED_OTHER))
+# endif /* HPUX */
+# else /* SCO missing sched_get_priority_max() implementation */
+# define ACE_PROC_PRI_FIFO_MAX 59
+# define ACE_PROC_PRI_RR_MAX 59
+# define ACE_PROC_PRI_OTHER_MAX 59
+# endif
+
+# if !defined(ACE_PROC_PRI_FIFO_DEF)
+# define ACE_PROC_PRI_FIFO_DEF (ACE_PROC_PRI_FIFO_MIN + (ACE_PROC_PRI_FIFO_MAX - ACE_PROC_PRI_FIFO_MIN)/2)
+# endif
+# if !defined(ACE_PROC_PRI_RR_DEF)
+# define ACE_PROC_PRI_RR_DEF (ACE_PROC_PRI_RR_MIN + (ACE_PROC_PRI_RR_MAX - ACE_PROC_PRI_RR_MIN)/2)
+# endif
+# if !defined(ACE_PROC_PRI_OTHER_DEF)
+# define ACE_PROC_PRI_OTHER_DEF (ACE_PROC_PRI_OTHER_MIN + (ACE_PROC_PRI_OTHER_MAX - ACE_PROC_PRI_OTHER_MIN)/2)
+# endif
+
+// THREAD-level values
+# if defined(PRI_FIFO_MIN) && defined(PRI_FIFO_MAX) && defined(PRI_RR_MIN) && defined(PRI_RR_MAX) && defined(PRI_OTHER_MIN) && defined(PRI_OTHER_MAX)
+# if !defined (ACE_THR_PRI_FIFO_MIN)
+# define ACE_THR_PRI_FIFO_MIN (long) PRI_FIFO_MIN
+# endif /* !ACE_THR_PRI_FIFO_MIN */
+# if !defined (ACE_THR_PRI_FIFO_MAX)
+# define ACE_THR_PRI_FIFO_MAX (long) PRI_FIFO_MAX
+# endif /* !ACE_THR_PRI_FIFO_MAX */
+# if !defined (ACE_THR_PRI_RR_MIN)
+# define ACE_THR_PRI_RR_MIN (long) PRI_RR_MIN
+# endif /* !ACE_THR_PRI_RR_MIN */
+# if !defined (ACE_THR_PRI_RR_MAX)
+# define ACE_THR_PRI_RR_MAX (long) PRI_RR_MAX
+# endif /* !ACE_THR_PRI_RR_MAX */
+# if !defined (ACE_THR_PRI_OTHER_MIN)
+# define ACE_THR_PRI_OTHER_MIN (long) PRI_OTHER_MIN
+# endif /* !ACE_THR_PRI_OTHER_MIN */
+# if !defined (ACE_THR_PRI_OTHER_MAX)
+# define ACE_THR_PRI_OTHER_MAX (long) PRI_OTHER_MAX
+# endif /* !ACE_THR_PRI_OTHER_MAX */
+# elif defined (AIX)
+ // AIX's priority range is 1 (low) to 127 (high). There aren't
+ // any preprocessor macros I can find. PRIORITY_MIN is for
+ // process priorities, as far as I can see, and does not apply
+ // to thread priority. The 1 to 127 range is from the
+ // pthread_attr_setschedparam man page (Steve Huston, 18-May-2001).
+# if !defined (ACE_THR_PRI_FIFO_MIN)
+# define ACE_THR_PRI_FIFO_MIN (long) 1
+# endif /* !ACE_THR_PRI_FIFO_MIN */
+# if !defined (ACE_THR_PRI_FIFO_MAX)
+# define ACE_THR_PRI_FIFO_MAX (long) 127
+# endif /* !ACE_THR_PRI_FIFO_MAX */
+# if !defined (ACE_THR_PRI_RR_MIN)
+# define ACE_THR_PRI_RR_MIN (long) 1
+# endif /* !ACE_THR_PRI_RR_MIN */
+# if !defined (ACE_THR_PRI_RR_MAX)
+# define ACE_THR_PRI_RR_MAX (long) 127
+# endif /* !ACE_THR_PRI_RR_MAX */
+# if !defined (ACE_THR_PRI_OTHER_MIN)
+# define ACE_THR_PRI_OTHER_MIN (long) 1
+# endif /* !ACE_THR_PRI_OTHER_MIN */
+# if !defined (ACE_THR_PRI_OTHER_MAX)
+# define ACE_THR_PRI_OTHER_MAX (long) 127
+# endif /* !ACE_THR_PRI_OTHER_MAX */
+# elif defined (sun)
+# if !defined (ACE_THR_PRI_FIFO_MIN)
+# define ACE_THR_PRI_FIFO_MIN (long) 0
+# endif /* !ACE_THR_PRI_FIFO_MIN */
+# if !defined (ACE_THR_PRI_FIFO_MAX)
+# define ACE_THR_PRI_FIFO_MAX (long) 59
+# endif /* !ACE_THR_PRI_FIFO_MAX */
+# if !defined (ACE_THR_PRI_RR_MIN)
+# define ACE_THR_PRI_RR_MIN (long) 0
+# endif /* !ACE_THR_PRI_RR_MIN */
+# if !defined (ACE_THR_PRI_RR_MAX)
+# define ACE_THR_PRI_RR_MAX (long) 59
+# endif /* !ACE_THR_PRI_RR_MAX */
+# if !defined (ACE_THR_PRI_OTHER_MIN)
+# define ACE_THR_PRI_OTHER_MIN (long) 0
+# endif /* !ACE_THR_PRI_OTHER_MIN */
+# if !defined (ACE_THR_PRI_OTHER_MAX)
+# define ACE_THR_PRI_OTHER_MAX (long) 127
+# endif /* !ACE_THR_PRI_OTHER_MAX */
+# else
+# if !defined (ACE_THR_PRI_FIFO_MIN)
+# define ACE_THR_PRI_FIFO_MIN (long) ACE_PROC_PRI_FIFO_MIN
+# endif /* !ACE_THR_PRI_FIFO_MIN */
+# if !defined (ACE_THR_PRI_FIFO_MAX)
+# define ACE_THR_PRI_FIFO_MAX (long) ACE_PROC_PRI_FIFO_MAX
+# endif /* !ACE_THR_PRI_FIFO_MAX */
+# if !defined (ACE_THR_PRI_RR_MIN)
+# define ACE_THR_PRI_RR_MIN (long) ACE_PROC_PRI_RR_MIN
+# endif /* !ACE_THR_PRI_RR_MIN */
+# if !defined (ACE_THR_PRI_RR_MAX)
+# define ACE_THR_PRI_RR_MAX (long) ACE_PROC_PRI_RR_MAX
+# endif /* !ACE_THR_PRI_RR_MAX */
+# if !defined (ACE_THR_PRI_OTHER_MIN)
+# define ACE_THR_PRI_OTHER_MIN (long) ACE_PROC_PRI_OTHER_MIN
+# endif /* !ACE_THR_PRI_OTHER_MIN */
+# if !defined (ACE_THR_PRI_OTHER_MAX)
+# define ACE_THR_PRI_OTHER_MAX (long) ACE_PROC_PRI_OTHER_MAX
+# endif /* !ACE_THR_PRI_OTHER_MAX */
+# endif
+# if !defined(ACE_THR_PRI_FIFO_DEF)
+# define ACE_THR_PRI_FIFO_DEF ((ACE_THR_PRI_FIFO_MIN + ACE_THR_PRI_FIFO_MAX)/2)
+# endif
+# if !defined(ACE_THR_PRI_RR_DEF)
+# define ACE_THR_PRI_RR_DEF ((ACE_THR_PRI_RR_MIN + ACE_THR_PRI_RR_MAX)/2)
+# endif
+# if !defined(ACE_THR_PRI_OTHER_DEF)
+# define ACE_THR_PRI_OTHER_DEF ((ACE_THR_PRI_OTHER_MIN + ACE_THR_PRI_OTHER_MAX)/2)
+# endif
+ // Typedefs to help compatibility with Windows NT and Pthreads.
+ typedef pthread_t ACE_hthread_t;
+ typedef pthread_t ACE_thread_t;
+
+ // native TSS key type
+ typedef pthread_key_t ACE_OS_thread_key_t;
+ // TSS key type to be used by application
+# if defined (ACE_HAS_TSS_EMULATION)
+ typedef u_int ACE_thread_key_t;
+# else /* ! ACE_HAS_TSS_EMULATION */
+ typedef ACE_OS_thread_key_t ACE_thread_key_t;
+# endif /* ! ACE_HAS_TSS_EMULATION */
+
+# if !defined (ACE_LACKS_COND_T)
+ typedef pthread_mutex_t ACE_mutex_t;
+ typedef pthread_cond_t ACE_cond_t;
+ typedef pthread_condattr_t ACE_condattr_t;
+ typedef pthread_mutexattr_t ACE_mutexattr_t;
+# endif /* ! ACE_LACKS_COND_T */
+ typedef pthread_mutex_t ACE_thread_mutex_t;
+
+# if !defined (PTHREAD_CANCEL_DISABLE)
+# define PTHREAD_CANCEL_DISABLE 0
+# endif /* PTHREAD_CANCEL_DISABLE */
+
+# if !defined (PTHREAD_CANCEL_ENABLE)
+# define PTHREAD_CANCEL_ENABLE 0
+# endif /* PTHREAD_CANCEL_ENABLE */
+
+# if !defined (PTHREAD_CANCEL_DEFERRED)
+# define PTHREAD_CANCEL_DEFERRED 0
+# endif /* PTHREAD_CANCEL_DEFERRED */
+
+# if !defined (PTHREAD_CANCEL_ASYNCHRONOUS)
+# define PTHREAD_CANCEL_ASYNCHRONOUS 0
+# endif /* PTHREAD_CANCEL_ASYNCHRONOUS */
+
+# define THR_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE
+# define THR_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE
+# define THR_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED
+# define THR_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS
+
+# if !defined (PTHREAD_CREATE_JOINABLE)
+# if defined (PTHREAD_CREATE_UNDETACHED)
+# define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
+# else
+# define PTHREAD_CREATE_JOINABLE 0
+# endif /* PTHREAD_CREATE_UNDETACHED */
+# endif /* PTHREAD_CREATE_JOINABLE */
+
+# if !defined (PTHREAD_CREATE_DETACHED)
+# define PTHREAD_CREATE_DETACHED 1
+# endif /* PTHREAD_CREATE_DETACHED */
+
+# if !defined (PTHREAD_PROCESS_PRIVATE) && !defined (ACE_HAS_PTHREAD_PROCESS_ENUM)
+# if defined (PTHREAD_MUTEXTYPE_FAST)
+# define PTHREAD_PROCESS_PRIVATE PTHREAD_MUTEXTYPE_FAST
+# else
+# define PTHREAD_PROCESS_PRIVATE 0
+# endif /* PTHREAD_MUTEXTYPE_FAST */
+# endif /* PTHREAD_PROCESS_PRIVATE */
+
+# if !defined (PTHREAD_PROCESS_SHARED) && !defined (ACE_HAS_PTHREAD_PROCESS_ENUM)
+# if defined (PTHREAD_MUTEXTYPE_FAST)
+# define PTHREAD_PROCESS_SHARED PTHREAD_MUTEXTYPE_FAST
+# else
+# define PTHREAD_PROCESS_SHARED 1
+# endif /* PTHREAD_MUTEXTYPE_FAST */
+# endif /* PTHREAD_PROCESS_SHARED */
+
+# if !defined (ACE_HAS_STHREADS)
+# if !defined (USYNC_THREAD)
+# define USYNC_THREAD PTHREAD_PROCESS_PRIVATE
+# endif /* ! USYNC_THREAD */
+# if !defined (USYNC_PROCESS)
+# define USYNC_PROCESS PTHREAD_PROCESS_SHARED
+# endif /* ! USYNC_PROCESS */
+# endif /* ACE_HAS_STHREADS */
+
+ /* MM-Graz: prevent warnings */
+# if !defined (UNIXWARE_7_1)
+# undef THR_BOUND
+# undef THR_NEW_LWP
+# undef THR_DETACHED
+# undef THR_SUSPENDED
+# undef THR_DAEMON
+
+# define THR_BOUND 0x00000001
+# define THR_NEW_LWP 0x00000002
+# define THR_DETACHED 0x00000040
+# define THR_SUSPENDED 0x00000080
+# define THR_DAEMON 0x00000100
+# define THR_SCHED_FIFO 0x00020000
+# define THR_SCHED_RR 0x00040000
+# define THR_SCHED_DEFAULT 0x00080000
+# endif /* UNIXWARE_7_1 */
+
+# define THR_JOINABLE 0x00010000
+
+# if defined (ACE_HAS_IRIX62_THREADS)
+# define THR_SCOPE_SYSTEM 0x00100000
+# else
+# define THR_SCOPE_SYSTEM THR_BOUND
+# endif /*ACE_HAS_IRIX62_THREADS*/
+
+# define THR_SCOPE_PROCESS 0x00200000
+# define THR_INHERIT_SCHED 0x00400000
+# define THR_EXPLICIT_SCHED 0x00800000
+# define THR_SCHED_IO 0x01000000
+
+# if !defined (ACE_HAS_STHREADS)
+# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_USES_FIFO_SEM)
+
+// This needs to be moved out of here.
+#include /**/ "ace/ACE_export.h"
+/**
+ * @class ACE_sema_t
+ *
+ * @brief This is used to implement semaphores for platforms that support
+ * POSIX pthreads, but do *not* support POSIX semaphores, i.e.,
+ * it's a different type than the POSIX <sem_t>.
+ */
+class ACE_Export ACE_sema_t
+{
+public:
+ /// Serialize access to internal state.
+ ACE_mutex_t lock_;
+
+ /// Block until there are no waiters.
+ ACE_cond_t count_nonzero_;
+
+ /// Count of the semaphore.
+ u_long count_;
+
+ /// Number of threads that have called <ACE_OS::sema_wait>.
+ u_long waiters_;
+};
+# endif /* !ACE_HAS_POSIX_SEM */
+
+# if defined (ACE_LACKS_PTHREAD_YIELD) && defined (ACE_HAS_THR_YIELD)
+ // If we are on Solaris we can just reuse the existing
+ // implementations of these synchronization types.
+# if !defined (ACE_LACKS_RWLOCK_T) && !defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+# include /**/ <synch.h>
+ typedef rwlock_t ACE_rwlock_t;
+# endif /* !ACE_LACKS_RWLOCK_T */
+# include /**/ <thread.h>
+# endif /* (ACE_LACKS_PTHREAD_YIELD) && defined (ACE_HAS_THR_YIELD) */
+
+# else
+# if !defined (ACE_HAS_POSIX_SEM)
+ typedef sema_t ACE_sema_t;
+# endif /* !ACE_HAS_POSIX_SEM */
+# endif /* !ACE_HAS_STHREADS */
+
+# if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+ typedef pthread_rwlock_t ACE_rwlock_t;
+# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
+
+# if defined (__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2))
+
+ // glibc 2.2.x or better has pthread_mutex_timedlock()
+# ifndef ACE_HAS_MUTEX_TIMEOUTS
+# define ACE_HAS_MUTEX_TIMEOUTS
+# endif /* ACE_HAS_MUTEX_TIMEOUTS */
+
+ // Use new pthread_attr_setstack if XPG6 support is enabled.
+# if defined (_XOPEN_SOURCE) && (_XOPEN_SOURCE - 0) < 600
+# define ACE_LACKS_PTHREAD_ATTR_SETSTACK
+# endif /* (_XOPEN_SOURCE - 0) < 600 */
+
+# if !defined (_XOPEN_SOURCE) \
+ || (defined (_XOPEN_SOURCE) && (_XOPEN_SOURCE - 0) < 600)
+ // pthread_mutex_timedlock() prototype is not visible if _XOPEN_SOURCE
+ // is not >= 600 (i.e. for XPG6).
+ extern "C" int pthread_mutex_timedlock (pthread_mutex_t *mutex,
+ const struct timespec * abstime);
+# endif /* _XOPEN_SOURCE && _XOPEN_SOURCE < 600 */
+
+# endif /* linux && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) */
+
+#elif defined (ACE_HAS_STHREADS)
+# if !defined (ACE_THR_PRI_FIFO_MIN)
+# define ACE_THR_PRI_FIFO_MIN (long) 0
+# endif /* !ACE_THR_PRI_FIFO_MIN */
+# if !defined (ACE_THR_PRI_FIFO_MAX)
+# define ACE_THR_PRI_FIFO_MAX (long) 59
+# endif /* !ACE_THR_PRI_FIFO_MAX */
+# if !defined (ACE_THR_PRI_RR_MIN)
+# define ACE_THR_PRI_RR_MIN (long) 0
+# endif /* !ACE_THR_PRI_RR_MIN */
+# if !defined (ACE_THR_PRI_RR_MAX)
+# define ACE_THR_PRI_RR_MAX (long) 59
+# endif /* !ACE_THR_PRI_RR_MAX */
+# if !defined (ACE_THR_PRI_OTHER_MIN)
+# define ACE_THR_PRI_OTHER_MIN (long) 0
+# endif /* !ACE_THR_PRI_OTHER_MIN */
+# if !defined (ACE_THR_PRI_OTHER_MAX)
+# define ACE_THR_PRI_OTHER_MAX (long) 127
+# endif /* !ACE_THR_PRI_OTHER_MAX */
+#endif /* ACE_HAS_PTHREADS */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_PTHREAD_H */
diff --git a/ACE/ace/os_include/os_pwd.h b/ACE/ace/os_include/os_pwd.h
new file mode 100644
index 00000000000..c5d591f2b7d
--- /dev/null
+++ b/ACE/ace/os_include/os_pwd.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_pwd.h
+ *
+ * password structure
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_PWD_H
+#define ACE_OS_INCLUDE_OS_PWD_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_PWD_H)
+# include /**/ <pwd.h>
+#endif /* !ACE_LACKS_PWD_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if !defined (ACE_WIN32)
+// VAC++ doesn't correctly grok the ::getpwnam_r - the function is redefined
+// in pwd.h, and that redefinition is used here
+# if defined (_AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
+ extern int _posix_getpwnam_r(const char *, struct passwd *, char *,
+ int, struct passwd **);
+# endif /* AIX and VAC++ 4 */
+#endif /* !ACE_WIN32 */
+
+#if defined (DIGITAL_UNIX)
+ extern int _Pgetpwnam_r (const char *, struct passwd *,
+ char *, size_t, struct passwd **);
+#endif /* DIGITAL_UNIX */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_PWD_H */
diff --git a/ACE/ace/os_include/os_regex.h b/ACE/ace/os_include/os_regex.h
new file mode 100644
index 00000000000..e6642dd943a
--- /dev/null
+++ b/ACE/ace/os_include/os_regex.h
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_regex.h
+ *
+ * regular expression matching types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_REGEX_H
+#define ACE_OS_INCLUDE_OS_REGEX_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_REGEX_H)
+# include /**/ <regex.h>
+#endif /* !ACE_LACKS_REGEX_H */
+
+#if defined (ACE_HAS_REGEX)
+# include /**/ <regexpr.h>
+#endif /* ACE_HAS_REGEX */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_REGEX_H */
diff --git a/ACE/ace/os_include/os_sched.h b/ACE/ace/os_include/os_sched.h
new file mode 100644
index 00000000000..e430a6f0fa1
--- /dev/null
+++ b/ACE/ace/os_include/os_sched.h
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_sched.h
+ *
+ * execution scheduling (REALTIME)
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_SCHED_H
+#define ACE_OS_INCLUDE_OS_SCHED_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/os_include/os_time.h"
+
+#if !defined (ACE_LACKS_SCHED_H)
+# include /**/ <sched.h>
+#endif /* !ACE_LACKS_SCHED_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if !defined (__cpu_set_t_defined) || !defined (ACE_HAS_CPU_SET_T)
+# define ACE_CPU_SETSIZE 1024
+ typedef struct
+ {
+ ACE_UINT32 bit_array_[ACE_CPU_SETSIZE / (8 * sizeof (ACE_UINT32))];
+ } cpu_set_t;
+#endif /* !ACE_HAS_CPU_SET_T || !__cpu_set_t_defined */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_SCHED_H */
diff --git a/ACE/ace/os_include/os_search.h b/ACE/ace/os_include/os_search.h
new file mode 100644
index 00000000000..f38efc58959
--- /dev/null
+++ b/ACE/ace/os_include/os_search.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_search.h
+ *
+ * search tables
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_SEARCH_H
+#define ACE_OS_INCLUDE_OS_SEARCH_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_SEARCH_H)
+# include /**/ <search.h>
+#endif /* !ACE_LACKS_SEARCH_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_SEARCH_H */
diff --git a/ACE/ace/os_include/os_semaphore.h b/ACE/ace/os_include/os_semaphore.h
new file mode 100644
index 00000000000..edf5532c6c5
--- /dev/null
+++ b/ACE/ace/os_include/os_semaphore.h
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_semaphore.h
+ *
+ * semaphores (REALTIME)
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_SEMAPHORE_H
+#define ACE_OS_INCLUDE_OS_SEMAPHORE_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/os_include/os_time.h"
+
+#if !defined (ACE_LACKS_SEMAPHORE_H)
+# include /**/ <semaphore.h>
+#endif /* !ACE_LACKS_SEMAPHORE_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_HAS_POSIX_SEM)
+# if !defined (SEM_FAILED) && !defined (ACE_LACKS_NAMED_POSIX_SEM)
+# define SEM_FAILED ((sem_t *) -1)
+# endif /* !SEM_FAILED */
+
+ typedef struct
+ {
+ /// Pointer to semaphore handle. This is allocated by ACE if we are
+ /// working with an unnamed POSIX semaphore or by the OS if we are
+ /// working with a named POSIX semaphore.
+ sem_t *sema_;
+
+ /// Name of the semaphore (if this is non-NULL then this is a named
+ /// POSIX semaphore, else its an unnamed POSIX semaphore).
+ char *name_;
+
+# if defined (ACE_LACKS_NAMED_POSIX_SEM)
+ /// this->sema_ doesn't always get created dynamically if a platform
+ /// doesn't support named posix semaphores. We use this flag to
+ /// remember if we need to delete <sema_> or not.
+ bool new_sema_;
+# endif /* ACE_LACKS_NAMED_POSIX_SEM */
+
+# if !defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
+ /// Serialize access to internal state.
+ ACE_mutex_t lock_;
+
+ /// Block until there are no waiters.
+ ACE_cond_t count_nonzero_;
+# endif /* !ACE_HAS_POSIX_SEM_TIMEOUT && !ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
+ } ACE_sema_t;
+#endif /* ACE_HAS_POSIX_SEM */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_SEMAPHORE_H */
diff --git a/ACE/ace/os_include/os_setjmp.h b/ACE/ace/os_include/os_setjmp.h
new file mode 100644
index 00000000000..ce6a20abccc
--- /dev/null
+++ b/ACE/ace/os_include/os_setjmp.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_setjmp.h
+ *
+ * stack environment declarations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_SETJMP_H
+#define ACE_OS_INCLUDE_OS_SETJMP_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_LACKS_SETJMP_H)
+# include /**/ <setjmp.h>
+#endif /* !ACE_LACKS_SETJMP_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_SETJMP_H */
diff --git a/ACE/ace/os_include/os_signal.h b/ACE/ace/os_include/os_signal.h
new file mode 100644
index 00000000000..c1a4511041c
--- /dev/null
+++ b/ACE/ace/os_include/os_signal.h
@@ -0,0 +1,253 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_signal.h
+ *
+ * signals
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_SIGNAL_H
+#define ACE_OS_INCLUDE_OS_SIGNAL_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_SIGNAL_H)
+ extern "C" {
+# include /**/ <signal.h>
+ }
+#endif /* !ACE_LACKS_SIGNAL_H */
+
+// This must come after signal.h is #included.
+#if defined (SCO)
+# define SIGIO SIGPOLL
+# include /**/ <sys/regset.h>
+#endif /* SCO */
+
+#if defined (ACE_HAS_SIGINFO_T)
+# if !defined (ACE_LACKS_SIGINFO_H)
+# if defined (__QNX__) || defined (__OpenBSD__) || defined (__INTERIX)
+# include /**/ <sys/siginfo.h>
+# else /* __QNX__ || __OpenBSD__ */
+# include /**/ <siginfo.h>
+# endif /* __QNX__ || __OpenBSD__ */
+# endif /* ACE_LACKS_SIGINFO_H */
+#endif /* ACE_HAS_SIGINFO_T */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x620) && !defined (__RTP__)
+# include /**/ <sigLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_SIGSET)
+ typedef u_int sigset_t;
+#endif /* ACE_LACKS_SIGSET */
+
+#if defined (ACE_HAS_SIG_MACROS)
+# undef sigemptyset
+# undef sigfillset
+# undef sigaddset
+# undef sigdelset
+# undef sigismember
+#endif /* ACE_HAS_SIG_MACROS */
+
+// This must come after signal.h is #included. It's to counteract
+// the sigemptyset and sigfillset #defines, which only happen
+// when __OPTIMIZE__ is #defined (really!) on Linux.
+#if defined (linux) && defined (__OPTIMIZE__)
+# undef sigemptyset
+# undef sigfillset
+#endif /* linux && __OPTIMIZE__ */
+
+#if !defined (ACE_HAS_SIG_ATOMIC_T)
+ typedef int sig_atomic_t;
+#endif /* !ACE_HAS_SIG_ATOMIC_T */
+
+# if !defined (SA_SIGINFO)
+# define SA_SIGINFO 0
+# endif /* SA_SIGINFO */
+
+# if !defined (SA_RESTART)
+# define SA_RESTART 0
+# endif /* SA_RESTART */
+
+#if !defined (SIGHUP)
+# define SIGHUP 0
+#endif /* SIGHUP */
+
+#if !defined (SIGINT)
+# define SIGINT 0
+#endif /* SIGINT */
+
+#if !defined (SIGSEGV)
+# define SIGSEGV 0
+#endif /* SIGSEGV */
+
+#if !defined (SIGIO)
+# define SIGIO 0
+#endif /* SIGSEGV */
+
+#if !defined (SIGUSR1)
+# define SIGUSR1 0
+#endif /* SIGUSR1 */
+
+#if !defined (SIGUSR2)
+# define SIGUSR2 0
+#endif /* SIGUSR2 */
+
+#if !defined (SIGCHLD)
+# define SIGCHLD 0
+#endif /* SIGCHLD */
+
+#if !defined (SIGCLD)
+# define SIGCLD SIGCHLD
+#endif /* SIGCLD */
+
+#if !defined (SIGQUIT)
+# define SIGQUIT 0
+#endif /* SIGQUIT */
+
+#if !defined (SIGPIPE)
+# define SIGPIPE 0
+#endif /* SIGPIPE */
+
+#if !defined (SIGALRM)
+# define SIGALRM 0
+#endif /* SIGALRM */
+
+#if !defined (SIG_DFL)
+# define SIG_DFL ((__sighandler_t) 0)
+#endif /* SIG_DFL */
+
+#if !defined (SIG_IGN)
+# define SIG_IGN ((__sighandler_t) 1) /* ignore signal */
+#endif /* SIG_IGN */
+
+#if !defined (SIG_ERR)
+# define SIG_ERR ((__sighandler_t) -1) /* error return from signal */
+#endif /* SIG_ERR */
+
+// These are used by the <ACE_IPC_SAP::enable> and
+// <ACE_IPC_SAP::disable> methods. They must be unique and cannot
+// conflict with the value of <ACE_NONBLOCK>. We make the numbers
+// negative here so they won't conflict with other values like SIGIO,
+// etc.
+# define ACE_SIGIO -1
+# define ACE_SIGURG -2
+# define ACE_CLOEXEC -3
+
+#if defined (ACE_VXWORKS)
+# define ACE_NSIG (_NSIGS + 1)
+#elif defined (__Lynx__) || defined (ACE_HAS_RTEMS)
+# define ACE_NSIG (NSIG + 1)
+#else
+ // All other platforms set NSIG to one greater than the
+ // highest-numbered signal.
+# define ACE_NSIG NSIG
+#endif /* __Lynx__ */
+
+#if defined (ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES)
+ // Prototypes for both signal() and struct sigaction are consistent..
+ typedef void (*ACE_SignalHandler)(int);
+ typedef void (*ACE_SignalHandlerV)(int);
+#elif defined (ACE_HAS_LYNXOS_SIGNALS) || defined (ACE_HAS_TANDEM_SIGNALS)
+ typedef void (*ACE_SignalHandler)(...);
+ typedef void (*ACE_SignalHandlerV)(...);
+#elif defined (ACE_HAS_SVR4_SIGNAL_T)
+ // SVR4 Signals are inconsistent (e.g., see struct sigaction)..
+ typedef void (*ACE_SignalHandler)(int);
+ typedef void (*ACE_SignalHandlerV)(void);
+#elif defined (ACE_WIN32)
+ typedef void (__cdecl *ACE_SignalHandler)(int);
+ typedef void (__cdecl *ACE_SignalHandlerV)(int);
+#elif defined (ACE_HAS_UNIXWARE_SVR4_SIGNAL_T)
+ typedef void (*ACE_SignalHandler)(int);
+ typedef void (*ACE_SignalHandlerV)(...);
+#elif defined (INTEGRITY)
+ typedef void (*ACE_SignalHandler)();
+ typedef void (*ACE_SignalHandlerV)(int);
+#elif defined (ACE_HAS_RTEMS)
+ typedef void (*ACE_SignalHandler)();
+ typedef void (*ACE_SignalHandlerV)();
+#else /* This is necessary for some older broken version of cfront */
+# if defined (SIG_PF)
+# define ACE_SignalHandler SIG_PF
+# else
+ typedef void (*ACE_SignalHandler)(int);
+# endif /* SIG_PF */
+ typedef void (*ACE_SignalHandlerV)(...);
+#endif /* ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES */
+
+#if defined (ACE_LACKS_SIGACTION)
+ struct sigaction
+ {
+ int sa_flags;
+ ACE_SignalHandlerV sa_handler;
+ sigset_t sa_mask;
+ };
+#endif /* ACE_LACKS_SIGACTION */
+
+// Defining POSIX4 real-time signal range.
+#if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
+# define ACE_SIGRTMIN SIGRTMIN
+# define ACE_SIGRTMAX SIGRTMAX
+#else /* !ACE_HAS_POSIX_REALTIME_SIGNALS */
+# ifndef ACE_SIGRTMIN
+# define ACE_SIGRTMIN 0
+# endif /* ACE_SIGRTMIN */
+# ifndef ACE_SIGRTMAX
+# define ACE_SIGRTMAX 0
+# endif /* ACE_SIGRTMAX */
+#endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
+
+#if defined (DIGITAL_UNIX)
+ // sigwait is yet another macro on Digital UNIX 4.0, just causing
+ // trouble when introducing member functions with the same name.
+ // Thanks to Thilo Kielmann" <kielmann@informatik.uni-siegen.de> for
+ // this fix.
+# if defined (__DECCXX_VER)
+# undef sigwait
+ // cxx on Digital Unix 4.0 needs this declaration. With it,
+ // <::_Psigwait> works with cxx -pthread. g++ does _not_ need
+ // it.
+ int _Psigwait __((const sigset_t *set, int *sig));
+# endif /* __DECCXX_VER */
+#elif !defined (ACE_HAS_SIGWAIT)
+# if defined(ACE_HAS_RTEMS)
+ int sigwait (const sigset_t *set, int *sig);
+# else
+ int sigwait (sigset_t *set);
+# endif /* ACE_HAS_RTEMS */
+#endif /* ! DIGITAL_UNIX && ! ACE_HAS_SIGWAIT */
+
+#if !defined (ACE_HAS_PTHREAD_SIGMASK_PROTOTYPE)
+ int pthread_sigmask(int, const sigset_t *, sigset_t *);
+#endif /*!ACE_HAS_PTHREAD_SIGMASK_PROTOTYPE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include "ace/os_include/os_ucontext.h"
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_SIGNAL_H */
diff --git a/ACE/ace/os_include/os_spawn.h b/ACE/ace/os_include/os_spawn.h
new file mode 100644
index 00000000000..879e49accd3
--- /dev/null
+++ b/ACE/ace/os_include/os_spawn.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_spawn.h
+ *
+ * spawn (ADVANCED REALTIME)
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_SPAWN_H
+#define ACE_OS_INCLUDE_OS_SPAWN_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/os_include/os_signal.h"
+#include "ace/os_include/sys/os_types.h"
+#include "ace/os_include/os_sched.h"
+
+#if !defined (ACE_LACKS_SPAWN_H)
+# include /**/ <spawn.h>
+#endif /* !ACE_LACKS_SPAWN_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_SPAWN_H */
diff --git a/ACE/ace/os_include/os_stdarg.h b/ACE/ace/os_include/os_stdarg.h
new file mode 100644
index 00000000000..66416bc480e
--- /dev/null
+++ b/ACE/ace/os_include/os_stdarg.h
@@ -0,0 +1,50 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_stdarg.h
+ *
+ * handle variable argument list
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_STDARG_H
+#define ACE_OS_INCLUDE_OS_STDARG_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_STDARG_H)
+# include /**/ <stdarg.h>
+#endif /* !ACE_LACKS_STDARG_H */
+
+#if !defined (va_copy)
+#if defined (__va_copy)
+#define va_copy(d, s) __va_copy((d),(s))
+#else
+#define va_copy(d, s) memcpy((void *)&(d),(void *)&(s),sizeof(va_list))
+#endif
+#endif
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STDARG_H */
diff --git a/ACE/ace/os_include/os_stdbool.h b/ACE/ace/os_include/os_stdbool.h
new file mode 100644
index 00000000000..a9fb79f2553
--- /dev/null
+++ b/ACE/ace/os_include/os_stdbool.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_stdbool.h
+ *
+ * boolean type and values
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_STDBOOL_H
+#define ACE_OS_INCLUDE_OS_STDBOOL_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_LACKS_STDBOOL_H)
+# include /**/ <stdbool.h>
+#endif /* !ACE_LACKS_STDBOOL_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STDBOOL_H */
diff --git a/ACE/ace/os_include/os_stddef.h b/ACE/ace/os_include/os_stddef.h
new file mode 100644
index 00000000000..1c047ac1983
--- /dev/null
+++ b/ACE/ace/os_include/os_stddef.h
@@ -0,0 +1,97 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_stddef.h
+ *
+ * standard type definitions
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+// From http://www.UNIX-systems.org/single_unix_specification/
+
+#ifndef ACE_OS_INCLUDE_OS_STDDEF_H
+#define ACE_OS_INCLUDE_OS_STDDEF_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_STDDEF_H)
+# include /**/ <stddef.h>
+#endif /* !ACE_LACKS_STDDEF_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+//FUZZ: disable check_for_NULL
+// NULL pointer constant
+#if defined (ACE_LACKS_NULL)
+# undef NULL
+# if defined(__cplusplus)
+# define NULL 0
+# else
+# define NULL ((void *)0)
+# endif
+#endif /* ACE_LACKS_NULL */
+//FUZZ: enable check_for_NULL
+
+/*
+ Integer constant expression of type size_t, the value of which is the offset
+ in bytes to the structure member (member-designator), from the beginning of
+ its structure (type).
+*/
+#if defined (ACE_LACKS_OFFSETOF)
+# undef offsetof
+# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif /* ACE_LACKS_OFFSETOF */
+
+// Signed integer type of the result of subtracting two pointers.
+#if defined (ACE_LACKS_PTRDIFF_T)
+# if !defined (ACE_PTRDIFF_T_TYPE)
+# define ACE_PTRDIFF_T_TYPE unsigned long
+# endif /* !ACE_PTRDIFF_T_TYPE */
+ typedef ACE_PTRDIFF_T_TYPE ptrdiff_t;
+#endif /* ACE_LACKS_PTRDIFF_T */
+
+/*
+ Integer type whose range of values can represent distinct wide-character
+ codes for all members of the largest character set specified among the
+ locales supported by the compilation environment: the null character has
+ the code value 0 and each member of the portable character set has a code
+ value equal to its value when used as the lone character in an integer
+ character constant.
+*/
+#if defined (ACE_LACKS_WCHAR_T)
+# if !defined (ACE_WCHAR_T_TYPE)
+# define ACE_WCHAR_T_TYPE long;
+# endif /* !ACE_WCHAR_T_TYPE */
+ typedef ACE_WCHAR_T_TYPE wchar_t;
+#endif /* ACE_LACKS_WCHAR_T */
+
+// Unsigned integer type of the result of the sizeof operator.
+#if defined (ACE_LACKS_SIZE_T)
+# if !defined (ACE_SIZE_T_TYPE)
+# define ACE_SIZE_T_TYPE unsigned int;
+# endif /* !ACE_SIZE_T_TYPE */
+ typedef ACE_SIZE_T_TYPE size_t;
+#endif /* ACE_LACKS_SIZE_T */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STDDEF_H */
diff --git a/ACE/ace/os_include/os_stdint.h b/ACE/ace/os_include/os_stdint.h
new file mode 100644
index 00000000000..97a6d4468d3
--- /dev/null
+++ b/ACE/ace/os_include/os_stdint.h
@@ -0,0 +1,141 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_stdint.h
+ *
+ * integer types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_STDINT_H
+#define ACE_OS_INCLUDE_OS_STDINT_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_STDINT_H)
+# include /**/ <stdint.h>
+#endif /* !ACE_LACKS_STDINT_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+// BSD style types
+#if defined (ACE_LACKS_SYS_TYPES_H) \
+ || (defined (__GLIBC__) && !defined (_BSD_SOURCE))
+ typedef unsigned char u_char;
+ typedef unsigned short u_short;
+ typedef unsigned int u_int;
+ typedef unsigned long u_long;
+
+ typedef unsigned char uchar_t;
+ typedef unsigned short ushort_t;
+ typedef unsigned int uint_t;
+ typedef unsigned long ulong_t;
+#endif /* ACE_LACKS_SYS_TYPES_H */
+
+/* Define required types if missing */
+
+#if defined (ACE_LACKS_INT8_T)
+# if !defined (ACE_INT8_T_TYPE)
+# define ACE_INT8_T_TYPE char
+# endif /* !ACE_INT8_T_TYPE */
+ typedef ACE_INT8_T_TYPE int8_t;
+#endif /* ACE_LACKS_INT8_T */
+
+#if defined (ACE_LACKS_UINT8_T)
+# if !defined (ACE_UINT8_T_TYPE)
+# define ACE_UINT8_T_TYPE unsigned char
+# endif /* !ACE_UINT8_T_TYPE */
+ typedef ACE_UINT8_T_TYPE int8_t;
+#endif /* ACE_LACKS_UINT8_T */
+
+#if defined (ACE_LACKS_INT16_T)
+# if !defined (ACE_INT16_T_TYPE)
+# define ACE_INT16_T_TYPE short
+# endif /* !ACE_INT16_T_TYPE */
+ typedef ACE_INT16_T_TYPE int16_t;
+#endif /* ACE_LACKS_INT16_T */
+
+#if defined (ACE_LACKS_UINT16_T)
+# if !defined (ACE_UINT16_T_TYPE)
+# define ACE_UINT16_T_TYPE unsigned short
+# endif /* !ACE_UINT16_T_TYPE */
+ typedef ACE_UINT16_T_TYPE int16_t;
+#endif /* ACE_LACKS_UINT16_T */
+
+#if defined (ACE_LACKS_INT32_T)
+# if !defined (ACE_INT32_T_TYPE)
+# define ACE_INT32_T_TYPE long
+# endif /* !ACE_INT32_T_TYPE */
+ typedef ACE_INT32_T_TYPE int32_t;
+#endif /* ACE_LACKS_INT32_T */
+
+#if defined (ACE_LACKS_UINT32_T)
+# if !defined (ACE_UINT32_T_TYPE)
+# define ACE_UINT32_T_TYPE unsigned long
+# endif /* !ACE_UINT32_T_TYPE */
+ typedef ACE_UINT32_T_TYPE int32_t;
+#endif /* ACE_LACKS_UIN32_T */
+
+// @todo pull in ACE class here
+// 64 bit will be a problem, but stub it out for now
+/*
+If an implementation provides integer types with width 64 that meet
+these requirements, then the following types are required: int64_t uint64_t
+
+In particular, this will be the case if any of the following are true:
+
+The implementation supports the _POSIX_V6_ILP32_OFFBIG programming
+environment and the application is being built in the
+_POSIX_V6_ILP32_OFFBIG programming environment (see the Shell and
+Utilities volume of IEEE Std 1003.1-2001, c99, Programming Environments).
+
+The implementation supports the _POSIX_V6_LP64_OFF64 programming
+environment and the application is being built in the
+_POSIX_V6_LP64_OFF64 programming environment.
+
+The implementation supports the _POSIX_V6_LPBIG_OFFBIG programming
+environment and the application is being built in the
+_POSIX_V6_LPBIG_OFFBIG programming environment.
+*/
+#if defined (ACE_LACKS_INT64_T)
+# if !defined (ACE_INT64_T_TYPE)
+# define ACE_INT64_T_TYPE long
+# endif /* !ACE_INT64_T_TYPE */
+ typedef ACE_INT64_T_TYPE int64_t;
+#endif /* ACE_LACKS_INT64_T */
+
+#if defined (ACE_LACKS_UINT64_T)
+# if !defined (ACE_UINT64_T_TYPE)
+# define ACE_UINT64_T_TYPE unsigned long
+# endif /* !ACE_UINT64_T_TYPE */
+ typedef ACE_UINT64_T_TYPE int64_t;
+#endif /* ACE_LACKS_UIN64_T */
+
+// @todo move the ACE_INT## typedefs here so that ACE_INT64 will
+// always be available.
+
+
+// @todo perhaps add macros
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STDINT_H */
diff --git a/ACE/ace/os_include/os_stdio.h b/ACE/ace/os_include/os_stdio.h
new file mode 100644
index 00000000000..ee0d779445b
--- /dev/null
+++ b/ACE/ace/os_include/os_stdio.h
@@ -0,0 +1,87 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_stdio.h
+ *
+ * standard buffered input/output
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_STDIO_H
+#define ACE_OS_INCLUDE_OS_STDIO_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// NOTE: stdarg.h must be #included before stdio.h on LynxOS.
+#include "ace/os_include/os_stdarg.h"
+#include "ace/os_include/os_stddef.h"
+
+#if !defined (ACE_LACKS_STDIO_H)
+# include /**/ <stdio.h>
+#endif /* !ACE_LACKS_STDIO_H */
+
+#if defined (ACE_VXWORKS)
+// for remove(), rename()
+# include /**/ <ioLib.h>
+// for remCurIdGet()
+# include /**/ <remLib.h>
+# if defined (__RTP__) && ((ACE_VXWORKS >= 0x620) && (ACE_VXWORKS <= 0x650))
+# define L_cuserid _PARM_L_cuserid
+# endif
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+# if defined (INTEGRITY)
+# define ACE_MAX_USERID 32
+# elif defined (ACE_WIN32)
+# define ACE_MAX_USERID 32
+# else
+# if defined (_POSIX_SOURCE) && defined (L_cuserid)
+# define ACE_MAX_USERID L_cuserid
+# else
+# define ACE_MAX_USERID 9
+# endif
+# endif /* INTEGRITY */
+
+#if defined (BUFSIZ)
+# define ACE_STREAMBUF_SIZE BUFSIZ
+#else
+# define ACE_STREAMBUF_SIZE 1024
+#endif /* BUFSIZ */
+
+#if defined (ACE_WIN32)
+ typedef OVERLAPPED ACE_OVERLAPPED;
+#else
+ struct ACE_OVERLAPPED
+ {
+ unsigned long Internal;
+ unsigned long InternalHigh;
+ unsigned long Offset;
+ unsigned long OffsetHigh;
+ ACE_HANDLE hEvent;
+ };
+#endif /* ACE_WIN32 */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STDIO_H */
diff --git a/ACE/ace/os_include/os_stdlib.h b/ACE/ace/os_include/os_stdlib.h
new file mode 100644
index 00000000000..a75dab5e35a
--- /dev/null
+++ b/ACE/ace/os_include/os_stdlib.h
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_stdlib.h
+ *
+ * standard library definitions
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_STDLIB_H
+#define ACE_OS_INCLUDE_OS_STDLIB_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_stddef.h"
+#include "ace/os_include/sys/os_wait.h"
+
+#if defined (ACE_HAS_ALLOCA_H)
+# include /**/ <alloca.h>
+#endif /* ACE_HAS_ALLOCA_H */
+
+#if !defined (ACE_LACKS_STDLIB_H)
+# include /**/ <stdlib.h>
+#endif /* !ACE_LACKS_STDLIB_H */
+
+#if defined (ACE_VXWORKS) && !defined (__RTP__)
+# include /**/ <envLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ typedef u_int ACE_RANDR_TYPE;
+#if defined (ACE_HAS_BROKEN_RANDR)
+ // The SunOS 5.4.X version of rand_r is inconsistent with the header
+ // files...
+ int rand_r (ACE_RANDR_TYPE seed);
+#else
+#endif /* ACE_HAS_BROKEN_RANDR */
+
+#if defined (DIGITAL_UNIX)
+ extern int _Prand_r (unsigned int *seedptr);
+#endif /* DIGITAL_UNIX */
+
+#if defined (ACE_LACKS_PUTENV_PROTOTYPE)
+ int putenv (char *);
+#endif /* ACE_LACKS_PUTENV_PROTOTYPE */
+
+#if defined (ACE_LACKS_MKTEMP_PROTOTYPE)
+ char *mktemp (char *);
+#endif /* ACE_LACKS_MKTEMP_PROTOTYPE */
+
+#if defined (ACE_LACKS_MKSTEMP_PROTOTYPE)
+ int mkstemp(char *);
+#endif /* ACE_LACKS_MKSTEMP_PROTOTYPE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STDLIB_H */
diff --git a/ACE/ace/os_include/os_string.h b/ACE/ace/os_include/os_string.h
new file mode 100644
index 00000000000..c2992a06d0e
--- /dev/null
+++ b/ACE/ace/os_include/os_string.h
@@ -0,0 +1,76 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_string.h
+ *
+ * string operations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_STRING_H
+#define ACE_OS_INCLUDE_OS_STRING_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/os_include/os_stddef.h"
+
+// Matthew Stevens 7-10-95 Fix GNU GCC 2.7 for memchr() problem.
+#if defined (ACE_HAS_GNU_CSTRING_H)
+// Define this file to keep /usr/include/memory.h from being included.
+# include /**/ <cstring>
+#else
+# if !defined (ACE_LACKS_MEMORY_H)
+# include /**/ <memory.h>
+# endif /* !ACE_LACKS_MEMORY_H */
+# if !defined (ACE_LACKS_STRING_H)
+# include /**/ <string.h>
+# endif /* !ACE_LACKS_STRING_H */
+#endif /* ACE_HAS_GNU_CSTRING_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ // this looks fishy... dhinton
+#if !defined (ACE_HAS_STRERROR)
+# if defined (ACE_HAS_SYS_ERRLIST)
+ extern char *sys_errlist[];
+# define strerror(err) sys_errlist[err]
+# else
+# define strerror(err) "strerror is unsupported"
+# endif /* ACE_HAS_SYS_ERRLIST */
+#endif /* !ACE_HAS_STRERROR */
+
+#if defined (ACE_LACKS_STRTOK_R_PROTOTYPE) && !defined (_POSIX_SOURCE)
+ char *strtok_r (char *s, const char *delim, char **save_ptr);
+#endif /* ACE_LACKS_STRTOK_R_PROTOTYPE */
+
+#if defined (ACE_LACKS_STRNLEN_PROTOTYPE)
+ size_t strnlen(const char *s, size_t maxlen);
+#endif /* ACE_LACKS_STRNLEN_PROTOTYPE */
+
+#if defined (__BORLANDC__) && (__BORLANDC__ < 0x560)
+# define _stricmp stricmp
+# define _strnicmp strnicmp
+#endif /* __BORLANDC__ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STRING_H */
diff --git a/ACE/ace/os_include/os_strings.h b/ACE/ace/os_include/os_strings.h
new file mode 100644
index 00000000000..21b99489b3b
--- /dev/null
+++ b/ACE/ace/os_include/os_strings.h
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_strings.h
+ *
+ * string operations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_STRINGS_H
+#define ACE_OS_INCLUDE_OS_STRINGS_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/os_include/os_stddef.h"
+
+#if !defined (ACE_LACKS_STRINGS_H)
+# include /**/ <strings.h>
+#endif /* !ACE_LACKS_STRINGS_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_STRCASECMP_PROTOTYPE)
+ int strcasecmp(const char *, const char *);
+#endif /* ACE_LACKS_STRCASECMP_PROTOTYPE */
+
+#if defined (ACE_LACKS_STRNCASECMP_PROTOTYPE)
+ int strncasecmp(const char *, const char *, size_t);
+#endif /* ACE_LACKS_STRNCASECMP_PROTOTYPE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STRINGS_H */
diff --git a/ACE/ace/os_include/os_stropts.h b/ACE/ace/os_include/os_stropts.h
new file mode 100644
index 00000000000..9d2429bebf6
--- /dev/null
+++ b/ACE/ace/os_include/os_stropts.h
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_stropts.h
+ *
+ * STREAMS interface (STREAMS)
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_STROPTS_H
+#define ACE_OS_INCLUDE_OS_STROPTS_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/os_include/os_unistd.h"
+
+#if defined (ACE_HAS_TIMOD_H)
+# if defined (ACE_HAS_STL_QUEUE_CONFLICT)
+# define queue _Queue_
+# endif /* ACE_HAS_STL_QUEUE_CONFLICT */
+# include /**/ <sys/timod.h>
+# if defined (ACE_HAS_STL_QUEUE_CONFLICT)
+# undef queue
+# endif /* ACE_HAS_STL_QUEUE_CONFLICT */
+#elif defined (ACE_HAS_OSF_TIMOD_H)
+# include /**/ <tli/timod.h>
+#endif /* ACE_HAS_TIMOD_H */
+
+#if !defined (ACE_LACKS_SYS_IOCTL_H)
+# include /**/ <sys/ioctl.h>
+#endif /* !ACE_LACKS_IOCTL_H */
+
+#if defined (ACE_HAS_SYS_FILIO_H)
+# include /**/ <sys/filio.h>
+#endif /* ACE_HAS_SYS_FILIO_H */
+
+#if defined (ACE_HAS_SYS_SOCKIO_H)
+# include /**/ <sys/sockio.h>
+#endif /* ACE_HAS_SOCKIO_H */
+
+// This is sorta counter intuitive, but this is how it was done in OS.h
+// @todo: fix this... dhinton
+#if defined (ACE_HAS_STREAMS)
+# if defined (AIX)
+# if !defined (_XOPEN_EXTENDED_SOURCE)
+# define _XOPEN_EXTENDED_SOURCE
+# endif /* !_XOPEN_EXTENDED_SOURCE */
+# endif /* AIX */
+#endif /* ACE_HAS_STREAMS */
+
+#if !defined (ACE_LACKS_STROPTS_H)
+# include /**/ <stropts.h>
+#endif /* !ACE_LACKS_STROPTS_H */
+
+// This is sorta counter intuitive, but this is how it was done in OS.h
+// @todo: fix this... dhinton
+#if defined (ACE_HAS_STREAMS)
+# if defined (AIX)
+# undef _XOPEN_EXTENDED_SOURCE
+# endif /* AIX */
+#endif /* ACE_HAS_STREAMS */
+
+#if defined (ACE_VXWORKS)
+// for ioctl()
+# include /**/ <ioLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_STRRECVFD)
+ struct strrecvfd {};
+#endif /* ACE_LACKS_STRRECVFD */
+
+# if !defined (SIOCGIFBRDADDR)
+# define SIOCGIFBRDADDR 0
+# endif /* SIOCGIFBRDADDR */
+
+# if !defined (SIOCGIFADDR)
+# define SIOCGIFADDR 0
+# endif /* SIOCGIFADDR */
+
+# if !defined (ACE_HAS_STRBUF_T)
+struct strbuf
+{
+ /// No. of bytes in buffer.
+ int maxlen;
+ /// No. of bytes returned.
+ int len;
+ /// Pointer to data.
+ void *buf;
+};
+# endif /* ACE_HAS_STRBUF_T */
+
+// These prototypes are chronically lacking from many versions of UNIX.
+#if !defined (ACE_WIN32) && !defined (ACE_HAS_ISASTREAM_PROTOTYPE)
+ int isastream (int);
+#endif /* !ACE_WIN32 && ACE_HAS_ISASTREAM_PROTOTYPE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_STROPTS_H */
diff --git a/ACE/ace/os_include/os_syslog.h b/ACE/ace/os_include/os_syslog.h
new file mode 100644
index 00000000000..f471c61acb0
--- /dev/null
+++ b/ACE/ace/os_include/os_syslog.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_syslog.h
+ *
+ * definitions for system error logging
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_SYSLOG_H
+#define ACE_OS_INCLUDE_OS_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_LACKS_SYSLOG_H)
+# include /**/ <syslog.h>
+#endif /* !ACE_LACKS_SYSLOG_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_SYSLOG_H */
diff --git a/ACE/ace/os_include/os_tar.h b/ACE/ace/os_include/os_tar.h
new file mode 100644
index 00000000000..e24a55f87b7
--- /dev/null
+++ b/ACE/ace/os_include/os_tar.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_tar.h
+ *
+ * extended tar definitions
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_TAR_H
+#define ACE_OS_INCLUDE_OS_TAR_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_LACKS_TAR_H)
+# include /**/ <tar.h>
+#endif /* !ACE_LACKS_TAR_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_TAR_H */
diff --git a/ACE/ace/os_include/os_termios.h b/ACE/ace/os_include/os_termios.h
new file mode 100644
index 00000000000..23d04c177f0
--- /dev/null
+++ b/ACE/ace/os_include/os_termios.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_termios.h
+ *
+ * define values for termios
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_TERMIOS_H
+#define ACE_OS_INCLUDE_OS_TERMIOS_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_LACKS_TERMIOS_H)
+# include /**/ <termios.h>
+#endif /* !ACE_LACKS_TERMIOS_H */
+
+#if defined (HPUX)
+# include /**/ <sys/modem.h>
+#endif /* HPUX */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_TERMIOS_H */
diff --git a/ACE/ace/os_include/os_tgmath.h b/ACE/ace/os_include/os_tgmath.h
new file mode 100644
index 00000000000..97f177be672
--- /dev/null
+++ b/ACE/ace/os_include/os_tgmath.h
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_tgmath.h
+ *
+ * type-generic macros
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_TGMATH_H
+#define ACE_OS_INCLUDE_OS_TGMATH_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/os_include/os_math.h"
+#include "ace/os_include/os_complex.h"
+
+#if !defined (ACE_LACKS_TGMATH_H)
+# include /**/ <tgmath.h>
+#endif /* !ACE_LACKS_TGMATH_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_TGMATH_H */
diff --git a/ACE/ace/os_include/os_time.h b/ACE/ace/os_include/os_time.h
new file mode 100644
index 00000000000..6d03b2f6e82
--- /dev/null
+++ b/ACE/ace/os_include/os_time.h
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_time.h
+ *
+ * time types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_TIME_H
+#define ACE_OS_INCLUDE_OS_TIME_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// @todo should we include anything from signal.h?
+#include "ace/os_include/sys/os_types.h"
+
+// To get the proper select() signature, this is required for HP-UX, and
+// maybe other platforms that offer both int and fdset forms of select().
+// For HP-UX, sys/time.h must be included before time.h, or
+// _XOPEN_SOURCE_EXTENDED must be defined. It's not nice to require
+// the preprocessor macro, so we force our select() preference this way.
+#if !defined (ACE_LACKS_SYS_TIME_H)
+# include /**/ <sys/time.h>
+#endif /* !ACE_LACKS_SYS_TIME_H */
+
+#if !defined (ACE_LACKS_TIME_H)
+# include /**/ <time.h>
+#endif /* !ACE_LACKS_TIME_H */
+
+# if defined (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB) && \
+ (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB != 0)
+using std::tm;
+# if !defined (ACE_HAS_DINKUM_STL)
+# if defined (ACE_WIN32)
+using std::_timezone;
+# else
+using std::timezone;
+# endif
+# endif
+using std::difftime;
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDC_LIB */
+
+# if !defined (ACE_HAS_POSIX_TIME)
+// Definition per POSIX.
+typedef struct timespec
+{
+ /// Seconds
+ time_t tv_sec;
+ /// Nanoseconds
+ long tv_nsec;
+} timespec_t;
+# elif defined (ACE_HAS_BROKEN_POSIX_TIME)
+# if defined (ACE_OPENVMS)
+# include /**/ <timers.h>
+# else
+// OSF/1 defines struct timespec in <sys/timers.h> - Tom Marrs
+# include /**/ <sys/timers.h>
+# endif
+# endif /* !ACE_HAS_POSIX_TIME */
+
+# if defined(ACE_LACKS_TIMESPEC_T)
+typedef struct timespec timespec_t;
+# endif /* ACE_LACKS_TIMESPEC_T */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_HAS_BROKEN_CTIME)
+# undef ctime
+#endif /* ACE_HAS_BROKEN_CTIME */
+
+// There are a lot of threads-related macro definitions in the config files.
+// They came in at different times and from different places and platform
+// requirements as threads evolved. They are probably not all needed - some
+// overlap or are otherwise confused. This is an attempt to start
+// straightening them out.
+#if defined (ACE_HAS_PTHREADS) /* POSIX.1c threads (pthreads) */
+ // ... and 2-parameter asctime_r and ctime_r
+# if !defined (ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R) && \
+ !defined (ACE_HAS_STHREADS) && !defined (ACE_VXWORKS)
+# define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R
+# endif
+#endif /* ACE_HAS_PTHREADS */
+
+#if defined (ACE_LACKS_STRPTIME_PROTOTYPE) && !defined (_XOPEN_SOURCE)
+ extern char *strptime (const char *s, const char *fmt, struct tm *tp);
+#endif /* ACE_LACKS_STRPTIME_PROTOTYPE */
+
+#if defined (ACE_LACKS_CONST_TIMESPEC_PTR)
+typedef struct timespec * ACE_TIMESPEC_PTR;
+#else
+typedef const struct timespec * ACE_TIMESPEC_PTR;
+#endif /* ACE_LACKS_CONST_TIMESPEC_PTR */
+
+#if defined (DIGITAL_UNIX)
+ extern char *_Pctime_r (const time_t *, char *);
+ extern struct tm *_Plocaltime_r (const time_t *, struct tm *);
+ extern struct tm *_Pgmtime_r (const time_t *, struct tm *);
+ extern char *_Pasctime_r (const struct tm *, char *);
+#endif /* DIGITAL_UNIX */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_TIME_H */
diff --git a/ACE/ace/os_include/os_trace.h b/ACE/ace/os_include/os_trace.h
new file mode 100644
index 00000000000..b08db2d5548
--- /dev/null
+++ b/ACE/ace/os_include/os_trace.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_trace.h
+ *
+ * tracing
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_TRACE_H
+#define ACE_OS_INCLUDE_OS_TRACE_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_TRACE_H)
+# include /**/ <trace.h>
+#endif /* !ACE_LACKS_TRACE_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_TRACE_H */
diff --git a/ACE/ace/os_include/os_ucontext.h b/ACE/ace/os_include/os_ucontext.h
new file mode 100644
index 00000000000..dd4b5001ba9
--- /dev/null
+++ b/ACE/ace/os_include/os_ucontext.h
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_ucontext.h
+ *
+ * user context
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_UCONTEXT_H
+#define ACE_OS_INCLUDE_OS_UCONTEXT_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_signal.h"
+
+#if !defined (ACE_LACKS_UCONTEXT_H)
+# include /**/ <ucontext.h>
+#endif /* !ACE_LACKS_ucontext_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+# if !defined (ACE_HAS_UCONTEXT_T)
+typedef int ucontext_t;
+# endif /* ACE_HAS_UCONTEXT_T */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_UCONTEXT_H */
diff --git a/ACE/ace/os_include/os_ulimit.h b/ACE/ace/os_include/os_ulimit.h
new file mode 100644
index 00000000000..450b6578c86
--- /dev/null
+++ b/ACE/ace/os_include/os_ulimit.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_ulimit.h
+ *
+ * ulimit commands
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_ULIMIT_H
+#define ACE_OS_INCLUDE_OS_ULIMIT_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_LACKS_ULIMIT_H)
+# include /**/ <ulimit.h>
+#endif /* !ACE_LACKS_ULIMIT_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_ULIMIT_H */
diff --git a/ACE/ace/os_include/os_unistd.h b/ACE/ace/os_include/os_unistd.h
new file mode 100644
index 00000000000..dc78271ce82
--- /dev/null
+++ b/ACE/ace/os_include/os_unistd.h
@@ -0,0 +1,203 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_unistd.h
+ *
+ * standard symbolic constants and types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_UNISTD_H
+#define ACE_OS_INCLUDE_OS_UNISTD_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+#include "ace/os_include/os_inttypes.h"
+
+#if defined (__BORLANDC__)
+# include "ace/os_include/os_fcntl.h"
+#endif /* __BORLANDC */
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+# include /**/ <process.h>
+# include /**/ <io.h>
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+
+#if defined (ACE_HAS_SYSINFO)
+# include /**/ <sys/systeminfo.h>
+#endif /* ACE_HAS_SYS_INFO */
+
+#if !defined (ACE_LACKS_UNISTD_H)
+# include /**/ <unistd.h>
+#endif /* !ACE_LACKS_UNISTD_H */
+
+#if defined (ACE_VXWORKS)
+# if !defined (__RTP__)
+ // for unlink(), close(), read(), write(), lseek(), chdir(), getcwd(),
+ // getwd(), and isatty()
+ # include /**/ <ioLib.h>
+# endif
+// for gethostname()
+# include /**/ <hostLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_WIN32)
+// The following are #defines and #includes that are specific to
+// WIN32.
+# if defined (ACE_HAS_WINCE)
+# define ACE_STDIN _fileno (stdin)
+# define ACE_STDOUT _fileno (stdout)
+# define ACE_STDERR _fileno (stderr)
+# else
+# define ACE_STDIN GetStdHandle (STD_INPUT_HANDLE)
+# define ACE_STDOUT GetStdHandle (STD_OUTPUT_HANDLE)
+# define ACE_STDERR GetStdHandle (STD_ERROR_HANDLE)
+# endif // ACE_HAS_WINCE
+// The following are #defines and #includes that are specific to UNIX.
+#else /* !ACE_WIN32 */
+# if defined (STDIN_FILENO)
+# define ACE_STDIN STDIN_FILENO
+# else
+# define ACE_STDIN 0
+# endif
+# if defined (STDOUT_FILENO)
+# define ACE_STDOUT STDOUT_FILENO
+# else
+# define ACE_STDOUT 1
+# endif
+# if defined (STDERR_FILENO)
+# define ACE_STDERR STDERR_FILENO
+# else
+# define ACE_STDERR 2
+# endif
+#endif /* ACE_WIN32 */
+
+#if (!defined (_BSD_SOURCE) && \
+ !defined (_XOPEN_SOURCE) && !defined (_XOPEN_SOURCE_EXTENDED)) \
+ || (defined (_XOPEN_SOURCE) && defined (__GNUC__))
+
+# if defined (ACE_LACKS_SETREUID_PROTOTYPE)
+ extern int setreuid (uid_t ruid, uid_t euid);
+# endif /* ACE_LACKS_SETREUID_PROTOTYPE */
+
+# if defined (ACE_LACKS_SETREGID_PROTOTYPE)
+ extern int setregid (gid_t rgid, gid_t egid);
+# endif /* ACE_LACKS_SETREGID_PROTOTYPE */
+#endif /* !_BSD_SOURCE && !_XOPEN_SOURCE && !_XOPEN_SOURCE_EXTENDED
+ || _XOPEN_SOURCE && __GNUC__ */
+
+ // for use by access()
+# if !defined (R_OK)
+# define R_OK 04 /* Test for Read permission. */
+# endif /* R_OK */
+
+# if !defined (W_OK)
+# define W_OK 02 /* Test for Write permission. */
+# endif /* W_OK */
+
+# if !defined (X_OK)
+# if defined (ACE_WIN32)
+ /* Windows has no test for X_OK - use R_OK instead */
+# define X_OK R_OK /* Test for eXecute permission. */
+# else /* ACE_WIN32 */
+# define X_OK 01 /* Test for eXecute permission. */
+# endif /* ACE_WIN32 */
+# endif /* X_OK */
+
+# if !defined (F_OK)
+# define F_OK 0 /* Test for existence of File. */
+# endif /* F_OK */
+
+#if defined (ACE_LACKS_UALARM_PROTOTYPE)
+ u_int ualarm (u_int usecs, u_int interval);
+#endif /* ACE_LACKS_UALARM_PROTOTYPE */
+
+#if defined (ACE_LACKS_PREAD_PROTOTYPE) && (_XOPEN_SOURCE - 0) < 500
+ // _XOPEN_SOURCE == 500 Single Unix conformance
+ // It seems that _XOPEN_SOURCE == 500 means that the prototypes are
+ // already defined in the system headers.
+ ssize_t pread (int fd,
+ void *buf,
+ size_t nbytes,
+ ACE_OFF_T offset);
+
+ ssize_t pwrite (int fd,
+ const void *buf,
+ size_t n,
+ ACE_OFF_T offset);
+#endif /* ACE_LACKS_PREAD_PROTOTYPE && (_XOPEN_SOURCE - 0) < 500 */
+
+#if defined (ACE_LACKS_GETPGID_PROTOTYPE) && \
+ !defined (_XOPEN_SOURCE) && !defined (_XOPEN_SOURCE_EXTENDED)
+ pid_t getpgid (pid_t pid);
+#endif /* ACE_LACKS_GETPGID_PROTOTYPE &&
+ !_XOPEN_SOURCE && !_XOPEN_SOURCE_EXTENDED */
+
+#if !defined (_LARGEFILE64_SOURCE)
+# if defined (ACE_LACKS_LSEEK64_PROTOTYPE) && \
+ defined (ACE_LACKS_LLSEEK_PROTOTYPE)
+# error Define either ACE_LACKS_LSEEK64_PROTOTYPE or ACE_LACKS_LLSEEK_PROTOTYPE, not both!
+# elif defined (ACE_LACKS_LSEEK64_PROTOTYPE)
+ ACE_LOFF_T lseek64 (int fd, ACE_LOFF_T offset, int whence);
+# elif defined (ACE_LACKS_LLSEEK_PROTOTYPE)
+ ACE_LOFF_T llseek (int fd, ACE_LOFF_T offset, int whence);
+# endif
+#endif /* _LARGEFILE64_SOURCE */
+
+#if defined (__BORLANDC__)
+# if (__BORLANDC__ <= 0x540)
+# define _getcwd getcwd
+# define _chdir chdir
+# undef _access
+# define _access access
+# endif
+# define _isatty isatty
+#endif /* __BORLANDC__ */
+
+# if defined (ACE_LACKS_TIMEDWAIT_PROTOTYPES)
+
+ ssize_t read_timedwait (ACE_HANDLE handle,
+ char *buf,
+ size_t n,
+ struct timespec *timeout);
+
+ ssize_t write_timedwait (ACE_HANDLE handle,
+ const void *buf,
+ size_t n,
+ struct timespec *timeout);
+
+# endif /* ACE_LACKS_TIMEDWAIT_PROTOTYPES */
+
+#if defined (ACE_LACKS_SWAB_PROTOTYPE)
+ void swab(const void *, void *, ssize_t);
+#endif /* ACE_LACKS_SWAB_PROTOTYPE */
+
+#if defined (ACE_LACKS_GETOPT_PROTOTYPE)
+ int getopt(int, char * const [], const char *);
+#endif /* ACE_LACKS_GETOPT_PROTOTYPE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_UNISTD_H */
diff --git a/ACE/ace/os_include/os_utime.h b/ACE/ace/os_include/os_utime.h
new file mode 100644
index 00000000000..a2eabeabbfa
--- /dev/null
+++ b/ACE/ace/os_include/os_utime.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_utime.h
+ *
+ * access and modification times structure
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_UTIME_H
+#define ACE_OS_INCLUDE_OS_UTIME_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/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_UTIME_H)
+# include /**/ <utime.h>
+#endif /* !ACE_LACKS_UTIME_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_UTIME_H */
diff --git a/ACE/ace/os_include/os_utmpx.h b/ACE/ace/os_include/os_utmpx.h
new file mode 100644
index 00000000000..74705d633ea
--- /dev/null
+++ b/ACE/ace/os_include/os_utmpx.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_utmpx.h
+ *
+ * user accounting database definitions
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_UTMPX_H
+#define ACE_OS_INCLUDE_OS_UTMPX_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/os_include/sys/os_time.h"
+
+#if !defined (ACE_LACKS_UTMPX_H)
+# include /**/ <utmpx.h>
+#endif /* !ACE_LACKS_UTMPX_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_UTMPX_H */
diff --git a/ACE/ace/os_include/os_wchar.h b/ACE/ace/os_include/os_wchar.h
new file mode 100644
index 00000000000..c0d1efa7aba
--- /dev/null
+++ b/ACE/ace/os_include/os_wchar.h
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_wchar.h
+ *
+ * wide-character handling
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_WCHAR_H
+#define ACE_OS_INCLUDE_OS_WCHAR_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// ctype.h, string.h, stdarg.h, stdio.h, stdlib.h, time.h
+#include "ace/os_include/os_stdio.h"
+#include "ace/os_include/os_stdlib.h"
+#include "ace/os_include/os_time.h"
+#include "ace/os_include/os_string.h"
+#include "ace/os_include/os_ctype.h"
+
+#if !defined (ACE_LACKS_WCHAR_H)
+# include /**/ <wchar.h>
+#endif /* !ACE_LACKS_WCHAR_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_WCHAR_H */
diff --git a/ACE/ace/os_include/os_wctype.h b/ACE/ace/os_include/os_wctype.h
new file mode 100644
index 00000000000..7b30377277a
--- /dev/null
+++ b/ACE/ace/os_include/os_wctype.h
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_wctype.h
+ *
+ * wide-character classification and mapping utilities
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_WCTYPE_H
+#define ACE_OS_INCLUDE_OS_WCTYPE_H
+
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// ctype.h, string.h, stdarg.h, stdio.h, stdlib.h, time.h
+#include "ace/os_include/os_wchar.h"
+
+#if !defined (ACE_LACKS_WCTYPE_H)
+# include /**/ <wctype.h>
+#endif /* !ACE_LACKS_WCTYPE_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_WCTYPE_H */
diff --git a/ACE/ace/os_include/os_wordexp.h b/ACE/ace/os_include/os_wordexp.h
new file mode 100644
index 00000000000..3d103edef56
--- /dev/null
+++ b/ACE/ace/os_include/os_wordexp.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_wordexp.h
+ *
+ * word-expansion types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_OS_WORDEXP_H
+#define ACE_OS_INCLUDE_OS_WORDEXP_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/os_include/os_stddef.h" // size_t
+
+#if !defined (ACE_LACKS_WORDEXP_H)
+# include /**/ <wordexp.h>
+#endif /* !ACE_LACKS_WORDEXP_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_OS_WORDEXP_H */
diff --git a/ACE/ace/os_include/sys/os_ipc.h b/ACE/ace/os_include/sys/os_ipc.h
new file mode 100644
index 00000000000..454c9e5b045
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_ipc.h
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_ipc.h
+ *
+ * XSI interprocess communication access structure
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_IPC_H
+#define ACE_OS_INCLUDE_SYS_OS_IPC_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_SYS_IPC_H)
+# include /**/ <sys/ipc.h>
+#endif /* !ACE_LACKS_SYS_IPC_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_WIN32)
+# define ACE_INVALID_SEM_KEY 0
+#else /* !ACE_WIN32 */
+# define ACE_INVALID_SEM_KEY -1
+#endif /* ACE_WIN32 */
+
+#if !defined (IPC_PRIVATE)
+# define IPC_PRIVATE ACE_INVALID_SEM_KEY
+#endif /* IPC_PRIVATE */
+
+#if !defined (IPC_STAT)
+# define IPC_STAT 0
+#endif /* IPC_STAT */
+
+#if !defined (IPC_CREAT)
+# define IPC_CREAT 0
+#endif /* IPC_CREAT */
+
+#if !defined (IPC_NOWAIT)
+# define IPC_NOWAIT 0
+#endif /* IPC_NOWAIT */
+
+#if !defined (IPC_RMID)
+# define IPC_RMID 0
+#endif /* IPC_RMID */
+
+#if !defined (IPC_EXCL)
+# define IPC_EXCL 0
+#endif /* IPC_EXCL */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_IPC_H */
diff --git a/ACE/ace/os_include/sys/os_loadavg.h b/ACE/ace/os_include/sys/os_loadavg.h
new file mode 100644
index 00000000000..66190970a90
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_loadavg.h
@@ -0,0 +1,41 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_loadavg.h
+ *
+ * loadavg functions
+ *
+ * $Id$
+ *
+ * @author Johnny Willemsen <jwillemsen@remedy.nl>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_LOADAVG_H
+#define ACE_OS_INCLUDE_SYS_OS_LOADAVG_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_HAS_SYS_LOADAVG_H)
+# include /**/ <sys/loadavg.h>
+#endif /* ACE_HAS_SYS_LOADAVG_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_LOADAVG_H */
diff --git a/ACE/ace/os_include/sys/os_mman.h b/ACE/ace/os_include/sys/os_mman.h
new file mode 100644
index 00000000000..74fef32f869
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_mman.h
@@ -0,0 +1,122 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_mman.h
+ *
+ * memory management declarations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_MMAN_H
+#define ACE_OS_INCLUDE_SYS_OS_MMAN_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+#if defined (ACE_LACKS_MMAP)
+# define ACE_LACKS_SYS_MMAN_H
+#endif /* ACE_LACKS_MMAP */
+
+#if !defined (ACE_LACKS_SYS_MMAN_H)
+ // Fixes a problem with HP/UX.
+# if defined (ACE_HAS_BROKEN_MMAP_H)
+ extern "C" {
+# endif /* ACE_HAS_BROKEN_MMAP_H */
+# include /**/ <sys/mman.h>
+# if defined (ACE_HAS_BROKEN_MMAP_H)
+ }
+# endif /* ACE_HAS_BROKEN_MMAP_H */
+#endif /* ACE_LACKS_SYS_MMAN_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_SYS_MMAN_H) && !defined (ACE_WIN32)
+# define PROT_READ 0
+# define PROT_WRITE 0
+# define PROT_EXEC 0
+# define PROT_NONE 0
+# define PROT_RDWR 0
+# define MAP_PRIVATE 0
+# define MAP_SHARED 0
+# define MAP_FIXED 0
+#elif defined (ACE_WIN32)
+ // These two may be used for internal flags soon:
+# define MAP_PRIVATE 1
+# define MAP_SHARED 2
+# define MAP_FIXED 4
+ // MMAP flags
+# define PROT_READ PAGE_READONLY
+# define PROT_WRITE PAGE_READWRITE
+# define PROT_RDWR PAGE_READWRITE
+/* If we can find suitable use for these flags, here they are:
+PAGE_WRITECOPY
+PAGE_EXECUTE
+PAGE_EXECUTE_READ
+PAGE_EXECUTE_READWRITE
+PAGE_EXECUTE_WRITECOPY
+PAGE_GUARD
+PAGE_NOACCESS
+PAGE_NOCACHE */
+#endif /* !ACE_LACKS_SYS_MMAN_H && !ACE_WIN32*/
+
+# if !defined (ACE_MAP_PRIVATE)
+# define ACE_MAP_PRIVATE MAP_PRIVATE
+# endif /* ! ACE_MAP_PRIVATE */
+
+# if !defined (ACE_MAP_SHARED)
+# define ACE_MAP_SHARED MAP_SHARED
+# endif /* ! ACE_MAP_SHARED */
+
+# if !defined (ACE_MAP_FIXED)
+# define ACE_MAP_FIXED MAP_FIXED
+# endif /* ! ACE_MAP_FIXED */
+
+# if !defined (MAP_FAILED) || defined (ACE_HAS_BROKEN_MAP_FAILED)
+# undef MAP_FAILED
+# define MAP_FAILED ((void *) -1)
+# elif defined (ACE_HAS_LONG_MAP_FAILED)
+# undef MAP_FAILED
+# define MAP_FAILED ((void *) -1L)
+# endif /* !MAP_FAILED || ACE_HAS_BROKEN_MAP_FAILED */
+
+#if !defined (PROT_RDWR)
+# define PROT_RDWR (PROT_READ|PROT_WRITE)
+#endif /* PROT_RDWR */
+
+# if defined (ACE_WIN32)
+ // Needed to map calls to NT transparently.
+# define MS_ASYNC 0
+# define MS_INVALIDATE 0
+# endif /* ACE_WIN32 */
+
+# if !defined (MS_SYNC)
+# define MS_SYNC 0x0
+# endif /* !MS_SYNC */
+
+#if !defined (ACE_LACKS_MADVISE) && defined (ACE_LACKS_MADVISE_PROTOTYPE)
+ extern "C" int madvise(caddr_t, size_t, int);
+#endif /* !ACE_LACKS_MADVISE && ACE_LACKS_MADVISE_PROTOTYPE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_MMAN_H */
diff --git a/ACE/ace/os_include/sys/os_msg.h b/ACE/ace/os_include/sys/os_msg.h
new file mode 100644
index 00000000000..fee07f3677b
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_msg.h
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_msg.h
+ *
+ * XSI message queue structures
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_MSG_H
+#define ACE_OS_INCLUDE_SYS_OS_MSG_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_ipc.h"
+
+#if !defined (ACE_LACKS_SYS_MSG_H)
+# include /**/ <sys/msg.h>
+#endif /* !ACE_LACKS_SYS_MSG_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ // Declare opaque type. Needed for ACE_OS wrappers on systems
+ // without SysV IPC.
+ struct msqid_ds;
+
+#if defined (ACE_LACKS_SYSV_MSQ_PROTOS)
+ int msgget (key_t, int);
+ int msgrcv (int, void *, size_t, long, int);
+ int msgsnd (int, const void *, size_t, int);
+ int msgctl (int, int, struct msqid_ds *);
+#endif /* ACE_LACKS_SYSV_MSQ_PROTOS */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_MSG_H */
diff --git a/ACE/ace/os_include/sys/os_pstat.h b/ACE/ace/os_include/sys/os_pstat.h
new file mode 100644
index 00000000000..15a9c4451a0
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_pstat.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_pstat.h
+ *
+ * pstat functions
+ *
+ * $Id$
+ *
+ * @author Johnny Willemsen <jwillemsen@remedy.nl>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_PSTAT_H
+#define ACE_OS_INCLUDE_SYS_OS_PSTAT_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_HAS_SYS_PSTAT_H)
+# include /**/ <sys/param.h>
+# include /**/ <sys/pstat.h>
+#endif /* ACE_HAS_SYS_PSTAT_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_PSTAT_H */
diff --git a/ACE/ace/os_include/sys/os_resource.h b/ACE/ace/os_include/sys/os_resource.h
new file mode 100644
index 00000000000..e92548e4189
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_resource.h
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_resource.h
+ *
+ * definitions for XSI resource operations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_RESOURCE_H
+#define ACE_OS_INCLUDE_SYS_OS_RESOURCE_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_time.h"
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_SYS_RESOURCE_H)
+# include /**/ <sys/resource.h>
+#endif /* !ACE_LACKS_SYS_RESOURCE_H */
+
+#if defined (ACE_HAS_SYSINFO)
+# include /**/ <sys/systeminfo.h>
+#endif /* ACE_HAS_SYS_INFO */
+
+#if defined (ACE_HAS_SYS_SYSCALL_H)
+# include /**/ <sys/syscall.h>
+#endif /* ACE_HAS_SYS_SYSCALL_H */
+
+// prusage_t is defined in <sys/procfs.h>
+#if defined (ACE_HAS_PROC_FS)
+# include /**/ <sys/procfs.h>
+#endif /* ACE_HAS_PROC_FS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+// There must be a better way to do this...
+#if !defined (RLIMIT_NOFILE) && !defined (ACE_LACKS_RLIMIT_NOFILE)
+# if defined (linux) || defined (AIX) || defined (SCO)
+# if defined (RLIMIT_OFILE)
+# define RLIMIT_NOFILE RLIMIT_OFILE
+# else
+# define RLIMIT_NOFILE 200
+# endif /* RLIMIT_OFILE */
+# endif /* defined (linux) || defined (AIX) || defined (SCO) */
+#endif /* RLIMIT_NOFILE */
+
+#if defined (ACE_WIN32)
+# define RUSAGE_SELF 1
+ /// Fake the UNIX rusage structure. Perhaps we can add more to this
+ /// later on?
+ struct rusage
+ {
+ FILETIME ru_utime;
+ FILETIME ru_stime;
+ };
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_LACKS_RLIMIT_PROTOTYPE)
+ int getrlimit (int resource, struct rlimit *rlp);
+ int setrlimit (int resource, const struct rlimit *rlp);
+#endif /* ACE_LACKS_RLIMIT_PROTOTYPE */
+
+#if defined (ACE_HAS_PRUSAGE_T)
+ typedef prusage_t ACE_Rusage;
+#elif defined (ACE_HAS_GETRUSAGE)
+ typedef rusage ACE_Rusage;
+#else
+ typedef int ACE_Rusage;
+#endif /* ACE_HAS_PRUSAGE_T */
+
+#if !defined (ACE_WIN32)
+// These prototypes are chronically lacking from many versions of UNIX.
+# if !defined (ACE_HAS_GETRUSAGE_PROTOTYPE)
+ int getrusage (int who, struct rusage *rusage);
+# endif /* ! ACE_HAS_GETRUSAGE_PROTOTYPE */
+
+# if defined (ACE_LACKS_SYSCALL)
+ int syscall (int, ACE_HANDLE, struct rusage *);
+# endif /* ACE_LACKS_SYSCALL */
+#endif /* !ACE_WIN32 */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_RESOURCE_H */
diff --git a/ACE/ace/os_include/sys/os_select.h b/ACE/ace/os_include/sys/os_select.h
new file mode 100644
index 00000000000..a8de27cbba8
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_select.h
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_select.h
+ *
+ * select types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_SELECT_H
+#define ACE_OS_INCLUDE_SYS_OS_SELECT_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_time.h"
+#include "ace/os_include/os_signal.h"
+#include "ace/os_include/os_unistd.h"
+
+#if !defined (ACE_LACKS_SYS_SELECT_H)
+# include /**/ <sys/select.h>
+#endif /* !ACE_LACKS_SYS_SELECT_H */
+
+#if defined (ACE_VXWORKS) && defined (ACE_LACKS_SYS_SELECT_H)
+# include /**/ <selectLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_WIN32)
+ // This will help until we figure out everything:
+# define NFDBITS 32 /* only used in unused functions... */
+#elif defined (__QNX__)
+# if !defined (NFDBITS)
+# define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
+# endif /* ! NFDBITS */
+#endif /* ACE_WIN32 */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_SELECT_H */
diff --git a/ACE/ace/os_include/sys/os_sem.h b/ACE/ace/os_include/sys/os_sem.h
new file mode 100644
index 00000000000..93f669d2913
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_sem.h
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_sem.h
+ *
+ * XSI semaphore facility
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_SEM_H
+#define ACE_OS_INCLUDE_SYS_OS_SEM_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_ipc.h"
+
+#if !defined (ACE_LACKS_SYS_SEM_H)
+# include /**/ <sys/sem.h>
+#endif /* !ACE_LACKS_SYS_SEM_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+# if !defined (GETVAL)
+# define GETVAL 0
+# endif /* GETVAL */
+
+# if !defined (SETVAL)
+# define SETVAL 0
+# endif /* SETVAL */
+
+# if !defined (GETALL)
+# define GETALL 0
+# endif /* GETALL */
+
+# if !defined (SETALL)
+# define SETALL 0
+# endif /* SETALL */
+
+# if !defined (SEM_UNDO)
+# define SEM_UNDO 0
+# endif /* SEM_UNDO */
+
+#if defined (ACE_LACKS_SEMBUF_T)
+ struct sembuf
+ {
+ /// semaphore #
+ unsigned short sem_num;
+
+ /// semaphore operation
+ short sem_op;
+
+ /// operation flags
+ short sem_flg;
+ };
+#endif /* ACE_LACKS_SEMBUF_T */
+
+#if !defined (ACE_HAS_SEMUN) || (defined (__GLIBC__) && defined (_SEM_SEMUN_UNDEFINED))
+ union semun
+ {
+ /// value for SETVAL
+ int val;
+ /// buffer for IPC_STAT & IPC_SET
+ struct semid_ds *buf;
+ /// array for GETALL & SETALL
+ u_short *array;
+ };
+#endif /* !ACE_HAS_SEMUN || (defined (__GLIBC__) && defined (_SEM_SEMUN_UNDEFINED)) */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_SEM_H */
diff --git a/ACE/ace/os_include/sys/os_shm.h b/ACE/ace/os_include/sys/os_shm.h
new file mode 100644
index 00000000000..af005e8dbb2
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_shm.h
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_shm.h
+ *
+ * XSI shared memory facility
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_SHM_H
+#define ACE_OS_INCLUDE_SYS_OS_SHM_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_ipc.h"
+
+#if !defined (ACE_LACKS_SYS_SHM_H)
+# include /**/ <sys/shm.h>
+#endif /* !ACE_LACKS_SYS_SHM_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ // Declare opaque type. Needed for ACE_OS wrappers on systems
+ // without SysV IPC.
+ struct shmid_ds;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_SHM_H */
diff --git a/ACE/ace/os_include/sys/os_socket.h b/ACE/ace/os_include/sys/os_socket.h
new file mode 100644
index 00000000000..3e18332d1fc
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_socket.h
@@ -0,0 +1,307 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_socket.h
+ *
+ * main sockets header
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_SOCKET_H
+#define ACE_OS_INCLUDE_SYS_OS_SOCKET_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_uio.h"
+
+#if !defined (ACE_LACKS_SYS_SOCKET_H)
+# include /**/ <sys/socket.h>
+#endif /* !ACE_LACKS_SYS_SOCKET_H */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x620)
+# include /**/ <sockLib.h>
+#endif /* ACE_VXWORKS */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if !defined (ACE_HAS_MSG) && !defined (SCO)
+ struct msghdr {};
+#endif /* ACE_HAS_MSG */
+
+#if defined (ACE_HAS_MSG) && defined (ACE_LACKS_MSG_ACCRIGHTS)
+# if !defined (msg_accrights)
+# undef msg_control
+# define msg_accrights msg_control
+# endif /* ! msg_accrights */
+
+# if !defined (msg_accrightslen)
+# undef msg_controllen
+# define msg_accrightslen msg_controllen
+# endif /* ! msg_accrightslen */
+#endif /* ACE_HAS_MSG && ACE_LACKS_MSG_ACCRIGHTS */
+
+# if defined (ACE_LACKS_SOCKADDR)
+ struct sockaddr {
+ u_char sa_len; /* total length */
+ u_char sa_family; /* address family */
+ char sa_data[14]; /* actually longer; address value */
+ };
+# endif /* ACE_LACKS_SOCKADDR */
+
+# if defined (ACE_LACKS_LINGER)
+ struct linger {
+ int l_onoff; /* option on/off */
+ int l_linger; /* linger time */
+ };
+# endif /* ACE_LACKS_LINGER */
+
+#if defined (ACE_WIN32)
+ struct msghdr
+ {
+ /// Optional address
+ sockaddr * msg_name;
+
+ /// Size of address
+ int msg_namelen;
+
+ /// Scatter/gather array
+ iovec *msg_iov;
+
+ /// # elements in msg_iov
+ int msg_iovlen;
+
+ /// Access rights sent/received
+ caddr_t msg_accrights;
+
+ int msg_accrightslen;
+ };
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ // Control message size to pass a file descriptor.
+# define ACE_BSD_CONTROL_MSG_LEN sizeof (struct cmsghdr) + sizeof (ACE_HANDLE)
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+// Increase the range of "address families". Please note that this
+// must appear _after_ the include of sys/socket.h, for the AF_FILE
+// definition on Linux/glibc2.
+#if !defined (AF_ANY)
+# define AF_ANY (-1)
+#endif /* AF_ANY */
+
+#if !defined (AF_UNSPEC)
+# define AF_UNSPEC 0
+#endif /* AF_UNSPEC */
+
+#if !defined (AF_LOCAL)
+# define AF_LOCAL 1
+#endif /* AF_LOCAL */
+
+#if !defined (AF_UNIX)
+# define AF_UNIX AF_LOCAL
+#endif /* AF_UNIX */
+
+#if !defined (AF_INET)
+# define AF_INET 2
+#endif /* AF_INET */
+
+#if !defined (PF_INET)
+# define PF_INET AF_INET
+#endif /* PF_INET */
+
+#if !defined (PF_LOCAL)
+# define PF_LOCAL AF_LOCAL
+#endif /* PF_LOCAL */
+
+#if !defined (PF_UNIX)
+# define PF_UNIX PF_LOCAL
+#endif /* PF_UNIX */
+
+#if !defined (AF_MAX)
+# define AF_MAX 29
+#endif /* AF_MAX */
+
+#if !defined (PF_UNSPEC)
+# define PF_UNSPEC 0
+#endif /* PF_UNSPEC */
+
+#define AF_SPIPE (AF_MAX + 1)
+#if !defined (AF_FILE)
+# define AF_FILE (AF_MAX + 2)
+#endif /* ! AF_FILE */
+#define AF_DEV (AF_MAX + 3)
+#define AF_UPIPE (AF_SPIPE)
+
+#if !defined (MSG_OOB)
+# define MSG_OOB 0x1
+#endif /* MSG_OOB */
+
+#if !defined (MSG_PEEK)
+# define MSG_PEEK 0x2
+#endif /* MSG_PEEK */
+
+#if !defined (SOCK_STREAM)
+# define SOCK_STREAM 1
+#endif /* SOCK_STREAM */
+
+#if !defined (SOCK_DGRAM)
+# define SOCK_DGRAM 2
+#endif /* SOCK_DGRAM */
+
+#if !defined (SOCK_SEQPACKET)
+# define SOCK_SEQPACKET 5
+#endif /* SOCK_SEQPACKET */
+
+#if !defined (SOL_SOCKET)
+# define SOL_SOCKET 0xffff
+#endif /* SOL_SOCKET */
+
+#if !defined (SO_REUSEADDR)
+# define SO_REUSEADDR 0x0004
+#endif /* SO_REUSEADDR */
+
+#if !defined (SO_LINGER)
+# define SO_LINGER 0x0080
+#endif /* SO_LINGER */
+
+#if !defined (SO_SNDBUF)
+# define SO_SNDBUF 0x1001
+#endif /* SO_SNDBUF */
+
+#if !defined (SO_RCVBUF)
+# define SO_RCVBUF 0x1002
+#endif /* SO_RCVBUF */
+
+#if !defined (SO_BROADCAST)
+# define SO_BROADCAST 0x0020
+#endif /* SO_BROADCAST */
+
+#if !defined (SO_ERROR)
+# define SO_ERROR 0x1007
+#endif /* SO_ERROR */
+
+#if !defined (SCM_RIGHTS)
+# define SCM_RIGHTS 0x01
+#endif /* SCM_RIGHTS */
+
+#if defined (ACE_HAS_IPV6)
+# if defined (ACE_USES_IPV4_IPV6_MIGRATION)
+# define ACE_ADDRESS_FAMILY_INET AF_UNSPEC
+# define ACE_PROTOCOL_FAMILY_INET PF_UNSPEC
+# else
+# define ACE_ADDRESS_FAMILY_INET AF_INET6
+# define ACE_PROTOCOL_FAMILY_INET PF_INET6
+# endif /* ACE_USES_IPV4_IPV6_MIGRATION */
+#else /* !ACE_HAS_IPV6 */
+# define ACE_ADDRESS_FAMILY_INET AF_INET
+# define ACE_PROTOCOL_FAMILY_INET PF_INET
+#endif /* ACE_HAS_IPV6 */
+
+#if !defined (ACE_HAS_SOCK_BUF_SIZE_MAX_VALUE)
+#define ACE_HAS_SOCK_BUF_SIZE_MAX_VALUE SSIZE_MAX
+#endif /* ACE_HAS_SOCK_BUF_SIZE_MAX_VALUE */
+
+#if defined (ACE_HAS_SOCKLEN_T)
+# if defined (__hpux)
+ /*
+ ** HP-UX supplies the socklen_t type unless some feature set less than
+ ** _XOPEN_SOURCE_EXTENDED is specifically requested. However, it only
+ ** actually uses the socklen_t type in supplied socket functions if
+ ** _XOPEN_SOURCE_EXTENDED is specifically requested. So, for example,
+ ** the compile options ACE usually uses (includes -mt) cause _HPUX_SOURCE
+ ** to be set, which sets _INCLUDE_XOPEN_SOURCE_EXTENDED (causing socklen_t
+ ** to be defined) but _not_ _XOPEN_SOURCE_EXTENDED (causing socket functions
+ ** to use int, not socklen_t). React to this situation here...
+ */
+# if defined (_XOPEN_SOURCE_EXTENDED)
+typedef socklen_t ACE_SOCKET_LEN;
+# else
+typedef int ACE_SOCKET_LEN;
+# endif /* _XOPEN_SOURCE_EXTENDED */
+# else
+typedef socklen_t ACE_SOCKET_LEN;
+# endif /* __hpux */
+#elif defined (ACE_HAS_SIZET_SOCKET_LEN)
+typedef size_t ACE_SOCKET_LEN;
+#else
+typedef int ACE_SOCKET_LEN;
+#endif /* ACE_HAS_SIZET_SOCKET_LEN */
+
+#if defined (ACE_HAS_NETLINK)
+# include /**/ <asm/types.h>
+# include /**/ <linux/netlink.h>
+# define ACE_PROTOCOL_FAMILY_NETLINK AF_NETLINK
+#endif
+
+#if defined (ACE_HAS_LKSCTP)
+extern "C"
+{
+#include /**/ <netinet/in.h>
+#include /**/ <netinet/sctp.h>
+}
+#endif /* ACE_HAS_LKSCTP */
+
+# if defined (ACE_LACKS_TIMEDWAIT_PROTOTYPES)
+
+ ssize_t recv_timedwait (ACE_HANDLE handle,
+ char *buf,
+ int len,
+ int flags,
+ struct timespec *timeout);
+
+ ssize_t recvmsg_timedwait (ACE_HANDLE handle,
+ struct msghdr *msg,
+ int flags,
+ struct timespec *timeout);
+
+ ssize_t recvfrom_timedwait (ACE_HANDLE handle,
+ char *buf,
+ int len,
+ int flags,
+ struct sockaddr *addr,
+ int *addrlen,
+ struct timespec *timeout);
+
+ ssize_t send_timedwait (ACE_HANDLE handle,
+ const char *buf,
+ int len,
+ int flags,
+ struct timespec *timeout);
+
+ ssize_t sendmsg_timedwait (ACE_HANDLE handle,
+ const struct msghdr *msg,
+ int flags,
+ struct timespec *timeout);
+
+ ssize_t sendto_timedwait (ACE_HANDLE handle,
+ const char *buf,
+ int len,
+ int flags,
+ const struct sockaddr *addr,
+ int addrlen,
+ struct timespec *timeout);
+
+# endif /* ACE_LACKS_TIMEDWAIT_PROTOTYPES */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_SOCKET_H */
diff --git a/ACE/ace/os_include/sys/os_stat.h b/ACE/ace/os_include/sys/os_stat.h
new file mode 100644
index 00000000000..a7c69dc36d4
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_stat.h
@@ -0,0 +1,127 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_stat.h
+ *
+ * data returned by the stat() function
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_STAT_H
+#define ACE_OS_INCLUDE_SYS_OS_STAT_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+# include /**/ <direct.h>
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+
+#if !defined (ACE_LACKS_SYS_STAT_H)
+# include /**/ <sys/stat.h>
+#endif /* !ACE_LACKS_SYS_STAT_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_MODE_MASKS)
+// MODE MASKS
+
+// the following macros are for POSIX conformance.
+
+# if !defined (ACE_HAS_USER_MODE_MASKS)
+# define S_IRWXU 00700 /* read, write, execute: owner. */
+# define S_IRUSR 00400 /* read permission: owner. */
+# define S_IWUSR 00200 /* write permission: owner. */
+# define S_IXUSR 00100 /* execute permission: owner. */
+# endif /* ACE_HAS_USER_MODE_MASKS */
+# define S_IRWXG 00070 /* read, write, execute: group. */
+# define S_IRGRP 00040 /* read permission: group. */
+# define S_IWGRP 00020 /* write permission: group. */
+# define S_IXGRP 00010 /* execute permission: group. */
+# define S_IRWXO 00007 /* read, write, execute: other. */
+# define S_IROTH 00004 /* read permission: other. */
+# define S_IWOTH 00002 /* write permission: other. */
+# define S_IXOTH 00001 /* execute permission: other. */
+
+// WinCE's S_IFLNK is defined with the other bits, below.
+#if !defined (S_IFLNK) && !defined (ACE_HAS_WINCE)
+#define S_IFLNK 0200000
+#endif /* S_IFLNK && !ACE_HAS_WINCE */
+
+#endif /* ACE_LACKS_MODE_MASKS */
+
+// Some systems (VxWorks) don't define S_ISLNK
+#if !defined (S_ISLNK)
+# if defined (S_IFLNK)
+# define S_ISLNK(mode) (((mode)&S_IFLNK) == S_IFLNK)
+# else
+# define S_ISLNK(mode) 0
+# endif /* S_IFLNK */
+#endif /* S_ISLNK */
+
+#if defined (ACE_HAS_WINCE)
+# include "ace/Time_Value.h"
+
+// Translate the WinCE bits into names expected by our callers.
+// The dwFileAttributes parameter doesn't have protection info, so
+// S_IFMT is the whole thing. Since there are no symbolic links, S_IFLNK is 0.
+# define S_IFMT 0xFFFF
+# define S_IFDIR FILE_ATTRIBUTE_DIRECTORY
+# define S_IFREG FILE_ATTRIBUTE_NORMAL
+# define S_IFLNK 0
+
+ struct stat
+ {
+ /// always 0 on Windows platforms
+ dev_t st_dev;
+
+ /// always 0 on Windows platforms
+ dev_t st_rdev;
+
+ /// file attribute
+ unsigned short st_mode;
+
+ /// number of hard links
+ short st_nlink;
+
+ /// time of last access
+ ACE_Time_Value st_atime;
+
+ /// time of last data modification
+ ACE_Time_Value st_mtime;
+
+ /// time of creation
+ ACE_Time_Value st_ctime;
+
+ /// file size, in bytes
+ ACE_OFF_T st_size;
+
+ // Following members do not have direct conversion in Window platforms.
+ //u_long st_blksize; // optimal blocksize for I/O
+ //u_long st_flags; // user defined flags for file
+ };
+#endif /* ACE_HAS_WINCE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_STAT_H */
diff --git a/ACE/ace/os_include/sys/os_statvfs.h b/ACE/ace/os_include/sys/os_statvfs.h
new file mode 100644
index 00000000000..546c20b10f2
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_statvfs.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_statvfs.h
+ *
+ * VFS File System information structure
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_STATVFS_H
+#define ACE_OS_INCLUDE_SYS_OS_STATVFS_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_SYS_STATVFS_H)
+# include /**/ <sys/statvfs.h>
+#endif /* !ACE_LACKS_SYS_STATVFS_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_STATVFS_H */
diff --git a/ACE/ace/os_include/sys/os_sysctl.h b/ACE/ace/os_include/sys/os_sysctl.h
new file mode 100644
index 00000000000..680c2562cbf
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_sysctl.h
@@ -0,0 +1,41 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_sysctl.h
+ *
+ * declarations for sysctl
+ *
+ * $Id$
+ *
+ * @author Johnny Willemsen <jwillemsen@remedy.nl>
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_SYSCTL_H
+#define ACE_OS_INCLUDE_SYS_OS_SYSCTL_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_SYS_SYSCTL_H)
+# include /**/ <sys/sysctl.h>
+#endif /* !ACE_LACKS_SYS_SYSCTL_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_SYSCTL_H */
diff --git a/ACE/ace/os_include/sys/os_time.h b/ACE/ace/os_include/sys/os_time.h
new file mode 100644
index 00000000000..d8d061b5d62
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_time.h
@@ -0,0 +1,60 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_time.h
+ *
+ * time types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_TIME_H
+#define ACE_OS_INCLUDE_SYS_OS_TIME_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_SYS_TIME_H)
+# include /**/ <sys/time.h>
+#endif /* !ACE_LACKS_SYS_TIME_H */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS == 0x620)
+# include /**/ <time.h> // VxWorks 6.2 defined timeval in time.h
+#endif
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_HAS_SVR4_GETTIMEOFDAY)
+# if !defined (SCO)
+ int gettimeofday (struct timeval *tp, void * = 0);
+# else
+ int gettimeofday (struct timeval *tp);
+# endif /* !SCO */
+#elif defined (ACE_HAS_OSF1_GETTIMEOFDAY)
+ int gettimeofday (struct timeval *tp, struct timezone * = 0);
+#elif defined (ACE_HAS_VOIDPTR_GETTIMEOFDAY)
+# define ACE_HAS_SVR4_GETTIMEOFDAY
+#endif /* ACE_HAS_SVR4_GETTIMEOFDAY */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_TIME_H */
diff --git a/ACE/ace/os_include/sys/os_timeb.h b/ACE/ace/os_include/sys/os_timeb.h
new file mode 100644
index 00000000000..2495097d344
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_timeb.h
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_timeb.h
+ *
+ * additional definitions for date and time
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_TIMEB_H
+#define ACE_OS_INCLUDE_SYS_OS_TIMEB_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_SYS_TIMEB_H)
+# include /**/ <sys/timeb.h>
+#endif /* !ACE_LACKS_SYS_TIMEB_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (__BORLANDC__) && (__BORLANDC__ <= 0x560)
+# define _ftime ftime
+# define _timeb timeb
+#endif /* __BORLANDC__ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_TIMEB_H */
diff --git a/ACE/ace/os_include/sys/os_times.h b/ACE/ace/os_include/sys/os_times.h
new file mode 100644
index 00000000000..c63b9e0098c
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_times.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_times.h
+ *
+ * file access and modification times structure
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_TIMES_H
+#define ACE_OS_INCLUDE_SYS_OS_TIMES_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+
+#if !defined (ACE_LACKS_SYS_TIMES_H)
+# include /**/ <sys/times.h>
+#endif /* !ACE_LACKS_SYS_TIMES_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_TIMES_H */
diff --git a/ACE/ace/os_include/sys/os_types.h b/ACE/ace/os_include/sys/os_types.h
new file mode 100644
index 00000000000..fbdbb23a318
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_types.h
@@ -0,0 +1,158 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_types.h
+ *
+ * data types
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_TYPES_H
+#define ACE_OS_INCLUDE_SYS_OS_TYPES_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_stddef.h"
+
+#if !defined (ACE_LACKS_SYS_TYPES_H)
+# include /**/ <sys/types.h>
+#endif /* !ACE_LACKS_SYS_TYPES_H */
+
+#if defined (ACE_HAS_WINCE)
+# include /**/ <types.h>
+#endif /* ACE_HAS_WINCE */
+
+# if defined (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB) && \
+ (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB != 0)
+using std::time_t;
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDC_LIB */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+typedef double ACE_timer_t;
+
+// todo: don't forget to clean this up! ;-)
+#if !defined (ACE_HAS_CLOCK_GETTIME) && !(defined (_CLOCKID_T_) || defined (_CLOCKID_T))
+ typedef int clockid_t;
+# if !defined (CLOCK_REALTIME)
+# define CLOCK_REALTIME 0
+# endif /* CLOCK_REALTIME */
+#endif /* ! ACE_HAS_CLOCK_GETTIME && ! _CLOCKID_T_ */
+
+#if defined (ACE_HAS_WINCE)
+
+// CE's add-on for c-style fstat/stat functionalities. This struct is
+// by no mean complete compared to what you usually find in UNIX
+// platforms. Only members that have direct conversion using Win32's
+// BY_HANDLE_FILE_INFORMATION are defined so that users can discover
+// non-supported members at compile time. Time values are of type
+// ACE_Time_Value for easy comparison.
+
+// Since CE does not have _stat by default as NT/2000 does, the 'stat'
+// struct defined here will be used. Also note that CE file system
+// struct is only for the CE 3.0 or later.
+// Refer to the WCHAR.H from Visual C++ and WIBASE.H from eVC 3.0.
+
+ typedef unsigned int dev_t;
+#endif /* ACE_HAS_WINCE */
+
+#if defined(ACE_WIN32) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS==64)
+ typedef __int64 ACE_OFF_T;
+#else
+ typedef off_t ACE_OFF_T;
+#endif
+
+#if defined (ACE_SIZEOF_LONG) && ACE_SIZEOF_LONG == 8
+ typedef off_t ACE_LOFF_T;
+#elif defined (ACE_HAS_RTEMS) || defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__APPLE__) || \
+ (defined (ACE_OPENVMS) && defined (_LARGEFILE)) || defined(ACE_MVS)
+ typedef off_t ACE_LOFF_T;
+#elif defined (__sgi) || defined (AIX) || defined (HPUX) || defined (__QNX__)
+ typedef off64_t ACE_LOFF_T;
+#elif defined (__sun)
+ typedef offset_t ACE_LOFF_T;
+#elif defined (WIN32)
+ typedef __int64 ACE_LOFF_T;
+#elif (defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x660)) || \
+ defined (ACE_LYNXOS_MAJOR) || \
+ (defined (ACE_OPENVMS) && !defined (_LARGEFILE)) || \
+ defined (__TANDEM)
+ typedef long long ACE_LOFF_T;
+#else
+ typedef loff_t ACE_LOFF_T;
+#endif
+
+#if defined (ACE_WIN32)
+# if !defined (__BORLANDC__)
+ typedef DWORD nlink_t;
+# if !defined(__MINGW32__)
+ typedef int mode_t;
+# endif /* !__MINGW32__ */
+ typedef long uid_t;
+ typedef long gid_t;
+# endif /* __BORLANDC__ */
+ typedef char *caddr_t;
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_LACKS_KEY_T)
+# if defined (ACE_WIN32)
+ // Win32 doesn't use numeric values to name its semaphores, it uses
+ // strings!
+ typedef char *key_t;
+# else
+ typedef int key_t;
+# endif /* ACE_WIN32 */
+#endif /* ACE_LACKS_KEY_T */
+
+#if !defined (ACE_HAS_SSIZE_T)
+# if defined (ACE_WIN64)
+ typedef SSIZE_T ssize_t;
+# else
+ typedef int ssize_t;
+# endif /* ACE_WIN64 */
+#endif /* ACE_HAS_SSIZE_T */
+
+#if defined (ACE_WIN32)
+ typedef DWORD ACE_exitcode;
+#else
+ typedef int ACE_exitcode;
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_LACKS_SUSECONDS_T)
+ typedef long suseconds_t;
+#endif
+
+#if defined (ACE_LACKS_USECONDS_T)
+ typedef unsigned long useconds_t;
+#endif
+
+#if defined (ACE_WIN32) && !defined(__MINGW32__)
+ typedef int pid_t;
+#endif /* ACE_WIN32 */
+
+# if !defined (ACE_INVALID_PID)
+# define ACE_INVALID_PID ((pid_t) -1)
+# endif /* ACE_INVALID_PID */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_TYPES_H */
diff --git a/ACE/ace/os_include/sys/os_uio.h b/ACE/ace/os_include/sys/os_uio.h
new file mode 100644
index 00000000000..463b1143eef
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_uio.h
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_uio.h
+ *
+ * definitions for vector I/O operations
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_UIO_H
+#define ACE_OS_INCLUDE_SYS_OS_UIO_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_types.h"
+#include "ace/os_include/os_limits.h"
+
+#if !defined (ACE_LACKS_SYS_UIO_H)
+# include /**/ <sys/uio.h>
+#endif /* !ACE_LACKS_SYS_UIO_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_LACKS_IOVEC)
+ /// The ordering of the fields in this struct is important. It has to
+ /// match those in WSABUF.
+ struct iovec
+ {
+ /// byte count to read/write
+ u_long iov_len;
+ /// data to be read/written
+ char *iov_base;
+
+ // WSABUF is a Winsock2-only type.
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ operator WSABUF &(void) { return *((WSABUF *) this); }
+# endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
+ };
+#endif /* ACE_LACKS_IOVEC */
+
+
+# if defined (ACE_LACKS_TIMEDWAIT_PROTOTYPES)
+
+ ssize_t readv_timedwait (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ struct timespec* timeout);
+
+ ssize_t writev_timedwait (ACE_HANDLE handle,
+ const iovec *iov,
+ int iovcnt,
+ struct timespec *timeout);
+
+# endif /* ACE_LACKS_TIMEDWAIT_PROTOTYPES */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_UIO_H */
diff --git a/ACE/ace/os_include/sys/os_un.h b/ACE/ace/os_include/sys/os_un.h
new file mode 100644
index 00000000000..a9bf2457dc1
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_un.h
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_un.h
+ *
+ * definitions for UNIX domain sockets
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_UN_H
+#define ACE_OS_INCLUDE_SYS_OS_UN_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/sys/os_socket.h"
+
+#if !defined (ACE_LACKS_SYS_UN_H)
+# include /**/ <sys/un.h>
+#endif /* !ACE_LACKS_SYS_UN_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x600)
+struct sockaddr_un {
+ short sun_family; // AF_UNIX.
+ char sun_path[108]; // path name.
+};
+#endif /* ACE_VXWORKS */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_UN_H */
diff --git a/ACE/ace/os_include/sys/os_utsname.h b/ACE/ace/os_include/sys/os_utsname.h
new file mode 100644
index 00000000000..d707cbecc7d
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_utsname.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_utsname.h
+ *
+ * system name structure
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_UTSNAME_H
+#define ACE_OS_INCLUDE_SYS_OS_UTSNAME_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_SYS_UTSNAME_H)
+# include /**/ <sys/utsname.h>
+#endif /* !ACE_LACKS_SYS_UTSNAME_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_UTSNAME_H */
diff --git a/ACE/ace/os_include/sys/os_wait.h b/ACE/ace/os_include/sys/os_wait.h
new file mode 100644
index 00000000000..eb9f7e1d2de
--- /dev/null
+++ b/ACE/ace/os_include/sys/os_wait.h
@@ -0,0 +1,97 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file os_wait.h
+ *
+ * declarations for waiting
+ *
+ * $Id$
+ *
+ * @author Don Hinton <dhinton@dresystems.com>
+ * @author This code was originally in various places including ace/OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_INCLUDE_SYS_OS_WAIT_H
+#define ACE_OS_INCLUDE_SYS_OS_WAIT_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-lite.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/os_include/os_signal.h"
+#include "ace/os_include/sys/os_resource.h"
+
+#if !defined (ACE_LACKS_SYS_WAIT_H)
+# include /**/ <sys/wait.h>
+#endif /* !ACE_LACKS_SYS_WAIT_H */
+
+// Place all additions (especially function declarations) within extern "C" {}
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ // Wrapping around wait status <wstat> macros for platforms that
+ // lack them.
+
+# if !defined (WCOREDUMP)
+# define WCOREDUMP(stat) 0
+# endif /* WCOREDUMP */
+
+# if !defined (WNOHANG)
+# define WNOHANG 0100
+# endif /* !WNOHANG */
+
+ // If the value of WIFEXITED(stat) is non-zero, this macro evaluates
+ // to the exit code that the child process exit(3C), or the value
+ // that the child process returned from main. Peaceful exit code is
+ // 0.
+# if !defined (WEXITSTATUS)
+# define WEXITSTATUS(stat) stat
+# endif /* WEXITSTATUS */
+
+# if !defined (WIFCONTINUED)
+# define WIFCONTINUED(stat) 0
+# endif /* WIFCONTINUED */
+
+ // Evaluates to a non-zero value if status was returned for a child
+ // process that terminated normally. 0 means status wasn't
+ // returned.
+# if !defined (WIFEXITED)
+# define WIFEXITED(stat) 1
+# endif /* WIFEXITED */
+
+ // Evaluates to a non-zero value if status was returned for a child
+ // process that terminated due to the receipt of a signal. 0 means
+ // status wasnt returned.
+# if !defined (WIFSIGNALED)
+# define WIFSIGNALED(stat) 0
+# endif /* WIFSIGNALED */
+
+# if !defined (WIFSTOPPED)
+# define WIFSTOPPED(stat) 0
+# endif /* WIFSTOPPED */
+
+# if !defined (WSTOPSIG)
+# define WSTOPSIG(stat) 0
+# endif /* WSTOPSIG */
+
+ // If the value of WIFSIGNALED(stat) is non-zero, this macro
+ // evaluates to the number of the signal that caused the
+ // termination of the child process.
+# if !defined (WTERMSIG)
+# define WTERMSIG(stat) 0
+# endif /* WTERMSIG */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_OS_INCLUDE_SYS_OS_WAIT_H */
diff --git a/ACE/ace/other.mpb b/ACE/ace/other.mpb
new file mode 100644
index 00000000000..9599ab8282b
--- /dev/null
+++ b/ACE/ace/other.mpb
@@ -0,0 +1,15 @@
+// -*- MPC -*-
+// $Id$
+
+feature(ace_other) {
+ Source_Files(ACE_COMPONENTS) {
+ Local_Name_Space.cpp
+ Name_Proxy.cpp
+ Name_Request_Reply.cpp
+ Name_Space.cpp
+ Naming_Context.cpp
+ Registry_Name_Space.cpp
+ Remote_Name_Space.cpp
+ NT_Service.cpp
+ }
+}
diff --git a/ACE/ace/post.h b/ACE/ace/post.h
new file mode 100644
index 00000000000..e39a3f9fa24
--- /dev/null
+++ b/ACE/ace/post.h
@@ -0,0 +1,22 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file post.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ *
+ * This file restores the original alignment rules.
+ */
+//=============================================================================
+
+// No header guard
+#if defined (_MSC_VER)
+# pragma pack (pop)
+#elif defined (__BORLANDC__)
+# pragma option pop
+# pragma nopushoptwarn
+# pragma nopackwarning
+#endif
diff --git a/ACE/ace/pre.h b/ACE/ace/pre.h
new file mode 100644
index 00000000000..8a7d7774c64
--- /dev/null
+++ b/ACE/ace/pre.h
@@ -0,0 +1,24 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file pre.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ *
+ * This file saves the original alignment rules and changes the alignment
+ * boundary to ACE's default.
+ */
+//=============================================================================
+
+// No header guard
+#if defined (_MSC_VER)
+# pragma warning (disable:4103)
+# pragma pack (push, 8)
+#elif defined (__BORLANDC__)
+# pragma option push -a8 -b -Ve- -Vx- -w-rvl -w-rch -w-ccc -w-obs -w-aus -w-pia -w-inl -w-sig
+# pragma nopushoptwarn
+# pragma nopackwarning
+#endif
diff --git a/ACE/ace/streams.h b/ACE/ace/streams.h
new file mode 100644
index 00000000000..d26ceb73dd7
--- /dev/null
+++ b/ACE/ace/streams.h
@@ -0,0 +1,141 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file streams.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali
+ *
+ * This file contains the portability ugliness for the Standard C++
+ * Library. As implementations of the "standard" emerge, this file
+ * will need to be updated.
+ *
+ * This files deals with the streams includes.
+ *
+ *
+ */
+//=============================================================================
+
+
+#ifndef ACE_STREAMS_H
+#define ACE_STREAMS_H
+#include /**/ "ace/pre.h"
+
+#include /**/ "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Do this so the #pragma warning in the MSVC headers do not
+// affect our #pragma warning settings
+#if defined (_MSC_VER)
+#pragma warning(push)
+#endif /* _MSC_VER*/
+
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+
+# if defined (ACE_HAS_STANDARD_CPP_LIBRARY) && \
+ (ACE_HAS_STANDARD_CPP_LIBRARY != 0)
+
+# if defined (_MSC_VER)
+# pragma warning(disable: 4018 4114 4146 4245)
+# pragma warning(disable: 4663 4664 4665 4511 4512)
+# endif /* _MSC_VER */
+
+# if defined (ACE_USES_OLD_IOSTREAMS)
+# include /**/ <iostream.h>
+# include /**/ <fstream.h>
+ // This has been commented as it is not needed and causes problems with Qt.
+ // (brunsch) But has been uncommented since it should be included. Qt
+ // probably should have some sort of macro that will prevent including this
+ // when it is used.
+# include /**/ <iomanip.h>
+# else
+# if defined (__BORLANDC__) && (__BORLANDC__ == 0x551)
+# include /**/ <iterator>
+# endif /* __BORLANDC__ && __BORLANDC__ == 0x551 */
+# include /**/ <iostream>
+# include /**/ <fstream>
+# include /**/ <istream>
+# include /**/ <ostream>
+# include /**/ <streambuf>
+# include /**/ <iomanip>
+# include /**/ <ios>
+# endif /* ACE_USES_OLD_IOSTREAMS */
+
+# if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB) && \
+ (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB != 0)
+
+# if !defined (ACE_USES_OLD_IOSTREAMS)
+ // Make these available in the global name space
+ using std::ios;
+ using std::ios_base;
+ using std::streambuf;
+ using std::istream;
+ using std::ostream;
+ using std::iostream;
+ using std::filebuf;
+ using std::ifstream;
+ using std::ofstream;
+ using std::fstream;
+
+ using std::cin;
+ using std::cout;
+ using std::cerr;
+ using std::clog;
+
+ using std::endl;
+ using std::ends;
+ using std::flush;
+
+ using std::ws;
+
+ using std::resetiosflags;
+ using std::setfill;
+ using std::setiosflags;
+ using std::setprecision;
+ using std::setw;
+
+ using std::dec;
+ using std::hex;
+ using std::oct;
+# endif /* ! ACE_USES_OLD_IOSTREAMS */
+
+# endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+
+# if defined (_MSC_VER)
+# pragma warning(4: 4018 4114 4146 4245)
+# pragma warning(4: 4663 4664 4665 4512 4511)
+# endif /* _MSC_VER */
+
+# else /* ! ACE_HAS_STANDARD_CPP_LIBRARY */
+
+# include /**/ <fstream.h>
+# include /**/ <iostream.h>
+# include /**/ <iomanip.h>
+
+# if defined (ACE_WIN32) && !defined(__MINGW32__)
+# if defined(_MSC_VER) // VSB
+# include /**/ <ios.h>
+# include /**/ <streamb.h>
+# include /**/ <istream.h>
+# include /**/ <ostream.h>
+# endif /* _MSC_VER */
+# endif /* ACE_WIN32 && !__MINGW32__ */
+
+# endif /* ! ACE_HAS_STANDARD_CPP_LIBRARY */
+
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+// Do this so the #pragma warning in the MSVC headers do not
+// affect our #pragma warning settings
+#if defined (_MSC_VER)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_STREAMS_H */
diff --git a/ACE/ace/svc_export.h b/ACE/ace/svc_export.h
new file mode 100644
index 00000000000..5e85a8ac2fd
--- /dev/null
+++ b/ACE/ace/svc_export.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+
+// This file was generated by generate_export_file.pl
+// but needed to be altered to support ACE_BUILD_SVC_DLL
+// instead of ACE_SVC_BUILD_DLL which was already being
+// used.
+
+// ------------------------------
+#if !defined (ACE_SVC_EXPORT_H)
+#define ACE_SVC_EXPORT_H
+
+#include /**/ "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_SVC_HAS_DLL)
+# define ACE_SVC_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ACE_SVC_HAS_DLL */
+
+#if !defined (ACE_SVC_HAS_DLL)
+#define ACE_SVC_HAS_DLL 1
+#endif /* ! ACE_SVC_HAS_DLL */
+
+#if defined (ACE_SVC_HAS_DLL)
+# if (ACE_SVC_HAS_DLL == 1)
+# if defined (ACE_BUILD_SVC_DLL) || defined (ACE_SVC_BUILD_DLL)
+# define ACE_Svc_Export ACE_Proper_Export_Flag
+# define ACE_SVC_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# else
+# define ACE_Svc_Export ACE_Proper_Import_Flag
+# define ACE_SVC_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# endif /* ACE_BUILD_SVC_DLL */
+# else
+# define ACE_Svc_Export
+# define ACE_SVC_SINGLETON_DECLARATION(T)
+# endif /* ! ACE_SVC_HAS_DLL == 1 */
+#else
+# define ACE_Svc_Export
+# define ACE_SVC_SINGLETON_DECLARATION(T)
+#endif /* ACE_SVC_HAS_DLL */
+
+#endif /* ACE_SVC_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/ace/svcconf.mpb b/ACE/ace/svcconf.mpb
new file mode 100644
index 00000000000..79fad93329a
--- /dev/null
+++ b/ACE/ace/svcconf.mpb
@@ -0,0 +1,64 @@
+// -*- MPC -*-
+// $Id$
+
+feature(ace_svcconf) {
+ macros -= ACE_LACKS_ACE_SVCCONF
+
+ Source_Files(ACE_COMPONENTS) {
+ DLL.cpp
+ Dynamic_Service_Base.cpp
+ Dynamic_Service_Dependency.cpp
+ Parse_Node.cpp
+ Service_Config.cpp
+ Service_Gestalt.cpp
+ Service_Manager.cpp
+ Service_Object.cpp
+ Service_Repository.cpp
+ Service_Types.cpp
+ Shared_Object.cpp
+ Svc_Conf_Lexer.cpp
+ Svc_Conf_y.cpp
+ Encoding_Converter.cpp
+ Encoding_Converter_Factory.cpp
+ UTF8_Encoding_Converter.cpp
+ UTF16_Encoding_Converter.cpp
+ UTF32_Encoding_Converter.cpp
+ XML_Svc_Conf.cpp
+ }
+
+ verbatim(gnuace, local) {
+ "Svc_Conf_y.cpp: Svc_Conf.y"
+ "ifeq ($(notdir $(YACC)), bison)"
+ " $(YACC) -l -d Svc_Conf.y"
+ " sed -e 's/char \\*getenv/char *ace_foo/g' \\" // Eliminates getenv prototype, use ACE's
+ " -e 's/= getenv/= ACE_OS::getenv/g' \\" // ... like this - qualified.
+ " -e 's/fprintf/ACE_OS::fprintf/g' \\" // Use ACE's fprintf, not library's
+ " -e 's/yy/ace_yy/g' \\"
+ " -e 's/->ace_yyerrno/->yyerrno/g' \\" // These reverse the unwanted ace_ prefix
+ " -e 's/->ace_yylineno/->yylineno/g' \\" // added by the substitution, above.
+ " -e 's/YY/ACE_YY/g' \\"
+ " -e 's/^char /ACE_TCHAR /g' \\"
+ " -e 's/\([^d]\) char /\$1 ACE_TCHAR /g' \\"
+ " -e 's/(char/(ACE_TCHAR/g' \\"
+ " -e 's/ NULL/ 0/g' \\"
+ " -e 's/ace_yyerror[ ]*(\"/ace_yyerror (ACE_SVC_CONF_PARAM->yyerrno, ACE_SVC_CONF_PARAM->yylineno, \"/g' \\"
+ " -e 's/ace_yyerror[ ]*(ace_yymsg/ace_yyerror (ACE_SVC_CONF_PARAM->yyerrno, ACE_SVC_CONF_PARAM->yylineno, ace_yymsg/g' \\"
+ " -e 's/ace_yyerror (int ace_yyerrno, int ace_yylineno, const ACE_TCHAR/ace_yyerror (int ace_yyerrno, int ace_yylineno, const char/' \\"
+ " -e 's@#include <stdio\.h>@@' \\"
+ " -e 's/Svc_Conf\\.tab\\.c/Svc_Conf_y.cpp/g' < Svc_Conf.tab.c > /tmp/$@"
+ " cp /tmp/$@ $@"
+ " echo \/\/ '$$I''d:$$' >Svc_Conf_Tokens.h"
+ " echo '#ifndef BISON_SVC_CONF_TAB_H' >>Svc_Conf_Tokens.h" // Inclusion protection macros
+ " echo '# define BISON_SVC_CONF_TAB_H' >>Svc_Conf_Tokens.h" // ... same ...
+ " echo '# define ACE_YYSTYPE_IS_DECLARED 1' >>Svc_Conf_Tokens.h" // Don't use Svc_Conf_y.cpp's
+ " sed -e 's/yy/ace_yy/g' \\"
+ " -e 's/YY/ACE_YY/g' <Svc_Conf.tab.h >>Svc_Conf_Tokens.h"
+ " echo '#endif \/\* ifndef BISON_SVC_CONF_TAB_H \*\/' >>Svc_Conf_Tokens.h"
+ " $(RM) -f /tmp/$@ Svc_Conf.tab.c Svc_Conf.tab.h Svc_Conf_y.cpp.orig"
+ "else"
+ " @echo 'ERROR: You must use bison 1.35 or higher to process this file'"
+ " @/bin/false"
+ "endif"
+
+ }
+}
diff --git a/ACE/ace/token.mpb b/ACE/ace/token.mpb
new file mode 100644
index 00000000000..ce261141a76
--- /dev/null
+++ b/ACE/ace/token.mpb
@@ -0,0 +1,15 @@
+// -*- MPC -*-
+// $Id$
+
+feature(ace_token) {
+ macros -= ACE_LACKS_ACE_TOKEN
+
+ Source_Files(ACE_COMPONENTS) {
+ Local_Tokens.cpp
+ Remote_Tokens.cpp
+ Token_Collection.cpp
+ Token_Invariants.cpp
+ Token_Manager.cpp
+ Token_Request_Reply.cpp
+ }
+}
diff --git a/ACE/ace/uuid.mpb b/ACE/ace/uuid.mpb
new file mode 100644
index 00000000000..3357a6e61b8
--- /dev/null
+++ b/ACE/ace/uuid.mpb
@@ -0,0 +1,8 @@
+// -*- MPC -*-
+// $Id$
+
+feature(ace_uuid) {
+ Source_Files(ACE_COMPONENTS) {
+ UUID.cpp
+ }
+}