root/Enterprise/branches/0075_TR_SCRIPTING/AppServer/scriptable_generic_service.hpp @ 3430

Revision 3430, 22.3 KB (checked in by mgray, 7 months ago)

Fleshed out implementation of scriptable_generic_service and refactored AppServer? interfaces to use it correctly (and vice versa)

Line 
1//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
2// Zen Enterprise Framework
3//
4// Copyright (C) 2001 - 2010 Tony Richards
5//
6//  This software is provided 'as-is', without any express or implied
7//  warranty.  In no event will the authors be held liable for any damages
8//  arising from the use of this software.
9//
10//  Permission is granted to anyone to use this software for any purpose,
11//  including commercial applications, and to alter it and redistribute it
12//  freely, subject to the following restrictions:
13//
14//  1. The origin of this software must not be misrepresented; you must not
15//     claim that you wrote the original software. If you use this software
16//     in a product, an acknowledgment in the product documentation would be
17//     appreciated but is not required.
18//  2. Altered source versions must be plainly marked as such, and must not be
19//     misrepresented as being the original software.
20//  3. This notice may not be removed or altered from any source distribution.
21//
22//  Tony Richards trichards@indiezen.com
23//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
24#ifndef ZEN_APPSERVER_SCRIPTABLE_GENERIC_SERVICE_HPP_INCLUDED
25#define ZEN_APPSERVER_SCRIPTABLE_GENERIC_SERVICE_HPP_INCLUDED
26
27#include <Zen/Core/Memory/managed_ptr.hpp>
28#include <Zen/Core/Memory/managed_weak_ptr.hpp>
29#include <Zen/Core/Memory/managed_self_ref.hpp>
30
31#include <Zen/Core/Threading/I_Mutex.hpp>
32#include <Zen/Core/Threading/MutexFactory.hpp>
33#include <Zen/Core/Threading/CriticalSection.hpp>
34
35#include <Zen/Core/Scripting.hpp>
36
37#include <Zen/Enterprise/AppServer/I_ApplicationService.hpp>
38#include <Zen/Enterprise/AppServer/I_ApplicationServer.hpp>
39
40#include <Zen/Enterprise/AppServer/I_MessageType.hpp>
41#include <Zen/Enterprise/AppServer/I_Request.hpp>
42#include <Zen/Enterprise/AppServer/I_RequestHandler.hpp>
43#include <Zen/Enterprise/AppServer/I_Response.hpp>
44#include <Zen/Enterprise/AppServer/I_ResponseHandler.hpp>
45#include <Zen/Enterprise/AppServer/I_ProtocolService.hpp>
46
47#include <Zen/Enterprise/Networking/I_Endpoint.hpp>
48
49#include <map>
50
51//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
52namespace Zen {
53    namespace Threading {
54        class ThreadPool;
55    } // namespace Threading
56namespace Enterprise {
57namespace AppServer {
58//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
59namespace detail {
60//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
61;
62/// base response handler.
63/// Used to make the I_ResponseHandler destructor public.
64class base_response_handler
65: public I_ResponseHandler
66{
67public:
68    virtual ~base_response_handler()
69    {
70    }
71
72};  // class base_response_handler
73
74//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
75/// Server side response handler.
76/// When the server recieves a request as a message (i.e. not as an
77/// internal request, but as a request recieved via a protocol adapter)
78/// a server_response_handler is created and the request is dispatched
79/// to the appropriate request handler.  When the request handler
80/// is finished and has a reply, it invokes I_ResponseHandler::handleReponse()
81/// with the reply.  This lightweight handler simply sends the response
82/// back to the application server which in turn (filters?) and then sends
83/// the message to the client.
84class server_response_handler
85:   public base_response_handler
86{
87public:
88    virtual void handleResponse(pResponse_type _pResponse)
89    {
90        // Send the response back to the app server.
91        m_appServer.handleMessage(_pResponse);
92    }
93
94    server_response_handler(I_ApplicationServer& _appServer)
95    :   m_appServer(_appServer) 
96    {
97    }
98
99    virtual ~server_response_handler()
100    {
101    }
102
103    static inline void destroy(Memory::managed_weak_ptr<I_ResponseHandler> _pResponseHandler)
104    {
105        delete dynamic_cast<base_response_handler*>(_pResponseHandler.get());
106    }
107
108private:
109    I_ApplicationServer&        m_appServer;
110};
111
112//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
113/// Response handler for the client side.
114/// When a client sends a request, it creates this response handler and
115/// associates a request, payload and handler function with the request.
116/// When the reply comes back from the server, the function is invoked,
117/// passing the original request, the response and the payload.
118/// This provides a mechanism by which the client application can
119/// have additional data associated with the request.
120template<typename Request_type, typename Payload_type>
121struct client_response_handler
122:   public I_ResponseHandler
123{
124    typedef typename Request_type::pRequest_type                pRequest_type;
125    typedef boost::function<void(pResponse_type, Request_type&, Payload_type)>  Function_type;
126
127    virtual void handleResponse(pResponse_type _pResponse)
128    {
129        // Use the function to dispatch the handler.
130        m_function(_pResponse, *dynamic_cast<Request_type*>(m_pRequest.get()), m_payload);
131    }
132
133    client_response_handler(pRequest_type _pRequest, Payload_type _payload, Function_type _function)
134    :   m_function(_function)
135    ,   m_pRequest(_pRequest)
136    ,   m_payload(_payload)
137    {
138    }
139
140    virtual ~client_response_handler()
141    {
142    }
143
144public:
145
146    Function_type               m_function;
147    pRequest_type               m_pRequest;
148    Payload_type                m_payload;
149};  // struct client_response_handler
150
151//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
152struct request_handler_base
153:   public I_RequestHandler
154{
155    virtual ~request_handler_base()
156    {
157    }
158};  // struct request_handler_base
159
160//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
161struct request_handler
162:   public request_handler_base
163{
164    typedef boost::function<void(pRequest_type, pResponseHandler_type)>    Function_type;
165
166    virtual void handleRequest(pRequest_type _pRequest, pResponseHandler_type _pResponseHandler)
167    {
168        m_function(_pRequest, _pResponseHandler);
169    }
170
171    request_handler(Function_type _function)
172    :   m_function(_function)
173    {
174    }
175
176    virtual ~request_handler()
177    {
178    }
179
180public:
181
182    Function_type               m_function;
183};  // struct request_handler
184
185//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
186} // namespace detail
187//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
188
189template<typename Request_type, typename Payload_type>
190class create_request
191{
192    /// @name Types
193    /// @{
194public:
195    typedef Zen::Memory::managed_ptr<Zen::Networking::I_Endpoint>   pEndpoint_type;
196    typedef typename Request_type::pRequest_type                    pRequest_type;
197    /// @}
198
199public:
200    inline
201    Request_type* operator->()
202    {
203        return m_pRawRequest;
204    }
205
206    /// @name 'Structors
207    /// @{
208public:
209    inline
210    create_request(pEndpoint_type _pEndpoint, Payload_type _payload)
211    :   m_payload(_payload)
212    ,   m_pRequest(Request_type::create(pEndpoint_type(), _pEndpoint))
213    {
214        m_pRawRequest = dynamic_cast<typename Request_type*>(m_pRequest.get());
215    }
216    /// @}
217
218    /// @name Member Variables
219    /// @{
220public:
221    Payload_type                m_payload;
222    Request_type*               m_pRawRequest;
223    pRequest_type               m_pRequest;   
224    /// @}
225};
226
227template<typename BaseClass_type, typename Class_type>
228class scriptable_generic_service
229:   public BaseClass_type
230,   public Zen::Scripting::I_ScriptableService
231,   public Zen::Memory::managed_self_ref<BaseClass_type>
232{
233    /// @name Types
234    /// @{
235public:
236    typedef Class_type*                                             pScriptObject_type;
237    typedef Zen::Scripting::ObjectReference<Class_type>             ScriptObjectReference_type;
238    typedef ScriptObjectReference_type                              ScriptWrapper_type;
239    typedef ScriptWrapper_type*                                     pScriptWrapper_type;
240
241    typedef Zen::Memory::managed_ptr<Zen::Networking::I_Endpoint>   pEndpoint_type;
242    typedef I_ApplicationServer::pResponseHandler_type              pResponseHandler_type;
243    typedef I_ApplicationServer::pRequest_type                      pRequest_type;
244    typedef I_ApplicationServer::pResponse_type                     pResponse_type;
245    typedef I_ApplicationServer::pMessage_type                      pMessage_type;
246
247    typedef Memory::managed_ptr<I_ResponseHandler>                  pResponseHandler_type;
248    typedef std::map<unsigned int, pResponseHandler_type>           ResponseHandlers_type;
249
250    typedef Zen::Memory::managed_ptr<I_MessageType>                 pMessageType_type;
251    typedef Zen::Memory::managed_ptr<I_RequestHandler>              pRequestHandler_type;
252    typedef std::map<pMessageType_type, pRequestHandler_type>       RequestHandlers_type;
253
254    //typedef Zen::Memory::managed_ptr<I_MessageHandler>              pMessageHandler_type;
255    //typedef std::map<pMessageType_type, pMessageHandler_type>       MessageHandlers_type;
256    /// @}
257
258    /// @name I_StartupShutdownParticipant implementation
259    /// @{
260public:
261    virtual void setConfiguration(const Zen::Plugins::I_ConfigurationElement& _config);
262    virtual Zen::Threading::I_Condition* prepareToStart(Zen::Threading::ThreadPool& _threadPool);
263    virtual void start();
264    virtual Zen::Threading::I_Condition* prepareToStop();
265    virtual void stop();
266    /// @}
267
268    /// @name I_RequestHandler implementation
269    /// @{
270public:
271    virtual void handleRequest(pRequest_type _pRequest, pResponseHandler_type _pResponseHandler);
272    /// @}
273
274    /// @name I_ApplicationService implementation
275    /// @{
276public:
277    virtual I_ApplicationServer& getApplicationServer();
278    virtual void handleMessage(pMessage_type _pMessage);
279    /// @}
280
281    /// @name Implementation
282    /// @{
283public:
284    template<typename Request_type, typename Payload_type>
285    void send(create_request<Request_type, Payload_type>& _request, boost::function<void(pResponse_type, Request_type&, Payload_type)> _function);
286
287    void registerRequestHandler(pMessageType_type _pMessageType, boost::function<void(pRequest_type, pResponseHandler_type)> _function);
288    void unregisterRequestHandler(pMessageType_type _pMessageType);
289
290    void registerMessageHandler(pMessageType_type _pMessageType, boost::function<void(pMessage_type)> _function);
291    void unregisterMessageHandler(pMessageType_type _pMessageType);
292    /// @}
293
294    /// @name 'Structors
295    /// @{
296protected:
297             scriptable_generic_service(Zen::Enterprise::AppServer::I_ApplicationServer& _appServer);
298    virtual ~scriptable_generic_service();
299    /// @}
300
301    /// @name Member Variables
302    /// @{
303private:
304    I_ApplicationServer&                                m_appServer;
305
306    /// Map from getRequestId() to the response handler.
307    ResponseHandlers_type                                m_responseHandlers;
308
309    /// Map from pMessageType_type to the request handler.
310    RequestHandlers_type                                m_requestHandlers;
311
312    /// Map from pMessageType_type to the message handler.
313    //MessageHandlers_type                                m_messageHandlers;
314
315    /// Mutex to guard m_responseHandlers.
316    Zen::Threading::I_Mutex*                            m_pHandlersMutex;
317
318protected:
319    /// Thread Pool from the application server.
320    /// Use this if you need a thread instead of spawning one yourself.
321    Zen::Threading::ThreadPool*                         m_pThreadPool;
322    /// @}
323};  // template scriptable_generic_service
324
325//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
326template<typename BaseClass_type, typename Class_type>
327inline
328scriptable_generic_service<BaseClass_type, Class_type>::scriptable_generic_service(Zen::Enterprise::AppServer::I_ApplicationServer& _appServer)
329:       m_appServer(_appServer)
330,       m_pHandlersMutex(Zen::Threading::MutexFactory::create())
331{
332}
333
334//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
335template<typename BaseClass_type, typename Class_type>
336inline
337scriptable_generic_service<BaseClass_type, Class_type>::~scriptable_generic_service()
338{
339    Zen::Threading::MutexFactory::destroy(m_pHandlersMutex);
340}
341
342//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
343template<typename BaseClass_type, typename Class_type>
344inline
345void
346scriptable_generic_service<BaseClass_type, Class_type>::setConfiguration(const Zen::Plugins::I_ConfigurationElement& _config)
347{
348}
349
350//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
351template<typename BaseClass_type, typename Class_type>
352inline
353Zen::Threading::I_Condition*
354scriptable_generic_service<BaseClass_type, Class_type>::prepareToStart(Zen::Threading::ThreadPool& _threadPool)
355{
356    m_pThreadPool = &_threadPool;
357
358    // Ready to go, so don't bother returning a condition variable
359    return NULL;
360}
361
362//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
363template<typename BaseClass_type, typename Class_type>
364inline
365void
366scriptable_generic_service<BaseClass_type, Class_type>::start()
367{
368}
369
370//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
371template<typename BaseClass_type, typename Class_type>
372inline
373Zen::Threading::I_Condition*
374scriptable_generic_service<BaseClass_type, Class_type>::prepareToStop()
375{
376    return NULL;
377}
378
379//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
380template<typename BaseClass_type, typename Class_type>
381inline
382void
383scriptable_generic_service<BaseClass_type, Class_type>::stop()
384{
385}
386
387//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
388template<typename BaseClass_type, typename Class_type>
389I_ApplicationServer&
390scriptable_generic_service<BaseClass_type, Class_type>::getApplicationServer()
391{
392    return m_appServer;
393}
394
395//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
396template<typename BaseClass_type, typename Class_type>
397inline
398void
399scriptable_generic_service<BaseClass_type, Class_type>::handleMessage(pMessage_type _pMessage)
400{
401    // Handle an inbound message, request or response.
402
403    // Check to see if it's a response
404    Zen::Memory::managed_ptr<I_Response> pResponse(
405        _pMessage.as<Zen::Memory::managed_ptr<I_Response> >());
406
407    // If it is a response, handle it.
408    if(pResponse.isValid())
409    {
410        pResponseHandler_type pHandler;
411
412        // Find the handler
413        {
414            Zen::Threading::CriticalSection guard(m_pHandlersMutex);
415            ResponseHandlers_type::iterator iter = m_responseHandlers.find(pResponse->getRequestMessageId());
416
417            if(iter != m_responseHandlers.end())
418            {
419                pHandler = iter->second;
420
421                m_responseHandlers.erase(iter);
422            }
423        }
424
425        // If the handler was found, use it.
426        if (pHandler.isValid())
427        {
428            // Dispatch the response
429            pHandler->handleResponse(pResponse);
430        }
431        else
432        {
433            // Probably a duplicate response... just ignore it
434            // Or maybe it was a message that timed out?
435        }
436    }
437    else
438    {
439        // Not a response.  Is it a request or a message?
440        // TODO Implement
441
442        // Check to see if it's a request
443        Zen::Memory::managed_ptr<I_Request> pRequest(
444            _pMessage.as<Zen::Memory::managed_ptr<I_Request> >());
445
446        if( pRequest.isValid() )
447        {
448            // TODO If this is a request, create a lightweight response handler then
449            // dispatch to scriptable_generic_service::handleRequest.
450            // This code path is invoked only when the message is coming from a
451            // protocol adapter.  When the response handler handleResponse() is called,
452            // it should simply dispatch to AppServer::handleMessage().  Since
453            // the destination endpoint is outbound, the app server will send it
454            // via the appropriate protocol adapter.
455
456            // If we use detail::client_response_handler here, where do payload and function
457            // come from?
458            RequestHandlers_type::iterator iter = m_requestHandlers.find(pRequest->getMessageType());
459
460            if (iter != m_requestHandlers.end())
461            {
462                pResponseHandler_type pResponseHandler
463                (
464                    new detail::server_response_handler(this->getApplicationServer()),
465                    &detail::server_response_handler::destroy
466                );
467                iter->second->handleRequest(pRequest, pResponseHandler);
468            }
469            else
470            {
471                // No request handler.
472                // TODO Pass the request to a default request handler.
473                throw Utility::runtime_exception("scriptable_generic_service::handleMessage(): Error, no handler specified for message type");
474            }
475        }
476
477        throw Utility::runtime_exception("scriptable_generic_service::handleMessage(): Error, handling request or message is not implemented.");
478    }
479}
480
481//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
482inline void destroyResponseHandler(Memory::managed_weak_ptr<I_ResponseHandler> _pHandler)
483{
484    delete dynamic_cast<detail::base_response_handler*>(_pHandler.get());
485}
486
487//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
488template<typename BaseClass_type, typename Class_type>
489template<typename Request_type, typename Payload_type>
490inline
491void
492scriptable_generic_service<BaseClass_type, Class_type>::send(create_request<Request_type, Payload_type>& _request, boost::function<void(pResponse_type, Request_type&, Payload_type)> _function)
493{
494    // Send an outbound request.
495    detail::client_response_handler<Request_type, Payload_type>* pRawHandler = 
496        new detail::client_response_handler<Request_type, Payload_type>(
497            _request.m_pRequest, 
498            _request.m_payload, 
499            _function
500        );
501
502    Memory::managed_ptr<I_ResponseHandler> pHandler(pRawHandler, destroyResponseHandler);
503
504    {
505        Zen::Threading::CriticalSection guard(m_pHandlersMutex);
506        m_responseHandlers[_request.m_pRawRequest->getMessageId()] = pHandler;
507    }
508
509    getApplicationServer().handleRequest(_request.m_pRequest, pHandler);
510}
511
512//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
513template<typename BaseClass_type, typename Class_type>
514inline
515void
516scriptable_generic_service<BaseClass_type, Class_type>::handleRequest(pRequest_type _pRequest, pResponseHandler_type _pResponseHandler)
517{
518    // Handle an inbound request.
519    RequestHandlers_type::iterator iter = m_requestHandlers.find(_pRequest->getMessageType());
520    if( iter != m_requestHandlers.end() )
521    {
522        iter->second->handleRequest(_pRequest, _pResponseHandler);
523    }
524
525    // This code was here for cases where the App Server sent outgoing requests
526    // back through the service.  App Server should not send it back through
527    // the service if the destionation endpoint is outbound.
528#if 0 // deprecated
529
530    ResponseHandlers_type::iterator iter = m_responseHandlers.find(_pRequest->getMessageId());
531    if(iter == m_responseHandlers.end())
532    {
533        m_responseHandlers[_pRequest->getMessageId()] = _pResponseHandler;
534    }
535
536    _pRequest->getDestinationEndpoint()->getProtocolAdapter().lock()->sendTo(
537        _pRequest,
538        _pRequest->getDestinationEndpoint()
539    );
540#endif // deprecated
541}
542
543//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
544inline void destroyRequestHandler(Memory::managed_weak_ptr<I_RequestHandler> _pRequestHandler)
545{
546    delete dynamic_cast<detail::request_handler_base*>(_pRequestHandler.get());
547}
548
549//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
550template<typename BaseClass_type, typename Class_type>
551inline
552void
553scriptable_generic_service<BaseClass_type, Class_type>::registerRequestHandler(pMessageType_type _pMessageType, boost::function<void(pRequest_type, pResponseHandler_type)> _function)
554{
555    RequestHandlers_type::iterator iter = m_requestHandlers.find(_pMessageType);
556    if( iter == m_requestHandlers.end() )
557    {
558        I_RequestHandler* pRaw = new detail::request_handler(_function);
559
560        pRequestHandler_type pRequestHandler(
561            pRaw,
562            destroyRequestHandler
563        );
564        m_requestHandlers[_pMessageType] = pRequestHandler;
565    }
566
567    /// TODO Exception?
568}
569
570//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
571template<typename BaseClass_type, typename Class_type>
572inline
573void
574scriptable_generic_service<BaseClass_type, Class_type>::unregisterRequestHandler(pMessageType_type _pMessageType)
575{
576    RequestHandlers_type::iterator iter = m_requestHandlers.find(_pMessageType);
577    if( iter != m_requestHandlers.end() )
578    {
579        m_requestHandlers.erase(iter);
580    }
581
582    /// TODO Exception?
583}
584
585//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
586template<typename BaseClass_type, typename Class_type>
587inline
588void
589scriptable_generic_service<BaseClass_type, Class_type>::registerMessageHandler(pMessageType_type _pMessageType, boost::function<void(pMessage_type)> _function)
590{
591    throw Zen::Utility::runtime_exception("scriptable_generic_service::registerMessageHandler() : Error, not implemented.");
592}
593
594//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
595template<typename BaseClass_type, typename Class_type>
596inline
597void
598scriptable_generic_service<BaseClass_type, Class_type>::unregisterMessageHandler(pMessageType_type _pMessageType)
599{
600    throw Zen::Utility::runtime_exception("scriptable_generic_service::unregisterMessageHandler() : Error, not implemented.");
601}
602
603//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
604}   // namespace AppServer
605}   // namespace Enterprise
606}   // namespace Zen
607//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
608
609#endif // ZEN_APPSERVER_SCRIPTABLE_GENERIC_SERVICE_HPP_INCLUDED
Note: See TracBrowser for help on using the browser.