1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* -*- C++ -*- */
/****************************************************************************
** Copyright (c) 2001-2014
**
** This file is part of the QuickFIX FIX Engine
**
** This file may be distributed under the terms of the quickfixengine.org
** license as defined by quickfixengine.org and appearing in the file
** LICENSE included in the packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.quickfixengine.org/LICENSE for licensing information.
**
** Contact ask@quickfixengine.org if any conditions of this licensing are
** not clear to you.
**
****************************************************************************/
#ifndef FIX_APPLICATION_H
#define FIX_APPLICATION_H
#include "Message.h"
#include "Mutex.h"
#include "SessionID.h"
namespace FIX {
/**
* This interface must be implemented to define what your %FIX application
* does.
*
* These methods notify your application about events that happen on
* active %FIX sessions. There is no guarantee how many threads will be calling
* these functions. If the application is sharing resources among multiple sessions,
* you must synchronize those resources. You can also use the SynchronizedApplication
* class to automatically synchronize all function calls into your application.
* The various MessageCracker classes can be used to parse the generic message
* structure into specific %FIX messages.
*/
class Application {
public:
virtual ~Application() {};
/// Notification of a session begin created
virtual void onCreate(const SessionID &) = 0;
/// Notification of a session successfully logging on
virtual void onLogon(const SessionID &) = 0;
/// Notification of a session logging off or disconnecting
virtual void onLogout(const SessionID &) = 0;
/// Notification of admin message being sent to target
virtual void toAdmin(Message &, const SessionID &) = 0;
/// Notification of app message being sent to target
virtual void toApp(Message &, const SessionID &) EXCEPT(DoNotSend) = 0;
/// Notification of admin message being received from target
virtual void fromAdmin(const Message &, const SessionID &)
EXCEPT(FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon)
= 0;
/// Notification of app message being received from target
virtual void fromApp(const Message &, const SessionID &)
EXCEPT(FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType)
= 0;
};
/**
* This is a special implementation of the Application interface that takes
* in another Application interface and synchronizes all of its callbacks. This
* will guarantee that only one thread will access the applications code at a time.
*
* This class is a great convenience for writing applications where you
* don't want to worry about synchronization. There is of course a tradeoff
* in that you may be synchronizing more than you need to. There is also a very
* minor performance penalty due to the extra virtual table lookup.
*/
class SynchronizedApplication : public Application {
public:
SynchronizedApplication(Application &app)
: m_app(app) {}
void onCreate(const SessionID &sessionID) {
Locker l(m_mutex);
app().onCreate(sessionID);
}
void onLogon(const SessionID &sessionID) {
Locker l(m_mutex);
app().onLogon(sessionID);
}
void onLogout(const SessionID &sessionID) {
Locker l(m_mutex);
app().onLogout(sessionID);
}
void toAdmin(Message &message, const SessionID &sessionID) {
Locker l(m_mutex);
app().toAdmin(message, sessionID);
}
void toApp(Message &message, const SessionID &sessionID) EXCEPT(DoNotSend) {
Locker l(m_mutex);
app().toApp(message, sessionID);
}
void fromAdmin(const Message &message, const SessionID &sessionID)
EXCEPT(FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon) {
Locker l(m_mutex);
app().fromAdmin(message, sessionID);
}
void fromApp(const Message &message, const SessionID &sessionID)
EXCEPT(FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType) {
Locker l(m_mutex);
app().fromApp(message, sessionID);
}
Mutex m_mutex;
Application &app() { return m_app; }
Application &m_app;
};
/**
* An empty implementation of an Application. This can be used if you
* do not want to provide an implementation for all the callback methods.
* It is also useful for unit tests where the callback
* values of some or all methods are not of interest.
*/
class NullApplication : public Application {
void onCreate(const SessionID &) {}
void onLogon(const SessionID &) {}
void onLogout(const SessionID &) {}
void toAdmin(Message &, const SessionID &) {}
void toApp(Message &, const SessionID &) EXCEPT(DoNotSend) {}
void fromAdmin(const Message &, const SessionID &)
EXCEPT(FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon) {}
void fromApp(const Message &, const SessionID &)
EXCEPT(FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType) {}
};
/*! @} */
} // namespace FIX
#endif // FIX_APPLICATION_H