1 /*
2 * Copyright (C) 2010 Emweb bv, Herent, Belgium.
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7 #include <Wt/WApplication.h>
8 #include <Wt/WServer.h>
9 #include <Wt/WRandom.h>
10 #include <mutex>
11
12 #include "CodeSession.h"
13
14 std::recursive_mutex CodeSession::mutex_;
15 std::vector<std::weak_ptr<CodeSession>> CodeSession::sessions_;
16
CodeSession(const CoderCallback & coderCallback)17 CodeSession::CodeSession(const CoderCallback& coderCallback)
18 {
19 generateId();
20
21 coder_ = std::make_unique<Coder>();
22 coder_->sessionId = Wt::WApplication::instance()->sessionId();
23 coder_->callback = coderCallback;
24 }
25
~CodeSession()26 CodeSession::~CodeSession()
27 {
28 }
29
addSession(const std::shared_ptr<CodeSession> & session)30 void CodeSession::addSession(const std::shared_ptr<CodeSession> &session)
31 {
32 Lock lock(mutex_);
33 cleanExpiredSessions();
34 sessions_.push_back(session);
35 }
36
addObserver(const std::string & id,const BufferCallback & bufferCallback)37 std::shared_ptr<CodeSession> CodeSession::addObserver(const std::string& id,
38 const BufferCallback& bufferCallback)
39 {
40 Lock lock(mutex_);
41
42 for (auto& sessionPtr : sessions_) {
43 auto session = sessionPtr.lock();
44 if (session && session->id() == id) {
45 Observer observer;
46 observer.sessionId = Wt::WApplication::instance()->sessionId();
47 observer.callback = bufferCallback;
48
49 session->observers_.push_back(observer);
50 session->postSessionChanged();
51
52 return session;
53 }
54 }
55
56 return 0;
57 }
58
removeObserver()59 void CodeSession::removeObserver()
60 {
61 Lock lock(mutex_);
62
63 std::string sessionId = Wt::WApplication::instance()->sessionId();
64
65 for (unsigned i = 0; i < observers_.size(); ++i) {
66 if (observers_[i].sessionId == sessionId) {
67 observers_.erase(observers_.begin() + i);
68
69 postSessionChanged();
70
71 return;
72 }
73 }
74 }
75
removeCoder()76 void CodeSession::removeCoder()
77 {
78 Lock lock(mutex_);
79 coder_.reset();
80 }
81
insertBuffer(int index)82 void CodeSession::insertBuffer(int index)
83 {
84 Lock lock(mutex_);
85
86 buffers_.insert(buffers_.begin() + index, Buffer());
87
88 postBufferChanged(index, Inserted);
89 }
90
updateBuffer(int buffer,const Wt::WString & name,const Wt::WString & text)91 void CodeSession::updateBuffer(int buffer, const Wt::WString& name,
92 const Wt::WString& text)
93 {
94 Lock lock(mutex_);
95
96 buffers_[buffer].name = name;
97 buffers_[buffer].text = text;
98
99 postBufferChanged(buffer, Changed);
100 }
101
buffers()102 std::vector<CodeSession::Buffer> CodeSession::buffers() const
103 {
104 Lock lock(mutex_);
105
106 return buffers_;
107 }
108
buffer(int buffer)109 CodeSession::Buffer CodeSession::buffer(int buffer) const
110 {
111 Lock lock(mutex_);
112
113 return buffers_[buffer];
114 }
115
cleanExpiredSessions()116 void CodeSession::cleanExpiredSessions()
117 {
118 auto it = sessions_.begin();
119
120 while(it != sessions_.end()) {
121 if((*it).expired()) {
122 it = sessions_.erase(it);
123 }
124 else ++it;
125 }
126 }
127
generateId()128 void CodeSession::generateId()
129 {
130 id_ = Wt::WRandom::generateId(32);
131 }
132
postSessionChanged()133 void CodeSession::postSessionChanged()
134 {
135 if (coder_)
136 Wt::WServer::instance()->post(coder_->sessionId, coder_->callback);
137 }
138
postBufferChanged(int buffer,BufferUpdate update)139 void CodeSession::postBufferChanged(int buffer, BufferUpdate update)
140 {
141 for (auto& observer : observers_) {
142 Wt::WServer::instance()
143 ->post(observer.sessionId,
144 std::bind(observer.callback, buffer, update));
145 }
146 }
147