about summary refs log blame commit diff stats
path: root/src/chrtrans/cp850_uni.tbl
blob: 91fe44eecc1a5c6c0c7dbec499e3e4781fee4490 (plain) (tree)
pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#
#
#            Nim's Runtime Library
#        (c) Copyright 2018 Jörg Wollenschläger
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## Types and operations for atomic operations and lockless algorithms.
##
## Unstable API.

runnableExamples:
  # Atomic
  var loc: Atomic[int]
  loc.store(4)
  assert loc.load == 4
  loc.store(2)
  assert loc.load(moRelaxed) == 2
  loc.store(9)
  assert loc.load(moAcquire) == 9
  loc.store(0, moRelease)
  assert loc.load == 0

  assert loc.exchange(7) == 0
  assert loc.load == 7

  var expected = 7
  assert loc.compareExchange(expected, 5, moRelaxed, moRelaxed)
  assert expected == 7
  assert loc.load == 5

  assert not loc.compareExchange(expected, 12, moRelaxed, moRelaxed)
  assert expected == 5
  assert loc.load == 5

  assert loc.fetchAdd(1) == 5
  assert loc.fetchAdd(2) == 6
  assert loc.fetchSub(3) == 8

  loc.atomicInc(1)
  assert loc.load == 6

  # AtomicFlag
  var flag: AtomicFlag

  assert not flag.testAndSet
  assert flag.testAndSet
  flag.clear(moRelaxed)
  assert not flag.testAndSet

when (defined(cpp) and not defined(nimUseCAtomics)) or defined(nimdoc):
  # For the C++ backend, types and operations map directly to C++11 atomics.

  {.push, header: "<atomic>".}

  type
    MemoryOrder* {.importcpp: "std::memory_order".} = enum
      ## Specifies how non-atomic operations can be reordered around atomic
      ## operations.

      moRelaxed
        ## No ordering constraints. Only the atomicity and ordering against
        ## other atomic operations is guaranteed.

      moConsume
        ## This ordering is currently discouraged as it's semantics are
        ## being revised. Acquire operations should be preferred.

      moAcquire
        ## When applied to a load operation, no reads or writes in the
        ## current thread can be reordered before this operation.

      moRelease
        ## When applied to a store operation, no reads or writes in the
        ## current thread can be reorderd after this operation.

      moAcquireRelease
        ## When applied to a read-modify-write operation, this behaves like
        ## both an acquire and a release operation.

      moSequentiallyConsistent
        ## Behaves like Acquire when applied to load, like Release when
        ## applied to a store and like AcquireRelease when applied to a
        ## read-modify-write operation.
        ## Also guarantees that all threads observe the same total ordering
        ## with other moSequentiallyConsistent operations.

  type
    Atomic*[T] {.importcpp: "std::atomic", completeStruct.} = object
      ## An atomic object with underlying type `T`.
      raw: T

    AtomicFlag* {.importcpp: "std::atomic_flag", size: 1.} = object
      ## An atomic boolean state.

  # Access operations

  proc load*[T](location: var Atomic[T]; order: MemoryOrder = moSequentiallyConsistent): T {.importcpp: "#.load(@)".}
<
#Shall this become the "default" translation?
#Meaning of that is currently unclear...  It's different
#from the default input or default output charset...
#but there has to be exactly one table marked as "default".
D0
#
#The MIME name of this charset.
Mcp850

#Name as a Display Charset (used on Options screen)
OWestern (cp850)

#Codepage number
C850

#
#    Name:     cp850_DOSLatin1 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.00
#    Table format:  Format A
#    Date:          04/24/96
#    Authors:       Lori Brownell <loribr@microsoft.com>
#                   K.D. Chang    <a-kchang@microsoft.com>
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp850_DOSLatin1 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')
#
#    The entries are in cp850_DOSLatin1 order
#
##################
# Lines with more than one Unicode (U+XXXX) value contain additional
# replacement mappings added for lynx. - kw

