1 using System;
2 using System.Collections;
3
4 namespace cmsx.kernel
5 {
6 public const long numSessionSlots = 128;
7
8 public class Session
9 {
10 public nothrow Session() : sid(-1), nextFree(null), fgpid(-1)
11 {
12 }
13 public nothrow Session(int sid_) : sid(sid_), nextFree(null), fgpid(-1)
14 {
15 }
16 public int sid;
17 public int fgpid;
18 public Session* nextFree;
19 }
20
21 public class SessionTable
22 {
23 static SessionTable() : instance(new SessionTable())
24 {
25 }
26 public static SessionTable& Instance()
27 {
28 return *instance;
29 }
30 private nothrow SessionTable() : nextFreeSessionSlot(0), nextSid(0), free(null)
31 {
32 }
33 public Session* CreateSession()
34 {
35 Session* session = null;
36 if (free != null)
37 {
38 session = free;
39 free = free->nextFree;
40 }
41 else if (nextFreeSessionSlot < numSessionSlots)
42 {
43 session = &sessions[nextFreeSessionSlot++];
44 }
45 else
46 {
47 throw SystemError(ERLIMITEXCEEDED, "maximum number of open sessions (" + ToString(numSessionSlots) + ") exceeeded");
48 }
49 session->sid = nextSid++;
50 session->nextFree = null;
51 sessionMap[session->sid] = session;
52 return session;
53 }
54 public void FreeSession(Session* session)
55 {
56 sessionMap.Remove(session->sid);
57 session->nextFree = free;
58 session->sid = -1;
59 free = session;
60 }
61 public Session* GetSession(int sid) const
62 {
63 HashMap<int, Session*>.ConstIterator it = sessionMap.CFind(sid);
64 if (it != sessionMap.CEnd())
65 {
66 return it->second;
67 }
68 else
69 {
70 throw SystemError(EINVAL, "invalid session identifier");
71 }
72 }
73 private static UniquePtr<SessionTable> instance;
74 private int nextFreeSessionSlot;
75 private int nextSid;
76 private Session[numSessionSlots] sessions;
77 private HashMap<int, Session*> sessionMap;
78 private Session* free;
79 }
80
81 public SessionTable& GetSessionTable()
82 {
83 return SessionTable.Instance();
84 }
85 }
86