updates.
[silc.git] / lib / silcclient / README
1 During client library implementation, few things to keep in mind.
2
3 Threads and locking in client library
4
5    The client library is multithreaded in so that the actual SilcClient
6    runs in one main thread (may be application main thread or its created
7    thread for the client), and each connection to a remote host runs in
8    an own thread.  There are no other threads in client library.  If there
9    is only one connection in the client, then most likely there is only
10    one thread in addition of main thread.
11
12    The SilcClient context must be protected with lock (client->internal->lock),
13    because it may be accessed from connection threads and by application.
14    It is guaranteed that the client main thread never access the connection
15    thread, and it is guaranteed that no other connection thread access
16    another connection thread.  Even still, the SilcClientConnection has
17    a lock (conn->internal->lock) because it may be accessed by application.
18
19    Practically everything in the client is executed in the connection thread.
20    Receiving packets, commands, notifys, etc all happen in connection thread.
21    It is not possible to receive packets in two different threads that would
22    be destined to one specific connection thread.  But, because packets and
23    commands may be sent from application thread the connection lock is
24    used to protect shared data in the SilcClientConnection.  It is, however,
25    guaranteed that the main client thread, or other connection thread will
26    not send any packets or commands to another connection.  When remembered
27    this makes programming easier.  Everything happens in one thread that
28    has something to do with the connection.  When packet is received and
29    it is processed asynchronously, it is always guaranteed that it is
30    processed in that same thread, even if it is processed asynchronously.
31    No other thread will process it.  If it is processed synchronously, no
32    other packet may arrive at the same time, not for that connection.
33    But it is possible that while we are processing incoming command reply,
34    application sends another command from application thread.  Because of
35    this, the lock exist in the connection context.
36
37
38 Using locks
39
40    Use locking only if necessary.  For performance reasons SILC Atomic
41    Operations API should be preferred if it can be used to achieve what
42    needs to be achieved.  All reference counters must be atomic integers
43    and locking must not be used with them.
44
45
46 Using FSM
47
48    The client library internals are to be rewritten with SILC FSM and all
49    major operations should be implemented as FSM.
50
51    Always return SILC_FSM_CONTINUE if you need to move to next state
52    synchronously.  Use SILC_FSM_YIELD if you are in FSM thread and
53    peformance is not an issue, but only if there really are other FSM
54    threads that need execution time also.
55
56    In packet processing do not use SILC_FSM_WAIT ever, since in current
57    design all packets are processed in one FSM thread, and if one packet
58    processor puts it into wait state, not other packets are received
59    in the mean time.  Instead go back to silc_client_connection_st_packet
60    with SILC_FSM_CONTINUE, and then in the async function's callback
61    set the old SilcPacket to the packet thread's state context and move back
62    to the packet processor with silc_fsm_next and silc_fsm_continue_sync
63    (always synchronously, never async).  This design may change later,
64    but for now this is it.  This also means that SILC_FSM_CALL must not
65    be used in packet processors because it returns SILC_FSM_WAIT.
66
67
68 When to use FSM semaphore signalling?
69
70    FSM semaphore signalling should be used only when multiple threads
71    (FSM threads) may be waiting for something to happen.  If only one thread
72    is waiting for something it should merely return SILC_FSM_WAIT and when
73    that something happens it should use silc_fsm_continue or
74    silc_fsm_continue_sync to continue in the waiting thread.  OTOH, if
75    multiple threads are waiting SILC_FSM_SEMA_POST is the only way to
76    deliver the signal.  Always remember that posting is signal is not
77    donbe synchronously (it won't be delivered immediately).
78
79    OTOH, if there is only one thread waiting for somtehing to happen but
80    there can be multiple threads signalling that something has happened
81    only way to do this is to use semaphore signalling.
82
83    Semaphore signals should be pre-allocated SilcFSMSemaStruct structures
84    and for signalling use they are always initialized as:
85
86      silc_fsm_sema_init(&sema, fsm, 0);
87
88    The call cannot fail.  Semaphores need not be uninitialized and the same
89    context may be reused.