#!/usr/bin/env dub
/+ dub.sdl:
name "gcd_root_queues"
platforms "osx"
targetPath "build"
+/
/**
* GCD — the twelve global root queues, read back from a live libdispatch.
*
* `dispatch_get_global_queue(qos, flags)` does not create anything: it indexes
* a static table of twelve queues that libdispatch defines at build time — six
* QoS classes × {non-overcommit, overcommit}. This program prints the label of
* each one, which is exactly the `dq_label` field of the corresponding entry in
* libdispatch's `src/init.c` `_dispatch_root_queues[]` array, and asserts the
* `com.apple.root.` prefix and the `.overcommit` suffix pairing.
*
* It also shows that a queue you create with `dispatch_queue_create` keeps its
* own label, and that `dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)`
* — a NULL argument — names whichever queue is currently running the code.
*
* Companion to the GCD deep-dive:
* see docs/research/async-io/gcd/index.md § "Root queues: twelve of them, all static".
*
* Run with: `dub run --single root-queues.d`
*
* Portability: macOS only (`platforms "osx"`); libdispatch is part of
* libSystem, so no extra link flags are needed.
*/
module (module) gcd_root_queuesGCD — the twelve global root queues, read back from a live libdispatch.
dispatch_get_global_queue(qos, flags) does not create anything: it indexes
a static table of twelve queues that libdispatch defines at build time — six
QoS classes × {non-overcommit, overcommit}. This program prints the label of
each one, which is exactly the dq_label field of the corresponding entry in
libdispatch's src/init.c _dispatch_root_queues[] array, and asserts the
com.apple.root. prefix and the .overcommit suffix pairing.
It also shows that a queue you create with dispatch_queue_create keeps its
own label, and that dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
— a NULL argument — names whichever queue is currently running the code.
Companion to the GCD deep-dive:
see docs/research/async-io/gcd/index.md § "Root queues: twelve of them, all static".
Run with: dub run --single root-queues.d
Portability
macOS only (platforms "osx"); libdispatch is part of
libSystem, so no extra link flags are needed.
gcd_root_queues;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stdintD header file for C99.
pubs.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.html, stdint.h
Source
core/stdc/stdint.d
stdint : intptr_t, uintptr_t;
import (package) stdstd.(module) std.algorithmThis package implements generic algorithms oriented towards the processing of
sequences. Sequences processed by these functions define range-based
interfaces. See also Reference on ranges and
tutorial on ranges.
Algorithms are categorized into the following submodules:
Submodule Functions
| Searching |
all
any
balancedParens
boyerMooreFinder
canFind
commonPrefix
count
countUntil
endsWith
find
findAdjacent
findAmong
findSkip
findSplit
findSplitAfter
findSplitBefore
minCount
maxCount
minElement
maxElement
minIndex
maxIndex
minPos
maxPos
skipOver
startsWith
until
|
| Comparison |
among
castSwitch
clamp
cmp
either
equal
isPermutation
isSameLength
levenshteinDistance
levenshteinDistanceAndPath
max
min
mismatch
predSwitch
|
| Iteration |
cache
cacheBidirectional
chunkBy
cumulativeFold
each
filter
filterBidirectional
fold
group
joiner
map
mean
permutations
reduce
splitWhen
splitter
substitute
sum
uniq
|
| Sorting |
completeSort
isPartitioned
isSorted
isStrictlyMonotonic
ordered
strictlyOrdered
makeIndex
merge
multiSort
nextEvenPermutation
nextPermutation
nthPermutation
partialSort
partition
partition3
schwartzSort
sort
topN
topNCopy
topNIndex
|
| Set operations (setops) |
cartesianProduct
largestPartialIntersection
largestPartialIntersectionWeighted
multiwayMerge
multiwayUnion
setDifference
setIntersection
setSymmetricDifference
|
| Mutation |
bringToFront
copy
fill
initializeAll
move
moveAll
moveSome
moveEmplace
moveEmplaceAll
moveEmplaceSome
remove
reverse
strip
stripLeft
stripRight
swap
swapRanges
uninitializedFill
|
Many functions in this package are parameterized with a predicate.
The predicate may be any suitable callable type
(a function, a delegate, a functor, or a lambda), or a
compile-time string. The string may consist of any legal D
expression that uses the symbol a (for unary functions) or the
symbols a and b (for binary functions). These names will NOT
interfere with other homonym symbols in user code because they are
evaluated in a different context. The default for all binary
comparison predicates is "a == b" for unordered operations and
"a < b" for ordered operations.
Example
int[] a = ...;
static bool greater(int a, int b)
{
return a > b;
}
sort!greater(a); // predicate as alias
sort!((a, b) => a > b)(a); // predicate as a lambda.
sort!"a > b"(a); // predicate as string
// (no ambiguity with array name)
sort(a); // no predicate, "a < b" is implicit
Source
std/algorithm/package.d
algorithm : (alias template) gcd_root_queues.endsWith = std.algorithm.searching.endsWith(alias pred = "a == b", Range, Needles...)(Range doesThisEnd, Needles withOneOfThese) if (isBidirectionalRange!Range && (Needles.length > 1) && allSatisfy!(canTestStartsWith!(pred, Range), Needles))Checks if the given range ends with (one of) the given needle(s).
The reciprocal of startsWith.
endsWith, (alias template) gcd_root_queues.startsWith = std.algorithm.searching.startsWith(alias pred = (a, b) => a == b, Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && (Needles.length > 1) && allSatisfy!(canTestStartsWith!(pred, Range), Needles))Checks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith;
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) gcd_root_queues.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))Equivalent to writef(fmt, args, '\n').
writefln, (alias template) gcd_root_queues.writeln = std.stdio.writeln(T...)(T args)Equivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln;
import (package) stdstd.(module) std.stringString handling functions.
Category Functions Searching column indexOf indexOfAny indexOfNeither lastIndexOf lastIndexOfAny lastIndexOfNeither Comparison isNumeric Mutation capitalize Pruning and Filling center chomp chompPrefix chop detabber detab entab entabber leftJustify outdent rightJustify strip stripLeft stripRight wrap Substitution abbrev soundex soundexer succ tr translate Miscellaneous assumeUTF fromStringz lineSplitter representation splitLines toStringz Objects of types string, wstring, and dstring are value types and cannot be mutated element-by-element. For using mutation during building strings, use char[], wchar[], or dchar[]. The xxxstring types are preferable because they don't exhibit undesired aliasing, thus making code more robust.
The following functions are publicly imported:
Module Functions Publicly imported functions std.algorithm cmp, std,algorithm,comparison count, std,algorithm,searching endsWith, std,algorithm,searching startsWith, std,algorithm,searching std.array join, std,array replace, std,array replaceInPlace, std,array split, std,array empty, std,array std.format format, std,format sformat, std,format std.uni icmp, std,uni toLower, std,uni toLowerInPlace, std,uni toUpper, std,uni toUpperInPlace, std,uni There is a rich set of functions for string handling defined in other modules. Functions related to Unicode and ASCII are found in std.uni and std.ascii, respectively. Other functions that have a wider generality than just strings can be found in std.algorithm and std.range.
Source
std/string.d
string : (alias template) gcd_root_queues.fromStringz = std.string.fromStringz(Char)(return scope inout(Char)* cString) if (isSomeChar!Char)fromStringz;
alias (alias) gcd_root_queues.dispatch_queue_t = void*dispatch_queue_t = void*;
alias (alias) gcd_root_queues.dispatch_function_t = extern (C) void function(void*) nothrowdispatch_function_t = extern (C) void function(void*) nothrow;
extern (C) nothrow @nogc
{
(alias) gcd_root_queues.dispatch_queue_t = void*dispatch_queue_t void* gcd_root_queues.dispatch_get_global_queue(long identifier, ulong flags) nothrow @nogcdispatch_get_global_queue(intptr_t (parameter) long identifieridentifier, uintptr_t (parameter) ulong flagsflags);
(alias) gcd_root_queues.dispatch_queue_t = void*dispatch_queue_t void* gcd_root_queues.dispatch_queue_create(const(char)* label, void* attr) nothrow @nogcdispatch_queue_create(const(char)* (parameter) const(char)* labellabel, void* (parameter) void* attrattr);
const(char)* const(char)* gcd_root_queues.dispatch_queue_get_label(void* queue) nothrow @nogcdispatch_queue_get_label((alias) gcd_root_queues.dispatch_queue_t = void*dispatch_queue_t (parameter) void* queuequeue);
void void gcd_root_queues.dispatch_sync_f(void* queue, void* context, extern (C) void function(void*) nothrow work) nothrow @nogcdispatch_sync_f((alias) gcd_root_queues.dispatch_queue_t = void*dispatch_queue_t (parameter) void* queuequeue, void* (parameter) void* contextcontext, (alias) gcd_root_queues.dispatch_function_t = extern (C) void function(void*) nothrowdispatch_function_t (parameter) extern (C) void function(void*) nothrow workwork);
void void gcd_root_queues.dispatch_release(void* object) nothrow @nogcdispatch_release(void* (parameter) void* objectobject);
}
/// `DISPATCH_QUEUE_OVERCOMMIT` — the only legal `flags` value for
/// `dispatch_get_global_queue`; selects the odd-indexed half of the table.
enum (constant) ulong gcd_root_queues.DISPATCH_QUEUE_OVERCOMMIT = 2LUDISPATCH_QUEUE_OVERCOMMIT — the only legal flags value for
dispatch_get_global_queue; selects the odd-indexed half of the table.
DISPATCH_QUEUE_OVERCOMMIT = 2UL;
/// The `qos_class_t` values from `<sys/qos.h>`. `dispatch_get_global_queue`
/// accepts either these or the legacy `DISPATCH_QUEUE_PRIORITY_*` integers,
/// resolving both through `_dispatch_qos_from_queue_priority`.
///
/// `MAINTENANCE` (0x05) is the odd one out: libdispatch has a root-queue pair
/// for it, but `<sys/qos.h>` declares no `QOS_CLASS_MAINTENANCE` constant — the
/// value is spelled out here to reach the twelfth and eleventh entries.
struct (struct) gcd_root_queues.QosClassThe qos_class_t values from <sys/qos.h>. dispatch_get_global_queue
accepts either these or the legacy DISPATCH_QUEUE_PRIORITY_* integers,
resolving both through _dispatch_qos_from_queue_priority.
MAINTENANCE (0x05) is the odd one out: libdispatch has a root-queue pair
for it, but <sys/qos.h> declares no QOS_CLASS_MAINTENANCE constant — the
value is spelled out here to reach the twelfth and eleventh entries.
QosClass
{
(alias) object.string = stringstring (field) string gcd_root_queues.QosClass.namename;
intptr_t (field) long gcd_root_queues.QosClass.valuevalue;
}
static immutable (struct) gcd_root_queues.QosClassThe qos_class_t values from <sys/qos.h>. dispatch_get_global_queue
accepts either these or the legacy DISPATCH_QUEUE_PRIORITY_* integers,
resolving both through _dispatch_qos_from_queue_priority.
MAINTENANCE (0x05) is the odd one out: libdispatch has a root-queue pair
for it, but <sys/qos.h> declares no QOS_CLASS_MAINTENANCE constant — the
value is spelled out here to reach the twelfth and eleventh entries.
QosClass[] (immutable global) immutable(gcd_root_queues.QosClass[]) gcd_root_queues.qosClassesqosClasses = [
(struct) gcd_root_queues.QosClassThe qos_class_t values from <sys/qos.h>. dispatch_get_global_queue
accepts either these or the legacy DISPATCH_QUEUE_PRIORITY_* integers,
resolving both through _dispatch_qos_from_queue_priority.
MAINTENANCE (0x05) is the odd one out: libdispatch has a root-queue pair
for it, but <sys/qos.h> declares no QOS_CLASS_MAINTENANCE constant — the
value is spelled out here to reach the twelfth and eleventh entries.
QosClass("MAINTENANCE (0x05, private)", 0x05),
(struct) gcd_root_queues.QosClassThe qos_class_t values from <sys/qos.h>. dispatch_get_global_queue
accepts either these or the legacy DISPATCH_QUEUE_PRIORITY_* integers,
resolving both through _dispatch_qos_from_queue_priority.
MAINTENANCE (0x05) is the odd one out: libdispatch has a root-queue pair
for it, but <sys/qos.h> declares no QOS_CLASS_MAINTENANCE constant — the
value is spelled out here to reach the twelfth and eleventh entries.
QosClass("QOS_CLASS_BACKGROUND", 0x09),
(struct) gcd_root_queues.QosClassThe qos_class_t values from <sys/qos.h>. dispatch_get_global_queue
accepts either these or the legacy DISPATCH_QUEUE_PRIORITY_* integers,
resolving both through _dispatch_qos_from_queue_priority.
MAINTENANCE (0x05) is the odd one out: libdispatch has a root-queue pair
for it, but <sys/qos.h> declares no QOS_CLASS_MAINTENANCE constant — the
value is spelled out here to reach the twelfth and eleventh entries.
QosClass("QOS_CLASS_UTILITY", 0x11),
(struct) gcd_root_queues.QosClassThe qos_class_t values from <sys/qos.h>. dispatch_get_global_queue
accepts either these or the legacy DISPATCH_QUEUE_PRIORITY_* integers,
resolving both through _dispatch_qos_from_queue_priority.
MAINTENANCE (0x05) is the odd one out: libdispatch has a root-queue pair
for it, but <sys/qos.h> declares no QOS_CLASS_MAINTENANCE constant — the
value is spelled out here to reach the twelfth and eleventh entries.
QosClass("QOS_CLASS_DEFAULT", 0x15),
(struct) gcd_root_queues.QosClassThe qos_class_t values from <sys/qos.h>. dispatch_get_global_queue
accepts either these or the legacy DISPATCH_QUEUE_PRIORITY_* integers,
resolving both through _dispatch_qos_from_queue_priority.
MAINTENANCE (0x05) is the odd one out: libdispatch has a root-queue pair
for it, but <sys/qos.h> declares no QOS_CLASS_MAINTENANCE constant — the
value is spelled out here to reach the twelfth and eleventh entries.
QosClass("QOS_CLASS_USER_INITIATED", 0x19),
(struct) gcd_root_queues.QosClassThe qos_class_t values from <sys/qos.h>. dispatch_get_global_queue
accepts either these or the legacy DISPATCH_QUEUE_PRIORITY_* integers,
resolving both through _dispatch_qos_from_queue_priority.
MAINTENANCE (0x05) is the odd one out: libdispatch has a root-queue pair
for it, but <sys/qos.h> declares no QOS_CLASS_MAINTENANCE constant — the
value is spelled out here to reach the twelfth and eleventh entries.
QosClass("QOS_CLASS_USER_INTERACTIVE", 0x21),
];
/// Runs on the created queue; `NULL` means "the queue running right now".
extern (C) void void gcd_root_queues.printCurrentQueue(void* context) nothrowRuns on the created queue; NULL means "the queue running right now".
printCurrentQueue(void* (parameter) void* contextcontext) nothrow
{
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stdioD header file for C99 <stdio.h>
pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h
Source
core/stdc/stdio.d
stdio : (alias) printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf;
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf(" running on: %s\n", const(char)* gcd_root_queues.dispatch_queue_get_label(void* queue) nothrow @nogcdispatch_queue_get_label(null));
}
int int D main()main()
{
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("QoS class root queue label");
foreach ((parameter) immutable(gcd_root_queues.QosClass) qosqos; (immutable global) immutable(gcd_root_queues.QosClass[]) gcd_root_queues.qosClassesqosClasses)
{
const (local variable) const(string) plainplain = void* gcd_root_queues.dispatch_get_global_queue(long identifier, ulong flags) nothrow @nogcdispatch_get_global_queue((local variable) immutable(gcd_root_queues.QosClass) qosqos.(field) long gcd_root_queues.QosClass.valuevalue, 0)
.const(char)* gcd_root_queues.dispatch_queue_get_label(void* queue) nothrow @nogcdispatch_queue_get_label.inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @systemfromStringz.string object.idup!(const(char))(const(char)[] a) pure nothrow @property @safeProvide the .idup array property, which creates an immutable duplicate.
idup;
const (local variable) const(string) overover = void* gcd_root_queues.dispatch_get_global_queue(long identifier, ulong flags) nothrow @nogcdispatch_get_global_queue((local variable) immutable(gcd_root_queues.QosClass) qosqos.(field) long gcd_root_queues.QosClass.valuevalue, (constant) ulong gcd_root_queues.DISPATCH_QUEUE_OVERCOMMIT = 2LUDISPATCH_QUEUE_OVERCOMMIT — the only legal flags value for
dispatch_get_global_queue; selects the odd-indexed half of the table.
DISPATCH_QUEUE_OVERCOMMIT)
.const(char)* gcd_root_queues.dispatch_queue_get_label(void* queue) nothrow @nogcdispatch_queue_get_label.inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @systemfromStringz.string object.idup!(const(char))(const(char)[] a) pure nothrow @property @safeProvide the .idup array property, which creates an immutable duplicate.
idup;
void std.stdio.writefln!(char, string, string)(in char[] fmt, string __param_1, string __param_2) @safeEquivalent to writef(fmt, args, '\n').
writefln("%-29s %s", (local variable) immutable(gcd_root_queues.QosClass) qosqos.(field) string gcd_root_queues.QosClass.namename, (local variable) const(string) plainplain);
void std.stdio.writefln!(char, string, string)(in char[] fmt, string __param_1, string __param_2) @safeEquivalent to writef(fmt, args, '\n').
writefln("%-29s %s", "", (local variable) const(string) overover);
// Every entry of `_dispatch_root_queues[]` is named `com.apple.root.<qos>`,
// and the overcommit twin is the same name plus a suffix.
assert((local variable) const(string) plainplain.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("com.apple.root."), "unexpected root queue label: " ~ (local variable) const(string) plainplain);
assert((local variable) const(string) overover == (local variable) const(string) plainplain ~ ".overcommit", "overcommit twin mismatch: " ~ (local variable) const(string) overover);
}
// A queue you create is a *lane* with its own label; it owns no threads and
// targets one of the root queues above.
auto (local variable) void* minemine = void* gcd_root_queues.dispatch_queue_create(const(char)* label, void* attr) nothrow @nogcdispatch_queue_create("dev.sparkles.research.gcd", null);
scope (exit)
void gcd_root_queues.dispatch_release(void* object) nothrow @nogcdispatch_release((local variable) void* minemine);
void std.stdio.writeln!()() @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln();
void std.stdio.writefln!(char, const(char)[])(in char[] fmt, const(char)[] __param_1) @safeEquivalent to writef(fmt, args, '\n').
writefln("created queue label: %s", (local variable) void* minemine.const(char)* gcd_root_queues.dispatch_queue_get_label(void* queue) nothrow @nogcdispatch_queue_get_label.inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @systemfromStringz);
void gcd_root_queues.dispatch_sync_f(void* queue, void* context, extern (C) void function(void*) nothrow work) nothrow @nogcdispatch_sync_f((local variable) void* minemine, null, &void gcd_root_queues.printCurrentQueue(void* context) nothrowRuns on the created queue; NULL means "the queue running right now".
printCurrentQueue);
assert((local variable) void* minemine.const(char)* gcd_root_queues.dispatch_queue_get_label(void* queue) nothrow @nogcdispatch_queue_get_label.inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @systemfromStringz == "dev.sparkles.research.gcd");
// The legacy priority constants are folded onto the same table:
// DISPATCH_QUEUE_PRIORITY_DEFAULT is 0, not a `qos_class_t` value at all.
const (local variable) const(string) legacyDefaultlegacyDefault = void* gcd_root_queues.dispatch_get_global_queue(long identifier, ulong flags) nothrow @nogcdispatch_get_global_queue(0, 0)
.const(char)* gcd_root_queues.dispatch_queue_get_label(void* queue) nothrow @nogcdispatch_queue_get_label.inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @systemfromStringz.string object.idup!(const(char))(const(char)[] a) pure nothrow @property @safeProvide the .idup array property, which creates an immutable duplicate.
idup;
assert((local variable) const(string) legacyDefaultlegacyDefault == "com.apple.root.default-qos",
"DISPATCH_QUEUE_PRIORITY_DEFAULT did not resolve to the default root queue");
void std.stdio.writeln!()() @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln();
void std.stdio.writefln!(char, ulong, ulong)(in char[] fmt, ulong __param_1, ulong __param_2) @safeEquivalent to writef(fmt, args, '\n').
writefln("observed %d of the 12 root queues (%d QoS classes × 2)",
(immutable global) immutable(gcd_root_queues.QosClass[]) gcd_root_queues.qosClassesqosClasses.(field) ulong immutable(gcd_root_queues.QosClass[]).lengthlength * 2, (immutable global) immutable(gcd_root_queues.QosClass[]) gcd_root_queues.qosClassesqosClasses.(field) ulong immutable(gcd_root_queues.QosClass[]).lengthlength);
assert((immutable global) immutable(gcd_root_queues.QosClass[]) gcd_root_queues.qosClassesqosClasses.(field) ulong immutable(gcd_root_queues.QosClass[]).lengthlength == 6, "expected six QoS buckets");
return 0;
}