11
11
#include " base/string_utils.hpp"
12
12
#include " base/timer.hpp"
13
13
14
- #include " std/ chrono.hpp "
15
- #include " std/ future.hpp "
14
+ #include < chrono>
15
+ #include < future>
16
16
17
17
#include " 3party/pugixml/src/pugixml.hpp"
18
18
19
19
namespace
20
20
{
21
- bool LoadFromXml (pugi::xml_document const & xml, list<editor::Note> & notes,
21
+ bool LoadFromXml (pugi::xml_document const & xml, std:: list<editor::Note> & notes,
22
22
uint32_t & uploadedNotesCount)
23
23
{
24
24
uint64_t notesCount;
@@ -55,7 +55,7 @@ bool LoadFromXml(pugi::xml_document const & xml, list<editor::Note> & notes,
55
55
return true ;
56
56
}
57
57
58
- void SaveToXml (list<editor::Note> const & notes, pugi::xml_document & xml,
58
+ void SaveToXml (std:: list<editor::Note> const & notes, pugi::xml_document & xml,
59
59
uint32_t const uploadedNotesCount)
60
60
{
61
61
auto constexpr kDigitsAfterComma = 7 ;
@@ -74,9 +74,10 @@ void SaveToXml(list<editor::Note> const & notes, pugi::xml_document & xml,
74
74
}
75
75
76
76
// / Not thread-safe, use only for initialization.
77
- bool Load (string const & fileName, list<editor::Note> & notes, uint32_t & uploadedNotesCount)
77
+ bool Load (std::string const & fileName, std::list<editor::Note> & notes,
78
+ uint32_t & uploadedNotesCount)
78
79
{
79
- string content;
80
+ std:: string content;
80
81
try
81
82
{
82
83
auto const reader = GetPlatform ().GetReader (fileName);
@@ -111,30 +112,31 @@ bool Load(string const & fileName, list<editor::Note> & notes, uint32_t & upload
111
112
}
112
113
113
114
// / Not thread-safe, use synchronization.
114
- bool Save (string const & fileName, list<editor::Note> const & notes,
115
+ bool Save (std:: string const & fileName, std:: list<editor::Note> const & notes,
115
116
uint32_t const uploadedNotesCount)
116
117
{
117
118
pugi::xml_document xml;
118
119
SaveToXml (notes, xml, uploadedNotesCount);
119
- return my::WriteToTempAndRenameToFile (
120
- fileName, [&xml](string const & fileName) { return xml.save_file (fileName.data (), " " ); });
120
+ return my::WriteToTempAndRenameToFile (fileName, [&xml](std::string const & fileName) {
121
+ return xml.save_file (fileName.data (), " " );
122
+ });
121
123
}
122
124
} // namespace
123
125
124
126
namespace editor
125
127
{
126
- shared_ptr<Notes> Notes::MakeNotes (string const & fileName, bool const fullPath)
128
+ std:: shared_ptr<Notes> Notes::MakeNotes (std:: string const & fileName, bool const fullPath)
127
129
{
128
- return shared_ptr<Notes>(
130
+ return std:: shared_ptr<Notes>(
129
131
new Notes (fullPath ? fileName : GetPlatform ().WritablePathForFile (fileName)));
130
132
}
131
133
132
- Notes::Notes (string const & fileName) : m_fileName(fileName)
134
+ Notes::Notes (std:: string const & fileName) : m_fileName(fileName)
133
135
{
134
136
Load (m_fileName, m_notes, m_uploadedNotesCount);
135
137
}
136
138
137
- void Notes::CreateNote (ms::LatLon const & latLon, string const & text)
139
+ void Notes::CreateNote (ms::LatLon const & latLon, std:: string const & text)
138
140
{
139
141
if (text.empty ())
140
142
{
@@ -148,7 +150,14 @@ void Notes::CreateNote(ms::LatLon const & latLon, string const & text)
148
150
return ;
149
151
}
150
152
151
- lock_guard<mutex> g (m_mu);
153
+ std::lock_guard<std::mutex> g (m_mu);
154
+ auto const it = std::find_if (m_notes.begin (), m_notes.end (), [&latLon, &text](Note const & note) {
155
+ return latLon.EqualDxDy (note.m_point , kTolerance ) && text == note.m_note ;
156
+ });
157
+ // No need to add the same note. It works in case when saved note are not uploaded yet.
158
+ if (it != m_notes.end ())
159
+ return ;
160
+
152
161
m_notes.emplace_back (latLon, text);
153
162
Save (m_fileName, m_notes, m_uploadedNotesCount);
154
163
}
@@ -159,20 +168,19 @@ void Notes::Upload(osm::OsmOAuth const & auth)
159
168
auto const self = shared_from_this ();
160
169
161
170
auto const doUpload = [self, auth]() {
162
- size_t size;
163
-
164
- {
165
- lock_guard<mutex> g (self->m_mu );
166
- size = self->m_notes .size ();
167
- }
168
-
171
+ std::unique_lock<std::mutex> ulock (self->m_mu );
172
+ // Size of m_notes is decreased only in this method.
173
+ size_t size = notes.size ();
174
+ auto & notes = self->m_notes ;
169
175
osm::ServerApi06 api (auth);
170
- auto it = begin (self-> m_notes );
171
- for ( size_t i = 0 ; i != size; ++i, ++it )
176
+
177
+ while ( size > 0 )
172
178
{
173
179
try
174
180
{
175
- auto const id = api.CreateNote (it->m_point , it->m_note );
181
+ ulock.unlock ();
182
+ auto const id = api.CreateNote (notes.front ().m_point , notes.front ().m_note );
183
+ ulock.lock ();
176
184
LOG (LINFO, (" A note uploaded with id" , id));
177
185
}
178
186
catch (osm::ServerApi06::ServerApi06Exception const & e)
@@ -182,35 +190,34 @@ void Notes::Upload(osm::OsmOAuth const & auth)
182
190
return ;
183
191
}
184
192
185
- lock_guard<mutex> g (self-> m_mu );
186
- it = self-> m_notes . erase (it) ;
193
+ notes. pop_front ( );
194
+ --size ;
187
195
++self->m_uploadedNotesCount ;
188
196
Save (self->m_fileName , self->m_notes , self->m_uploadedNotesCount );
189
197
}
190
198
};
191
199
192
- // Do not run more than one upload thread at a time.
193
- static auto future = async (launch::async, doUpload);
194
- auto const status = future.wait_for (milliseconds (0 ));
195
- if (status == future_status::ready)
196
- future = async (launch::async, doUpload);
200
+ static auto future = std::async (std::launch::async, doUpload);
201
+ auto const status = future.wait_for (std::chrono::milliseconds (0 ));
202
+ if (status == std::future_status::ready)
203
+ future = std::async (std::launch::async, doUpload);
197
204
}
198
205
199
- vector <Note> const Notes::GetNotes () const
206
+ std::list <Note> Notes::GetNotes () const
200
207
{
201
- lock_guard<mutex> g (m_mu);
202
- return { begin ( m_notes), end (m_notes)} ;
208
+ std:: lock_guard<std:: mutex> g (m_mu);
209
+ return m_notes;
203
210
}
204
211
205
212
size_t Notes::NotUploadedNotesCount () const
206
213
{
207
- lock_guard<mutex> g (m_mu);
214
+ std:: lock_guard<std:: mutex> g (m_mu);
208
215
return m_notes.size ();
209
216
}
210
217
211
218
size_t Notes::UploadedNotesCount () const
212
219
{
213
- lock_guard<mutex> g (m_mu);
220
+ std:: lock_guard<std:: mutex> g (m_mu);
214
221
return m_uploadedNotesCount;
215
222
}
216
223
} // namespace editor
0 commit comments