Skip to content

Commit d7b44c4

Browse files
committed
get rid of incorrect information about lock-free implementation; It was based on spinlocks and it is definitely has nothing common with lock-free
1 parent 73e9ac5 commit d7b44c4

8 files changed

+36
-36
lines changed

LineReader.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ std::optional<std::string_view> CMappingLineReader::GetNextLine()
361361
//////////////////////////////////////////////////////////////////////////
362362
//////////////////////////////////////////////////////////////////////////
363363

364-
CLockFreeLineReader::CLockFreeLineReader()
364+
CSpinlockLineReader::CSpinlockLineReader()
365365
{
366366
this->_buffer1.Allocate(ReadBufferSize);
367367
if (this->_buffer1.ptr != nullptr)
@@ -370,7 +370,7 @@ CLockFreeLineReader::CLockFreeLineReader()
370370
}
371371
}
372372

373-
bool CLockFreeLineReader::Open(const wchar_t* const filename)
373+
bool CSpinlockLineReader::Open(const wchar_t* const filename)
374374
{
375375
if (this->_buffer1.ptr == nullptr || filename == nullptr)
376376
{
@@ -389,32 +389,32 @@ bool CLockFreeLineReader::Open(const wchar_t* const filename)
389389
this->_bufferData = std::string_view(this->_buffer1.ptr, 0);
390390
this->_firstBufferIsActive = true;
391391

392-
const bool initLockFreeOk = this->_file.LockFreecInit();
393-
if (!initLockFreeOk)
392+
const bool initSpinlockOk = this->_file.SpinlockInit();
393+
if (!initSpinlockOk)
394394
{
395395
this->_file.Close();
396396
return false;
397397
}
398398

399-
const bool readStartOk = this->_file.LockFreeReadStart(this->_buffer2.ptr + ReadBufferOffset, ReadChunkSize);
399+
const bool readStartOk = this->_file.SpinlockReadStart(this->_buffer2.ptr + ReadBufferOffset, ReadChunkSize);
400400
if (!readStartOk)
401401
{
402-
this->_file.LockFreecClean();
402+
this->_file.SpinlockClean();
403403
this->_file.Close();
404404
return false;
405405
}
406406

407407
return true;
408408
}
409409

410-
void CLockFreeLineReader::Close()
410+
void CSpinlockLineReader::Close()
411411
{
412-
this->_file.LockFreecClean();
412+
this->_file.SpinlockClean();
413413
this->_file.Close();
414414
}
415415

416416
__declspec(noinline) // noinline is added to help CPU profiling in release version
417-
std::optional<std::string_view> CLockFreeLineReader::GetNextLine()
417+
std::optional<std::string_view> CSpinlockLineReader::GetNextLine()
418418
{
419419
if (this->_buffer1.ptr == nullptr)
420420
{
@@ -446,15 +446,15 @@ std::optional<std::string_view> CLockFreeLineReader::GetNextLine()
446446
memcpy(newDataBufferPtr, this->_bufferData.data(), prefixLength);
447447

448448
size_t readBytes = 0;
449-
const bool readCompleteOk = this->_file.LockFreeReadWait(readBytes);
449+
const bool readCompleteOk = this->_file.SpinlockReadWait(readBytes);
450450
if (!readCompleteOk)
451451
{
452452
// Previous reading failed
453453
return {};
454454
}
455455

456456
// Read missing data:
457-
const bool readOk = this->_file.LockFreeReadStart(currentBuffer.ptr + ReadBufferOffset, ReadChunkSize);
457+
const bool readOk = this->_file.SpinlockReadStart(currentBuffer.ptr + ReadBufferOffset, ReadChunkSize);
458458
if (!readOk)
459459
{
460460
// New reading failed

LineReader.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ class CMappingLineReader
7878

7979
//////////////////////////////////////////////////////////////////////////
8080

81-
// Implementation with 2 buffers and separate thread for sync calls to ReadFile(); synchronization is done without Windows EVENTs (lock free)
82-
class CLockFreeLineReader
81+
// Implementation with 2 buffers and separate thread for sync calls to ReadFile(); synchronization is done without Windows EVENTs (manual spin locks)
82+
class CSpinlockLineReader
8383
{
8484
public:
85-
CLockFreeLineReader();
85+
CSpinlockLineReader();
8686

8787
bool Open(const wchar_t* const filename);
8888
void Close();

LogReader.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class CLogReader final
5757
#if 0
5858
CAsyncLineReader _lineReader;
5959
#else
60-
CLockFreeLineReader _lineReader;
60+
CSpinlockLineReader _lineReader;
6161
#endif
6262
#endif
6363
CCharBuffer _pattern;

ScanFile.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ bool CScanFile::Open(const wchar_t* const filename, const bool asyncMode)
6969

7070
void CScanFile::Close()
7171
{
72-
this->LockFreecClean();
72+
this->SpinlockClean();
7373

7474
if (this->_pViewOfFile != nullptr)
7575
{
@@ -242,7 +242,7 @@ bool CScanFile::AsyncReadWait(size_t& readBytes)
242242
/// Implementation of file API executed in a separate thread with the help of spinlocks
243243
//////////////////////////////////////////////////////////////////////////
244244

245-
bool CScanFile::LockFreecInit()
245+
bool CScanFile::SpinlockInit()
246246
{
247247
if (this->_hThread != nullptr)
248248
{
@@ -284,7 +284,7 @@ bool CScanFile::LockFreecInit()
284284
#endif
285285

286286
CScanFile* const that = static_cast<CScanFile*>(p);
287-
that->LockFreeThreadProc();
287+
that->SpinlockThreadProc();
288288
_endthreadex(0);
289289
return 0;
290290
};
@@ -299,7 +299,7 @@ bool CScanFile::LockFreecInit()
299299
return true;
300300
}
301301

302-
void CScanFile::LockFreecClean()
302+
void CScanFile::SpinlockClean()
303303
{
304304
if (this->_hThread != nullptr)
305305
{
@@ -310,7 +310,7 @@ void CScanFile::LockFreecClean()
310310
}
311311

312312
__declspec(noinline) // noinline is added to help CPU profiling in release version
313-
bool CScanFile::LockFreeReadStart(char* const buffer, const size_t bufferLength)
313+
bool CScanFile::SpinlockReadStart(char* const buffer, const size_t bufferLength)
314314
{
315315
if (this->_hThread == nullptr || this->_threadOperationInProgress)
316316
{
@@ -332,7 +332,7 @@ bool CScanFile::LockFreeReadStart(char* const buffer, const size_t bufferLength)
332332
}
333333

334334
__declspec(noinline) // noinline is added to help CPU profiling in release version
335-
bool CScanFile::LockFreeReadWait(size_t& readBytes)
335+
bool CScanFile::SpinlockReadWait(size_t& readBytes)
336336
{
337337
if (this->_hThread == nullptr || !this->_threadOperationInProgress)
338338
{
@@ -359,7 +359,7 @@ bool CScanFile::LockFreeReadWait(size_t& readBytes)
359359
return true;
360360
}
361361

362-
void CScanFile::LockFreeThreadProc()
362+
void CScanFile::SpinlockThreadProc()
363363
{
364364
while (true)
365365
{

ScanFile.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ class CScanFile
2929
bool AsyncReadWait(size_t& readBytes);
3030

3131
// Current limitation: only one async operation can be in progress.
32-
bool LockFreecInit();
33-
void LockFreecClean();
34-
bool LockFreeReadStart(char* const buffer, const size_t bufferLength);
35-
bool LockFreeReadWait(size_t& readBytes);
36-
void LockFreeThreadProc();
32+
bool SpinlockInit();
33+
void SpinlockClean();
34+
bool SpinlockReadStart(char* const buffer, const size_t bufferLength);
35+
bool SpinlockReadWait(size_t& readBytes);
36+
void SpinlockThreadProc();
3737

3838
protected:
3939
alignas(std::hardware_constructive_interference_size) // small speedup to get a bunch of variables into single cache line
@@ -49,7 +49,7 @@ class CScanFile
4949
OVERLAPPED _asyncOverlapped = {};
5050
bool _asyncOperationInProgress = false;
5151

52-
// Separate thread + Lock free:
52+
// Separate thread + spin locks:
5353
HANDLE _hThread = nullptr;
5454

5555
// for protection against wrong API usage, not for use in a worker thread, no memory protection:

TestLineReaderLockFree.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
namespace
1212
{
13-
# define CLineReader CLockFreeLineReader
13+
# define CLineReader CSpinlockLineReader
1414

1515
const size_t MaxLogLineLength = 1024; // copy-pasted value from LineReader.cpp
1616
}

docs/implementation-notes-letter.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Test Task Implementation Notes
1+
# Test Task Implementation Notes
22

33
## Decision progress
44

@@ -66,7 +66,7 @@ The latest application version takes 1.6 seconds to process test data while `gre
6666

6767
**ADDED:**
6868
I also implemented reading the file in a separate thread. The file operation is synchronous,
69-
synchronization between threads is done with the lock free loop (spinlock).
69+
synchronization between threads is done using spinlocks.
7070
It gave a total gain of 25% over the synchronous and asynchronous API solutions (total work time is 1.2 seconds).
7171
This is 2 times faster than `grep`.
7272

@@ -85,7 +85,7 @@ I kept all four implementations of reading files. You can switch them in code:
8585
#if 0
8686
CAsyncLineReader _lineReader;
8787
#else
88-
CLockFreeLineReader _lineReader;
88+
CSpinlockLineReader _lineReader;
8989
#endif
9090
#endif
9191
```

docs/implementation-notes-letter.ru.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@
6464

6565
**ДОПОЛНЕНО:**
6666
Реализовал также чтение файла в отдельном потоке. Файловая операция синхронная,
67-
синхронизация с потоком lock free (spinlock).
67+
синхронизация с рабочим потоком на спинлоках.
6868
Получил общий выигрыш в 25% относительно решения на синхронном и асинхронном API (1.2 секунды).
6969
Итого в 2 раза быстрее чем grep.
7070

7171
## Особенности реализации
7272

73-
В итоге у меня остались все три реализации чтения файлов.
74-
Я оставил асинхронную версию как самую перспективную. Переключаются так:
73+
В итоге у меня остались все четыре реализации чтения файлов.
74+
Я оставил по умолчанию версию на спинлоках как самую перспективную. Переключаются так:
7575

7676
```cpp
7777
#if 0
@@ -84,7 +84,7 @@
8484
#if 0
8585
CAsyncLineReader _lineReader;
8686
#else
87-
CLockFreeLineReader _lineReader;
87+
CSpinlockLineReader _lineReader;
8888
#endif
8989
#endif
9090
```

0 commit comments

Comments
 (0)