Recommendations for Developers¶
This section provides general recommendations and solutions to common problems encountered by plugin developers.
Multithreading¶
Key aspects of working with threads:
- Calls to Server API methods (e.g., the IMTServerAPI interface: Group, Symbol, etc.) are thread-safe. They can be invoked from different threads without additional synchronization.
- Calls to object interface methods (e.g., IMTConGroup, IMTConSymbol, IMTConGateway, etc.) are NOT thread-safe. When accessing the same object from multiple threads, synchronization must be handled manually.
- Sequential invocation of hooks and events is not guaranteed. Multiple hook or event handlers (even of the same type) may be triggered simultaneously, each in a separate thread. Therefore, your handlers must be thread-safe.
- Synchronous calls from client-base events/hooks (e.g., IMTUserSink) to the trading database in plugins are forbidden. Violating this may cause deadlocks and server crashes.
- Calls from trading events/hooks to the client database are allowed (all IMTServerAPI::User* methods, except those related to trading activity: UserAccountGet, UserDepositChange, UserDepositChangeRaw).
- All plugin components must be implemented with thread safety in mind, except for calls to IMTServerAPI methods.
Interaction with Trading Server Threads¶
- Do not interfere with server threads and do not use custom synchronization primitives that affect server threads (especially in hooks).
- Data grouping for open orders and positions is done per client group, each using its own synchronization primitive.
- Trading databases (orders, history, trades, positions) also use their own synchronization primitives.
- In general, request processing follows a thread chain: initial check, routing, execution — with locking of the required client groups.
- Incoming quotes, as well as symbol and group changes, are handled by a separate thread pool with corresponding locks.
- Execution of trade requests from gateways is handled by a dedicated thread, in the order they arrive, with locking of the relevant groups.
- Many events and hooks are invoked "under lock" — including group and/or trading database locks.
Interaction between trading and client databases is one-way only:
The trading database always accesses the client database, but never the other way around.
To avoid deadlocks:¶
- Minimize direct and indirect access to data of other groups from hooks (e.g., fetching data from other orders/positions/accounts).
- Minimize the use of custom synchronization primitives.
- Do not attempt to explicitly control server threads (stop, synchronize, etc.).
- In hooks and client-base events (e.g., IMTUserSink::OnUser, HookUser), API methods related to the trading database (e.g., IMTServerAPI::PositionGet) must not be called.
- In IMTDealSink events, synchronous calls to methods for creating/modifying/deleting trades are allowed only for trades in the same group. For working with other groups, use asynchronous calls in a separate thread.
Memory Management¶
- Plugins operate within the server’s address space; therefore, they must be memory-efficient and avoid excessive reallocation (fragmentation).
- All interface objects are allocated via Create methods and released via Release.
- If the API allocates memory (e.g., the IMTServerAPI::UserLogins function returns an array of clients), it must be freed using IMTServerAPI::Free.
- Use IMTServerAPI::Allocate for memory allocation (paired with Free).
Working with Configuration and Data Interfaces¶
- Methods like Add, Update, Delete, Clear for object interfaces modify only the local object. To apply changes to the server, call the corresponding Server API method.
- For example, IMTConGroup::SymbolUpdate changes the symbol settings only in the local object. To send the changes to the server, call IMTServerAPI::GroupAdd.
Escaping Special Characters¶
- When passing special characters (=, |, \, newline) in method parameters, they must be escaped with a backslash ().
- If a backslash is not followed by a special character, it is interpreted as a regular character.
Examples:
| Sent to server | Interpreted as |
|---|---|
| \= | = |
| | | |
| (newline) | (newline) |
| \ | \ |