Skip to content

Commit e2a609d

Browse files
committed
Add syntax highlighting for README.md
Related to 6679561 (Added syntax highlighting for samples.md, 2018-12-14).
1 parent 88ab4bd commit e2a609d

1 file changed

Lines changed: 118 additions & 94 deletions

File tree

README.md

Lines changed: 118 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,16 @@ it from many threads at once :-)
9999

100100
Simple example:
101101

102-
#include "concurrentqueue.h"
103-
104-
moodycamel::ConcurrentQueue<int> q;
105-
q.enqueue(25);
106-
107-
int item;
108-
bool found = q.try_dequeue(item);
109-
assert(found && item == 25);
102+
```C++
103+
#include "concurrentqueue.h"
104+
105+
moodycamel::ConcurrentQueue<int> q;
106+
q.enqueue(25);
107+
108+
int item;
109+
bool found = q.try_dequeue(item);
110+
assert(found && item == 25);
111+
```
110112

111113
Description of basic methods:
112114
- `ConcurrentQueue(size_t initialSizeEstimate)`
@@ -180,31 +182,33 @@ in use either, but it can be easier to coordinate the cleanup.)
180182

181183
Blocking example:
182184

183-
#include "blockingconcurrentqueue.h"
184-
185-
moodycamel::BlockingConcurrentQueue<int> q;
186-
std::thread producer([&]() {
187-
for (int i = 0; i != 100; ++i) {
188-
std::this_thread::sleep_for(std::chrono::milliseconds(i % 10));
189-
q.enqueue(i);
190-
}
191-
});
192-
std::thread consumer([&]() {
193-
for (int i = 0; i != 100; ++i) {
194-
int item;
195-
q.wait_dequeue(item);
185+
```C++
186+
#include "blockingconcurrentqueue.h"
187+
188+
moodycamel::BlockingConcurrentQueue<int> q;
189+
std::thread producer([&]() {
190+
for (int i = 0; i != 100; ++i) {
191+
std::this_thread::sleep_for(std::chrono::milliseconds(i % 10));
192+
q.enqueue(i);
193+
}
194+
});
195+
std::thread consumer([&]() {
196+
for (int i = 0; i != 100; ++i) {
197+
int item;
198+
q.wait_dequeue(item);
199+
assert(item == i);
200+
201+
if (q.wait_dequeue_timed(item, std::chrono::milliseconds(5))) {
202+
++i;
196203
assert(item == i);
197-
198-
if (q.wait_dequeue_timed(item, std::chrono::milliseconds(5))) {
199-
++i;
200-
assert(item == i);
201-
}
202204
}
203-
});
204-
producer.join();
205-
consumer.join();
206-
207-
assert(q.size_approx() == 0);
205+
}
206+
});
207+
producer.join();
208+
consumer.join();
209+
210+
assert(q.size_approx() == 0);
211+
```
208212
209213
## Advanced features
210214
@@ -216,15 +220,17 @@ You can create a consumer token and/or a producer token for each thread or task
216220
(tokens themselves are not thread-safe), and use the methods that accept a token
217221
as their first parameter:
218222
219-
moodycamel::ConcurrentQueue<int> q;
220-
221-
moodycamel::ProducerToken ptok(q);
222-
q.enqueue(ptok, 17);
223-
224-
moodycamel::ConsumerToken ctok(q);
225-
int item;
226-
q.try_dequeue(ctok, item);
227-
assert(item == 17);
223+
```C++
224+
moodycamel::ConcurrentQueue<int> q;
225+
226+
moodycamel::ProducerToken ptok(q);
227+
q.enqueue(ptok, 17);
228+
229+
moodycamel::ConsumerToken ctok(q);
230+
int item;
231+
q.try_dequeue(ctok, item);
232+
assert(item == 17);
233+
```
228234

229235
If you happen to know which producer you want to consume from (e.g. in
230236
a single-producer, multi-consumer scenario), you can use the `try_dequeue_from_producer`
@@ -253,16 +259,18 @@ Thanks to the [novel design][blog] of the queue, it's just as easy to enqueue/de
253259
items as it is to do one at a time. This means that overhead can be cut drastically for
254260
bulk operations. Example syntax:
255261

256-
moodycamel::ConcurrentQueue<int> q;
262+
```C++
263+
moodycamel::ConcurrentQueue<int> q;
257264

258-
int items[] = { 1, 2, 3, 4, 5 };
259-
q.enqueue_bulk(items, 5);
260-
261-
int results[5]; // Could also be any iterator
262-
size_t count = q.try_dequeue_bulk(results, 5);
263-
for (size_t i = 0; i != count; ++i) {
264-
assert(results[i] == items[i]);
265-
}
265+
int items[] = { 1, 2, 3, 4, 5 };
266+
q.enqueue_bulk(items, 5);
267+
268+
int results[5]; // Could also be any iterator
269+
size_t count = q.try_dequeue_bulk(results, 5);
270+
for (size_t i = 0; i != count; ++i) {
271+
assert(results[i] == items[i]);
272+
}
273+
```
266274

267275
#### Preallocation (correctly using `try_enqueue`)
268276

@@ -289,15 +297,21 @@ integer division (in order for `ceil()` to work).
289297

290298
For explicit producers (using tokens to enqueue):
291299

292-
(ceil(N / BLOCK_SIZE) + 1) * MAX_NUM_PRODUCERS * BLOCK_SIZE
300+
```C++
301+
(ceil(N / BLOCK_SIZE) + 1) * MAX_NUM_PRODUCERS * BLOCK_SIZE
302+
```
293303

294304
For implicit producers (no tokens):
295305

296-
(ceil(N / BLOCK_SIZE) - 1 + 2 * MAX_NUM_PRODUCERS) * BLOCK_SIZE
306+
```C++
307+
(ceil(N / BLOCK_SIZE) - 1 + 2 * MAX_NUM_PRODUCERS) * BLOCK_SIZE
308+
```
297309

298310
When using mixed producer types:
299311

300-
((ceil(N / BLOCK_SIZE) - 1) * (MAX_EXPLICIT_PRODUCERS + 1) + 2 * (MAX_IMPLICIT_PRODUCERS + MAX_EXPLICIT_PRODUCERS)) * BLOCK_SIZE
312+
```C++
313+
((ceil(N / BLOCK_SIZE) - 1) * (MAX_EXPLICIT_PRODUCERS + 1) + 2 * (MAX_IMPLICIT_PRODUCERS + MAX_EXPLICIT_PRODUCERS)) * BLOCK_SIZE
314+
```
301315

302316
If these formulas seem rather inconvenient, you can use the constructor overload that accepts the minimum
303317
number of elements (`N`) and the maximum number of explicit and implicit producers directly, and let it do the
@@ -352,12 +366,14 @@ and the memory allocation and deallocation functions that are to be used by the
352366
to providing your own traits is to create a class that inherits from the default traits
353367
and override only the values you wish to change. Example:
354368

355-
struct MyTraits : public moodycamel::ConcurrentQueueDefaultTraits
356-
{
357-
static const size_t BLOCK_SIZE = 256; // Use bigger blocks
358-
};
359-
360-
moodycamel::ConcurrentQueue<int, MyTraits> q;
369+
```C++
370+
struct MyTraits : public moodycamel::ConcurrentQueueDefaultTraits
371+
{
372+
static const size_t BLOCK_SIZE = 256; // Use bigger blocks
373+
};
374+
375+
moodycamel::ConcurrentQueue<int, MyTraits> q;
376+
```
361377

362378
#### How to dequeue types without calling the constructor
363379

@@ -369,44 +385,48 @@ workaround: Create a wrapper class that copies the memory contents of the object
369385
is assigned by the queue (a poor man's move, essentially). Note that this only works if
370386
the object contains no internal pointers. Example:
371387

372-
struct MyObjectMover {
373-
inline void operator=(MyObject&& obj) {
374-
std::memcpy(data, &obj, sizeof(MyObject));
375-
376-
// TODO: Cleanup obj so that when it's destructed by the queue
377-
// it doesn't corrupt the data of the object we just moved it into
378-
}
388+
```C++
389+
struct MyObjectMover {
390+
inline void operator=(MyObject&& obj) {
391+
std::memcpy(data, &obj, sizeof(MyObject));
392+
393+
// TODO: Cleanup obj so that when it's destructed by the queue
394+
// it doesn't corrupt the data of the object we just moved it into
395+
}
379396

380-
inline MyObject& obj() { return *reinterpret_cast<MyObject*>(data); }
397+
inline MyObject& obj() { return *reinterpret_cast<MyObject*>(data); }
381398

382-
private:
383-
align(alignof(MyObject)) char data[sizeof(MyObject)];
384-
};
399+
private:
400+
align(alignof(MyObject)) char data[sizeof(MyObject)];
401+
};
402+
```
385403
386404
A less dodgy alternative, if moves are cheap but default construction is not, is to use a
387405
wrapper that defers construction until the object is assigned, enabling use of the move
388406
constructor:
389407
390-
struct MyObjectMover {
391-
inline void operator=(MyObject&& x) {
392-
new (data) MyObject(std::move(x));
393-
created = true;
394-
}
408+
```C++
409+
struct MyObjectMover {
410+
inline void operator=(MyObject&& x) {
411+
new (data) MyObject(std::move(x));
412+
created = true;
413+
}
395414
396-
inline MyObject& obj() {
397-
assert(created);
398-
return *reinterpret_cast<MyObject*>(data);
399-
}
415+
inline MyObject& obj() {
416+
assert(created);
417+
return *reinterpret_cast<MyObject*>(data);
418+
}
400419
401-
~MyObjectMover() {
402-
if (created)
403-
obj().~MyObject();
404-
}
420+
~MyObjectMover() {
421+
if (created)
422+
obj().~MyObject();
423+
}
405424
406-
private:
407-
align(alignof(MyObject)) char data[sizeof(MyObject)];
408-
bool created = false;
409-
};
425+
private:
426+
align(alignof(MyObject)) char data[sizeof(MyObject)];
427+
bool created = false;
428+
};
429+
```
410430

411431
## Samples
412432

@@ -419,9 +439,11 @@ See my blog post for some [benchmark results][benchmarks] (including versus `boo
419439
or run the benchmarks yourself (requires MinGW and certain GnuWin32 utilities to build on Windows, or a recent
420440
g++ on Linux):
421441

422-
cd build
423-
make benchmarks
424-
bin/benchmarks
442+
```Shell
443+
cd build
444+
make benchmarks
445+
bin/benchmarks
446+
```
425447

426448
The short version of the benchmarks is that it's so fast (especially the bulk methods), that if you're actually
427449
using the queue to *do* anything, the queue won't be your bottleneck.
@@ -443,11 +465,13 @@ a unit test for it can be cooked up.) Just open an issue on GitHub.
443465
## Using vcpkg
444466
You can download and install `moodycamel::ConcurrentQueue` using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
445467

446-
git clone https://github.com/Microsoft/vcpkg.git
447-
cd vcpkg
448-
./bootstrap-vcpkg.sh
449-
./vcpkg integrate install
450-
vcpkg install concurrentqueue
468+
```Shell
469+
git clone https://github.com/Microsoft/vcpkg.git
470+
cd vcpkg
471+
./bootstrap-vcpkg.sh
472+
./vcpkg integrate install
473+
vcpkg install concurrentqueue
474+
```
451475

452476
The `moodycamel::ConcurrentQueue` port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
453477

0 commit comments

Comments
 (0)