0x20-0x7e       idem
#
0x80	U+00c7	#LATIN CAPITAL LETTER C WITH CEDILLA
0x81	U+00fc	U+03cb	#LATIN SMALL LETTER U WITH DIAERESIS
0x82	U+00e9	U+03ad	#LATIN SMALL LETTER E WITH ACUTE
0x83	U+00e2	#LATIN SMALL LETTER A WITH CIRCUMFLEX
0x84	U+00e4	#LATIN SMALL LETTER A WITH DIAERESIS
0x85	U+00e0	#LATIN SMALL LETTER A WITH GRAVE
0x86	U+00e5	#LATIN SMALL LETTER A WITH RING ABOVE
0x87	U+00e7	#LATIN SMALL LETTER C WITH CEDILLA
0x88	U+00ea	#LATIN SMALL LETTER E WITH CIRCUMFLEX
0x89	U+00eb	#LATIN SMALL LETTER E WITH DIAERESIS
0x8a	U+00e8	#LATIN SMALL LETTER E WITH GRAVE
0x8b	U+00ef	U+03ca	#LATIN SMALL LETTER I WITH DIAERESIS
0x8c	U+00ee	#LATIN SMALL LETTER I WITH CIRCUMFLEX
0x8d	U+00ec	#LATIN SMALL LETTER I WITH GRAVE
0x8e	U+00c4	#LATIN CAPITAL LETTER A WITH DIAERESIS
0x8f	U+00c5	#LATIN CAPITAL LETTER A WITH RING ABOVE
0x90	U+00c9	U+0388	#LATIN CAPITAL LETTER E WITH ACUTE
0x91	U+00e6	#LATIN SMALL LIGATURE AE
0x92	U+00c6	#LATIN CAPITAL LIGATURE AE
0x93	U+00f4	#LATIN SMALL LETTER O WITH CIRCUMFLEX
0x94	U+00f6	#LATIN SMALL LETTER O WITH DIAERESIS
0x95	U+00f2	#LATIN SMALL LETTER O WITH GRAVE
0x96	U+00fb	#LATIN SMALL LETTER U WITH CIRCUMFLEX
0x97	U+00f9	#LATIN SMALL LETTER U WITH GRAVE
0x98	U+00ff	#LATIN SMALL LETTER Y WITH DIAERESIS
0x99	U+00d6	#LATIN CAPITAL LETTER O WITH DIAERESIS
0x9a	U+00dc	U+03ab	#LATIN CAPITAL LETTER U WITH DIAERESIS
0x9b	U+00f8	#LATIN SMALL LETTER O WITH STROKE
0x9c	U+00a3	#POUND SIGN
0x9d	U+00d8	#LATIN CAPITAL LETTER O WITH STROKE
0x9e	U+00d7	#MULTIPLICATION SIGN
0x9f	U+0192	#LATIN SMALL LETTER F WITH HOOK
0xa0	U+00e1	U+03ac	#LATIN SMALL LETTER A WITH ACUTE
0xa1	U+00ed	U+03af	#LATIN SMALL LETTER I WITH ACUTE
0xa2	U+00f3	U+03cc	#LATIN SMALL LETTER O WITH ACUTE
0xa3	U+00fa	U+03cd	#LATIN SMALL LETTER U WITH ACUTE
0xa4	U+00f1	#LATIN SMALL LETTER N WITH TILDE
0xa5	U+00d1	#LATIN CAPITAL LETTER N WITH TILDE
0xa6	U+00aa	#FEMININE ORDINAL INDICATOR
0xa7	U+00ba	#MASCULINE ORDINAL INDICATOR
0xa8	U+00bf	#INVERTED QUESTION MARK
0xa9	U+00ae	#REGISTERED SIGN
0xaa	U+00ac	#NOT SIGN
0xab	U+00bd	#VULGAR FRACTION ONE HALF
0xac	U+00bc	#VULGAR FRACTION ONE QUARTER
0xad	U+00a1	#INVERTED EXCLAMATION MARK
0xae	U+00ab	#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
0xaf	U+00bb	#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
0xb0	U+2591	#LIGHT SHADE
0xb1	U+2592	#MEDIUM SHADE
0xb2	U+2593	#DARK SHADE
0xb3	U+2502	#BOX DRAWINGS LIGHT VERTICAL
0xb4	U+2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT
0xb5	U+00c1	U+0386	#LATIN CAPITAL LETTER A WITH ACUTE
0xb6	U+00c2	#LATIN CAPITAL LETTER A WITH CIRCUMFLEX
0xb7	U+00c0	#LATIN CAPITAL LETTER A WITH GRAVE
0xb8	U+00a9	#COPYRIGHT SIGN
0xb9	U+2563	#BOX DRAWINGS DOUBLE VERTICAL AND LEFT
0xba	U+2551	#BOX DRAWINGS DOUBLE VERTICAL
0xbb	U+2557	#BOX DRAWINGS DOUBLE DOWN AND LEFT
0xbc	U+255d	#BOX DRAWINGS DOUBLE UP AND LEFT
0xbd	U+00a2	#CENT SIGN
0xbe	U+00a5	#YEN SIGN
0xbf	U+2510	#BOX DRAWINGS LIGHT DOWN AND LEFT
0xc0	U+2514	#BOX DRAWINGS LIGHT UP AND RIGHT
0xc1	U+2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL
0xc2	U+252c	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
0xc3	U+251c	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
0xc4	U+2500	#BOX DRAWINGS LIGHT HORIZONTAL
0xc5	U+253c	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
0xc6	U+00e3	#LATIN SMALL LETTER A WITH TILDE
0xc7	U+00c3	#LATIN CAPITAL LETTER A WITH TILDE
0xc8	U+255a	#BOX DRAWINGS DOUBLE UP AND RIGHT
0xc9	U+2554	#BOX DRAWINGS DOUBLE DOWN AND RIGHT
0xca	U+2569	#BOX DRAWINGS DOUBLE UP AND HORIZONTAL
0xcb	U+2566	#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
0xcc	U+2560	#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
0xcd	U+2550	#BOX DRAWINGS DOUBLE HORIZONTAL
0xce	U+256c	#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
0xcf	U+00a4	#CURRENCY SIGN
0xd0	U+00f0	#LATIN SMALL LETTER ETH
0xd1	U+00d0	#LATIN CAPITAL LETTER ETH
0xd2	U+00ca	#LATIN CAPITAL LETTER E WITH CIRCUMFLEX
0xd3	U+00cb	#LATIN CAPITAL LETTER E WITH DIAERESIS
0xd4	U+00c8	#LATIN CAPITAL LETTER E WITH GRAVE
0xd5	U+0131	U+03b9	#LATIN SMALL LETTER DOTLESS I
0xd6	U+00cd	U+038a	#LATIN CAPITAL LETTER I WITH ACUTE
0xd7	U+00ce	#LATIN CAPITAL LETTER I WITH CIRCUMFLEX
0xd8	U+00cf	U+03aa	#LATIN CAPITAL LETTER I WITH DIAERESIS
0xd9	U+2518	#BOX DRAWINGS LIGHT UP AND LEFT
0xda	U+250c	#BOX DRAWINGS LIGHT DOWN AND RIGHT
0xdb	U+2588	#FULL BLOCK
0xdc	U+2584	#LOWER HALF BLOCK
0xdd	U+00a6	#BROKEN BAR
0xde	U+00cc	#LATIN CAPITAL LETTER I WITH GRAVE
0xdf	U+2580	#UPPER HALF BLOCK
0xe0	U+00d3	U+038c	#LATIN CAPITAL LETTER O WITH ACUTE
0xe1	U+00df	#LATIN SMALL LETTER SHARP S
0xe2	U+00d4	#LATIN CAPITAL LETTER O WITH CIRCUMFLEX
0xe3	U+00d2	#LATIN CAPITAL LETTER O WITH GRAVE
0xe4	U+00f5	#LATIN SMALL LETTER O WITH TILDE
0xe5	U+00d5	#LATIN CAPITAL LETTER O WITH TILDE
0xe6	U+00b5	U+03bc	#MICRO SIGN
0xe7	U+00fe	#LATIN SMALL LETTER THORN
0xe8	U+00de	#LATIN CAPITAL LETTER THORN
0xe9	U+00da	#LATIN CAPITAL LETTER U WITH ACUTE
0xea	U+00db	#LATIN CAPITAL LETTER U WITH CIRCUMFLEX
0xeb	U+00d9	#LATIN CAPITAL LETTER U WITH GRAVE
0xec	U+00fd	#LATIN SMALL LETTER Y WITH ACUTE
0xed	U+00dd	#LATIN CAPITAL LETTER Y WITH ACUTE
0xee	U+00af	U+0304	#MACRON
0xef	U+00b4	U+0301	#ACUTE ACCENT
0xf0	U+00ad	#SOFT HYPHEN
0xf1	U+00b1	#PLUS-MINUS SIGN
0xf2	U+2017	U+0333	#DOUBLE LOW LINE
0xf3	U+00be	#VULGAR FRACTION THREE QUARTERS
0xf4	U+00b6	#PILCROW SIGN
0xf5	U+00a7	#SECTION SIGN
0xf6	U+00f7	#DIVISION SIGN
0xf7	U+00b8	U+0327	#CEDILLA
0xf8	U+00b0	U+030a	#DEGREE SIGN
0xf9	U+00a8	U+0308	#DIAERESIS
0xfa	U+00b7	U+0307	U+0387	U+2027	#MIDDLE DOT
0xfb	U+00b9	#SUPERSCRIPT ONE
0xfc	U+00b3	#SUPERSCRIPT THREE
0xfd	U+00b2	#SUPERSCRIPT TWO
0xfe	U+25a0	#BLACK SQUARE
0xff	U+00a0	#NO-BREAK SPACE

