]> code.bitgloo.com Git - clyne/zephyr-os-alpha.git/commitdiff
trying out distortos
authorClyne Sullivan <tullivan99@gmail.com>
Wed, 9 Nov 2016 01:09:05 +0000 (20:09 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Wed, 9 Nov 2016 01:09:05 +0000 (20:09 -0500)
125 files changed:
Makefile [deleted file]
STM32F103VD.ld [new file with mode: 0644]
chconf.h [deleted file]
halconf.h [deleted file]
include/control.h [deleted file]
include/distortos/ConditionVariable.hpp [new file with mode: 0644]
include/distortos/DynamicFifoQueue.hpp [new file with mode: 0644]
include/distortos/DynamicMessageQueue.hpp [new file with mode: 0644]
include/distortos/DynamicRawFifoQueue.hpp [new file with mode: 0644]
include/distortos/DynamicRawMessageQueue.hpp [new file with mode: 0644]
include/distortos/DynamicSignalsReceiver.hpp [new file with mode: 0644]
include/distortos/DynamicThread.hpp [new file with mode: 0644]
include/distortos/DynamicThreadParameters.hpp [new file with mode: 0644]
include/distortos/FifoQueue.hpp [new file with mode: 0644]
include/distortos/MessageQueue.hpp [new file with mode: 0644]
include/distortos/Mutex.hpp [new file with mode: 0644]
include/distortos/OnceFlag.hpp [new file with mode: 0644]
include/distortos/RawFifoQueue.hpp [new file with mode: 0644]
include/distortos/RawMessageQueue.hpp [new file with mode: 0644]
include/distortos/SchedulingPolicy.hpp [new file with mode: 0644]
include/distortos/Semaphore.hpp [new file with mode: 0644]
include/distortos/SignalAction.hpp [new file with mode: 0644]
include/distortos/SignalInformation.hpp [new file with mode: 0644]
include/distortos/SignalInformationQueueWrapper.hpp [new file with mode: 0644]
include/distortos/SignalSet.hpp [new file with mode: 0644]
include/distortos/SignalsCatcher.hpp [new file with mode: 0644]
include/distortos/SignalsReceiver.hpp [new file with mode: 0644]
include/distortos/SoftwareTimer.hpp [new file with mode: 0644]
include/distortos/SoftwareTimerCommon.hpp [new file with mode: 0644]
include/distortos/StaticFifoQueue.hpp [new file with mode: 0644]
include/distortos/StaticMessageQueue.hpp [new file with mode: 0644]
include/distortos/StaticRawFifoQueue.hpp [new file with mode: 0644]
include/distortos/StaticRawMessageQueue.hpp [new file with mode: 0644]
include/distortos/StaticSignalsReceiver.hpp [new file with mode: 0644]
include/distortos/StaticSoftwareTimer.hpp [new file with mode: 0644]
include/distortos/StaticThread.hpp [new file with mode: 0644]
include/distortos/ThisThread-Signals.hpp [new file with mode: 0644]
include/distortos/ThisThread.hpp [new file with mode: 0644]
include/distortos/Thread.hpp [new file with mode: 0644]
include/distortos/ThreadCommon.hpp [new file with mode: 0644]
include/distortos/ThreadState.hpp [new file with mode: 0644]
include/distortos/TickClock.hpp [new file with mode: 0644]
include/distortos/UndetachableThread.hpp [new file with mode: 0644]
include/distortos/architecture/InterruptMaskingLock.hpp [new file with mode: 0644]
include/distortos/architecture/InterruptMaskingUnmaskingLock.hpp [new file with mode: 0644]
include/distortos/architecture/InterruptUnmaskingLock.hpp [new file with mode: 0644]
include/distortos/architecture/Stack.hpp [new file with mode: 0644]
include/distortos/architecture/disableInterruptMasking.hpp [new file with mode: 0644]
include/distortos/architecture/enableInterruptMasking.hpp [new file with mode: 0644]
include/distortos/architecture/getMainStack.hpp [new file with mode: 0644]
include/distortos/architecture/initializeStack.hpp [new file with mode: 0644]
include/distortos/architecture/lowLevelInitialization.hpp [new file with mode: 0644]
include/distortos/architecture/requestContextSwitch.hpp [new file with mode: 0644]
include/distortos/architecture/requestFunctionExecution.hpp [new file with mode: 0644]
include/distortos/architecture/restoreInterruptMasking.hpp [new file with mode: 0644]
include/distortos/architecture/startScheduling.hpp [new file with mode: 0644]
include/distortos/board/lowLevelInitialization.hpp [new file with mode: 0644]
include/distortos/callOnce.hpp [new file with mode: 0644]
include/distortos/chip/lowLevelInitialization.hpp [new file with mode: 0644]
include/distortos/devices/io/InputPin.hpp [new file with mode: 0644]
include/distortos/devices/io/OutputPin.hpp [new file with mode: 0644]
include/distortos/distortosVersion.h [new file with mode: 0644]
include/distortos/internal/memory/DeferredThreadDeleter.hpp [new file with mode: 0644]
include/distortos/internal/memory/dummyDeleter.hpp [new file with mode: 0644]
include/distortos/internal/memory/getDeferredThreadDeleter.hpp [new file with mode: 0644]
include/distortos/internal/memory/getMallocMutex.hpp [new file with mode: 0644]
include/distortos/internal/memory/storageDeleter.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/DynamicThreadBase.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/MainThread.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/RoundRobinQuantum.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/Scheduler.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/SoftwareTimerControlBlock.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/SoftwareTimerList.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/SoftwareTimerListNode.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/SoftwareTimerSupervisor.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/ThreadControlBlock.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/ThreadGroupControlBlock.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/ThreadList.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/ThreadListNode.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/forceContextSwitch.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/getScheduler.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/idleThreadFunction.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/lowLevelInitialization.hpp [new file with mode: 0644]
include/distortos/internal/scheduler/threadRunner.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/BoundQueueFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/CallOnceControlBlock.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/CopyConstructQueueFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/FifoQueueBase.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/MemcpyPopQueueFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/MemcpyPushQueueFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/MessageQueueBase.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/MoveConstructQueueFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/MutexControlBlock.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/MutexList.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/MutexListNode.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/QueueFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SemaphoreFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SemaphoreTryWaitForFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SemaphoreTryWaitFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SemaphoreTryWaitUntilFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SemaphoreWaitFunctor.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SignalInformationQueue.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SignalsCatcherControlBlock.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SignalsReceiverControlBlock.hpp [new file with mode: 0644]
include/distortos/internal/synchronization/SwapPopQueueFunctor.hpp [new file with mode: 0644]
include/distortos/statistics.hpp [new file with mode: 0644]
include/estd/ContiguousRange.hpp [new file with mode: 0644]
include/estd/IntegerSequence.hpp [new file with mode: 0644]
include/estd/IntrusiveForwardList.hpp [new file with mode: 0644]
include/estd/IntrusiveList.hpp [new file with mode: 0644]
include/estd/ReferenceHolder.hpp [new file with mode: 0644]
include/estd/ReverseAdaptor.hpp [new file with mode: 0644]
include/estd/SortedIntrusiveForwardList.hpp [new file with mode: 0644]
include/estd/SortedIntrusiveList.hpp [new file with mode: 0644]
include/estd/TypeErasedFunctor.hpp [new file with mode: 0644]
include/estd/apply.hpp [new file with mode: 0644]
include/estd/invoke.hpp [new file with mode: 0644]
include/motor.h [deleted file]
include/sys/signal.h [new file with mode: 0644]
libdistortos.a [new file with mode: 0644]
main.cpp [deleted file]
mcuconf.h [deleted file]
setup.mk [deleted file]
src/motor.cpp [deleted file]
vexuser.cpp [deleted file]

diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index 5a7aaed..0000000
--- a/Makefile
+++ /dev/null
@@ -1,239 +0,0 @@
-##############################################################################\r
-# Build global options\r
-# NOTE: Can be overridden externally.\r
-#\r
-include setup.mk\r
-\r
-# Compiler options here.\r
-ifeq ($(USE_OPT),)\r
-  USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 -fsingle-precision-constant \r
-endif\r
-\r
-# C specific options here (added to USE_OPT).\r
-ifeq ($(USE_COPT),)\r
-  USE_COPT = -std=gnu99\r
-endif\r
-\r
-# C++ specific options here (added to USE_OPT).\r
-ifeq ($(USE_CPPOPT),)\r
-  USE_CPPOPT = -fno-rtti \r
-endif\r
-\r
-# Enable this if you want the linker to remove unused code and data\r
-ifeq ($(USE_LINK_GC),)\r
-  USE_LINK_GC = yes\r
-endif\r
-\r
-# If enabled, this option allows to compile the application in THUMB mode.\r
-ifeq ($(USE_THUMB),)\r
-  USE_THUMB = yes\r
-endif\r
-\r
-# Enable this if you want to see the full log while compiling.\r
-ifeq ($(USE_VERBOSE_COMPILE),)\r
-  USE_VERBOSE_COMPILE = yes\r
-endif\r
-\r
-#\r
-# Build global options\r
-##############################################################################\r
-\r
-##############################################################################\r
-# Architecture or project specific options\r
-#\r
-\r
-# Enable this if you really want to use the STM FWLib.\r
-ifeq ($(USE_FWLIB),)\r
-  USE_FWLIB = no\r
-endif\r
-\r
-#\r
-# Architecture or project specific options\r
-##############################################################################\r
-\r
-##############################################################################\r
-# Project, sources and paths\r
-#\r
-\r
-# PROS compatible build directory\r
-ifeq ($(BUILDDIR),)\r
-BUILDDIR = bin\r
-endif\r
-\r
-# Define project name here\r
-ifeq ($(PROJECT),)\r
-PROJECT  = output\r
-endif\r
-\r
-# Path to ChibiOS/RT - default assumes making examples\r
-ifeq ($(CHIBIOS),)\r
-CHIBIOS = ../../../../ChibiOS_2.6.2\r
-endif\r
-\r
-# Path to ConVEX root - default assumes making examples\r
-ifeq ($(CONVEX),)\r
-CONVEX  = ../..\r
-endif\r
-\r
-# Imported source files and paths\r
-include $(CONVEX)/boards/VEX_STM32_CORTEX/board.mk\r
-include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk\r
-include $(CHIBIOS)/os/hal/hal.mk\r
-include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk\r
-include $(CHIBIOS)/os/kernel/kernel.mk\r
-include $(CONVEX)/fw/vexfw.mk\r
-\r
-# include the optional code\r
-ifeq    ($(CONVEX_OPT),yes)\r
-include $(CONVEX)/opt/vexopt.mk\r
-endif\r
-\r
-# Define linker script file here\r
-LDSCRIPT= $(CONVEX)/ld/STM32F103xD.ld\r
-\r
-\r
-# C sources that can be compiled in ARM or THUMB mode depending on the global\r
-# setting.\r
-# replaced standard shell with custom variant\r
-# $(CHIBIOS)/os/various/shell.c \\r
-       \r
-CSRC = $(PORTSRC) \\r
-       $(KERNSRC) \\r
-       $(HALSRC) \\r
-       $(PLATFORMSRC) \\r
-       $(BOARDSRC) \\r
-       $(CHIBIOS)/os/various/evtimer.c \\r
-       $(CHIBIOS)/os/various/syscalls.c \\r
-       $(CHIBIOS)/os/various/chprintf.c \\r
-       $(VEXFWSRC) \\r
-       $(VEXOPTSRC)\r
-#       $(VEXUSERSRC) \\r
-#       main.c\r
-\r
-# C++ sources that can be compiled in ARM or THUMB mode depending on the global\r
-# setting.\r
-CPPSRC = $(VEXUSERSRC) \\r
-        main.cpp\r
-\r
-# C sources to be compiled in ARM mode regardless of the global setting.\r
-# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler\r
-#       option that results in lower performance and larger code size.\r
-ACSRC =\r
-\r
-# C++ sources to be compiled in ARM mode regardless of the global setting.\r
-# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler\r
-#       option that results in lower performance and larger code size.\r
-ACPPSRC =\r
-\r
-# C sources to be compiled in THUMB mode regardless of the global setting.\r
-# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler\r
-#       option that results in lower performance and larger code size.\r
-TCSRC =\r
-\r
-# C sources to be compiled in THUMB mode regardless of the global setting.\r
-# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler\r
-#       option that results in lower performance and larger code size.\r
-TCPPSRC =\r
-\r
-# List ASM source files here\r
-ASMSRC = $(PORTASM)\r
-\r
-INCDIR = $(PORTINC) $(KERNINC) \\r
-         $(HALINC) $(PLATFORMINC) $(BOARDINC) \\r
-         $(CHIBIOS)/os/various $(VEXFWINC) $(VEXOPTINC) $(VEXUSERINC)\r
-\r
-#\r
-# Project, sources and paths\r
-##############################################################################\r
-\r
-##############################################################################\r
-# Compiler settings\r
-#\r
-\r
-MCU  = cortex-m3\r
-\r
-#TRGT = arm-elf-\r
-TRGT = arm-none-eabi-\r
-CC   = $(TRGT)gcc\r
-CPPC = $(TRGT)g++\r
-# Enable loading with g++ only if you need C++ runtime support.\r
-# NOTE: You can use C++ even without C++ support if you are careful. C++\r
-#       runtime support makes code size explode.\r
-#D   = $(TRGT)gcc\r
-LD   = $(TRGT)g++\r
-CP   = $(TRGT)objcopy\r
-AS   = $(TRGT)gcc -x assembler-with-cpp\r
-OD   = $(TRGT)objdump\r
-HEX  = $(CP) -O ihex\r
-BIN  = $(CP) -O binary\r
-\r
-# ARM-specific options here\r
-AOPT = -mfloat-abi=hard -mcpu=cortex-m3 \r
-\r
-# THUMB-specific options here\r
-TOPT = -mthumb -DTHUMB\r
-\r
-# Define C warning options here\r
-CWARN = -Wall -Wextra -Wstrict-prototypes\r
-\r
-# Define C++ warning options here\r
-CPPWARN = -Wall -Wextra -Wno-write-strings\r
-\r
-#\r
-# Compiler settings\r
-##############################################################################\r
-\r
-##############################################################################\r
-# Start of default section\r
-#\r
-\r
-# List all default C defines here, like -D_DEBUG=1\r
-DDEFS =\r
-\r
-# List all default ASM defines here, like -D_DEBUG=1\r
-DADEFS =\r
-\r
-# List all default directories to look for include files here\r
-DINCDIR =\r
-\r
-# List the default directory to look for the libraries here\r
-DLIBDIR = \r
-\r
-# List all default libraries here\r
-DLIBS =\r
-\r
-#\r
-# End of default section\r
-##############################################################################\r
-\r
-##############################################################################\r
-# Start of user section\r
-#\r
-\r
-# List all user C define here, like -D_DEBUG=1\r
-UDEFS =\r
-\r
-# Define ASM defines here\r
-UADEFS =\r
-\r
-# List all user directories here\r
-UINCDIR =\r
-\r
-# List the user directory to look for the libraries here\r
-ULIBDIR =\r
-\r
-# List all user libraries here\r
-ULIBS = -lm\r
-\r
-#\r
-# End of user defines\r
-##############################################################################\r
-\r
-ifeq ($(USE_FWLIB),yes)\r
-  include $(CHIBIOS)/ext/stm32lib/stm32lib.mk\r
-  CSRC += $(STM32SRC)\r
-  INCDIR += $(STM32INC)\r
-  USE_OPT += -DUSE_STDPERIPH_DRIVER\r
-endif\r
-\r
-include $(CHIBIOS)/os/ports/GCC/ARMCMx/rules.mk\r
diff --git a/STM32F103VD.ld b/STM32F103VD.ld
new file mode 100644 (file)
index 0000000..21f2004
--- /dev/null
@@ -0,0 +1,267 @@
+/**
+ * \file
+ * \brief Linker script for STM32F103VD chip:
+ * - 393216 bytes of rom;
+ * - 65536 bytes of ram;
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * \warning
+ * Automatically generated file - do not edit!
+ *
+ * \date 2016-11-08 19:50:43
+ */
+
+SEARCH_DIR(.);
+OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm");
+OUTPUT_ARCH(arm);
+
+/*---------------------------------------------------------------------------------------------------------------------+
+| stacks sizes
++---------------------------------------------------------------------------------------------------------------------*/
+
+/* Handler mode (core exceptions / interrupts) can use only main stack */
+PROVIDE(__main_stack_size = 2048);
+
+/* Thread mode can use main stack (default after reset) or process stack - selected in CONTROL special register */
+PROVIDE(__process_stack_size = 2048);
+
+/*---------------------------------------------------------------------------------------------------------------------+
+| available memories
++---------------------------------------------------------------------------------------------------------------------*/
+
+MEMORY
+{
+       rom : org = 0x08000000, len = 393216
+       ram : org = 0x20000000, len = 65536
+}
+
+PROVIDE(__rom_start = ORIGIN(rom));
+PROVIDE(__rom_size = LENGTH(rom));
+PROVIDE(__rom_end = __rom_start + __rom_size);
+
+PROVIDE(__ram_start = ORIGIN(ram));
+PROVIDE(__ram_size = LENGTH(ram));
+PROVIDE(__ram_end = __ram_start + __ram_size);
+
+/*---------------------------------------------------------------------------------------------------------------------+
+| entry point
++---------------------------------------------------------------------------------------------------------------------*/
+
+ENTRY(Reset_Handler);
+
+/*---------------------------------------------------------------------------------------------------------------------+
+| put data in sections
++---------------------------------------------------------------------------------------------------------------------*/
+
+SECTIONS
+{
+       .text :
+       {
+               . = ALIGN(4);
+               PROVIDE(__text_start = .);
+
+               /* sub-section: .vectors */
+
+               . = ALIGN(4);
+               PROVIDE(__vectors_start = .);
+
+               KEEP(*(.coreVectors));
+               KEEP(*(.chipVectors));
+
+               . = ALIGN(4);
+               PROVIDE(__vectors_end = .);
+
+               /* end of sub-section: .vectors */
+
+               *(.text* .gnu.linkonce.t.*);
+               *(.rodata* .gnu.linkonce.r.*);
+               *(.glue_7t .glue_7);
+
+               *(.ARM.extab* .gnu.linkonce.armextab.*);        /* exception unwinding information */
+               *(.gcc_except_table);                                           /* information used for stack unwinding during exception */
+               *(.eh_frame_hdr);                                                       /* additional information about .ex_frame section */
+               *(.eh_frame);                                                           /* information used for stack unwinding during exception */
+
+               /* sub-section: data_array */
+
+               . = ALIGN(4);
+               PROVIDE(__data_array_start = .);
+
+               LONG(LOADADDR(.data)); LONG(ADDR(.data)); LONG(ADDR(.data) + SIZEOF(.data));
+
+               . = ALIGN(4);
+               PROVIDE(__data_array_end = .);
+
+               /* end of sub-section: data_array */
+
+               /* sub-section: bss_array */
+
+               . = ALIGN(4);
+               PROVIDE(__bss_array_start = .);
+
+               LONG(ADDR(.bss)); LONG(ADDR(.bss) + SIZEOF(.bss));
+               LONG(ADDR(.stack)); LONG(ADDR(.stack) + SIZEOF(.stack));
+
+               . = ALIGN(4);
+               PROVIDE(__bss_array_end = .);
+
+               /* end of sub-section: bss_array */
+
+               /* sub-sections: init, preinit_array, init_array and fini_array */
+
+               KEEP(*(.init));
+
+               . = ALIGN(4);
+               PROVIDE(__preinit_array_start = .);
+
+               KEEP(*(.preinit_array));
+
+               . = ALIGN(4);
+               PROVIDE(__preinit_array_end = .);
+
+               . = ALIGN(4);
+               PROVIDE(__init_array_start = .);
+
+               KEEP(*(SORT(.init_array.*)));
+               KEEP(*(.init_array));
+
+               . = ALIGN(4);
+               PROVIDE(__init_array_end = .);
+
+               KEEP(*(.fini));
+
+               . = ALIGN(4);
+               PROVIDE(__fini_array_start = .);
+
+               KEEP(*(.fini_array));
+               KEEP(*(SORT(.fini_array.*)));
+
+               . = ALIGN(4);
+               PROVIDE(__fini_array_end = .);
+
+               /* end of sub-sections: init, preinit_array, init_array and fini_array */
+
+               . = ALIGN(4);
+               PROVIDE(__text_end = .);
+       } > rom AT > rom
+
+       . = ALIGN(4);
+       PROVIDE(__exidx_start = .);
+
+       .ARM.exidx :
+       {
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*);
+       } > rom AT > rom                                                                /* index entries for section unwinding */
+
+       . = ALIGN(4);
+       PROVIDE(__exidx_end = .);
+
+       .bss :
+       {
+               . = ALIGN(4);
+               PROVIDE(__bss_start = .);
+
+               *(.bss* .gnu.linkonce.b.*)
+               *(COMMON);
+
+               . = ALIGN(4);
+               PROVIDE(__bss_end = .);
+       } > ram AT > ram
+
+       .data :
+       {
+               . = ALIGN(4);
+               PROVIDE(__data_init_start = LOADADDR(.data));
+               PROVIDE(__data_start = .);
+
+               *(.data* .gnu.linkonce.d.*)
+
+               . = ALIGN(4);
+               PROVIDE(__data_end = .);
+       } > ram AT > rom
+
+       .noinit (NOLOAD) :
+       {
+               . = ALIGN(4);
+               PROVIDE(__noinit_start = .);
+
+               *(.noinit)
+
+               . = ALIGN(4);
+               PROVIDE(__noinit_end = .);
+       } > ram AT > ram
+
+       .stack :
+       {
+               . = ALIGN(8);
+               PROVIDE(__stack_start = .);
+               PROVIDE(__main_stack_start = .);
+
+               . += __main_stack_size;
+
+               . = ALIGN(8);
+               PROVIDE(__main_stack_end = .);
+               PROVIDE(__process_stack_start = .);
+
+               . += __process_stack_size;
+
+               . = ALIGN(8);
+               PROVIDE(__process_stack_end = .);
+               PROVIDE(__stack_end = .);
+       } > ram AT > ram
+
+       . = ALIGN(4);
+       PROVIDE(__heap_start = .);
+       PROVIDE(__heap_end = __ram_end);
+
+       .stab                           0 (NOLOAD) : { *(.stab) }
+       .stabstr                        0 (NOLOAD) : { *(.stabstr) }
+       /* DWARF debug sections.
+       * Symbols in the DWARF debugging sections are relative to the beginning
+       * of the section so we begin them at 0. */
+       /* DWARF 1 */
+       .debug                          0 : { *(.debug) }
+       .line                           0 : { *(.line) }
+       /* GNU DWARF 1 extensions */
+       .debug_srcinfo          0 : { *(.debug_srcinfo) }
+       .debug_sfnames          0 : { *(.debug_sfnames) }
+       /* DWARF 1.1 and DWARF 2 */
+       .debug_aranges          0 : { *(.debug_aranges) }
+       .debug_pubnames         0 : { *(.debug_pubnames) }
+       /* DWARF 2 */
+       .debug_info                     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+       .debug_abbrev           0 : { *(.debug_abbrev) }
+       .debug_line                     0 : { *(.debug_line) }
+       .debug_frame            0 : { *(.debug_frame) }
+       .debug_str                      0 : { *(.debug_str) }
+       .debug_loc                      0 : { *(.debug_loc) }
+       .debug_macinfo          0 : { *(.debug_macinfo) }
+       /* SGI/MIPS DWARF 2 extensions */
+       .debug_weaknames        0 : { *(.debug_weaknames) }
+       .debug_funcnames        0 : { *(.debug_funcnames) }
+       .debug_typenames        0 : { *(.debug_typenames) }
+       .debug_varnames         0 : { *(.debug_varnames) }
+
+       .note.gnu.arm.ident     0 : { KEEP(*(.note.gnu.arm.ident)) }
+       .ARM.attributes         0 : { KEEP(*(.ARM.attributes)) }
+       /DISCARD/                               : { *(.note.GNU-stack) }
+}
+
+PROVIDE(__text_size = __text_end - __text_start);
+PROVIDE(__vectors_size = __vectors_end - __vectors_start);
+PROVIDE(__data_array_size = __data_array_end - __data_array_start);
+PROVIDE(__bss_array_size = __bss_array_end - __bss_array_start);
+PROVIDE(__exidx_size = __exidx_end - __exidx_start);
+PROVIDE(__bss_size = __bss_end - __bss_start);
+PROVIDE(__data_size = __data_end - __data_start);
+PROVIDE(__noinit_size = __noinit_end - __noinit_start);
+PROVIDE(__stack_size = __stack_end - __stack_start);
+PROVIDE(__heap_size = __heap_end - __heap_start);
+
+PROVIDE(__bss_start__ = __bss_start);
+PROVIDE(__bss_end__ = __bss_end);
diff --git a/chconf.h b/chconf.h
deleted file mode 100644 (file)
index f943ea8..0000000
--- a/chconf.h
+++ /dev/null
@@ -1,531 +0,0 @@
-/*\r
-    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio\r
-\r
-    Licensed under the Apache License, Version 2.0 (the "License");\r
-    you may not use this file except in compliance with the License.\r
-    You may obtain a copy of the License at\r
-\r
-        http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-    Unless required by applicable law or agreed to in writing, software\r
-    distributed under the License is distributed on an "AS IS" BASIS,\r
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-    See the License for the specific language governing permissions and\r
-    limitations under the License.\r
-*/\r
-\r
-/**\r
- * @file    templates/chconf.h\r
- * @brief   Configuration file template.\r
- * @details A copy of this file must be placed in each project directory, it\r
- *          contains the application specific kernel settings.\r
- *\r
- * @addtogroup config\r
- * @details Kernel related settings and hooks.\r
- * @{\r
- */\r
-\r
-#ifndef _CHCONF_H_\r
-#define _CHCONF_H_\r
-\r
-/*===========================================================================*/\r
-/**\r
- * @name Kernel parameters and options\r
- * @{\r
- */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   System tick frequency.\r
- * @details Frequency of the system timer that drives the system ticks. This\r
- *          setting also defines the system tick time unit.\r
- */\r
-#if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)\r
-#define CH_FREQUENCY                    1000\r
-#endif\r
-\r
-/**\r
- * @brief   Round robin interval.\r
- * @details This constant is the number of system ticks allowed for the\r
- *          threads before preemption occurs. Setting this value to zero\r
- *          disables the preemption for threads with equal priority and the\r
- *          round robin becomes cooperative. Note that higher priority\r
- *          threads can still preempt, the kernel is always preemptive.\r
- *\r
- * @note    Disabling the round robin preemption makes the kernel more compact\r
- *          and generally faster.\r
- */\r
-#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)\r
-#define CH_TIME_QUANTUM                 20\r
-#endif\r
-\r
-/**\r
- * @brief   Managed RAM size.\r
- * @details Size of the RAM area to be managed by the OS. If set to zero\r
- *          then the whole available RAM is used. The core memory is made\r
- *          available to the heap allocator and/or can be used directly through\r
- *          the simplified core memory allocator.\r
- *\r
- * @note    In order to let the OS manage the whole RAM the linker script must\r
- *          provide the @p __heap_base__ and @p __heap_end__ symbols.\r
- * @note    Requires @p CH_USE_MEMCORE.\r
- */\r
-#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)\r
-#define CH_MEMCORE_SIZE                 0\r
-#endif\r
-\r
-/**\r
- * @brief   Idle thread automatic spawn suppression.\r
- * @details When this option is activated the function @p chSysInit()\r
- *          does not spawn the idle thread automatically. The application has\r
- *          then the responsibility to do one of the following:\r
- *          - Spawn a custom idle thread at priority @p IDLEPRIO.\r
- *          - Change the main() thread priority to @p IDLEPRIO then enter\r
- *            an endless loop. In this scenario the @p main() thread acts as\r
- *            the idle thread.\r
- *          .\r
- * @note    Unless an idle thread is spawned the @p main() thread must not\r
- *          enter a sleep state.\r
- */\r
-#if !defined(CH_NO_IDLE_THREAD) || defined(__DOXYGEN__)\r
-#define CH_NO_IDLE_THREAD               FALSE\r
-#endif\r
-\r
-/** @} */\r
-\r
-/*===========================================================================*/\r
-/**\r
- * @name Performance options\r
- * @{\r
- */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   OS optimization.\r
- * @details If enabled then time efficient rather than space efficient code\r
- *          is used when two possible implementations exist.\r
- *\r
- * @note    This is not related to the compiler optimization options.\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__)\r
-#define CH_OPTIMIZE_SPEED               TRUE\r
-#endif\r
-\r
-/** @} */\r
-\r
-/*===========================================================================*/\r
-/**\r
- * @name Subsystem options\r
- * @{\r
- */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Threads registry APIs.\r
- * @details If enabled then the registry APIs are included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__)\r
-#define CH_USE_REGISTRY                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Threads synchronization APIs.\r
- * @details If enabled then the @p chThdWait() function is included in\r
- *          the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)\r
-#define CH_USE_WAITEXIT                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Semaphores APIs.\r
- * @details If enabled then the Semaphores APIs are included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)\r
-#define CH_USE_SEMAPHORES               TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Semaphores queuing mode.\r
- * @details If enabled then the threads are enqueued on semaphores by\r
- *          priority rather than in FIFO order.\r
- *\r
- * @note    The default is @p FALSE. Enable this if you have special requirements.\r
- * @note    Requires @p CH_USE_SEMAPHORES.\r
- */\r
-#if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__)\r
-#define CH_USE_SEMAPHORES_PRIORITY      FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Atomic semaphore API.\r
- * @details If enabled then the semaphores the @p chSemSignalWait() API\r
- *          is included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- * @note    Requires @p CH_USE_SEMAPHORES.\r
- */\r
-#if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__)\r
-#define CH_USE_SEMSW                    TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Mutexes APIs.\r
- * @details If enabled then the mutexes APIs are included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)\r
-#define CH_USE_MUTEXES                  TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Conditional Variables APIs.\r
- * @details If enabled then the conditional variables APIs are included\r
- *          in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- * @note    Requires @p CH_USE_MUTEXES.\r
- */\r
-#if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__)\r
-#define CH_USE_CONDVARS                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Conditional Variables APIs with timeout.\r
- * @details If enabled then the conditional variables APIs with timeout\r
- *          specification are included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- * @note    Requires @p CH_USE_CONDVARS.\r
- */\r
-#if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__)\r
-#define CH_USE_CONDVARS_TIMEOUT         TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Events Flags APIs.\r
- * @details If enabled then the event flags APIs are included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)\r
-#define CH_USE_EVENTS                   TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Events Flags APIs with timeout.\r
- * @details If enabled then the events APIs with timeout specification\r
- *          are included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- * @note    Requires @p CH_USE_EVENTS.\r
- */\r
-#if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__)\r
-#define CH_USE_EVENTS_TIMEOUT           TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Synchronous Messages APIs.\r
- * @details If enabled then the synchronous messages APIs are included\r
- *          in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)\r
-#define CH_USE_MESSAGES                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Synchronous Messages queuing mode.\r
- * @details If enabled then messages are served by priority rather than in\r
- *          FIFO order.\r
- *\r
- * @note    The default is @p FALSE. Enable this if you have special requirements.\r
- * @note    Requires @p CH_USE_MESSAGES.\r
- */\r
-#if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__)\r
-#define CH_USE_MESSAGES_PRIORITY        FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Mailboxes APIs.\r
- * @details If enabled then the asynchronous messages (mailboxes) APIs are\r
- *          included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- * @note    Requires @p CH_USE_SEMAPHORES.\r
- */\r
-#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__)\r
-#define CH_USE_MAILBOXES                TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   I/O Queues APIs.\r
- * @details If enabled then the I/O queues APIs are included in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__)\r
-#define CH_USE_QUEUES                   TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Core Memory Manager APIs.\r
- * @details If enabled then the core memory manager APIs are included\r
- *          in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_MEMCORE) || defined(__DOXYGEN__)\r
-#define CH_USE_MEMCORE                  TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Heap Allocator APIs.\r
- * @details If enabled then the memory heap allocator APIs are included\r
- *          in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- * @note    Requires @p CH_USE_MEMCORE and either @p CH_USE_MUTEXES or\r
- *          @p CH_USE_SEMAPHORES.\r
- * @note    Mutexes are recommended.\r
- */\r
-#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)\r
-#define CH_USE_HEAP                     TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   C-runtime allocator.\r
- * @details If enabled the the heap allocator APIs just wrap the C-runtime\r
- *          @p malloc() and @p free() functions.\r
- *\r
- * @note    The default is @p FALSE.\r
- * @note    Requires @p CH_USE_HEAP.\r
- * @note    The C-runtime may or may not require @p CH_USE_MEMCORE, see the\r
- *          appropriate documentation.\r
- */\r
-#if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)\r
-#define CH_USE_MALLOC_HEAP              FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Memory Pools Allocator APIs.\r
- * @details If enabled then the memory pools allocator APIs are included\r
- *          in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- */\r
-#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)\r
-#define CH_USE_MEMPOOLS                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Dynamic Threads APIs.\r
- * @details If enabled then the dynamic threads creation APIs are included\r
- *          in the kernel.\r
- *\r
- * @note    The default is @p TRUE.\r
- * @note    Requires @p CH_USE_WAITEXIT.\r
- * @note    Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS.\r
- */\r
-#if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__)\r
-#define CH_USE_DYNAMIC                  TRUE\r
-#endif\r
-\r
-/** @} */\r
-\r
-/*===========================================================================*/\r
-/**\r
- * @name Debug options\r
- * @{\r
- */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Debug option, system state check.\r
- * @details If enabled the correct call protocol for system APIs is checked\r
- *          at runtime.\r
- *\r
- * @note    The default is @p FALSE.\r
- */\r
-#if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__)\r
-#define CH_DBG_SYSTEM_STATE_CHECK       FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Debug option, parameters checks.\r
- * @details If enabled then the checks on the API functions input\r
- *          parameters are activated.\r
- *\r
- * @note    The default is @p FALSE.\r
- */\r
-#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)\r
-#define CH_DBG_ENABLE_CHECKS            FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Debug option, consistency checks.\r
- * @details If enabled then all the assertions in the kernel code are\r
- *          activated. This includes consistency checks inside the kernel,\r
- *          runtime anomalies and port-defined checks.\r
- *\r
- * @note    The default is @p FALSE.\r
- */\r
-#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)\r
-#define CH_DBG_ENABLE_ASSERTS           FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Debug option, trace buffer.\r
- * @details If enabled then the context switch circular trace buffer is\r
- *          activated.\r
- *\r
- * @note    The default is @p FALSE.\r
- */\r
-#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)\r
-#define CH_DBG_ENABLE_TRACE             FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Debug option, stack checks.\r
- * @details If enabled then a runtime stack check is performed.\r
- *\r
- * @note    The default is @p FALSE.\r
- * @note    The stack check is performed in a architecture/port dependent way.\r
- *          It may not be implemented or some ports.\r
- * @note    The default failure mode is to halt the system with the global\r
- *          @p panic_msg variable set to @p NULL.\r
- */\r
-#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)\r
-#define CH_DBG_ENABLE_STACK_CHECK       FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Debug option, stacks initialization.\r
- * @details If enabled then the threads working area is filled with a byte\r
- *          value when a thread is created. This can be useful for the\r
- *          runtime measurement of the used stack.\r
- *\r
- * @note    The default is @p FALSE.\r
- */\r
-#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)\r
-#define CH_DBG_FILL_THREADS             FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Debug option, threads profiling.\r
- * @details If enabled then a field is added to the @p Thread structure that\r
- *          counts the system ticks occurred while executing the thread.\r
- *\r
- * @note    The default is @p TRUE.\r
- * @note    This debug option is defaulted to TRUE because it is required by\r
- *          some test cases into the test suite.\r
- */\r
-#if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)\r
-#define CH_DBG_THREADS_PROFILING        TRUE\r
-#endif\r
-\r
-/** @} */\r
-\r
-/*===========================================================================*/\r
-/**\r
- * @name Kernel hooks\r
- * @{\r
- */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Threads descriptor structure extension.\r
- * @details User fields added to the end of the @p Thread structure.\r
- */\r
-#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)\r
-#define THREAD_EXT_FIELDS                                                   \\r
-  /* Add threads custom fields here.*/\r
-#endif\r
-\r
-/**\r
- * @brief   Threads initialization hook.\r
- * @details User initialization code added to the @p chThdInit() API.\r
- *\r
- * @note    It is invoked from within @p chThdInit() and implicitly from all\r
- *          the threads creation APIs.\r
- */\r
-#if !defined(THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__)\r
-#define THREAD_EXT_INIT_HOOK(tp) {                                          \\r
-  /* Add threads initialization code here.*/                                \\r
-}\r
-#endif\r
-\r
-/**\r
- * @brief   Threads finalization hook.\r
- * @details User finalization code added to the @p chThdExit() API.\r
- *\r
- * @note    It is inserted into lock zone.\r
- * @note    It is also invoked when the threads simply return in order to\r
- *          terminate.\r
- */\r
-#if !defined(THREAD_EXT_EXIT_HOOK) || defined(__DOXYGEN__)\r
-#define THREAD_EXT_EXIT_HOOK(tp) {                                          \\r
-  /* Add threads finalization code here.*/                                  \\r
-}\r
-#endif\r
-\r
-/**\r
- * @brief   Context switch hook.\r
- * @details This hook is invoked just before switching between threads.\r
- */\r
-#if !defined(THREAD_CONTEXT_SWITCH_HOOK) || defined(__DOXYGEN__)\r
-#define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) {                              \\r
-  /* System halt code here.*/                                               \\r
-}\r
-#endif\r
-\r
-/**\r
- * @brief   Idle Loop hook.\r
- * @details This hook is continuously invoked by the idle thread loop.\r
- */\r
-#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)\r
-#define IDLE_LOOP_HOOK() {                                                  \\r
-  /* Idle loop code here.*/                                                 \\r
-}\r
-#endif\r
-\r
-/**\r
- * @brief   System tick event hook.\r
- * @details This hook is invoked in the system tick handler immediately\r
- *          after processing the virtual timers queue.\r
- */\r
-#if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__)\r
-#define SYSTEM_TICK_EVENT_HOOK() {                                          \\r
-  /* System tick event code here.*/                                         \\r
-}\r
-#endif\r
-\r
-/**\r
- * @brief   System halt hook.\r
- * @details This hook is invoked in case to a system halting error before\r
- *          the system is halted.\r
- */\r
-#if !defined(SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)\r
-#define SYSTEM_HALT_HOOK() {                                                \\r
-  /* System halt code here.*/                                               \\r
-}\r
-#endif\r
-\r
-/** @} */\r
-\r
-/*===========================================================================*/\r
-/* Port-specific settings (override port settings defaulted in chcore.h).    */\r
-/*===========================================================================*/\r
-\r
-#endif  /* _CHCONF_H_ */\r
-\r
-/** @} */\r
diff --git a/halconf.h b/halconf.h
deleted file mode 100644 (file)
index aaf2f31..0000000
--- a/halconf.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/*\r
-    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio\r
-\r
-    Licensed under the Apache License, Version 2.0 (the "License");\r
-    you may not use this file except in compliance with the License.\r
-    You may obtain a copy of the License at\r
-\r
-        http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-    Unless required by applicable law or agreed to in writing, software\r
-    distributed under the License is distributed on an "AS IS" BASIS,\r
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-    See the License for the specific language governing permissions and\r
-    limitations under the License.\r
-*/\r
-\r
-/**\r
- * @file    templates/halconf.h\r
- * @brief   HAL configuration header.\r
- * @details HAL configuration file, this file allows to enable or disable the\r
- *          various device drivers from your application. You may also use\r
- *          this file in order to override the device drivers default settings.\r
- *\r
- * @addtogroup HAL_CONF\r
- * @{\r
- */\r
-\r
-#ifndef _HALCONF_H_\r
-#define _HALCONF_H_\r
-\r
-#include "mcuconf.h"\r
-\r
-/**\r
- * @brief   Enables the TM subsystem.\r
- */\r
-#if !defined(HAL_USE_TM) || defined(__DOXYGEN__)\r
-#define HAL_USE_TM                  TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the PAL subsystem.\r
- */\r
-#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)\r
-#define HAL_USE_PAL                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the ADC subsystem.\r
- */\r
-#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)\r
-#define HAL_USE_ADC                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the CAN subsystem.\r
- */\r
-#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)\r
-#define HAL_USE_CAN                 FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the EXT subsystem.\r
- */\r
-#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)\r
-#define HAL_USE_EXT                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the GPT subsystem.\r
- */\r
-#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)\r
-#define HAL_USE_GPT                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the I2C subsystem.\r
- */\r
-#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)\r
-#define HAL_USE_I2C                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the ICU subsystem.\r
- */\r
-#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)\r
-#define HAL_USE_ICU                 FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the MAC subsystem.\r
- */\r
-#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)\r
-#define HAL_USE_MAC                 FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the MMC_SPI subsystem.\r
- */\r
-#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)\r
-#define HAL_USE_MMC_SPI             FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the PWM subsystem.\r
- */\r
-#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)\r
-#define HAL_USE_PWM                 FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the RTC subsystem.\r
- */\r
-#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)\r
-#define HAL_USE_RTC                 FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the SDC subsystem.\r
- */\r
-#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)\r
-#define HAL_USE_SDC                 FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the SERIAL subsystem.\r
- */\r
-#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)\r
-#define HAL_USE_SERIAL              TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the SERIAL over USB subsystem.\r
- */\r
-#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)\r
-#define HAL_USE_SERIAL_USB          FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the SPI subsystem.\r
- */\r
-#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)\r
-#define HAL_USE_SPI                 TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the UART subsystem.\r
- */\r
-#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)\r
-#define HAL_USE_UART                FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the USB subsystem.\r
- */\r
-#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)\r
-#define HAL_USE_USB                 FALSE\r
-#endif\r
-\r
-/*===========================================================================*/\r
-/* ADC driver related settings.                                              */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Enables synchronous APIs.\r
- * @note    Disabling this option saves both code and data space.\r
- */\r
-#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)\r
-#define ADC_USE_WAIT                TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.\r
- * @note    Disabling this option saves both code and data space.\r
- */\r
-#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)\r
-#define ADC_USE_MUTUAL_EXCLUSION    TRUE\r
-#endif\r
-\r
-/*===========================================================================*/\r
-/* CAN driver related settings.                                              */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Sleep mode related APIs inclusion switch.\r
- */\r
-#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)\r
-#define CAN_USE_SLEEP_MODE          TRUE\r
-#endif\r
-\r
-/*===========================================================================*/\r
-/* I2C driver related settings.                                              */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Enables the mutual exclusion APIs on the I2C bus.\r
- */\r
-#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)\r
-#define I2C_USE_MUTUAL_EXCLUSION    TRUE\r
-#endif\r
-\r
-/*===========================================================================*/\r
-/* MAC driver related settings.                                              */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Enables an event sources for incoming packets.\r
- */\r
-#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)\r
-#define MAC_USE_ZERO_COPY           FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables an event sources for incoming packets.\r
- */\r
-#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)\r
-#define MAC_USE_EVENTS              TRUE\r
-#endif\r
-\r
-/*===========================================================================*/\r
-/* MMC_SPI driver related settings.                                          */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Block size for MMC transfers.\r
- */\r
-#if !defined(MMC_SECTOR_SIZE) || defined(__DOXYGEN__)\r
-#define MMC_SECTOR_SIZE             512\r
-#endif\r
-\r
-/**\r
- * @brief   Delays insertions.\r
- * @details If enabled this options inserts delays into the MMC waiting\r
- *          routines releasing some extra CPU time for the threads with\r
- *          lower priority, this may slow down the driver a bit however.\r
- *          This option is recommended also if the SPI driver does not\r
- *          use a DMA channel and heavily loads the CPU.\r
- */\r
-#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)\r
-#define MMC_NICE_WAITING            TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Number of positive insertion queries before generating the\r
- *          insertion event.\r
- */\r
-#if !defined(MMC_POLLING_INTERVAL) || defined(__DOXYGEN__)\r
-#define MMC_POLLING_INTERVAL        10\r
-#endif\r
-\r
-/**\r
- * @brief   Interval, in milliseconds, between insertion queries.\r
- */\r
-#if !defined(MMC_POLLING_DELAY) || defined(__DOXYGEN__)\r
-#define MMC_POLLING_DELAY           10\r
-#endif\r
-\r
-/**\r
- * @brief   Uses the SPI polled API for small data transfers.\r
- * @details Polled transfers usually improve performance because it\r
- *          saves two context switches and interrupt servicing. Note\r
- *          that this option has no effect on large transfers which\r
- *          are always performed using DMAs/IRQs.\r
- */\r
-#if !defined(MMC_USE_SPI_POLLING) || defined(__DOXYGEN__)\r
-#define MMC_USE_SPI_POLLING         TRUE\r
-#endif\r
-\r
-/*===========================================================================*/\r
-/* SDC driver related settings.                                              */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Number of initialization attempts before rejecting the card.\r
- * @note    Attempts are performed at 10mS intervals.\r
- */\r
-#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)\r
-#define SDC_INIT_RETRY              100\r
-#endif\r
-\r
-/**\r
- * @brief   Include support for MMC cards.\r
- * @note    MMC support is not yet implemented so this option must be kept\r
- *          at @p FALSE.\r
- */\r
-#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)\r
-#define SDC_MMC_SUPPORT             FALSE\r
-#endif\r
-\r
-/**\r
- * @brief   Delays insertions.\r
- * @details If enabled this options inserts delays into the MMC waiting\r
- *          routines releasing some extra CPU time for the threads with\r
- *          lower priority, this may slow down the driver a bit however.\r
- */\r
-#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)\r
-#define SDC_NICE_WAITING            TRUE\r
-#endif\r
-\r
-/*===========================================================================*/\r
-/* SERIAL driver related settings.                                           */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Default bit rate.\r
- * @details Configuration parameter, this is the baud rate selected for the\r
- *          default configuration.\r
- */\r
-#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)\r
-#define SERIAL_DEFAULT_BITRATE      19200\r
-#endif\r
-\r
-/**\r
- * @brief   Serial buffers size.\r
- * @details Configuration parameter, you can change the depth of the queue\r
- *          buffers depending on the requirements of your application.\r
- * @note    The default is 64 bytes for both the transmission and receive\r
- *          buffers.\r
- */\r
-#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)\r
-#define SERIAL_BUFFERS_SIZE         64\r
-#endif\r
-\r
-/*===========================================================================*/\r
-/* SPI driver related settings.                                              */\r
-/*===========================================================================*/\r
-\r
-/**\r
- * @brief   Enables synchronous APIs.\r
- * @note    Disabling this option saves both code and data space.\r
- */\r
-#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)\r
-#define SPI_USE_WAIT                TRUE\r
-#endif\r
-\r
-/**\r
- * @brief   Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.\r
- * @note    Disabling this option saves both code and data space.\r
- */\r
-#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)\r
-#define SPI_USE_MUTUAL_EXCLUSION    TRUE\r
-#endif\r
-\r
-#endif /* _HALCONF_H_ */\r
-\r
-/** @} */\r
diff --git a/include/control.h b/include/control.h
deleted file mode 100644 (file)
index ee9cca2..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef CONTROL_H_
-#define CONTROL_H_
-
-#include <stdint.h>
-
-#include "ch.h"
-#include "hal.h"
-#include "vex.h"
-
-typedef enum {
-       BUTTON_UP,
-       BUTTON_RELEASE,
-       BUTTON_DOWN
-} button_t;
-
-struct joydata_t {
-       int Ch1 :8;
-       int Ch2 :8;
-       int Ch3 :8;
-       int Ch4 :8;
-
-       struct accel_t {
-               int y :8;
-               int x :8;
-               int z :8;
-       } __attribute__ ((packed)) accel;
-
-       char Btn5D      :1;
-       char Btn5U  :1;
-       char Btn6D  :1;
-       char Btn6U  :1;
-
-       char Reserved :4;
-
-       char Btn8D      :1;
-       char Btn8L  :1;
-       char Btn8U  :1;
-       char Btn8R  :1;
-       char Btn7D      :1;
-       char Btn7L  :1;
-       char Btn7U  :1;
-       char Btn7R  :1;
-
-       char Reserved2[2];
-
-} __attribute__ ((packed));
-
-struct Controller {
-private:
-       int index;
-       struct joydata_t* data;
-
-public:
-       Controller(int idx = 1)
-               : index(idx), data(nullptr) {}
-       ~Controller(void) {}
-
-       void update(void) {
-               data = reinterpret_cast<struct joydata_t*>(vexSpiGetJoystickDataPtr(index));
-               data->Ch1 = vexControllerGet(Ch1);//( data->Ch1 == 0xFF ) ? 127 : data->Ch1 - 127;
-               data->Ch2 = vexControllerGet(Ch2);//-(( data->Ch2 == 0xFF ) ? 127 : data->Ch2 - 127);
-               data->Ch3 = vexControllerGet(Ch3);//-(( data->Ch3 == 0xFF ) ? 127 : data->Ch3 - 127);
-               data->Ch4 = vexControllerGet(Ch4);//( data->Ch4 == 0xFF ) ? 127 : data->Ch4 - 127;
-       }
-       
-       inline const struct joydata_t* operator->(void) const 
-       { return data; }
-
-} __attribute__ ((packed));
-
-#endif // CONTROL_H_
diff --git a/include/distortos/ConditionVariable.hpp b/include/distortos/ConditionVariable.hpp
new file mode 100644 (file)
index 0000000..6b7f869
--- /dev/null
@@ -0,0 +1,304 @@
+/**
+ * \file
+ * \brief ConditionVariable class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_CONDITIONVARIABLE_HPP_
+#define INCLUDE_DISTORTOS_CONDITIONVARIABLE_HPP_
+
+#include "distortos/internal/scheduler/ThreadList.hpp"
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+class Mutex;
+
+/**
+ * \brief ConditionVariable is an advanced synchronization primitive
+ *
+ * Similar to std::condition_variable - http://en.cppreference.com/w/cpp/thread/condition_variable
+ * Similar to POSIX pthread_cond_t
+ *
+ * \ingroup synchronization
+ */
+
+class ConditionVariable
+{
+public:
+
+       /**
+        * \brief ConditionVariable constructor
+        *
+        * Similar to std::condition_variable::condition_variable() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/condition_variable
+        * Similar to pthread_cond_init() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_init.html
+        */
+
+       constexpr ConditionVariable() :
+                       blockedList_{}
+       {
+
+       }
+
+       /**
+        * \brief Notifies all waiting threads.
+        *
+        * Similar to std::condition_variable::notify_all() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all
+        * Similar to pthread_cond_broadcast() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_signal.html
+        *
+        * Unblocks all threads waiting on this condition variable. The notifying thread does not need to hold the same
+        * mutex as the one held by the waiting thread(s).
+        */
+
+       void notifyAll();
+
+       /**
+        * \brief Notifies one waiting thread.
+        *
+        * Similar to std::condition_variable::notify_one() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/notify_one
+        * Similar to pthread_cond_signal() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_signal.html
+        *
+        * Unblocks one thread waiting on this condition variable. The notifying thread does not need to hold the same
+        * mutex as the one held by the waiting thread(s).
+        */
+
+       void notifyOne();
+
+       /**
+        * \brief Waits for notification.
+        *
+        * Similar to std::condition_variable::wait() - http://en.cppreference.com/w/cpp/thread/condition_variable/wait
+        * Similar to pthread_cond_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html
+        *
+        * Atomically releases supplied mutex and blocks current thread until the condition variable is notified. The thread
+        * will be unblocked when notifyAll() or notifyOne() is executed. It may also be unblocked spuriously. When
+        * unblocked, regardless of the reason, lock is reacquired and wait exits.
+        *
+        * \param [in] mutex is a reference to mutex which must be owned by calling thread
+        *
+        * \return zero if the wait was completed successfully, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        */
+
+       int wait(Mutex& mutex);
+
+       /**
+        * \brief Waits for predicate to become true.
+        *
+        * Similar to std::condition_variable::wait() - http://en.cppreference.com/w/cpp/thread/condition_variable/wait
+        * Similar to pthread_cond_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html
+        *
+        * Overload for wait() which also checks the predicate. This function will return only if the predicate is true.
+        *
+        * \tparam Predicate is a type of functor to check the predicate
+        *
+        * \param [in] mutex is a reference to mutex which must be owned by calling thread
+        * \param [in] predicate is the predicate that will be checked
+        *
+        * \return zero if the wait was completed successfully, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        */
+
+       template<typename Predicate>
+       int wait(Mutex& mutex, Predicate predicate);
+
+       /**
+        * \brief Waits for notification for given duration of time.
+        *
+        * Similar to std::condition_variable::wait_for() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
+        * Similar to pthread_cond_timedwait() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+        *
+        * Atomically releases supplied mutex and blocks current thread until the condition variable is notified. The thread
+        * will be unblocked when notifyAll() or notifyOne() is executed or when given duration of time expires. It may also
+        * be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits.
+        *
+        * \param [in] mutex is a reference to mutex which must be owned by calling thread
+        * \param [in] duration is the duration after which the wait for notification will be terminated
+        *
+        * \return zero if the wait was completed successfully, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        * - ETIMEDOUT - no notification was received before the specified timeout expired;
+        */
+
+       int waitFor(Mutex& mutex, TickClock::duration duration);
+
+       /**
+        * \brief Waits for notification for given duration of time.
+        *
+        * Similar to std::condition_variable::wait_for() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
+        * Similar to pthread_cond_timedwait() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+        *
+        * Template variant of waitFor(Mutex& mutex, TickClock::duration duration).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] mutex is a reference to mutex which must be owned by calling thread
+        * \param [in] duration is the duration after which the wait for notification will be terminated
+        *
+        * \return zero if the wait was completed successfully, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        * - ETIMEDOUT - no notification was received before the specified timeout expired;
+        */
+
+       template<typename Rep, typename Period>
+       int waitFor(Mutex& mutex, const std::chrono::duration<Rep, Period> duration)
+       {
+               return waitFor(mutex, std::chrono::duration_cast<TickClock::duration>(duration));
+       }
+
+       /**
+        * \brief Waits for predicate to become true for given duration of time.
+        *
+        * Similar to std::condition_variable::wait_for() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
+        * Similar to pthread_cond_timedwait() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+        *
+        * Overload for waitFor() which also checks the predicate. This function will return only if the predicate is true
+        * or when given duration of time expires.
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        * \tparam Predicate is a type of functor to check the predicate
+        *
+        * \param [in] mutex is a reference to mutex which must be owned by calling thread
+        * \param [in] duration is the duration after which the wait for notification will be terminated
+        * \param [in] predicate is the predicate that will be checked
+        *
+        * \return zero if the wait was completed successfully, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        * - ETIMEDOUT - no notification was received before the specified timeout expired;
+        */
+
+       template<typename Rep, typename Period, typename Predicate>
+       int waitFor(Mutex& mutex, const std::chrono::duration<Rep, Period> duration, Predicate predicate)
+       {
+               return waitUntil(mutex, TickClock::now() + duration + TickClock::duration{1}, std::move(predicate));
+       }
+
+       /**
+        * \brief Waits for notification until given time point.
+        *
+        * Similar to std::condition_variable::wait_until() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
+        * Similar to pthread_cond_timedwait() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+        *
+        * Atomically releases supplied mutex and blocks current thread until the condition variable is notified. The thread
+        * will be unblocked when notifyAll() or notifyOne() is executed or when given time point is reached. It may also be
+        * unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits.
+        *
+        * \param [in] mutex is a reference to mutex which must be owned by calling thread
+        * \param [in] timePoint is the time point at which the wait for notification will be terminated
+        *
+        * \return zero if the wait was completed successfully, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        * - ETIMEDOUT - no notification was received before the specified timeout expired;
+        */
+
+       int waitUntil(Mutex& mutex, TickClock::time_point timePoint);
+
+       /**
+        * \brief Waits for notification until given time point.
+        *
+        * Similar to std::condition_variable::wait_until() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
+        * Similar to pthread_cond_timedwait() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+        *
+        * Template variant of waitUntil(Mutex& mutex, TickClock::time_point timePoint).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] mutex is a reference to mutex which must be owned by calling thread
+        * \param [in] timePoint is the time point at which the wait for notification will be terminated
+        *
+        * \return zero if the wait was completed successfully, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        * - ETIMEDOUT - no notification was received before the specified timeout expired;
+        */
+
+       template<typename Duration>
+       int waitUntil(Mutex& mutex, const std::chrono::time_point<TickClock, Duration> timePoint)
+       {
+               return waitUntil(mutex, std::chrono::time_point_cast<TickClock::duration>(timePoint));
+       }
+
+       /**
+        * \brief Waits for predicate to become true until given time point.
+        *
+        * Similar to std::condition_variable::wait_until() -
+        * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
+        * Similar to pthread_cond_timedwait() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+        *
+        * Overload for waitUntil() which also checks the predicate. This function will return only if the predicate is true
+        * or when given time point is reached.
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        * \tparam Predicate is a type of functor to check the predicate
+        *
+        * \param [in] mutex is a reference to mutex which must be owned by calling thread
+        * \param [in] timePoint is the time point at which the wait for notification will be terminated
+        * \param [in] predicate is the predicate that will be checked
+        *
+        * \return zero if the wait was completed successfully, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        * - ETIMEDOUT - no notification was received before the specified timeout expired;
+        */
+
+       template<typename Duration, typename Predicate>
+       int waitUntil(Mutex& mutex, std::chrono::time_point<TickClock, Duration> timePoint, Predicate predicate);
+
+private:
+
+       /// ThreadControlBlock objects blocked on this condition variable
+       internal::ThreadList blockedList_;
+};
+
+template<typename Predicate>
+int ConditionVariable::wait(Mutex& mutex, Predicate predicate)
+{
+       while (predicate() == false)
+       {
+               const auto ret = wait(mutex);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+template<typename Duration, typename Predicate>
+int ConditionVariable::waitUntil(Mutex& mutex, const std::chrono::time_point<TickClock, Duration> timePoint, Predicate predicate)
+{
+       while (predicate() == false)
+       {
+               const auto ret = waitUntil(mutex, timePoint);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_CONDITIONVARIABLE_HPP_
diff --git a/include/distortos/DynamicFifoQueue.hpp b/include/distortos/DynamicFifoQueue.hpp
new file mode 100644 (file)
index 0000000..fba876f
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * \file
+ * \brief DynamicFifoQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DYNAMICFIFOQUEUE_HPP_
+#define INCLUDE_DISTORTOS_DYNAMICFIFOQUEUE_HPP_
+
+#include "FifoQueue.hpp"
+
+#include "distortos/internal/memory/storageDeleter.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief DynamicFifoQueue class is a variant of FifoQueue that has dynamic storage for queue's contents.
+ *
+ * \tparam T is the type of data in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T>
+class DynamicFifoQueue : public FifoQueue<T>
+{
+public:
+
+       /// import Storage type from base class
+       using typename FifoQueue<T>::Storage;
+
+       /**
+        * \brief DynamicFifoQueue's constructor
+        *
+        * \param [in] queueSize is the maximum number of elements in queue
+        */
+
+       explicit DynamicFifoQueue(size_t queueSize);
+};
+
+template<typename T>
+DynamicFifoQueue<T>::DynamicFifoQueue(const size_t queueSize) :
+               FifoQueue<T>{{new Storage[queueSize], internal::storageDeleter<Storage>}, queueSize}
+{
+
+}
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_DYNAMICFIFOQUEUE_HPP_
diff --git a/include/distortos/DynamicMessageQueue.hpp b/include/distortos/DynamicMessageQueue.hpp
new file mode 100644 (file)
index 0000000..b298351
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * \file
+ * \brief DynamicMessageQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DYNAMICMESSAGEQUEUE_HPP_
+#define INCLUDE_DISTORTOS_DYNAMICMESSAGEQUEUE_HPP_
+
+#include "MessageQueue.hpp"
+
+#include "distortos/internal/memory/storageDeleter.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief DynamicMessageQueue class is a variant of MessageQueue that has dynamic storage for queue's contents.
+ *
+ * \tparam T is the type of data in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T>
+class DynamicMessageQueue : public MessageQueue<T>
+{
+public:
+
+       /// import EntryStorage type from base class
+       using typename MessageQueue<T>::EntryStorage;
+
+       /// import ValueStorage type from base class
+       using typename MessageQueue<T>::ValueStorage;
+
+       /**
+        * \brief DynamicMessageQueue's constructor
+        *
+        * \param [in] queueSize is the maximum number of elements in queue
+        */
+
+       explicit DynamicMessageQueue(size_t queueSize);
+};
+
+template<typename T>
+DynamicMessageQueue<T>::DynamicMessageQueue(const size_t queueSize) :
+               MessageQueue<T>{{new EntryStorage[queueSize], internal::storageDeleter<EntryStorage>},
+                               {new ValueStorage[queueSize], internal::storageDeleter<ValueStorage>}, queueSize}
+{
+
+}
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_DYNAMICMESSAGEQUEUE_HPP_
diff --git a/include/distortos/DynamicRawFifoQueue.hpp b/include/distortos/DynamicRawFifoQueue.hpp
new file mode 100644 (file)
index 0000000..afd2f0b
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * \file
+ * \brief DynamicRawFifoQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DYNAMICRAWFIFOQUEUE_HPP_
+#define INCLUDE_DISTORTOS_DYNAMICRAWFIFOQUEUE_HPP_
+
+#include "RawFifoQueue.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief DynamicRawFifoQueue class is a variant of RawFifoQueue that has dynamic storage for queue's contents.
+ *
+ * \ingroup queues
+ */
+
+class DynamicRawFifoQueue : public RawFifoQueue
+{
+public:
+
+       /**
+        * \brief DynamicRawFifoQueue's constructor
+        *
+        * \param [in] elementSize is the size of single queue element, bytes
+        * \param [in] queueSize is the maximum number of elements in queue
+        */
+
+       DynamicRawFifoQueue(size_t elementSize, size_t queueSize);
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_DYNAMICRAWFIFOQUEUE_HPP_
diff --git a/include/distortos/DynamicRawMessageQueue.hpp b/include/distortos/DynamicRawMessageQueue.hpp
new file mode 100644 (file)
index 0000000..ab68807
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * \file
+ * \brief DynamicRawMessageQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DYNAMICRAWMESSAGEQUEUE_HPP_
+#define INCLUDE_DISTORTOS_DYNAMICRAWMESSAGEQUEUE_HPP_
+
+#include "distortos/RawMessageQueue.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief DynamicRawMessageQueue class is a variant of RawMessageQueue that has dynamic storage for queue's contents.
+ *
+ * \ingroup queues
+ */
+
+class DynamicRawMessageQueue : public RawMessageQueue
+{
+public:
+
+       /**
+        * \brief DynamicRawMessageQueue's constructor
+        *
+        * \param [in] elementSize is the size of single queue element, bytes
+        * \param [in] queueSize is the maximum number of elements in queue
+        */
+
+       DynamicRawMessageQueue(size_t elementSize, size_t queueSize);
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_DYNAMICRAWMESSAGEQUEUE_HPP_
diff --git a/include/distortos/DynamicSignalsReceiver.hpp b/include/distortos/DynamicSignalsReceiver.hpp
new file mode 100644 (file)
index 0000000..386a612
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * \file
+ * \brief DynamicSignalsReceiver class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DYNAMICSIGNALSRECEIVER_HPP_
+#define INCLUDE_DISTORTOS_DYNAMICSIGNALSRECEIVER_HPP_
+
+#include "distortos/SignalInformationQueueWrapper.hpp"
+#include "distortos/SignalsCatcher.hpp"
+#include "distortos/SignalsReceiver.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief DynamicSignalsReceiver class is a templated interface for SignalsReceiver that has dynamic storage for queued
+ * signals and SignalAction associations required for catching signals.
+ */
+
+class DynamicSignalsReceiver : public SignalsReceiver
+{
+public:
+
+       /**
+        * \brief DynamicSignalsReceiver's constructor
+        *
+        * \param [in] queuedSignals is the max number of queued signals, 0 to disable queuing of signals for this receiver
+        * \param [in] signalActions is the max number of different SignalAction objects, 0 to disable catching of signals
+        * for this receiver
+        */
+
+       DynamicSignalsReceiver(size_t queuedSignals, size_t signalActions);
+
+private:
+
+       /// internal SignalInformationQueueWrapper object
+       SignalInformationQueueWrapper signalInformationQueueWrapper_;
+
+       /// internal SignalsCatcher object
+       SignalsCatcher signalsCatcher_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_DYNAMICSIGNALSRECEIVER_HPP_
diff --git a/include/distortos/DynamicThread.hpp b/include/distortos/DynamicThread.hpp
new file mode 100644 (file)
index 0000000..4d7550a
--- /dev/null
@@ -0,0 +1,373 @@
+/**
+ * \file
+ * \brief DynamicThread class header
+ *
+ * \author Copyright (C) 2015-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DYNAMICTHREAD_HPP_
+#define INCLUDE_DISTORTOS_DYNAMICTHREAD_HPP_
+
+#include "distortos/internal/scheduler/DynamicThreadBase.hpp"
+
+namespace distortos
+{
+
+/// \addtogroup threads
+/// \{
+
+/**
+ * \brief DynamicThread class is a type-erased interface for thread that has dynamic storage for bounded function, stack
+ * and internal DynamicSignalsReceiver object.
+ */
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+class DynamicThread : public Thread
+{
+public:
+
+       /**
+        * \brief DynamicThread's constructor
+        *
+        * \tparam Function is the function that will be executed in separate thread
+        * \tparam Args are the arguments for \a Function
+        *
+        * \param [in] stackSize is the size of stack, bytes
+        * \param [in] canReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this
+        * thread
+        * \param [in] queuedSignals is the max number of queued signals for this thread, relevant only if
+        * \a canReceiveSignals == true, 0 to disable queuing of signals for this thread
+        * \param [in] signalActions is the max number of different SignalAction objects for this thread, relevant only if
+        * \a canReceiveSignals == true, 0 to disable catching of signals for this thread
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicy is the scheduling policy of the thread
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for \a function
+        */
+
+       template<typename Function, typename... Args>
+       DynamicThread(size_t stackSize, bool canReceiveSignals, size_t queuedSignals, size_t signalActions,
+                       uint8_t priority, SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args);
+
+       /**
+        * \brief DynamicThread's constructor
+        *
+        * \tparam Function is the function that will be executed in separate thread
+        * \tparam Args are the arguments for \a Function
+        *
+        * \param [in] parameters is a DynamicThreadParameters struct with thread parameters
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for \a function
+        */
+
+       template<typename Function, typename... Args>
+       DynamicThread(const DynamicThreadParameters parameters, Function&& function, Args&&... args) :
+                       DynamicThread{parameters.stackSize, parameters.canReceiveSignals, parameters.queuedSignals,
+                                       parameters.signalActions, parameters.priority, parameters.schedulingPolicy,
+                                       std::forward<Function>(function), std::forward<Args>(args)...}
+       {
+
+       }
+
+       /**
+        * \brief DynamicThread's destructor
+        */
+
+       ~DynamicThread() override;
+
+       /**
+        * \brief Detaches the thread.
+        *
+        * Similar to std::thread::detach() - http://en.cppreference.com/w/cpp/thread/thread/detach
+        * Similar to POSIX pthread_detach() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_detach.html
+        *
+        * Detaches the executing thread from the Thread object, allowing execution to continue independently. All resources
+        * allocated for the thread will be deallocated when the thread terminates.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - this thread is already detached;
+        */
+
+       int detach() override;
+
+       /**
+        * \brief Generates signal for thread.
+        *
+        * Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
+        *
+        * Adds the signalNumber to set of pending signals. If this thread is currently waiting for this signal, it will be
+        * unblocked.
+        *
+        * \param [in] signalNumber is the signal that will be generated, [0; 31]
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - reception of signals is disabled for this thread;
+        * - EINVAL - internal thread object was detached;
+        *
+        * \ingroup signals
+        */
+
+       int generateSignal(uint8_t signalNumber) override;
+
+       /**
+        * \return effective priority of thread
+        */
+
+       uint8_t getEffectivePriority() const override;
+
+       /**
+        * \brief Gets set of currently pending signals.
+        *
+        * Similar to sigpending() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html
+        *
+        * This function shall return the set of signals that are blocked from delivery and are pending on the thread.
+        *
+        * \return set of currently pending signals
+        *
+        * \ingroup signals
+        */
+
+       SignalSet getPendingSignalSet() const override;
+
+       /**
+        * \return priority of thread
+        */
+
+       uint8_t getPriority() const override;
+
+       /**
+        * \return scheduling policy of the thread
+        */
+
+       SchedulingPolicy getSchedulingPolicy() const override;
+
+       /**
+        * \return current state of thread
+        */
+
+       ThreadState getState() const override;
+
+       /**
+        * \brief Waits for thread termination.
+        *
+        * Similar to std::thread::join() - http://en.cppreference.com/w/cpp/thread/thread/join
+        * Similar to POSIX pthread_join() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html
+        *
+        * Blocks current thread until this thread finishes its execution. The results of multiple simultaneous calls to
+        * join() on the same target thread are undefined.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EDEADLK - deadlock condition was detected,
+        * - EINVAL - this thread is not joinable,
+        * - EINVAL - internal thread object was detached;
+        * - ...
+        *
+        * \ingroup synchronization
+        */
+
+       int join() override;
+
+       /**
+        * \brief Queues signal for thread.
+        *
+        * Similar to sigqueue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigqueue.html
+        *
+        * Adds the signalNumber and signal value (sigval union) to queue of SignalInformation objects. If this thread is
+        * currently waiting for this signal, it will be unblocked.
+        *
+        * \param [in] signalNumber is the signal that will be queued, [0; 31]
+        * \param [in] value is the signal value
+        *
+        * \return 0 on success, error code otherwise:
+        * - EAGAIN - no resources are available to queue the signal, maximal number of signals is already queued in
+        * associated queue of SignalInformation objects;
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - reception or queuing of signals are disabled for this thread;
+        * - EINVAL - internal thread object was detached;
+        *
+        * \ingroup signals
+        */
+
+       int queueSignal(uint8_t signalNumber, sigval value) override;
+
+       /**
+        * \brief Changes priority of thread.
+        *
+        * If the priority really changes, the position in the thread list is adjusted and context switch may be requested.
+        *
+        * \param [in] priority is the new priority of thread
+        * \param [in] alwaysBehind selects the method of ordering when lowering the priority
+        * - false - the thread is moved to the head of the group of threads with the new priority (default),
+        * - true - the thread is moved to the tail of the group of threads with the new priority.
+        */
+
+       void setPriority(uint8_t priority, bool alwaysBehind = {}) override;
+
+       /**
+        * param [in] schedulingPolicy is the new scheduling policy of the thread
+        */
+
+       void setSchedulingPolicy(SchedulingPolicy schedulingPolicy) override;
+
+       /**
+        * \brief Starts the thread.
+        *
+        * This operation can be performed on threads in "New" state only.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - thread is already started;
+        * - EINVAL - internal thread object was detached;
+        * - error codes returned by scheduler::Scheduler::add();
+        */
+
+       int start() override;
+
+       DynamicThread(const DynamicThread&) = delete;
+       DynamicThread(DynamicThread&&) = default;
+       const DynamicThread& operator=(const DynamicThread&) = delete;
+       DynamicThread& operator=(DynamicThread&&) = delete;
+
+private:
+
+       /// internal thread object
+       std::unique_ptr<internal::DynamicThreadBase> detachableThread_;
+};
+
+#else  // !def CONFIG_THREAD_DETACH_ENABLE
+
+class DynamicThread : public internal::DynamicThreadBase
+{
+public:
+
+       using internal::DynamicThreadBase::DynamicThreadBase;
+};
+
+#endif // !def CONFIG_THREAD_DETACH_ENABLE
+
+/**
+ * \brief Helper factory function to make DynamicThread object
+ *
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] stackSize is the size of stack, bytes
+ * \param [in] canReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this
+ * thread
+ * \param [in] queuedSignals is the max number of queued signals for this thread, relevant only if
+ * \a canReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \param [in] signalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * \a canReceiveSignals == true, 0 to disable catching of signals for this thread
+ * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+ * \param [in] schedulingPolicy is the scheduling policy of the thread
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for \a function
+ *
+ * \return DynamicThread object
+ */
+
+template<typename Function, typename... Args>
+DynamicThread makeDynamicThread(const size_t stackSize, const bool canReceiveSignals, const size_t queuedSignals,
+               const size_t signalActions, const uint8_t priority, const SchedulingPolicy schedulingPolicy,
+               Function&& function, Args&&... args)
+{
+       return {stackSize, canReceiveSignals, queuedSignals, signalActions, priority, schedulingPolicy,
+                       std::forward<Function>(function), std::forward<Args>(args)...};
+}
+
+/**
+ * \brief Helper factory function to make DynamicThread object
+ *
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] parameters is a DynamicThreadParameters struct with thread parameters
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for \a function
+ *
+ * \return DynamicThread object
+ */
+
+template<typename Function, typename... Args>
+DynamicThread makeDynamicThread(const DynamicThreadParameters parameters, Function&& function, Args&&... args)
+{
+       return {parameters, std::forward<Function>(function), std::forward<Args>(args)...};
+}
+
+/**
+ * \brief Helper factory function to make and start DynamicThread object
+ *
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] stackSize is the size of stack, bytes
+ * \param [in] canReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this
+ * thread
+ * \param [in] queuedSignals is the max number of queued signals for this thread, relevant only if
+ * \a canReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \param [in] signalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * \a canReceiveSignals == true, 0 to disable catching of signals for this thread
+ * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+ * \param [in] schedulingPolicy is the scheduling policy of the thread
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for \a function
+ *
+ * \return DynamicThread object
+ */
+
+template<typename Function, typename... Args>
+DynamicThread makeAndStartDynamicThread(const size_t stackSize, const bool canReceiveSignals,
+               const size_t queuedSignals, const size_t signalActions, const uint8_t priority,
+               const SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args)
+{
+       auto thread = makeDynamicThread(stackSize, canReceiveSignals, queuedSignals, signalActions, priority,
+                       schedulingPolicy, std::forward<Function>(function), std::forward<Args>(args)...);
+       thread.start(); /// \todo make sure this never fails
+       return thread;
+}
+
+/**
+ * \brief Helper factory function to make and start DynamicThread object
+ *
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] parameters is a DynamicThreadParameters struct with thread parameters
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for \a function
+ *
+ * \return DynamicThread object
+ */
+
+template<typename Function, typename... Args>
+DynamicThread makeAndStartDynamicThread(const DynamicThreadParameters parameters, Function&& function, Args&&... args)
+{
+       auto thread = makeDynamicThread(parameters, std::forward<Function>(function), std::forward<Args>(args)...);
+       thread.start(); /// \todo make sure this never fails
+       return thread;
+}
+
+/// \}
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+template<typename Function, typename... Args>
+DynamicThread::DynamicThread(const size_t stackSize, const bool canReceiveSignals, const size_t queuedSignals,
+               const size_t signalActions, const uint8_t priority, const SchedulingPolicy schedulingPolicy,
+               Function&& function, Args&&... args) :
+               detachableThread_{new internal::DynamicThreadBase{stackSize, canReceiveSignals, queuedSignals, signalActions,
+                               priority, schedulingPolicy, *this, std::forward<Function>(function), std::forward<Args>(args)...}}
+{
+
+}
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_DYNAMICTHREAD_HPP_
diff --git a/include/distortos/DynamicThreadParameters.hpp b/include/distortos/DynamicThreadParameters.hpp
new file mode 100644 (file)
index 0000000..b27056c
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * \file
+ * \brief DynamicThreadParameters class header
+ *
+ * \author Copyright (C) 2015-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DYNAMICTHREADPARAMETERS_HPP_
+#define INCLUDE_DISTORTOS_DYNAMICTHREADPARAMETERS_HPP_
+
+#include "distortos/SchedulingPolicy.hpp"
+
+#include <cstddef>
+
+namespace distortos
+{
+
+/**
+ * \brief DynamicThreadParameters struct is a helper with parameters for DynamicThread's constructor
+ *
+ * This struct is a replacement for overloads of DynamicThread's constructor, makeDynamicThread() and
+ * makeAndStartDynamicThread() which - unfortunately - cannot be used, as they would lead to compilation errors due to
+ * ambiguity.
+ *
+ * \ingroup threads
+ */
+
+struct DynamicThreadParameters
+{
+       /**
+        * \brief DynamicThreadParameters's constructor
+        *
+        * \param [in] stackSizee is the size of stack, bytes
+        * \param [in] canReceiveSignalss selects whether reception of signals is enabled (true) or disabled (false) for
+        * this thread
+        * \param [in] queuedSignalss is the max number of queued signals for this thread, relevant only if
+        * \a canReceiveSignals == true, 0 to disable queuing of signals for this thread
+        * \param [in] signalActionss is the max number of different SignalAction objects for this thread, relevant only if
+        * \a canReceiveSignals == true, 0 to disable catching of signals for this thread
+        * \param [in] priorityy is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicyy is the scheduling policy of the thread, default - SchedulingPolicy::roundRobin
+        */
+
+       constexpr DynamicThreadParameters(const size_t stackSizee, const bool canReceiveSignalss,
+                       const size_t queuedSignalss, const size_t signalActionss, const uint8_t priorityy,
+                       const SchedulingPolicy schedulingPolicyy = SchedulingPolicy::roundRobin) :
+                                       queuedSignals{queuedSignalss},
+                                       signalActions{signalActionss},
+                                       stackSize{stackSizee},
+                                       canReceiveSignals{canReceiveSignalss},
+                                       priority{priorityy},
+                                       schedulingPolicy{schedulingPolicyy}
+       {
+
+       }
+
+       /**
+        * \brief DynamicThreadParameters's constructor
+        *
+        * \param [in] stackSizee is the size of stack, bytes
+        * \param [in] priorityy is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicyy is the scheduling policy of the thread, default - SchedulingPolicy::roundRobin
+        */
+
+       constexpr DynamicThreadParameters(const size_t stackSizee, const uint8_t priorityy,
+                       const SchedulingPolicy schedulingPolicyy = SchedulingPolicy::roundRobin) :
+                                       DynamicThreadParameters{stackSizee, false, 0, 0, priorityy, schedulingPolicyy}
+       {
+
+       }
+
+       /// max number of queued signals for this thread, relevant only if \a canReceiveSignals == true, 0 to disable
+       /// queuing of signals for this thread
+       size_t queuedSignals;
+
+       /// max number of different SignalAction objects for this thread, relevant only if \a canReceiveSignals == true, 0
+       /// to disable catching of signals for this thread
+       size_t signalActions;
+
+       /// size of stack, bytes
+       size_t stackSize;
+
+       /// selects whether reception of signals is enabled (true) or disabled (false) for this thread
+       bool canReceiveSignals;
+
+       /// thread's priority, 0 - lowest, UINT8_MAX - highest
+       uint8_t priority;
+
+       /// scheduling policy of the thread
+       SchedulingPolicy schedulingPolicy;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_DYNAMICTHREADPARAMETERS_HPP_
diff --git a/include/distortos/FifoQueue.hpp b/include/distortos/FifoQueue.hpp
new file mode 100644 (file)
index 0000000..9f6c952
--- /dev/null
@@ -0,0 +1,682 @@
+/**
+ * \file
+ * \brief FifoQueue class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
+#define INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
+
+#include "distortos/internal/synchronization/FifoQueueBase.hpp"
+#include "distortos/internal/synchronization/BoundQueueFunctor.hpp"
+#include "distortos/internal/synchronization/CopyConstructQueueFunctor.hpp"
+#include "distortos/internal/synchronization/MoveConstructQueueFunctor.hpp"
+#include "distortos/internal/synchronization/SwapPopQueueFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreWaitFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitForFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitUntilFunctor.hpp"
+
+/// GCC 4.9 is needed for all FifoQueue::*emplace*() functions - earlier versions don't support parameter pack expansion
+/// in lambdas
+#define DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED  __GNUC_PREREQ(4, 9)
+
+namespace distortos
+{
+
+/**
+ * \brief FifoQueue class is a simple FIFO queue for thread-thread, thread-interrupt or interrupt-interrupt
+ * communication. It supports multiple readers and multiple writers. It is implemented as a wrapper for
+ * internal::FifoQueueBase.
+ *
+ * \tparam T is the type of data in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T>
+class FifoQueue
+{
+public:
+
+       /// type of uninitialized storage for data
+       using Storage = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
+
+       /// unique_ptr (with deleter) to Storage[]
+       using StorageUniquePointer =
+                       std::unique_ptr<Storage[], internal::FifoQueueBase::StorageUniquePointer::deleter_type>;
+
+       /**
+        * \brief FifoQueue's constructor
+        *
+        * \param [in] storageUniquePointer is a rvalue reference to StorageUniquePointer with storage for queue elements
+        * (sufficiently large for \a maxElements, each sizeof(T) bytes long) and appropriate deleter
+        * \param [in] maxElements is the number of elements in storage array
+        */
+
+       FifoQueue(StorageUniquePointer&& storageUniquePointer, const size_t maxElements) :
+                       fifoQueueBase_{{storageUniquePointer.release(), storageUniquePointer.get_deleter()}, sizeof(T), maxElements}
+       {
+
+       }
+
+       /**
+        * \brief FifoQueue's destructor
+        *
+        * Pops all remaining elements from the queue.
+        */
+
+       ~FifoQueue();
+
+#if DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Emplaces the element in the queue.
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int emplace(Args&&... args)
+       {
+               const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+               return emplaceInternal(semaphoreWaitFunctor, std::forward<Args>(args)...);
+       }
+
+#endif // DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Pops the oldest (first) element from the queue.
+        *
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pop(T& value)
+       {
+               const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+               return popInternal(semaphoreWaitFunctor, value);
+       }
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int push(const T& value)
+       {
+               const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+               return pushInternal(semaphoreWaitFunctor, value);
+       }
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int push(T&& value)
+       {
+               const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+               return pushInternal(semaphoreWaitFunctor, std::move(value));
+       }
+
+#if DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Tries to emplace the element in the queue.
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int tryEmplace(Args&&... args)
+       {
+               const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+               return emplaceInternal(semaphoreTryWaitFunctor, std::forward<Args>(args)...);
+       }
+
+       /**
+        * \brief Tries to emplace the element in the queue for a given duration of time.
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without emplacing the element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int tryEmplaceFor(const TickClock::duration duration, Args&&... args)
+       {
+               const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+               return emplaceInternal(semaphoreTryWaitForFunctor, std::forward<Args>(args)...);
+       }
+
+       /**
+        * \brief Tries to emplace the element in the queue for a given duration of time.
+        *
+        * Template variant of FifoQueue::tryEmplaceFor(TickClock::duration, Args&&...).
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without emplacing the element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period, typename... Args>
+       int tryEmplaceFor(const std::chrono::duration<Rep, Period> duration, Args&&... args)
+       {
+               return tryEmplaceFor(std::chrono::duration_cast<TickClock::duration>(duration), std::forward<Args>(args)...);
+       }
+
+       /**
+        * \brief Tries to emplace the element in the queue until a given time point.
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without emplacing the element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int tryEmplaceUntil(const TickClock::time_point timePoint, Args&&... args)
+       {
+               const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+               return emplaceInternal(semaphoreTryWaitUntilFunctor, std::forward<Args>(args)...);
+       }
+
+       /**
+        * \brief Tries to emplace the element in the queue until a given time point.
+        *
+        * Template variant of FifoQueue::tryEmplaceUntil(TickClock::time_point, Args&&...).
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without emplacing the element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration, typename... Args>
+       int tryEmplaceUntil(const std::chrono::time_point<TickClock, Duration> timePoint, Args&&... args)
+       {
+               return tryEmplaceUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint),
+                               std::forward<Args>(args)...);
+       }
+
+#endif // DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue.
+        *
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPop(T& value)
+       {
+               internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+               return popInternal(semaphoreTryWaitFunctor, value);
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue for a given duration of time.
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPopFor(const TickClock::duration duration, T& value)
+       {
+               const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+               return popInternal(semaphoreTryWaitForFunctor, value);
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue for a given duration of time.
+        *
+        * Template variant of tryPopFor(TickClock::duration, T&).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPopFor(const std::chrono::duration<Rep, Period> duration, T& value)
+       {
+               return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), value);
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue until a given time point.
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPopUntil(const TickClock::time_point timePoint, T& value)
+       {
+               const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+               return popInternal(semaphoreTryWaitUntilFunctor, value);
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue until a given time point.
+        *
+        * Template variant of tryPopUntil(TickClock::time_point, T&).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, T& value)
+       {
+               return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue.
+        *
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPush(const T& value)
+       {
+               const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+               return pushInternal(semaphoreTryWaitFunctor, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue.
+        *
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPush(T&& value)
+       {
+               const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+               return pushInternal(semaphoreTryWaitFunctor, std::move(value));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushFor(const TickClock::duration duration, const T& value)
+       {
+               const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+               return pushInternal(semaphoreTryWaitForFunctor, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Template variant of tryPushFor(TickClock::duration, const T&).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPushFor(const std::chrono::duration<Rep, Period> duration, const T& value)
+       {
+               return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * \param [in] duration is the duration after which the call will be terminated without pushing the element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushFor(const TickClock::duration duration, T&& value)
+       {
+               const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+               return pushInternal(semaphoreTryWaitForFunctor, std::move(value));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Template variant of tryPushFor(TickClock::duration, T&&).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the call will be terminated without pushing the element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPushFor(const std::chrono::duration<Rep, Period> duration, T&& value)
+       {
+               return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), std::move(value));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushUntil(const TickClock::time_point timePoint, const T& value)
+       {
+               const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+               return pushInternal(semaphoreTryWaitUntilFunctor, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Template variant of tryPushUntil(TickClock::time_point, const T&).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const T& value)
+       {
+               return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushUntil(const TickClock::time_point timePoint, T&& value)
+       {
+               const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+               return pushInternal(semaphoreTryWaitUntilFunctor, std::move(value));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Template variant of tryPushUntil(TickClock::time_point, T&&).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, T&& value)
+       {
+               return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), std::move(value));
+       }
+
+private:
+
+#if DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Emplaces the element in the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, Args&&... args);
+
+#endif // DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Pops the oldest (first) element from the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a popSemaphore_
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, T& value);
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const T& value);
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, T&& value);
+
+       /// contained internal::FifoQueueBase object which implements whole functionality
+       internal::FifoQueueBase fifoQueueBase_;
+};
+
+template<typename T>
+FifoQueue<T>::~FifoQueue()
+{
+       T value;
+       while (tryPop(value) == 0);
+}
+
+#if DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+template<typename T>
+template<typename... Args>
+int FifoQueue<T>::emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, Args&&... args)
+{
+       const auto emplaceFunctor = internal::makeBoundQueueFunctor(
+                       [&args...](void* const storage)
+                       {
+                               new (storage) T{std::forward<Args>(args)...};
+                       });
+       return fifoQueueBase_.push(waitSemaphoreFunctor, emplaceFunctor);
+}
+
+#endif // DISTORTOS_FIFOQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+template<typename T>
+int FifoQueue<T>::popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, T& value)
+{
+       const internal::SwapPopQueueFunctor<T> swapPopQueueFunctor {value};
+       return fifoQueueBase_.pop(waitSemaphoreFunctor, swapPopQueueFunctor);
+}
+
+template<typename T>
+int FifoQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const T& value)
+{
+       const internal::CopyConstructQueueFunctor<T> copyConstructQueueFunctor {value};
+       return fifoQueueBase_.push(waitSemaphoreFunctor, copyConstructQueueFunctor);
+}
+
+template<typename T>
+int FifoQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, T&& value)
+{
+       const internal::MoveConstructQueueFunctor<T> moveConstructQueueFunctor {std::move(value)};
+       return fifoQueueBase_.push(waitSemaphoreFunctor, moveConstructQueueFunctor);
+}
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
diff --git a/include/distortos/MessageQueue.hpp b/include/distortos/MessageQueue.hpp
new file mode 100644 (file)
index 0000000..0f44d8f
--- /dev/null
@@ -0,0 +1,762 @@
+/**
+ * \file
+ * \brief MessageQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_MESSAGEQUEUE_HPP_
+#define INCLUDE_DISTORTOS_MESSAGEQUEUE_HPP_
+
+#include "distortos/internal/synchronization/MessageQueueBase.hpp"
+#include "distortos/internal/synchronization/BoundQueueFunctor.hpp"
+#include "distortos/internal/synchronization/CopyConstructQueueFunctor.hpp"
+#include "distortos/internal/synchronization/MoveConstructQueueFunctor.hpp"
+#include "distortos/internal/synchronization/SwapPopQueueFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreWaitFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitForFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitUntilFunctor.hpp"
+
+namespace distortos
+{
+
+/// GCC 4.9 is needed for all MessageQueue::*emplace*() functions - earlier versions don't support parameter pack
+/// expansion in lambdas
+#define DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED       __GNUC_PREREQ(4, 9)
+
+/**
+ * \brief MessageQueue class is a message queue for thread-thread, thread-interrupt or interrupt-interrupt
+ * communication. It supports multiple readers and multiple writers. It is implemented as a wrapper for
+ * internal::MessageQueueBase.
+ *
+ * Similar to POSIX mqd_t - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/mqueue.h.html
+ *
+ * \tparam T is the type of data in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T>
+class MessageQueue
+{
+public:
+
+       /// type of uninitialized storage for Entry with link
+       using EntryStorage = internal::MessageQueueBase::EntryStorage;
+
+       /// type of uninitialized storage for value
+       using ValueStorage = internal::MessageQueueBase::ValueStorage<T>;
+
+       /// import EntryStorageUniquePointer type from internal::MessageQueueBase class
+       using EntryStorageUniquePointer = internal::MessageQueueBase::EntryStorageUniquePointer;
+
+       /// unique_ptr (with deleter) to ValueStorage[]
+       using ValueStorageUniquePointer =
+                       std::unique_ptr<ValueStorage[], internal::MessageQueueBase::ValueStorageUniquePointer::deleter_type>;
+
+       /**
+        * \brief MessageQueue's constructor
+        *
+        * \param [in] entryStorageUniquePointer is a rvalue reference to EntryStorageUniquePointer with storage for queue
+        * entries (sufficiently large for \a maxElements EntryStorage objects) and appropriate deleter
+        * \param [in] valueStorageUniquePointer is a rvalue reference to ValueStorageUniquePointer with storage for queue
+        * elements (sufficiently large for \a maxElements, each sizeof(T) bytes long) and appropriate deleter
+        * \param [in] maxElements is the number of elements in \a entryStorage and \a valueStorage arrays
+        */
+
+       MessageQueue(EntryStorageUniquePointer&& entryStorageUniquePointer,
+                       ValueStorageUniquePointer&& valueStorageUniquePointer, const size_t maxElements) :
+                       messageQueueBase_{std::move(entryStorageUniquePointer),
+                                       {valueStorageUniquePointer.release(), valueStorageUniquePointer.get_deleter()},
+                                       sizeof(*valueStorageUniquePointer.get()), maxElements}
+       {
+
+       }
+
+       /**
+        * \brief MessageQueue's destructor
+        *
+        * Pops all remaining elements from the queue.
+        */
+
+       ~MessageQueue();
+
+#if DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Emplaces the element in the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int emplace(const uint8_t priority, Args&&... args)
+       {
+               const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+               return emplaceInternal(semaphoreWaitFunctor, priority, std::forward<Args>(args)...);
+       }
+
+#endif // DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Pops oldest element with highest priority from the queue.
+        *
+        * Similar to mq_receive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pop(uint8_t& priority, T& value)
+       {
+               const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+               return popInternal(semaphoreWaitFunctor, priority, value);
+       }
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int push(const uint8_t priority, const T& value)
+       {
+               const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+               return pushInternal(semaphoreWaitFunctor, priority, value);
+       }
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int push(const uint8_t priority, T&& value)
+       {
+               const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+               return pushInternal(semaphoreWaitFunctor, priority, std::move(value));
+       }
+
+#if DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Tries to emplace the element in the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int tryEmplace(const uint8_t priority, Args&&... args)
+       {
+               const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+               return emplaceInternal(semaphoreTryWaitFunctor, priority, std::forward<Args>(args)...);
+       }
+
+       /**
+        * \brief Tries to emplace the element in the queue for a given duration of time.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without emplacing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int tryEmplaceFor(const TickClock::duration duration, const uint8_t priority, Args&&... args)
+       {
+               const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+               return emplaceInternal(semaphoreTryWaitForFunctor, priority, std::forward<Args>(args)...);
+       }
+
+       /**
+        * \brief Tries to emplace the element in the queue for a given duration of time.
+        *
+        * Template variant of MessageQueue::tryEmplaceFor(TickClock::duration, uint8_t, Args&&...).
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without emplacing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period, typename... Args>
+       int tryEmplaceFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, Args&&... args)
+       {
+               return tryEmplaceFor(std::chrono::duration_cast<TickClock::duration>(duration), priority,
+                               std::forward<Args>(args)...);
+       }
+
+       /**
+        * \brief Tries to emplace the element in the queue until a given time point.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without emplacing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int tryEmplaceUntil(const TickClock::time_point timePoint, const uint8_t priority, Args&&... args)
+       {
+               const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+               return emplaceInternal(semaphoreTryWaitUntilFunctor, priority, std::forward<Args>(args)...);
+       }
+
+       /**
+        * \brief Tries to emplace the element in the queue until a given time point.
+        *
+        * Template variant of FifoQueue::tryEmplaceUntil(TickClock::time_point, uint8_t, Args&&...).
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without emplacing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration, typename... Args>
+       int tryEmplaceUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
+                       Args&&... args)
+       {
+               return tryEmplaceUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority,
+                               std::forward<Args>(args)...);
+       }
+
+#endif // DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Tries to pop oldest element with highest priority from the queue.
+        *
+        * Similar to mq_receive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPop(uint8_t& priority, T& value)
+       {
+               const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+               return popInternal(semaphoreTryWaitFunctor, priority, value);
+       }
+
+       /**
+        * \brief Tries to pop oldest element with highest priority from the queue for a given duration of time.
+        *
+        * Similar to mq_timedreceive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPopFor(const TickClock::duration duration, uint8_t& priority, T& value)
+       {
+               const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+               return popInternal(semaphoreTryWaitForFunctor, priority, value);
+       }
+
+       /**
+        * \brief Tries to pop oldest element with highest priority from the queue for a given duration of time.
+        *
+        * Template variant of tryPopFor(TickClock::duration, uint8_t&, T&).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPopFor(const std::chrono::duration<Rep, Period> duration, uint8_t& priority, T& value)
+       {
+               return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, value);
+       }
+
+       /**
+        * \brief Tries to pop oldest element with highest priority from the queue until a given time point.
+        *
+        * Similar to mq_timedreceive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPopUntil(const TickClock::time_point timePoint, uint8_t& priority, T& value)
+       {
+               const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+               return popInternal(semaphoreTryWaitUntilFunctor, priority, value);
+       }
+
+       /**
+        * \brief Tries to pop oldest element with highest priority from the queue until a given time point.
+        *
+        * Template variant of tryPopUntil(TickClock::time_point, uint8_t&, T&).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, uint8_t& priority, T& value)
+       {
+               return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPush(const uint8_t priority, const T& value)
+       {
+               const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+               return pushInternal(semaphoreTryWaitFunctor, priority, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPush(const uint8_t priority, T&& value)
+       {
+               const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+               return pushInternal(semaphoreTryWaitFunctor, priority, std::move(value));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushFor(const TickClock::duration duration, const uint8_t priority, const T& value)
+       {
+               const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+               return pushInternal(semaphoreTryWaitForFunctor, priority, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Template variant of tryPushFor(TickClock::duration, uint8_t, const T&).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, const T& value)
+       {
+               return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushFor(const TickClock::duration duration, const uint8_t priority, T&& value)
+       {
+               const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+               return pushInternal(semaphoreTryWaitForFunctor, priority, std::move(value));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Template variant of tryPushFor(TickClock::duration, uint8_t, T&&).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the call will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, T&& value)
+       {
+               return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, std::move(value));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, const T& value)
+       {
+               const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+               return pushInternal(semaphoreTryWaitUntilFunctor, priority, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Template variant of tryPushUntil(TickClock::time_point, uint8_t, const T&).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
+                       const T& value)
+       {
+               return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, value);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, T&& value)
+       {
+               const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+               return pushInternal(semaphoreTryWaitUntilFunctor, priority, std::move(value));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Template variant of tryPushUntil(TickClock::time_point, uint8_t, T&&).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority, T&& value)
+       {
+               return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, std::move(value));
+       }
+
+private:
+
+#if DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Emplaces the element in the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \note This function requires GCC 4.9.
+        *
+        * \tparam Args are types of arguments for constructor of T
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] priority is the priority of new element
+        * \param [in] args are arguments for constructor of T
+        *
+        * \return zero if element was emplaced successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename... Args>
+       int emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, Args&&... args);
+
+#endif // DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+       /**
+        * \brief Pops oldest element with highest priority from the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a popSemaphore_
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, T& value);
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, const T& value);
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] priority is the priority of new element
+        * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+        * move-constructed
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, T&& value);
+
+       /// contained internal::MessageQueueBase object which implements whole functionality
+       internal::MessageQueueBase messageQueueBase_;
+};
+
+template<typename T>
+MessageQueue<T>::~MessageQueue()
+{
+       uint8_t priority;
+       T value;
+       while (tryPop(priority, value) == 0);
+}
+
+#if DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+template<typename T>
+template<typename... Args>
+int MessageQueue<T>::emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
+               Args&&... args)
+{
+       const auto emplaceFunctor = internal::makeBoundQueueFunctor(
+                       [&args...](void* const storage)
+                       {
+                               new (storage) T{std::forward<Args>(args)...};
+                       });
+       return messageQueueBase_.push(waitSemaphoreFunctor, priority, emplaceFunctor);
+}
+
+#endif // DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+template<typename T>
+int MessageQueue<T>::popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, T& value)
+{
+       const internal::SwapPopQueueFunctor<T> swapPopQueueFunctor {value};
+       return messageQueueBase_.pop(waitSemaphoreFunctor, priority, swapPopQueueFunctor);
+}
+
+template<typename T>
+int MessageQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
+               const T& value)
+{
+       const internal::CopyConstructQueueFunctor<T> copyConstructQueueFunctor {value};
+       return messageQueueBase_.push(waitSemaphoreFunctor, priority, copyConstructQueueFunctor);
+}
+
+template<typename T>
+int MessageQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
+               T&& value)
+{
+       const internal::MoveConstructQueueFunctor<T> moveConstructQueueFunctor {std::move(value)};
+       return messageQueueBase_.push(waitSemaphoreFunctor, priority, moveConstructQueueFunctor);
+}
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_MESSAGEQUEUE_HPP_
diff --git a/include/distortos/Mutex.hpp b/include/distortos/Mutex.hpp
new file mode 100644 (file)
index 0000000..481700d
--- /dev/null
@@ -0,0 +1,280 @@
+/**
+ * \file
+ * \brief Mutex class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_MUTEX_HPP_
+#define INCLUDE_DISTORTOS_MUTEX_HPP_
+
+#include "distortos/internal/synchronization/MutexControlBlock.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief Mutex is the basic synchronization primitive
+ *
+ * Similar to std::mutex - http://en.cppreference.com/w/cpp/thread/mutex
+ * Similar to POSIX pthread_mutex_t -
+ * http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09 -> 2.9.3 Thread Mutexes
+ *
+ * \ingroup synchronization
+ */
+
+class Mutex
+{
+public:
+
+       /// mutex protocols
+       using Protocol = internal::MutexControlBlock::Protocol;
+
+       /// type used for counting recursive locks
+       using RecursiveLocksCount = uint16_t;
+
+       /// type of mutex
+       enum class Type : uint8_t
+       {
+               /// normal mutex, similar to PTHREAD_MUTEX_NORMAL
+               normal,
+               /// mutex with additional error checking, similar to PTHREAD_MUTEX_ERRORCHECK
+               errorChecking,
+               /// recursive mutex, similar to PTHREAD_MUTEX_RECURSIVE
+               recursive
+       };
+
+       /**
+        * \brief Gets the maximum number of recursive locks possible before returning EAGAIN
+        *
+        * \note Actual number of lock() operations possible is getMaxRecursiveLocks() + 1.
+        *
+        * \return maximum number of recursive locks possible before returning EAGAIN
+        */
+
+       constexpr static RecursiveLocksCount getMaxRecursiveLocks()
+       {
+               return std::numeric_limits<RecursiveLocksCount>::max();
+       }
+
+       /**
+        * \brief Mutex constructor
+        *
+        * Similar to std::mutex::mutex() - http://en.cppreference.com/w/cpp/thread/mutex/mutex
+        * Similar to pthread_mutex_init() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html
+        *
+        * \param [in] type is the type of mutex, default - Type::normal
+        * \param [in] protocol is the mutex protocol, default - Protocol::none
+        * \param [in] priorityCeiling is the priority ceiling of mutex, ignored when protocol != Protocol::priorityProtect,
+        * default - 0
+        */
+
+       constexpr explicit Mutex(const Type type = Type::normal, const Protocol protocol = Protocol::none,
+                       const uint8_t priorityCeiling = {}) :
+                       controlBlock_{protocol, priorityCeiling},
+                       recursiveLocksCount_{},
+                       type_{type}
+       {
+
+       }
+
+       /**
+        * \brief Locks the mutex.
+        *
+        * Similar to std::mutex::lock() - http://en.cppreference.com/w/cpp/thread/mutex/lock
+        * Similar to pthread_mutex_lock() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html#
+        *
+        * If the mutex is already locked by another thread, the calling thread shall block until the mutex becomes
+        * available. This function shall return with the mutex in the locked state with the calling thread as its owner. If
+        * a thread attempts to relock a mutex that it has already locked, deadlock occurs.
+        *
+        * \return zero if the caller successfully locked the mutex, error code otherwise:
+        * - EAGAIN - the mutex could not be acquired because the maximum number of recursive locks for mutex has been
+        * exceeded;
+        * - EDEADLK - the mutex type is ErrorChecking and the current thread already owns the mutex;
+        * - EINVAL - the mutex was created with the protocol attribute having the value PriorityProtect and the calling
+        * thread's priority is higher than the mutex's current priority ceiling;
+        */
+
+       int lock();
+
+       /**
+        * \brief Tries to lock the mutex.
+        *
+        * Similar to std::mutex::try_lock() - http://en.cppreference.com/w/cpp/thread/mutex/try_lock
+        * Similar to pthread_mutex_trylock() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html#
+        *
+        * This function shall be equivalent to lock(), except that if the mutex is currently locked (by any thread,
+        * including the current thread), the call shall return immediately.
+        *
+        * \return zero if the caller successfully locked the mutex, error code otherwise:
+        * - EAGAIN - the mutex could not be acquired because the maximum number of recursive locks for mutex has been
+        * exceeded;
+        * - EBUSY - the mutex could not be acquired because it was already locked;
+        * - EINVAL - the mutex was created with the protocol attribute having the value PriorityProtect and the calling
+        * thread's priority is higher than the mutex's current priority ceiling;
+        */
+
+       int tryLock();
+
+       /**
+        * \brief Tries to lock the mutex for given duration of time.
+        *
+        * Similar to std::timed_mutex::try_lock_for() - http://en.cppreference.com/w/cpp/thread/timed_mutex/try_lock_for
+        * Similar to pthread_mutex_timedlock() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_timedlock.html#
+        *
+        * If the mutex is already locked, the calling thread shall block until the mutex becomes available as in lock()
+        * function. If the mutex cannot be locked without waiting for another thread to unlock the mutex, this wait shall
+        * be terminated when the specified timeout expires.
+        *
+        * Under no circumstance shall the function fail with a timeout if the mutex can be locked immediately. The validity
+        * of the duration parameter need not be checked if the mutex can be locked immediately.
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without locking the mutex
+        *
+        * \return zero if the caller successfully locked the mutex, error code otherwise:
+        * - EAGAIN - the mutex could not be acquired because the maximum number of recursive locks for mutex has been
+        * exceeded;
+        * - EDEADLK - the mutex type is ErrorChecking and the current thread already owns the mutex;
+        * - EINVAL - the mutex was created with the protocol attribute having the value PriorityProtect and the calling
+        * thread's priority is higher than the mutex's current priority ceiling;
+        * - ETIMEDOUT - the mutex could not be locked before the specified timeout expired;
+        */
+
+       int tryLockFor(TickClock::duration duration);
+
+       /**
+        * Tries to lock the mutex for given duration of time.
+        *
+        * Template variant of tryLockFor(TickClock::duration duration).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without locking the mutex
+        *
+        * \return zero if the caller successfully locked the mutex, error code otherwise:
+        * - EAGAIN - the mutex could not be acquired because the maximum number of recursive locks for mutex has been
+        * exceeded;
+        * - EDEADLK - the mutex type is ErrorChecking and the current thread already owns the mutex;
+        * - EINVAL - the mutex was created with the protocol attribute having the value PriorityProtect and the calling
+        * thread's priority is higher than the mutex's current priority ceiling;
+        * - ETIMEDOUT - the mutex could not be locked before the specified timeout expired;
+        */
+
+       template<typename Rep, typename Period>
+       int tryLockFor(const std::chrono::duration<Rep, Period> duration)
+       {
+               return tryLockFor(std::chrono::duration_cast<TickClock::duration>(duration));
+       }
+
+       /**
+        * \brief Tries to lock the mutex until given time point.
+        *
+        * Similar to std::timed_mutex::try_lock_until() -
+        * http://en.cppreference.com/w/cpp/thread/timed_mutex/try_lock_until
+        * Similar to pthread_mutex_timedlock() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_timedlock.html#
+        *
+        * If the mutex is already locked, the calling thread shall block until the mutex becomes available as in lock()
+        * function. If the mutex cannot be locked without waiting for another thread to unlock the mutex, this wait shall
+        * be terminated when the specified timeout expires.
+        *
+        * Under no circumstance shall the function fail with a timeout if the mutex can be locked immediately. The validity
+        * of the timePoint parameter need not be checked if the mutex can be locked immediately.
+        *
+        * \param [in] timePoint is the time point at which the wait will be terminated without locking the mutex
+        *
+        * \return zero if the caller successfully locked the mutex, error code otherwise:
+        * - EAGAIN - the mutex could not be acquired because the maximum number of recursive locks for mutex has been
+        * exceeded;
+        * - EDEADLK - the mutex type is ErrorChecking and the current thread already owns the mutex;
+        * - EINVAL - the mutex was created with the protocol attribute having the value PriorityProtect and the calling
+        * thread's priority is higher than the mutex's current priority ceiling;
+        * - ETIMEDOUT - the mutex could not be locked before the specified timeout expired;
+        */
+
+       int tryLockUntil(TickClock::time_point timePoint);
+
+       /**
+        * \brief Tries to lock the mutex until given time point.
+        *
+        * Template variant of tryLockUntil(TickClock::time_point timePoint).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the wait will be terminated without locking the mutex
+        *
+        * \return zero if the caller successfully locked the mutex, error code otherwise:
+        * - EAGAIN - the mutex could not be acquired because the maximum number of recursive locks for mutex has been
+        * exceeded;
+        * - EDEADLK - the mutex type is ErrorChecking and the current thread already owns the mutex;
+        * - EINVAL - the mutex was created with the protocol attribute having the value PriorityProtect and the calling
+        * thread's priority is higher than the mutex's current priority ceiling;
+        * - ETIMEDOUT - the mutex could not be locked before the specified timeout expired;
+        */
+
+       template<typename Duration>
+       int tryLockUntil(const std::chrono::time_point<TickClock, Duration> timePoint)
+       {
+               return tryLockUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint));
+       }
+
+       /**
+        * \brief Unlocks the mutex.
+        *
+        * Similar to std::mutex::unlock() - http://en.cppreference.com/w/cpp/thread/mutex/unlock
+        * Similar to pthread_mutex_unlock() -
+        * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html#
+        *
+        * The mutex must be locked by the current thread, otherwise, the behavior is undefined. If there are threads
+        * blocked on this mutex, the highest priority waiting thread shall be unblocked, and if there is more than one
+        * highest priority thread blocked waiting, then the highest priority thread that has been waiting the longest shall
+        * be unblocked.
+        *
+        * \return zero if the caller successfully unlocked the mutex, error code otherwise:
+        * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+        */
+
+       int unlock();
+
+private:
+
+       /**
+        * \brief Internal version of tryLock().
+        *
+        * Internal version with no interrupt masking and additional code for ErrorChecking type (which is not required for
+        * tryLock()).
+        *
+        * \return zero if the caller successfully locked the mutex, error code otherwise:
+        * - EAGAIN - the mutex could not be acquired because the maximum number of recursive locks for mutex has been
+        * exceeded;
+        * - EBUSY - the mutex could not be acquired because it was already locked;
+        * - EDEADLK - the mutex type is ErrorChecking and the current thread already owns the mutex;
+        * - EINVAL - the mutex was created with the protocol attribute having the value PriorityProtect and the calling
+        * thread's priority is higher than the mutex's current priority ceiling;
+        */
+
+       int tryLockInternal();
+
+       /// instance of control block
+       internal::MutexControlBlock controlBlock_;
+
+       /// number of recursive locks, used when mutex type is Recursive
+       RecursiveLocksCount recursiveLocksCount_;
+
+       /// type of mutex
+       Type type_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_MUTEX_HPP_
diff --git a/include/distortos/OnceFlag.hpp b/include/distortos/OnceFlag.hpp
new file mode 100644 (file)
index 0000000..0ac6185
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * \file
+ * \brief OnceFlag class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ONCEFLAG_HPP_
+#define INCLUDE_DISTORTOS_ONCEFLAG_HPP_
+
+#include "distortos/internal/synchronization/CallOnceControlBlock.hpp"
+
+#if DISTORTOS_CALLONCE_SUPPORTED == 1 || DOXYGEN == 1
+
+namespace distortos
+{
+
+/**
+ * \brief OnceFlag is a helper class for callOnce().
+ *
+ * Similar to std::once_flag - http://en.cppreference.com/w/cpp/thread/once_flag
+ * Similar to POSIX pthread_once_t - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_once.html#
+ *
+ * \note This class requires GCC 4.9.
+ *
+ * \ingroup synchronization
+ */
+
+class OnceFlag
+{
+       template<typename Function, typename... Args>
+       friend void callOnce(OnceFlag& onceFlag, Function&& function, Args&&... args);
+
+public:
+
+       /**
+        * \brief OnceFlag's constructor
+        */
+
+       constexpr OnceFlag() :
+                       callOnceControlBlock_{}
+       {
+
+       }
+
+private:
+
+       /// internal internal::CallOnceControlBlock object used by callOnce()
+       internal::CallOnceControlBlock callOnceControlBlock_;
+};
+
+}      // namespace distortos
+
+#endif // DISTORTOS_CALLONCE_SUPPORTED == 1 || DOXYGEN == 1
+
+#endif // INCLUDE_DISTORTOS_ONCEFLAG_HPP_
diff --git a/include/distortos/RawFifoQueue.hpp b/include/distortos/RawFifoQueue.hpp
new file mode 100644 (file)
index 0000000..94456a7
--- /dev/null
@@ -0,0 +1,463 @@
+/**
+ * \file
+ * \brief RawFifoQueue class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_RAWFIFOQUEUE_HPP_
+#define INCLUDE_DISTORTOS_RAWFIFOQUEUE_HPP_
+
+#include "distortos/internal/synchronization/FifoQueueBase.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief RawFifoQueue class is very similar to FifoQueue, but optimized for binary serializable types (like POD types).
+ *
+ * Type \a T can be used with both RawFifoQueue and FifoQueue only when
+ * <em>std::is_trivially_copyable<T>::value == true</em>, otherwise only FifoQueue use is safe, while using RawFifoQueue
+ * results in undefined behavior.
+ *
+ * \ingroup queues
+ */
+
+class RawFifoQueue
+{
+public:
+
+       /// unique_ptr (with deleter) to storage
+       using StorageUniquePointer = internal::FifoQueueBase::StorageUniquePointer;
+
+       /**
+        * \brief RawFifoQueue's constructor
+        *
+        * \param [in] storageUniquePointer is a rvalue reference to StorageUniquePointer with storage for queue elements
+        * (sufficiently large for \a maxElements, each \a elementSize bytes long) and appropriate deleter
+        * \param [in] elementSize is the size of single queue element, bytes
+        * \param [in] maxElements is the number of elements in storage memory block
+        */
+
+       RawFifoQueue(StorageUniquePointer&& storageUniquePointer, size_t elementSize, size_t maxElements);
+
+       /**
+        * \brief Pops the oldest (first) element from the queue.
+        *
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pop(void* buffer, size_t size);
+
+       /**
+        * \brief Pops the oldest (first) element from the queue.
+        *
+        * \tparam T is the type of data popped from the queue
+        *
+        * \param [out] buffer is a reference to object that will be used to return popped value
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename T>
+       int pop(T& buffer)
+       {
+               return pop(&buffer, sizeof(buffer));
+       }
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * \param [in] data is a pointer to data that will be pushed to RawFifoQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int push(const void* data, size_t size);
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * \tparam T is the type of data pushed to the queue
+        *
+        * \param [in] data is a reference to data that will be pushed to RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename T>
+       int push(const T& data)
+       {
+               return push(&data, sizeof(data));
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue.
+        *
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPop(void* buffer, size_t size);
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue.
+        *
+        * \tparam T is the type of data popped from the queue
+        *
+        * \param [out] buffer is a reference to object that will be used to return popped value
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename T>
+       int tryPop(T& buffer)
+       {
+               return tryPop(&buffer, sizeof(buffer));
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue for a given duration of time.
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPopFor(TickClock::duration duration, void* buffer, size_t size);
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue for a given duration of time.
+        *
+        * Template variant of tryPopFor(TickClock::duration, void*, size_t).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPopFor(const std::chrono::duration<Rep, Period> duration, void* const buffer, const size_t size)
+       {
+               return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), buffer, size);
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue for a given duration of time.
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        * \tparam T is the type of data popped from the queue
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] buffer is a reference to object that will be used to return popped value
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period, typename T>
+       int tryPopFor(const std::chrono::duration<Rep, Period> duration, T& buffer)
+       {
+               return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), &buffer, sizeof(buffer));
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue until a given time point.
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPopUntil(TickClock::time_point timePoint, void* buffer, size_t size);
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue until a given time point.
+        *
+        * Template variant of tryPopUntil(TickClock::time_point, void*, size_t).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, void* const buffer, const size_t size)
+       {
+               return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), buffer, size);
+       }
+
+       /**
+        * \brief Tries to pop the oldest (first) element from the queue until a given time point.
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        * \tparam T is the type of data popped from the queue
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] buffer is a reference to object that will be used to return popped value
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration, typename T>
+       int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, T& buffer)
+       {
+               return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), &buffer, sizeof(buffer));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue.
+        *
+        * \param [in] data is a pointer to data that will be pushed to RawFifoQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPush(const void* data, size_t size);
+
+       /**
+        * \brief Tries to push the element to the queue.
+        *
+        * \tparam T is the type of data pushed to the queue
+        *
+        * \param [in] data is a reference to data that will be pushed to RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename T>
+       int tryPush(const T& data)
+       {
+               return tryPush(&data, sizeof(data));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] data is a pointer to data that will be pushed to RawFifoQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushFor(TickClock::duration duration, const void* data, size_t size);
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Template variant of tryPushFor(TickClock::duration, const void*, size_t).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] data is a pointer to data that will be pushed to RawFifoQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPushFor(const std::chrono::duration<Rep, Period> duration, const void* const data, const size_t size)
+       {
+               return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), data, size);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        * \tparam T is the type of data pushed to the queue
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] data is a reference to data that will be pushed to RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period, typename T>
+       int tryPushFor(const std::chrono::duration<Rep, Period> duration, const T& data)
+       {
+               return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), &data, sizeof(data));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] data is a pointer to data that will be pushed to RawFifoQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushUntil(TickClock::time_point timePoint, const void* data, size_t size);
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Template variant of tryPushUntil(TickClock::time_point, const void*, size_t).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] data is a pointer to data that will be pushed to RawFifoQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const void* const data,
+                       const size_t size)
+       {
+               return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), data, size);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        * \tparam T is the type of data pushed to the queue
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] data is a reference to data that will be pushed to RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration, typename T>
+       int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const T& data)
+       {
+               return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), &data, sizeof(data));
+       }
+
+private:
+
+       /**
+        * \brief Pops the oldest (first) element from the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a popSemaphore_
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, void* buffer, size_t size);
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] data is a pointer to data that will be pushed to RawFifoQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawFifoQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawFifoQueue;
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const void* data, size_t size);
+
+       /// contained internal::FifoQueueBase object which implements base functionality
+       internal::FifoQueueBase fifoQueueBase_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_RAWFIFOQUEUE_HPP_
diff --git a/include/distortos/RawMessageQueue.hpp b/include/distortos/RawMessageQueue.hpp
new file mode 100644 (file)
index 0000000..d4b2a54
--- /dev/null
@@ -0,0 +1,555 @@
+/**
+ * \file
+ * \brief RawMessageQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_RAWMESSAGEQUEUE_HPP_
+#define INCLUDE_DISTORTOS_RAWMESSAGEQUEUE_HPP_
+
+#include "distortos/internal/synchronization/MessageQueueBase.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief RawMessageQueue class is very similar to MessageQueue, but optimized for binary serializable types (like POD
+ * types).
+ *
+ * Type \a T can be used with both RawMessageQueue and MessageQueue only when
+ * <em>std::is_trivially_copyable<T>::value == true</em>, otherwise only MessageQueue use is safe, while using
+ * RawMessageQueue results in undefined behavior.
+ *
+ * Similar to POSIX mqd_t - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/mqueue.h.html
+ *
+ * \ingroup queues
+ */
+
+class RawMessageQueue
+{
+public:
+
+       /// type of uninitialized storage for Entry with link
+       using EntryStorage = internal::MessageQueueBase::EntryStorage;
+
+       /// import EntryStorageUniquePointer type from internal::MessageQueueBase class
+       using EntryStorageUniquePointer = internal::MessageQueueBase::EntryStorageUniquePointer;
+
+       /**
+        * type of uninitialized storage for value
+        *
+        * \tparam T is the type of data in queue
+        */
+
+       template<typename T>
+       using ValueStorage = internal::MessageQueueBase::ValueStorage<T>;
+
+       using ValueStorageUniquePointer = internal::MessageQueueBase::ValueStorageUniquePointer;
+
+       /**
+        * \brief RawMessageQueue's constructor
+        *
+        * \param [in] entryStorageUniquePointer is a rvalue reference to EntryStorageUniquePointer with storage for queue
+        * entries (sufficiently large for \a maxElements EntryStorage objects) and appropriate deleter
+        * \param [in] valueStorageUniquePointer is a rvalue reference to ValueStorageUniquePointer with storage for queue
+        * elements (sufficiently large for \a maxElements, each \a elementSize bytes long) and appropriate deleter
+        * \param [in] elementSize is the size of single queue element, bytes
+        * \param [in] maxElements is the number of elements in \a entryStorage array and \a valueStorage memory block
+        */
+
+       RawMessageQueue(EntryStorageUniquePointer&& entryStorageUniquePointer,
+                       ValueStorageUniquePointer&& valueStorageUniquePointer, size_t elementSize, size_t maxElements);
+
+       /**
+        * \brief Pops oldest element with highest priority from the queue.
+        *
+        * Similar to mq_receive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of
+        * RawMessageQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pop(uint8_t& priority, void* buffer, size_t size);
+
+       /**
+        * \brief Pops oldest element with highest priority from the queue.
+        *
+        * Similar to mq_receive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \tparam T is the type of data popped from the queue
+        *
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a reference to object that will be used to return popped value
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename T>
+       int pop(uint8_t& priority, T& buffer)
+       {
+               return pop(priority, &buffer, sizeof(buffer));
+       }
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int push(uint8_t priority, const void* data, size_t size);
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \tparam T is the type of data pushed to the queue
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a reference to data that will be pushed to RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::wait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename T>
+       int push(const uint8_t priority, const T& data)
+       {
+               return push(priority, &data, sizeof(data));
+       }
+
+       /**
+        * \brief Tries to pop the oldest element with highest priority from the queue.
+        *
+        * Similar to mq_receive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of
+        * RawMessageQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPop(uint8_t& priority, void* buffer, size_t size);
+
+       /**
+        * \brief Tries to pop the oldest element with highest priority from the queue.
+        *
+        * Similar to mq_receive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \tparam T is the type of data popped from the queue
+        *
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a reference to object that will be used to return popped value
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename T>
+       int tryPop(uint8_t& priority, T& buffer)
+       {
+               return tryPop(priority, &buffer, sizeof(buffer));
+       }
+
+       /**
+        * \brief Tries to pop the oldest element with highest priority from the queue for a given duration of time.
+        *
+        * Similar to mq_timedreceive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of
+        * RawMessageQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPopFor(TickClock::duration duration, uint8_t& priority, void* buffer, size_t size);
+
+       /**
+        * \brief Tries to pop the oldest element with highest priority from the queue for a given duration of time.
+        *
+        * Template variant of tryPopFor(TickClock::duration, uint8_t&, void*, size_t).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of
+        * RawMessageQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPopFor(const std::chrono::duration<Rep, Period> duration, uint8_t& priority, void* const buffer,
+                       const size_t size)
+       {
+               return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, buffer, size);
+       }
+
+       /**
+        * \brief Tries to pop the oldest element with highest priority from the queue for a given duration of time.
+        *
+        * Similar to mq_timedreceive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        * \tparam T is the type of data popped from the queue
+        *
+        * \param [in] duration is the duration after which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a reference to object that will be used to return popped value
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period, typename T>
+       int tryPopFor(const std::chrono::duration<Rep, Period> duration, uint8_t& priority, T& buffer)
+       {
+               return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, &buffer, sizeof(buffer));
+       }
+
+       /**
+        * \brief Tries to pop the oldest element with highest priority from the queue until a given time point.
+        *
+        * Similar to mq_timedreceive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of
+        * RawMessageQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPopUntil(TickClock::time_point timePoint, uint8_t& priority, void* buffer, size_t size);
+
+       /**
+        * \brief Tries to pop the oldest element with highest priority from the queue until a given time point.
+        *
+        * Template variant of tryPopUntil(TickClock::time_point, uint8_t&, void*, size_t).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of
+        * RawMessageQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, uint8_t& priority, void* const buffer,
+                       const size_t size)
+       {
+               return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, buffer, size);
+       }
+
+       /**
+        * \brief Tries to pop the oldest element with highest priority from the queue until a given time point.
+        *
+        * Similar to mq_timedreceive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        * \tparam T is the type of data popped from the queue
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a reference to object that will be used to return popped value
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration, typename T>
+       int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, uint8_t& priority, T& buffer)
+       {
+               return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, &buffer,
+                               sizeof(buffer));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPush(uint8_t priority, const void* data, size_t size);
+
+       /**
+        * \brief Tries to push the element to the queue.
+        *
+        * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \tparam T is the type of data pushed to the queue
+        *
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a reference to data that will be pushed to RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWait();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename T>
+       int tryPush(const uint8_t priority, const T& data)
+       {
+               return tryPush(priority, &data, sizeof(data));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushFor(TickClock::duration duration, uint8_t priority, const void* data, size_t size);
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Template variant of tryPushFor(TickClock::duration, uint8_t, const void*, size_t).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period>
+       int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, const void* const data,
+                       const size_t size)
+       {
+               return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, data, size);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue for a given duration of time.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        * \tparam T is the type of data pushed to the queue
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a reference to data that will be pushed to RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitFor();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Rep, typename Period, typename T>
+       int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, const T& data)
+       {
+               return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, &data, sizeof(data));
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       int tryPushUntil(TickClock::time_point timePoint, uint8_t priority, const void* data, size_t size);
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Template variant of tryPushUntil(TickClock::time_point, uint8_t, const void*, size_t).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration>
+       int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
+                       const void* const data, const size_t size)
+       {
+               return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, data, size);
+       }
+
+       /**
+        * \brief Tries to push the element to the queue until a given time point.
+        *
+        * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        * \tparam T is the type of data pushed to the queue
+        *
+        * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a reference to data that will be pushed to RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - sizeof(T) doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by Semaphore::tryWaitUntil();
+        * - error codes returned by Semaphore::post();
+        */
+
+       template<typename Duration, typename T>
+       int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
+                       const T& data)
+       {
+               return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, &data,
+                               sizeof(data));
+       }
+
+private:
+
+       /**
+        * \brief Pops oldest element with highest priority from the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a popSemaphore_
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes - must be equal to the \a elementSize attribute of
+        * RawMessageQueue
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, void* buffer,
+                       size_t size);
+
+       /**
+        * \brief Pushes the element to the queue.
+        *
+        * Internal version - builds the Functor object.
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] priority is the priority of new element
+        * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
+        * \param [in] size is the size of \a data, bytes - must be equal to the \a elementSize attribute of RawMessageQueue
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - EMSGSIZE - \a size doesn't match the \a elementSize attribute of RawMessageQueue;
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, const void* data,
+                       size_t size);
+
+       /// contained internal::MessageQueueBase object which implements base functionality
+       internal::MessageQueueBase messageQueueBase_;
+
+       /// size of single queue element, bytes
+       const size_t elementSize_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_RAWMESSAGEQUEUE_HPP_
diff --git a/include/distortos/SchedulingPolicy.hpp b/include/distortos/SchedulingPolicy.hpp
new file mode 100644 (file)
index 0000000..8793fb4
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * \file
+ * \brief SchedulingPolicy enum class header
+ *
+ * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SCHEDULINGPOLICY_HPP_
+#define INCLUDE_DISTORTOS_SCHEDULINGPOLICY_HPP_
+
+#include <cstdint>
+
+namespace distortos
+{
+
+/**
+ * \brief scheduling policy of the thread
+ *
+ * \ingroup threads
+ */
+
+enum class SchedulingPolicy : uint8_t
+{
+       /// FIFO scheduling policy
+       fifo,
+       /// round-robin scheduling policy
+       roundRobin,
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SCHEDULINGPOLICY_HPP_
diff --git a/include/distortos/Semaphore.hpp b/include/distortos/Semaphore.hpp
new file mode 100644 (file)
index 0000000..26ca298
--- /dev/null
@@ -0,0 +1,245 @@
+/**
+ * \file
+ * \brief Semaphore class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SEMAPHORE_HPP_
+#define INCLUDE_DISTORTOS_SEMAPHORE_HPP_
+
+#include "distortos/internal/scheduler/ThreadList.hpp"
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief Semaphore is the basic synchronization primitive
+ *
+ * Similar to POSIX semaphores - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
+ *
+ * \ingroup synchronization
+ */
+
+class Semaphore
+{
+public:
+
+       /// type used for semaphore's "value"
+       using Value = unsigned int;
+
+       /**
+        * \brief Semaphore constructor
+        *
+        * Similar to sem_init() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html#
+        *
+        * \param [in] value is the initial value of the semaphore, if this value is greater than maxValue, it will be
+        * truncated
+        * \param [in] maxValue is the max value of the semaphore before post() returns EOVERFLOW, default - max for Value
+        * type
+        */
+
+       constexpr explicit Semaphore(const Value value, const Value maxValue = std::numeric_limits<Value>::max()) :
+                       blockedList_{},
+                       value_{value <= maxValue ? value : maxValue},
+                       maxValue_{maxValue}
+       {
+
+       }
+
+       /**
+        * \brief Semaphore destructor
+        *
+        * Similar to sem_destroy() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html#
+        *
+        * It is safe to destroy a semaphore upon which no threads are currently blocked. The effect of destroying a
+        * semaphore upon which other threads are currently blocked is system error.
+        */
+
+       ~Semaphore()
+       {
+
+       }
+
+       /**
+        * \brief Gets current value of semaphore.
+        *
+        * Similar to sem_getvalue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html#
+        *
+        * \return current value of semaphore, positive value if semaphore is not locked, zero otherwise
+        */
+
+       Value getValue() const
+       {
+               return value_;
+       }
+
+       /**
+        * \brief Unlocks the semaphore.
+        *
+        * Similar to sem_post() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html#
+        *
+        * This function shall unlock the semaphore by performing a semaphore unlock operation. If the semaphore value
+        * resulting from this operation is positive, then no threads were blocked waiting for the semaphore to become
+        * unlocked; the semaphore value is simply incremented. Otherwise one of the threads blocked waiting for the
+        * semaphore shall be allowed to return successfully from its call to lock() - the highest priority waiting thread
+        * shall be unblocked, and if there is more than one highest priority thread blocked waiting for the semaphore, then
+        * the highest priority thread that has been waiting the longest shall be unblocked.
+        *
+        * \return zero if the calling process successfully "posted" the semaphore, error code otherwise:
+        * - EOVERFLOW - the maximum allowable value for a semaphore would be exceeded;
+        */
+
+       int post();
+
+       /**
+        * \brief Tries to lock the semaphore.
+        *
+        * Similar to sem_trywait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
+        *
+        * This function shall lock the semaphore only if the semaphore is currently not locked; that is, if the semaphore
+        * value is currently positive. Otherwise, it shall not lock the semaphore. Upon successful return, the state of the
+        * semaphore shall be locked and shall remain locked until unlock() function is executed.
+        *
+        * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
+        * - EAGAIN - semaphore was already locked, so it cannot be immediately locked by the tryWait() operation;
+        */
+
+       int tryWait();
+
+       /**
+        * \brief Tries to lock the semaphore for given duration of time.
+        *
+        * Similar to sem_timedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html#
+        *
+        * If the semaphore is already locked, the calling thread shall block until the semaphore becomes available as in
+        * wait() function. If the semaphore cannot be locked without waiting for another thread to unlock the semaphore,
+        * this wait shall be terminated when the specified timeout expires.
+        *
+        * Under no circumstance shall the function fail with a timeout if the semaphore can be locked immediately. The
+        * validity of the duration parameter need not be checked if the semaphore can be locked immediately.
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without locking the semaphore
+        *
+        * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
+        * - EINTR - the wait was interrupted by an unmasked, caught signal;
+        * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
+        */
+
+       int tryWaitFor(TickClock::duration duration);
+
+       /**
+        * \brief Tries to lock the semaphore for given duration of time.
+        *
+        * Template variant of tryWaitFor(TickClock::duration duration).
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the wait will be terminated without locking the semaphore
+        *
+        * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
+        * - EINTR - the wait was interrupted by an unmasked, caught signal;
+        * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
+        */
+
+       template<typename Rep, typename Period>
+       int tryWaitFor(const std::chrono::duration<Rep, Period> duration)
+       {
+               return tryWaitFor(std::chrono::duration_cast<TickClock::duration>(duration));
+       }
+
+       /**
+        * \brief Tries to lock the semaphore until given time point.
+        *
+        * Similar to sem_timedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html#
+        *
+        * If the semaphore is already locked, the calling thread shall block until the semaphore becomes available as in
+        * wait() function. If the semaphore cannot be locked without waiting for another thread to unlock the semaphore,
+        * this wait shall be terminated when the specified timeout expires.
+        *
+        * Under no circumstance shall the function fail with a timeout if the semaphore can be locked immediately. The
+        * validity of the timePoint parameter need not be checked if the semaphore can be locked immediately.
+        *
+        * \param [in] timePoint is the time point at which the wait will be terminated without locking the semaphore
+        *
+        * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
+        * - EINTR - the wait was interrupted by an unmasked, caught signal;
+        * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
+        */
+
+       int tryWaitUntil(TickClock::time_point timePoint);
+
+       /**
+        * \brief Tries to lock the semaphore until given time point.
+        *
+        * Template variant of tryWaitUntil(TickClock::time_point timePoint).
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the wait will be terminated without locking the semaphore
+        *
+        * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
+        * - EINTR - the wait was interrupted by an unmasked, caught signal;
+        * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
+        */
+
+       template<typename Duration>
+       int tryWaitUntil(const std::chrono::time_point<TickClock, Duration> timePoint)
+       {
+               return tryWaitUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint));
+       }
+
+       /**
+        * \brief Locks the semaphore.
+        *
+        * Similar to sem_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
+        *
+        * This function shall lock the semaphore by performing a semaphore lock operation on that semaphore. If the
+        * semaphore value is currently zero, then the calling thread shall not return from the call to lock() until it
+        * either locks the semaphore or the call is interrupted by a signal. Upon successful return, the state of the
+        * semaphore shall be locked and shall remain locked until unlock() function is executed.
+        *
+        * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
+        * - EINTR - the wait was interrupted by an unmasked, caught signal;
+        */
+
+       int wait();
+
+       Semaphore(const Semaphore&) = delete;
+       Semaphore(Semaphore&&) = default;
+       const Semaphore& operator=(const Semaphore&) = delete;
+       Semaphore& operator=(Semaphore&&) = delete;
+
+private:
+
+       /**
+        * \brief Internal version of tryWait().
+        *
+        * Internal version with no interrupt masking.
+        *
+        * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
+        * - EAGAIN - semaphore was already locked, so it cannot be immediately locked by the tryWait() operation;
+        */
+
+       int tryWaitInternal();
+
+       /// ThreadControlBlock objects blocked on this semaphore
+       internal::ThreadList blockedList_;
+
+       /// internal value of the semaphore
+       Value value_;
+
+       /// max value of the semaphore
+       Value maxValue_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SEMAPHORE_HPP_
diff --git a/include/distortos/SignalAction.hpp b/include/distortos/SignalAction.hpp
new file mode 100644 (file)
index 0000000..d91d696
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+ * \file
+ * \brief SignalAction class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SIGNALACTION_HPP_
+#define INCLUDE_DISTORTOS_SIGNALACTION_HPP_
+
+#include "distortos/SignalSet.hpp"
+
+namespace distortos
+{
+
+class SignalInformation;
+
+/**
+ * \brief SignalAction class contains information needed to handle signal that was caught
+ *
+ * Similar to \a sigaction - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
+ *
+ * \ingroup signals
+ */
+
+class SignalAction
+{
+public:
+
+       /// handler function
+       using Handler = void(const SignalInformation&);
+
+       /**
+        * \brief SignalAction's constructor which uses "default" signal handler.
+        */
+
+       constexpr SignalAction() :
+                       signalMask_{SignalSet::empty},
+                       handler_{}
+       {
+
+       }
+
+       /**
+        * \brief SignalAction's constructor.
+        *
+        * \param [in] handler is a reference to handler function (similar to \a sa_sigaction member of \a sigaction)
+        * \param [in] signalMask is the additional set of signals to be masked during execution of signal-catching function
+        * (similar to \a sa_mask member of \a sigaction)
+        */
+
+       constexpr SignalAction(Handler& handler, const SignalSet signalMask) :
+                       signalMask_{signalMask},
+                       handler_{&handler}
+       {
+
+       }
+
+       /**
+        * \return pointer to handler function (similar to \a sa_sigaction member of \a sigaction), nullptr if use of
+        * default handler was configured (similar to \a SIG_DFL)
+        */
+
+       Handler* getHandler() const
+       {
+               return handler_;
+       }
+
+       /**
+        * \return additional set of signals to be masked during execution of signal-catching function (similar to
+        * \a sa_mask member of \a sigaction)
+        */
+
+       SignalSet getSignalMask() const
+       {
+               return signalMask_;
+       }
+
+private:
+
+       /// additional set of signals to be masked during execution of signal-catching function (similar to \a sa_mask
+       /// member of \a sigaction)
+       SignalSet signalMask_;
+
+       /// pointer to handler function (similar to \a sa_sigaction member of \a sigaction), nullptr to use default handler
+       /// (similar to \a SIG_DFL)
+       Handler* handler_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SIGNALACTION_HPP_
diff --git a/include/distortos/SignalInformation.hpp b/include/distortos/SignalInformation.hpp
new file mode 100644 (file)
index 0000000..b3d897c
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * \file
+ * \brief SignalInformation class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SIGNALINFORMATION_HPP_
+#define INCLUDE_DISTORTOS_SIGNALINFORMATION_HPP_
+
+#include <csignal>
+#include <cstdint>
+
+namespace distortos
+{
+
+/**
+ * \brief SignalInformation class contains information about queued signal
+ *
+ * Similar to siginfo_t - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
+ *
+ * \ingroup signals
+ */
+
+class SignalInformation
+{
+public:
+
+       /// replacement for predefined \a si_code values
+       enum class Code : uint8_t
+       {
+               /// signal generated by Thread::generateSignal() or ThisThread::Signals::generateSignal() (similar to
+               /// \a SI_USER)
+               generated,
+               /// signal queued by Thread::queueSignal() or ThisThread::Signals::queueSignal() (similar to \a SI_QUEUE)
+               queued,
+       };
+
+       /**
+        * \brief SignalInformation's constructor.
+        *
+        * \param [in] signalNumber is the signal number (similar to \a si_signo member of \a siginfo_t)
+        * \param [in] code is the signal code (similar to \a si_code member of \a siginfo_t)
+        * \param [in] value is the signal value (similar to \a si_value member of \a siginfo_t)
+        */
+
+       constexpr SignalInformation(const uint8_t signalNumber, const Code code, const sigval value) :
+                       value_(value),
+                       code_{code},
+                       signalNumber_{signalNumber}
+       {
+
+       }
+
+       /**
+        * \return signal code (similar to \a si_code member of \a siginfo_t)
+        */
+
+       Code getCode() const
+       {
+               return code_;
+       }
+
+       /**
+        * \return signal number (similar to \a si_signo member of \a siginfo_t)
+        */
+
+       uint8_t getSignalNumber() const
+       {
+               return signalNumber_;
+       }
+
+       /**
+        * \return signal value (similar to \a si_value member of \a siginfo_t)
+        */
+
+       sigval getValue() const
+       {
+               return value_;
+       }
+
+private:
+
+       /// signal value (similar to \a si_value member of \a siginfo_t)
+       sigval value_;
+
+       /// signal code (similar to \a si_code member of \a siginfo_t)
+       Code code_;
+
+       /// signal number (similar to \a si_signo member of \a siginfo_t)
+       uint8_t signalNumber_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SIGNALINFORMATION_HPP_
diff --git a/include/distortos/SignalInformationQueueWrapper.hpp b/include/distortos/SignalInformationQueueWrapper.hpp
new file mode 100644 (file)
index 0000000..f3825a5
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * \file
+ * \brief SignalInformationQueueWrapper class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SIGNALINFORMATIONQUEUEWRAPPER_HPP_
+#define INCLUDE_DISTORTOS_SIGNALINFORMATIONQUEUEWRAPPER_HPP_
+
+#include "distortos/internal/synchronization/SignalInformationQueue.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class SignalsReceiverControlBlock;
+
+}      // namespace internal
+
+/// SignalInformationQueueWrapper class is a container for internal::SignalInformationQueue
+class SignalInformationQueueWrapper
+{
+       friend class internal::SignalsReceiverControlBlock;
+
+public:
+
+       /// import Storage type alias from internal::SignalInformationQueue
+       using Storage = internal::SignalInformationQueue::Storage;
+
+       /// import StorageUniquePointer type alias from internal::SignalInformationQueue
+       using StorageUniquePointer = internal::SignalInformationQueue::StorageUniquePointer;
+
+       /**
+        * \brief SignalInformationQueueWrapper's constructor
+        *
+        * \param [in] storageUniquePointer is a rvalue reference to StorageUniquePointer with storage for queue elements
+        * (sufficiently large for \a maxElements Storage objects) and appropriate deleter
+        * \param [in] maxElements is the number of elements in \a storage array
+        */
+
+       SignalInformationQueueWrapper(StorageUniquePointer&& storageUniquePointer, const size_t maxElements) :
+                       signalInformationQueue_{std::move(storageUniquePointer), maxElements}
+       {
+
+       }
+
+private:
+
+       /// contained internal::SignalInformationQueue object
+       internal::SignalInformationQueue signalInformationQueue_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SIGNALINFORMATIONQUEUEWRAPPER_HPP_
diff --git a/include/distortos/SignalSet.hpp b/include/distortos/SignalSet.hpp
new file mode 100644 (file)
index 0000000..8473bdd
--- /dev/null
@@ -0,0 +1,179 @@
+/**
+ * \file
+ * \brief SignalSet class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SIGNALSET_HPP_
+#define INCLUDE_DISTORTOS_SIGNALSET_HPP_
+
+#include <bitset>
+
+namespace distortos
+{
+
+/**
+ * \brief SignalSet class is used as a set of signals.
+ *
+ * Similar to POSIX sigset_t - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
+ *
+ * \ingroup signals
+ */
+
+class SignalSet
+{
+public:
+
+       /// type of internal bitset for 32 signals
+       using Bitset = std::bitset<32>;
+
+       /// tag struct to construct empty SignalSet
+       struct Empty
+       {
+
+       };
+
+       /// tag struct to construct full SignalSet
+       struct Full
+       {
+
+       };
+
+       /// tag object to construct empty SignalSet
+       constexpr static Empty empty = {};
+
+       /// tag object to construct full SignalSet
+       constexpr static Full full = {};
+
+       /**
+        * \brief SignalSet's constructor
+        *
+        * \param [in] bitmask is the bit mask used to initialize internal bitset
+        */
+
+       constexpr explicit SignalSet(uint32_t bitmask) :
+                       bitset_{bitmask}
+       {
+
+       }
+
+       /**
+        * \brief SignalSet's constructor
+        *
+        * \param [in] bitset is a reference to Bitset from which internal bitset is copy-constructed
+        */
+
+       constexpr explicit SignalSet(const Bitset& bitset) :
+                       bitset_{bitset}
+       {
+
+       }
+
+       /**
+        * \brief SignalSet's constructor
+        *
+        * Constructs empty SignalSet.
+        *
+        * Similar to sigemptyset() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigemptyset.html#
+        */
+
+       constexpr explicit SignalSet(const Empty&) :
+                       SignalSet{uint32_t{}}
+       {
+
+       }
+
+       /**
+        * \brief SignalSet's constructor
+        *
+        * Constructs full SignalSet.
+        *
+        * Similar to sigfillset() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigfillset.html#
+        */
+
+       constexpr explicit SignalSet(const Full&) :
+                       SignalSet{~uint32_t{}}
+       {
+
+       }
+
+       /**
+        * \brief Sets single bit.
+        *
+        * Similar to sigaddset() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaddset.html#
+        *
+        * \param [in] signalNumber is the bit position that will be set, [0; 31]
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       int add(const uint8_t signalNumber)
+       {
+               return set(signalNumber, true);
+       }
+
+       /**
+        * \return copy of internal bitset
+        */
+
+       Bitset getBitset() const
+       {
+               return bitset_;
+       }
+
+       /**
+        * \brief Clears single bit.
+        *
+        * Similar to sigdelset() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigdelset.html#
+        *
+        * \param [in] signalNumber is the bit position that will be cleared, [0; 31]
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       int remove(const uint8_t signalNumber)
+       {
+               return set(signalNumber, false);
+       }
+
+       /**
+        * \brief Tests whether the bit is set.
+        *
+        * Similar to sigismember() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigismember.html#
+        *
+        * \param [in] signalNumber is the bit position that will be tested, [0; 31]
+        *
+        * \return pair with return code (0 on success, error code otherwise) and value of selected bit; error codes:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       std::pair<int, bool> test(uint8_t signalNumber) const;
+
+private:
+
+       /**
+        * \brief Sets value of single bit.
+        *
+        * \param [in] signalNumber is the bit position that will be modified, [0; 31]
+        * \param [in] value is the new value for selected bit
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       int set(uint8_t signalNumber, bool value);
+
+       /// internal bitset for 32 signals
+       Bitset bitset_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SIGNALSET_HPP_
diff --git a/include/distortos/SignalsCatcher.hpp b/include/distortos/SignalsCatcher.hpp
new file mode 100644 (file)
index 0000000..effaf73
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * \file
+ * \brief SignalsCatcher class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SIGNALSCATCHER_HPP_
+#define INCLUDE_DISTORTOS_SIGNALSCATCHER_HPP_
+
+#include "distortos/internal/synchronization/SignalsCatcherControlBlock.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class SignalsReceiverControlBlock;
+
+}      // namespace internal
+
+/// SignalsCatcher class is a container for internal::SignalsCatcherControlBlock
+class SignalsCatcher
+{
+       friend class internal::SignalsReceiverControlBlock;
+
+public:
+
+       /// import Storage type alias from internal::SignalsCatcherControlBlock
+       using Storage = internal::SignalsCatcherControlBlock::Storage;
+
+       /// import StorageUniquePointer type alias from internal::SignalsCatcherControlBlock
+       using StorageUniquePointer = internal::SignalsCatcherControlBlock::StorageUniquePointer;
+
+       /**
+        * \brief SignalsCatcher's constructor
+        *
+        * \param [in] storageUniquePointer is a rvalue reference to StorageUniquePointer with storage for
+        * internal::Association objects (sufficiently large for \a storageSize elements) and appropriate deleter
+        * \param [in] storageSize is the number of elements in \a storage array
+        */
+
+       SignalsCatcher(StorageUniquePointer&& storageUniquePointer, const size_t storageSize) :
+                       signalsCatcherControlBlock_{std::move(storageUniquePointer), storageSize}
+       {
+
+       }
+
+private:
+
+       /// contained internal::SignalsCatcherControlBlock object
+       internal::SignalsCatcherControlBlock signalsCatcherControlBlock_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SIGNALSCATCHER_HPP_
diff --git a/include/distortos/SignalsReceiver.hpp b/include/distortos/SignalsReceiver.hpp
new file mode 100644 (file)
index 0000000..fa41cad
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * \file
+ * \brief SignalsReceiver class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SIGNALSRECEIVER_HPP_
+#define INCLUDE_DISTORTOS_SIGNALSRECEIVER_HPP_
+
+#include "distortos/internal/synchronization/SignalsReceiverControlBlock.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class ThreadControlBlock;
+
+}      // namespace internal
+
+/// SignalsReceiver class is a container for internal::SignalsReceiverControlBlock
+class SignalsReceiver
+{
+       friend class internal::ThreadControlBlock;
+
+public:
+
+       /**
+        * \brief SignalsReceiver's constructor
+        *
+        * \param [in] signalInformationQueueWrapper is a pointer to SignalInformationQueueWrapper for this receiver,
+        * nullptr to disable queuing of signals for this receiver
+        * \param [in] signalsCatcher is a pointer to SignalsCatcher for this receiver, nullptr if this receiver cannot
+        * catch/handle signals
+        */
+
+       explicit SignalsReceiver(SignalInformationQueueWrapper* const signalInformationQueueWrapper,
+                       SignalsCatcher* const signalsCatcher) :
+                       signalsReceiverControlBlock_{signalInformationQueueWrapper, signalsCatcher}
+       {
+
+       }
+
+private:
+
+       /// contained internal::SignalsReceiverControlBlock object
+       internal::SignalsReceiverControlBlock signalsReceiverControlBlock_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SIGNALSRECEIVER_HPP_
diff --git a/include/distortos/SoftwareTimer.hpp b/include/distortos/SoftwareTimer.hpp
new file mode 100644 (file)
index 0000000..c10060c
--- /dev/null
@@ -0,0 +1,130 @@
+/**
+ * \file
+ * \brief SoftwareTimer class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SOFTWARETIMER_HPP_
+#define INCLUDE_DISTORTOS_SOFTWARETIMER_HPP_
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief SoftwareTimer class is an abstract interface for software timers
+ *
+ * \ingroup softwareTimers
+ */
+
+class SoftwareTimer
+{
+public:
+
+       /**
+        * \brief SoftwareTimer's destructor
+        */
+
+       virtual ~SoftwareTimer() = 0;
+
+       /**
+        * \return true if the timer is running, false otherwise
+        */
+
+       virtual bool isRunning() const = 0;
+
+       /**
+        * \brief Starts the timer.
+        *
+        * \note The duration will never be shorter, so one additional tick is always added to the duration.
+        *
+        * \param [in] duration is the duration after which the function will be executed
+        *
+        * \return 0 on success, error code otherwise
+        */
+
+       int start(TickClock::duration duration);
+
+       /**
+        * \brief Starts the timer.
+        *
+        * \note The duration must not be shorter, so one additional tick is always added to the duration.
+        *
+        * \tparam Rep is type of tick counter
+        * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+        *
+        * \param [in] duration is the duration after which the function will be executed
+        *
+        * \return 0 on success, error code otherwise
+        */
+
+       template<typename Rep, typename Period>
+       int start(const std::chrono::duration<Rep, Period> duration)
+       {
+               return start(std::chrono::duration_cast<TickClock::duration>(duration));
+       }
+
+       /**
+        * \brief Starts the timer.
+        *
+        * \param [in] timePoint is the time point at which the function will be executed
+        *
+        * \return 0 on success, error code otherwise
+        */
+
+       virtual int start(TickClock::time_point timePoint) = 0;
+
+       /**
+        * \brief Starts the timer.
+        *
+        * \tparam Duration is a std::chrono::duration type used to measure duration
+        *
+        * \param [in] timePoint is the time point at which the function will be executed
+        *
+        * \return 0 on success, error code otherwise
+        */
+
+       template<typename Duration>
+       int start(const std::chrono::time_point<TickClock, Duration> timePoint)
+       {
+               return start(std::chrono::time_point_cast<TickClock::duration>(timePoint));
+       }
+
+       /**
+        * \brief Stops the timer.
+        *
+        * \return 0 on success, error code otherwise
+        */
+
+       virtual int stop() = 0;
+
+protected:
+
+       /**
+        * \brief Software timer's function runner
+        *
+        * \param [in] softwareTimer is a reference to SoftwareTimer object that is being run
+        */
+
+       static void softwareTimerRunner(SoftwareTimer& softwareTimer);
+
+private:
+
+       /**
+        * \brief "Run" function of software timer
+        *
+        * This should be overridden by derived classes.
+        */
+
+       virtual void run() = 0;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SOFTWARETIMER_HPP_
diff --git a/include/distortos/SoftwareTimerCommon.hpp b/include/distortos/SoftwareTimerCommon.hpp
new file mode 100644 (file)
index 0000000..636a264
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * \file
+ * \brief SoftwareTimerCommon class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_SOFTWARETIMERCOMMON_HPP_
+#define INCLUDE_DISTORTOS_SOFTWARETIMERCOMMON_HPP_
+
+#include "distortos/SoftwareTimer.hpp"
+
+#include "distortos/internal/scheduler/SoftwareTimerControlBlock.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief SoftwareTimerCommon class implements common functionality of software timers
+ *
+ * \ingroup softwareTimers
+ */
+
+class SoftwareTimerCommon : public SoftwareTimer
+{
+public:
+
+       /**
+        * \brief SoftwareTimerCommon's constructor
+        */
+
+       constexpr SoftwareTimerCommon() :
+                       softwareTimerControlBlock_{softwareTimerRunner, *this}
+       {
+
+       }
+
+       /**
+        * \brief SoftwareTimerCommon's destructor
+        */
+
+       ~SoftwareTimerCommon() override;
+
+       /**
+        * \return true if the timer is running, false otherwise
+        */
+
+       bool isRunning() const override;
+
+       /**
+        * \brief Starts the timer.
+        *
+        * \param [in] timePoint is the time point at which the function will be executed
+        *
+        * \return 0 on success, error code otherwise
+        */
+
+       int start(TickClock::time_point timePoint) override;
+
+       using SoftwareTimer::start;
+
+       /**
+        * \brief Stops the timer.
+        *
+        * \return 0 on success, error code otherwise
+        */
+
+       int stop() override;
+
+       SoftwareTimerCommon(const SoftwareTimerCommon&) = delete;
+       SoftwareTimerCommon(SoftwareTimerCommon&&) = default;
+       const SoftwareTimerCommon& operator=(const SoftwareTimerCommon&) = delete;
+       SoftwareTimerCommon& operator=(SoftwareTimerCommon&&) = delete;
+
+private:
+
+       /// internal SoftwareTimerControlBlock object
+       internal::SoftwareTimerControlBlock softwareTimerControlBlock_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SOFTWARETIMERCOMMON_HPP_
diff --git a/include/distortos/StaticFifoQueue.hpp b/include/distortos/StaticFifoQueue.hpp
new file mode 100644 (file)
index 0000000..63bb636
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * \file
+ * \brief StaticFifoQueue class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_
+#define INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_
+
+#include "FifoQueue.hpp"
+
+#include "distortos/internal/memory/dummyDeleter.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief StaticFifoQueue class is a variant of FifoQueue that has automatic storage for queue's contents.
+ *
+ * \tparam T is the type of data in queue
+ * \tparam QueueSize is the maximum number of elements in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T, size_t QueueSize>
+class StaticFifoQueue : public FifoQueue<T>
+{
+public:
+
+       /// import Storage type from base class
+       using typename FifoQueue<T>::Storage;
+
+       /**
+        * \brief StaticFifoQueue's constructor
+        */
+
+       explicit StaticFifoQueue() :
+                       FifoQueue<T>{{storage_.data(), internal::dummyDeleter<Storage>}, storage_.size()}
+       {
+
+       }
+
+private:
+
+       /// storage for queue's contents
+       std::array<Storage, QueueSize> storage_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_
diff --git a/include/distortos/StaticMessageQueue.hpp b/include/distortos/StaticMessageQueue.hpp
new file mode 100644 (file)
index 0000000..ed370d0
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * \file
+ * \brief StaticMessageQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_STATICMESSAGEQUEUE_HPP_
+#define INCLUDE_DISTORTOS_STATICMESSAGEQUEUE_HPP_
+
+#include "MessageQueue.hpp"
+
+#include "distortos/internal/memory/dummyDeleter.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief StaticMessageQueue class is a variant of MessageQueue that has automatic storage for queue's contents.
+ *
+ * \tparam T is the type of data in queue
+ * \tparam QueueSize is the maximum number of elements in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T, size_t QueueSize>
+class StaticMessageQueue : public MessageQueue<T>
+{
+public:
+
+       /// import EntryStorage type from base class
+       using typename MessageQueue<T>::EntryStorage;
+
+       /// import ValueStorage type from base class
+       using typename MessageQueue<T>::ValueStorage;
+
+       /**
+        * \brief StaticMessageQueue's constructor
+        */
+
+       explicit StaticMessageQueue() :
+                       MessageQueue<T>{{entryStorage_.data(), internal::dummyDeleter<EntryStorage>},
+                                       {valueStorage_.data(), internal::dummyDeleter<ValueStorage>}, valueStorage_.size()}
+       {
+
+       }
+
+private:
+
+       /// storage for queue's entries
+       std::array<EntryStorage, QueueSize> entryStorage_;
+
+       /// storage for queue's contents
+       std::array<ValueStorage, QueueSize> valueStorage_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_STATICMESSAGEQUEUE_HPP_
diff --git a/include/distortos/StaticRawFifoQueue.hpp b/include/distortos/StaticRawFifoQueue.hpp
new file mode 100644 (file)
index 0000000..a271020
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * \file
+ * \brief StaticRawFifoQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_STATICRAWFIFOQUEUE_HPP_
+#define INCLUDE_DISTORTOS_STATICRAWFIFOQUEUE_HPP_
+
+#include "RawFifoQueue.hpp"
+
+#include "distortos/internal/memory/dummyDeleter.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief StaticRawFifoQueue class is a variant of RawFifoQueue that has automatic storage for queue's contents.
+ *
+ * \tparam T is the type of data in queue
+ * \tparam QueueSize is the maximum number of elements in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T, size_t QueueSize>
+class StaticRawFifoQueue : public RawFifoQueue
+{
+public:
+
+       /// type of uninitialized storage for data
+       using Storage = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
+
+       /**
+        * \brief StaticRawFifoQueue's constructor
+        */
+
+       explicit StaticRawFifoQueue() :
+                       RawFifoQueue{{storage_.data(), internal::dummyDeleter<Storage>}, sizeof(*storage_.data()), storage_.size()}
+       {
+
+       }
+
+private:
+
+       /// storage for queue's contents
+       std::array<Storage, QueueSize> storage_;
+};
+
+/**
+ * \brief StaticRawFifoQueueFromSize type alias is a variant of StaticRawFifoQueue which uses size of element (instead
+ * of type) as template argument.
+ *
+ * \tparam ElementSize is the size of single queue element, bytes
+ * \tparam QueueSize is the maximum number of elements in queue
+ */
+
+template<size_t ElementSize, size_t QueueSize>
+using StaticRawFifoQueueFromSize =
+               StaticRawFifoQueue<typename std::aligned_storage<ElementSize, ElementSize>::type, QueueSize>;
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_STATICRAWFIFOQUEUE_HPP_
diff --git a/include/distortos/StaticRawMessageQueue.hpp b/include/distortos/StaticRawMessageQueue.hpp
new file mode 100644 (file)
index 0000000..8120d17
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+ * \file
+ * \brief StaticRawMessageQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_
+#define INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_
+
+#include "distortos/RawMessageQueue.hpp"
+
+#include "distortos/internal/memory/dummyDeleter.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief StaticRawMessageQueue class is a variant of RawMessageQueue that has automatic storage for queue's contents.
+ *
+ * \tparam T is the type of data in queue
+ * \tparam QueueSize is the maximum number of elements in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T, size_t QueueSize>
+class StaticRawMessageQueue : public RawMessageQueue
+{
+public:
+
+       /**
+        * \brief StaticRawMessageQueue's constructor
+        */
+
+       explicit StaticRawMessageQueue() :
+                       RawMessageQueue{{entryStorage_.data(), internal::dummyDeleter<EntryStorage>},
+                                       {valueStorage_.data(), internal::dummyDeleter<ValueStorage<T>>}, sizeof(*valueStorage_.data()),
+                                       valueStorage_.size()}
+       {
+
+       }
+
+private:
+
+       /// storage for queue's entries
+       std::array<EntryStorage, QueueSize> entryStorage_;
+
+       /// storage for queue's contents
+       std::array<ValueStorage<T>, QueueSize> valueStorage_;
+};
+
+/**
+ * \brief StaticRawMessageQueueFromSize type alias is a variant of StaticRawMessageQueue which uses size of element
+ * (instead of type) as template argument.
+ *
+ * \tparam ElementSize is the size of single queue element, bytes
+ * \tparam QueueSize is the maximum number of elements in queue
+ */
+
+template<size_t ElementSize, size_t QueueSize>
+using StaticRawMessageQueueFromSize =
+               StaticRawMessageQueue<typename std::aligned_storage<ElementSize, ElementSize>::type, QueueSize>;
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_
diff --git a/include/distortos/StaticSignalsReceiver.hpp b/include/distortos/StaticSignalsReceiver.hpp
new file mode 100644 (file)
index 0000000..a6894ab
--- /dev/null
@@ -0,0 +1,166 @@
+/**
+ * \file
+ * \brief StaticSignalsReceiver class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_STATICSIGNALSRECEIVER_HPP_
+#define INCLUDE_DISTORTOS_STATICSIGNALSRECEIVER_HPP_
+
+#include "distortos/SignalInformationQueueWrapper.hpp"
+#include "distortos/SignalsCatcher.hpp"
+#include "distortos/SignalsReceiver.hpp"
+
+#include "distortos/internal/memory/dummyDeleter.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief StaticSignalsReceiver class is a templated interface for SignalsReceiver that has automatic storage for queued
+ * signals and SignalAction associations required for catching signals.
+ *
+ * \tparam QueuedSignals is the max number of queued signals, 0 to disable queuing of signals for this receiver
+ * \tparam SignalActions is the max number of different SignalAction objects, 0 to disable catching of signals for this
+ * receiver
+ */
+
+template<size_t QueuedSignals, size_t SignalActions>
+class StaticSignalsReceiver : public SignalsReceiver
+{
+public:
+
+       /**
+        * \brief StaticSignalsReceiver's constructor
+        */
+
+       StaticSignalsReceiver() :
+                       SignalsReceiver{&signalInformationQueueWrapper_, &signalsCatcher_},
+                       signalInformationQueueWrapper_{{signalInformationQueueWrapperStorage_.data(),
+                                       internal::dummyDeleter<SignalInformationQueueWrapper::Storage>},
+                                       signalInformationQueueWrapperStorage_.size()},
+                       signalsCatcher_{{signalsCatcherStorage_.data(), internal::dummyDeleter<SignalsCatcher::Storage>},
+                                       signalsCatcherStorage_.size()}
+       {
+
+       }
+
+private:
+
+       /// storage for \a signalInformationQueueWrapper_
+       std::array<SignalInformationQueueWrapper::Storage, QueuedSignals> signalInformationQueueWrapperStorage_;
+
+       /// internal SignalInformationQueueWrapper object
+       SignalInformationQueueWrapper signalInformationQueueWrapper_;
+
+       /// storage for \a signalsCatcher_
+       std::array<SignalsCatcher::Storage, SignalActions> signalsCatcherStorage_;
+
+       /// internal SignalsCatcher object
+       SignalsCatcher signalsCatcher_;
+};
+
+/**
+ * \brief StaticSignalsReceiver class is a templated interface for SignalsReceiver that has automatic storage for queued
+ * signals and SignalAction associations required for catching signals.
+ *
+ * \tparam QueuedSignals is the max number of queued signals
+ *
+ * Specialization for receiver with enabled queuing (QueuedSignals != 0) and disabled catching (SignalActions == 0) of
+ * signals
+ */
+
+template<size_t QueuedSignals>
+class StaticSignalsReceiver<QueuedSignals, 0> : public SignalsReceiver
+{
+public:
+
+       /**
+        * \brief StaticSignalsReceiver's constructor
+        */
+
+       StaticSignalsReceiver() :
+                       SignalsReceiver{&signalInformationQueueWrapper_, nullptr},
+                       signalInformationQueueWrapper_{{signalInformationQueueWrapperStorage_.data(),
+                                       internal::dummyDeleter<SignalInformationQueueWrapper::Storage>},
+                                       signalInformationQueueWrapperStorage_.size()}
+       {
+
+       }
+
+private:
+
+       /// storage for \a signalInformationQueueWrapper_
+       std::array<SignalInformationQueueWrapper::Storage, QueuedSignals> signalInformationQueueWrapperStorage_;
+
+       /// internal SignalInformationQueueWrapper object
+       SignalInformationQueueWrapper signalInformationQueueWrapper_;
+};
+
+/**
+ * \brief StaticSignalsReceiver class is a templated interface for SignalsReceiver that has automatic storage for queued
+ * signals and SignalAction associations required for catching signals.
+ *
+ * \tparam SignalActions is the max number of different SignalAction objects
+ *
+ * Specialization for receiver with disabled queuing (QueuedSignals == 0) and enabled catching (SignalActions != 0) of
+ * signals
+ */
+
+template<size_t SignalActions>
+class StaticSignalsReceiver<0, SignalActions> : public SignalsReceiver
+{
+public:
+
+       /**
+        * \brief StaticSignalsReceiver's constructor
+        */
+
+       StaticSignalsReceiver() :
+                       SignalsReceiver{nullptr, &signalsCatcher_},
+                       signalsCatcher_{{signalsCatcherStorage_.data(), internal::dummyDeleter<SignalsCatcher::Storage>},
+                                       signalsCatcherStorage_.size()}
+       {
+
+       }
+
+private:
+
+       /// storage for \a signalsCatcher_
+       std::array<SignalsCatcher::Storage, SignalActions> signalsCatcherStorage_;
+
+       /// internal SignalsCatcher object
+       SignalsCatcher signalsCatcher_;
+};
+
+/**
+ * \brief StaticSignalsReceiver class is a templated interface for SignalsReceiver that has automatic storage for queued
+ * signals and SignalAction associations required for catching signals.
+ *
+ * Specialization for receiver with disabled queuing (QueuedSignals == 0) and catching (SignalActions == 0) of signals
+ */
+
+template<>
+class StaticSignalsReceiver<0, 0> : public SignalsReceiver
+{
+public:
+
+       /**
+        * \brief StaticSignalsReceiver's constructor
+        */
+
+       StaticSignalsReceiver() :
+                       SignalsReceiver{nullptr, nullptr}
+       {
+
+       }
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_STATICSIGNALSRECEIVER_HPP_
diff --git a/include/distortos/StaticSoftwareTimer.hpp b/include/distortos/StaticSoftwareTimer.hpp
new file mode 100644 (file)
index 0000000..e1c27f7
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * \file
+ * \brief StaticSoftwareTimer class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_STATICSOFTWARETIMER_HPP_
+#define INCLUDE_DISTORTOS_STATICSOFTWARETIMER_HPP_
+
+#include "distortos/SoftwareTimerCommon.hpp"
+
+#include <functional>
+
+namespace distortos
+{
+
+/// \addtogroup softwareTimers
+/// \{
+
+/**
+ * \brief StaticSoftwareTimer class is a templated interface for software timer
+ *
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for function
+ */
+
+template<typename Function, typename... Args>
+class StaticSoftwareTimer : public SoftwareTimerCommon
+{
+public:
+
+       /**
+        * \brief StaticSoftwareTimer's constructor
+        *
+        * \param [in] function is a function that will be executed from interrupt context at a later time
+        * \param [in] args are arguments for function
+        */
+
+       StaticSoftwareTimer(Function&& function, Args&&... args) :
+                       SoftwareTimerCommon{},
+                       boundFunction_{std::bind(std::forward<Function>(function), std::forward<Args>(args)...)}
+       {
+
+       }
+
+private:
+
+       /**
+        * \brief "Run" function of software timer
+        *
+        * Executes bound function object.
+        */
+
+       void run() override
+       {
+               boundFunction_();
+       }
+
+       /// bound function object
+       decltype(std::bind(std::declval<Function>(), std::declval<Args>()...)) boundFunction_;
+};
+
+/**
+ * \brief Helper factory function to make StaticSoftwareTimer object with deduced template arguments
+ *
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for function
+ *
+ * \param [in] function is a function that will be executed from interrupt context at a later time
+ * \param [in] args are arguments for function
+ *
+ * \return StaticSoftwareTimer object with deduced template arguments
+ */
+
+template<typename Function, typename... Args>
+StaticSoftwareTimer<Function, Args...> makeStaticSoftwareTimer(Function&& function, Args&&... args)
+{
+       return {std::forward<Function>(function), std::forward<Args>(args)...};
+}
+
+/// \}
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_STATICSOFTWARETIMER_HPP_
diff --git a/include/distortos/StaticThread.hpp b/include/distortos/StaticThread.hpp
new file mode 100644 (file)
index 0000000..c135e55
--- /dev/null
@@ -0,0 +1,357 @@
+/**
+ * \file
+ * \brief StaticThread class header
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_STATICTHREAD_HPP_
+#define INCLUDE_DISTORTOS_STATICTHREAD_HPP_
+
+#include "distortos/StaticSignalsReceiver.hpp"
+#include "distortos/UndetachableThread.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * \brief StaticThreadBase class is a templated common base for StaticThread
+ *
+ * \tparam Function is the function that will be executed in separate thread
+ * \tparam Args are the arguments for \a Function
+ */
+
+template<typename Function, typename... Args>
+class StaticThreadBase : public UndetachableThread
+{
+public:
+
+       /// base of StaticThreadBase
+       using Base = UndetachableThread;
+
+       /**
+        * \brief StaticThreadBase's constructor
+        *
+        * \param [in] stackStorageUniquePointer is a rvalue reference to StackStorageUniquePointer with storage for stack
+        * (\a size bytes long) and appropriate deleter
+        * \param [in] size is the size of stack's storage, bytes
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicy is the scheduling policy of the thread
+        * \param [in] signalsReceiver is a pointer to SignalsReceiver object for this thread, nullptr to disable reception
+        * of signals for this thread
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for function
+        */
+
+       StaticThreadBase(StackStorageUniquePointer&& stackStorageUniquePointer, const size_t size, const uint8_t priority,
+                       const SchedulingPolicy schedulingPolicy, SignalsReceiver* const signalsReceiver, Function&& function,
+                       Args&&... args) :
+                                       Base{{std::move(stackStorageUniquePointer), size, *this, run, nullptr, terminationHook},
+                                                       priority, schedulingPolicy, nullptr, signalsReceiver},
+                                       boundFunction_{std::bind(std::forward<Function>(function), std::forward<Args>(args)...)}
+       {
+
+       }
+
+       StaticThreadBase(const StaticThreadBase&) = delete;
+       StaticThreadBase(StaticThreadBase&&) = default;
+       const StaticThreadBase& operator=(const StaticThreadBase&) = delete;
+       StaticThreadBase& operator=(StaticThreadBase&&) = delete;
+
+private:
+
+       /**
+        * \brief Thread's "run" function.
+        *
+        * Executes bound function object.
+        *
+        * \param [in] thread is a reference to Thread object, this must be StaticThreadBase!
+        */
+
+       static void run(Thread& thread)
+       {
+               static_cast<StaticThreadBase&>(thread).boundFunction_();
+       }
+
+       /// bound function object
+       decltype(std::bind(std::declval<Function>(), std::declval<Args>()...)) boundFunction_;
+};
+
+}      // namespace internal
+
+/// \addtogroup threads
+/// \{
+
+/**
+ * \brief StaticThread class is a templated interface for thread that has automatic storage for stack.
+ *
+ * \tparam StackSize is the size of stack, bytes
+ * \tparam CanReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this thread
+ * \tparam QueuedSignals is the max number of queued signals for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \tparam SignalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable catching of signals for this thread
+ * \tparam Function is the function that will be executed in separate thread
+ * \tparam Args are the arguments for \a Function
+ */
+
+template<size_t StackSize, bool CanReceiveSignals, size_t QueuedSignals, size_t SignalActions, typename Function,
+               typename... Args>
+class StaticThread : public internal::StaticThreadBase<Function, Args...>
+{
+public:
+
+       /// base of StaticThread
+       using Base = internal::StaticThreadBase<Function, Args...>;
+
+       /**
+        * \brief StaticThread's constructor
+        *
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicy is the scheduling policy of the thread
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for function
+        */
+
+       StaticThread(uint8_t priority, SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args);
+
+       /**
+        * \brief StaticThread's constructor
+        *
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for function
+        */
+
+       StaticThread(const uint8_t priority, Function&& function, Args&&... args) :
+                       StaticThread{priority, SchedulingPolicy::roundRobin, std::forward<Function>(function),
+                                       std::forward<Args>(args)...}
+       {
+
+       }
+
+       StaticThread(const StaticThread&) = delete;
+       StaticThread(StaticThread&&) = default;
+       const StaticThread& operator=(const StaticThread&) = delete;
+       StaticThread& operator=(StaticThread&&) = delete;
+
+private:
+
+       /// stack buffer
+       typename std::aligned_storage<StackSize>::type stack_;
+};
+
+/**
+ * \brief StaticThread class is a templated interface for thread that has automatic storage for stack and internal
+ * StaticSignalsReceiver object.
+ *
+ * Specialization for threads with enabled reception of signals (CanReceiveSignals == true)
+ *
+ * \tparam StackSize is the size of stack, bytes
+ * \tparam QueuedSignals is the max number of queued signals for this thread, 0 to disable queuing of signals for this
+ * thread
+ * \tparam SignalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable catching of signals for this thread
+ * \tparam Function is the function that will be executed in separate thread
+ * \tparam Args are the arguments for \a Function
+ */
+
+template<size_t StackSize, size_t QueuedSignals, size_t SignalActions, typename Function, typename... Args>
+class StaticThread<StackSize, true, QueuedSignals, SignalActions, Function, Args...> :
+               public internal::StaticThreadBase<Function, Args...>
+{
+public:
+
+       /// base of StaticThread
+       using Base = internal::StaticThreadBase<Function, Args...>;
+
+       /**
+        * \brief StaticThread's constructor
+        *
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicy is the scheduling policy of the thread
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for function
+        */
+
+       StaticThread(uint8_t priority, SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args);
+
+       /**
+        * \brief StaticThread's constructor
+        *
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for function
+        */
+
+       StaticThread(const uint8_t priority, Function&& function, Args&&... args) :
+                       StaticThread{priority, SchedulingPolicy::roundRobin, std::forward<Function>(function),
+                                       std::forward<Args>(args)...}
+       {
+
+       }
+
+       StaticThread(const StaticThread&) = delete;
+       StaticThread(StaticThread&&) = default;
+       const StaticThread& operator=(const StaticThread&) = delete;
+       StaticThread& operator=(StaticThread&&) = delete;
+
+private:
+
+       /// stack buffer
+       typename std::aligned_storage<StackSize>::type stack_;
+
+       /// internal StaticSignalsReceiver object
+       StaticSignalsReceiver<QueuedSignals, SignalActions> staticSignalsReceiver_;
+};
+
+/**
+ * \brief Helper factory function to make StaticThread object with partially deduced template arguments
+ *
+ * \tparam StackSize is the size of stack, bytes
+ * \tparam CanReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this thread
+ * \tparam QueuedSignals is the max number of queued signals for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \tparam SignalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable catching of signals for this thread
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+ * \param [in] schedulingPolicy is the scheduling policy of the thread
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for function
+ *
+ * \return StaticThread object with partially deduced template arguments
+ */
+
+template<size_t StackSize, bool CanReceiveSignals = {}, size_t QueuedSignals = {}, size_t SignalActions = {},
+               typename Function, typename... Args>
+StaticThread<StackSize, CanReceiveSignals, QueuedSignals, SignalActions, Function, Args...>
+makeStaticThread(const uint8_t priority, const SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args)
+{
+       return {priority, schedulingPolicy, std::forward<Function>(function), std::forward<Args>(args)...};
+}
+
+/**
+ * \brief Helper factory function to make StaticThread object with partially deduced template arguments
+ *
+ * \tparam StackSize is the size of stack, bytes
+ * \tparam CanReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this thread
+ * \tparam QueuedSignals is the max number of queued signals for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \tparam SignalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable catching of signals for this thread
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for function
+ *
+ * \return StaticThread object with partially deduced template arguments
+ */
+
+template<size_t StackSize, bool CanReceiveSignals = {}, size_t QueuedSignals = {}, size_t SignalActions = {},
+               typename Function, typename... Args>
+StaticThread<StackSize, CanReceiveSignals, QueuedSignals, SignalActions, Function, Args...>
+makeStaticThread(const uint8_t priority, Function&& function, Args&&... args)
+{
+       return {priority, std::forward<Function>(function), std::forward<Args>(args)...};
+}
+
+/**
+ * \brief Helper factory function to make and start StaticThread object with partially deduced template arguments
+ *
+ * \tparam StackSize is the size of stack, bytes
+ * \tparam CanReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this thread
+ * \tparam QueuedSignals is the max number of queued signals for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \tparam SignalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable catching of signals for this thread
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+ * \param [in] schedulingPolicy is the scheduling policy of the thread
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for function
+ *
+ * \return StaticThread object with partially deduced template arguments
+ */
+
+template<size_t StackSize, bool CanReceiveSignals = {}, size_t QueuedSignals = {}, size_t SignalActions = {},
+               typename Function, typename... Args>
+StaticThread<StackSize, CanReceiveSignals, QueuedSignals, SignalActions, Function, Args...>
+makeAndStartStaticThread(const uint8_t priority, const SchedulingPolicy schedulingPolicy, Function&& function,
+               Args&&... args)
+{
+       auto thread = makeStaticThread<StackSize, CanReceiveSignals, QueuedSignals, SignalActions>(priority,
+                       schedulingPolicy, std::forward<Function>(function), std::forward<Args>(args)...);
+       thread.start(); /// \todo make sure this never fails
+       return thread;
+}
+
+/**
+ * \brief Helper factory function to make and start StaticThread object with partially deduced template arguments
+ *
+ * \tparam StackSize is the size of stack, bytes
+ * \tparam CanReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this thread
+ * \tparam QueuedSignals is the max number of queued signals for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \tparam SignalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * CanReceiveSignals == true, 0 to disable catching of signals for this thread
+ * \tparam Function is the function that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for function
+ *
+ * \return StaticThread object with partially deduced template arguments
+ */
+
+template<size_t StackSize, bool CanReceiveSignals = {}, size_t QueuedSignals = {}, size_t SignalActions = {},
+               typename Function, typename... Args>
+StaticThread<StackSize, CanReceiveSignals, QueuedSignals, SignalActions, Function, Args...>
+makeAndStartStaticThread(const uint8_t priority, Function&& function, Args&&... args)
+{
+       auto thread = makeStaticThread<StackSize, CanReceiveSignals, QueuedSignals, SignalActions>(priority,
+                       std::forward<Function>(function), std::forward<Args>(args)...);
+       thread.start(); /// \todo make sure this never fails
+       return thread;
+}
+
+/// \}
+
+template<size_t StackSize, bool CanReceiveSignals, size_t QueuedSignals, size_t SignalActions, typename Function,
+               typename... Args>
+StaticThread<StackSize, CanReceiveSignals, QueuedSignals, SignalActions, Function, Args...>::
+StaticThread(const uint8_t priority, const SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args) :
+               Base{{&stack_, internal::dummyDeleter<decltype(stack_)>}, sizeof(stack_), priority, schedulingPolicy, nullptr,
+                               std::forward<Function>(function), std::forward<Args>(args)...}
+{
+
+}
+
+template<size_t StackSize, size_t QueuedSignals, size_t SignalActions, typename Function, typename... Args>
+StaticThread<StackSize, true, QueuedSignals, SignalActions, Function, Args...>::StaticThread(const uint8_t priority,
+               const SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args) :
+               Base{{&stack_, internal::dummyDeleter<decltype(stack_)>}, sizeof(stack_), priority, schedulingPolicy,
+                               &static_cast<SignalsReceiver&>(staticSignalsReceiver_), std::forward<Function>(function),
+                               std::forward<Args>(args)...},
+               staticSignalsReceiver_{}
+{
+
+}
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_STATICTHREAD_HPP_
diff --git a/include/distortos/ThisThread-Signals.hpp b/include/distortos/ThisThread-Signals.hpp
new file mode 100644 (file)
index 0000000..b0a808d
--- /dev/null
@@ -0,0 +1,279 @@
+/**
+ * \file
+ * \brief ThisThread::Signals namespace header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_THISTHREAD_SIGNALS_HPP_
+#define INCLUDE_DISTORTOS_THISTHREAD_SIGNALS_HPP_
+
+#include "distortos/SignalInformation.hpp"
+#include "distortos/TickClock.hpp"
+
+#include <utility>
+
+#include <cstdint>
+
+namespace distortos
+{
+
+class SignalAction;
+class SignalSet;
+
+namespace ThisThread
+{
+
+namespace Signals
+{
+
+/// \addtogroup signals
+/// \{
+
+/**
+ * \brief Generates signal for current thread.
+ *
+ * Similar to raise() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html
+ *
+ * Adds the signalNumber to set of pending signals of current thread.
+ *
+ * \param [in] signalNumber is the signal that will be generated, [0; 31]
+ *
+ * \return 0 on success, error code otherwise:
+ * - EINVAL - \a signalNumber value is invalid;
+ * - ENOTSUP - reception of signals is disabled for current thread;
+ */
+
+int generateSignal(uint8_t signalNumber);
+
+/**
+ * \brief Gets set of currently pending signals for current thread.
+ *
+ * Similar to sigpending() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html
+ *
+ * This function shall return the set of signals that are blocked from delivery and are pending on the current thread.
+ *
+ * \return set of currently pending signals for current thread
+ */
+
+SignalSet getPendingSignalSet();
+
+/**
+ * \brief Gets SignalAction associated with given signal number.
+ *
+ * Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
+ *
+ * \param [in] signalNumber is the signal for which the association is requested, [0; 31]
+ *
+ * \return pair with return code (0 on success, error code otherwise) and SignalAction that is associated with
+ * \a signalNumber, default-constructed object if no association was found;
+ * error codes:
+ * - EINVAL - \a signalNumber value is invalid;
+ * - ENOTSUP - reception or catching/handling of signals are disabled for current thread;
+ */
+
+std::pair<int, SignalAction> getSignalAction(uint8_t signalNumber);
+
+/**
+ * \brief Gets signal mask for current thread.
+ *
+ * Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
+ *
+ * \return SignalSet with signal mask for current thread
+ */
+
+SignalSet getSignalMask();
+
+/**
+ * \brief Queues signal for current thread.
+ *
+ * Similar to sigqueue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigqueue.html
+ *
+ * Adds the signalNumber and signal value (sigval union) to queue of SignalInformation objects.
+ *
+ * \param [in] signalNumber is the signal that will be queued, [0; 31]
+ * \param [in] value is the signal value
+ *
+ * \return 0 on success, error code otherwise:
+ * - EAGAIN - no resources are available to queue the signal, maximal number of signals is already queued in
+ * associated queue of SignalInformation objects;
+ * - EINVAL - \a signalNumber value is invalid;
+ * - ENOTSUP - reception or queuing of signals are disabled for current thread;
+ */
+
+int queueSignal(uint8_t signalNumber, sigval value);
+
+/**
+ * \brief Sets association for given signal number.
+ *
+ * Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
+ *
+ * \param [in] signalNumber is the signal for which the association will be set, [0; 31]
+ * \param [in] signalAction is a reference to SignalAction that will be associated with given signal number, object in
+ * internal storage is copy-constructed
+ *
+ * \return pair with return code (0 on success, error code otherwise) and SignalAction that was associated with
+ * \a signalNumber, default-constructed object if no association was found;
+ * error codes:
+ * - EAGAIN - no resources are available to associate \a signalNumber with \a signalAction;
+ * - EINVAL - \a signalNumber value is invalid;
+ * - ENOTSUP - reception or catching/handling of signals are disabled for current thread;
+ */
+
+std::pair<int, SignalAction> setSignalAction(uint8_t signalNumber, const SignalAction& signalAction);
+
+/**
+ * \brief Sets signal mask for current thread.
+ *
+ * Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
+ *
+ * \param [in] signalMask is the SignalSet with new signal mask for current thread
+ *
+ * \return 0 on success, error code otherwise:
+ * - ENOTSUP - reception or catching/handling of signals are disabled for current thread;
+ */
+
+int setSignalMask(SignalSet signalMask);
+
+/**
+ * \brief Tries to accept pending signals.
+ *
+ * Similar to sigtimedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html
+ *
+ * This function shall select the lowest pending signal from provided set, atomically clear it from current thread's set
+ * of pending signals and return that signal number. If no signal in provided set is pending at the time of the call,
+ * then this function shall return immediately with an error.
+ *
+ * \param [in] signalSet is a reference to set of signals that may be accepted
+ *
+ * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted signal;
+ * error codes:
+ * - EAGAIN - no signal specified by \a signalSet was pending;
+ * - ENOTSUP - reception of signals is disabled for current thread;
+ */
+
+std::pair<int, SignalInformation> tryWait(const SignalSet& signalSet);
+
+/**
+ * \brief Tries to wait for signals for given duration of time.
+ *
+ * Similar to sigtimedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html
+ *
+ * This function shall select the lowest pending signal from provided set, atomically clear it from current thread's set
+ * of pending signals and return that signal number. If no signal in provided set is pending at the time of the call,
+ * the thread shall be suspended until one or more becomes pending or until given duration of time expires.
+ *
+ * \param [in] signalSet is a reference to set of signals that will be waited for
+ * \param [in] duration is the duration after which the wait for signals will be terminated
+ *
+ * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted signal;
+ * error codes:
+ * - EINTR - the wait was interrupted by an unmasked, caught signal;
+ * - ENOTSUP - reception of signals is disabled for current thread;
+ * - ETIMEDOUT - no signal specified by \a signalSet was generated before the specified \a duration passed;
+ */
+
+std::pair<int, SignalInformation> tryWaitFor(const SignalSet& signalSet, TickClock::duration duration);
+
+/**
+ * \brief Tries to wait for signals for given duration of time.
+ *
+ * Template variant of tryWaitFor(const SignalSet&, TickClock::duration).
+ *
+ * \tparam Rep is type of tick counter
+ * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+ *
+ * \param [in] signalSet is a reference to set of signals that will be waited for
+ * \param [in] duration is the duration after which the wait for signals will be terminated
+ *
+ * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted signal;
+ * error codes:
+ * - EINTR - the wait was interrupted by an unmasked, caught signal;
+ * - ENOTSUP - reception of signals is disabled for current thread;
+ * - ETIMEDOUT - no signal specified by \a signalSet was generated before the specified \a duration passed;
+ */
+
+template<typename Rep, typename Period>
+std::pair<int, SignalInformation> tryWaitFor(const SignalSet& signalSet,
+               const std::chrono::duration<Rep, Period> duration)
+{
+       return tryWaitFor(signalSet, std::chrono::duration_cast<TickClock::duration>(duration));
+}
+
+/**
+ * \brief Tries to wait for signals until given time point.
+ *
+ * Similar to sigtimedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html
+ *
+ * This function shall select the lowest pending signal from provided set, atomically clear it from current thread's set
+ * of pending signals and return that signal number. If no signal in provided set is pending at the time of the call,
+ * the thread shall be suspended until one or more becomes pending or until given time point is reached
+ *
+ * \param [in] signalSet is a reference to set of signals that will be waited for
+ * \param [in] timePoint is the time point at which the wait for signals will be terminated
+ *
+ * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted signal;
+ * error codes:
+ * - EINTR - the wait was interrupted by an unmasked, caught signal;
+ * - ENOTSUP - reception of signals is disabled for current thread;
+ * - ETIMEDOUT - no signal specified by \a signalSet was generated before specified \a timePoint;
+ */
+
+std::pair<int, SignalInformation> tryWaitUntil(const SignalSet& signalSet, TickClock::time_point timePoint);
+
+/**
+ * \brief Tries to wait for signals until given time point.
+ *
+ * Template variant of tryWaitUntil(const SignalSet&, TickClock::time_point).
+ *
+ * \tparam Duration is a std::chrono::duration type used to measure duration
+ *
+ * \param [in] signalSet is a reference to set of signals that will be waited for
+ * \param [in] timePoint is the time point at which the wait for signals will be terminated
+ *
+ * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted signal;
+ * error codes:
+ * - EINTR - the wait was interrupted by an unmasked, caught signal;
+ * - ENOTSUP - reception of signals is disabled for current thread;
+ * - ETIMEDOUT - no signal specified by \a signalSet was generated before specified \a timePoint;
+ */
+
+template<typename Duration>
+std::pair<int, SignalInformation> tryWaitUntil(const SignalSet& signalSet,
+               const std::chrono::time_point<TickClock, Duration> timePoint)
+{
+       return tryWaitUntil(signalSet, std::chrono::time_point_cast<TickClock::duration>(timePoint));
+}
+
+/**
+ * \brief Waits for signals.
+ *
+ * Similar to sigwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigwait.html
+ *
+ * This function shall select the lowest pending signal from provided set, atomically clear it from current thread's set
+ * of pending signals and return that signal number. If no signal in provided set is pending at the time of the call,
+ * the thread shall be suspended until one or more becomes pending.
+ *
+ * \param [in] signalSet is a reference to set of signals that will be waited for
+ *
+ * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted signal;
+ * error codes:
+ * - EINTR - the wait was interrupted by an unmasked, caught signal;
+ * - ENOTSUP - reception of signals is disabled for current thread;
+ */
+
+std::pair<int, SignalInformation> wait(const SignalSet& signalSet);
+
+/// \}
+
+}      // namespace Signals
+
+}      // namespace ThisThread
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_THISTHREAD_SIGNALS_HPP_
diff --git a/include/distortos/ThisThread.hpp b/include/distortos/ThisThread.hpp
new file mode 100644 (file)
index 0000000..5528412
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+ * \file
+ * \brief ThisThread namespace header
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_THISTHREAD_HPP_
+#define INCLUDE_DISTORTOS_THISTHREAD_HPP_
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+class Thread;
+
+namespace ThisThread
+{
+
+/// \addtogroup threads
+/// \{
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+/**
+ * \brief Detaches calling (current) thread.
+ *
+ * Similar to std::thread::detach() - http://en.cppreference.com/w/cpp/thread/thread/detach
+ * Similar to POSIX pthread_detach() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_detach.html
+ *
+ * Detaches calling (current) thread from its Thread object, allowing execution to continue independently. All resources
+ * allocated for the thread will be deallocated when the thread terminates.
+ *
+ * \return 0 on success, error code otherwise:
+ * - EINVAL - current thread is already detached;
+ * - ENOTSUP - current thread cannot be detached;
+ */
+
+int detach();
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+/**
+ * \return reference to Thread object of currently active thread
+ */
+
+Thread& get();
+
+/**
+ * \return effective priority of calling (current) thread
+ */
+
+uint8_t getEffectivePriority();
+
+/**
+ * \return priority of calling (current) thread
+ */
+
+uint8_t getPriority();
+
+/**
+ * Changes priority of calling (current) thread.
+ *
+ * \param [in] priority is the new priority for thread
+ * \param [in] alwaysBehind selects the method of ordering when lowering the priority
+ * - false - the thread is moved to the head of the group of threads with the new priority (default),
+ * - true - the thread is moved to the tail of the group of threads with the new priority.
+ */
+
+void setPriority(uint8_t priority, bool alwaysBehind = {});
+
+/**
+ * \brief Makes the calling (current) thread sleep for at least given duration.
+ *
+ * Current thread's state is changed to "sleeping".
+ *
+ * \note To fulfill the "at least" requirement, one additional tick is always added to the sleep duration.
+ *
+ * \param [in] duration is the duration after which the thread will be woken
+ *
+ * \return 0 on success, error code otherwise:
+ * - EINTR - the sleep was interrupted by an unmasked, caught signal;
+ */
+
+int sleepFor(TickClock::duration duration);
+
+/**
+ * \brief Makes the calling (current) thread sleep for at least given duration.
+ *
+ * Current thread's state is changed to "sleeping".
+ *
+ * \note To fulfill the "at least" requirement, one additional tick is always added to the sleep duration.
+ *
+ * \tparam Rep is type of tick counter
+ * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+ *
+ * \param [in] duration is the duration after which the thread will be woken
+ *
+ * \return 0 on success, error code otherwise:
+ * - EINTR - the sleep was interrupted by an unmasked, caught signal;
+ */
+
+template<typename Rep, typename Period>
+int sleepFor(const std::chrono::duration<Rep, Period> duration)
+{
+       return sleepFor(std::chrono::duration_cast<TickClock::duration>(duration));
+}
+
+/**
+ * \brief Makes the calling (current) thread sleep until some time point is reached.
+ *
+ * Current thread's state is changed to "sleeping".
+ *
+ * \param [in] timePoint is the time point at which the thread will be woken
+ *
+ * \return 0 on success, error code otherwise:
+ * - EINTR - the sleep was interrupted by an unmasked, caught signal;
+ */
+
+int sleepUntil(TickClock::time_point timePoint);
+
+/**
+ * \brief Makes the calling (current) thread sleep until some time point is reached.
+ *
+ * Current thread's state is changed to "sleeping".
+ *
+ * \tparam Duration is a std::chrono::duration type used to measure duration
+ *
+ * \param [in] timePoint is the time point at which the thread will be woken
+ *
+ * \return 0 on success, error code otherwise:
+ * - EINTR - the sleep was interrupted by an unmasked, caught signal;
+ */
+
+template<typename Duration>
+int sleepUntil(const std::chrono::time_point<TickClock, Duration> timePoint)
+{
+       return sleepUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint));
+}
+
+/**
+ * \brief Yields time slot of the scheduler to next thread.
+ */
+
+void yield();
+
+/// \}
+
+}      // namespace ThisThread
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_THISTHREAD_HPP_
diff --git a/include/distortos/Thread.hpp b/include/distortos/Thread.hpp
new file mode 100644 (file)
index 0000000..54139c1
--- /dev/null
@@ -0,0 +1,194 @@
+/**
+ * \file
+ * \brief Thread class header
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_THREAD_HPP_
+#define INCLUDE_DISTORTOS_THREAD_HPP_
+
+#include "distortos/distortosConfiguration.h"
+
+#include "distortos/SchedulingPolicy.hpp"
+#include "distortos/SignalSet.hpp"
+#include "distortos/ThreadState.hpp"
+
+#include <csignal>
+
+namespace distortos
+{
+
+/**
+ * \brief Thread class is a pure abstract interface for threads
+ *
+ * \ingroup threads
+ */
+
+class Thread
+{
+public:
+
+       /**
+        * \brief Thread's destructor
+        */
+
+       virtual ~Thread() = 0;
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+       /**
+        * \brief Detaches the thread.
+        *
+        * Similar to std::thread::detach() - http://en.cppreference.com/w/cpp/thread/thread/detach
+        * Similar to POSIX pthread_detach() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_detach.html
+        *
+        * Detaches the executing thread from the Thread object, allowing execution to continue independently. All resources
+        * allocated for the thread will be deallocated when the thread terminates.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - this thread is already detached;
+        * - ENOTSUP - this thread cannot be detached;
+        */
+
+       virtual int detach() = 0;
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+       /**
+        * \brief Generates signal for thread.
+        *
+        * Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
+        *
+        * Adds the signalNumber to set of pending signals. If this thread is currently waiting for this signal, it will be
+        * unblocked.
+        *
+        * \param [in] signalNumber is the signal that will be generated, [0; 31]
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - reception of signals is disabled for this thread;
+        *
+        * \ingroup signals
+        */
+
+       virtual int generateSignal(uint8_t signalNumber) = 0;
+
+       /**
+        * \return effective priority of thread
+        */
+
+       virtual uint8_t getEffectivePriority() const = 0;
+
+       /**
+        * \brief Gets set of currently pending signals.
+        *
+        * Similar to sigpending() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html
+        *
+        * This function shall return the set of signals that are blocked from delivery and are pending on the thread.
+        *
+        * \return set of currently pending signals
+        *
+        * \ingroup signals
+        */
+
+       virtual SignalSet getPendingSignalSet() const = 0;
+
+       /**
+        * \return priority of thread
+        */
+
+       virtual uint8_t getPriority() const = 0;
+
+       /**
+        * \return scheduling policy of the thread
+        */
+
+       virtual SchedulingPolicy getSchedulingPolicy() const = 0;
+
+       /**
+        * \return current state of thread
+        */
+
+       virtual ThreadState getState() const = 0;
+
+       /**
+        * \brief Waits for thread termination.
+        *
+        * Similar to std::thread::join() - http://en.cppreference.com/w/cpp/thread/thread/join
+        * Similar to POSIX pthread_join() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html
+        *
+        * Blocks current thread until this thread finishes its execution. The results of multiple simultaneous calls to
+        * join() on the same target thread are undefined.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EDEADLK - deadlock condition was detected,
+        * - EINVAL - this thread is not joinable,
+        * - ...
+        *
+        * \ingroup synchronization
+        */
+
+       virtual int join() = 0;
+
+       /**
+        * \brief Queues signal for thread.
+        *
+        * Similar to sigqueue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigqueue.html
+        *
+        * Adds the signalNumber and signal value (sigval union) to queue of SignalInformation objects. If this thread is
+        * currently waiting for this signal, it will be unblocked.
+        *
+        * \param [in] signalNumber is the signal that will be queued, [0; 31]
+        * \param [in] value is the signal value
+        *
+        * \return 0 on success, error code otherwise:
+        * - EAGAIN - no resources are available to queue the signal, maximal number of signals is already queued in
+        * associated queue of SignalInformation objects;
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - reception or queuing of signals are disabled for this thread;
+        *
+        * \ingroup signals
+        */
+
+       virtual int queueSignal(uint8_t signalNumber, sigval value) = 0;
+
+       /**
+        * \brief Changes priority of thread.
+        *
+        * If the priority really changes, the position in the thread list is adjusted and context switch may be requested.
+        *
+        * \param [in] priority is the new priority of thread
+        * \param [in] alwaysBehind selects the method of ordering when lowering the priority
+        * - false - the thread is moved to the head of the group of threads with the new priority (default),
+        * - true - the thread is moved to the tail of the group of threads with the new priority.
+        */
+
+       virtual void setPriority(uint8_t priority, bool alwaysBehind = {}) = 0;
+
+       /**
+        * param [in] schedulingPolicy is the new scheduling policy of the thread
+        */
+
+       virtual void setSchedulingPolicy(SchedulingPolicy schedulingPolicy) = 0;
+
+       /**
+        * \brief Starts the thread.
+        *
+        * This operation can be performed on threads in "New" state only.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - thread is already started;
+        * - error codes returned by scheduler::Scheduler::add();
+        */
+
+       virtual int start() = 0;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_THREAD_HPP_
diff --git a/include/distortos/ThreadCommon.hpp b/include/distortos/ThreadCommon.hpp
new file mode 100644 (file)
index 0000000..8f34290
--- /dev/null
@@ -0,0 +1,230 @@
+/**
+ * \file
+ * \brief ThreadCommon class header
+ *
+ * \author Copyright (C) 2015-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_THREADCOMMON_HPP_
+#define INCLUDE_DISTORTOS_THREADCOMMON_HPP_
+
+#include "distortos/internal/scheduler/ThreadControlBlock.hpp"
+
+#include "distortos/Semaphore.hpp"
+#include "distortos/Thread.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief ThreadCommon class implements common functionality of threads
+ *
+ * \ingroup threads
+ */
+
+class ThreadCommon : public Thread
+{
+public:
+
+       /// unique_ptr (with deleter) to storage for stack
+       using StackStorageUniquePointer = architecture::Stack::StorageUniquePointer;
+
+       /**
+        * \brief ThreadCommon's constructor
+        *
+        * \param [in] stack is an rvalue reference to architecture::Stack object which will be adopted for this thread
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicy is the scheduling policy of the thread
+        * \param [in] threadGroupControlBlock is a pointer to internal::ThreadGroupControlBlock to which this object will
+        * be added, nullptr to inherit thread group from currently running thread
+        * \param [in] signalsReceiver is a pointer to SignalsReceiver object for this thread, nullptr to disable reception
+        * of signals for this thread
+        */
+
+       ThreadCommon(architecture::Stack&& stack, uint8_t priority, SchedulingPolicy schedulingPolicy,
+                       internal::ThreadGroupControlBlock* threadGroupControlBlock, SignalsReceiver* signalsReceiver);
+
+       /**
+        * \brief ThreadCommon's destructor
+        */
+
+       ~ThreadCommon() override;
+
+       /**
+        * \brief Generates signal for thread.
+        *
+        * Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
+        *
+        * Adds the signalNumber to set of pending signals. If this thread is currently waiting for this signal, it will be
+        * unblocked.
+        *
+        * \param [in] signalNumber is the signal that will be generated, [0; 31]
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - reception of signals is disabled for this thread;
+        *
+        * \ingroup signals
+        */
+
+       int generateSignal(uint8_t signalNumber) override;
+
+       /**
+        * \return effective priority of thread
+        */
+
+       uint8_t getEffectivePriority() const override;
+
+       /**
+        * \brief Gets set of currently pending signals.
+        *
+        * Similar to sigpending() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html
+        *
+        * This function shall return the set of signals that are blocked from delivery and are pending on the thread.
+        *
+        * \return set of currently pending signals
+        *
+        * \ingroup signals
+        */
+
+       SignalSet getPendingSignalSet() const override;
+
+       /**
+        * \return priority of thread
+        */
+
+       uint8_t getPriority() const override;
+
+       /**
+        * \return scheduling policy of the thread
+        */
+
+       SchedulingPolicy getSchedulingPolicy() const override;
+
+       /**
+        * \return current state of thread
+        */
+
+       ThreadState getState() const override;
+
+       /**
+        * \brief Waits for thread termination.
+        *
+        * Similar to std::thread::join() - http://en.cppreference.com/w/cpp/thread/thread/join
+        * Similar to POSIX pthread_join() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html
+        *
+        * Blocks current thread until this thread finishes its execution. The results of multiple simultaneous calls to
+        * join() on the same target thread are undefined.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EDEADLK - deadlock condition was detected,
+        * - EINVAL - this thread is not joinable,
+        * - ...
+        *
+        * \ingroup synchronization
+        */
+
+       int join() override;
+
+       /**
+        * \brief Queues signal for thread.
+        *
+        * Similar to sigqueue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigqueue.html
+        *
+        * Adds the signalNumber and signal value (sigval union) to queue of SignalInformation objects. If this thread is
+        * currently waiting for this signal, it will be unblocked.
+        *
+        * \param [in] signalNumber is the signal that will be queued, [0; 31]
+        * \param [in] value is the signal value
+        *
+        * \return 0 on success, error code otherwise:
+        * - EAGAIN - no resources are available to queue the signal, maximal number of signals is already queued in
+        * associated queue of SignalInformation objects;
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - reception or queuing of signals are disabled for this thread;
+        *
+        * \ingroup signals
+        */
+
+       int queueSignal(uint8_t signalNumber, sigval value) override;
+
+       /**
+        * \brief Changes priority of thread.
+        *
+        * If the priority really changes, the position in the thread list is adjusted and context switch may be requested.
+        *
+        * \param [in] priority is the new priority of thread
+        * \param [in] alwaysBehind selects the method of ordering when lowering the priority
+        * - false - the thread is moved to the head of the group of threads with the new priority (default),
+        * - true - the thread is moved to the tail of the group of threads with the new priority.
+        */
+
+       void setPriority(uint8_t priority, bool alwaysBehind = {}) override;
+
+       /**
+        * param [in] schedulingPolicy is the new scheduling policy of the thread
+        */
+
+       void setSchedulingPolicy(SchedulingPolicy schedulingPolicy) override;
+
+       /**
+        * \brief Starts the thread.
+        *
+        * This operation can be performed on threads in "New" state only.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - thread is already started;
+        * - error codes returned by internal::Scheduler::add();
+        */
+
+       int start() override;
+
+       ThreadCommon(const ThreadCommon&) = delete;
+       ThreadCommon(ThreadCommon&&) = default;
+       const ThreadCommon& operator=(const ThreadCommon&) = delete;
+       ThreadCommon& operator=(ThreadCommon&&) = delete;
+
+protected:
+
+       /**
+        * \return reference to internal ThreadControlBlock object
+        */
+
+       internal::ThreadControlBlock& getThreadControlBlock()
+       {
+               return threadControlBlock_;
+       }
+
+       /**
+        * \return const reference to internal ThreadControlBlock object
+        */
+
+       const internal::ThreadControlBlock& getThreadControlBlock() const
+       {
+               return threadControlBlock_;
+       }
+
+       /**
+        * \brief Termination hook function of thread
+        *
+        * \param [in] thread is a reference to Thread object, this must be ThreadCommon!
+        */
+
+       static void terminationHook(Thread& thread);
+
+private:
+
+       /// internal ThreadControlBlock object
+       internal::ThreadControlBlock threadControlBlock_;
+
+       /// semaphore used by join()
+       Semaphore joinSemaphore_;
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_THREADCOMMON_HPP_
diff --git a/include/distortos/ThreadState.hpp b/include/distortos/ThreadState.hpp
new file mode 100644 (file)
index 0000000..15a92e3
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * \file
+ * \brief ThreadState enum class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_THREADSTATE_HPP_
+#define INCLUDE_DISTORTOS_THREADSTATE_HPP_
+
+#include <cstdint>
+
+namespace distortos
+{
+
+/**
+ * \brief state of the thread
+ *
+ * \ingroup threads
+ */
+
+enum class ThreadState : uint8_t
+{
+       /// state in which thread is created, before being added to Scheduler
+       created,
+       /// thread is runnable
+       runnable,
+       /// thread is terminated
+       terminated,
+       /// thread is sleeping
+       sleeping,
+       /// thread is blocked on Semaphore
+       blockedOnSemaphore,
+       /// thread is suspended
+       suspended,
+       /// thread is blocked on Mutex
+       blockedOnMutex,
+       /// thread is blocked on ConditionVariable
+       blockedOnConditionVariable,
+       /// thread is waiting for signal
+       waitingForSignal,
+       /// thread is blocked on OnceFlag
+       blockedOnOnceFlag,
+       /// internal thread object was detached
+       detached,
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_THREADSTATE_HPP_
diff --git a/include/distortos/TickClock.hpp b/include/distortos/TickClock.hpp
new file mode 100644 (file)
index 0000000..7f1ace0
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * \file
+ * \brief TickClock class header
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_TICKCLOCK_HPP_
+#define INCLUDE_DISTORTOS_TICKCLOCK_HPP_
+
+#include "distortos/distortosConfiguration.h"
+
+#include <chrono>
+
+namespace distortos
+{
+
+/**
+ * \brief TickClock is a std::chrono clock, equivalent of std::chrono::steady_clock
+ *
+ * \ingroup clocks
+ */
+
+class TickClock
+{
+public:
+
+       /// type of tick counter
+       using rep = uint64_t;
+
+       /// std::ratio type representing the tick period of the clock, in seconds
+       using period = std::ratio<1, CONFIG_TICK_FREQUENCY>;
+
+       /// basic duration type of clock
+       using duration = std::chrono::duration<rep, period>;
+
+       /// basic time_point type of clock
+       using time_point = std::chrono::time_point<TickClock>;
+
+       /**
+        * \return time_point representing the current value of the clock
+        */
+
+       static time_point now();
+
+       /// this is a steady clock - it cannot be adjusted
+       static constexpr bool is_steady {true};
+};
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_TICKCLOCK_HPP_
diff --git a/include/distortos/UndetachableThread.hpp b/include/distortos/UndetachableThread.hpp
new file mode 100644 (file)
index 0000000..772b9aa
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * \file
+ * \brief UndetachableThread class header
+ *
+ * \author Copyright (C) 2015-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_UNDETACHABLETHREAD_HPP_
+#define INCLUDE_DISTORTOS_UNDETACHABLETHREAD_HPP_
+
+#include "distortos/ThreadCommon.hpp"
+
+namespace distortos
+{
+
+/**
+ * \brief UndetachableThread class is a ThreadCommon that cannot be detached
+ *
+ * \ingroup threads
+ */
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+class UndetachableThread : public ThreadCommon
+{
+public:
+
+       using ThreadCommon::ThreadCommon;
+
+       /**
+        * \brief Detaches the thread.
+        *
+        * Similar to std::thread::detach() - http://en.cppreference.com/w/cpp/thread/thread/detach
+        * Similar to POSIX pthread_detach() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_detach.html
+        *
+        * Detaches the executing thread from the Thread object, allowing execution to continue independently. All resources
+        * allocated for the thread will be deallocated when the thread terminates.
+        *
+        * \return ENOTSUP - this thread cannot be detached;
+        */
+
+       int detach() override;
+};
+
+#else  // !def CONFIG_THREAD_DETACH_ENABLE
+
+using UndetachableThread = ThreadCommon;
+
+#endif // !def CONFIG_THREAD_DETACH_ENABLE
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_UNDETACHABLETHREAD_HPP_
diff --git a/include/distortos/architecture/InterruptMaskingLock.hpp b/include/distortos/architecture/InterruptMaskingLock.hpp
new file mode 100644 (file)
index 0000000..6f8253b
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * \file
+ * \brief InterruptMaskingLock class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTMASKINGLOCK_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTMASKINGLOCK_HPP_
+
+#include "distortos/architecture/InterruptMaskingUnmaskingLock.hpp"
+#include "distortos/architecture/enableInterruptMasking.hpp"
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/// InterruptMaskingLock class is a RAII wrapper for enableInterruptMasking() / restoreInterruptMasking()
+class InterruptMaskingLock : private InterruptMaskingUnmaskingLock<enableInterruptMasking>
+{
+
+};
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTMASKINGLOCK_HPP_
diff --git a/include/distortos/architecture/InterruptMaskingUnmaskingLock.hpp b/include/distortos/architecture/InterruptMaskingUnmaskingLock.hpp
new file mode 100644 (file)
index 0000000..65bd0f0
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * \file
+ * \brief InterruptMaskingUnmaskingLock class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTMASKINGUNMASKINGLOCK_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTMASKINGUNMASKINGLOCK_HPP_
+
+#include "distortos/architecture/restoreInterruptMasking.hpp"
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/**
+ * \brief InterruptMaskingUnmaskingLock class is a RAII wrapper for interrupt mask manipulation.
+ *
+ * \tparam Function is a reference to function which modifies interrupt mask and returns InterruptMask;
+ * enableInterruptMasking() or disableInterruptMasking() should be used
+ */
+
+template<InterruptMask (& Function)()>
+class InterruptMaskingUnmaskingLock
+{
+public:
+
+       /**
+        * \brief InterruptMaskingUnmaskingLock's constructor
+        *
+        * Enables/disables interrupt masking, saving current interrupt mask for use in destructor.
+        */
+
+       InterruptMaskingUnmaskingLock() :
+                       interruptMask_{Function()}
+       {
+
+       }
+
+       /**
+        * \brief InterruptMaskingUnmaskingLock's destructor
+        *
+        * Restores previous interrupt masking state by restoring interrupt mask saved in constructor.
+        */
+
+       ~InterruptMaskingUnmaskingLock()
+       {
+               restoreInterruptMasking(interruptMask_);
+       }
+
+       InterruptMaskingUnmaskingLock(const InterruptMaskingUnmaskingLock&) = delete;
+       InterruptMaskingUnmaskingLock(InterruptMaskingUnmaskingLock&&) = delete;
+       InterruptMaskingUnmaskingLock& operator=(const InterruptMaskingUnmaskingLock&) = delete;
+       InterruptMaskingUnmaskingLock& operator=(InterruptMaskingUnmaskingLock&&) = delete;
+
+private:
+
+       /// interrupt mask
+       const InterruptMask interruptMask_;
+};
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTMASKINGUNMASKINGLOCK_HPP_
diff --git a/include/distortos/architecture/InterruptUnmaskingLock.hpp b/include/distortos/architecture/InterruptUnmaskingLock.hpp
new file mode 100644 (file)
index 0000000..263bbea
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * \file
+ * \brief InterruptUnmaskingLock class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTUNMASKINGLOCK_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTUNMASKINGLOCK_HPP_
+
+#include "distortos/architecture/InterruptMaskingUnmaskingLock.hpp"
+#include "distortos/architecture/disableInterruptMasking.hpp"
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/// InterruptUnmaskingLock class is a RAII wrapper for disableInterruptMasking() / restoreInterruptMasking()
+class InterruptUnmaskingLock : private InterruptMaskingUnmaskingLock<disableInterruptMasking>
+{
+
+};
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_INTERRUPTUNMASKINGLOCK_HPP_
diff --git a/include/distortos/architecture/Stack.hpp b/include/distortos/architecture/Stack.hpp
new file mode 100644 (file)
index 0000000..bd23452
--- /dev/null
@@ -0,0 +1,122 @@
+/**
+ * \file
+ * \brief Stack class header
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_STACK_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_STACK_HPP_
+
+#include <memory>
+
+namespace distortos
+{
+
+class Thread;
+
+namespace architecture
+{
+
+/// Stack class is an abstraction of architecture's stack
+class Stack
+{
+public:
+
+       /// unique_ptr (with deleter) to storage
+       using StorageUniquePointer = std::unique_ptr<void, void(&)(void*)>;
+
+       /**
+        * \brief Stack's constructor
+        *
+        * This function initializes valid architecture-specific stack in provided storage. This requires following steps:
+        * - adjustment of storage's address to suit architecture's alignment requirements,
+        * - adjustment of storage's size to suit architecture's divisibility requirements,
+        * - creating hardware and software stack frame in suitable place in the stack,
+        * - calculation of stack pointer register value.
+        *
+        * After this constructor completes, stack is ready for context switching.
+        *
+        * \param [in] storageUniquePointer is a rvalue reference to StorageUniquePointer with storage for stack (\a size
+        * bytes long) and appropriate deleter
+        * \param [in] size is the size of stack's storage, bytes
+        * \param [in] thread is a reference to Thread object passed to function
+        * \param [in] run is a reference to Thread's "run" function
+        * \param [in] preTerminationHook is a pointer to Thread's pre-termination hook, nullptr to skip
+        * \param [in] terminationHook is a reference to Thread's termination hook
+        */
+
+       Stack(StorageUniquePointer&& storageUniquePointer, size_t size, Thread& thread, void (& run)(Thread&),
+                       void (* preTerminationHook)(Thread&), void (& terminationHook)(Thread&));
+
+       /**
+        * \brief Stack's constructor
+        *
+        * This function adopts existing valid architecture-specific stack in provided storage. No adjustments are done,
+        * no stack frame is created and stack pointer register's value is not calculated.
+        *
+        * This is meant to adopt main()'s stack.
+        *
+        * \param [in] storage is a pointer to stack's storage
+        * \param [in] size is the size of stack's storage, bytes
+        */
+
+       Stack(void* storage, size_t size);
+
+       /**
+        * \brief Stack's destructor
+        */
+
+       ~Stack();
+
+       /**
+        * \brief Gets current value of stack pointer.
+        *
+        * \return current value of stack pointer
+        */
+
+       void* getStackPointer() const
+       {
+               return stackPointer_;
+       }
+
+       /**
+        * \brief Sets value of stack pointer.
+        *
+        * \param [in] stackPointer is the new value of stack pointer
+        */
+
+       void setStackPointer(void* const stackPointer)
+       {
+               stackPointer_ = stackPointer;
+       }
+
+       Stack(const Stack&) = delete;
+       Stack(Stack&&) = default;
+       const Stack& operator=(const Stack&) = delete;
+       Stack& operator=(Stack&&) = delete;
+
+private:
+
+       /// storage for stack
+       StorageUniquePointer storageUniquePointer_;
+
+       /// adjusted address of stack's storage
+       void* const adjustedStorage_;
+
+       /// adjusted size of stack's storage
+       const size_t adjustedSize_;
+
+       /// current value of stack pointer register
+       void* stackPointer_;
+};
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_STACK_HPP_
diff --git a/include/distortos/architecture/disableInterruptMasking.hpp b/include/distortos/architecture/disableInterruptMasking.hpp
new file mode 100644 (file)
index 0000000..d82eda1
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * \file
+ * \brief disableInterruptMasking() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_DISABLEINTERRUPTMASKING_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_DISABLEINTERRUPTMASKING_HPP_
+
+#include "distortos/architecture/parameters.hpp"
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/**
+ * \brief Disables interrupt masking.
+ *
+ * Enables normal-priority interrupts.
+ *
+ * \return previous value of interrupts' mask, must be used for matched restoreInterruptMasking() call
+ */
+
+InterruptMask disableInterruptMasking();
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_DISABLEINTERRUPTMASKING_HPP_
diff --git a/include/distortos/architecture/enableInterruptMasking.hpp b/include/distortos/architecture/enableInterruptMasking.hpp
new file mode 100644 (file)
index 0000000..8fb6566
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * \file
+ * \brief enableInterruptMasking() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_ENABLEINTERRUPTMASKING_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_ENABLEINTERRUPTMASKING_HPP_
+
+#include "distortos/architecture/parameters.hpp"
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/**
+ * \brief Enables interrupt masking.
+ *
+ * Disables normal-priority interrupts.
+ *
+ * \note High-priority interrupts are not controlled by distortos, so they may be left enabled. Support for that feature
+ * is architecture-dependent.
+ *
+ * \return previous value of interrupts' mask, must be used for matched restoreInterruptMasking() call
+ */
+
+InterruptMask enableInterruptMasking();
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_ENABLEINTERRUPTMASKING_HPP_
diff --git a/include/distortos/architecture/getMainStack.hpp b/include/distortos/architecture/getMainStack.hpp
new file mode 100644 (file)
index 0000000..6f75c2b
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * \file
+ * \brief getMainStack() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_GETMAINSTACK_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_GETMAINSTACK_HPP_
+
+#include <utility>
+
+#include <cstddef>
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/**
+ * \brief Gets the stack used to run main().
+ *
+ * \return beginning of stack and its size in bytes
+ */
+
+std::pair<void*, size_t> getMainStack();
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_GETMAINSTACK_HPP_
diff --git a/include/distortos/architecture/initializeStack.hpp b/include/distortos/architecture/initializeStack.hpp
new file mode 100644 (file)
index 0000000..6cc73ae
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * \file
+ * \brief initializeStack() declaration
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_INITIALIZESTACK_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_INITIALIZESTACK_HPP_
+
+#include <cstddef>
+
+namespace distortos
+{
+
+class Thread;
+
+namespace architecture
+{
+
+/**
+ * \brief Architecture-specific stack initialization.
+ *
+ * This function fills provided buffer with hardware and software stack frame and calculates value of stack pointer
+ * register. After this function completes, stack is ready for context switching.
+ *
+ * \attention buffer and size must be properly adjusted for architecture requirements
+ *
+ * \param [in] buffer is a pointer to stack's buffer
+ * \param [in] size is the size of stack's buffer, bytes
+ * \param [in] thread is a reference to Thread object passed to function
+ * \param [in] run is a reference to Thread's "run" function
+ * \param [in] preTerminationHook is a pointer to Thread's pre-termination hook, nullptr to skip
+ * \param [in] terminationHook is a reference to Thread's termination hook
+ *
+ * \return value that can be used as thread's stack pointer, ready for context switching
+ */
+
+void* initializeStack(void* buffer, size_t size, Thread& thread, void (& run)(Thread&),
+               void (* preTerminationHook)(Thread&), void (& terminationHook)(Thread&));
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_INITIALIZESTACK_HPP_
diff --git a/include/distortos/architecture/lowLevelInitialization.hpp b/include/distortos/architecture/lowLevelInitialization.hpp
new file mode 100644 (file)
index 0000000..4c9d3d2
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * \file
+ * \brief lowLevelInitialization() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_LOWLEVELINITIALIZATION_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_LOWLEVELINITIALIZATION_HPP_
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/**
+ * \brief Low level architecture initialization.
+ *
+ * This function is called before constructors for global and static objects from __libc_init_array() via address in
+ * distortosPreinitArray[].
+ */
+
+void lowLevelInitialization();
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_LOWLEVELINITIALIZATION_HPP_
diff --git a/include/distortos/architecture/requestContextSwitch.hpp b/include/distortos/architecture/requestContextSwitch.hpp
new file mode 100644 (file)
index 0000000..bc92b6b
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * \file
+ * \brief requestContextSwitch() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_REQUESTCONTEXTSWITCH_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_REQUESTCONTEXTSWITCH_HPP_
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/**
+ * \brief Architecture-specific request for context switch.
+ *
+ * Causes the architecture to do context save, call scheduler::getScheduler().switchContext() and do context restore.
+ * The call to scheduler::getScheduler().switchContext() must be done from the context in which such call is valid
+ * (usually system interrupt).
+ */
+
+void requestContextSwitch();
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_REQUESTCONTEXTSWITCH_HPP_
diff --git a/include/distortos/architecture/requestFunctionExecution.hpp b/include/distortos/architecture/requestFunctionExecution.hpp
new file mode 100644 (file)
index 0000000..69c9eda
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * \file
+ * \brief requestFunctionExecution() declaration
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_REQUESTFUNCTIONEXECUTION_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_REQUESTFUNCTIONEXECUTION_HPP_
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class ThreadControlBlock;
+
+}      // namespace internal
+
+namespace architecture
+{
+
+/**
+ * \brief Requests execution of provided function in the specified thread.
+ *
+ * Main use case for this function is to request execution of signals delivery function. In such case it is called when
+ * an unblocked signal, which is not ignored, is generated or queued for specified thread.
+ *
+ * It must arrange for given function to be executed in specified thread as soon as possible. This generally requires
+ * dealing with following scenarios:
+ * - current thread is sending the request to itself - in that case just execute function right away;
+ * - current thread is sending the request to non-current thread;
+ * - interrupt is sending the request to current thread;
+ * - interrupt is sending the request to non-current thread;
+ *
+ * \param [in] threadControlBlock is a reference to internal::ThreadControlBlock of thread in which \a function should
+ * be executed
+ * \param [in] function is a reference to function that should be executed in thread associated with
+ * \a threadControlBlock
+ */
+
+void requestFunctionExecution(internal::ThreadControlBlock& threadControlBlock, void (& function)());
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_REQUESTFUNCTIONEXECUTION_HPP_
diff --git a/include/distortos/architecture/restoreInterruptMasking.hpp b/include/distortos/architecture/restoreInterruptMasking.hpp
new file mode 100644 (file)
index 0000000..268159b
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * \file
+ * \brief restoreInterruptMasking() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_RESTOREINTERRUPTMASKING_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_RESTOREINTERRUPTMASKING_HPP_
+
+#include "distortos/architecture/parameters.hpp"
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/**
+ * \brief Restores interrupt masking.
+ *
+ * Restores previous interrupt masking state (before matching enableInterruptMasking() or disableInterruptMasking() was
+ * called), enabling some (maybe all, maybe none) interrupts.
+ *
+ * \param [in] interruptMask is the value of interrupts' mask, must come from previous call to enableInterruptMasking()
+ * or disableInterruptMasking()
+ */
+
+void restoreInterruptMasking(InterruptMask interruptMask);
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_RESTOREINTERRUPTMASKING_HPP_
diff --git a/include/distortos/architecture/startScheduling.hpp b/include/distortos/architecture/startScheduling.hpp
new file mode 100644 (file)
index 0000000..20db514
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * \file
+ * \brief startScheduling() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_ARCHITECTURE_STARTSCHEDULING_HPP_
+#define INCLUDE_DISTORTOS_ARCHITECTURE_STARTSCHEDULING_HPP_
+
+namespace distortos
+{
+
+namespace architecture
+{
+
+/**
+ * \brief Architecture-specific start of scheduling.
+ *
+ * Initializes all required hardware/software to perform context switching and starts the scheduling.
+ */
+
+void startScheduling();
+
+}      // namespace architecture
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_ARCHITECTURE_STARTSCHEDULING_HPP_
diff --git a/include/distortos/board/lowLevelInitialization.hpp b/include/distortos/board/lowLevelInitialization.hpp
new file mode 100644 (file)
index 0000000..6007422
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * \file
+ * \brief board::lowLevelInitialization() declaration
+ *
+ * \author Copyright (C) 2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_BOARD_LOWLEVELINITIALIZATION_HPP_
+#define INCLUDE_DISTORTOS_BOARD_LOWLEVELINITIALIZATION_HPP_
+
+namespace distortos
+{
+
+namespace board
+{
+
+/**
+ * \brief Low level board initialization.
+ *
+ * This function is called before constructors for global and static objects from __libc_init_array() via address in
+ * distortosPreinitArray[].
+ *
+ * \note Use of this function is optional - it may be left undefined, in which case it will not be called.
+ */
+
+void lowLevelInitialization() __attribute__ ((weak));
+
+}      // namespace board
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_BOARD_LOWLEVELINITIALIZATION_HPP_
diff --git a/include/distortos/callOnce.hpp b/include/distortos/callOnce.hpp
new file mode 100644 (file)
index 0000000..ed1cd1d
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * \file
+ * \brief callOnce() header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_CALLONCE_HPP_
+#define INCLUDE_DISTORTOS_CALLONCE_HPP_
+
+#include "distortos/OnceFlag.hpp"
+
+#if DISTORTOS_CALLONCE_SUPPORTED == 1 || DOXYGEN == 1
+
+namespace distortos
+{
+
+/**
+ * \brief Executes the callable object exactly once, even if called from multiple threads.
+ *
+ * Similar to std::call_once() - http://en.cppreference.com/w/cpp/thread/call_once
+ * Similar to POSIX pthread_once() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_once.html#
+ *
+ * \note This function requires GCC 4.9.
+ *
+ * \tparam Function is the function object that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] onceFlag is a reference to shared OnceFlag object
+ * \param [in] function is the function object that will be executed
+ * \param [in] args are arguments for \a function
+ *
+ * \ingroup synchronization
+ */
+
+template<typename Function, typename... Args>
+void callOnce(OnceFlag& onceFlag, Function&& function, Args&&... args)
+{
+       onceFlag.callOnceControlBlock_(std::forward<Function>(function), std::forward<Args>(args)...);
+}
+
+}      // namespace distortos
+
+#endif // DISTORTOS_CALLONCE_SUPPORTED == 1 || DOXYGEN == 1
+
+#endif // INCLUDE_DISTORTOS_CALLONCE_HPP_
diff --git a/include/distortos/chip/lowLevelInitialization.hpp b/include/distortos/chip/lowLevelInitialization.hpp
new file mode 100644 (file)
index 0000000..f9e28ac
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * \file
+ * \brief chip::lowLevelInitialization() declaration
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_CHIP_LOWLEVELINITIALIZATION_HPP_
+#define INCLUDE_DISTORTOS_CHIP_LOWLEVELINITIALIZATION_HPP_
+
+namespace distortos
+{
+
+namespace chip
+{
+
+/**
+ * \brief Low level chip initialization.
+ *
+ * This function is called before constructors for global and static objects from __libc_init_array() via address in
+ * distortosPreinitArray[].
+ */
+
+void lowLevelInitialization();
+
+}      // namespace chip
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_CHIP_LOWLEVELINITIALIZATION_HPP_
diff --git a/include/distortos/devices/io/InputPin.hpp b/include/distortos/devices/io/InputPin.hpp
new file mode 100644 (file)
index 0000000..9838998
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * \file
+ * \brief InputPin class header
+ *
+ * \author Copyright (C) 2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DEVICES_IO_INPUTPIN_HPP_
+#define INCLUDE_DISTORTOS_DEVICES_IO_INPUTPIN_HPP_
+
+namespace distortos
+{
+
+namespace devices
+{
+
+/**
+ * InputPin class is an interface for single input pin
+ *
+ * \ingroup devices
+ */
+
+class InputPin
+{
+public:
+
+       /**
+        * \brief InputPin's destructor
+        */
+
+       virtual ~InputPin() = 0;
+
+       /**
+        * \return current state of pin
+        */
+
+       virtual bool get() const = 0;
+};
+
+}      // namespace devices
+
+}      // namespace devices
+
+#endif // INCLUDE_DISTORTOS_DEVICES_IO_INPUTPIN_HPP_
diff --git a/include/distortos/devices/io/OutputPin.hpp b/include/distortos/devices/io/OutputPin.hpp
new file mode 100644 (file)
index 0000000..6651d9d
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * \file
+ * \brief OutputPin class header
+ *
+ * \author Copyright (C) 2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DEVICES_IO_OUTPUTPIN_HPP_
+#define INCLUDE_DISTORTOS_DEVICES_IO_OUTPUTPIN_HPP_
+
+#include "distortos/devices/io/InputPin.hpp"
+
+namespace distortos
+{
+
+namespace devices
+{
+
+/**
+ * OutputPin class is an interface for single output pin
+ *
+ * \ingroup devices
+ */
+
+class OutputPin : public InputPin
+{
+public:
+
+       /**
+        * \brief Sets state of pin.
+        *
+        * \param [in] state is the new state of pin
+        */
+
+       virtual void set(bool state) = 0;
+};
+
+}      // namespace devices
+
+}      // namespace devices
+
+#endif // INCLUDE_DISTORTOS_DEVICES_IO_OUTPUTPIN_HPP_
diff --git a/include/distortos/distortosVersion.h b/include/distortos/distortosVersion.h
new file mode 100644 (file)
index 0000000..554758d
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * \file
+ * \brief distortos version
+ *
+ * \author Copyright (C) 2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_DISTORTOSVERSION_H_
+#define INCLUDE_DISTORTOS_DISTORTOSVERSION_H_
+
+/// major version of distortos
+#define DISTORTOS_VERSION_MAJOR                0
+
+/// minor version of distortos
+#define DISTORTOS_VERSION_MINOR                2
+
+/// patch version of distortos
+#define DISTORTOS_VERSION_PATCH                0
+
+/// distortos version as a 32-bit variable
+#define DISTORTOS_VERSION      ((DISTORTOS_VERSION_MAJOR << 16) | (DISTORTOS_VERSION_MINOR << 8) | DISTORTOS_VERSION_PATCH)
+
+/// internals of STRINGIZE() macro
+#define STRINGIZE_INTERNAL(x)          #x
+
+/// macro used for stringification
+#define STRINGIZE(x)                           STRINGIZE_INTERNAL(x)
+
+/// distortos version as string
+#define DISTORTOS_VERSION_STRING       \
+               STRINGIZE(DISTORTOS_VERSION_MAJOR) "." STRINGIZE(DISTORTOS_VERSION_MINOR) "." STRINGIZE(DISTORTOS_VERSION_PATCH)
+
+#endif /* INCLUDE_DISTORTOS_DISTORTOSVERSION_H_ */
diff --git a/include/distortos/internal/memory/DeferredThreadDeleter.hpp b/include/distortos/internal/memory/DeferredThreadDeleter.hpp
new file mode 100644 (file)
index 0000000..bb38ebc
--- /dev/null
@@ -0,0 +1,121 @@
+/**
+ * \file
+ * \brief DeferredThreadDeleter class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_MEMORY_DEFERREDTHREADDELETER_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_MEMORY_DEFERREDTHREADDELETER_HPP_
+
+#include "distortos/distortosConfiguration.h"
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+#include "distortos/Mutex.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// DeferredThreadDeleter class can be used to defer deletion of dynamic detached threads
+class DeferredThreadDeleter
+{
+public:
+
+       /**
+        * \brief DeferredThreadDeleter's constructor
+        */
+
+       constexpr DeferredThreadDeleter() :
+                       list_{},
+                       mutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
+                       notEmpty_{}
+       {
+
+       }
+
+       /**
+        * \brief DeferredThreadDeleter's function call operator
+        *
+        * Adds thread to internal list of threads scheduled for deferred deletion and marks the list as "not empty".
+        *
+        * \note The object must be locked (with a successful call to DeferredThreadDeleter::lock()) before this function is
+        * used!
+        *
+        * \param [in] threadControlBlock is a reference to ThreadControlBlock object associated with dynamic and detached
+        * thread that has terminated its execution
+        *
+        * \return 0 on success, error code otherwise:
+        * - error codes returned by Mutex::unlock();
+        */
+
+       int operator()(ThreadControlBlock& threadControlBlock);
+
+       /**
+        * \brief Locks the object, preparing it for adding thread to internal list.
+        *
+        * Locks the mutex that synchronizes access to internal list. Locking (performed in this function) and unlocking
+        * (performed at the end of function call operator) are separated, because the locking must be done while the thread
+        * is still runnable, while the transfer to internal list is performed when the thread is not in this state.
+        *
+        * \note This function must be called before function call operator is used!
+        *
+        * \return 0 on success, error code otherwise:
+        * - error codes returned by Mutex::lock();
+        */
+
+       int lock();
+
+       /**
+        * \brief Tries to perform deferred deletion of threads.
+        *
+        * Does nothing is the list is not marked as "not empty". Otherwise this function first tries to lock following two
+        * mutexes:
+        * - mutex that protects dynamic memory allocator;
+        * - mutex that synchronizes access to list of threads scheduled for deferred deletion;
+        * If any Mutex::tryLock() call fails, this function just returns (unlocking any mutexes is necessary). Otherwise
+        * the threads are removed from the list and deleted, while the list's "not empty" marker is cleared.
+        *
+        * \return 0 on success, error code otherwise:
+        * - error codes returned by Mutex::tryLock();
+        * - error codes returned by Mutex::unlock();
+        */
+
+       int tryCleanup();
+
+private:
+
+       /**
+        * \brief Internals of tryCleanup().
+        *
+        * \return 0 on success, error code otherwise:
+        * - error codes returned by Mutex::tryLock();
+        * - error codes returned by Mutex::unlock();
+        */
+
+       int tryCleanupInternal();
+
+       /// list of threads scheduled for deferred deletion
+       ThreadList::UnsortedIntrusiveList list_;
+
+       /// mutex that synchronizes access to the \a list_
+       Mutex mutex_;
+
+       /// true if \a list_ is not empty, false otherwise
+       bool notEmpty_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_MEMORY_DEFERREDTHREADDELETER_HPP_
diff --git a/include/distortos/internal/memory/dummyDeleter.hpp b/include/distortos/internal/memory/dummyDeleter.hpp
new file mode 100644 (file)
index 0000000..3cee5cf
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * \file
+ * \brief dummyDeleter() declaration
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_MEMORY_DUMMYDELETER_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_MEMORY_DUMMYDELETER_HPP_
+
+#include <type_traits>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/*---------------------------------------------------------------------------------------------------------------------+
+| global functions' declarations
++---------------------------------------------------------------------------------------------------------------------*/
+
+/**
+ * \brief A "no-op" dummy deleter that can be used with std::unique_ptr and automatic storage that is trivially
+ * destructible.
+ *
+ * \tparam T is the real type of storage, must be trivially destructible
+ * \tparam U is the type of \a storage pointer
+ *
+ * \param [in] storage is a pointer to storage
+ */
+
+template<typename T, typename U>
+void dummyDeleter(U*)
+{
+       static_assert(std::is_trivially_destructible<T>::value == true,
+                       "internal::dummyDeleter() cannot be used with types that are not trivially destructible!");
+}
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_MEMORY_DUMMYDELETER_HPP_
diff --git a/include/distortos/internal/memory/getDeferredThreadDeleter.hpp b/include/distortos/internal/memory/getDeferredThreadDeleter.hpp
new file mode 100644 (file)
index 0000000..30fea99
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * \file
+ * \brief getDeferredThreadDeleter() declaration
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_MEMORY_GETDEFERREDTHREADDELETER_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_MEMORY_GETDEFERREDTHREADDELETER_HPP_
+
+#include "distortos/distortosConfiguration.h"
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class DeferredThreadDeleter;
+
+/**
+ * \return reference to main instance of DeferredThreadDeleter
+ */
+
+DeferredThreadDeleter& getDeferredThreadDeleter();
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_MEMORY_GETDEFERREDTHREADDELETER_HPP_
diff --git a/include/distortos/internal/memory/getMallocMutex.hpp b/include/distortos/internal/memory/getMallocMutex.hpp
new file mode 100644 (file)
index 0000000..0ba5621
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * \file
+ * \brief getMallocMutex() declaration
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_MEMORY_GETMALLOCMUTEX_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_MEMORY_GETMALLOCMUTEX_HPP_
+
+namespace distortos
+{
+
+class Mutex;
+
+namespace internal
+{
+
+/**
+ * \return reference to main instance of Mutex used for malloc() and free() locking
+ */
+
+Mutex& getMallocMutex();
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_MEMORY_GETMALLOCMUTEX_HPP_
diff --git a/include/distortos/internal/memory/storageDeleter.hpp b/include/distortos/internal/memory/storageDeleter.hpp
new file mode 100644 (file)
index 0000000..da7173f
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * \file
+ * \brief storageDeleter() definition
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_MEMORY_STORAGEDELETER_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_MEMORY_STORAGEDELETER_HPP_
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/*---------------------------------------------------------------------------------------------------------------------+
+| global functions' declarations
++---------------------------------------------------------------------------------------------------------------------*/
+
+/**
+ * \brief Templated deleter that can be used with std::unique_ptr and dynamic storage allocated with new T[].
+ *
+ * \tparam T is the real type of allocated storage
+ * \tparam U is the type of \a storage pointer
+ *
+ * \param [in] storage is a pointer to storage that will be deleted
+ */
+
+template<typename T, typename U>
+void storageDeleter(U* const storage)
+{
+       delete[] reinterpret_cast<T*>(storage);
+}
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_MEMORY_STORAGEDELETER_HPP_
diff --git a/include/distortos/internal/scheduler/DynamicThreadBase.hpp b/include/distortos/internal/scheduler/DynamicThreadBase.hpp
new file mode 100644 (file)
index 0000000..5ca3ff8
--- /dev/null
@@ -0,0 +1,231 @@
+/**
+ * \file
+ * \brief DynamicThreadBase class header
+ *
+ * \author Copyright (C) 2015-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_DYNAMICTHREADBASE_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_DYNAMICTHREADBASE_HPP_
+
+#include "distortos/DynamicSignalsReceiver.hpp"
+#include "distortos/DynamicThreadParameters.hpp"
+#include "distortos/ThreadCommon.hpp"
+
+#include "distortos/internal/memory/storageDeleter.hpp"
+
+namespace distortos
+{
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+class DynamicThread;
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+namespace internal
+{
+
+/**
+ * \brief DynamicThreadBase class is a type-erased interface for thread that has dynamic storage for bounded function,
+ * stack and internal DynamicSignalsReceiver object.
+ *
+ * If thread detachment is enabled (CONFIG_THREAD_DETACH_ENABLE is defined) then this class is dynamically allocated by
+ * DynamicThread - which allows it to be "detached". Otherwise - if thread detachment is disabled
+ * (CONFIG_THREAD_DETACH_ENABLE is not defined) - DynamicThread just inherits from this class.
+ */
+
+class DynamicThreadBase : public ThreadCommon
+{
+public:
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+       /**
+        * \brief DynamicThreadBase's constructor
+        *
+        * \tparam Function is the function that will be executed in separate thread
+        * \tparam Args are the arguments for \a Function
+        *
+        * \param [in] stackSize is the size of stack, bytes
+        * \param [in] canReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this
+        * thread
+        * \param [in] queuedSignals is the max number of queued signals for this thread, relevant only if
+        * \a canReceiveSignals == true, 0 to disable queuing of signals for this thread
+        * \param [in] signalActions is the max number of different SignalAction objects for this thread, relevant only if
+        * \a canReceiveSignals == true, 0 to disable catching of signals for this thread
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicy is the scheduling policy of the thread
+        * \param [in] owner is a reference to owner DynamicThread object
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for \a function
+        */
+
+       template<typename Function, typename... Args>
+       DynamicThreadBase(size_t stackSize, bool canReceiveSignals, size_t queuedSignals, size_t signalActions,
+                       uint8_t priority, SchedulingPolicy schedulingPolicy, DynamicThread& owner, Function&& function,
+                       Args&&... args);
+
+       /**
+        * \brief Detaches the thread.
+        *
+        * Similar to std::thread::detach() - http://en.cppreference.com/w/cpp/thread/thread/detach
+        * Similar to POSIX pthread_detach() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_detach.html
+        *
+        * Detaches the executing thread from the Thread object, allowing execution to continue independently. All resources
+        * allocated for the thread will be deallocated when the thread terminates.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - this thread is already detached;
+        */
+
+       int detach() override;
+
+#else  // !def CONFIG_THREAD_DETACH_ENABLE
+
+       /**
+        * \brief DynamicThreadBase's constructor
+        *
+        * \tparam Function is the function that will be executed in separate thread
+        * \tparam Args are the arguments for \a Function
+        *
+        * \param [in] stackSize is the size of stack, bytes
+        * \param [in] canReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this
+        * thread
+        * \param [in] queuedSignals is the max number of queued signals for this thread, relevant only if
+        * \a canReceiveSignals == true, 0 to disable queuing of signals for this thread
+        * \param [in] signalActions is the max number of different SignalAction objects for this thread, relevant only if
+        * \a canReceiveSignals == true, 0 to disable catching of signals for this thread
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicy is the scheduling policy of the thread
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for \a function
+        */
+
+       template<typename Function, typename... Args>
+       DynamicThreadBase(size_t stackSize, bool canReceiveSignals, size_t queuedSignals, size_t signalActions,
+                       uint8_t priority, SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args);
+
+       /**
+        * \brief DynamicThreadBase's constructor
+        *
+        * \tparam Function is the function that will be executed in separate thread
+        * \tparam Args are the arguments for \a Function
+        *
+        * \param [in] parameters is a DynamicThreadParameters struct with thread parameters
+        * \param [in] function is a function that will be executed in separate thread
+        * \param [in] args are arguments for \a function
+        */
+
+       template<typename Function, typename... Args>
+       DynamicThreadBase(const DynamicThreadParameters parameters, Function&& function, Args&&... args) :
+                       DynamicThreadBase{parameters.stackSize, parameters.canReceiveSignals, parameters.queuedSignals,
+                                       parameters.signalActions, parameters.priority, parameters.schedulingPolicy,
+                                       std::forward<Function>(function), std::forward<Args>(args)...}
+       {
+
+       }
+
+#endif // !def CONFIG_THREAD_DETACH_ENABLE
+
+       DynamicThreadBase(const DynamicThreadBase&) = delete;
+       DynamicThreadBase(DynamicThreadBase&&) = default;
+       const DynamicThreadBase& operator=(const DynamicThreadBase&) = delete;
+       DynamicThreadBase& operator=(DynamicThreadBase&&) = delete;
+
+protected:
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+       /**
+        * \brief Pre-termination hook function of thread
+        *
+        * If thread is detached, locks object used for deferred deletion.
+        *
+        * \param [in] thread is a reference to Thread object, this must be DynamicThreadBase!
+        */
+
+       static void preTerminationHook(Thread& thread);
+
+       /**
+        * \brief Termination hook function of thread
+        *
+        * Calls ThreadCommon::terminationHook() and - if thread is detached - schedules itself for deferred deletion.
+        *
+        * \param [in] thread is a reference to Thread object, this must be DynamicThreadBase!
+        */
+
+       static void terminationHook(Thread& thread);
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+private:
+
+       /**
+        * \brief Thread's "run" function.
+        *
+        * Executes bound function object.
+        *
+        * \param [in] thread is a reference to Thread object, this must be DynamicThreadBase!
+        */
+
+       static void run(Thread& thread);
+
+       /// internal DynamicSignalsReceiver object
+       DynamicSignalsReceiver dynamicSignalsReceiver_;
+
+       /// bound function object
+       std::function<void()> boundFunction_;
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+       /// pointer to owner DynamicThread object, nullptr if thread is detached
+       DynamicThread* owner_;
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+};
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+template<typename Function, typename... Args>
+DynamicThreadBase::DynamicThreadBase(const size_t stackSize, const bool canReceiveSignals, const size_t queuedSignals,
+               const size_t signalActions, const uint8_t priority, const SchedulingPolicy schedulingPolicy,
+               DynamicThread& owner, Function&& function, Args&&... args) :
+                               ThreadCommon{{{new uint8_t[stackSize], storageDeleter<uint8_t>}, stackSize, *this, run,
+                                               preTerminationHook, terminationHook}, priority, schedulingPolicy, nullptr,
+                                               canReceiveSignals == true ? &dynamicSignalsReceiver_ : nullptr},
+                               dynamicSignalsReceiver_{canReceiveSignals == true ? queuedSignals : 0,
+                                               canReceiveSignals == true ? signalActions : 0},
+                               boundFunction_{std::bind(std::forward<Function>(function), std::forward<Args>(args)...)},
+                               owner_{&owner}
+{
+
+}
+
+#else  // !def CONFIG_THREAD_DETACH_ENABLE
+
+template<typename Function, typename... Args>
+DynamicThreadBase::DynamicThreadBase(const size_t stackSize, const bool canReceiveSignals, const size_t queuedSignals,
+               const size_t signalActions, const uint8_t priority, const SchedulingPolicy schedulingPolicy,
+               Function&& function, Args&&... args) :
+                               ThreadCommon{{{new uint8_t[stackSize], storageDeleter<uint8_t>}, stackSize, *this, run, nullptr,
+                                               terminationHook}, priority, schedulingPolicy, nullptr,
+                                               canReceiveSignals == true ? &dynamicSignalsReceiver_ : nullptr},
+                               dynamicSignalsReceiver_{canReceiveSignals == true ? queuedSignals : 0,
+                                               canReceiveSignals == true ? signalActions : 0},
+                               boundFunction_{std::bind(std::forward<Function>(function), std::forward<Args>(args)...)}
+{
+
+}
+
+#endif // !def CONFIG_THREAD_DETACH_ENABLE
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_DYNAMICTHREADBASE_HPP_
diff --git a/include/distortos/internal/scheduler/MainThread.hpp b/include/distortos/internal/scheduler/MainThread.hpp
new file mode 100644 (file)
index 0000000..2eadab6
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * \file
+ * \brief MainThread class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_MAINTHREAD_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_MAINTHREAD_HPP_
+
+#include "distortos/UndetachableThread.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// MainThread class is a Thread for main()
+class MainThread : public UndetachableThread
+{
+public:
+
+       /**
+        * \brief MainThread's constructor.
+        *
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] threadGroupControlBlock is a reference to ThreadGroupControlBlock to which this object will be added
+        * \param [in] signalsReceiver is a pointer to SignalsReceiver object for main thread, nullptr to disable reception
+        * of signals for main thread
+        */
+
+       MainThread(uint8_t priority, ThreadGroupControlBlock& threadGroupControlBlock, SignalsReceiver* signalsReceiver);
+
+       using UndetachableThread::getThreadControlBlock;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_MAINTHREAD_HPP_
diff --git a/include/distortos/internal/scheduler/RoundRobinQuantum.hpp b/include/distortos/internal/scheduler/RoundRobinQuantum.hpp
new file mode 100644 (file)
index 0000000..e0a443e
--- /dev/null
@@ -0,0 +1,123 @@
+/**
+ * \file
+ * \brief RoundRobinQuantum class header
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_ROUNDROBINQUANTUM_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_ROUNDROBINQUANTUM_HPP_
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// RoundRobinQuantum class is a quantum of time for round-robin scheduling
+class RoundRobinQuantum
+{
+public:
+
+       /// type of quantum counter
+       using Representation = uint8_t;
+
+       /// duration type used for quantum
+       using Duration = std::chrono::duration<Representation, TickClock::period>;
+
+       /**
+        * \return initial value for round-robin quantum
+        */
+
+       constexpr static Duration getInitial()
+       {
+               return Duration{quantumRawInitializer_};
+       }
+
+       /**
+        * \brief RoundRobinQuantum's constructor
+        *
+        * Initializes quantum value to initial value - just like after call to reset().
+        */
+
+       constexpr RoundRobinQuantum() :
+                       quantum_{getInitial()}
+       {
+
+       }
+
+       /**
+        * \brief Decrements round-robin's quantum.
+        *
+        * This function should be called from tick interrupt for the currently running thread. Underflow of quantum after
+        * this decrement is not possible.
+        *
+        * \note this function must be called with enabled interrupt masking
+        */
+
+       void decrement()
+       {
+               if (isZero() == false)
+                       --quantum_;
+       }
+
+       /**
+        * \brief Gets current value of round-robin's quantum.
+        *
+        * \return current value of round-robin's quantum of the thread
+        */
+
+       Duration get() const
+       {
+               return quantum_;
+       }
+
+       /**
+        * \brief Convenience function to test whether the quantum is already at 0.
+        *
+        * \return true if quantum is zero, false otherwise
+        */
+
+       bool isZero() const
+       {
+               return quantum_ == Duration{0};
+       }
+
+       /**
+        * \brief Resets value of round-robin's quantum.
+        *
+        * This function should be called from context switcher after selecting new task that will be run.
+        */
+
+       void reset()
+       {
+               quantum_ = getInitial();
+       }
+
+private:
+
+       static_assert(CONFIG_TICK_FREQUENCY > 0, "CONFIG_TICK_FREQUENCY must be positive and non-zero!");
+       static_assert(CONFIG_ROUND_ROBIN_FREQUENCY > 0, "CONFIG_ROUND_ROBIN_FREQUENCY must be positive and non-zero!");
+
+       /// raw initializer value for round-robin quantum, calculated with rounding to nearest
+       constexpr static auto quantumRawInitializer_ = (CONFIG_TICK_FREQUENCY + CONFIG_ROUND_ROBIN_FREQUENCY / 2) /
+                       CONFIG_ROUND_ROBIN_FREQUENCY;
+
+       static_assert(quantumRawInitializer_ > 0 || quantumRawInitializer_ <= UINT8_MAX,
+                       "CONFIG_TICK_FREQUENCY and CONFIG_ROUND_ROBIN_FREQUENCY values produce invalid round-robin quantum!");
+
+       /// round-robin quantum
+       Duration quantum_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_ROUNDROBINQUANTUM_HPP_
diff --git a/include/distortos/internal/scheduler/Scheduler.hpp b/include/distortos/internal/scheduler/Scheduler.hpp
new file mode 100644 (file)
index 0000000..42037f2
--- /dev/null
@@ -0,0 +1,351 @@
+/**
+ * \file
+ * \brief Scheduler class header
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SCHEDULER_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SCHEDULER_HPP_
+
+#include "distortos/internal/scheduler/ThreadControlBlock.hpp"
+#include "distortos/internal/scheduler/ThreadList.hpp"
+#include "distortos/internal/scheduler/SoftwareTimerSupervisor.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class MainThread;
+
+/// Scheduler class is a system's scheduler
+class Scheduler
+{
+public:
+
+       /**
+        * \brief Scheduler's constructor
+        */
+
+       constexpr Scheduler() :
+                       currentThreadControlBlock_{},
+                       runnableList_{},
+                       suspendedList_{},
+                       softwareTimerSupervisor_{},
+                       contextSwitchCount_{},
+                       tickCount_{}
+       {
+
+       }
+
+       /**
+        * \brief Adds new ThreadControlBlock to scheduler.
+        *
+        * ThreadControlBlock's state is changed to "runnable".
+        *
+        * \param [in] threadControlBlock is a reference to added ThreadControlBlock object
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - thread is already started;
+        * - error codes returned by Scheduler::addInternal();
+        */
+
+       int add(ThreadControlBlock& threadControlBlock);
+
+       /**
+        * \brief Blocks current thread, transferring it to provided container.
+        *
+        * \param [in] container is a reference to destination container to which the thread will be transferred
+        * \param [in] state is the new state of thread that will be blocked
+        * \param [in] unblockFunctor is a pointer to ThreadControlBlock::UnblockFunctor which will be executed in
+        * ThreadControlBlock::unblockHook(), default - nullptr (no functor will be executed)
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINTR - thread was unblocked with ThreadControlBlock::UnblockReason::signal;
+        * - ETIMEDOUT - thread was unblocked with ThreadControlBlock::UnblockReason::timeout;
+        */
+
+       int block(ThreadList& container, ThreadState state, const ThreadControlBlock::UnblockFunctor* unblockFunctor = {});
+
+       /**
+        * \brief Blocks thread, transferring it to provided container.
+        *
+        * The thread must be on "runnable" list - trying to block thread in other state is an error.
+        *
+        * \param [in] container is a reference to destination container to which the thread will be transferred
+        * \param [in] iterator is the iterator to the thread that will be blocked
+        * \param [in] state is the new state of thread that will be blocked
+        * \param [in] unblockFunctor is a pointer to ThreadControlBlock::UnblockFunctor which will be executed in
+        * ThreadControlBlock::unblockHook(), default - nullptr (no functor will be executed)
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINTR - thread was unblocked with ThreadControlBlock::UnblockReason::signal (possible only when blocking
+        * current thread);
+        * - EINVAL - provided thread is not on "runnable" list;
+        * - ETIMEDOUT - thread was unblocked with ThreadControlBlock::UnblockReason::timeout (possible only when blocking
+        * current thread);
+        */
+
+       int block(ThreadList& container, ThreadList::iterator iterator, ThreadState state,
+                       const ThreadControlBlock::UnblockFunctor* unblockFunctor = {});
+
+       /**
+        * \brief Blocks current thread with timeout, transferring it to provided container.
+        *
+        * \param [in] container is a reference to destination container to which the thread will be transferred
+        * \param [in] state is the new state of thread that will be blocked
+        * \param [in] timePoint is the time point at which the thread will be unblocked (if not already unblocked)
+        * \param [in] unblockFunctor is a pointer to ThreadControlBlock::UnblockFunctor which will be executed in
+        * ThreadControlBlock::unblockHook(), default - nullptr (no functor will be executed)
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINTR - thread was unblocked with ThreadControlBlock::UnblockReason::signal;
+        * - ETIMEDOUT - thread was unblocked because timePoint was reached;
+        */
+
+       int blockUntil(ThreadList& container, ThreadState state, TickClock::time_point timePoint,
+                       const ThreadControlBlock::UnblockFunctor* unblockFunctor = {});
+
+       /**
+        * \return number of context switches
+        */
+
+       uint64_t getContextSwitchCount() const;
+
+       /**
+        * \return reference to currently active ThreadControlBlock
+        */
+
+       ThreadControlBlock& getCurrentThreadControlBlock() const
+       {
+               return *currentThreadControlBlock_;
+       }
+
+       /**
+        * \return reference to internal SoftwareTimerSupervisor object
+        */
+
+       SoftwareTimerSupervisor& getSoftwareTimerSupervisor()
+       {
+               return softwareTimerSupervisor_;
+       }
+
+       /**
+        * \return const reference to internal SoftwareTimerSupervisor object
+        */
+
+       const SoftwareTimerSupervisor& getSoftwareTimerSupervisor() const
+       {
+               return softwareTimerSupervisor_;
+       }
+
+       /**
+        * \return current value of tick count
+        */
+
+       uint64_t getTickCount() const;
+
+       /**
+        * \brief Scheduler's initialization
+        *
+        * \attention This must be called after constructor, before enabling any scheduling. Priority of main thread must
+        * be higher than priority of idle thread
+        *
+        * \param [in] mainThread is a reference to main thread
+        *
+        * \return 0 on success, error code otherwise:
+        * - error codes returned by Scheduler::addInternal();
+        */
+
+       int initialize(MainThread& mainThread);
+
+       /**
+        * \brief Requests context switch if it is needed.
+        *
+        * \attention This function must be called with interrupt masking enabled.
+        */
+
+       void maybeRequestContextSwitch() const;
+
+       /**
+        * \brief Removes current thread from Scheduler's control.
+        *
+        * Thread's state is changed to "terminated".
+        *
+        * \note This function must be called with masked interrupts.
+        *
+        * \note This function can be used only after thread's function returns an all cleanup is done.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - provided thread is not on "runnable" list and cannot be removed/terminated;
+        */
+
+       int remove();
+
+       /**
+        * \brief Resumes suspended thread.
+        *
+        * The thread must be on the "suspended" list - trying to resume thread that is not suspended is an error.
+        *
+        * \param [in] iterator is the iterator to the thread that will be resumed
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - provided thread is not on "suspended" list;
+        */
+
+       int resume(ThreadList::iterator iterator);
+
+       /**
+        * \brief Suspends current thread.
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINTR - thread was unblocked with ThreadControlBlock::UnblockReason::signal;
+        */
+
+       int suspend();
+
+       /**
+        * \brief Suspends thread.
+        *
+        * The thread must be on "runnable" list - trying to suspend thread in other state is an error.
+        *
+        * \param [in] iterator is the iterator to the thread that will be suspended
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINTR - thread was unblocked with ThreadControlBlock::UnblockReason::signal;
+        * - EINVAL - provided thread is not on "runnable" list;
+        */
+
+       int suspend(ThreadList::iterator iterator);
+
+       /**
+        * \brief Called by architecture-specific code to do final context switch.
+        *
+        * Current task is suspended and the next available task is started.
+        *
+        * \param [in] stackPointer is the current value of current thread's stack pointer
+        *
+        * \return new thread's stack pointer
+        */
+
+       void* switchContext(void* stackPointer);
+
+       /**
+        * \brief Handler of "tick" interrupt.
+        *
+        * \note this must not be called by user code
+        *
+        * \return true if context switch is required, false otherwise
+        */
+
+       bool tickInterruptHandler();
+
+       /**
+        * \brief Unblocks provided thread, transferring it from it's current container to "runnable" container.
+        *
+        * Current container of the thread is obtained with ThreadControlBlock::getList().
+        *
+        * \param [in] iterator is the iterator which points to unblocked thread
+        * \param [in] unblockReason is the reason of unblocking of the thread, default -
+        * ThreadControlBlock::UnblockReason::unblockRequest
+        */
+
+       void unblock(ThreadList::iterator iterator,
+                       ThreadControlBlock::UnblockReason unblockReason = ThreadControlBlock::UnblockReason::unblockRequest);
+
+       /**
+        * \brief Yields time slot of the scheduler to next thread.
+        */
+
+       void yield();
+
+private:
+
+       /**
+        * \brief Adds new ThreadControlBlock to scheduler.
+        *
+        * Internal version - without interrupt masking and call to Scheduler::maybeRequestContextSwitch()
+        *
+        * \param [in] threadControlBlock is a reference to added ThreadControlBlock object
+        *
+        * \return 0 on success, error code otherwise:
+        * - error codes returned by ThreadControlBlock::addHook();
+        */
+
+       int addInternal(ThreadControlBlock& threadControlBlock);
+
+       /**
+        * \brief Blocks thread, transferring it to provided container.
+        *
+        * Internal version - without interrupt masking and forced context switch.
+        *
+        * \param [in] container is a reference to destination container to which the thread will be transferred
+        * \param [in] iterator is the iterator to the thread that will be blocked
+        * \param [in] state is the new state of thread that will be blocked
+        * \param [in] unblockFunctor is a pointer to ThreadControlBlock::UnblockFunctor which will be executed in
+        * ThreadControlBlock::unblockHook()
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - provided thread is not on "runnable" list;
+        */
+
+       int blockInternal(ThreadList& container, ThreadList::iterator iterator, ThreadState state,
+                       const ThreadControlBlock::UnblockFunctor* unblockFunctor);
+
+       /**
+        * \brief Tests whether context switch is required or not.
+        *
+        * Context switch is required in following situations:
+        * - current thread is no longer on "runnable" list,
+        * - current thread is no longer on the beginning of the "runnable" list (because higher-priority thread is
+        * available or current thread was "rotated" due to round-robin scheduling policy).
+        *
+        * \return true if context switch is required
+        */
+
+       bool isContextSwitchRequired() const;
+
+       /**
+        * \brief Unblocks provided thread, transferring it from it's current container to "runnable" container.
+        *
+        * Current container of the thread is obtained with ThreadControlBlock::getList(). Round-robin quantum of thread is
+        * reset.
+        *
+        * \note Internal version - without interrupt masking and yield()
+        *
+        * \param [in] iterator is the iterator which points to unblocked thread
+        * \param [in] unblockReason is the reason of unblocking of the thread
+        */
+
+       void unblockInternal(ThreadList::iterator iterator, ThreadControlBlock::UnblockReason unblockReason);
+
+       /// iterator to the currently active ThreadControlBlock
+       ThreadList::iterator currentThreadControlBlock_;
+
+       /// list of ThreadControlBlock elements in "runnable" state, sorted by priority in descending order
+       ThreadList runnableList_;
+
+       /// list of ThreadControlBlock elements in "suspended" state, sorted by priority in descending order
+       ThreadList suspendedList_;
+
+       /// internal SoftwareTimerSupervisor object
+       SoftwareTimerSupervisor softwareTimerSupervisor_;
+
+       /// number of context switches
+       uint64_t contextSwitchCount_;
+
+       /// tick count
+       uint64_t tickCount_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SCHEDULER_HPP_
diff --git a/include/distortos/internal/scheduler/SoftwareTimerControlBlock.hpp b/include/distortos/internal/scheduler/SoftwareTimerControlBlock.hpp
new file mode 100644 (file)
index 0000000..c020d35
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+ * \file
+ * \brief SoftwareTimerControlBlock class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERCONTROLBLOCK_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERCONTROLBLOCK_HPP_
+
+#include "distortos/internal/scheduler/SoftwareTimerListNode.hpp"
+
+namespace distortos
+{
+
+class SoftwareTimer;
+
+namespace internal
+{
+
+/// SoftwareTimerControlBlock class is a control block of software timer
+class SoftwareTimerControlBlock : public SoftwareTimerListNode
+{
+public:
+
+       /// type of runner for software timer's function
+       using FunctionRunner = void(SoftwareTimer&);
+
+       /**
+        * \brief SoftwareTimerControlBlock's constructor
+        *
+        * \param [in] functionRunner is a reference to runner for software timer's function
+        * \param [in] owner is a reference to SoftwareTimer object that owns this SoftwareTimerControlBlock
+        */
+
+       constexpr SoftwareTimerControlBlock(FunctionRunner& functionRunner, SoftwareTimer& owner) :
+                       SoftwareTimerListNode{},
+                       functionRunner_{functionRunner},
+                       owner_{owner}
+       {
+
+       }
+
+       /**
+        * \brief SoftwareTimerControlBlock's destructor
+        *
+        * If the timer is running it is stopped.
+        */
+
+       ~SoftwareTimerControlBlock()
+       {
+               stop();
+       }
+
+       /**
+        * \return true if the timer is running, false otherwise
+        */
+
+       bool isRunning() const
+       {
+               return node.isLinked();
+       }
+
+       /**
+        * \brief Runs software timer's function.
+        *
+        * \note this should only be called by SoftwareTimerSupervisor::tickInterruptHandler()
+        */
+
+       void run() const
+       {
+               functionRunner_(owner_);
+       }
+
+       /**
+        * \brief Starts the timer.
+        *
+        * \param [in] timePoint is the time point at which the function will be executed
+        */
+
+       void start(TickClock::time_point timePoint);
+
+       /**
+        * \brief Stops the timer.
+        */
+
+       void stop();
+
+       SoftwareTimerControlBlock(const SoftwareTimerControlBlock&) = delete;
+       SoftwareTimerControlBlock(SoftwareTimerControlBlock&&) = default;
+       const SoftwareTimerControlBlock& operator=(const SoftwareTimerControlBlock&) = delete;
+       SoftwareTimerControlBlock& operator=(SoftwareTimerControlBlock&&) = delete;
+
+private:
+
+       /// reference to runner for software timer's function
+       FunctionRunner& functionRunner_;
+
+       /// reference to SoftwareTimer object that owns this SoftwareTimerControlBlock
+       SoftwareTimer& owner_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERCONTROLBLOCK_HPP_
diff --git a/include/distortos/internal/scheduler/SoftwareTimerList.hpp b/include/distortos/internal/scheduler/SoftwareTimerList.hpp
new file mode 100644 (file)
index 0000000..5d38f47
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * \file
+ * \brief SoftwareTimerList class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERLIST_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERLIST_HPP_
+
+#include "distortos/internal/scheduler/SoftwareTimerListNode.hpp"
+
+#include "estd/SortedIntrusiveList.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class SoftwareTimerControlBlock;
+
+/// functor which gives ascending expiration time point order of elements on the list
+struct SoftwareTimerAscendingTimePoint
+{
+       /**
+        * \brief SoftwareTimerAscendingTimePoint's constructor
+        */
+
+       constexpr SoftwareTimerAscendingTimePoint()
+       {
+
+       }
+
+       /**
+        * \brief SoftwareTimerAscendingTimePoint's function call operator
+        *
+        * \param [in] left is the object on the left side of comparison
+        * \param [in] right is the object on the right side of comparison
+        *
+        * \return true if left's expiration time point is greater than right's expiration time point
+        */
+
+       bool operator()(const SoftwareTimerListNode& left, const SoftwareTimerListNode& right) const
+       {
+               return left.getTimePoint() > right.getTimePoint();
+       }
+};
+
+/// sorted intrusive list of software timers (software timer control blocks)
+using SoftwareTimerList = estd::SortedIntrusiveList<SoftwareTimerAscendingTimePoint, SoftwareTimerListNode,
+               &SoftwareTimerListNode::node, SoftwareTimerControlBlock>;
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERLIST_HPP_
diff --git a/include/distortos/internal/scheduler/SoftwareTimerListNode.hpp b/include/distortos/internal/scheduler/SoftwareTimerListNode.hpp
new file mode 100644 (file)
index 0000000..299e078
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * \file
+ * \brief SoftwareTimerListNode class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERLISTNODE_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERLISTNODE_HPP_
+
+#include "distortos/TickClock.hpp"
+
+#include "estd/IntrusiveList.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * \brief SoftwareTimerListNode class is a base for SoftwareTimerControlBlock that serves as a node in intrusive list of
+ * software timers (software timer control blocks)
+ *
+ * This class is needed to break any potential circular dependencies.
+ */
+
+class SoftwareTimerListNode
+{
+public:
+
+       /**
+        * \brief SoftwareTimerListNode's constructor
+        */
+
+       constexpr SoftwareTimerListNode() :
+                       node{},
+                       timePoint_{}
+       {
+
+       }
+
+       /**
+        * \return const reference to expiration time point
+        */
+
+       const TickClock::time_point& getTimePoint() const
+       {
+               return timePoint_;
+       }
+
+       /// node for intrusive list
+       estd::IntrusiveListNode node;
+
+protected:
+
+       /**
+        * \brief Sets time point of expiration
+        *
+        * \param [in] timePoint is the new time point of expiration
+        */
+
+       void setTimePoint(const TickClock::time_point timePoint)
+       {
+               timePoint_ = timePoint;
+       }
+
+private:
+
+       ///time point of expiration
+       TickClock::time_point timePoint_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERLISTNODE_HPP_
diff --git a/include/distortos/internal/scheduler/SoftwareTimerSupervisor.hpp b/include/distortos/internal/scheduler/SoftwareTimerSupervisor.hpp
new file mode 100644 (file)
index 0000000..8367a0a
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * \file
+ * \brief SoftwareTimerSupervisor class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERSUPERVISOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERSUPERVISOR_HPP_
+
+#include "distortos/internal/scheduler/SoftwareTimerList.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// SoftwareTimerSupervisor class is a supervisor of software timers
+class SoftwareTimerSupervisor
+{
+public:
+
+       /**
+        * \brief SoftwareTimerControlBlock's constructor
+        */
+
+       constexpr SoftwareTimerSupervisor() :
+                       activeList_{}
+       {
+
+       }
+
+       /**
+        * \brief Adds SoftwareTimerControlBlock to supervisor, effectively starting the software timer.
+        *
+        * \param [in] softwareTimerControlBlock is the SoftwareTimerControlBlock being added/started
+        */
+
+       void add(SoftwareTimerControlBlock& softwareTimerControlBlock);
+
+       /**
+        * \brief Handler of "tick" interrupt.
+        *
+        * \note this must not be called by user code
+        *
+        * \param [in] timePoint is the current time point
+        */
+
+       void tickInterruptHandler(TickClock::time_point timePoint);
+
+private:
+
+       /// list of active software timers (waiting for execution)
+       SoftwareTimerList activeList_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_SOFTWARETIMERSUPERVISOR_HPP_
diff --git a/include/distortos/internal/scheduler/ThreadControlBlock.hpp b/include/distortos/internal/scheduler/ThreadControlBlock.hpp
new file mode 100644 (file)
index 0000000..6d6f458
--- /dev/null
@@ -0,0 +1,336 @@
+/**
+ * \file
+ * \brief ThreadControlBlock class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADCONTROLBLOCK_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADCONTROLBLOCK_HPP_
+
+#include "distortos/internal/scheduler/RoundRobinQuantum.hpp"
+#include "distortos/internal/scheduler/ThreadListNode.hpp"
+
+#include "distortos/internal/synchronization/MutexList.hpp"
+
+#include "distortos/architecture/Stack.hpp"
+
+#include "distortos/SchedulingPolicy.hpp"
+#include "distortos/ThreadState.hpp"
+
+#include "estd/TypeErasedFunctor.hpp"
+
+namespace distortos
+{
+
+class SignalsReceiver;
+
+namespace internal
+{
+
+class SignalsReceiverControlBlock;
+class ThreadList;
+class ThreadGroupControlBlock;
+
+/// ThreadControlBlock class is a simple description of a Thread
+class ThreadControlBlock : public ThreadListNode
+{
+public:
+
+       /// reason of thread unblocking
+       enum class UnblockReason : uint8_t
+       {
+               /// explicit request to unblock the thread - normal unblock
+               unblockRequest,
+               /// timeout - unblock via software timer
+               timeout,
+               /// signal handler - unblock to deliver unmasked signal
+               signal,
+       };
+
+       /// UnblockFunctor is a functor executed when unblocking the thread, it receives two parameter - a reference to
+       /// ThreadControlBlock that is being unblocked and the reason of thread unblocking
+       class UnblockFunctor : public estd::TypeErasedFunctor<void(ThreadControlBlock&, UnblockReason)>
+       {
+
+       };
+
+       /**
+        * \brief ThreadControlBlock constructor.
+        *
+        * \param [in] stack is an rvalue reference to architecture::Stack object which will be adopted for this thread
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        * \param [in] schedulingPolicy is the scheduling policy of the thread
+        * \param [in] threadGroupControlBlock is a pointer to ThreadGroupControlBlock to which this object will be added,
+        * nullptr to inherit thread group from currently running thread
+        * \param [in] signalsReceiver is a pointer to SignalsReceiver object for this thread, nullptr to disable reception
+        * of signals for this thread
+        * \param [in] owner is a reference to Thread object that owns this ThreadControlBlock
+        */
+
+       ThreadControlBlock(architecture::Stack&& stack, uint8_t priority, SchedulingPolicy schedulingPolicy,
+                       ThreadGroupControlBlock* threadGroupControlBlock, SignalsReceiver* signalsReceiver, Thread& owner);
+
+       /**
+        * \brief ThreadControlBlock's destructor
+        */
+
+       ~ThreadControlBlock();
+
+       /**
+        * \brief Hook function executed when thread is added to scheduler.
+        *
+        * If threadGroupControlBlock_ is nullptr, it is inherited from currently running thread. Then this object is added
+        * to the thread group (if it is valid).
+        *
+        * \attention This function should be called only by Scheduler::addInternal().
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - inherited thread group is invalid;
+        */
+
+       int addHook();
+
+       /**
+        * \brief Block hook function of thread
+        *
+        * Saves pointer to UnblockFunctor.
+        *
+        * \attention This function should be called only by Scheduler::blockInternal().
+        *
+        * \param [in] unblockFunctor is a pointer to UnblockFunctor which will be executed in unblockHook()
+        */
+
+       void blockHook(const UnblockFunctor* const unblockFunctor)
+       {
+               unblockFunctor_ = unblockFunctor;
+       }
+
+       /**
+        * \return pointer to list that has this object
+        */
+
+       ThreadList* getList() const
+       {
+               return list_;
+       }
+
+       /**
+        * \return reference to list of mutexes (mutex control blocks) with enabled priority protocol owned by this thread
+        */
+
+       MutexList& getOwnedProtocolMutexList()
+       {
+               return ownedProtocolMutexList_;
+       }
+
+       /**
+        * \return reference to Thread object that owns this ThreadControlBlock
+        */
+
+       Thread& getOwner() const
+       {
+               return owner_;
+       }
+
+       /**
+        * \return reference to internal RoundRobinQuantum object
+        */
+
+       RoundRobinQuantum& getRoundRobinQuantum()
+       {
+               return roundRobinQuantum_;
+       }
+
+       /**
+        * \return scheduling policy of the thread
+        */
+
+       SchedulingPolicy getSchedulingPolicy() const
+       {
+               return schedulingPolicy_;
+       }
+
+       /**
+        * \return pointer to SignalsReceiverControlBlock object for this thread, nullptr if this thread cannot receive
+        * signals
+        */
+
+       SignalsReceiverControlBlock* getSignalsReceiverControlBlock() const
+       {
+               return signalsReceiverControlBlock_;
+       }
+
+       /**
+        * \return reference to internal Stack object
+        */
+
+       architecture::Stack& getStack()
+       {
+               return stack_;
+       }
+
+       /**
+        * \return current state of object
+        */
+
+       ThreadState getState() const
+       {
+               return state_;
+       }
+
+       /**
+        * \brief Sets the list that has this object.
+        *
+        * \param [in] list is a pointer to list that has this object
+        */
+
+       void setList(ThreadList* const list)
+       {
+               list_ = list;
+       }
+
+       /**
+        * \brief Changes priority of thread.
+        *
+        * If the priority really changes, the position in the thread list is adjusted and context switch may be requested.
+        *
+        * \param [in] priority is the new priority of thread
+        * \param [in] alwaysBehind selects the method of ordering when lowering the priority
+        * - false - the thread is moved to the head of the group of threads with the new priority (default),
+        * - true - the thread is moved to the tail of the group of threads with the new priority.
+        */
+
+       void setPriority(uint8_t priority, bool alwaysBehind = {});
+
+       /**
+        * \param [in] priorityInheritanceMutexControlBlock is a pointer to MutexControlBlock (with PriorityInheritance
+        * protocol) that blocks this thread
+        */
+
+       void setPriorityInheritanceMutexControlBlock(const MutexControlBlock* const priorityInheritanceMutexControlBlock)
+       {
+               priorityInheritanceMutexControlBlock_ = priorityInheritanceMutexControlBlock;
+       }
+
+       /**
+        * param [in] schedulingPolicy is the new scheduling policy of the thread
+        */
+
+       void setSchedulingPolicy(SchedulingPolicy schedulingPolicy);
+
+       /**
+        * \param [in] state is the new state of object
+        */
+
+       void setState(const ThreadState state)
+       {
+               state_ = state;
+       }
+
+       /**
+        * \brief Hook function called when context is switched to this thread.
+        *
+        * Sets global _impure_ptr (from newlib) to thread's \a reent_ member variable.
+        *
+        * \attention This function should be called only by Scheduler::switchContext().
+        */
+
+       void switchedToHook()
+       {
+               _impure_ptr = &reent_;
+       }
+
+       /**
+        * \brief Unblock hook function of thread
+        *
+        * Resets round-robin's quantum and executes unblock functor saved in blockHook().
+        *
+        * \attention This function should be called only by Scheduler::unblockInternal().
+        *
+        * \param [in] unblockReason is the new reason of unblocking of the thread
+        */
+
+       void unblockHook(UnblockReason unblockReason);
+
+       /**
+        * \brief Updates boosted priority of the thread.
+        *
+        * This function should be called after all operations involving this thread and a mutex with enabled priority
+        * protocol.
+        *
+        * \param [in] boostedPriority is the initial boosted priority, this should be effective priority of the thread that
+        * is about to be blocked on a mutex owned by this thread, default - 0
+        */
+
+       void updateBoostedPriority(uint8_t boostedPriority = {});
+
+       ThreadControlBlock(const ThreadControlBlock&) = delete;
+       ThreadControlBlock(ThreadControlBlock&&) = default;
+       const ThreadControlBlock& operator=(const ThreadControlBlock&) = delete;
+       ThreadControlBlock& operator=(ThreadControlBlock&&) = delete;
+
+private:
+
+       /**
+        * \brief Repositions the thread on the list it's currently on.
+        *
+        * This function should be called when thread's effective priority changes.
+        *
+        * \attention list_ must not be nullptr
+        *
+        * \param [in] loweringBefore selects the method of ordering when lowering the priority (it must be false when the
+        * priority is raised!):
+        * - true - the thread is moved to the head of the group of threads with the new priority, this is accomplished by
+        * temporarily boosting effective priority by 1,
+        * - false - the thread is moved to the tail of the group of threads with the new priority.
+        */
+
+       void reposition(bool loweringBefore);
+
+       /// internal stack object
+       architecture::Stack stack_;
+
+       /// reference to Thread object that owns this ThreadControlBlock
+       Thread& owner_;
+
+       /// list of mutexes (mutex control blocks) with enabled priority protocol owned by this thread
+       MutexList ownedProtocolMutexList_;
+
+       /// pointer to MutexControlBlock (with PriorityInheritance protocol) that blocks this thread
+       const MutexControlBlock* priorityInheritanceMutexControlBlock_;
+
+       /// pointer to list that has this object
+       ThreadList* list_;
+
+       /// pointer to ThreadGroupControlBlock with which this object is associated
+       ThreadGroupControlBlock* threadGroupControlBlock_;
+
+       /// functor executed in unblockHook()
+       const UnblockFunctor* unblockFunctor_;
+
+       /// pointer to SignalsReceiverControlBlock object for this thread, nullptr if this thread cannot receive signals
+       SignalsReceiverControlBlock* signalsReceiverControlBlock_;
+
+       /// newlib's _reent structure with thread-specific data
+       _reent reent_;
+
+       /// round-robin quantum
+       RoundRobinQuantum roundRobinQuantum_;
+
+       /// scheduling policy of the thread
+       SchedulingPolicy schedulingPolicy_;
+
+       /// current state of object
+       ThreadState state_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADCONTROLBLOCK_HPP_
diff --git a/include/distortos/internal/scheduler/ThreadGroupControlBlock.hpp b/include/distortos/internal/scheduler/ThreadGroupControlBlock.hpp
new file mode 100644 (file)
index 0000000..59ff313
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * \file
+ * \brief ThreadGroupControlBlock class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADGROUPCONTROLBLOCK_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADGROUPCONTROLBLOCK_HPP_
+
+#include "distortos/internal/scheduler/ThreadListNode.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class ThreadControlBlock;
+
+/// ThreadGroupControlBlock class is a control block for ThreadGroup
+class ThreadGroupControlBlock
+{
+public:
+
+       /**
+        * \brief ThreadGroupControlBlock's constructor
+        */
+
+       constexpr ThreadGroupControlBlock() :
+                       threadList_{}
+       {
+
+       }
+
+       /**
+        * \brief Adds new ThreadControlBlock to internal list of this object.
+        *
+        * \param [in] threadControlBlock is a reference to added ThreadControlBlock object
+        */
+
+       void add(ThreadControlBlock& threadControlBlock);
+
+private:
+
+       /// intrusive list of threads (thread control blocks)
+       using List = estd::IntrusiveList<ThreadListNode, &ThreadListNode::threadGroupNode, ThreadControlBlock>;
+
+       /// list of threads (thread control blocks) in this group
+       List threadList_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADGROUPCONTROLBLOCK_HPP_
diff --git a/include/distortos/internal/scheduler/ThreadList.hpp b/include/distortos/internal/scheduler/ThreadList.hpp
new file mode 100644 (file)
index 0000000..edf2483
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * \file
+ * \brief ThreadList class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_
+
+#include "distortos/internal/scheduler/ThreadListNode.hpp"
+
+#include "estd/SortedIntrusiveList.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class ThreadControlBlock;
+
+/// functor which gives descending effective priority order of elements on the list
+struct ThreadDescendingEffectivePriority
+{
+       /**
+        * \brief ThreadDescendingEffectivePriority's constructor
+        */
+
+       constexpr ThreadDescendingEffectivePriority()
+       {
+
+       }
+
+       /**
+        * \brief ThreadDescendingEffectivePriority's function call operator
+        *
+        * \param [in] left is the object on the left-hand side of comparison
+        * \param [in] right is the object on the right-hand side of comparison
+        *
+        * \return true if left's effective priority is less than right's effective priority
+        */
+
+       bool operator()(const ThreadListNode& left, const ThreadListNode& right) const
+       {
+               return left.getEffectivePriority() < right.getEffectivePriority();
+       }
+};
+
+/// sorted intrusive list of threads (thread control blocks)
+class ThreadList : public estd::SortedIntrusiveList<ThreadDescendingEffectivePriority, ThreadListNode,
+               &ThreadListNode::threadListNode, ThreadControlBlock>
+{
+
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_
diff --git a/include/distortos/internal/scheduler/ThreadListNode.hpp b/include/distortos/internal/scheduler/ThreadListNode.hpp
new file mode 100644 (file)
index 0000000..fcd7c85
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+ * \file
+ * \brief ThreadListNode class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLISTNODE_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLISTNODE_HPP_
+
+#include "estd/IntrusiveList.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * \brief ThreadListNode class is a base for ThreadControlBlock that provides nodes for intrusive lists
+ *
+ * This class is needed to break circular dependency - MutexList is contained in ThreadControlBlock and ThreadList is
+ * contained in MutexControlBlock.
+ */
+
+class ThreadListNode
+{
+public:
+
+       /**
+        * \brief ThreadListNode's constructor
+        *
+        * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+        */
+
+       constexpr ThreadListNode(const uint8_t priority) :
+                       threadListNode{},
+                       threadGroupNode{},
+                       priority_{priority},
+                       boostedPriority_{}
+       {
+
+       }
+
+       /**
+        * \return effective priority of thread
+        */
+
+       uint8_t getEffectivePriority() const
+       {
+               return std::max(priority_, boostedPriority_);
+       }
+
+       /**
+        * \return priority of thread
+        */
+
+       uint8_t getPriority() const
+       {
+               return priority_;
+       }
+
+       /// node for intrusive list in thread lists
+       estd::IntrusiveListNode threadListNode;
+
+       /// node for intrusive list in thread group
+       estd::IntrusiveListNode threadGroupNode;
+
+protected:
+
+       /// thread's priority, 0 - lowest, UINT8_MAX - highest
+       uint8_t priority_;
+
+       /// thread's boosted priority, 0 - no boosting
+       uint8_t boostedPriority_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLISTNODE_HPP_
diff --git a/include/distortos/internal/scheduler/forceContextSwitch.hpp b/include/distortos/internal/scheduler/forceContextSwitch.hpp
new file mode 100644 (file)
index 0000000..4509e51
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * \file
+ * \brief forceContextSwitch() declaration
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_FORCECONTEXTSWITCH_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_FORCECONTEXTSWITCH_HPP_
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * \brief Forces unconditional context switch.
+ *
+ * Requests unconditional context switch and temporarily disables any interrupt masking.
+ */
+
+void forceContextSwitch();
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_FORCECONTEXTSWITCH_HPP_
diff --git a/include/distortos/internal/scheduler/getScheduler.hpp b/include/distortos/internal/scheduler/getScheduler.hpp
new file mode 100644 (file)
index 0000000..f95d51c
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * \file
+ * \brief getScheduler() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_GETSCHEDULER_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_GETSCHEDULER_HPP_
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class Scheduler;
+
+/**
+ * \return reference to main instance of system's Scheduler
+ */
+
+Scheduler& getScheduler();
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_GETSCHEDULER_HPP_
diff --git a/include/distortos/internal/scheduler/idleThreadFunction.hpp b/include/distortos/internal/scheduler/idleThreadFunction.hpp
new file mode 100644 (file)
index 0000000..23699d4
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * \file
+ * \brief idleThreadFunction() declaration
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_IDLETHREADFUNCTION_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_IDLETHREADFUNCTION_HPP_
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * \brief Idle thread's function
+ */
+
+void idleThreadFunction();
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_IDLETHREADFUNCTION_HPP_
diff --git a/include/distortos/internal/scheduler/lowLevelInitialization.hpp b/include/distortos/internal/scheduler/lowLevelInitialization.hpp
new file mode 100644 (file)
index 0000000..a6298c2
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * \file
+ * \brief internal::lowLevelInitialization() declaration
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_LOWLEVELINITIALIZATION_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_LOWLEVELINITIALIZATION_HPP_
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/*---------------------------------------------------------------------------------------------------------------------+
+| global functions' declarations
++---------------------------------------------------------------------------------------------------------------------*/
+
+/**
+ * \brief Low level system initialization
+ *
+ * 1. Initializes main instance of system's Scheduler;
+ * 2. Initializes main thread with its group;
+ * 3. Starts idle thread;
+ * 4. Initializes main instance of Mutex used for malloc() and free() locking;
+ * 5. Initializes main instance of DeferredThreadDeleter (only if CONFIG_THREAD_DETACH_ENABLE option is enabled);
+ *
+ * This function is called before constructors for global and static objects from __libc_init_array() via address in
+ * distortosPreinitArray[].
+ */
+
+void lowLevelInitialization();
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_LOWLEVELINITIALIZATION_HPP_
diff --git a/include/distortos/internal/scheduler/threadRunner.hpp b/include/distortos/internal/scheduler/threadRunner.hpp
new file mode 100644 (file)
index 0000000..1cee654
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * \file
+ * \brief threadRunner() declaration
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADRUNNER_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADRUNNER_HPP_
+
+namespace distortos
+{
+
+class Thread;
+
+namespace internal
+{
+
+/**
+ * \brief Thread runner function - entry point of threads.
+ *
+ * Performs following actions:
+ * - executes thread's "run" function;
+ * - thread's pre-termination hook is executed (if provided);
+ * - thread is terminated and removed from scheduler;
+ * - thread's termination hook is executed;
+ * - context switch is forced;
+ *
+ * This function never returns.
+ *
+ * \param [in] thread is a reference to Thread object that is being run
+ * \param [in] run is a reference to Thread's "run" function
+ * \param [in] preTerminationHook is a pointer to Thread's pre-termination hook, nullptr to skip
+ * \param [in] terminationHook is a reference to Thread's termination hook
+ */
+
+void threadRunner(Thread& thread, void (& run)(Thread&), void (* preTerminationHook)(Thread&),
+               void (& terminationHook)(Thread&)) __attribute__ ((noreturn));
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADRUNNER_HPP_
diff --git a/include/distortos/internal/synchronization/BoundQueueFunctor.hpp b/include/distortos/internal/synchronization/BoundQueueFunctor.hpp
new file mode 100644 (file)
index 0000000..35a9d14
--- /dev/null
@@ -0,0 +1,89 @@
+/**
+ * \file
+ * \brief BoundQueueFunctor class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_BOUNDQUEUEFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_BOUNDQUEUEFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/QueueFunctor.hpp"
+
+#include <utility>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * \brief BoundQueueFunctor is a type-erased QueueFunctor which calls its bound functor to execute actions on queue's
+ * storage
+ *
+ * \tparam F is the type of bound functor, it will be called with <em>void*</em> as only argument
+ */
+
+template<typename F>
+class BoundQueueFunctor : public QueueFunctor
+{
+public:
+
+       /**
+        * \brief BoundQueueFunctor's constructor
+        *
+        * \param [in] boundFunctor is a rvalue reference to bound functor which will be used to move-construct internal
+        * bound functor
+        */
+
+       constexpr explicit BoundQueueFunctor(F&& boundFunctor) :
+                       boundFunctor_{std::move(boundFunctor)}
+       {
+
+       }
+
+       /**
+        * \brief Calls the bound functor which will execute some action on queue's storage (like copy-constructing,
+        * swapping, destroying, emplacing, ...)
+        *
+        * \param [in,out] storage is a pointer to storage with/for element
+        */
+
+       void operator()(void* const storage) const override
+       {
+               boundFunctor_(storage);
+       }
+
+private:
+
+       /// bound functor
+       F boundFunctor_;
+};
+
+/**
+ * \brief Helper factory function to make BoundQueueFunctor object with deduced template arguments
+ *
+ * \tparam F is the type of bound functor, it will be called with <em>void*</em> as only argument
+ *
+ * \param [in] boundFunctor is a rvalue reference to bound functor which will be used to move-construct internal bound
+ * functor
+ *
+ * \return BoundQueueFunctor object with deduced template arguments
+ */
+
+template<typename F>
+constexpr BoundQueueFunctor<F> makeBoundQueueFunctor(F&& boundFunctor)
+{
+       return BoundQueueFunctor<F>{std::move(boundFunctor)};
+}
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_BOUNDQUEUEFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/CallOnceControlBlock.hpp b/include/distortos/internal/synchronization/CallOnceControlBlock.hpp
new file mode 100644 (file)
index 0000000..1684faf
--- /dev/null
@@ -0,0 +1,172 @@
+/**
+ * \file
+ * \brief CallOnceControlBlock class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_CALLONCECONTROLBLOCK_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_CALLONCECONTROLBLOCK_HPP_
+
+#include "estd/invoke.hpp"
+#include "estd/TypeErasedFunctor.hpp"
+
+#include <sys/features.h>
+
+namespace distortos
+{
+
+/// GCC 4.9 is needed for CallOnceControlBlock::operator()() function - and thus for OnceFlag and callOnce() - earlier
+/// versions don't support parameter pack expansion in lambdas
+#define DISTORTOS_CALLONCE_SUPPORTED   __GNUC_PREREQ(4, 9)
+
+#if DISTORTOS_CALLONCE_SUPPORTED == 1 || DOXYGEN == 1
+
+namespace internal
+{
+
+class ThreadList;
+
+/// CallOnceControlBlock class implements functionality of OnceFlag class and callOnce()
+/// \note This class requires GCC 4.9.
+class CallOnceControlBlock
+{
+public:
+
+       /**
+        * \brief CallOnceControlBlock's constructor
+        */
+
+       constexpr CallOnceControlBlock() :
+                       blockedList_{},
+                       done_{}
+       {
+
+       }
+
+       /**
+        * \brief CallOnceControlBlock's function call operator
+        *
+        * Does nothing if any function was already called for this object. In other case provided function and arguments
+        * are wrapped in a type-erased functor and passed to callOnceImplementation().
+        *
+        * \tparam Function is the function object that will be executed
+        * \tparam Args are the arguments for \a Function
+        *
+        * \param [in] function is the function object that will be executed
+        * \param [in] args are arguments for \a function
+        */
+
+       template<typename Function, typename... Args>
+       void operator()(Function&& function, Args&&... args);
+
+private:
+
+       /// Functor is a type-erased interface for functors which execute bounded function with bounded arguments
+       class Functor : public estd::TypeErasedFunctor<void()>
+       {
+
+       };
+
+       /**
+        * \brief BoundedFunctor is a type-erased Functor which calls its bounded functor
+        *
+        * \tparam F is the type of bounded functor
+        */
+
+       template<typename F>
+       class BoundedFunctor : public Functor
+       {
+       public:
+
+               /**
+                * \brief BoundedFunctor's constructor
+                *
+                * \param [in] boundedFunctor is a rvalue reference to bounded functor which will be used to move-construct
+                * internal bounded functor
+                */
+
+               constexpr explicit BoundedFunctor(F&& boundedFunctor) :
+                               boundedFunctor_{std::move(boundedFunctor)}
+               {
+
+               }
+
+               /**
+                * \brief BoundedFunctor's function call operator
+                *
+                * Calls the bounded functor.
+                */
+
+               void operator()() const override
+               {
+                       boundedFunctor_();
+               }
+
+       private:
+
+               /// bounded functor
+               F boundedFunctor_;
+       };
+
+       /**
+        * \brief Helper factory function to make BoundedFunctor object with deduced template arguments
+        *
+        * \tparam F is the type of bounded functor
+        *
+        * \param [in] boundedFunctor is a rvalue reference to bounded functor which will be used to move-construct internal
+        * bounded functor
+        *
+        * \return BoundedFunctor object with deduced template arguments
+        */
+
+       template<typename F>
+       constexpr static BoundedFunctor<F> makeBoundedFunctor(F&& boundedFunctor)
+       {
+               return BoundedFunctor<F>{std::move(boundedFunctor)};
+       }
+
+       /**
+        * \brief Implements callOnce() using type-erased functor.
+        *
+        * Does nothing if any function was already called for this object. If the function is currently being executed, but
+        * not yet done, then the calling thread is blocked. In other case the function is executed and - after it is done -
+        * all blocked threads are unblocked.
+        *
+        * \param [in] functor is a reference to functor which will execute bounded function with bounded arguments
+        */
+
+       void callOnceImplementation(const Functor& functor);
+
+       /// pointer to stack-allocated list of ThreadControlBlock objects blocked on associated OnceFlag
+       ThreadList* blockedList_;
+
+       /// tells whether any function was already called for this object (true) or not (false)
+       bool done_;
+};
+
+template<typename Function, typename... Args>
+void CallOnceControlBlock::operator()(Function&& function, Args&&... args)
+{
+       if (done_ == true)      // function already executed?
+               return;
+
+       const auto functor = makeBoundedFunctor(
+                       [&function, &args...]()
+                       {
+                               estd::invoke(std::forward<Function>(function), std::forward<Args>(args)...);
+                       });
+       callOnceImplementation(functor);
+}
+
+}      // namespace internal
+
+#endif // DISTORTOS_CALLONCE_SUPPORTED == 1 || DOXYGEN == 1
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_CALLONCECONTROLBLOCK_HPP_
diff --git a/include/distortos/internal/synchronization/CopyConstructQueueFunctor.hpp b/include/distortos/internal/synchronization/CopyConstructQueueFunctor.hpp
new file mode 100644 (file)
index 0000000..7c29c8a
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * \file
+ * \brief CopyConstructQueueFunctor class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_COPYCONSTRUCTQUEUEFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_COPYCONSTRUCTQUEUEFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/QueueFunctor.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * CopyConstructQueueFunctor is a functor used for pushing of data to the queue using copy-construction
+ *
+ * \tparam T is the type of data pushed to the queue
+ */
+
+template<typename T>
+class CopyConstructQueueFunctor : public QueueFunctor
+{
+public:
+
+       /**
+        * \brief CopyConstructQueueFunctor's constructor
+        *
+        * \param [in] value is a reference to object that will be used as argument of copy constructor
+        */
+
+       constexpr explicit CopyConstructQueueFunctor(const T& value) :
+                       value_{value}
+       {
+
+       }
+
+       /**
+        * \brief Copy-constructs the element in the queue's storage
+        *
+        * \param [in,out] storage is a pointer to storage for element
+        */
+
+       void operator()(void* const storage) const override
+       {
+               new (storage) T{value_};
+       }
+
+private:
+
+       /// reference to object that will be used as argument of copy constructor
+       const T& value_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_COPYCONSTRUCTQUEUEFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/FifoQueueBase.hpp b/include/distortos/internal/synchronization/FifoQueueBase.hpp
new file mode 100644 (file)
index 0000000..f45eec8
--- /dev/null
@@ -0,0 +1,145 @@
+/**
+ * \file
+ * \brief FifoQueueBase class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_FIFOQUEUEBASE_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_FIFOQUEUEBASE_HPP_
+
+#include "distortos/Semaphore.hpp"
+
+#include "distortos/internal/synchronization/QueueFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreFunctor.hpp"
+
+#include <memory>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// FifoQueueBase class implements basic functionality of FifoQueue template class
+class FifoQueueBase
+{
+public:
+
+       /// unique_ptr (with deleter) to storage
+       using StorageUniquePointer = std::unique_ptr<void, void(&)(void*)>;
+
+       /**
+        * \brief FifoQueueBase's constructor
+        *
+        * \param [in] storageUniquePointer is a rvalue reference to StorageUniquePointer with storage for queue elements
+        * (sufficiently large for \a maxElements, each \a elementSize bytes long) and appropriate deleter
+        * \param [in] elementSize is the size of single queue element, bytes
+        * \param [in] maxElements is the number of elements in storage
+        */
+
+       FifoQueueBase(StorageUniquePointer&& storageUniquePointer, size_t elementSize, size_t maxElements);
+
+       /**
+        * \brief FifoQueueBase's destructor
+        */
+
+       ~FifoQueueBase();
+
+       /**
+        * \return size of single queue element, bytes
+        */
+
+       size_t getElementSize() const
+       {
+               return elementSize_;
+       }
+
+       /**
+        * \brief Implementation of pop() using type-erased functor
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a popSemaphore_
+        * \param [in] functor is a reference to QueueFunctor which will execute actions related to popping - it will get
+        * readPosition_ as argument
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pop(const SemaphoreFunctor& waitSemaphoreFunctor, const QueueFunctor& functor)
+       {
+               return popPush(waitSemaphoreFunctor, functor, popSemaphore_, pushSemaphore_, readPosition_);
+       }
+
+       /**
+        * \brief Implementation of push() using type-erased functor
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] functor is a reference to QueueFunctor which will execute actions related to pushing - it will get
+        * writePosition_ as argument
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int push(const SemaphoreFunctor& waitSemaphoreFunctor, const QueueFunctor& functor)
+       {
+               return popPush(waitSemaphoreFunctor, functor, pushSemaphore_, popSemaphore_, writePosition_);
+       }
+
+private:
+
+       /**
+        * \brief Implementation of pop() and push() using type-erased functor
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a waitSemaphore
+        * \param [in] functor is a reference to QueueFunctor which will execute actions related to popping/pushing - it
+        * will get \a storage as argument
+        * \param [in] waitSemaphore is a reference to semaphore that will be waited for, \a popSemaphore_ for pop(), \a
+        * pushSemaphore_ for push()
+        * \param [in] postSemaphore is a reference to semaphore that will be posted after the operation, \a pushSemaphore_
+        * for pop(), \a popSemaphore_ for push()
+        * \param [in] storage is a reference to appropriate pointer to storage, which will be passed to \a functor, \a
+        * readPosition_ for pop(), \a writePosition_ for push()
+        *
+        * \return zero if operation was successful, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int popPush(const SemaphoreFunctor& waitSemaphoreFunctor, const QueueFunctor& functor, Semaphore& waitSemaphore,
+                       Semaphore& postSemaphore, void*& storage);
+
+       /// semaphore guarding access to "pop" functions - its value is equal to the number of available elements
+       Semaphore popSemaphore_;
+
+       /// semaphore guarding access to "push" functions - its value is equal to the number of free slots
+       Semaphore pushSemaphore_;
+
+       /// storage for queue elements
+       const StorageUniquePointer storageUniquePointer_;
+
+       /// pointer to past-the-last element of storage for queue elements
+       const void* const storageEnd_;
+
+       /// pointer to first element available for reading
+       void* readPosition_;
+
+       /// pointer to first free slot available for writing
+       void* writePosition_;
+
+       /// size of single queue element, bytes
+       const size_t elementSize_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_FIFOQUEUEBASE_HPP_
diff --git a/include/distortos/internal/synchronization/MemcpyPopQueueFunctor.hpp b/include/distortos/internal/synchronization/MemcpyPopQueueFunctor.hpp
new file mode 100644 (file)
index 0000000..29113a5
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * \file
+ * \brief MemcpyPopQueueFunctor class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MEMCPYPOPQUEUEFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MEMCPYPOPQUEUEFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/QueueFunctor.hpp"
+
+#include <cstddef>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// MemcpyPopQueueFunctor is a functor used for popping of data from the raw queue with memecpy()
+class MemcpyPopQueueFunctor : public QueueFunctor
+{
+public:
+
+       /**
+        * \brief MemcpyPopQueueFunctor's constructor
+        *
+        * \param [out] buffer is a pointer to buffer for popped element
+        * \param [in] size is the size of \a buffer, bytes
+        */
+
+       constexpr MemcpyPopQueueFunctor(void* const buffer, const size_t size) :
+                       buffer_{buffer},
+                       size_{size}
+       {
+
+       }
+
+       /**
+        * \brief Copies the data from raw queue's storage (with memcpy()).
+        *
+        * \param [in,out] storage is a pointer to storage for element
+        */
+
+       void operator()(void* storage) const override;
+
+private:
+
+       /// pointer to buffer for popped element
+       void* const buffer_;
+
+       /// size of \a buffer_, bytes
+       const size_t size_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MEMCPYPOPQUEUEFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/MemcpyPushQueueFunctor.hpp b/include/distortos/internal/synchronization/MemcpyPushQueueFunctor.hpp
new file mode 100644 (file)
index 0000000..89fb4b0
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * \file
+ * \brief MemcpyPushQueueFunctor class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MEMCPYPUSHQUEUEFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MEMCPYPUSHQUEUEFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/QueueFunctor.hpp"
+
+#include <cstddef>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// MemcpyPushQueueFunctor is a functor used for pushing of data to the raw queue with memcpy()
+class MemcpyPushQueueFunctor : public QueueFunctor
+{
+public:
+
+       /**
+        * \brief MemcpyPushQueueFunctor's constructor
+        *
+        * \param [in] data is a pointer to data that will be pushed to raw queue
+        * \param [in] size is the size of \a data, bytes
+        */
+
+       constexpr MemcpyPushQueueFunctor(const void* const data, const size_t size) :
+                       data_{data},
+                       size_{size}
+       {
+
+       }
+
+       /**
+        * \brief Copies the data to raw queue's storage (with memcpy()).
+        *
+        * \param [in,out] storage is a pointer to storage for element
+        */
+
+       void operator()(void* storage) const override;
+
+private:
+
+       /// pointer to data that will be pushed to raw queue
+       const void* const data_;
+
+       /// size of \a data_, bytes
+       const size_t size_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MEMCPYPUSHQUEUEFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/MessageQueueBase.hpp b/include/distortos/internal/synchronization/MessageQueueBase.hpp
new file mode 100644 (file)
index 0000000..e0bd4e5
--- /dev/null
@@ -0,0 +1,221 @@
+/**
+ * \file
+ * \brief MessageQueueBase class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MESSAGEQUEUEBASE_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MESSAGEQUEUEBASE_HPP_
+
+#include "distortos/Semaphore.hpp"
+
+#include "distortos/internal/synchronization/QueueFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreFunctor.hpp"
+
+#include "estd/SortedIntrusiveForwardList.hpp"
+
+#include <memory>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// MessageQueueBase class implements basic functionality of MessageQueue template class
+class MessageQueueBase
+{
+public:
+
+       /// entry in the MessageQueueBase
+       struct Entry
+       {
+               /**
+                * \brief Entry's constructor
+                *
+                * \param [in] priorityy is the priority of the entry
+                * \param [in] storagee is the storage for the entry
+                */
+
+               constexpr Entry(const uint8_t priorityy, void* const storagee) :
+                               node{},
+                               priority{priorityy},
+                               storage{storagee}
+               {
+
+               }
+
+               /// node for intrusive forward list
+               estd::IntrusiveForwardListNode node;
+
+               /// priority of the entry
+               uint8_t priority;
+
+               /// storage for the entry
+               void* storage;
+       };
+
+       /// type of uninitialized storage for Entry
+       using EntryStorage = typename std::aligned_storage<sizeof(Entry), alignof(Entry)>::type;
+
+       /// unique_ptr (with deleter) to EntryStorage[]
+       using EntryStorageUniquePointer = std::unique_ptr<EntryStorage[], void(&)(EntryStorage*)>;
+
+       /**
+        * type of uninitialized storage for value
+        *
+        * \tparam T is the type of data in queue
+        */
+
+       template<typename T>
+       using ValueStorage = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
+
+       /// unique_ptr (with deleter) to storage
+       using ValueStorageUniquePointer = std::unique_ptr<void, void(&)(void*)>;
+
+       /// functor which gives descending priority order of elements on the list
+       struct DescendingPriority
+       {
+               /**
+                * \brief DescendingPriority's constructor
+                */
+
+               constexpr DescendingPriority()
+               {
+
+               }
+
+               /**
+                * \brief DescendingPriority's function call operator
+                *
+                * \param [in] left is the object on the left side of comparison
+                * \param [in] right is the object on the right side of comparison
+                *
+                * \return true if left's priority is less than right's priority
+                */
+
+               bool operator()(const Entry& left, const Entry& right) const
+               {
+                       return left.priority < right.priority;
+               }
+       };
+
+       /// type of entry list
+       using EntryList = estd::SortedIntrusiveForwardList<DescendingPriority, Entry, &Entry::node>;
+
+       /// type of free entry list
+       using FreeEntryList = EntryList::UnsortedIntrusiveForwardList;
+
+       /**
+        * \brief InternalFunctor is a type-erased interface for functors which execute common code of pop() and push()
+        * operations.
+        *
+        * The functor will be called by MessageQueueBase internals with references to \a entryList_ and \a freeEntryList_.
+        * It should perform common actions and execute the QueueFunctor passed from callers.
+        */
+
+       class InternalFunctor : public estd::TypeErasedFunctor<void(EntryList&, FreeEntryList&)>
+       {
+
+       };
+
+       /**
+        * \brief MessageQueueBase's constructor
+        *
+        * \param [in] entryStorageUniquePointer is a rvalue reference to EntryStorageUniquePointer with storage for queue
+        * entries (sufficiently large for \a maxElements EntryStorage objects) and appropriate deleter
+        * \param [in] valueStorageUniquePointer is a rvalue reference to ValueStorageUniquePointer with storage for queue
+        * elements (sufficiently large for \a maxElements, each \a elementSize bytes long) and appropriate deleter
+        * \param [in] elementSize is the size of single queue element, bytes
+        * \param [in] maxElements is the number of elements in \a entryStorage array and valueStorage memory block
+        */
+
+       MessageQueueBase(EntryStorageUniquePointer&& entryStorageUniquePointer,
+                       ValueStorageUniquePointer&& valueStorageUniquePointer, size_t elementSize, size_t maxElements);
+
+       /**
+        * \brief MessageQueueBase's destructor
+        */
+
+       ~MessageQueueBase();
+
+       /**
+        * \brief Implementation of pop() using type-erased functor
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a popSemaphore_
+        * \param [out] priority is a reference to variable that will be used to return priority of popped value
+        * \param [in] functor is a reference to QueueFunctor which will execute actions related to popping - it will get a
+        * pointer to storage with element
+        *
+        * \return zero if element was popped successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int pop(const SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, const QueueFunctor& functor);
+
+       /**
+        * \brief Implementation of push() using type-erased functor
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+        * \param [in] priority is the priority of new element
+        * \param [in] functor is a reference to QueueFunctor which will execute actions related to pushing - it will get a
+        * pointer to storage for element
+        *
+        * \return zero if element was pushed successfully, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int push(const SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, const QueueFunctor& functor);
+
+private:
+
+       /**
+        * \brief Implementation of pop() and push() using type-erased internal functor
+        *
+        * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a waitSemaphore
+        * \param [in] internalFunctor is a reference to InternalFunctor which will execute actions related to
+        * popping/pushing
+        * \param [in] waitSemaphore is a reference to semaphore that will be waited for, \a popSemaphore_ for pop(), \a
+        * pushSemaphore_ for push()
+        * \param [in] postSemaphore is a reference to semaphore that will be posted after the operation, \a pushSemaphore_
+        * for pop(), \a popSemaphore_ for push()
+        *
+        * \return zero if operation was successful, error code otherwise:
+        * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+        * - error codes returned by Semaphore::post();
+        */
+
+       int popPush(const SemaphoreFunctor& waitSemaphoreFunctor, const InternalFunctor& internalFunctor,
+                       Semaphore& waitSemaphore, Semaphore& postSemaphore);
+
+       /// semaphore guarding access to "pop" functions - its value is equal to the number of available elements
+       Semaphore popSemaphore_;
+
+       /// semaphore guarding access to "push" functions - its value is equal to the number of free slots
+       Semaphore pushSemaphore_;
+
+       /// storage for queue entries
+       const EntryStorageUniquePointer entryStorageUniquePointer_;
+
+       /// storage for queue elements
+       const ValueStorageUniquePointer valueStorageUniquePointer_;
+
+       /// list of available entries, sorted in descending order of priority
+       EntryList entryList_;
+
+       /// list of "free" entries
+       FreeEntryList freeEntryList_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MESSAGEQUEUEBASE_HPP_
diff --git a/include/distortos/internal/synchronization/MoveConstructQueueFunctor.hpp b/include/distortos/internal/synchronization/MoveConstructQueueFunctor.hpp
new file mode 100644 (file)
index 0000000..ff6587f
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * \file
+ * \brief MoveConstructQueueFunctor class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MOVECONSTRUCTQUEUEFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MOVECONSTRUCTQUEUEFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/QueueFunctor.hpp"
+
+#include <utility>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * MoveConstructQueueFunctor is a functor used for pushing of data to the queue using move-construction
+ *
+ * \tparam T is the type of data pushed to the queue
+ */
+
+template<typename T>
+class MoveConstructQueueFunctor : public QueueFunctor
+{
+public:
+
+       /**
+        * \brief MoveConstructQueueFunctor's constructor
+        *
+        * \param [in] value is a rvalue reference to object that will be used as argument of move constructor
+        */
+
+       constexpr explicit MoveConstructQueueFunctor(T&& value) :
+                       value_{std::move(value)}
+       {
+
+       }
+
+       /**
+        * \brief Move-constructs the element in the queue's storage
+        *
+        * \param [in,out] storage is a pointer to storage for element
+        */
+
+       void operator()(void* const storage) const override
+       {
+               new (storage) T{std::move(value_)};
+       }
+
+private:
+
+       /// rvalue reference to object that will be used as argument of move constructor
+       T&& value_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MOVECONSTRUCTQUEUEFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/MutexControlBlock.hpp b/include/distortos/internal/synchronization/MutexControlBlock.hpp
new file mode 100644 (file)
index 0000000..93c3ee6
--- /dev/null
@@ -0,0 +1,184 @@
+/**
+ * \file
+ * \brief MutexControlBlock class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXCONTROLBLOCK_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXCONTROLBLOCK_HPP_
+
+#include "distortos/internal/scheduler/ThreadList.hpp"
+
+#include "distortos/internal/synchronization/MutexListNode.hpp"
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// MutexControlBlock class is a control block for Mutex
+class MutexControlBlock : public MutexListNode
+{
+public:
+
+       /// mutex protocols
+       enum class Protocol : uint8_t
+       {
+               /// no protocol, similar to PTHREAD_PRIO_NONE
+               none,
+               /// priority inheritance protocol, similar to PTHREAD_PRIO_INHERIT
+               priorityInheritance,
+               /// priority protection protocol (Immediate Ceiling Priority Protocol), similar to PTHREAD_PRIO_PROTECT
+               priorityProtect,
+       };
+
+       /**
+        * \brief MutexControlBlock constructor
+        *
+        * \param [in] protocol is the mutex protocol
+        * \param [in] priorityCeiling is the priority ceiling of mutex, ignored when protocol != Protocol::priorityProtect
+        */
+
+       constexpr MutexControlBlock(const Protocol protocol, const uint8_t priorityCeiling) :
+                       MutexListNode{},
+                       blockedList_{},
+                       owner_{},
+                       protocol_{protocol},
+                       priorityCeiling_{priorityCeiling}
+       {
+
+       }
+
+       /**
+        * \brief Blocks current thread, transferring it to blockedList_.
+        *
+        * \return 0 on success, error code otherwise:
+        * - values returned by Scheduler::block();
+        */
+
+       int block();
+
+       /**
+        * \brief Blocks current thread with timeout, transferring it to blockedList_.
+        *
+        * \param [in] timePoint is the time point at which the thread will be unblocked (if not already unblocked)
+        *
+        * \return 0 on success, error code otherwise:
+        * - values returned by Scheduler::blockUntil();
+        */
+
+       int blockUntil(TickClock::time_point timePoint);
+
+       /**
+        * \brief Gets "boosted priority" of the mutex.
+        *
+        * "Boosted priority" of the mutex depends on the selected priority protocol:
+        * - None - 0,
+        * - PriorityInheritance - effective priority of the highest priority thread blocked on this mutex or 0 if no
+        * threads are blocked,
+        * - PriorityProtect - priority ceiling.
+        *
+        * \return "boosted priority" of the mutex
+        */
+
+       uint8_t getBoostedPriority() const;
+
+       /**
+        * \return owner of the mutex, nullptr if mutex is currently unlocked
+        */
+
+       ThreadControlBlock* getOwner() const
+       {
+               return owner_;
+       }
+
+       /**
+        * \return priority ceiling of mutex, valid only when protocol_ == Protocol::priorityProtect
+        */
+
+       uint8_t getPriorityCeiling() const
+       {
+               return priorityCeiling_;
+       }
+
+       /**
+        * \return mutex protocol
+        */
+
+       Protocol getProtocol() const
+       {
+               return protocol_;
+       }
+
+       /**
+        * \brief Performs actual locking of previously unlocked mutex.
+        *
+        * \attention mutex must be unlocked
+        */
+
+       void lock();
+
+       /**
+        * \brief Performs unlocking or transfer of lock from current owner to next thread on the list.
+        *
+        * Mutex is unlocked if blockedList_ is empty, otherwise the ownership is transfered to the next thread.
+        *
+        * \attention mutex must be locked
+        */
+
+       void unlockOrTransferLock();
+
+private:
+
+       /**
+        * \brief Performs action required for priority inheritance before actually blocking on the mutex.
+        *
+        * This must be called in block() and blockUntil() before actually blocking of the calling thread.
+        *
+        * \attantion mutex's protocol must be PriorityInheritance
+        */
+
+       void priorityInheritanceBeforeBlock() const;
+
+       /**
+        * \brief Performs transfer of lock from current owner to next thread on the list.
+        *
+        * \attention mutex must be locked and blockedList_ must not be empty
+        */
+
+       void transferLock();
+
+       /**
+        * \brief Performs actual unlocking of previously locked mutex.
+        *
+        * \attention mutex must be locked and blockedList_ must be empty
+        */
+
+       void unlock();
+
+       /// ThreadControlBlock objects blocked on mutex
+       ThreadList blockedList_;
+
+       /// owner of the mutex
+       ThreadControlBlock* owner_;
+
+       /// mutex protocol
+       Protocol protocol_;
+
+       /// priority ceiling of mutex, valid only when protocol_ == Protocol::priorityProtect
+       uint8_t priorityCeiling_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXCONTROLBLOCK_HPP_
diff --git a/include/distortos/internal/synchronization/MutexList.hpp b/include/distortos/internal/synchronization/MutexList.hpp
new file mode 100644 (file)
index 0000000..18d5794
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * \file
+ * \brief MutexList class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXLIST_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXLIST_HPP_
+
+#include "distortos/internal/synchronization/MutexListNode.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class MutexControlBlock;
+
+/// intrusive list of mutexes (mutex control blocks)
+using MutexList = estd::IntrusiveList<MutexListNode, &MutexListNode::node, MutexControlBlock>;
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXLIST_HPP_
diff --git a/include/distortos/internal/synchronization/MutexListNode.hpp b/include/distortos/internal/synchronization/MutexListNode.hpp
new file mode 100644 (file)
index 0000000..049eb76
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * \file
+ * \brief MutexListNode class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXLISTNODE_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXLISTNODE_HPP_
+
+#include "estd/IntrusiveList.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * \brief MutexListNode class is a base for MutexControlBlock that serves as a node in intrusive list of mutexes (mutex
+ * control blocks)
+ *
+ * This class is needed to break circular dependency - MutexList is contained in ThreadControlBlock and ThreadList is
+ * contained in MutexControlBlock.
+ */
+
+class MutexListNode
+{
+public:
+
+       /**
+        * \brief MutexListNode's constructor
+        */
+
+       constexpr MutexListNode() :
+                       node{}
+       {
+
+       }
+
+       /// node for intrusive list
+       estd::IntrusiveListNode node;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_MUTEXLISTNODE_HPP_
diff --git a/include/distortos/internal/synchronization/QueueFunctor.hpp b/include/distortos/internal/synchronization/QueueFunctor.hpp
new file mode 100644 (file)
index 0000000..7c14a59
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * \file
+ * \brief QueueFunctor class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_QUEUEFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_QUEUEFUNCTOR_HPP_
+
+#include "estd/TypeErasedFunctor.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * \brief QueueFunctor is a type-erased interface for functors which execute some action on queue's storage (like
+ * copy-constructing, swapping, destroying, emplacing, ...).
+ *
+ * The functor will be called by queue internals with one argument - \a storage - which is a pointer to storage with/for
+ * element
+ */
+
+class QueueFunctor : public estd::TypeErasedFunctor<void(void*)>
+{
+
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_SYNCHRONIZATION_QUEUEFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/SemaphoreFunctor.hpp b/include/distortos/internal/synchronization/SemaphoreFunctor.hpp
new file mode 100644 (file)
index 0000000..0b937ff
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * \file
+ * \brief SemaphoreFunctor class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHOREFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHOREFUNCTOR_HPP_
+
+#include "estd/TypeErasedFunctor.hpp"
+
+namespace distortos
+{
+
+class Semaphore;
+
+namespace internal
+{
+
+/**
+ * \brief SemaphoreFunctor is a type-erased interface for functors which execute some action on semaphore (wait(),
+ * tryWait(), tryWaitFor(), tryWaitUntil(), ...).
+ *
+ * The functor will be called with one argument - \a semaphore - which is a reference to Semaphore object on which the
+ * action will be executed. Functor's operator should return zero if the action was executed successfully, error code
+ * otherwise.
+ */
+
+class SemaphoreFunctor : public estd::TypeErasedFunctor<int(Semaphore&)>
+{
+
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHOREFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/SemaphoreTryWaitForFunctor.hpp b/include/distortos/internal/synchronization/SemaphoreTryWaitForFunctor.hpp
new file mode 100644 (file)
index 0000000..88580de
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * \file
+ * \brief SemaphoreTryWaitForFunctor class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITFORFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITFORFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/SemaphoreFunctor.hpp"
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// SemaphoreTryWaitForFunctor class is a SemaphoreFunctor which calls Semaphore::tryWaitFor() with bounded duration
+class SemaphoreTryWaitForFunctor : public SemaphoreFunctor
+{
+public:
+
+       /**
+        * \brief SemaphoreTryWaitForFunctor's constructor
+        *
+        * \param [in] duration is the bounded duration for Semaphore::tryWaitFor() call
+        */
+
+       constexpr explicit SemaphoreTryWaitForFunctor(const TickClock::duration duration) :
+                       duration_{duration}
+       {
+
+       }
+
+       /**
+        * \brief Calls Semaphore::tryWaitFor() with bounded duration
+        *
+        * \param [in] semaphore is a reference to Semaphore object for which Semaphore::tryWaitFor() will be called
+        *
+        * \return value returned by Semaphore::tryWaitFor()
+        */
+
+       int operator()(Semaphore& semaphore) const override;
+
+private:
+
+       /// bounded duration for Semaphore::tryWaitFor() call
+       const TickClock::duration duration_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITFORFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/SemaphoreTryWaitFunctor.hpp b/include/distortos/internal/synchronization/SemaphoreTryWaitFunctor.hpp
new file mode 100644 (file)
index 0000000..4084563
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * \file
+ * \brief SemaphoreTryWaitFunctor class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/SemaphoreFunctor.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// SemaphoreTryWaitFunctor class is a SemaphoreFunctor which calls Semaphore::tryWait()
+class SemaphoreTryWaitFunctor : public SemaphoreFunctor
+{
+public:
+
+       /**
+        * \brief Calls Semaphore::tryWait()
+        *
+        * \param [in] semaphore is a reference to Semaphore object for which Semaphore::tryWait() will be called
+        *
+        * \return value returned by Semaphore::tryWait()
+        */
+
+       int operator()(Semaphore& semaphore) const override;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/SemaphoreTryWaitUntilFunctor.hpp b/include/distortos/internal/synchronization/SemaphoreTryWaitUntilFunctor.hpp
new file mode 100644 (file)
index 0000000..a8eaab2
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * \file
+ * \brief SemaphoreTryWaitUntilFunctor class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITUNTILFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITUNTILFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/SemaphoreFunctor.hpp"
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// SemaphoreTryWaitUntilFunctor class is a SemaphoreFunctor which calls Semaphore::tryWaitUntil() with bounded time
+/// point
+class SemaphoreTryWaitUntilFunctor : public SemaphoreFunctor
+{
+public:
+
+       /**
+        * \brief SemaphoreTryWaitUntilFunctor's constructor
+        *
+        * \param [in] timePoint is the bounded time point for Semaphore::tryWaitUntil() call
+        */
+
+       constexpr explicit SemaphoreTryWaitUntilFunctor(const TickClock::time_point timePoint) :
+                       timePoint_{timePoint}
+       {
+
+       }
+
+       /**
+        * \brief Calls Semaphore::tryWaitUntil() with bounded time point.
+        *
+        * \param [in] semaphore is a reference to Semaphore object for which Semaphore::tryWaitUntil() will be called
+        *
+        * \return value returned by Semaphore::tryWaitUntil()
+        */
+
+       int operator()(Semaphore& semaphore) const override;
+
+private:
+
+       /// bounded time point for Semaphore::tryWaitUntil() call
+       const TickClock::time_point timePoint_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHORETRYWAITUNTILFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/SemaphoreWaitFunctor.hpp b/include/distortos/internal/synchronization/SemaphoreWaitFunctor.hpp
new file mode 100644 (file)
index 0000000..a787b2b
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * \file
+ * \brief SemaphoreWaitFunctor class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHOREWAITFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHOREWAITFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/SemaphoreFunctor.hpp"
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/// SemaphoreWaitFunctor class is a SemaphoreFunctor which calls Semaphore::wait()
+class SemaphoreWaitFunctor : public SemaphoreFunctor
+{
+public:
+
+       /**
+        * \brief Calls Semaphore::wait()
+        *
+        * \param [in] semaphore is a reference to Semaphore object for which Semaphore::wait() will be called
+        *
+        * \return value returned by Semaphore::wait()
+        */
+
+       int operator()(Semaphore& semaphore) const override;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SEMAPHOREWAITFUNCTOR_HPP_
diff --git a/include/distortos/internal/synchronization/SignalInformationQueue.hpp b/include/distortos/internal/synchronization/SignalInformationQueue.hpp
new file mode 100644 (file)
index 0000000..7a9d08a
--- /dev/null
@@ -0,0 +1,123 @@
+/**
+ * \file
+ * \brief SignalInformationQueue class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALINFORMATIONQUEUE_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALINFORMATIONQUEUE_HPP_
+
+#include "distortos/SignalInformation.hpp"
+
+#include "estd/IntrusiveForwardList.hpp"
+
+#include <memory>
+
+namespace distortos
+{
+
+class SignalSet;
+
+namespace internal
+{
+
+/// SignalInformationQueue class can be used for queuing of SignalInformation objects
+class SignalInformationQueue
+{
+public:
+
+       /// single node of internal forward list - estd::IntrusiveForwardListNode and SignalInformation
+       struct QueueNode
+       {
+               /// node for intrusive forward list
+               estd::IntrusiveForwardListNode node;
+
+               /// queued SignalInformation
+               SignalInformation signalInformation;
+       };
+
+       /// type of uninitialized storage for QueueNode
+       using Storage = typename std::aligned_storage<sizeof(QueueNode), alignof(QueueNode)>::type;
+
+       /// unique_ptr (with deleter) to Storage[]
+       using StorageUniquePointer = std::unique_ptr<Storage[], void(&)(Storage*)>;
+
+       /**
+        * \brief SignalInformationQueue's constructor
+        *
+        * \param [in] storageUniquePointer is a rvalue reference to StorageUniquePointer with storage for queue elements
+        * (sufficiently large for \a maxElements Storage objects) and appropriate deleter
+        * \param [in] maxElements is the number of elements in \a storage array
+        */
+
+       SignalInformationQueue(StorageUniquePointer&& storageUniquePointer, size_t maxElements);
+
+       /**
+        * \brief SignalInformationQueue's destructor
+        */
+
+       ~SignalInformationQueue();
+
+       /**
+        * \brief Accepts (dequeues) one of signals that are queued.
+        *
+        * This should be called when the signal is "accepted".
+        *
+        * \param [in] signalNumber is the signal that will be accepted, [0; 31]
+        *
+        * \return pair with return code (0 on success, error code otherwise) and dequeued SignalInformation object;
+        * error codes:
+        * - EAGAIN - no SignalInformation object with signal number equal to \a signalNumber was queued;
+        */
+
+       std::pair<int, SignalInformation> acceptQueuedSignal(uint8_t signalNumber);
+
+       /**
+        * \return set of currently queued signals
+        */
+
+       SignalSet getQueuedSignalSet() const;
+
+       /**
+        * \brief Adds the signalNumber and signal value (sigval union) to list of queued SignalInformation objects.
+        *
+        * \param [in] signalNumber is the signal that will be queued, [0; 31]
+        * \param [in] value is the signal value
+        *
+        * \return 0 on success, error code otherwise:
+        * - EAGAIN - no resources are available to queue the signal, \a maxElements signals are already queued;
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       int queueSignal(uint8_t signalNumber, sigval value);
+
+       SignalInformationQueue(const SignalInformationQueue&) = delete;
+       SignalInformationQueue(SignalInformationQueue&&) = default;
+       const SignalInformationQueue& operator=(const SignalInformationQueue&) = delete;
+       SignalInformationQueue& operator=(SignalInformationQueue&&) = delete;
+
+private:
+
+       /// type of container with SignalInformation objects
+       using List = estd::IntrusiveForwardList<QueueNode, &QueueNode::node>;
+
+       /// storage for queue elements
+       StorageUniquePointer storageUniquePointer_;
+
+       /// list of queued SignalInformation objects
+       List signalInformationList_;
+
+       /// list of "free" SignalInformation objects
+       List freeSignalInformationList_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALINFORMATIONQUEUE_HPP_
diff --git a/include/distortos/internal/synchronization/SignalsCatcherControlBlock.hpp b/include/distortos/internal/synchronization/SignalsCatcherControlBlock.hpp
new file mode 100644 (file)
index 0000000..6676216
--- /dev/null
@@ -0,0 +1,213 @@
+/**
+ * \file
+ * \brief SignalsCatcherControlBlock class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
+
+#include "distortos/SignalAction.hpp"
+
+#include <memory>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+class SignalsReceiverControlBlock;
+class ThreadControlBlock;
+
+/// SignalsCatcherControlBlock class is a structure required by threads for "catching" and "handling" of signals
+class SignalsCatcherControlBlock
+{
+public:
+
+       /// association of signal numbers (as SignalSet) with SignalAction
+       using Association = std::pair<SignalSet, SignalAction>;
+
+       /// type of uninitialized storage for Association objects
+       using Storage = std::aligned_storage<sizeof(Association), alignof(Association)>::type;
+
+       /// unique_ptr (with deleter) to Storage[]
+       using StorageUniquePointer = std::unique_ptr<Storage[], void(&)(Storage*)>;
+
+       /**
+        * \brief SignalsCatcherControlBlock's constructor
+        *
+        * \param [in] storageUniquePointer is a rvalue reference to StorageUniquePointer with storage for Association
+        * objects (sufficiently large for \a storageSize elements) and appropriate deleter
+        * \param [in] storageSize is the number of elements in \a storage array
+        */
+
+       SignalsCatcherControlBlock(StorageUniquePointer&& storageUniquePointer, size_t storageSize);
+
+       /**
+        * \brief SignalsCatcherControlBlock's destructor
+        */
+
+       ~SignalsCatcherControlBlock();
+
+       /**
+        * \brief Hook function executed when delivery of signals is started.
+        *
+        * Clears "delivery pending" flag.
+        *
+        * \attention This function should be called only by SignalsReceiverControlBlock::deliveryOfSignalsFinishedHook().
+        */
+
+       void deliveryOfSignalsStartedHook()
+       {
+               deliveryIsPending_ = false;
+       }
+
+       /**
+        * \brief Gets SignalAction associated with given signal number.
+        *
+        * \param [in] signalNumber is the signal for which the association is requested, [0; 31]
+        *
+        * \return pair with return code (0 on success, error code otherwise) and SignalAction that is associated with
+        * \a signalNumber, default-constructed object if no association was found;
+        * error codes:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       std::pair<int, SignalAction> getAssociation(uint8_t signalNumber) const;
+
+       /**
+        * \return SignalSet with signal mask for associated thread
+        */
+
+       SignalSet getSignalMask() const
+       {
+               return signalMask_;
+       }
+
+       /**
+        * \brief Part of SignalsReceiverControlBlock::postGenerate() specific to catching unmasked signals.
+        *
+        * Requests delivery of signals to associated thread if there is some non-default signal handler for the signal.
+        *
+        * \param [in] signalNumber is the unmasked signal that was generated, [0; 31]
+        * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       int postGenerate(uint8_t signalNumber, ThreadControlBlock& threadControlBlock);
+
+       /**
+        * \brief Sets association for given signal number.
+        *
+        * \param [in] signalNumber is the signal for which the association will be set, [0; 31]
+        * \param [in] signalAction is a reference to SignalAction that will be associated with given signal number, object
+        * in internal storage is copy-constructed
+        *
+        * \return pair with return code (0 on success, error code otherwise) and SignalAction that was associated with
+        * \a signalNumber, default-constructed object if no association was found;
+        * error codes:
+        * - EAGAIN - no resources are available to associate \a signalNumber with \a signalAction;
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       std::pair<int, SignalAction> setAssociation(uint8_t signalNumber, const SignalAction& signalAction);
+
+       /**
+        * \brief Sets signal mask for associated thread.
+        *
+        * If any pending signal is unblocked and \a owner doesn't equal nullptr, then delivery of signals to associated
+        * thread will be requested.
+        *
+        * \param [in] signalMask is the SignalSet with new signal mask for associated thread
+        * \param [in] owner selects whether delivery of signals will be requested if any pending signal is unblocked
+        * (pointer to owner SignalsReceiverControlBlock object) or not (nullptr)
+        */
+
+       void setSignalMask(SignalSet signalMask, const SignalsReceiverControlBlock* owner);
+
+       SignalsCatcherControlBlock(const SignalsCatcherControlBlock&) = delete;
+       SignalsCatcherControlBlock(SignalsCatcherControlBlock&&) = default;
+       const SignalsCatcherControlBlock& operator=(const SignalsCatcherControlBlock&) = delete;
+       SignalsCatcherControlBlock& operator=(SignalsCatcherControlBlock&&) = delete;
+
+private:
+
+       /**
+        * \brief Clears association for given signal number.
+        *
+        * \param [in] signalNumber is the signal for which the association will be cleared, [0; 31]
+        *
+        * \return SignalAction that was associated with \a signalNumber, default-constructed object if no association was
+        * found
+        */
+
+       SignalAction clearAssociation(uint8_t signalNumber);
+
+       /**
+        * \brief Clears given association for given signal number.
+        *
+        * \param [in] signalNumber is the signal for which the association will be cleared, [0; 31]
+        * \param [in] association is a reference to Association object from <em>[associationsBegin_; associationsEnd_)</em>
+        * range that will be removed
+        *
+        * \return SignalAction from \a association
+        */
+
+       SignalAction clearAssociation(uint8_t signalNumber, Association& association);
+
+       /**
+        * \return pointer to first element of range of Association objects
+        */
+
+       Association* getAssociationsBegin() const
+       {
+               return reinterpret_cast<Association*>(storageUniquePointer_.get());
+       }
+
+       /**
+        * \brief Requests delivery of signals to associated thread.
+        *
+        * Delivery of signals (via special function executed in the associated thread) is requested only if it's not
+        * already pending. The thread is unblocked if it was blocked.
+        *
+        * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
+        */
+
+       void requestDeliveryOfSignals(ThreadControlBlock& threadControlBlock);
+
+       /// storage for Association objects
+       StorageUniquePointer storageUniquePointer_;
+
+       /// SignalSet with signal mask for associated thread
+       SignalSet signalMask_;
+
+       /// union binds \a associationsEnd_ and \a storageBegin_ - these point to the same address
+       union
+       {
+               /// pointer to "one past the last" element of range of Association objects
+               Association* associationsEnd_;
+
+               /// pointer to first element of range of Storage objects
+               Storage* storageBegin_;
+       };
+
+       /// pointer to "one past the last" element of range of Storage objects
+       Storage* storageEnd_;
+
+       /// true if signal delivery is pending, false otherwise
+       bool deliveryIsPending_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
diff --git a/include/distortos/internal/synchronization/SignalsReceiverControlBlock.hpp b/include/distortos/internal/synchronization/SignalsReceiverControlBlock.hpp
new file mode 100644 (file)
index 0000000..c70d79d
--- /dev/null
@@ -0,0 +1,243 @@
+/**
+ * \file
+ * \brief SignalsReceiverControlBlock class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
+
+#include "distortos/SignalSet.hpp"
+
+#include <cstdint>
+
+union sigval;
+
+namespace distortos
+{
+
+class SignalAction;
+class SignalInformation;
+class SignalInformationQueueWrapper;
+class SignalsCatcher;
+
+namespace internal
+{
+
+class SignalInformationQueue;
+class SignalsCatcherControlBlock;
+class ThreadControlBlock;
+
+/// SignalsReceiverControlBlock class is a structure required by threads for "receiving" of signals
+class SignalsReceiverControlBlock
+{
+public:
+
+       /**
+        * \brief SignalsReceiverControlBlock's constructor
+        *
+        * \param [in] signalInformationQueueWrapper is a pointer to SignalInformationQueueWrapper for this receiver,
+        * nullptr to disable queuing of signals for this receiver
+        * \param [in] signalsCatcher is a pointer to SignalsCatcher for this receiver, nullptr if this receiver cannot
+        * catch/handle signals
+        */
+
+       explicit SignalsReceiverControlBlock(SignalInformationQueueWrapper* signalInformationQueueWrapper,
+                       SignalsCatcher* signalsCatcher);
+
+       /**
+        * \brief Accepts (clears) one of signals that are pending.
+        *
+        * This should be called when the signal is "accepted".
+        *
+        * \param [in] signalNumber is the signal that will be accepted, [0; 31]
+        *
+        * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted
+        * signal; error codes:
+        * - EAGAIN - no signal specified by \a signalNumber was pending;
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       std::pair<int, SignalInformation> acceptPendingSignal(uint8_t signalNumber);
+
+       /**
+        * \brief Hook function executed when delivery of signals is started.
+        *
+        * Calls SignalsCatcherControlBlock::deliveryOfSignalsStartedHook().
+        *
+        * \attention This function should be called only by the function that delivers signals (<em>deliverSignals()</em>).
+        *
+        * \return 0 on success, error code otherwise:
+        * - ENOTSUP - catching/handling of signals is disabled for this receiver;
+        */
+
+       int deliveryOfSignalsStartedHook() const;
+
+       /**
+        * \brief Generates signal for associated thread.
+        *
+        * Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
+        *
+        * Adds the signalNumber to set of pending signals. If associated thread is currently waiting for this signal, it
+        * will be unblocked.
+        *
+        * \param [in] signalNumber is the signal that will be generated, [0; 31]
+        * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       int generateSignal(uint8_t signalNumber, ThreadControlBlock& threadControlBlock);
+
+       /**
+        * \return set of currently pending signals
+        */
+
+       SignalSet getPendingSignalSet() const;
+
+       /**
+        * \brief Gets SignalAction associated with given signal number.
+        *
+        * Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
+        *
+        * \param [in] signalNumber is the signal for which the association is requested, [0; 31]
+        *
+        * \return pair with return code (0 on success, error code otherwise) and SignalAction that is associated with
+        * \a signalNumber, default-constructed object if no association was found;
+        * error codes:
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - catching/handling of signals is disabled for this receiver;
+        */
+
+       std::pair<int, SignalAction> getSignalAction(uint8_t signalNumber) const;
+
+       /**
+        * \brief Gets signal mask for associated thread.
+        *
+        * Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
+        *
+        * \return SignalSet with signal mask for associated thread
+        */
+
+       SignalSet getSignalMask() const;
+
+       /**
+        * \brief Queues signal for associated thread.
+        *
+        * Similar to sigqueue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigqueue.html
+        *
+        * Queues the signalNumber and signal value (sigval union) in associated SignalInformationQueue object. If
+        * associated thread is currently waiting for this signal, it will be unblocked.
+        *
+        * \param [in] signalNumber is the signal that will be queued, [0; 31]
+        * \param [in] value is the signal value
+        * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
+        *
+        * \return 0 on success, error code otherwise:
+        * - EAGAIN - no resources are available to queue the signal, maximal number of signals is already queued in
+        * associated SignalInformationQueue object;
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - queuing of signals is disabled for this receiver;
+        */
+
+       int queueSignal(uint8_t signalNumber, sigval value, ThreadControlBlock& threadControlBlock) const;
+
+       /**
+        * \brief Sets association for given signal number.
+        *
+        * Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
+        *
+        * \param [in] signalNumber is the signal for which the association will be set, [0; 31]
+        * \param [in] signalAction is a reference to SignalAction that will be associated with given signal number, object
+        * in internal storage is copy-constructed
+        *
+        * \return pair with return code (0 on success, error code otherwise) and SignalAction that was associated with
+        * \a signalNumber, default-constructed object if no association was found;
+        * error codes:
+        * - EAGAIN - no resources are available to associate \a signalNumber with \a signalAction;
+        * - EINVAL - \a signalNumber value is invalid;
+        * - ENOTSUP - catching/handling of signals is disabled for this receiver;
+        */
+
+       std::pair<int, SignalAction> setSignalAction(uint8_t signalNumber, const SignalAction& signalAction);
+
+       /**
+        * \brief Sets signal mask for associated thread.
+        *
+        * Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
+        *
+        * \param [in] signalMask is the SignalSet with new signal mask for associated thread
+        * \param [in] requestDelivery selects whether delivery of signals will be requested if any pending signal is
+        * unblocked (true) or not (false)
+        *
+        * \return 0 on success, error code otherwise:
+        * - ENOTSUP - catching/handling of signals is disabled for this receiver;
+        */
+
+       int setSignalMask(SignalSet signalMask, bool requestDelivery);
+
+       /**
+        * \param [in] signalSet is a pointer to set of signals that will be "waited for", nullptr when wait was terminated
+        */
+
+       void setWaitingSignalSet(const SignalSet* const signalSet)
+       {
+               waitingSignalSet_ = signalSet;
+       }
+
+private:
+
+       /**
+        * \brief Checks whether signal is ignored.
+        *
+        * Signal is ignored if it has no SignalAction object associated. Signal is never ignored if catching/handling of
+        * signals is disabled for this receiver.
+        *
+        * \param [in] signalNumber is the signal for which the check will be performed, [0; 31]
+        *
+        * \return pair with return code (0 on success, error code otherwise) and boolean telling whether the signal is
+        * ignored (true) or not (false);
+        * error codes:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       std::pair<int, bool> isSignalIgnored(uint8_t signalNumber) const;
+
+       /**
+        * \brief Actions executed after signal is "generated" with generateSignal() or queueSignal().
+        *
+        * If associated thread is currently waiting for the signal that was generated, it will be unblocked.
+        *
+        * \param [in] signalNumber is the signal that was generated, [0; 31]
+        * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
+        *
+        * \return 0 on success, error code otherwise:
+        * - EINVAL - \a signalNumber value is invalid;
+        */
+
+       int postGenerate(uint8_t signalNumber, ThreadControlBlock& threadControlBlock) const;
+
+       /// set of pending signals
+       SignalSet pendingSignalSet_;
+
+       /// pointer to set of "waited for" signals, nullptr if associated thread is not waiting for any signals
+       const SignalSet* waitingSignalSet_;
+
+       /// pointer to SignalsCatcherControlBlock for this receiver, nullptr if this receiver cannot catch/handle signals
+       SignalsCatcherControlBlock* signalsCatcherControlBlock_;
+
+       /// pointer to SignalInformationQueue for this receiver, nullptr if this receiver cannot queue signals
+       SignalInformationQueue* signalInformationQueue_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
diff --git a/include/distortos/internal/synchronization/SwapPopQueueFunctor.hpp b/include/distortos/internal/synchronization/SwapPopQueueFunctor.hpp
new file mode 100644 (file)
index 0000000..1009f3c
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * \file
+ * \brief SwapPopQueueFunctor class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SWAPPOPQUEUEFUNCTOR_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SWAPPOPQUEUEFUNCTOR_HPP_
+
+#include "distortos/internal/synchronization/QueueFunctor.hpp"
+
+#include <utility>
+
+namespace distortos
+{
+
+namespace internal
+{
+
+/**
+ * SwapPopQueueFunctor is a functor used for popping of data from the queue using swap
+ *
+ * \tparam T is the type of data popped from the queue
+ */
+
+template<typename T>
+class SwapPopQueueFunctor : public QueueFunctor
+{
+public:
+
+       /**
+        * \brief SwapPopQueueFunctor's constructor
+        *
+        * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+        * with the value in the queue's storage and destructed when no longer needed
+        */
+
+       constexpr explicit SwapPopQueueFunctor(T& value) :
+                       value_{value}
+       {
+
+       }
+
+       /**
+        * \brief Swaps the element in the queue's storage with the value provided by user and destroys this value when no
+        * longer needed.
+        *
+        * \param [in,out] storage is a pointer to storage with element
+        */
+
+       void operator()(void* const storage) const override
+       {
+               auto& swappedValue = *reinterpret_cast<T*>(storage);
+               using std::swap;
+               swap(value_, swappedValue);
+               swappedValue.~T();
+       }
+
+private:
+
+       /// reference to object that will be used to return popped value
+       T& value_;
+};
+
+}      // namespace internal
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SWAPPOPQUEUEFUNCTOR_HPP_
diff --git a/include/distortos/statistics.hpp b/include/distortos/statistics.hpp
new file mode 100644 (file)
index 0000000..68645ef
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * \file
+ * \brief statistics namespace header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_STATISTICS_HPP_
+#define INCLUDE_DISTORTOS_STATISTICS_HPP_
+
+#include <cstdint>
+
+namespace distortos
+{
+
+namespace statistics
+{
+
+/// \addtogroup statistics
+/// \{
+
+/**
+ * \return number of context switches
+ */
+
+uint64_t getContextSwitchCount();
+
+/// \}
+
+}      // namespace statistics
+
+}      // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_STATISTICS_HPP_
diff --git a/include/estd/ContiguousRange.hpp b/include/estd/ContiguousRange.hpp
new file mode 100644 (file)
index 0000000..adfc8a0
--- /dev/null
@@ -0,0 +1,164 @@
+/**
+ * \file
+ * \brief ContiguousRange template class header.
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_CONTIGUOUSRANGE_HPP_
+#define ESTD_CONTIGUOUSRANGE_HPP_
+
+#include <iterator>
+
+namespace estd
+{
+
+/**
+ * \brief ContiguousRange template class is a pair of iterators to contiguous sequence of elements in memory
+ *
+ * \tparam T is the type of data in the range
+ */
+
+template<typename T>
+class ContiguousRange
+{
+public:
+
+       /// value_type type
+       using value_type = T;
+
+       /// pointer type
+       using pointer = value_type*;
+
+       /// const_pointer type
+       using const_pointer = const value_type*;
+
+       /// reference type
+       using reference = value_type&;
+
+       /// const_reference type
+       using const_reference = const value_type&;
+
+       /// iterator type
+       using iterator = value_type*;
+
+       /// const_iterator type
+       using const_iterator = const value_type*;
+
+       /// size_type type
+       using size_type = std::size_t;
+
+       /// difference_type type
+       using difference_type = std::ptrdiff_t;
+
+       /// reverse_iterator type
+       using reverse_iterator = std::reverse_iterator<iterator>;
+
+       /// const_reverse_iterator type
+       using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+       /**
+        * \brief ContiguousRange's constructor.
+        *
+        * \param [in] beginn is an iterator to first element in the range
+        * \param [in] endd is an iterator to "one past the last" element in the range
+        */
+
+       constexpr ContiguousRange(const iterator beginn, const iterator endd) noexcept :
+                       begin_{beginn},
+                       end_{endd}
+       {
+
+       }
+
+       /**
+        * \brief Empty ContiguousRange's constructor.
+        */
+
+       constexpr explicit ContiguousRange() noexcept :
+                       ContiguousRange{nullptr, nullptr}
+       {
+
+       }
+
+       /**
+        * \brief ContiguousRange's constructor using C-style array.
+        *
+        * \tparam N is the number of elements in the array
+        *
+        * \param [in] array is the array used to initialize the range
+        */
+
+       template<size_t N>
+       constexpr explicit ContiguousRange(T (& array)[N]) noexcept :
+                       ContiguousRange{array, array + N}
+       {
+
+       }
+
+       /**
+        * \brief ContiguousRange's constructor using single value
+        *
+        * \param [in] value is a reference to variable used to initialize the range
+        */
+
+       constexpr explicit ContiguousRange(T& value) noexcept :
+                       ContiguousRange{&value, &value + 1}
+       {
+
+       }
+
+       /**
+        * \return iterator to first element in the range
+        */
+
+       constexpr iterator begin() const noexcept
+       {
+               return begin_;
+       }
+
+       /**
+        * \return iterator to "one past the last" element in the range
+        */
+
+       constexpr iterator end() const noexcept
+       {
+               return end_;
+       }
+
+       /**
+        * \return number of elements in the range
+        */
+
+       constexpr size_type size() const noexcept
+       {
+               return end_ - begin_;
+       }
+
+       /**
+        * \param [in] i is the index of element that will be accessed
+        *
+        * \return reference to element at given index
+        */
+
+       reference operator[](const size_type i) const noexcept
+       {
+               return begin_[i];
+       }
+
+private:
+
+       /// iterator to first element in the range
+       iterator begin_;
+
+       /// iterator to "one past the last" element in the range
+       iterator end_;
+};
+
+}      // namespace estd
+
+#endif // ESTD_CONTIGUOUSRANGE_HPP_
diff --git a/include/estd/IntegerSequence.hpp b/include/estd/IntegerSequence.hpp
new file mode 100644 (file)
index 0000000..a0776f5
--- /dev/null
@@ -0,0 +1,229 @@
+/**
+ * \file
+ * \brief IntegerSequence template class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_INTEGERSEQUENCE_HPP_
+#define ESTD_INTEGERSEQUENCE_HPP_
+
+#include <type_traits>
+
+namespace estd
+{
+
+/**
+ * \brief Compile-time sequence of integers
+ *
+ * Similar to std::integer_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
+ *
+ * \tparam T is an integer type to use for the elements of the sequence
+ * \tparam Integers is a non-type parameter pack representing the sequence
+ */
+
+template<typename T, T... Integers>
+class IntegerSequence
+{
+public:
+
+       /// integer type used for the elements of the sequence
+       using value_type = T;
+
+       /**
+        * \return number of elements in the sequence
+        */
+
+       constexpr static std::size_t size() noexcept
+       {
+               return sizeof...(Integers);
+       };
+};
+
+/**
+ * \brief Compile-time sequence of std::size_t elements
+ *
+ * Similar to std::index_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
+ *
+ * \tparam Indexes is a non-type parameter pack representing the sequence
+ */
+
+template<std::size_t... Indexes>
+using IndexSequence = IntegerSequence<std::size_t, Indexes...>;
+
+namespace internal
+{
+
+/**
+ * \brief IntegerSequence with two internal type aliases.
+ *
+ * \tparam T is an integer type to use for the elements of the sequence
+ * \tparam Integers is a non-type parameter pack representing the sequence
+ */
+
+template<typename T, T... Integers>
+struct TypedSequence : IntegerSequence<T, Integers...>
+{
+       /// type of base class
+       using base = IntegerSequence<T, Integers...>;
+
+       /// type of class
+       using type = TypedSequence;
+};
+
+/**
+ * \brief TypedSequence with doubled number of elements
+ *
+ * \tparam Sequence is the type of sequence that will be doubled
+ */
+
+template<typename Sequence>
+struct DoubledIntegerSequence;
+
+/**
+ * \brief TypedSequence with doubled number of elements
+ *
+ * Specialization for TypedSequence.
+ *
+ * \tparam T is an integer type to use for the elements of the sequence
+ * \tparam Integers is a non-type parameter pack representing the sequence
+ */
+
+template<typename T, T... Integers>
+struct DoubledIntegerSequence<TypedSequence<T, Integers...>>
+{
+       /// TypedSequence with doubled number of elements - TypedSequence<T, 0, 1, ..., N - 1> is turned into
+       /// TypedSequence<T, 0, 1, ..., N - 1, N, N + 1, ..., 2 * N - 1>
+       using type = TypedSequence<T, Integers..., (sizeof...(Integers) + Integers)...>;
+};
+
+/**
+ * \brief TypedSequence optionally extended by one element
+ *
+ * \tparam Extend selects whether the sequence will be extended by one element (true) or not (false)
+ * \tparam Sequence is the type of sequence that will optionally be extended
+ */
+
+template<bool Extend, typename Sequence>
+struct ExtendedIntegerSequence
+{
+       /// same as \a Sequence
+       using type = Sequence;
+};
+
+/**
+ * \brief TypedSequence optionally extended by one element
+ *
+ * Specialization for the case with extending.
+ *
+ * \tparam T is an integer type to use for the elements of the sequence
+ * \tparam Integers is a non-type parameter pack representing the sequence
+ */
+
+template<typename T, T... Integers>
+struct ExtendedIntegerSequence<true, TypedSequence<T, Integers...>>
+{
+       /// sequence extended by one element - TypedSequence<T, 0, 1, ..., N - 1> is turned into
+       /// TypedSequence<T, 0, 1, ..., N - 1, N>
+       using type = TypedSequence<T, Integers..., sizeof...(Integers)>;
+};
+
+/**
+ * \brief Implementation of generator of IntegerSequence types
+ *
+ * Generates TypedSequence<T, 0, 1, ..., N - 1> type.
+ *
+ * \tparam T is an integer type to use for the elements of the sequence
+ * \tparam N is the requested number of elements in the sequence
+ */
+
+template<typename T, std::size_t N>
+struct MakeIntegerSequenceImplementation :
+               ExtendedIntegerSequence<N % 2 != 0,
+                               typename DoubledIntegerSequence<typename MakeIntegerSequenceImplementation<T, N / 2>::type>::type>
+{
+
+};
+
+/**
+ * \brief Implementation of generator of IntegerSequence types
+ *
+ * Specialization for terminal case - 0 elements - generates TypedSequence<T> type.
+ *
+ * \tparam T is an integer type to use for the elements of the sequence
+ */
+
+template<typename T>
+struct MakeIntegerSequenceImplementation<T, 0>
+{
+       /// empty TypedSequence<T> type
+       using type = TypedSequence<T>;
+};
+
+/**
+ * \brief Wrapper for MakeIntegerSequenceImplementation that ensures \a N is non-negative
+ *
+ * Generates TypedSequence<T, 0, 1, ..., N - 1> type.
+ *
+ * \tparam T is an integer type to use for the elements of the sequence
+ * \tparam N is the requested number of elements in the sequence, must be non-negative
+ */
+
+template<typename T, T N>
+struct MakeIntegerSequenceImplementationWrapper :
+               std::enable_if<N >= 0, MakeIntegerSequenceImplementation<T, static_cast<std::size_t>(N)>>::type
+{
+       static_assert(N >= 0, "Number of elements in the sequence must be non-negative!");
+};
+
+}      // namespace internal
+
+/**
+ * \brief Generator of IntegerSequence types
+ *
+ * Similar to std::make_integer_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
+ *
+ * Whole implementation is based on code from http://stackoverflow.com/a/20101039/157344
+ *
+ * Generates IntegerSequence<T, 0, 1, ..., N - 1> type.
+ *
+ * \tparam T is an integer type to use for the elements of the sequence
+ * \tparam N is the requested number of elements in the sequence
+ */
+
+template<typename T, T N>
+using MakeIntegerSequence = typename internal::MakeIntegerSequenceImplementationWrapper<T, N>::type::base;
+
+/**
+ * \brief Generator of IndexSequence types
+ *
+ * Similar to std::make_index_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
+ *
+ * Generates IndexSequence<0, 1, ..., N - 1> type.
+ *
+ * \tparam N is the requested number of elements in the sequence
+ */
+
+template<std::size_t N>
+using MakeIndexSequence = MakeIntegerSequence<std::size_t, N>;
+
+/**
+ * \brief Generator of IndexSequence types
+ *
+ * Similar to std::index_sequence_for from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
+ *
+ * Generates IndexSequence<0, 1, ..., sizeof...(T) - 1> type.
+ *
+ * \tparam T is the type parameter pack for which an index sequence of the same length will be generated
+ */
+
+template<typename... T>
+using IndexSequenceFor = MakeIndexSequence<sizeof...(T)>;
+
+}      // namespace estd
+
+#endif // ESTD_INTEGERSEQUENCE_HPP_
diff --git a/include/estd/IntrusiveForwardList.hpp b/include/estd/IntrusiveForwardList.hpp
new file mode 100644 (file)
index 0000000..faa98d1
--- /dev/null
@@ -0,0 +1,1120 @@
+/**
+ * \file
+ * \brief IntrusiveForwardList template class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_INTRUSIVEFORWARDLIST_HPP_
+#define ESTD_INTRUSIVEFORWARDLIST_HPP_
+
+#include <iterator>
+
+#include <cstddef>
+
+namespace estd
+{
+
+namespace internal
+{
+
+class IntrusiveForwardListBase;
+
+}
+
+/**
+ * \brief IntrusiveForwardListNode class is the node that is needed for the object to be linked in IntrusiveForwardList
+ *
+ * To some extent, this class can be considered to be a limited (raw) iterator.
+ *
+ * The object that wants to be linked in IntrusiveForwardList must contain a variable of this type - one for each
+ * intrusive forward list that will be used with object.
+ */
+
+class IntrusiveForwardListNode
+{
+public:
+
+       /// AccessKey class is used to limit access to IntrusiveForwardListNode's linkAfter() and unlinkNext() functions -
+       /// only internal::IntrusiveForwardListBase can link/unlink nodes
+       class AccessKey
+       {
+               friend class internal::IntrusiveForwardListBase;
+
+               /**
+                * \brief AccessKey's constructor
+                */
+
+               constexpr AccessKey()
+               {
+
+               }
+
+               AccessKey(const AccessKey&) = delete;
+               AccessKey(AccessKey&&) = delete;
+               const AccessKey& operator=(const AccessKey&) = delete;
+               AccessKey& operator=(AccessKey&&) = delete;
+       };
+
+       /**
+        * \brief IntrusiveForwardListNode's constructor
+        */
+
+       constexpr IntrusiveForwardListNode() :
+                       nextNode_{}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveForwardListNode's move constructor
+        *
+        * \param [in] other is a rvalue reference to IntrusiveForwardListNode used as source of move construction
+        */
+
+       IntrusiveForwardListNode(IntrusiveForwardListNode&& other) :
+                       nextNode_{other.nextNode_}
+       {
+               other.reset();
+       }
+
+       /**
+        * \return pointer to next node on the list
+        */
+
+       IntrusiveForwardListNode* getNextNode() const
+       {
+               return nextNode_;
+       }
+
+       /**
+        * \return true if the node is linked in some list, false otherwise
+        */
+
+       bool isLinked() const
+       {
+               return nextNode_ != nullptr;
+       }
+
+       /**
+        * \brief Links the node in the list after \a position.
+        *
+        * \note Access to this function is restricted only to functions from internal::IntrusiveForwardListBase class
+        *
+        * \param [in] position is a pointer to node after which this node will be linked
+        * \param [in] accessKey is used to limit access to this function
+        */
+
+       void linkAfter(IntrusiveForwardListNode* const position, AccessKey)
+       {
+               nextNode_ = position->getNextNode();
+               position->nextNode_ = this;
+       }
+
+       /**
+        * \brief Swaps contents with another node.
+        *
+        * \param [in] other is a reference to IntrusiveForwardListNode with which contents of this node will be swapped
+        */
+
+       void swap(IntrusiveForwardListNode& other)
+       {
+               using std::swap;
+               swap(nextNode_, other.nextNode_);
+       }
+
+       /**
+        * \brief Unlinks the node following this one from the list.
+        *
+        * \note Access to this function is restricted only to functions from internal::IntrusiveForwardListBase class
+        *
+        * \param [in] accessKey is used to limit access to this function
+        */
+
+       void unlinkNext(AccessKey)
+       {
+               auto& nextNode = *nextNode_;
+               nextNode_ = nextNode.nextNode_;
+
+               nextNode.reset();
+       }
+
+       IntrusiveForwardListNode(const IntrusiveForwardListNode&) = delete;
+       const IntrusiveForwardListNode& operator=(const IntrusiveForwardListNode&) = delete;
+       IntrusiveForwardListNode& operator=(IntrusiveForwardListNode&&) = delete;
+
+private:
+
+       /**
+        * \brief Resets the node to the same state as right after construction.
+        */
+
+       void reset()
+       {
+               nextNode_ = {};
+       }
+
+       /// pointer to next node on the list
+       IntrusiveForwardListNode* nextNode_;
+};
+
+/**
+ * \brief Swaps contents of two nodes.
+ *
+ * \param [in] left is a reference to IntrusiveForwardListNode with which contents of \a right will be swapped
+ * \param [in] right is a reference to IntrusiveForwardListNode with which contents of \a left will be swapped
+ */
+
+inline void swap(IntrusiveForwardListNode& left, IntrusiveForwardListNode& right)
+{
+       left.swap(right);
+}
+
+namespace internal
+{
+
+/**
+ * \brief IntrusiveForwardListBase class provides base functionalities for IntrusiveForwardList class, but without any
+ * knowledge about types
+ *
+ * This class tries to provide an interface similar to std::forward_list.
+ */
+
+class IntrusiveForwardListBase
+{
+public:
+
+       /**
+        * \brief IntrusiveForwardListBase's constructor
+        */
+
+       constexpr IntrusiveForwardListBase() :
+                       rootNode_{}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveForwardListBase's destructor
+        *
+        * Unlinks all nodes from the list.
+        */
+
+       ~IntrusiveForwardListBase()
+       {
+               clear();
+       }
+
+       /**
+        * \return pointer to "one before the first" node on the list
+        */
+
+       IntrusiveForwardListNode* before_begin()
+       {
+               return &rootNode_;
+       }
+
+       /**
+        * \return const pointer to "one before the first" node on the list
+        */
+
+       const IntrusiveForwardListNode* before_begin() const
+       {
+               return &rootNode_;
+       }
+
+       /**
+        * \return pointer to first node on the list
+        */
+
+       IntrusiveForwardListNode* begin()
+       {
+               return rootNode_.getNextNode();
+       }
+
+       /**
+        * \return const pointer to first node on the list
+        */
+
+       const IntrusiveForwardListNode* begin() const
+       {
+               return rootNode_.getNextNode();
+       }
+
+       /**
+        * \return const pointer to "one before the first" node on the list
+        */
+
+       const IntrusiveForwardListNode* cbefore_begin() const
+       {
+               return before_begin();
+       }
+
+       /**
+        * \return const pointer to first node on the list
+        */
+
+       const IntrusiveForwardListNode* cbegin() const
+       {
+               return begin();
+       }
+
+       /**
+        * \return const pointer to "one past the last" node on the list
+        */
+
+       const IntrusiveForwardListNode* cend() const
+       {
+               return end();
+       }
+
+       /**
+        * \brief Unlinks all nodes from the list.
+        */
+
+       void clear()
+       {
+               while (empty() == false)
+                       pop_front();
+       }
+
+       /**
+        * \return true is the list is empty, false otherwise
+        */
+
+       bool empty() const
+       {
+               return begin() == end();
+       }
+
+       /**
+        * \return pointer to "one past the last" node on the list
+        */
+
+       IntrusiveForwardListNode* end()
+       {
+               return nullptr;
+       }
+
+       /**
+        * \return const pointer to "one past the last" node on the list
+        */
+
+       const IntrusiveForwardListNode* end() const
+       {
+               return nullptr;
+       }
+
+       /**
+        * \brief Unlinks the first node from the list.
+        */
+
+       void pop_front()
+       {
+               erase_after(before_begin());
+       }
+
+       /**
+        * \brief Links the node at the beginning of the list.
+        *
+        * \param [in] newNode is a reference to node that will be linked in the list
+        */
+
+       void push_front(IntrusiveForwardListNode& newNode)
+       {
+               insert_after(before_begin(), newNode);
+       }
+
+       /**
+        * \brief Swaps contents with another list.
+        *
+        * \param [in] other is a reference to IntrusiveForwardListBase with which contents of this list will be swapped
+        */
+
+       void swap(IntrusiveForwardListBase& other)
+       {
+               rootNode_.swap(other.rootNode_);
+       }
+
+       /**
+        * \brief Unlinks the node following \a position from the list.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is a pointer to the node preceding the one which will be unlinked from the list
+        *
+        * \return pointer to the node that was following the node which was unlinked
+        */
+
+       static IntrusiveForwardListNode* erase_after(IntrusiveForwardListNode* const position)
+       {
+               position->unlinkNext({});
+               return position->getNextNode();
+       }
+
+       /**
+        * \brief Links the node in the list after \a position.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is a pointer to node after which \a newNode will be linked
+        * \param [in] newNode is a reference to node that will be linked in the list
+        */
+
+       static void insert_after(IntrusiveForwardListNode* const position, IntrusiveForwardListNode& newNode)
+       {
+               newNode.linkAfter(position, {});
+       }
+
+       /**
+        * \brief Transfers the node from one list to another list after \a position.
+        *
+        * \note No instance of any list is needed for this operation.
+        *
+        * \param [in] position is a pointer to node after which spliced node will be linked
+        * \param [in] beforeSplicedNode is a pointer to node preceding the one which will be spliced from one list to
+        * another
+        */
+
+       static void splice_after(IntrusiveForwardListNode* const position,
+                       IntrusiveForwardListNode* const beforeSplicedNode)
+       {
+               const auto splicedNode = beforeSplicedNode->getNextNode();
+               erase_after(beforeSplicedNode);
+               insert_after(position, *splicedNode);
+       }
+
+       IntrusiveForwardListBase(const IntrusiveForwardListBase&) = delete;
+       IntrusiveForwardListBase(IntrusiveForwardListBase&&) = default;
+       const IntrusiveForwardListBase& operator=(const IntrusiveForwardListBase&) = delete;
+       IntrusiveForwardListBase& operator=(IntrusiveForwardListBase&&) = delete;
+
+private:
+
+       /// root node of the intrusive forward list
+       IntrusiveForwardListNode rootNode_;
+};
+
+/**
+ * \brief Swaps contents of two lists.
+ *
+ * \param [in] left is a reference to IntrusiveForwardListBase with which contents of \a right will be swapped
+ * \param [in] right is a reference to IntrusiveForwardListBase with which contents of \a left will be swapped
+ */
+
+inline void swap(IntrusiveForwardListBase& left, IntrusiveForwardListBase& right)
+{
+       left.swap(right);
+}
+
+}      // namespace internal
+
+/**
+ * \brief IntrusiveForwardListIterator class is an iterator of elements on IntrusiveForwardList.
+ *
+ * This class provides an interface similar to std::forward_list::iterator.
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ */
+
+template<typename T, IntrusiveForwardListNode T::* NodePointer, typename U = T>
+class IntrusiveForwardListIterator
+{
+public:
+
+       /// difference type
+       using difference_type = ptrdiff_t;
+
+       /// category of the iterator
+       using iterator_category = std::forward_iterator_tag;
+
+       /// pointer to object "pointed to" by the iterator
+       using pointer = U*;
+
+       /// reference to object "pointed to" by the iterator
+       using reference = U&;
+
+       /// value "pointed to" by the iterator
+       using value_type = U;
+
+       /**
+        * \brief IntrusiveForwardListIterator's constructor
+        */
+
+       constexpr IntrusiveForwardListIterator() :
+                       node_{}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveForwardListIterator's constructor
+        *
+        * \param [in] node is a pointer to IntrusiveForwardListNode of element that will be "pointed to" by the iterator
+        */
+
+       constexpr explicit IntrusiveForwardListIterator(IntrusiveForwardListNode* const node) :
+                       node_{node}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveForwardListIterator's constructor
+        *
+        * \param [in] element is a reference to element that will be "pointed to" by the iterator
+        */
+
+       constexpr explicit IntrusiveForwardListIterator(reference element) :
+                       node_{&(element.*NodePointer)}
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+       }
+
+       /**
+        * \brief IntrusiveForwardListIterator's binary infix pointer member access operator
+        *
+        * \return pointer to object "pointed to" by the iterator
+        */
+
+       pointer operator->() const
+       {
+               return getPointer();
+       }
+
+       /**
+        * \brief IntrusiveForwardListIterator's unary prefix dereference operator
+        *
+        * \return reference to object "pointed to" by the iterator
+        */
+
+       reference operator*() const
+       {
+               return *getPointer();
+       }
+
+       /**
+        * \brief IntrusiveForwardListIterator's unary prefix increment operator
+        *
+        * \return reference to "this" iterator
+        */
+
+       IntrusiveForwardListIterator& operator++()
+       {
+               node_ = node_->getNextNode();
+               return *this;
+       }
+
+       /**
+        * \brief IntrusiveForwardListIterator's unary postfix increment operator
+        *
+        * \return copy of "this" iterator before increment
+        */
+
+       IntrusiveForwardListIterator operator++(int)
+       {
+               const auto temporary = *this;
+               node_ = node_->getNextNode();
+               return temporary;
+       }
+
+       /**
+        * \brief IntrusiveForwardListIterator's "equal to" comparison operator
+        *
+        * \param [in] other is a const reference to IntrusiveForwardListIterator on right-hand side of equality operator
+        *
+        * \return true if both iterators are equal, false otherwise
+        */
+
+       bool operator==(const IntrusiveForwardListIterator& other) const
+       {
+               return node_ == other.node_;
+       }
+
+private:
+
+       /**
+        * \brief Converts contained pointer to IntrusiveForwardListNode to pointer to object that contains this node.
+        *
+        * \return pointer to object "pointed to" by the iterator
+        */
+
+       pointer getPointer() const
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+               const auto offset = reinterpret_cast<size_t>(&(static_cast<pointer>(nullptr)->*NodePointer));
+               return reinterpret_cast<pointer>(reinterpret_cast<size_t>(node_) - offset);
+       }
+
+       /// pointer to IntrusiveForwardListNode of the object "pointed to" by the iterator
+       IntrusiveForwardListNode* node_;
+};
+
+/**
+ * \brief IntrusiveForwardListIterator's "not equal to" comparison operator
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveForwardListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveForwardListIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveForwardListNode T::* NodePointer, typename U = T>
+inline bool operator!=(const IntrusiveForwardListIterator<T, NodePointer, U>& left,
+               const IntrusiveForwardListIterator<T, NodePointer, U>& right)
+{
+       return (left == right) == false;
+}
+
+/**
+ * \brief IntrusiveForwardListConstIterator class is a const iterator of elements on IntrusiveForwardList.
+ *
+ * This class provides an interface similar to std::forward_list::const_iterator.
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a const pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ */
+
+template<typename T, const IntrusiveForwardListNode T::* NodePointer, typename U = T>
+class IntrusiveForwardListConstIterator
+{
+public:
+
+       /// difference type
+       using difference_type = ptrdiff_t;
+
+       /// category of the iterator
+       using iterator_category = std::forward_iterator_tag;
+
+       /// pointer to object "pointed to" by the iterator
+       using pointer = const U*;
+
+       /// reference to object "pointed to" by the iterator
+       using reference = const U&;
+
+       /// value "pointed to" by the iterator
+       using value_type = U;
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's constructor
+        */
+
+       constexpr IntrusiveForwardListConstIterator() :
+                       node_{}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's constructor
+        *
+        * \param [in] node is a pointer to const IntrusiveForwardListNode of element that will be "pointed to" by the
+        * iterator
+        */
+
+       constexpr explicit IntrusiveForwardListConstIterator(const IntrusiveForwardListNode* const node) :
+                       node_{node}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's constructor
+        *
+        * \param [in] element is a const reference to element that will be "pointed to" by the iterator
+        */
+
+       constexpr explicit IntrusiveForwardListConstIterator(reference element) :
+                       node_{&(element.*NodePointer)}
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+       }
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's constructor
+        *
+        * Converts non-const iterator (IntrusiveForwardListIterator) to const iterator (IntrusiveForwardListConstIterator).
+        *
+        * \tparam NonConstNodePointer is a non-const version of \a NodePointer
+        *
+        * \param [in] iterator is a const reference to non-const iterator (IntrusiveForwardListIterator)
+        */
+
+       template<IntrusiveForwardListNode T::* NonConstNodePointer>
+       constexpr
+       IntrusiveForwardListConstIterator(const IntrusiveForwardListIterator<T, NonConstNodePointer, U>& iterator) :
+                       IntrusiveForwardListConstIterator{*iterator}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's binary infix pointer member access operator
+        *
+        * \return pointer to object "pointed to" by the iterator
+        */
+
+       pointer operator->() const
+       {
+               return getPointer();
+       }
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's unary prefix dereference operator
+        *
+        * \return reference to object "pointed to" by the iterator
+        */
+
+       reference operator*() const
+       {
+               return *getPointer();
+       }
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's unary prefix increment operator
+        *
+        * \return reference to "this" iterator
+        */
+
+       IntrusiveForwardListConstIterator& operator++()
+       {
+               node_ = node_->getNextNode();
+               return *this;
+       }
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's unary postfix increment operator
+        *
+        * \return copy of "this" iterator before increment
+        */
+
+       IntrusiveForwardListConstIterator operator++(int)
+       {
+               const auto temporary = *this;
+               node_ = node_->getNextNode();
+               return temporary;
+       }
+
+       /**
+        * \brief IntrusiveForwardListConstIterator's "equal to" comparison operator
+        *
+        * \param [in] other is a const reference to IntrusiveForwardListConstIterator on right-hand side of equality
+        * operator
+        *
+        * \return true if both iterators are equal, false otherwise
+        */
+
+       bool operator==(const IntrusiveForwardListConstIterator& other) const
+       {
+               return node_ == other.node_;
+       }
+
+private:
+
+       /**
+        * \brief Converts contained pointer to IntrusiveForwardListNode to pointer to object that contains this node.
+        *
+        * \return pointer to object "pointed to" by the iterator
+        */
+
+       pointer getPointer() const
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+               const auto offset = reinterpret_cast<size_t>(&(static_cast<pointer>(nullptr)->*NodePointer));
+               return reinterpret_cast<pointer>(reinterpret_cast<size_t>(node_) - offset);
+       }
+
+       /// pointer to const IntrusiveForwardListNode of the object "pointed to" by the iterator
+       const IntrusiveForwardListNode* node_;
+};
+
+/**
+ * \brief IntrusiveForwardListConstIterator's "not equal to" comparison operator
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a const pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveForwardListConstIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveForwardListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, const IntrusiveForwardListNode T::* NodePointer, typename U = T>
+inline bool operator!=(const IntrusiveForwardListConstIterator<T, NodePointer, U>& left,
+               const IntrusiveForwardListConstIterator<T, NodePointer, U>& right)
+{
+       return (left == right) == false;
+}
+
+/**
+ * \brief "Equal to" comparison operator for IntrusiveForwardListIterator and IntrusiveForwardListConstIterator
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveForwardListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveForwardListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if both iterators are equal, false otherwise
+ */
+
+template<typename T, IntrusiveForwardListNode T::* NodePointer, const IntrusiveForwardListNode T::* ConstNodePointer,
+               typename U = T>
+inline bool operator==(const IntrusiveForwardListIterator<T, NodePointer, U>& left,
+               const IntrusiveForwardListConstIterator<T, ConstNodePointer, U>& right)
+{
+       return decltype(right){left} == right;
+}
+
+/**
+ * \brief "Not equal to" comparison operator for IntrusiveForwardListIterator and IntrusiveForwardListConstIterator
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveForwardListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveForwardListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveForwardListNode T::* NodePointer, const IntrusiveForwardListNode T::* ConstNodePointer,
+               typename U = T>
+inline bool operator!=(const IntrusiveForwardListIterator<T, NodePointer, U>& left,
+               const IntrusiveForwardListConstIterator<T, ConstNodePointer, U>& right)
+{
+       return (left == right) == false;
+}
+
+/**
+ * \brief "Not equal to" comparison operator for IntrusiveForwardListConstIterator and IntrusiveForwardListIterator
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveForwardListConstIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveForwardListIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveForwardListNode T::* NodePointer, const IntrusiveForwardListNode T::* ConstNodePointer,
+               typename U = T>
+inline bool operator!=(const IntrusiveForwardListConstIterator<T, ConstNodePointer, U>& left,
+               const IntrusiveForwardListIterator<T, NodePointer, U>& right)
+{
+       return right != left;
+}
+
+/**
+ * \brief IntrusiveForwardList class is an intrusive linear singly linked list.
+ *
+ * This class tries to provide an interface similar to std::forward_list.
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T; using different type than \a T can be used
+ * to break circular dependencies, because \a T must be fully defined to instantiate this class, but it is enough to
+ * forward declare \a U - it only needs to be fully defined to use member functions
+ */
+
+template<typename T, IntrusiveForwardListNode T::* NodePointer, typename U = T>
+class IntrusiveForwardList
+{
+public:
+
+       /// const iterator of elements on the list
+       using const_iterator = IntrusiveForwardListConstIterator<T, NodePointer, U>;
+
+       /// const pointer to value linked in the list
+       using const_pointer = const U*;
+
+       /// const reference to value linked in the list
+       using const_reference = const U&;
+
+       /// iterator of elements on the list
+       using iterator = IntrusiveForwardListIterator<T, NodePointer, U>;
+
+       /// pointer to value linked in the list
+       using pointer = U*;
+
+       /// reference to value linked in the list
+       using reference = U&;
+
+       /// value linked in the list
+       using value_type = U;
+
+       /**
+        * \brief IntrusiveForwardList's constructor
+        */
+
+       constexpr IntrusiveForwardList() :
+                       intrusiveForwardListBase_{}
+       {
+
+       }
+
+       /**
+        * \return iterator of "one before the first" element on the list
+        */
+
+       iterator before_begin()
+       {
+               return iterator{intrusiveForwardListBase_.before_begin()};
+       }
+
+       /**
+        * \return const iterator of "one before the first" element on the list
+        */
+
+       const_iterator before_begin() const
+       {
+               return const_iterator{intrusiveForwardListBase_.before_begin()};
+       }
+
+       /**
+        * \return iterator of first element on the list
+        */
+
+       iterator begin()
+       {
+               return iterator{intrusiveForwardListBase_.begin()};
+       }
+
+       /**
+        * \return const iterator of first element on the list
+        */
+
+       const_iterator begin() const
+       {
+               return const_iterator{intrusiveForwardListBase_.begin()};
+       }
+
+       /**
+        * \return const iterator of "one before the first" element on the list
+        */
+
+       const_iterator cbefore_begin() const
+       {
+               return before_begin();
+       }
+
+       /**
+        * \return const iterator of first element on the list
+        */
+
+       const_iterator cbegin() const
+       {
+               return begin();
+       }
+
+       /**
+        * \return const iterator of "one past the last" element on the list
+        */
+
+       const_iterator cend() const
+       {
+               return end();
+       }
+
+       /**
+        * \brief Unlinks all elements from the list.
+        */
+
+       void clear()
+       {
+               intrusiveForwardListBase_.clear();
+       }
+
+       /**
+        * \return true is the list is empty, false otherwise
+        */
+
+       bool empty() const
+       {
+               return intrusiveForwardListBase_.empty();
+       }
+
+       /**
+        * \return iterator of "one past the last" element on the list
+        */
+
+       iterator end()
+       {
+               return iterator{intrusiveForwardListBase_.end()};
+       }
+
+       /**
+        * \return const iterator of "one past the last" element on the list
+        */
+
+       const_iterator end() const
+       {
+               return const_iterator{intrusiveForwardListBase_.end()};
+       }
+
+       /**
+        * \return reference to first element on the list
+        */
+
+       reference front()
+       {
+               return *begin();
+       }
+
+       /**
+        * \return const reference to first element on the list
+        */
+
+       const_reference front() const
+       {
+               return *begin();
+       }
+
+       /**
+        * \brief Unlinks the first element from the list.
+        */
+
+       void pop_front()
+       {
+               erase_after(before_begin());
+       }
+
+       /**
+        * \brief Links the element at the beginning of the list.
+        *
+        * \param [in] newElement is a reference to the element that will be linked in the list
+        */
+
+       void push_front(reference newElement)
+       {
+               insert_after(before_begin(), newElement);
+       }
+
+       /**
+        * \brief Swaps contents with another list.
+        *
+        * \param [in] other is a reference to IntrusiveForwardList with which contents of this list will be swapped
+        */
+
+       void swap(IntrusiveForwardList& other)
+       {
+               intrusiveForwardListBase_.swap(other.intrusiveForwardListBase_);
+       }
+
+       /**
+        * \brief Unlinks the element following \a position from the list.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is an iterator preceding the element which will be unlinked from the list
+        *
+        * \return iterator of the element that was following the element which was unlinked
+        */
+
+       static iterator erase_after(const iterator position)
+       {
+               auto& positionNode = (*position).*NodePointer;
+               const auto afterNextNode = internal::IntrusiveForwardListBase::erase_after(&positionNode);
+               return iterator{afterNextNode};
+       }
+
+       /**
+        * \brief Links the element in the list after \a position.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is an iterator of the element after which \a newNode will be linked
+        * \param [in] newElement is a reference to the element that will be linked in the list
+        *
+        * \return iterator of \a newElement
+        */
+
+       static iterator insert_after(const iterator position, reference newElement)
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+               auto& positionNode = (*position).*NodePointer;
+               auto& newElementNode = newElement.*NodePointer;
+               internal::IntrusiveForwardListBase::insert_after(&positionNode, newElementNode);
+               return iterator{&newElementNode};
+       }
+
+       /**
+        * \brief Transfers the element from one list to another list after \a position.
+        *
+        * \note No instance of any list is needed for this operation.
+        *
+        * \param [in] position is an iterator of the element after which spliced element will be linked
+        * \param [in] beforeSplicedElement is an iterator of the element preceding the one which will be spliced from one
+        * list to another
+        */
+
+       static void splice_after(const iterator position, const iterator beforeSplicedElement)
+       {
+               auto& positionNode = (*position).*NodePointer;
+               auto& beforeSplicedElementNode = (*beforeSplicedElement).*NodePointer;
+               internal::IntrusiveForwardListBase::splice_after(&positionNode, &beforeSplicedElementNode);
+       }
+
+       IntrusiveForwardList(const IntrusiveForwardList&) = delete;
+       IntrusiveForwardList(IntrusiveForwardList&&) = default;
+       const IntrusiveForwardList& operator=(const IntrusiveForwardList&) = delete;
+       IntrusiveForwardList& operator=(IntrusiveForwardList&&) = delete;
+
+private:
+
+       /// internal IntrusiveForwardListBase object
+       internal::IntrusiveForwardListBase intrusiveForwardListBase_;
+};
+
+/**
+ * \brief Swaps contents of two lists.
+ *
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a reference to IntrusiveForwardList with which contents of \a right will be swapped
+ * \param [in] right is a reference to IntrusiveForwardList with which contents of \a left will be swapped
+ */
+
+template<typename T, IntrusiveForwardListNode T::* NodePointer, typename U = T>
+inline void swap(IntrusiveForwardList<T, NodePointer, U>& left, IntrusiveForwardList<T, NodePointer, U>& right)
+{
+       left.swap(right);
+}
+
+}      // namespace estd
+
+#endif // ESTD_INTRUSIVEFORWARDLIST_HPP_
diff --git a/include/estd/IntrusiveList.hpp b/include/estd/IntrusiveList.hpp
new file mode 100644 (file)
index 0000000..82597f4
--- /dev/null
@@ -0,0 +1,1208 @@
+/**
+ * \file
+ * \brief IntrusiveList template class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_INTRUSIVELIST_HPP_
+#define ESTD_INTRUSIVELIST_HPP_
+
+#include <iterator>
+
+#include <cstddef>
+
+namespace estd
+{
+
+namespace internal
+{
+
+class IntrusiveListBase;
+
+}
+
+/**
+ * \brief IntrusiveListNode class is the node that is needed for the object to be linked in IntrusiveList
+ *
+ * To some extent, this class can be considered to be a limited (raw) iterator.
+ *
+ * The object that wants to be linked in IntrusiveList must contain a variable of this type - one for each intrusive
+ * list that will be used with object.
+ */
+
+class IntrusiveListNode
+{
+public:
+
+       /// LinkAccessKey class is used to limit access to IntrusiveListNode::link() function - only
+       /// internal::IntrusiveListBase can link nodes to the list
+       class LinkAccessKey
+       {
+               friend class internal::IntrusiveListBase;
+
+               /**
+                * \brief LinkAccessKey's constructor
+                */
+
+               constexpr LinkAccessKey()
+               {
+
+               }
+
+               LinkAccessKey(const LinkAccessKey&) = delete;
+               LinkAccessKey(LinkAccessKey&&) = delete;
+               const LinkAccessKey& operator=(const LinkAccessKey&) = delete;
+               LinkAccessKey& operator=(LinkAccessKey&&) = delete;
+       };
+
+       /**
+        * \brief IntrusiveListNode's constructor
+        */
+
+       constexpr IntrusiveListNode() :
+                       nextNode_{this},
+                       previousNode_{this}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveListNode's move constructor
+        *
+        * \param [in] other is a rvalue reference to IntrusiveListNode used as source of move construction
+        */
+
+       IntrusiveListNode(IntrusiveListNode&& other)
+       {
+               if (other.isLinked() == false)
+               {
+                       reset();
+                       return;
+               }
+
+               nextNode_ = other.nextNode_;
+               previousNode_ = other.previousNode_;
+               nextNode_->previousNode_ = previousNode_->nextNode_ = this;
+               other.reset();
+       }
+
+       /**
+        * \brief IntrusiveListNode's destructor
+        *
+        * Unlinks the node from the list.
+        */
+
+       ~IntrusiveListNode()
+       {
+               unlink();
+       }
+
+       /**
+        * \return reference to next node on the list
+        */
+
+       IntrusiveListNode& getNextNode() const
+       {
+               return *nextNode_;
+       }
+
+       /**
+        * \return reference to previous node on the list
+        */
+
+       IntrusiveListNode& getPreviousNode() const
+       {
+               return *previousNode_;
+       }
+
+       /**
+        * \return true if the node is linked in some list, false otherwise
+        */
+
+       bool isLinked() const
+       {
+               return nextNode_ != this;
+       }
+
+       /**
+        * \brief Links the node in the list before \a position.
+        *
+        * \note Access to this function is restricted only to functions from internal::IntrusiveListBase class
+        *
+        * \param [in] position is a reference to node before which this node will be linked
+        * \param [in] linkAccessKey is used to limit access to this function
+        */
+
+       void link(IntrusiveListNode& position, LinkAccessKey)
+       {
+               unlink();
+
+               nextNode_ = &position;
+               previousNode_ = position.previousNode_;
+               position.previousNode_->nextNode_ = this;
+               position.previousNode_ = this;
+       }
+
+       /**
+        * \brief Swaps contents with another node.
+        *
+        * \param [in] other is a reference to IntrusiveListNode with which contents of this node will be swapped
+        */
+
+       void swap(IntrusiveListNode& other)
+       {
+               const auto thisWasLinked = isLinked();
+               const auto otherWasLinked = other.isLinked();
+
+               if (thisWasLinked == true || otherWasLinked == true)
+               {
+                       using std::swap;
+                       swap(nextNode_, other.nextNode_);
+                       swap(previousNode_, other.previousNode_);
+
+                       if (thisWasLinked == true)
+                               other.nextNode_->previousNode_ = other.previousNode_->nextNode_ = &other;
+                       else
+                               other.reset();
+
+                       if (otherWasLinked == true)
+                               nextNode_->previousNode_ = previousNode_->nextNode_ = this;
+                       else
+                               reset();
+               }
+       }
+
+       /**
+        * \brief Unlinks the node from the list.
+        */
+
+       void unlink()
+       {
+               previousNode_->nextNode_ = nextNode_;
+               nextNode_->previousNode_ = previousNode_;
+
+               reset();
+       }
+
+       IntrusiveListNode(const IntrusiveListNode&) = delete;
+       const IntrusiveListNode& operator=(const IntrusiveListNode&) = delete;
+       IntrusiveListNode& operator=(IntrusiveListNode&&) = delete;
+
+private:
+
+       /**
+        * \brief Resets the node to the same state as right after construction.
+        */
+
+       void reset()
+       {
+               nextNode_ = this;
+               previousNode_ = this;
+       }
+
+       /// reference to next node on the list
+       IntrusiveListNode* nextNode_;
+
+       /// reference to previous node on the list
+       IntrusiveListNode* previousNode_;
+};
+
+namespace internal
+{
+
+/**
+ * \brief IntrusiveListBase class provides base functionalities for IntrusiveList class, but without any knowledge about
+ * types
+ *
+ * This class tries to provide an interface similar to std::list.
+ */
+
+class IntrusiveListBase
+{
+public:
+
+       /**
+        * \brief IntrusiveListBase's constructor
+        */
+
+       constexpr IntrusiveListBase() :
+                       rootNode_{}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveListBase's destructor
+        *
+        * Unlinks all nodes from the list.
+        */
+
+       ~IntrusiveListBase()
+       {
+               clear();
+       }
+
+       /**
+        * \return reference to first node on the list
+        */
+
+       IntrusiveListNode& begin()
+       {
+               return rootNode_.getNextNode();
+       }
+
+       /**
+        * \return const reference to first node on the list
+        */
+
+       const IntrusiveListNode& begin() const
+       {
+               return rootNode_.getNextNode();
+       }
+
+       /**
+        * \return const reference to first node on the list
+        */
+
+       const IntrusiveListNode& cbegin() const
+       {
+               return begin();
+       }
+
+       /**
+        * \return const reference to "one past the last" node on the list
+        */
+
+       const IntrusiveListNode& cend() const
+       {
+               return end();
+       }
+
+       /**
+        * \brief Unlinks all nodes from the list.
+        */
+
+       void clear()
+       {
+               while (empty() == false)
+                       pop_front();
+       }
+
+       /**
+        * \return true is the list is empty, false otherwise
+        */
+
+       bool empty() const
+       {
+               return &begin() == &end();
+       }
+
+       /**
+        * \return reference to "one past the last" node on the list
+        */
+
+       IntrusiveListNode& end()
+       {
+               return rootNode_;
+       }
+
+       /**
+        * \return const reference to "one past the last" node on the list
+        */
+
+       const IntrusiveListNode& end() const
+       {
+               return rootNode_;
+       }
+
+       /**
+        * \brief Unlinks the last node from the list.
+        */
+
+       void pop_back()
+       {
+               erase(end().getPreviousNode());
+       }
+
+       /**
+        * \brief Unlinks the first node from the list.
+        */
+
+       void pop_front()
+       {
+               erase(begin());
+       }
+
+       /**
+        * \brief Links the node at the end of the list.
+        *
+        * \param [in] newNode is a reference to node that will be linked in the list
+        */
+
+       void push_back(IntrusiveListNode& newNode)
+       {
+               insert(end(), newNode);
+       }
+
+       /**
+        * \brief Links the node at the beginning of the list.
+        *
+        * \param [in] newNode is a reference to node that will be linked in the list
+        */
+
+       void push_front(IntrusiveListNode& newNode)
+       {
+               insert(begin(), newNode);
+       }
+
+       /**
+        * \brief Swaps contents with another list.
+        *
+        * \param [in] other is a reference to IntrusiveListBase with which contents of this list will be swapped
+        */
+
+       void swap(IntrusiveListBase& other)
+       {
+               rootNode_.swap(other.rootNode_);
+       }
+
+       /**
+        * \brief Unlinks the node at \a position from the list.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is a reference to the node that will be unlinked from the list
+        *
+        * \return reference to the node that was following the node which was unlinked
+        */
+
+       static IntrusiveListNode& erase(IntrusiveListNode& position)
+       {
+               auto& next = position.getNextNode();
+               position.unlink();
+               return next;
+       }
+
+       /**
+        * \brief Links the node in the list before \a position.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is a reference to node before which \a newNode will be linked
+        * \param [in] newNode is a reference to node that will be linked in the list
+        */
+
+       static void insert(IntrusiveListNode& position, IntrusiveListNode& newNode)
+       {
+               newNode.link(position, {});
+       }
+
+       /**
+        * \brief Transfers the node from one list to another list before \a position.
+        *
+        * \note No instance of any list is needed for this operation.
+        *
+        * \param [in] position is a reference to node before which \a splicedNode will be linked
+        * \param [in] splicedNode is a reference to node that will be spliced from one list to another
+        */
+
+       static void splice(IntrusiveListNode& position, IntrusiveListNode& splicedNode)
+       {
+               insert(position, splicedNode);
+       }
+
+       IntrusiveListBase(const IntrusiveListBase&) = delete;
+       IntrusiveListBase(IntrusiveListBase&&) = default;
+       const IntrusiveListBase& operator=(const IntrusiveListBase&) = delete;
+       IntrusiveListBase& operator=(IntrusiveListBase&&) = delete;
+
+private:
+
+       /// root node of the intrusive list
+       IntrusiveListNode rootNode_;
+};
+
+/**
+ * \brief Swaps contents of two lists.
+ *
+ * \param [in] left is a reference to IntrusiveListBase with which contents of \a right will be swapped
+ * \param [in] right is a reference to IntrusiveListBase with which contents of \a left will be swapped
+ */
+
+inline void swap(IntrusiveListBase& left, IntrusiveListBase& right)
+{
+       left.swap(right);
+}
+
+}      // namespace internal
+
+/**
+ * \brief IntrusiveListIterator class is an iterator of elements on IntrusiveList.
+ *
+ * This class provides an interface similar to std::list::iterator.
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+class IntrusiveListIterator
+{
+public:
+
+       /// difference type
+       using difference_type = ptrdiff_t;
+
+       /// category of the iterator
+       using iterator_category = std::bidirectional_iterator_tag;
+
+       /// pointer to object "pointed to" by the iterator
+       using pointer = U*;
+
+       /// reference to object "pointed to" by the iterator
+       using reference = U&;
+
+       /// value "pointed to" by the iterator
+       using value_type = U;
+
+       /**
+        * \brief IntrusiveListIterator's constructor
+        */
+
+       constexpr IntrusiveListIterator() :
+                       node_{}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveListIterator's constructor
+        *
+        * \param [in] node is a pointer to IntrusiveListNode of element that will be "pointed to" by the iterator
+        */
+
+       constexpr explicit IntrusiveListIterator(IntrusiveListNode* const node) :
+                       node_{node}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveListIterator's constructor
+        *
+        * \param [in] element is a reference to element that will be "pointed to" by the iterator
+        */
+
+       constexpr explicit IntrusiveListIterator(reference element) :
+                       node_{&(element.*NodePointer)}
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+       }
+
+       /**
+        * \brief IntrusiveListIterator's binary infix pointer member access operator
+        *
+        * \return pointer to object "pointed to" by the iterator
+        */
+
+       pointer operator->() const
+       {
+               return getPointer();
+       }
+
+       /**
+        * \brief IntrusiveListIterator's unary prefix dereference operator
+        *
+        * \return reference to object "pointed to" by the iterator
+        */
+
+       reference operator*() const
+       {
+               return *getPointer();
+       }
+
+       /**
+        * \brief IntrusiveListIterator's unary prefix increment operator
+        *
+        * \return reference to "this" iterator
+        */
+
+       IntrusiveListIterator& operator++()
+       {
+               node_ = &node_->getNextNode();
+               return *this;
+       }
+
+       /**
+        * \brief IntrusiveListIterator's unary postfix increment operator
+        *
+        * \return copy of "this" iterator before increment
+        */
+
+       IntrusiveListIterator operator++(int)
+       {
+               const auto temporary = *this;
+               node_ = &node_->getNextNode();
+               return temporary;
+       }
+
+       /**
+        * \brief IntrusiveListIterator's unary prefix decrement operator
+        *
+        * \return reference to "this" iterator
+        */
+
+       IntrusiveListIterator& operator--()
+       {
+               node_ = &node_->getPreviousNode();
+               return *this;
+       }
+
+       /**
+        * \brief IntrusiveListIterator's unary postfix decrement operator
+        *
+        * \return copy of "this" iterator before decrement
+        */
+
+       IntrusiveListIterator operator--(int)
+       {
+               const auto temporary = *this;
+               node_ = &node_->getPreviousNode();
+               return temporary;
+       }
+
+       /**
+        * \brief IntrusiveListIterator's "equal to" comparison operator
+        *
+        * \param [in] other is a const reference to IntrusiveListIterator on right-hand side of comparison operator
+        *
+        * \return true if both iterators are equal, false otherwise
+        */
+
+       bool operator==(const IntrusiveListIterator& other) const
+       {
+               return node_ == other.node_;
+       }
+
+private:
+
+       /**
+        * \brief Converts contained pointer to IntrusiveListNode to pointer to object that contains this node.
+        *
+        * \return pointer to object "pointed to" by the iterator
+        */
+
+       pointer getPointer() const
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+               const auto offset = reinterpret_cast<size_t>(&(static_cast<pointer>(nullptr)->*NodePointer));
+               return reinterpret_cast<pointer>(reinterpret_cast<size_t>(node_) - offset);
+       }
+
+       /// pointer to IntrusiveListNode of the object "pointed to" by the iterator
+       IntrusiveListNode* node_;
+};
+
+/**
+ * \brief IntrusiveListIterator's "not equal to" comparison operator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+inline bool operator!=(const IntrusiveListIterator<T, NodePointer, U>& left,
+               const IntrusiveListIterator<T, NodePointer, U>& right)
+{
+       return (left == right) == false;
+}
+
+/**
+ * \brief IntrusiveListConstIterator class is a const iterator of elements on IntrusiveList.
+ *
+ * This class provides an interface similar to std::list::const_iterator.
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ */
+
+template<typename T, const IntrusiveListNode T::* NodePointer, typename U = T>
+class IntrusiveListConstIterator
+{
+public:
+
+       /// difference type
+       using difference_type = ptrdiff_t;
+
+       /// category of the iterator
+       using iterator_category = std::bidirectional_iterator_tag;
+
+       /// pointer to object "pointed to" by the iterator
+       using pointer = const U*;
+
+       /// reference to object "pointed to" by the iterator
+       using reference = const U&;
+
+       /// value "pointed to" by the iterator
+       using value_type = U;
+
+       /**
+        * \brief IntrusiveListConstIterator's constructor
+        */
+
+       constexpr IntrusiveListConstIterator() :
+                       node_{}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's constructor
+        *
+        * \param [in] node is a pointer to const IntrusiveListNode of element that will be "pointed to" by the iterator
+        */
+
+       constexpr explicit IntrusiveListConstIterator(const IntrusiveListNode* const node) :
+                       node_{node}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's constructor
+        *
+        * \param [in] element is a const reference to element that will be "pointed to" by the iterator
+        */
+
+       constexpr explicit IntrusiveListConstIterator(reference element) :
+                       node_{&(element.*NodePointer)}
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's constructor
+        *
+        * Converts non-const iterator (IntrusiveListIterator) to const iterator (IntrusiveListConstIterator).
+        *
+        * \tparam NonConstNodePointer is a non-const version of \a NodePointer
+        *
+        * \param [in] iterator is a const reference to non-const iterator (IntrusiveListIterator)
+        */
+
+       template<IntrusiveListNode T::* NonConstNodePointer>
+       constexpr IntrusiveListConstIterator(const IntrusiveListIterator<T, NonConstNodePointer, U>& iterator) :
+                       IntrusiveListConstIterator{*iterator}
+       {
+
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's binary infix pointer member access operator
+        *
+        * \return pointer to object "pointed to" by the iterator
+        */
+
+       pointer operator->() const
+       {
+               return getPointer();
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's unary prefix dereference operator
+        *
+        * \return reference to object "pointed to" by the iterator
+        */
+
+       reference operator*() const
+       {
+               return *getPointer();
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's unary prefix increment operator
+        *
+        * \return reference to "this" iterator
+        */
+
+       IntrusiveListConstIterator& operator++()
+       {
+               node_ = &node_->getNextNode();
+               return *this;
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's unary postfix increment operator
+        *
+        * \return copy of "this" iterator before increment
+        */
+
+       IntrusiveListConstIterator operator++(int)
+       {
+               const auto temporary = *this;
+               node_ = &node_->getNextNode();
+               return temporary;
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's unary prefix decrement operator
+        *
+        * \return reference to "this" iterator
+        */
+
+       IntrusiveListConstIterator& operator--()
+       {
+               node_ = &node_->getPreviousNode();
+               return *this;
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's unary postfix decrement operator
+        *
+        * \return copy of "this" iterator before decrement
+        */
+
+       IntrusiveListConstIterator operator--(int)
+       {
+               const auto temporary = *this;
+               node_ = &node_->getPreviousNode();
+               return temporary;
+       }
+
+       /**
+        * \brief IntrusiveListConstIterator's "equal to" comparison operator
+        *
+        * \param [in] other is a const reference to IntrusiveListConstIterator on right-hand side of comparison operator
+        *
+        * \return true if both iterators are equal, false otherwise
+        */
+
+       bool operator==(const IntrusiveListConstIterator& other) const
+       {
+               return node_ == other.node_;
+       }
+
+private:
+
+       /**
+        * \brief Converts contained pointer to IntrusiveListNode to pointer to object that contains this node.
+        *
+        * \return pointer to object "pointed to" by the iterator
+        */
+
+       pointer getPointer() const
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+               const auto offset = reinterpret_cast<size_t>(&(static_cast<pointer>(nullptr)->*NodePointer));
+               return reinterpret_cast<pointer>(reinterpret_cast<size_t>(node_) - offset);
+       }
+
+       /// pointer to const IntrusiveListNode of the object "pointed to" by the iterator
+       const IntrusiveListNode* node_;
+};
+
+/**
+ * \brief IntrusiveListConstIterator's "not equal to" comparison operator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListConstIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, const IntrusiveListNode T::* NodePointer, typename U = T>
+inline bool operator!=(const IntrusiveListConstIterator<T, NodePointer, U>& left,
+               const IntrusiveListConstIterator<T, NodePointer, U>& right)
+{
+       return (left == right) == false;
+}
+
+/**
+ * \brief "Equal to" comparison operator for IntrusiveListIterator and IntrusiveListConstIterator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if both iterators are equal, false otherwise
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, const IntrusiveListNode T::* ConstNodePointer, typename U = T>
+inline bool operator==(const IntrusiveListIterator<T, NodePointer, U>& left,
+               const IntrusiveListConstIterator<T, ConstNodePointer, U>& right)
+{
+       return decltype(right){left} == right;
+}
+
+/**
+ * \brief "Not equal to" comparison operator for IntrusiveListIterator and IntrusiveListConstIterator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, const IntrusiveListNode T::* ConstNodePointer, typename U = T>
+inline bool operator!=(const IntrusiveListIterator<T, NodePointer, U>& left,
+               const IntrusiveListConstIterator<T, ConstNodePointer, U>& right)
+{
+       return (left == right) == false;
+}
+
+/**
+ * \brief "Not equal to" comparison operator for IntrusiveListConstIterator and IntrusiveListIterator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListConstIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, const IntrusiveListNode T::* ConstNodePointer, typename U = T>
+inline bool operator!=(const IntrusiveListConstIterator<T, ConstNodePointer, U>& left,
+               const IntrusiveListIterator<T, NodePointer, U>& right)
+{
+       return right != left;
+}
+
+/**
+ * \brief IntrusiveList class is an intrusive circular doubly linked list.
+ *
+ * This class tries to provide an interface similar to std::list.
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T; using different type than \a T can be used
+ * to break circular dependencies, because \a T must be fully defined to instantiate this class, but it is enough to
+ * forward declare \a U - it only needs to be fully defined to use member functions
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+class IntrusiveList
+{
+public:
+
+       /// const iterator of elements on the list
+       using const_iterator = IntrusiveListConstIterator<T, NodePointer, U>;
+
+       /// const reverse iterator of elements on the list
+       using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+       /// const pointer to value linked in the list
+       using const_pointer = const U*;
+
+       /// const reference to value linked in the list
+       using const_reference = const U&;
+
+       /// iterator of elements on the list
+       using iterator = IntrusiveListIterator<T, NodePointer, U>;
+
+       /// reverse iterator of elements on the list
+       using reverse_iterator = std::reverse_iterator<iterator>;
+
+       /// pointer to value linked in the list
+       using pointer = U*;
+
+       /// reference to value linked in the list
+       using reference = U&;
+
+       /// value linked in the list
+       using value_type = U;
+
+       /**
+        * \brief IntrusiveList's constructor
+        */
+
+       constexpr IntrusiveList() :
+                       intrusiveListBase_{}
+       {
+
+       }
+
+       /**
+        * \return reference to last element on the list
+        */
+
+       reference back()
+       {
+               return *--end();
+       }
+
+       /**
+        * \return const reference to last element on the list
+        */
+
+       const_reference back() const
+       {
+               return *--end();
+       }
+
+       /**
+        * \return iterator of first element on the list
+        */
+
+       iterator begin()
+       {
+               return iterator{&intrusiveListBase_.begin()};
+       }
+
+       /**
+        * \return const iterator of first element on the list
+        */
+
+       const_iterator begin() const
+       {
+               return const_iterator{&intrusiveListBase_.begin()};
+       }
+
+       /**
+        * \return const iterator of first element on the list
+        */
+
+       const_iterator cbegin() const
+       {
+               return begin();
+       }
+
+       /**
+        * \return const iterator of "one past the last" element on the list
+        */
+
+       const_iterator cend() const
+       {
+               return end();
+       }
+
+       /**
+        * \brief Unlinks all elements from the list.
+        */
+
+       void clear()
+       {
+               intrusiveListBase_.clear();
+       }
+
+       /**
+        * \return true is the list is empty, false otherwise
+        */
+
+       bool empty() const
+       {
+               return intrusiveListBase_.empty();
+       }
+
+       /**
+        * \return iterator of "one past the last" element on the list
+        */
+
+       iterator end()
+       {
+               return iterator{&intrusiveListBase_.end()};
+       }
+
+       /**
+        * \return const iterator of "one past the last" element on the list
+        */
+
+       const_iterator end() const
+       {
+               return const_iterator{&intrusiveListBase_.end()};
+       }
+
+       /**
+        * \return reference to first element on the list
+        */
+
+       reference front()
+       {
+               return *begin();
+       }
+
+       /**
+        * \return const reference to first element on the list
+        */
+
+       const_reference front() const
+       {
+               return *begin();
+       }
+
+       /**
+        * \brief Unlinks the last element from the list.
+        */
+
+       void pop_back()
+       {
+               erase(--end());
+       }
+
+       /**
+        * \brief Unlinks the first element from the list.
+        */
+
+       void pop_front()
+       {
+               erase(begin());
+       }
+
+       /**
+        * \brief Links the element at the end of the list.
+        *
+        * \param [in] newElement is a reference to the element that will be linked in the list
+        */
+
+       void push_back(reference newElement)
+       {
+               insert(end(), newElement);
+       }
+
+       /**
+        * \brief Links the element at the beginning of the list.
+        *
+        * \param [in] newElement is a reference to the element that will be linked in the list
+        */
+
+       void push_front(reference newElement)
+       {
+               insert(begin(), newElement);
+       }
+
+       /**
+        * \brief Swaps contents with another list.
+        *
+        * \param [in] other is a reference to IntrusiveList with which contents of this list will be swapped
+        */
+
+       void swap(IntrusiveList& other)
+       {
+               intrusiveListBase_.swap(other.intrusiveListBase_);
+       }
+
+       /**
+        * \brief Unlinks the element at \a position from the list.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is an iterator of the element that will be unlinked from the list
+        *
+        * \return iterator of the element that was following the element which was unlinked
+        */
+
+       static iterator erase(const iterator position)
+       {
+               auto& positionNode = (*position).*NodePointer;
+               auto& nextNode = internal::IntrusiveListBase::erase(positionNode);
+               return iterator{&nextNode};
+       }
+
+       /**
+        * \brief Links the element in the list before \a position.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is an iterator of the element before which \a newNode will be linked
+        * \param [in] newElement is a reference to the element that will be linked in the list
+        *
+        * \return iterator of \a newElement
+        */
+
+       static iterator insert(const iterator position, reference newElement)
+       {
+               static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+               auto& positionNode = (*position).*NodePointer;
+               auto& newElementNode = newElement.*NodePointer;
+               internal::IntrusiveListBase::insert(positionNode, newElementNode);
+               return iterator{&newElementNode};
+       }
+
+       /**
+        * \brief Transfers the element from one list to another list before \a position.
+        *
+        * \note No instance of any list is needed for this operation.
+        *
+        * \param [in] position is an iterator of the element before which \a splicedElement will be linked
+        * \param [in] splicedElement is an iterator of the element that will be spliced from one list to another
+        */
+
+       static void splice(const iterator position, const iterator splicedElement)
+       {
+               auto& positionNode = (*position).*NodePointer;
+               auto& splicedElementNode = (*splicedElement).*NodePointer;
+               internal::IntrusiveListBase::splice(positionNode, splicedElementNode);
+       }
+
+       IntrusiveList(const IntrusiveList&) = delete;
+       IntrusiveList(IntrusiveList&&) = default;
+       const IntrusiveList& operator=(const IntrusiveList&) = delete;
+       IntrusiveList& operator=(IntrusiveList&&) = delete;
+
+private:
+
+       /// internal IntrusiveListBase object
+       internal::IntrusiveListBase intrusiveListBase_;
+};
+
+/**
+ * \brief Swaps contents of two lists.
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a reference to IntrusiveList with which contents of \a right will be swapped
+ * \param [in] right is a reference to IntrusiveList with which contents of \a left will be swapped
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+inline void swap(IntrusiveList<T, NodePointer, U>& left, IntrusiveList<T, NodePointer, U>& right)
+{
+       left.swap(right);
+}
+
+}      // namespace estd
+
+#endif // ESTD_INTRUSIVELIST_HPP_
diff --git a/include/estd/ReferenceHolder.hpp b/include/estd/ReferenceHolder.hpp
new file mode 100644 (file)
index 0000000..2bb4602
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * \file
+ * \brief ReferenceHolder template class header.
+ *
+ * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_REFERENCEHOLDER_HPP_
+#define ESTD_REFERENCEHOLDER_HPP_
+
+namespace estd
+{
+
+/**
+ * \brief ReferenceHolder template class is a ROMable holder of a reference.
+ *
+ * \tparam T is the type of reference held in the object
+ */
+
+template<typename T>
+class ReferenceHolder
+{
+public:
+
+       /**
+        * \brief ReferenceHolder constructor.
+        *
+        * \param [in] reference is a reference that will be held by the object
+        */
+
+       constexpr explicit ReferenceHolder(T& reference) noexcept :
+                       reference_{reference}
+       {
+
+       }
+
+       /// \return reference held by the object
+       constexpr operator T&() const noexcept
+       {
+               return reference_;
+       }
+
+       /// \return reference held by the object
+       constexpr T& get() const noexcept
+       {
+               return reference_;
+       }
+
+private:
+
+       /// reference held by the object
+       T& reference_;
+};
+
+}      // namespace estd
+
+#endif // ESTD_REFERENCEHOLDER_HPP_
diff --git a/include/estd/ReverseAdaptor.hpp b/include/estd/ReverseAdaptor.hpp
new file mode 100644 (file)
index 0000000..6738cac
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+ * \file
+ * \brief ReverseAdaptor template class header.
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_REVERSEADAPTOR_HPP_
+#define ESTD_REVERSEADAPTOR_HPP_
+
+namespace estd
+{
+
+/**
+ * \brief ReverseAdaptor template class is an adaptor that "reverses" access to the container
+ *
+ * \tparam T is the type of container
+ */
+
+template<typename T>
+class ReverseAdaptor
+{
+public:
+
+       /**
+        * \brief ReverseAdaptor's constructor.
+        *
+        * \param [in] container is a reference to container
+        */
+
+       constexpr explicit ReverseAdaptor(T& container) noexcept :
+                       container_{container}
+       {
+
+       }
+
+       /**
+        * \return reverse_iterator to the beginning of "reversed" container (last element of original container)
+        */
+
+       typename T::reverse_iterator begin() const noexcept
+       {
+               return container_.rbegin();
+       }
+
+       /**
+        * \return reverse_iterator to the end of "reversed" container (before-the-first element of original container)
+        */
+
+       typename T::reverse_iterator end() const noexcept
+       {
+               return container_.rend();
+       }
+
+private:
+
+       /// reference to container
+       T& container_;
+};
+
+/**
+ * \brief Helper factory function to make ReverseAdaptor object with deduced template arguments
+ *
+ * \tparam T is the type of container
+ *
+ * \param [in] container is a reference to container
+ *
+ * \return ReverseAdaptor object
+ */
+
+template<typename T>
+ReverseAdaptor<T> makeReverseAdaptor(T& container)
+{
+       return ReverseAdaptor<T>{container};
+}
+
+}      // namespace estd
+
+#endif // ESTD_REVERSEADAPTOR_HPP_
diff --git a/include/estd/SortedIntrusiveForwardList.hpp b/include/estd/SortedIntrusiveForwardList.hpp
new file mode 100644 (file)
index 0000000..de35845
--- /dev/null
@@ -0,0 +1,355 @@
+/**
+ * \file
+ * \brief SortedIntrusiveForwardList template class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_SORTEDINTRUSIVEFORWARDLIST_HPP_
+#define ESTD_SORTEDINTRUSIVEFORWARDLIST_HPP_
+
+#include "estd/IntrusiveForwardList.hpp"
+
+#include <algorithm>
+
+namespace estd
+{
+
+/**
+ * \brief SortedIntrusiveForwardList class is an IntrusiveForwardList with sorted elements
+ *
+ * This class tries to provide an interface similar to std::forward_list.
+ *
+ * \note The elements are sorted as long as the user does not modify the contents.
+ *
+ * \tparam Compare is a type of functor used for comparison, std::less results in descending order, std::greater - in
+ * ascending order
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T; using different type than \a T can be used
+ * to break circular dependencies, because \a T must be fully defined to instantiate this class, but it is enough to
+ * forward declare \a U - it only needs to be fully defined to use member functions
+ */
+
+template<typename Compare, typename T, IntrusiveForwardListNode T::* NodePointer, typename U = T>
+class SortedIntrusiveForwardList
+{
+public:
+
+       /// unsorted intrusive forward list used internally
+       using UnsortedIntrusiveForwardList = IntrusiveForwardList<T, NodePointer, U>;
+
+       /// const iterator of elements on the list
+       using const_iterator = typename UnsortedIntrusiveForwardList::const_iterator;
+
+       /// const pointer to value linked in the list
+       using const_pointer = typename UnsortedIntrusiveForwardList::const_pointer;
+
+       /// const reference to value linked in the list
+       using const_reference = typename UnsortedIntrusiveForwardList::const_reference;
+
+       /// iterator of elements on the list
+       using iterator = typename UnsortedIntrusiveForwardList::iterator;
+
+       /// pointer to value linked in the list
+       using pointer = typename UnsortedIntrusiveForwardList::pointer;
+
+       /// reference to value linked in the list
+       using reference = typename UnsortedIntrusiveForwardList::reference;
+
+       /// value linked in the list
+       using value_type = typename UnsortedIntrusiveForwardList::value_type;
+
+       /**
+        * \brief SortedIntrusiveForwardList's constructor
+        *
+        * \param [in] compare is a reference to Compare object used to copy-construct internal comparison functor
+        */
+
+       constexpr SortedIntrusiveForwardList(const Compare& compare = Compare{}) :
+                       implementation_{compare}
+       {
+
+       }
+
+       /**
+        * \return iterator of "one before the first" element on the list
+        */
+
+       iterator before_begin()
+       {
+               return implementation_.intrusiveForwardList.before_begin();
+       }
+
+       /**
+        * \return const iterator of "one before the first" element on the list
+        */
+
+       const_iterator before_begin() const
+       {
+               return implementation_.intrusiveForwardList.before_begin();
+       }
+
+       /**
+        * \return iterator of first element on the list
+        */
+
+       iterator begin()
+       {
+               return implementation_.intrusiveForwardList.begin();
+       }
+
+       /**
+        * \return const iterator of first element on the list
+        */
+
+       const_iterator begin() const
+       {
+               return implementation_.intrusiveForwardList.begin();
+       }
+
+       /**
+        * \return const iterator of "one before the first" element on the list
+        */
+
+       const_iterator cbefore_begin() const
+       {
+               return implementation_.intrusiveForwardList.cbefore_begin();
+       }
+
+       /**
+        * \return const iterator of first element on the list
+        */
+
+       const_iterator cbegin() const
+       {
+               return implementation_.intrusiveForwardList.cbegin();
+       }
+
+       /**
+        * \return const iterator of "one past the last" element on the list
+        */
+
+       const_iterator cend() const
+       {
+               return implementation_.intrusiveForwardList.cend();
+       }
+
+       /**
+        * \brief Unlinks all elements from the list.
+        */
+
+       void clear()
+       {
+               implementation_.intrusiveForwardList.clear();
+       }
+
+       /**
+        * \return true is the list is empty, false otherwise
+        */
+
+       bool empty() const
+       {
+               return implementation_.intrusiveForwardList.empty();
+       }
+
+       /**
+        * \return iterator of "one past the last" element on the list
+        */
+
+       iterator end()
+       {
+               return implementation_.intrusiveForwardList.end();
+       }
+
+       /**
+        * \return const iterator of "one past the last" element on the list
+        */
+
+       const_iterator end() const
+       {
+               return implementation_.intrusiveForwardList.end();
+       }
+
+       /**
+        * \return reference to first element on the list
+        */
+
+       reference front()
+       {
+               return implementation_.intrusiveForwardList.front();
+       }
+
+       /**
+        * \return const reference to first element on the list
+        */
+
+       const_reference front() const
+       {
+               return implementation_.intrusiveForwardList.front();
+       }
+
+       /**
+        * \brief Links the element in the list, keeping it sorted.
+        *
+        * \param [in] newElement is a reference to the element that will be linked in the list
+        *
+        * \return iterator of \a newElement
+        */
+
+       iterator insert(reference newElement)
+       {
+               return UnsortedIntrusiveForwardList::insert_after(implementation_.findInsertPositionBefore(newElement),
+                               newElement);
+       }
+
+       /**
+        * \brief Unlinks the first element from the list.
+        */
+
+       void pop_front()
+       {
+               implementation_.intrusiveForwardList.pop_front();
+       }
+
+       /**
+        * \brief Transfers the element from another list to this one, keeping it sorted.
+        *
+        * \param [in] beforeSplicedElement is an iterator of the element preceding the one which will be spliced from
+        * another list to this one
+        */
+
+       void splice_after(const iterator beforeSplicedElement)
+       {
+               const auto splicedElement = std::next(beforeSplicedElement);
+               UnsortedIntrusiveForwardList::splice_after(implementation_.findInsertPositionBefore(*splicedElement),
+                               beforeSplicedElement);
+       }
+
+       /**
+        * \brief Swaps contents with another list.
+        *
+        * \param [in] other is a reference to SortedIntrusiveForwardList with which contents of this list will be swapped
+        */
+
+       void swap(SortedIntrusiveForwardList& other)
+       {
+               implementation_.swap(other.implementation_);
+       }
+
+       /**
+        * \brief Unlinks the element following \a position from the list.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is an iterator preceding the element which will be unlinked from the list
+        *
+        * \return iterator of the element that was following the element which was unlinked
+        */
+
+       static iterator erase_after(const iterator position)
+       {
+               return UnsortedIntrusiveForwardList::erase_after(position);
+       }
+
+       SortedIntrusiveForwardList(const SortedIntrusiveForwardList&) = delete;
+       SortedIntrusiveForwardList(SortedIntrusiveForwardList&&) = default;
+       const SortedIntrusiveForwardList& operator=(const SortedIntrusiveForwardList&) = delete;
+       SortedIntrusiveForwardList& operator=(SortedIntrusiveForwardList&&) = delete;
+
+private:
+
+       /// Implementation struct is used primarily for "Empty Base Optimization" with \a Compare type
+       struct Implementation : public Compare
+       {
+               /**
+                * \brief Implementation's constructor
+                *
+                * \param [in] comparee is a reference to Compare object used to copy-construct internal comparison functor
+                */
+
+               constexpr Implementation(const Compare& comparee) :
+                               Compare{comparee},
+                               intrusiveForwardList{}
+               {
+
+               }
+
+               /**
+                * \brief Finds insert position "before" the position that satisfies sorting criteria.
+                *
+                * \param [in] newElement is a const reference to new element that is going to be inserted/spliced
+                *
+                * \return iterator for which Compare's function call operator of next value and \a newElement returns true.
+                */
+
+               iterator findInsertPositionBefore(const_reference newElement)
+               {
+                       auto it = intrusiveForwardList.before_begin();
+                       auto next = intrusiveForwardList.begin();
+                       const auto end = intrusiveForwardList.end();
+
+                       while (next != end && this->Compare::operator()(*next, newElement) == false)
+                       {
+                               it = next;
+                               ++next;
+                       }
+
+                       return it;
+               }
+
+               /**
+                * \brief Swaps contents with another instance.
+                *
+                * \param [in] other is a reference to Implementation with which contents of this instance will be swapped
+                */
+
+               void swap(Implementation& other)
+               {
+                       intrusiveForwardList.swap(other.intrusiveForwardList);
+                       using std::swap;
+                       swap(static_cast<Compare&>(*this), static_cast<Compare&>(other));
+               }
+
+               Implementation(const Implementation&) = delete;
+               Implementation(Implementation&&) = default;
+               const Implementation& operator=(const Implementation&) = delete;
+               Implementation& operator=(Implementation&&) = delete;
+
+               /// internal unsorted IntrusiveForwardList
+               UnsortedIntrusiveForwardList intrusiveForwardList;
+       };
+
+       /// internal Implementation object - unsorted IntrusiveForwardList and Compare instance
+       Implementation implementation_;
+};
+
+/**
+ * \brief Swaps contents of two lists.
+ *
+ * \tparam Compare is a type of functor used for comparison, std::less results in descending order, std::greater - in
+ * ascending order
+ * \tparam T is the type that has the IntrusiveForwardListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveForwardListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a reference to SortedIntrusiveForwardList with which contents of \a right will be swapped
+ * \param [in] right is a reference to SortedIntrusiveForwardList with which contents of \a left will be swapped
+ */
+
+template<typename Compare, typename T, IntrusiveForwardListNode T::* NodePointer, typename U = T>
+inline void swap(SortedIntrusiveForwardList<Compare, T, NodePointer, U>& left,
+               SortedIntrusiveForwardList<Compare, T, NodePointer, U>& right)
+{
+       left.swap(right);
+}
+
+}      // namespace estd
+
+#endif // ESTD_SORTEDINTRUSIVEFORWARDLIST_HPP_
diff --git a/include/estd/SortedIntrusiveList.hpp b/include/estd/SortedIntrusiveList.hpp
new file mode 100644 (file)
index 0000000..1d65ee3
--- /dev/null
@@ -0,0 +1,353 @@
+/**
+ * \file
+ * \brief SortedIntrusiveList template class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_SORTEDINTRUSIVELIST_HPP_
+#define ESTD_SORTEDINTRUSIVELIST_HPP_
+
+#include "estd/IntrusiveList.hpp"
+
+#include <algorithm>
+
+namespace estd
+{
+
+/**
+ * \brief SortedIntrusiveList class is an IntrusiveList with sorted elements
+ *
+ * This class tries to provide an interface similar to std::list.
+ *
+ * \note The elements are sorted as long as the user does not modify the contents.
+ *
+ * \tparam Compare is a type of functor used for comparison, std::less results in descending order, std::greater - in
+ * ascending order
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T; using different type than \a T can be used
+ * to break circular dependencies, because \a T must be fully defined to instantiate this class, but it is enough to
+ * forward declare \a U - it only needs to be fully defined to use member functions
+ */
+
+template<typename Compare, typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+class SortedIntrusiveList
+{
+public:
+
+       /// unsorted intrusive list used internally
+       using UnsortedIntrusiveList = IntrusiveList<T, NodePointer, U>;
+
+       /// const iterator of elements on the list
+       using const_iterator = typename UnsortedIntrusiveList::const_iterator;
+
+       /// const reverse iterator of elements on the list
+       using const_reverse_iterator = typename UnsortedIntrusiveList::const_reverse_iterator;
+
+       /// const pointer to value linked in the list
+       using const_pointer = typename UnsortedIntrusiveList::const_pointer;
+
+       /// const reference to value linked in the list
+       using const_reference = typename UnsortedIntrusiveList::const_reference;
+
+       /// iterator of elements on the list
+       using iterator = typename UnsortedIntrusiveList::iterator;
+
+       /// reverse iterator of elements on the list
+       using reverse_iterator = typename UnsortedIntrusiveList::reverse_iterator;
+
+       /// pointer to value linked in the list
+       using pointer = typename UnsortedIntrusiveList::pointer;
+
+       /// reference to value linked in the list
+       using reference = typename UnsortedIntrusiveList::reference;
+
+       /// value linked in the list
+       using value_type = typename UnsortedIntrusiveList::value_type;
+
+       /**
+        * \brief SortedIntrusiveList's constructor
+        *
+        * \param [in] compare is a reference to Compare object used to copy-construct internal comparison functor
+        */
+
+       constexpr SortedIntrusiveList(const Compare& compare = Compare{}) :
+                       implementation_{compare}
+       {
+
+       }
+
+       /**
+        * \return reference to last element on the list
+        */
+
+       reference back()
+       {
+               return implementation_.intrusiveList.back();
+       }
+
+       /**
+        * \return const reference to last element on the list
+        */
+
+       const_reference back() const
+       {
+               return implementation_.intrusiveList.back();
+       }
+
+       /**
+        * \return iterator of first element on the list
+        */
+
+       iterator begin()
+       {
+               return implementation_.intrusiveList.begin();
+       }
+
+       /**
+        * \return const iterator of first element on the list
+        */
+
+       const_iterator begin() const
+       {
+               return implementation_.intrusiveList.begin();
+       }
+
+       /**
+        * \return const iterator of first element on the list
+        */
+
+       const_iterator cbegin() const
+       {
+               return implementation_.intrusiveList.cbegin();
+       }
+
+       /**
+        * \return const iterator of "one past the last" element on the list
+        */
+
+       const_iterator cend() const
+       {
+               return implementation_.intrusiveList.cend();
+       }
+
+       /**
+        * \brief Unlinks all elements from the list.
+        */
+
+       void clear()
+       {
+               implementation_.intrusiveList.clear();
+       }
+
+       /**
+        * \return true is the list is empty, false otherwise
+        */
+
+       bool empty() const
+       {
+               return implementation_.intrusiveList.empty();
+       }
+
+       /**
+        * \return iterator of "one past the last" element on the list
+        */
+
+       iterator end()
+       {
+               return implementation_.intrusiveList.end();
+       }
+
+       /**
+        * \return const iterator of "one past the last" element on the list
+        */
+
+       const_iterator end() const
+       {
+               return implementation_.intrusiveList.end();
+       }
+
+       /**
+        * \return reference to first element on the list
+        */
+
+       reference front()
+       {
+               return implementation_.intrusiveList.front();
+       }
+
+       /**
+        * \return const reference to first element on the list
+        */
+
+       const_reference front() const
+       {
+               return implementation_.intrusiveList.front();
+       }
+
+       /**
+        * \brief Links the element in the list, keeping it sorted.
+        *
+        * \param [in] newElement is a reference to the element that will be linked in the list
+        *
+        * \return iterator of \a newElement
+        */
+
+       iterator insert(reference newElement)
+       {
+               return UnsortedIntrusiveList::insert(implementation_.findInsertPosition(newElement), newElement);
+       }
+
+       /**
+        * \brief Unlinks the last element from the list.
+        */
+
+       void pop_back()
+       {
+               implementation_.intrusiveList.pop_back();
+       }
+
+       /**
+        * \brief Unlinks the first element from the list.
+        */
+
+       void pop_front()
+       {
+               implementation_.intrusiveList.pop_front();
+       }
+
+       /**
+        * \brief Transfers the element from another list to this one, keeping it sorted.
+        *
+        * \param [in] splicedElement is an iterator of the element that will be spliced from another list to this one
+        */
+
+       void splice(const iterator splicedElement)
+       {
+               UnsortedIntrusiveList::splice(implementation_.findInsertPosition(*splicedElement), splicedElement);
+       }
+
+       /**
+        * \brief Swaps contents with another list.
+        *
+        * \param [in] other is a reference to SortedIntrusiveList with which contents of this list will be swapped
+        */
+
+       void swap(SortedIntrusiveList& other)
+       {
+               implementation_.swap(other.implementation_);
+       }
+
+       /**
+        * \brief Unlinks the element at \a position from the list.
+        *
+        * \note No instance of the list is needed for this operation.
+        *
+        * \param [in] position is an iterator of the element that will be unlinked from the list
+        *
+        * \return iterator of the element that was following the element which was unlinked
+        */
+
+       static iterator erase(const iterator position)
+       {
+               return UnsortedIntrusiveList::erase(position);
+       }
+
+       SortedIntrusiveList(const SortedIntrusiveList&) = delete;
+       SortedIntrusiveList(SortedIntrusiveList&&) = default;
+       const SortedIntrusiveList& operator=(const SortedIntrusiveList&) = delete;
+       SortedIntrusiveList& operator=(SortedIntrusiveList&&) = delete;
+
+private:
+
+       /// Implementation struct is used primarily for "Empty Base Optimization" with \a Compare type
+       struct Implementation : public Compare
+       {
+               /**
+                * \brief Implementation's constructor
+                *
+                * \param [in] comparee is a reference to Compare object used to copy-construct internal comparison functor
+                */
+
+               constexpr Implementation(const Compare& comparee) :
+                               Compare{comparee},
+                               intrusiveList{}
+               {
+
+               }
+
+               /**
+                * \brief Finds insert position that satisfies sorting criteria.
+                *
+                * \param [in] newElement is a const reference to new element that is going to be inserted/spliced
+                *
+                * \return iterator for which Compare's function call operator of dereferenced value and \a newElement returns
+                * true.
+                */
+
+               iterator findInsertPosition(const_reference newElement)
+               {
+                       return std::find_if(intrusiveList.begin(), intrusiveList.end(),
+                                       [this, &newElement](const_reference& element) -> bool
+                                       {
+                                               return this->Compare::operator()(element, newElement);
+                                       }
+                       );
+               }
+
+               /**
+                * \brief Swaps contents with another instance.
+                *
+                * \param [in] other is a reference to Implementation with which contents of this instance will be swapped
+                */
+
+               void swap(Implementation& other)
+               {
+                       intrusiveList.swap(other.intrusiveList);
+                       using std::swap;
+                       swap(static_cast<Compare&>(*this), static_cast<Compare&>(other));
+               }
+
+               Implementation(const Implementation&) = delete;
+               Implementation(Implementation&&) = default;
+               const Implementation& operator=(const Implementation&) = delete;
+               Implementation& operator=(Implementation&&) = delete;
+
+               /// internal unsorted IntrusiveList
+               UnsortedIntrusiveList intrusiveList;
+       };
+
+       /// internal Implementation object - unsorted IntrusiveList and Compare instance
+       Implementation implementation_;
+};
+
+/**
+ * \brief Swaps contents of two lists.
+ *
+ * \tparam Compare is a type of functor used for comparison, std::less results in descending order, std::greater - in
+ * ascending order
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a reference to SortedIntrusiveList with which contents of \a right will be swapped
+ * \param [in] right is a reference to SortedIntrusiveList with which contents of \a left will be swapped
+ */
+
+template<typename Compare, typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+inline void swap(SortedIntrusiveList<Compare, T, NodePointer, U>& left,
+               SortedIntrusiveList<Compare, T, NodePointer, U>& right)
+{
+       left.swap(right);
+}
+
+}      // namespace estd
+
+#endif // ESTD_SORTEDINTRUSIVELIST_HPP_
diff --git a/include/estd/TypeErasedFunctor.hpp b/include/estd/TypeErasedFunctor.hpp
new file mode 100644 (file)
index 0000000..a19d59b
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * \file
+ * \brief TypeErasedFunctor template class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_TYPEERASEDFUNCTOR_HPP_
+#define ESTD_TYPEERASEDFUNCTOR_HPP_
+
+namespace estd
+{
+
+template<typename Signature, bool NonConst = {}>
+class TypeErasedFunctor;
+
+/**
+ * \brief TypeErasedFunctor class is an interface for type-erased functors.
+ *
+ * Overload with const operator()().
+ *
+ * \tparam R is the type returned by <em>TypeErasedFunctor::operator()() const</em>
+ * \tparam Args are the types of arguments for <em>TypeErasedFunctor::operator()() const</em>
+ */
+
+template<typename R, typename... Args>
+class TypeErasedFunctor<R(Args...), false>
+{
+public:
+
+       /**
+        * \brief Function call operator of TypeErasedFunctor
+        *
+        * \param [in,out] args are arguments for derived function
+        *
+        * \return value returned by derived function
+        */
+
+       virtual R operator()(Args... args) const = 0;
+
+protected:
+
+       /**
+        * \brief TypeErasedFunctor's destructor
+        *
+        * \note Polymorphic objects of TypeErasedFunctor type must not be deleted via pointer/reference
+        */
+
+       ~TypeErasedFunctor()
+       {
+
+       }
+};
+
+/**
+ * \brief TypeErasedFunctor class is an interface for type-erased functors.
+ *
+ * Overload with non-const operator()().
+ *
+ * \tparam R is the type returned by <em>TypeErasedFunctor::operator()()</em>
+ * \tparam Args are the types of arguments for <em>TypeErasedFunctor::operator()()</em>
+ */
+
+template<typename R, typename... Args>
+class TypeErasedFunctor<R(Args...), true>
+{
+public:
+
+       /**
+        * \brief Function call operator of TypeErasedFunctor
+        *
+        * \param [in,out] args are arguments for derived function
+        *
+        * \return value returned by derived function
+        */
+
+       virtual R operator()(Args... args) = 0;
+
+protected:
+
+       /**
+        * \brief TypeErasedFunctor's destructor
+        *
+        * \note Polymorphic objects of TypeErasedFunctor type must not be deleted via pointer/reference
+        */
+
+       ~TypeErasedFunctor()
+       {
+
+       }
+};
+
+}      // namespace estd
+
+#endif // ESTD_TYPEERASEDFUNCTOR_HPP_
diff --git a/include/estd/apply.hpp b/include/estd/apply.hpp
new file mode 100644 (file)
index 0000000..743cce6
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * \file
+ * \brief apply() header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_APPLY_HPP_
+#define ESTD_APPLY_HPP_
+
+#include "estd/IntegerSequence.hpp"
+#include "estd/invoke.hpp"
+
+#include <tuple>
+
+namespace estd
+{
+
+namespace internal
+{
+
+/**
+ * \brief Implementation of apply()
+ *
+ * \tparam Function is the function object that will be invoked
+ * \tparam Tuple is the type of tuple of arguments
+ * \tparam Indexes is a sequence of std::size_t indexes for \a Tuple
+ *
+ * \param [in] function is the function object that will be executed
+ * \param [in] tuple is the tuple of arguments
+ *
+ * \return value returned by call to \a function with arguments from \a tuple
+ */
+
+template<typename Function, typename Tuple, std::size_t... Indexes>
+constexpr auto apply(Function&& function, Tuple&& tuple, estd::IndexSequence<Indexes...>) ->
+               decltype(estd::invoke(std::forward<Function>(function), std::get<Indexes>(std::forward<Tuple>(tuple))...))
+{
+       return estd::invoke(std::forward<Function>(function), std::get<Indexes>(std::forward<Tuple>(tuple))...);
+}
+
+} // namespace internal
+
+/**
+ * \brief Invokes callable object with a tuple of arguments.
+ *
+ * Implementation inspired by http://en.cppreference.com/w/cpp/experimental/apply
+ *
+ * \tparam Function is the function object that will be invoked
+ * \tparam Tuple is the type of tuple of arguments
+ *
+ * \param [in] function is the function object that will be executed
+ * \param [in] tuple is the tuple of arguments
+ *
+ * \return value returned by call to \a function with arguments from \a tuple
+ */
+
+template <typename Function, typename Tuple>
+constexpr auto apply(Function&& function, Tuple&& tuple) ->
+               decltype(internal::apply(std::forward<Function>(function), std::forward<Tuple>(tuple),
+                               estd::MakeIndexSequence<std::tuple_size<typename std::decay<Tuple>::type>{}>{}))
+{
+       return internal::apply(std::forward<Function>(function), std::forward<Tuple>(tuple),
+                       estd::MakeIndexSequence<std::tuple_size<typename std::decay<Tuple>::type>{}>{});
+}
+
+}      // namespace estd
+
+#endif // ESTD_APPLY_HPP_
diff --git a/include/estd/invoke.hpp b/include/estd/invoke.hpp
new file mode 100644 (file)
index 0000000..bdac1a0
--- /dev/null
@@ -0,0 +1,147 @@
+/**
+ * \file
+ * \brief invoke() header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_INVOKE_HPP_
+#define ESTD_INVOKE_HPP_
+
+#include <utility>
+
+namespace estd
+{
+
+namespace internal
+{
+
+/**
+ * \brief Implementation of invoke() for function objects
+ *
+ * \tparam Function is the function object that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] function is the function object that will be executed
+ * \param [in] args are arguments for \a function
+ *
+ * \return value returned by call to \a function with \a args
+ */
+
+template<typename Function, typename... Args>
+inline auto invoke(Function&& function, Args&&... args) ->
+               decltype(std::forward<Function>(function)(std::forward<Args>(args)...))
+{
+       return std::forward<Function>(function)(std::forward<Args>(args)...);
+}
+
+/**
+ * \brief Implementation of invoke() for member functions
+ *
+ * \tparam T is the type returned by call to member function
+ * \tparam Base is the type of base class
+ * \tparam Derived is the type of derived class
+ * \tparam Args are the arguments for member function
+ *
+ * \param [in] memberFunction is a pointer to member function of \a object that will be executed
+ * \param [in] object is an object or a reference to object on which \a memberFunction will be executed
+ * \param [in] args are arguments for \a memberFunction
+ *
+ * \return value returned by call to \a memberFunction on \a object with \a args
+ */
+
+template<typename T, typename Base, typename Derived, typename... Args>
+inline auto invoke(T Base::* memberFunction, Derived&& object, Args&&... args) ->
+               decltype((std::forward<Derived>(object).*memberFunction)(std::forward<Args>(args)...))
+{
+       return (std::forward<Derived>(object).*memberFunction)(std::forward<Args>(args)...);
+}
+
+/**
+ * \brief Implementation of invoke() for member functions
+ *
+ * \tparam MemberFunction is the type or pointer to member function
+ * \tparam Pointer is the type of pointer to object
+ * \tparam Args are the arguments for member function
+ *
+ * \param [in] memberFunction is a pointer to member function of object that will be executed
+ * \param [in] pointer is a pointer to object on which \a memberFunction will be executed
+ * \param [in] args are arguments for \a memberFunction
+ *
+ * \return value returned by call to \a memberFunction on \a (*pointer) with \a args
+ */
+
+template<typename MemberFunction, typename Pointer, typename... Args>
+inline auto invoke(MemberFunction memberFunction, Pointer&& pointer, Args&&... args) ->
+               decltype(((*std::forward<Pointer>(pointer)).*memberFunction)(std::forward<Args>(args)...))
+{
+       return ((*std::forward<Pointer>(pointer)).*memberFunction)(std::forward<Args>(args)...);
+}
+
+/**
+ * \brief Implementation of invoke() for data members
+ *
+ * \tparam T is the type of data member
+ * \tparam Base is the type of base class
+ * \tparam Derived is the type of derived class
+ *
+ * \param [in] dataMember is a pointer to data member of \a object that will be accessed
+ * \param [in] object is an object or a reference to object in which \a dataMember will be accessed
+ *
+ * \return value returned by access to \a dataMember in \a object
+ */
+
+template<typename T, typename Base, typename Derived>
+inline auto invoke(T Base::* dataMember, Derived&& object) -> decltype(std::forward<Derived>(object).*dataMember)
+{
+       return std::forward<Derived>(object).*dataMember;
+}
+
+/**
+ * \brief Implementation of invoke() for data members
+ *
+ * \tparam DataMember is the type or pointer to data member
+ * \tparam Pointer is the type of pointer to object
+ *
+ * \param [in] dataMember is a pointer to data member of object that will be accessed
+ * \param [in] pointer is a pointer to object in which \a dataMember will be accessed
+ *
+ * \return value returned by access to \a dataMember in \a (*pointer)
+ */
+
+template<typename DataMember, typename Pointer>
+inline auto invoke(DataMember dataMember, Pointer&& pointer) -> decltype((*std::forward<Pointer>(pointer)).*dataMember)
+{
+       return (*std::forward<Pointer>(pointer)).*dataMember;
+}
+
+}      // namespace internal
+
+/**
+ * \brief Invokes callable object in an appropriate way.
+ *
+ * Implementation inspired by http://en.cppreference.com/w/cpp/utility/functional/invoke
+ *
+ * \tparam Function is the function object that will be executed
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] function is the function object that will be executed
+ * \param [in] args are arguments for \a function
+ *
+ * \return value returned by call to \a function with \a args
+ */
+
+template<typename Function, typename... Args>
+auto invoke(Function&& function, Args&&... args) ->
+               decltype(internal::invoke(std::forward<Function>(function), std::forward<Args>(args)...))
+{
+       return internal::invoke(std::forward<Function>(function), std::forward<Args>(args)...);
+}
+
+}      // namespace estd
+
+#endif // ESTD_INVOKE_HPP_
diff --git a/include/motor.h b/include/motor.h
deleted file mode 100644 (file)
index cf15088..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef MOTOR_H_
-#define MOTOR_H_
-
-#include "ch.h"
-#include "hal.h"
-#include "vex.h"
-
-typedef enum {
-       /* 1 */  mClawThingy = kVexMotor_1,
-       /* 2 */  mLiftHighLeft,
-       /* 3 */  mLiftLowLeft,
-       /* 4 */  mLiftHighRight,
-       /* 5 */  mLiftLowRight,
-       /* 6 */  mDriveFrontLeft,
-       /* 7 */  mDriveBackLeft,
-       /* 8 */  mDriveBackRight,
-       /* 9 */  mDriveFrontRight,
-       /* 10 */ mPickupThingy,
-} motor_port_t;
-
-constexpr const tVexImeChannels iLiftLowLeft   = kImeChannel_1;
-constexpr const tVexImeChannels iLiftHighLeft  = kImeChannel_2;
-constexpr const tVexImeChannels iLiftLowRight  = kImeChannel_3;
-constexpr const tVexImeChannels iLiftHighRight = kImeChannel_4;
-
-#define DIGI_CFG_DIGI_OUT(p) { kVexDigital_##p, kVexSensorDigitalOutput, kVexConfigOutput, 0 }
-#define DIGI_CFG_DIGI_IN(p)  { kVexDigital_##p, kVexSensorDigitalInput,  kVexConfigInput,  0 }
-
-#define MOTOR_CFG_MOT(p, t, r)   (tVexMotor)p, kVexMotor##t, kVexMotor##r
-#define MOTOR_CFG_NOIME          kVexSensorNone, 0
-#define MOTOR_CFG_IME(c)         kVexSensorIME,  c
-
-#endif // MOTOR_H_
diff --git a/include/sys/signal.h b/include/sys/signal.h
new file mode 100644 (file)
index 0000000..02509ac
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * \file
+ * \brief Override for newlib's sys/signal.h
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_SYS_SIGNAL_H_
+#define INCLUDE_SYS_SIGNAL_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* def __cplusplus */
+
+/*---------------------------------------------------------------------------------------------------------------------+
+| global types
++---------------------------------------------------------------------------------------------------------------------*/
+
+/** pointer to function taking an int argument (required by newlib's signal.h) */
+typedef void (* _sig_func_ptr)(int);
+
+/** standard sigval union - integer and void pointer */
+union sigval
+{
+       /** integer signal value */
+       int sival_int;
+
+       /** pointer signal value */
+       void* sival_ptr;
+};
+
+#ifdef __cplusplus
+}      /* extern "C" */
+#endif /* def __cplusplus */
+
+#endif /* INCLUDE_SYS_SIGNAL_H_ */
diff --git a/libdistortos.a b/libdistortos.a
new file mode 100644 (file)
index 0000000..54a0aa1
Binary files /dev/null and b/libdistortos.a differ
diff --git a/main.cpp b/main.cpp
deleted file mode 100644 (file)
index 38b6a1b..0000000
--- a/main.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*-----------------------------------------------------------------------------*/\r
-/*                                                                             */\r
-/*                        Copyright (c) James Pearman                          */\r
-/*                                   2013                                      */\r
-/*                            All Rights Reserved                              */\r
-/*                                                                             */\r
-/*-----------------------------------------------------------------------------*/\r
-/*                                                                             */\r
-/*    Module:     vexmain.c                                                    */\r
-/*    Author:     James Pearman                                                */\r
-/*    Created:    7 May 2013                                                   */\r
-/*                                                                             */\r
-/*    Revisions:                                                               */\r
-/*                V1.00  04 July 2013 - Initial release                        */\r
-/*                                                                             */\r
-/*-----------------------------------------------------------------------------*/\r
-/*                                                                             */\r
-/*    The author is supplying this software for use with the VEX cortex        */\r
-/*    control system. This file can be freely distributed and teams are        */\r
-/*    authorized to freely use this program , however, it is requested that    */\r
-/*    improvements or additions be shared with the Vex community via the vex   */\r
-/*    forum.  Please acknowledge the work of the authors when appropriate.     */\r
-/*    Thanks.                                                                  */\r
-/*                                                                             */\r
-/*    Licensed under the Apache License, Version 2.0 (the "License");          */\r
-/*    you may not use this file except in compliance with the License.         */\r
-/*    You may obtain a copy of the License at                                  */\r
-/*                                                                             */\r
-/*      http://www.apache.org/licenses/LICENSE-2.0                             */\r
-/*                                                                             */\r
-/*    Unless required by applicable law or agreed to in writing, software      */\r
-/*    distributed under the License is distributed on an "AS IS" BASIS,        */\r
-/*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */\r
-/*    See the License for the specific language governing permissions and      */\r
-/*    limitations under the License.                                           */\r
-/*                                                                             */\r
-/*    The author can be contacted on the vex forums as jpearman                */\r
-/*    or electronic mail using jbpearman_at_mac_dot_com                        */\r
-/*    Mentor for team 8888 RoboLancers, Pasadena CA.                           */\r
-/*                                                                             */\r
-/*-----------------------------------------------------------------------------*/\r
-\r
-\r
-#include <string.h>\r
-\r
-#include "ch.h"\r
-#include "hal.h"\r
-#include "chprintf.h"\r
-#include "vex.h"\r
-\r
-/*-----------------------------------------------------------------------------*/\r
-/* Command line related.                                                       */\r
-/*-----------------------------------------------------------------------------*/\r
-\r
-#define SHELL_WA_SIZE   THD_WA_SIZE(512)\r
-\r
-// Shell command\r
-static const ShellCommand commands[] = {\r
-  {"adc",     vexAdcDebug },\r
-  {"spi",     vexSpiDebug },\r
-  {"motor",   vexMotorDebug},\r
-  {"lcd",     vexLcdDebug},\r
-  {"enc",     vexEncoderDebug},\r
-  {"son",     vexSonarDebug},\r
-  {"ime",     vexIMEDebug},\r
-  {"test",    vexTestDebug},\r
-   {NULL, NULL}\r
-};\r
-\r
-// configuration for the shell\r
-static const ShellConfig shell_cfg1 = {\r
-  (vexStream *)SD_CONSOLE,\r
-   commands\r
-};\r
-\r
-/*-----------------------------------------------------------------------------*/\r
-//  Application entry point.                                                                                          */\r
-/*-----------------------------------------------------------------------------*/\r
-\r
-int main(void)\r
-{\r
-       Thread *shelltp = NULL;\r
-       short   timeout = 0;\r
-\r
-       // System initializations.\r
-    // - HAL initialization, this also initializes the configured device drivers\r
-    //   and performs the board-specific initializations.\r
-    // - Kernel initialization, the main() function becomes a thread and the\r
-    //   RTOS is active.\r
-       halInit();\r
-       chSysInit();\r
-\r
-       // Init the serial port associated with the console\r
-       vexConsoleInit();\r
-\r
-    // init VEX\r
-    vexCortexInit();\r
-\r
-    // wait for good spi comms\r
-    while( vexSpiGetOnlineStatus() == 0 )\r
-       {\r
-        // wait for a while\r
-        chThdSleepMilliseconds(100);\r
-        // dump after 5 seconds\r
-        if(timeout++ == 50)\r
-               break;\r
-       }\r
-\r
-    // Shell manager initialization.\r
-    shellInit();\r
-\r
-    // spin in loop monitoring the shell\r
-    while (TRUE)\r
-       {\r
-           if (!shelltp)\r
-               shelltp = shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO);\r
-           else\r
-           if (chThdTerminated(shelltp))\r
-               {\r
-               chThdRelease(shelltp);    /* Recovers memory of the previous shell.   */\r
-               shelltp = NULL;           /* Triggers spawning of a new shell.        */\r
-               }\r
-\r
-           chThdSleepMilliseconds(50);\r
-       }\r
-}\r
diff --git a/mcuconf.h b/mcuconf.h
deleted file mode 100644 (file)
index 8095cb7..0000000
--- a/mcuconf.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*\r
-    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio\r
-\r
-    Licensed under the Apache License, Version 2.0 (the "License");\r
-    you may not use this file except in compliance with the License.\r
-    You may obtain a copy of the License at\r
-\r
-        http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-    Unless required by applicable law or agreed to in writing, software\r
-    distributed under the License is distributed on an "AS IS" BASIS,\r
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-    See the License for the specific language governing permissions and\r
-    limitations under the License.\r
-*/\r
-\r
-#define STM32F103_MCUCONF\r
-\r
-/*\r
- * STM32F1xx drivers configuration.\r
- * The following settings override the default settings present in\r
- * the various device driver implementation headers.\r
- * Note that the settings for each driver only have effect if the whole\r
- * driver is enabled in halconf.h.\r
- *\r
- * IRQ priorities:\r
- * 15...0       Lowest...Highest.\r
- *\r
- * DMA priorities:\r
- * 0...3        Lowest...Highest.\r
- */\r
-\r
-/*\r
- * HAL driver system settings.\r
- */\r
-#define STM32_NO_INIT                       FALSE\r
-#define STM32_HSI_ENABLED                   TRUE\r
-#define STM32_LSI_ENABLED                   FALSE\r
-#define STM32_HSE_ENABLED                   TRUE\r
-#define STM32_LSE_ENABLED                   FALSE\r
-#define STM32_SW                            STM32_SW_PLL\r
-#define STM32_PLLSRC                        STM32_PLLSRC_HSE\r
-#define STM32_PLLXTPRE                      STM32_PLLXTPRE_DIV1\r
-#define STM32_PLLMUL_VALUE                  9\r
-#define STM32_HPRE                          STM32_HPRE_DIV1\r
-#define STM32_PPRE1                         STM32_PPRE1_DIV2\r
-#define STM32_PPRE2                         STM32_PPRE2_DIV1\r
-#define STM32_ADCPRE                        STM32_ADCPRE_DIV8\r
-#define STM32_USB_CLOCK_REQUIRED            TRUE\r
-#define STM32_USBPRE                        STM32_USBPRE_DIV1P5\r
-#define STM32_MCOSEL                        STM32_MCOSEL_NOCLOCK\r
-#define STM32_RTCSEL                        STM32_RTCSEL_HSEDIV\r
-#define STM32_PVD_ENABLE                    FALSE\r
-#define STM32_PLS                           STM32_PLS_LEV0\r
-\r
-/*\r
- * ADC driver system settings.\r
- */\r
-#define STM32_ADC_USE_ADC1                  TRUE\r
-#define STM32_ADC_ADC1_DMA_PRIORITY         2\r
-#define STM32_ADC_ADC1_IRQ_PRIORITY         5\r
-\r
-/*\r
- * CAN driver system settings.\r
- */\r
-#define STM32_CAN_USE_CAN1                  TRUE\r
-#define STM32_CAN_CAN1_IRQ_PRIORITY         11\r
-\r
-/*\r
- * EXT driver system settings.\r
- */\r
-#define STM32_EXT_EXTI0_IRQ_PRIORITY        6\r
-#define STM32_EXT_EXTI1_IRQ_PRIORITY        6\r
-#define STM32_EXT_EXTI2_IRQ_PRIORITY        6\r
-#define STM32_EXT_EXTI3_IRQ_PRIORITY        6\r
-#define STM32_EXT_EXTI4_IRQ_PRIORITY        6\r
-#define STM32_EXT_EXTI5_9_IRQ_PRIORITY      6\r
-#define STM32_EXT_EXTI10_15_IRQ_PRIORITY    6\r
-#define STM32_EXT_EXTI16_IRQ_PRIORITY       6\r
-#define STM32_EXT_EXTI17_IRQ_PRIORITY       6\r
-#define STM32_EXT_EXTI18_IRQ_PRIORITY       6\r
-#define STM32_EXT_EXTI19_IRQ_PRIORITY       6\r
-\r
-/*\r
- * GPT driver system settings.\r
- */\r
-#define STM32_GPT_USE_TIM1                  TRUE\r
-#define STM32_GPT_USE_TIM2                  TRUE\r
-#define STM32_GPT_USE_TIM3                  FALSE\r
-#define STM32_GPT_USE_TIM4                  FALSE\r
-#define STM32_GPT_USE_TIM5                  TRUE\r
-#define STM32_GPT_USE_TIM8                  FALSE\r
-#define STM32_GPT_TIM1_IRQ_PRIORITY         7\r
-#define STM32_GPT_TIM2_IRQ_PRIORITY         7\r
-#define STM32_GPT_TIM3_IRQ_PRIORITY         7\r
-#define STM32_GPT_TIM4_IRQ_PRIORITY         7\r
-#define STM32_GPT_TIM5_IRQ_PRIORITY         7\r
-#define STM32_GPT_TIM8_IRQ_PRIORITY         7\r
-\r
-/*\r
- * I2C driver system settings.\r
- */\r
-#define STM32_I2C_USE_I2C1                  TRUE\r
-#define STM32_I2C_USE_I2C2                  FALSE\r
-#define STM32_I2C_USE_I2C3                  FALSE\r
-#define STM32_I2C_I2C1_IRQ_PRIORITY         10\r
-#define STM32_I2C_I2C2_IRQ_PRIORITY         10\r
-#define STM32_I2C_I2C3_IRQ_PRIORITY         10\r
-#define STM32_I2C_I2C1_DMA_PRIORITY         1\r
-#define STM32_I2C_I2C2_DMA_PRIORITY         1\r
-#define STM32_I2C_I2C3_DMA_PRIORITY         1\r
-#define STM32_I2C_I2C1_DMA_ERROR_HOOK()     chSysHalt()\r
-#define STM32_I2C_I2C2_DMA_ERROR_HOOK()     chSysHalt()\r
-#define STM32_I2C_I2C3_DMA_ERROR_HOOK()     chSysHalt()\r
-\r
-/*\r
- * ICU driver system settings.\r
- */\r
-#define STM32_ICU_USE_TIM1                  FALSE\r
-#define STM32_ICU_USE_TIM2                  FALSE\r
-#define STM32_ICU_USE_TIM3                  FALSE\r
-#define STM32_ICU_USE_TIM4                  FALSE\r
-#define STM32_ICU_USE_TIM5                  FALSE\r
-#define STM32_ICU_USE_TIM8                  FALSE\r
-#define STM32_ICU_TIM1_IRQ_PRIORITY         7\r
-#define STM32_ICU_TIM2_IRQ_PRIORITY         7\r
-#define STM32_ICU_TIM3_IRQ_PRIORITY         7\r
-#define STM32_ICU_TIM4_IRQ_PRIORITY         7\r
-#define STM32_ICU_TIM5_IRQ_PRIORITY         7\r
-#define STM32_ICU_TIM8_IRQ_PRIORITY         7\r
-\r
-/*\r
- * PWM driver system settings.\r
- */\r
-#define STM32_PWM_USE_ADVANCED              FALSE\r
-#define STM32_PWM_USE_TIM1                  FALSE\r
-#define STM32_PWM_USE_TIM2                  FALSE\r
-#define STM32_PWM_USE_TIM3                  FALSE\r
-#define STM32_PWM_USE_TIM4                  FALSE\r
-#define STM32_PWM_USE_TIM5                  FALSE\r
-#define STM32_PWM_USE_TIM8                  FALSE\r
-#define STM32_PWM_TIM1_IRQ_PRIORITY         7\r
-#define STM32_PWM_TIM2_IRQ_PRIORITY         7\r
-#define STM32_PWM_TIM3_IRQ_PRIORITY         7\r
-#define STM32_PWM_TIM4_IRQ_PRIORITY         7\r
-#define STM32_PWM_TIM5_IRQ_PRIORITY         7\r
-#define STM32_PWM_TIM8_IRQ_PRIORITY         7\r
-\r
-/*\r
- * RTC driver system settings.\r
- */\r
-#define STM32_RTC_IRQ_PRIORITY              15\r
-\r
-/*\r
- * SERIAL driver system settings.\r
- */\r
-#define STM32_SERIAL_USE_USART1             TRUE\r
-#define STM32_SERIAL_USE_USART2             TRUE\r
-#define STM32_SERIAL_USE_USART3             TRUE\r
-#define STM32_SERIAL_USE_UART4              FALSE\r
-#define STM32_SERIAL_USE_UART5              FALSE\r
-#define STM32_SERIAL_USE_USART6             FALSE\r
-#define STM32_SERIAL_USART1_PRIORITY        12\r
-#define STM32_SERIAL_USART2_PRIORITY        12\r
-#define STM32_SERIAL_USART3_PRIORITY        12\r
-#define STM32_SERIAL_UART4_PRIORITY         12\r
-#define STM32_SERIAL_UART5_PRIORITY         12\r
-#define STM32_SERIAL_USART6_PRIORITY        12\r
-\r
-/*\r
- * SPI driver system settings.\r
- */\r
-#define STM32_SPI_USE_SPI1                  TRUE\r
-#define STM32_SPI_USE_SPI2                  FALSE\r
-#define STM32_SPI_USE_SPI3                  FALSE\r
-#define STM32_SPI_SPI1_DMA_PRIORITY         1\r
-#define STM32_SPI_SPI2_DMA_PRIORITY         1\r
-#define STM32_SPI_SPI3_DMA_PRIORITY         1\r
-#define STM32_SPI_SPI1_IRQ_PRIORITY         10\r
-#define STM32_SPI_SPI2_IRQ_PRIORITY         10\r
-#define STM32_SPI_SPI3_IRQ_PRIORITY         10\r
-#define STM32_SPI_DMA_ERROR_HOOK(spip)      chSysHalt()\r
-\r
-/*\r
- * UART driver system settings.\r
- */\r
-#define STM32_UART_USE_USART1               FALSE\r
-#define STM32_UART_USE_USART2               FALSE\r
-#define STM32_UART_USE_USART3               FALSE\r
-#define STM32_UART_USART1_IRQ_PRIORITY      12\r
-#define STM32_UART_USART2_IRQ_PRIORITY      12\r
-#define STM32_UART_USART3_IRQ_PRIORITY      12\r
-#define STM32_UART_USART1_DMA_PRIORITY      0\r
-#define STM32_UART_USART2_DMA_PRIORITY      0\r
-#define STM32_UART_USART3_DMA_PRIORITY      0\r
-#define STM32_UART_DMA_ERROR_HOOK(uartp)    chSysHalt()\r
-\r
-/*\r
- * USB driver system settings.\r
- */\r
-#define STM32_USB_USE_USB1                  FALSE\r
-#define STM32_USB_LOW_POWER_ON_SUSPEND      FALSE\r
-#define STM32_USB_USB1_HP_IRQ_PRIORITY      6\r
-#define STM32_USB_USB1_LP_IRQ_PRIORITY      14\r
diff --git a/setup.mk b/setup.mk
deleted file mode 100644 (file)
index 131405e..0000000
--- a/setup.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-# uncomment these if running from default project location\r
-# Path to ChibiOS\r
-#CHIBIOS    = ../ChibiOS_2.6.2\r
-# Path to convex\r
-#CONVEX     = ../convex/cortex\r
-\r
-# uncomment to use the optional code like the smart motor library\r
-#CONVEX_OPT  = yes\r
-\r
-# User C code files\r
-VEXUSERSRC = vexuser.cpp src/motor.cpp \r
-\r
-# Uncomment and add/modify user include files\r
-VEXUSERINC = include/\r
-\r
diff --git a/src/motor.cpp b/src/motor.cpp
deleted file mode 100644 (file)
index d9e7c4b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <motor.h>
-
-
diff --git a/vexuser.cpp b/vexuser.cpp
deleted file mode 100644 (file)
index 8bd3088..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-#include <unistd.h>\r
-#include <array>\r
-\r
-#include "ch.h"                // needs for all ChibiOS programs\r
-#include "hal.h"               // hardware abstraction layer header\r
-#include "vex.h"               // vex library header\r
-\r
-#include <motor.h>\r
-#include <control.h>\r
-\r
-//static WORKING_AREA(waVexIME, 512);\r
-//static msg_t vexIME(void *);\r
-\r
-// Digi IO configuration\r
-static vexDigiCfg dConfig[] = {\r
-};\r
-\r
-static vexMotorCfg mConfig[] = {\r
-       { MOTOR_CFG_MOT(mClawThingy,      393T, Normal),   MOTOR_CFG_NOIME },\r
-       { MOTOR_CFG_MOT(mDriveFrontLeft,  393T, Normal),   MOTOR_CFG_NOIME },\r
-       { MOTOR_CFG_MOT(mDriveFrontRight, 393T, Reversed), MOTOR_CFG_NOIME },\r
-       { MOTOR_CFG_MOT(mDriveBackLeft,   393T, Reversed), MOTOR_CFG_NOIME },\r
-       { MOTOR_CFG_MOT(mDriveBackRight,  393T, Normal),   MOTOR_CFG_NOIME },\r
-       { MOTOR_CFG_MOT(mLiftLowRight,    393T, Normal),   MOTOR_CFG_IME(iLiftLowRight)  },\r
-       { MOTOR_CFG_MOT(mLiftHighRight,   393T, Normal),   MOTOR_CFG_IME(iLiftHighRight) },\r
-       { MOTOR_CFG_MOT(mLiftLowLeft,     393T, Normal),   MOTOR_CFG_IME(iLiftLowLeft)   },\r
-       { MOTOR_CFG_MOT(mLiftHighLeft,    393T, Normal),   MOTOR_CFG_IME(iLiftHighLeft)  },\r
-       { MOTOR_CFG_MOT(mPickupThingy,    393T, Normal),   MOTOR_CFG_NOIME }\r
-};\r
-\r
-void vexUserSetup(void)\r
-{\r
-       vexDigitalConfigure(dConfig, DIG_CONFIG_SIZE(dConfig));\r
-       vexMotorConfigure(mConfig, MOT_CONFIG_SIZE(mConfig));\r
-}\r
-\r
-void vexUserInit(void)\r
-{}\r
-\r
-#define AIRCR_ADDR             0xE000ED0C\r
-#define VECTKEY                        0x05FA\r
-#define SYSRESETREQ            (1<<2)\r
-#define VECTRESET              (1<<0)\r
-\r
-void softwareReset(void){\r
-       uint32_t AIRCR = *((uint32_t *)AIRCR_ADDR);\r
-       AIRCR = (AIRCR & 0xFFFF) | (VECTKEY << 16) | SYSRESETREQ | VECTRESET;\r
-       *((volatile uint32_t *)0xE000ED0C) = AIRCR;\r
-       asm("DSB");\r
-       while(1);\r
-}\r
-\r
-msg_t vexAutonomous(void* arg)\r
-{\r
-    (void)arg;\r
-\r
-    vexTaskRegister("auton");\r
-\r
-       vexMotorSet(mClawThingy, -127);\r
-       vexMotorSet(mPickupThingy, -64);\r
-       vexSleep(300);\r
-       vexMotorSet(mClawThingy, 0);\r
-       vexMotorSet(mPickupThingy, 0);\r
-\r
-       vexMotorSet(mDriveFrontLeft,  -127);\r
-       vexMotorSet(mDriveFrontRight, -127);\r
-       vexMotorSet(mDriveBackLeft,   -127);\r
-       vexMotorSet(mDriveBackRight,  -127);\r
-       vexSleep(3000);\r
-       vexMotorSet(mDriveFrontLeft,  30);\r
-       vexMotorSet(mDriveFrontRight, 30);\r
-       vexMotorSet(mDriveBackLeft,   30);\r
-       vexMotorSet(mDriveBackRight,  30);\r
-       vexSleep(1000);\r
-       vexMotorSet(mDriveFrontLeft,  0);\r
-       vexMotorSet(mDriveFrontRight, 0);\r
-       vexMotorSet(mDriveBackLeft,   0);\r
-       vexMotorSet(mDriveBackRight,  0);\r
-\r
-    while(1)\r
-        vexSleep(25);\r
-\r
-    return (msg_t)0;\r
-}\r
-\r
-int doubleButton(int btnp, int btnn, int speed);\r
-\r
-msg_t vexOperator(void* arg)\r
-{\r
-       Controller joyMain (1);\r
-\r
-       (void)arg;\r
-\r
-       vexTaskRegister("operator");\r
-\r
-       //chThdCreateStatic(waVexIME, sizeof(waVexIME), NORMALPRIO - 1, vexIME, nullptr);\r
-\r
-       while(!chThdShouldTerminate()) {\r
-\r
-               // control update\r
-               joyMain.update();\r
-\r
-               // drive motors\r
-               int dx = joyMain->Ch4, dy = -joyMain->Ch3;\r
-               vexMotorSet(mDriveFrontLeft,  dy - dx);\r
-               vexMotorSet(mDriveFrontRight, dy + dx);\r
-               vexMotorSet(mDriveBackLeft,   dy - dx);\r
-               vexMotorSet(mDriveBackRight,  dy + dx);\r
-\r
-               // lift motors\r
-#ifndef NEW_LIFT\r
-               int ly = joyMain->Ch2;\r
-               vexMotorSet(mLiftLowRight,  ly);\r
-               vexMotorSet(mLiftHighRight, ly);\r
-               vexMotorSet(mLiftLowLeft,   ly);\r
-               vexMotorSet(mLiftHighLeft,  ly);\r
-#else\r
-               if (joyMain->Btn8U)\r
-                       motorCountInc();\r
-               else if (joyMain->Btn7D)\r
-                       motorCountDec();\r
-#endif // NEW_LIFT\r
-\r
-               // lift thingy\r
-               vexMotorSet(mPickupThingy, doubleButton(joyMain->Btn5U, joyMain->Btn5D, 64));\r
-\r
-               // claw thingy\r
-               vexMotorSet(mClawThingy, doubleButton(joyMain->Btn6U, joyMain->Btn6D, 127));\r
-\r
-               if (joyMain->Btn8R)\r
-                       softwareReset();\r
-\r
-               vexSleep(25);\r
-       }\r
-\r
-       return (msg_t)0;\r
-}\r
-\r
-\r
-int doubleButton(int btnp, int btnn, int speed)\r
-{\r
-       return (btnp ? speed : (btnn ? -speed : 0));\r
-}\r
-\r
-extern "C" {\r
-       void _exit(int code) {\r
-               (void)code;\r
-\r
-               vexLcdPrintf(0, 0, "PANIC: exit(%d)", code);\r
-               vexLcdPrintf(0, 1, "Halting...");\r
-\r
-               while(1);\r
-       }\r
-       void _kill(pid_t pid) {\r
-               (void)pid;\r
-               // no way to kill here\r
-       }\r
-       pid_t _getpid(void) {\r
-               // no pids here\r
-               return 0;\r
-       }\r
-}\r
-\r
-/*using CountTuple = std::tuple<tVexMotor, tVexImeChannels, int32_t>;\r
-\r
-static std::array<CountTuple, 4> MotorCounts = {\r
-       std::make_tuple(mLiftLowLeft,   iLiftLowLeft,   0),\r
-       std::make_tuple(mLiftHighLeft,  iLiftHighLeft,  0),\r
-       std::make_tuple(mLiftLowRight,  iLiftLowRight,  0),\r
-       std::make_tuple(mLiftHighRight, iLiftHighRight, 0)\r
-};\r
-\r
-void\r
-motorCountInc(void)\r
-{\r
-       for (auto &c : MotorCounts)\r
-               std::get<2>(c) += 10;\r
-}\r
-\r
-void\r
-motorCountDec(void)\r
-{\r
-       for (auto &c : MotorCounts)\r
-               std::get<2>(c) -= 10;\r
-}\r
-\r
-static msg_t\r
-vexIME(void *arg)\r
-{\r
-       (void)arg;\r
-\r
-       vexTaskRegister("uime");\r
-\r
-       while (1) {\r
-               for (auto &c : MotorCounts) {\r
-                       auto count = vexImeGetPtr(std::get<1>(c))->count;\r
-                       auto comp = std::get<2>(c);\r
-\r
-                       if (count > comp)\r
-                               vexMotorSet(vexMotorGet(std::get<0>(c)) - 2);\r
-                       else if(count < comp)\r
-                               vexMotorSet(vexMotorGet(std::get<0>(c)) + 2);\r
-               }\r
-\r
-               vexSleep(100);\r
-       }\r
-}*/\r