#ifndef _MSC_VER
#  include <stdatomic.h>

typedef atomic_size_t Refcount;

#  define refcount_inited(counter) (refcount_load(counter) != 0)
#  define refcount_load(counter) atomic_load(counter)
#  define refcount_init(counter, value) atomic_init(counter, value)
#  define refcount_inc(counter) atomic_fetch_add_explicit(counter, 1, memory_order_relaxed)
#  define refcount_dec(counter) atomic_fetch_sub_explicit(counter, 1, memory_order_acq_rel)
#  define refcount_destroy(count) ((void)0)
#else
/* Visual C++ doesn't support C11 atomics yet. However, Windows documentation
 * guarantees that simple reads and writes are atomic:
 * https://docs.microsoft.com/en-us/windows/win32/sync/interlocked-variable-access
 */
#  include <windows.h>

typedef volatile size_t Refcount;

#  define refcount_inited(counter) (*(counter) != 0)
#  define refcount_load(counter) *(counter)
#  define refcount_init(counter, value) *(counter) = (value)
#  define refcount_destroy(count) ((void)0)

#  ifdef _WIN64
#    define refcount_inc(counter) InterlockedExchangeAdd64((LONG64*)(counter), 1)
#    define refcount_dec(counter) InterlockedExchangeAdd64((LONG64*)(counter), -1)
#  else
#    define refcount_inc(counter) InterlockedExchangeAdd((LONG*)(counter), 1)
#    define refcount_dec(counter) InterlockedExchangeAdd((LONG*)(counter), -1)
#  endif
#endif