File size: 2,957 Bytes
053b80b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#ifndef _NOTIFICATION_HANDLER_H_
#define _NOTIFICATION_HANDLER_H_


#include <memory>
#include <map>
#include <vector>
#include <functional>
#include <future>

#include "common/KBasicException.h"
#include "common/KDetailedException.h"

#include "messages/Frame.pb.h"

#include "ITransportClient.h"
#include "IRouterClient.h"

namespace Kinova
{
namespace Api
{

    struct AbstractCallbackFunction

    {
        AbstractCallbackFunction() = default;
        virtual ~AbstractCallbackFunction() = default;

        virtual Error call(Frame& msgFrameNotif) = 0;
    };

    template <class DataType>
    struct CallbackFunction : public AbstractCallbackFunction
    {
        static constexpr bool isOk = std::is_base_of<::google::protobuf::Message, DataType>::value;
        static_assert(isOk, "DataType must inherit from ::google::protobuf::Message");

        std::function< void (DataType) > m_callbackFct;

        CallbackFunction(std::function< void(DataType) > callback) : AbstractCallbackFunction() { m_callbackFct = callback; }
        virtual ~CallbackFunction() override {}

        virtual Error call(Frame& msgFrameNotif) override
        {
            Error error;
            error.set_error_code(ErrorCodes::ERROR_NONE);

            DataType decodedMsgNotif;
            if( !decodedMsgNotif.ParseFromString(msgFrameNotif.payload()) )
            {
                HeaderInfo headerInfo( msgFrameNotif.header() );

                error.set_error_code(ERROR_PROTOCOL_CLIENT);
                error.set_error_sub_code(PAYLOAD_DECODING_ERR);
                error.set_error_sub_string(string("The data payload could not be deserialized : notification for serviceId=") + to_string(headerInfo.m_serviceInfo.serviceId) + " \n");
            }
            else
            {
                // todo ???  thread(m_callbackFct, move(decodedMsgNotif)).detach();
                thread(m_callbackFct, decodedMsgNotif).detach();
            }

            return error;
        }
    };

    // todoErr add the validation information beside the callback
    typedef std::unordered_map< uint32_t, std::unique_ptr<AbstractCallbackFunction>> CallbackMap;

    class NotificationHandler

    {
        CallbackMap     m_callbackMap;
        std::mutex      m_mutex;

    public:
        NotificationHandler();
        ~NotificationHandler();

        template <class DataType>
        void addCallback( uint32_t idKey, std::function<void(DataType)> callback )
        {
            std::lock_guard<std::mutex> w_scoped(m_mutex);
            std::unique_ptr<AbstractCallbackFunction> fct{new CallbackFunction<DataType>(callback)};
            m_callbackMap[idKey] = std::move(fct);
        }

        void clearIdKeyCallbacks( uint32_t idKey );
        void clearAll();

        Error call(Frame& msgFrameNotif);
    };

}
}

#endif // _NOTIFICATION_HANDLER_H_