U+2218 " \370 "		# RING OPERATOR
U+221b " ROOT\374 "
U+2297 "(\236)"		# CIRCLED TIMES
U+2299 "(\372)"		# CIRCLED DOT OPERATOR
U+229A "(\370)"		# CIRCLED RING OPERATOR
U+22A0 "[\236]"		# SQUARED TIMES
U+22A1 "[\372]"		# SQUARED DOT OPERATOR
U+22C5 " \372 "		# DOT OPERATOR
pan class="sx">bitwise AND ## with the specified `value` and returns the original value. proc fetchOr*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importcpp: "#.fetch_or(@)".} ## Atomically replaces the atomic integer with it's bitwise OR ## with the specified `value` and returns the original value. proc fetchXor*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importcpp: "#.fetch_xor(@)".} ## Atomically replaces the atomic integer with it's bitwise XOR ## with the specified `value` and returns the original value. # Flag operations proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool {.importcpp: "#.test_and_set(@)".} ## Atomically sets the atomic flag to true and returns the original value. proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) {.importcpp: "#.clear(@)".} ## Atomically sets the value of the atomic flag to false. proc fence*(order: MemoryOrder) {.importcpp: "std::atomic_thread_fence(@)".} ## Ensures memory ordering without using atomic operations. proc signalFence*(order: MemoryOrder) {.importcpp: "std::atomic_signal_fence(@)".} ## Prevents reordering of accesses by the compiler as would fence, but ## inserts no CPU instructions for memory ordering. {.pop.} else: # For the C backend, atomics map to C11 built-ins on GCC and Clang for # trivial Nim types. Other types are implemented using spin locks. # This could be overcome by supporting advanced importc-patterns. # Since MSVC does not implement C11, we fall back to MS intrinsics # where available. type Trivial = SomeNumber | bool | enum | ptr | pointer # A type that is known to be atomic and whose size is known at # compile time to be 8 bytes or less template nonAtomicType*(T: typedesc[Trivial]): untyped = # Maps types to integers of the same size when sizeof(T) == 1: int8 elif sizeof(T) == 2: int16 elif sizeof(T) == 4: int32 elif sizeof(T) == 8: int64 when defined(vcc): # TODO: Trivial types should be volatile and use VC's special volatile # semantics for store and loads. type MemoryOrder* = enum moRelaxed moConsume moAcquire moRelease moAcquireRelease moSequentiallyConsistent Atomic*[T] = object when T is Trivial: value: T.nonAtomicType else: nonAtomicValue: T guard: AtomicFlag AtomicFlag* = distinct int8 {.push header: "<intrin.h>".} # MSVC intrinsics proc interlockedExchange(location: pointer; desired: int8): int8 {.importc: "_InterlockedExchange8".} proc interlockedExchange(location: pointer; desired: int16): int16 {.importc: "_InterlockedExchange16".} proc interlockedExchange(location: pointer; desired: int32): int32 {.importc: "_InterlockedExchange".} proc interlockedExchange(location: pointer; desired: int64): int64 {.importc: "_InterlockedExchange64".} proc interlockedCompareExchange(location: pointer; desired, expected: int8): int8 {.importc: "_InterlockedCompareExchange8".} proc interlockedCompareExchange(location: pointer; desired, expected: int16): int16 {.importc: "_InterlockedCompareExchange16".} proc interlockedCompareExchange(location: pointer; desired, expected: int32): int32 {.importc: "_InterlockedCompareExchange".} proc interlockedCompareExchange(location: pointer; desired, expected: int64): int64 {.importc: "_InterlockedCompareExchange64".} proc interlockedAnd(location: pointer; value: int8): int8 {.importc: "_InterlockedAnd8".} proc interlockedAnd(location: pointer; value: int16): int16 {.importc: "_InterlockedAnd16".} proc interlockedAnd(location: pointer; value: int32): int32 {.importc: "_InterlockedAnd".} proc interlockedAnd(location: pointer; value: int64): int64 {.importc: "_InterlockedAnd64".} proc interlockedOr(location: pointer; value: int8): int8 {.importc: "_InterlockedOr8".} proc interlockedOr(location: pointer; value: int16): int16 {.importc: "_InterlockedOr16".} proc interlockedOr(location: pointer; value: int32): int32 {.importc: "_InterlockedOr".} proc interlockedOr(location: pointer; value: int64): int64 {.importc: "_InterlockedOr64".} proc interlockedXor(location: pointer; value: int8): int8 {.importc: "_InterlockedXor8".} proc interlockedXor(location: pointer; value: int16): int16 {.importc: "_InterlockedXor16".} proc interlockedXor(location: pointer; value: int32): int32 {.importc: "_InterlockedXor".} proc interlockedXor(location: pointer; value: int64): int64 {.importc: "_InterlockedXor64".} proc fence(order: MemoryOrder): int64 {.importc: "_ReadWriteBarrier()".} proc signalFence(order: MemoryOrder): int64 {.importc: "_ReadWriteBarrier()".} {.pop.} proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool = interlockedOr(addr(location), 1'i8) == 1'i8 proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) = discard interlockedAnd(addr(location), 0'i8) proc load*[T: Trivial](location: var Atomic[T]; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](interlockedOr(addr(location.value), (nonAtomicType(T))0)) proc store*[T: Trivial](location: var Atomic[T]; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.inline.} = discard interlockedExchange(addr(location.value), cast[nonAtomicType(T)](desired)) proc exchange*[T: Trivial](location: var Atomic[T]; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](interlockedExchange(addr(location.value), cast[int64](desired))) proc compareExchange*[T: Trivial](location: var Atomic[T]; expected: var T; desired: T; success, failure: MemoryOrder): bool {.inline.} = cast[T](interlockedCompareExchange(addr(location.value), cast[nonAtomicType(T)](desired), cast[nonAtomicType(T)](expected))) == expected proc compareExchange*[T: Trivial](location: var Atomic[T]; expected: var T; desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.inline.} = compareExchange(location, expected, desired, order, order) proc compareExchangeWeak*[T: Trivial](location: var Atomic[T]; expected: var T; desired: T; success, failure: MemoryOrder): bool {.inline.} = compareExchange(location, expected, desired, success, failure) proc compareExchangeWeak*[T: Trivial](location: var Atomic[T]; expected: var T; desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.inline.} = compareExchangeWeak(location, expected, desired, order, order) proc fetchAdd*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = var currentValue = location.load() while not compareExchangeWeak(location, currentValue, currentValue + value): discard proc fetchSub*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = fetchAdd(location, -value, order) proc fetchAnd*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](interlockedAnd(addr(location.value), cast[nonAtomicType(T)](value))) proc fetchOr*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](interlockedOr(addr(location.value), cast[nonAtomicType(T)](value))) proc fetchXor*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](interlockedXor(addr(location.value), cast[nonAtomicType(T)](value))) else: when defined(cpp): {.push, header: "<atomic>".} template maybeWrapStd(x: string): string = "std::" & x else: {.push, header: "<stdatomic.h>".} template maybeWrapStd(x: string): string = x type MemoryOrder* {.importc: "memory_order".maybeWrapStd.} = enum moRelaxed moConsume moAcquire moRelease moAcquireRelease moSequentiallyConsistent when defined(cpp): type # Atomic*[T] {.importcpp: "_Atomic('0)".} = object AtomicInt8 {.importc: "std::atomic<NI8>".} = int8 AtomicInt16 {.importc: "std::atomic<NI16>".} = int16 AtomicInt32 {.importc: "std::atomic<NI32>".} = int32 AtomicInt64 {.importc: "std::atomic<NI64>".} = int64 else: type # Atomic*[T] {.importcpp: "_Atomic('0)".} = object AtomicInt8 {.importc: "_Atomic NI8".} = int8 AtomicInt16 {.importc: "_Atomic NI16".} = int16 AtomicInt32 {.importc: "_Atomic NI32".} = int32 AtomicInt64 {.importc: "_Atomic NI64".} = int64 type AtomicFlag* {.importc: "atomic_flag".maybeWrapStd, size: 1.} = object Atomic*[T] = object when T is Trivial: # Maps the size of a trivial type to it's internal atomic type when sizeof(T) == 1: value: AtomicInt8 elif sizeof(T) == 2: value: AtomicInt16 elif sizeof(T) == 4: value: AtomicInt32 elif sizeof(T) == 8: value: AtomicInt64 else: nonAtomicValue: T guard: AtomicFlag #proc init*[T](location: var Atomic[T]; value: T): T {.importcpp: "atomic_init(@)".} proc atomic_load_explicit[T, A](location: ptr A; order: MemoryOrder): T {.importc: "atomic_load_explicit".maybeWrapStd.} proc atomic_store_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_store_explicit".maybeWrapStd.} proc atomic_exchange_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_exchange_explicit".maybeWrapStd.} proc atomic_compare_exchange_strong_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc: "atomic_compare_exchange_strong_explicit".maybeWrapStd.} proc atomic_compare_exchange_weak_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc: "atomic_compare_exchange_weak_explicit".maybeWrapStd.} # Numerical operations proc atomic_fetch_add_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_add_explicit".maybeWrapStd.} proc atomic_fetch_sub_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_sub_explicit".maybeWrapStd.} proc atomic_fetch_and_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_and_explicit".maybeWrapStd.} proc atomic_fetch_or_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_or_explicit".maybeWrapStd.} proc atomic_fetch_xor_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_xor_explicit".maybeWrapStd.} # Flag operations # var ATOMIC_FLAG_INIT {.importc, nodecl.}: AtomicFlag # proc init*(location: var AtomicFlag) {.inline.} = location = ATOMIC_FLAG_INIT proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool {.importc: "atomic_flag_test_and_set_explicit".maybeWrapStd.} proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_flag_clear_explicit".maybeWrapStd.} proc fence*(order: MemoryOrder) {.importc: "atomic_thread_fence".maybeWrapStd.} proc signalFence*(order: MemoryOrder) {.importc: "atomic_signal_fence".maybeWrapStd.} {.pop.} proc load*[T: Trivial](location: var Atomic[T]; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](atomic_load_explicit[nonAtomicType(T), typeof(location.value)](addr(location.value), order)) proc store*[T: Trivial](location: var Atomic[T]; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.inline.} = atomic_store_explicit(addr(location.value), cast[nonAtomicType(T)](desired), order) proc exchange*[T: Trivial](location: var Atomic[T]; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](atomic_exchange_explicit(addr(location.value), cast[nonAtomicType(T)](desired), order)) proc compareExchange*[T: Trivial](location: var Atomic[T]; expected: var T; desired: T; success, failure: MemoryOrder): bool {.inline.} = atomic_compare_exchange_strong_explicit(addr(location.value), cast[ptr nonAtomicType(T)](addr(expected)), cast[nonAtomicType(T)](desired), success, failure) proc compareExchange*[T: Trivial](location: var Atomic[T]; expected: var T; desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.inline.} = compareExchange(location, expected, desired, order, order) proc compareExchangeWeak*[T: Trivial](location: var Atomic[T]; expected: var T; desired: T; success, failure: MemoryOrder): bool {.inline.} = atomic_compare_exchange_weak_explicit(addr(location.value), cast[ptr nonAtomicType(T)](addr(expected)), cast[nonAtomicType(T)](desired), success, failure) proc compareExchangeWeak*[T: Trivial](location: var Atomic[T]; expected: var T; desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.inline.} = compareExchangeWeak(location, expected, desired, order, order) # Numerical operations proc fetchAdd*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](atomic_fetch_add_explicit(addr(location.value), cast[nonAtomicType(T)](value), order)) proc fetchSub*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](atomic_fetch_sub_explicit(addr(location.value), cast[nonAtomicType(T)](value), order)) proc fetchAnd*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](atomic_fetch_and_explicit(addr(location.value), cast[nonAtomicType(T)](value), order)) proc fetchOr*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](atomic_fetch_or_explicit(addr(location.value), cast[nonAtomicType(T)](value), order)) proc fetchXor*[T: SomeInteger](location: var Atomic[T]; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = cast[T](atomic_fetch_xor_explicit(addr(location.value), cast[nonAtomicType(T)](value), order)) template withLock[T: not Trivial](location: var Atomic[T]; order: MemoryOrder; body: untyped): untyped = while testAndSet(location.guard, moAcquire): discard try: body finally: clear(location.guard, moRelease) proc load*[T: not Trivial](location: var Atomic[T]; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = withLock(location, order): result = location.nonAtomicValue proc store*[T: not Trivial](location: var Atomic[T]; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.inline.} = withLock(location, order): location.nonAtomicValue = desired proc exchange*[T: not Trivial](location: var Atomic[T]; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} = withLock(location, order): result = location.nonAtomicValue location.nonAtomicValue = desired proc compareExchange*[T: not Trivial](location: var Atomic[T]; expected: var T; desired: T; success, failure: MemoryOrder): bool {.inline.} = withLock(location, success): if location.nonAtomicValue != expected: expected = location.nonAtomicValue return false expected = desired swap(location.nonAtomicValue, expected) return true proc compareExchangeWeak*[T: not Trivial](location: var Atomic[T]; expected: var T; desired: T; success, failure: MemoryOrder): bool {.inline.} = compareExchange(location, expected, desired, success, failure) proc compareExchange*[T: not Trivial](location: var Atomic[T]; expected: var T; desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.inline.} = compareExchange(location, expected, desired, order, order) proc compareExchangeWeak*[T: not Trivial](location: var Atomic[T]; expected: var T; desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.inline.} = compareExchangeWeak(location, expected, desired, order, order) proc atomicInc*[T: SomeInteger](location: var Atomic[T]; value: T = 1) {.inline.} = ## Atomically increments the atomic integer by some `value`. discard location.fetchAdd(value) proc atomicDec*[T: SomeInteger](location: var Atomic[T]; value: T = 1) {.inline.} = ## Atomically decrements the atomic integer by some `value`. discard location.fetchSub(value) proc `+=`*[T: SomeInteger](location: var Atomic[T]; value: T) {.inline.} = ## Atomically increments the atomic integer by some `value`. discard location.fetchAdd(value) proc `-=`*[T: SomeInteger](location: var Atomic[T]; value: T) {.inline.} = ## Atomically decrements the atomic integer by some `value`. discard location.fetchSub(value)