Commit b725a254 authored by Andreas Schmidt's avatar Andreas Schmidt

Merge branch 'develop' into timer

parents 0c850fd9 fb9d8722
Pipeline #2417 passed with stages
in 1 minute and 46 seconds
......@@ -8,6 +8,7 @@
* Clock synchronization between sending stack and receiving stack
* Applications can specify packet-level expiration times
* Different receive modes for ASAP and time-synchronized operation
* Passive measurement of propagation delay, bottleneck data rate and packet loss rate
* Packet-level timing analysis using [X-Lap](http://xlap.larn.systems)
* [Hardware timestamping support](https://git.nt.uni-saarland.de/LARN/PRRT/wikis/hardware-timestamping)
......@@ -25,7 +26,7 @@ import prrt
port = int(sys.argv[1])
s = prrt.PrrtSocket(port=port, isSender=False)
s = prrt.PrrtSocket(port=port)
while True:
d = s.recv()
......@@ -44,7 +45,7 @@ import prrt
host = sys.argv[1]
port = int(sys.argv[2])
s = prrt.PrrtSocket(port=port, isSender=True)
s = prrt.PrrtSocket(port=port)
s.connect(host, port)
for i in range(10):
......
......@@ -3,11 +3,12 @@ import prrt
port = int(sys.argv[1])
s = prrt.PrrtSocket(port=port, isSender=False)
s = prrt.PrrtSocket(("127.0.0.1", port))
while True:
d = s.recv()
d, addr = s.recv()
d = d.decode("utf8")
if d != "Close":
print d
print(d, addr)
else:
break
......@@ -3,10 +3,11 @@ import prrt
host = sys.argv[1]
port = int(sys.argv[2])
localport = int(sys.argv[3])
s = prrt.PrrtSocket(port=port, isSender=True)
s.connect(host, port)
s = prrt.PrrtSocket(("127.0.1.1", localport), mtu=150)
s.connect((host, port))
for i in range(10):
s.send("Packet {}".format(i))
s.send("Close")
s.send("Packet {}".format(i).encode("utf8"))
s.send("Close".encode("utf8"))
......@@ -15,7 +15,7 @@ add_subdirectory(proto)
add_subdirectory(util)
add_executable(sender sender.c)
add_executable(receiver receiver.c)
add_executable(receiver receiver.c ../tests/common.h)
target_link_libraries(sender LINK_PUBLIC PRRT UTIL ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(receiver LINK_PUBLIC PRRT UTIL ${CMAKE_THREAD_LIBS_INIT})
include "posix/time.pxd"
include "sockets.pxd"
from libc.stdint cimport uint32_t, uint16_t, uint8_t, int32_t
from libc.string cimport const_char
cdef extern from "pthread.h" nogil:
ctypedef struct pthread_t:
pass
......@@ -26,18 +28,17 @@ cdef extern from "proto/channelStateInformation.h":
ctypedef prrtChannelStateInformation PrrtChannelStateInformation
cdef extern from "proto/codingParams.h":
ctypedef struct prrtCodingParams:
ctypedef struct prrtCodingConfiguration:
uint8_t k
uint8_t r
uint8_t n
uint8_t c
uint8_t *n_cycle
ctypedef prrtCodingParams PrrtCodingParams
PrrtCodingParams *PrrtCodingParams_create()
PrrtCodingParams *PrrtCodingParams_copy(PrrtCodingParams *cpar)
bint PrrtCodingParams_update(PrrtCodingParams *cpar, uint8_t k, uint8_t n, uint8_t c, uint8_t *n_cycle)
bint PrrtCodingParams_destroy(PrrtCodingParams *cpar)
ctypedef prrtCodingConfiguration PrrtCodingConfiguration
PrrtCodingConfiguration *PrrtCodingConfiguration_create()
PrrtCodingConfiguration *PrrtCodingConfiguration_copy(PrrtCodingConfiguration *cpar)
bint PrrtCodingConfiguration_destroy(PrrtCodingConfiguration *cpar)
cdef extern from "util/list.h":
cdef struct list:
......@@ -62,7 +63,7 @@ cdef extern from "proto/block.h":
cdef struct prrtBlock:
uint32_t data_count
uint32_t redundancy_count
PrrtCodingParams coding_params
PrrtCodingConfiguration coding_params
uint32_t largest_data_length
uint16_t baseSequenceNumber
List* data_blocks
......@@ -94,9 +95,7 @@ cdef extern from "proto/receiver.h":
cdef extern from "proto/socket.h":
cdef struct prrtSocket:
int dataSocketFd
int feedbackSocketFd
pthread_t receiveFeedbackThread
int socketFd
pthread_t sendDataThread
pthread_mutex_t outQueueFilledMutex
......@@ -120,34 +119,41 @@ cdef extern from "proto/socket.h":
ctypedef prrtSocket PrrtSocket
cdef PrrtSocket* PrrtSocket_create(bint isSender, const uint32_t target_delay)
cdef PrrtSocket* PrrtSocket_create(const uint32_t mtu, const uint32_t target_delay)
bint PrrtSocket_bind(PrrtSocket *sock_ptr, const_char *ipAddress, const uint16_t port)
int PrrtSocket_close(const PrrtSocket *sock_ptr)
int PrrtSocket_connect(PrrtSocket *sock_ptr, const_char *host, const uint16_t port)
int PrrtSocket_send(PrrtSocket *sock_ptr, const uint8_t *data, const size_t data_len)
int32_t PrrtSocket_recv(PrrtSocket *sock_ptr, void *buf_ptr) nogil
int32_t PrrtSocket_receive_asap(PrrtSocket *s, void *buf_ptr) nogil
int32_t PrrtSocket_receive_asap_wait(PrrtSocket *s, void *buf_ptr) nogil
int32_t PrrtSocket_receive_asap_timedwait(PrrtSocket *s, void *buf_ptr, timespec* deadline) nogil
int32_t PrrtSocket_recv(PrrtSocket *sock_ptr, void *buf_ptr, sockaddr* addr) nogil
int32_t PrrtSocket_receive_asap(PrrtSocket *s, void *buf_ptr, sockaddr* addr) nogil
int32_t PrrtSocket_receive_asap_wait(PrrtSocket *s, void *buf_ptr, sockaddr* addr) nogil
int32_t PrrtSocket_receive_asap_timedwait(PrrtSocket *s, void *buf_ptr, sockaddr* addr, timespec* deadline) nogil
int32_t PrrtSocket_receive_ordered(PrrtSocket *s, void *buf_ptr, prrtTimedelta_t time_window_us) nogil
int32_t PrrtSocket_receive_ordered_wait(PrrtSocket *s, void *buf_ptr, prrtTimedelta_t time_window_us) nogil
int32_t PrrtSocket_receive_ordered_timedwait(PrrtSocket *s, void *buf_ptr, prrtTimedelta_t time_window_us, timespec* deadline) nogil
int32_t PrrtSocket_receive_ordered(PrrtSocket *s, void *buf_ptr, sockaddr* addr, prrtTimedelta_t time_window_us) nogil
int32_t PrrtSocket_receive_ordered_wait(PrrtSocket *s, void *buf_ptr, sockaddr* addr, prrtTimedelta_t time_window_us) nogil
int32_t PrrtSocket_receive_ordered_timedwait(PrrtSocket *s, void *buf_ptr, sockaddr* addr, prrtTimedelta_t time_window_us, timespec* deadline) nogil
bint PrrtSocket_set_sock_opt(PrrtSocket *sock_ptr, const_char *name, const uint32_t value)
uint32_t PrrtSocket_get_sock_opt(PrrtSocket *sock_ptr, const_char *name)
bint PrrtSocket_set_coding_parameters(PrrtSocket *s, uint8_t k, uint8_t n, uint8_t c, uint8_t *n_cycle)
PrrtCodingParams *PrrtSocket_get_coding_parameters(PrrtSocket *s)
PrrtCodingConfiguration *PrrtSocket_get_coding_parameters(PrrtSocket *s)
bint PrrtSocket_uses_thread_pinning(PrrtSocket *socket)
uint32_t PrrtSocket_get_rtprop(PrrtSocket *socket)
bint PrrtSocket_uses_thread_pinning(PrrtSocket *socket)
uint32_t PrrtSocket_get_rtt(PrrtSocket *socket)
float PrrtSocket_get_plr(PrrtSocket *socket)
uint32_t PrrtSocket_get_delivery_rate(PrrtSocket *socket)
uint32_t PrrtSocket_get_rtprop_fwd(PrrtSocket *socket)
float PrrtSocket_get_plr_fwd(PrrtSocket *socket)
uint32_t PrrtSocket_get_delivery_rate_fwd(PrrtSocket *socket)
uint32_t PrrtSocket_get_btlbw_fwd(PrrtSocket *s);
uint32_t PrrtSocket_get_btlbw_back(PrrtSocket *s);
bint PrrtSocket_get_app_limited(PrrtSocket *socket)
bint PrrtSocket_enable_thread_pinning(PrrtSocket *socket)
char *PrrtSocket_inet_ntoa(in_addr*)
uint16_t PrrtSocket_ntohs(uint16_t v)
cdef extern from "proto/stores/packetDeliveryStore.h":
ctypedef struct PrrtPacketDeliveryStore:
pass
......@@ -170,3 +176,4 @@ cdef extern from "util/pipe.h":
cdef extern from "util/mpsc_queue.h":
ctypedef struct MPSCQueue:
pass
......@@ -5,6 +5,13 @@
# define __builtin_ia32_rdtsc() (0)
#endif
#ifndef __cplusplus
# include <stdatomic.h>
#else
# include <atomic>
# define _Atomic(X) std::atomic< X >
#endif
#ifndef MAX
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#endif
......@@ -29,6 +36,8 @@
#define RRT_ALPHA 0.125
#define MIN_RTT 300
// Uncomment the line below if you are compiling on Windows.
// #define WINDOWS
#include <stdio.h>
......
add_library(PRRT ../defines.h
set (PRRT_SOURCES ../defines.h
block.c block.h
channelStateInformation.c channelStateInformation.h
clock.c clock.h
......@@ -9,7 +9,6 @@ add_library(PRRT ../defines.h
../xlap/xlap.c ../xlap/xlap.h
applicationConstraints.c applicationConstraints.h
processes/dataReceiver.c processes/dataReceiver.h
processes/feedbackReceiver.c processes/feedbackReceiver.h
processes/dataTransmitter.c processes/dataTransmitter.h
stores/dataPacketStore.c stores/dataPacketStore.h
stores/deliveredPacketTable.c stores/deliveredPacketTable.h
......@@ -23,4 +22,10 @@ add_library(PRRT ../defines.h
types/packet.c types/packet.h
vdmcode/block_code.c vdmcode/block_code.h)
if (XLAP)
set(PRRT_SOURCES ${PRRT_SOURCES} ../xlap/xlap.c ../xlap/xlap.h)
endif()
add_library(PRRT ${PRRT_SOURCES})
target_link_libraries(PRRT rt)
......@@ -57,6 +57,14 @@ bool PrrtBlock_destroy(PrrtBlock *block_ptr)
PrrtPacket_destroy(pkt);
}
if(block_ptr->coder != NULL) {
PrrtCoder_destroy(block_ptr->coder);
}
if(block_ptr->codingParams != NULL) {
PrrtCodingConfiguration_destroy(block_ptr->codingParams);
}
List_destroy(block_ptr->dataPackets);
List_destroy(block_ptr->redundancyPackets);
free(block_ptr);
......@@ -68,17 +76,17 @@ bool PrrtBlock_destroy(PrrtBlock *block_ptr)
return false;
}
PrrtBlock * PrrtBlock_create(PrrtCodingParams *cpar, prrtSequenceNumber_t baseSequenceNumber)
PrrtBlock * PrrtBlock_create(PrrtCodingConfiguration *cpar, PrrtCoder* coder, prrtSequenceNumber_t baseSequenceNumber)
{
PrrtBlock *block_ptr = calloc(1, sizeof(PrrtBlock));
check_mem(block_ptr);
block_ptr->coder = coder;
block_ptr->codingParams = cpar;
block_ptr->dataPackets = List_create();
block_ptr->redundancyPackets = List_create();
block_ptr->baseSequenceNumber = baseSequenceNumber;
block_ptr->largestPayloadLength = 0;
block_ptr->coder = NULL;
pthread_mutexattr_t attr;
check(pthread_mutexattr_init(&attr) == EXIT_SUCCESS, "Mutex attr init failed.");
......@@ -184,8 +192,6 @@ void PrrtBlock_encode(PrrtBlock *block_ptr, prrtSequenceNumber_t *seqno)
prrtSequenceNumber_t baseSequenceNumber = block_ptr->baseSequenceNumber;
prrtPacketLength_t length = block_ptr->largestPayloadLength;
PrrtCoder *coder = block_ptr->codingParams->coder;
gf **src = calloc(k, sizeof(gf *));
check_mem(src);
......@@ -203,7 +209,7 @@ void PrrtBlock_encode(PrrtBlock *block_ptr, prrtSequenceNumber_t *seqno)
for(j = 0; j < r; j++) {
fec[j] = calloc(length, sizeof(gf));
check_mem(fec[j]);
PrrtCoder_encode(coder, src, fec[j], j + k, length);
PrrtCoder_encode(block_ptr->coder, src, fec[j], j + k, length);
PrrtPacket *red_packet_ptr = PrrtPacket_create_redundancy_packet(0, (void *) fec[j], length, *seqno,
(uint8_t) (k + j), block_ptr->baseSequenceNumber,
block_ptr->codingParams);
......@@ -237,8 +243,6 @@ bool PrrtBlock_decode(PrrtBlock *block_ptr)
prrtSequenceNumber_t baseSequenceNumber = block_ptr->baseSequenceNumber;
prrtPacketLength_t length = block_ptr->largestPayloadLength;
PrrtCoder *coder = block_ptr->codingParams->coder;
fec = calloc(k, sizeof(gf *));
check_mem(fec);
for(i = 0; i < k; i++) {
......@@ -254,7 +258,7 @@ bool PrrtBlock_decode(PrrtBlock *block_ptr)
gather_data_packets(block_ptr, fec, idx_p);
gather_redundancy_packets(block_ptr, fec, idx_p);
check(PrrtCoder_decode(coder, fec, idx_p, length) == EXIT_SUCCESS, "Could not decode current block.");
check(PrrtCoder_decode(block_ptr->coder, fec, idx_p, length) == EXIT_SUCCESS, "Could not decode current block.");
for(j = 0; j < k; j++) {
if(idx_p[j] >= k) {
......
......@@ -8,21 +8,21 @@
#include "vdmcode/block_code.h"
typedef struct prrtBlock {
PrrtCodingParams* codingParams;
PrrtCodingConfiguration* codingParams;
prrtPacketLength_t largestPayloadLength;
prrtSequenceNumber_t baseSequenceNumber;
List*dataPackets;
List*redundancyPackets;
bool isCoded;
PrrtCoder *coder;
pthread_mutex_t lock;
PrrtCoder *coder;
} PrrtBlock;
/**
* Allocate space for a block.
*/
PrrtBlock * PrrtBlock_create(PrrtCodingParams *cpar, prrtSequenceNumber_t baseSequenceNumber);
PrrtBlock * PrrtBlock_create(PrrtCodingConfiguration *cpar, PrrtCoder* coder, prrtSequenceNumber_t baseSequenceNumber);
/**
* Frees the PrrtBlock data structure.
......
......@@ -4,6 +4,7 @@
#include "../util/dbg.h"
#include "channelStateInformation.h"
#include "clock.h"
#include "receiver.h"
PrrtChannelStateInformation * PrrtChannelStateInformation_create()
{
......@@ -15,6 +16,15 @@ PrrtChannelStateInformation * PrrtChannelStateInformation_create()
csi->rtprop = TIMESTAMP_SPACE;
csi->rtprop_filter_length_us = 2 * 1000 * 1000; // 2 seconds
csi->deliveryRate = 0;
csi->btlbw = 0;
csi->btlbw_next_round_delivered = 0;
csi->btlbw_round_start = false;
csi->btlbw_round_count = 0;
csi->btlbw_filter_length = 10;
csi->appLimited = 0;
csi->plr = 0.0;
return csi;
error:
......@@ -42,11 +52,16 @@ void PrrtChannelStateInformation_update_plr(PrrtChannelStateInformation *csi, pr
}
void PrrtChannelStateInformation_update_delivery_rate(PrrtChannelStateInformation *csi, prrtDeliveryRate_t rate) {
void PrrtChannelStateInformation_update_delivery_rate(PrrtChannelStateInformation *csi, PrrtPacket* packet, prrtDeliveryRate_t rate) {
pthread_mutex_lock(&csi->lock);
csi->deliveryRate = rate;
pthread_mutex_unlock(&csi->lock);
}
void PrrtChannelStateInformation_update_app_limited(PrrtChannelStateInformation *csi, bool appLimited) {
pthread_mutex_lock(&csi->lock);
csi->appLimited = appLimited;
pthread_mutex_unlock(&csi->lock);
}
prrtTimedelta_t PrrtChannelStateInformation_get_rtprop(PrrtChannelStateInformation *csi)
{
......@@ -71,4 +86,12 @@ prrtPacketLossRate_t PrrtChannelStateInformation_get_plr(PrrtChannelStateInforma
prrtDeliveryRate_t PrrtChannelStateInformation_get_delivery_rate(PrrtChannelStateInformation *csi) {
return csi->deliveryRate;
}
prrtDeliveryRate_t PrrtChannelStateInformation_get_btlbw(PrrtChannelStateInformation *csi) {
return csi->btlbw;
}
bool PrrtChannelStateInformation_get_app_limited(PrrtChannelStateInformation *csi) {
return csi->appLimited;
}
\ No newline at end of file
......@@ -6,22 +6,37 @@
typedef struct prrtChannelStateInformation {
pthread_mutex_t lock;
prrtTimedelta_t rtprop;
prrtTimestamp_t rtprop_stamp;
prrtTimedelta_t rtprop_filter_length_us;
bool rtprop_expired;
prrtPacketLossRate_t plr;
prrtDeliveryRate_t deliveryRate;
prrtDeliveryRate_t btlbw;
prrtByteCount_t btlbw_next_round_delivered;
bool btlbw_round_start;
uint32_t btlbw_round_count;
uint8_t btlbw_filter_length;
bool appLimited;
} PrrtChannelStateInformation;
PrrtChannelStateInformation* PrrtChannelStateInformation_create(void);
void PrrtChannelStateInformation_update_rtprop(PrrtChannelStateInformation *csi, prrtTimedelta_t rtprop);
prrtTimedelta_t PrrtChannelStateInformation_get_rtprop(PrrtChannelStateInformation *csi);
prrtDeliveryRate_t PrrtChannelStateInformation_get_delivery_rate(PrrtChannelStateInformation *csi);
prrtDeliveryRate_t PrrtChannelStateInformation_get_btlbw(PrrtChannelStateInformation *csi);
bool PrrtChannelStateInformation_get_app_limited(PrrtChannelStateInformation *csi);
prrtPacketLossRate_t PrrtChannelStateInformation_get_plr(PrrtChannelStateInformation* csi);
void PrrtChannelStateInformation_update_plr(PrrtChannelStateInformation *csi, prrtSequenceNumber_t erasures,
prrtSequenceNumber_t packets);
void PrrtChannelStateInformation_update_delivery_rate(PrrtChannelStateInformation *csi, prrtDeliveryRate_t rate);
void PrrtChannelStateInformation_update_delivery_rate(PrrtChannelStateInformation *csi, PrrtPacket* packet, prrtDeliveryRate_t rate);
void PrrtChannelStateInformation_update_app_limited(PrrtChannelStateInformation *csi, bool appLimited);
bool PrrtChannelStateInformation_destroy(PrrtChannelStateInformation* csi);
void PrrtChannelStateInformation_print(PrrtChannelStateInformation *csi);
......
......@@ -2,70 +2,37 @@
#include "../util/common.h"
#include "../util/dbg.h"
#include "../defines.h"
#include "codingParams.h"
PrrtCodingParams *PrrtCodingParams_create(void)
{
PrrtCodingParams *cpar = calloc(1, sizeof(PrrtCodingParams));
check_mem(cpar);
pthread_mutex_init(&cpar->lock, NULL);
cpar->coder = NULL;
uint8_t* n_cycle = calloc(1, sizeof(uint8_t));
n_cycle[0] = N_START - K_START;
PrrtCodingParams_update(cpar, K_START, N_START, 1, n_cycle);
PrrtCodingConfiguration *PrrtCodingConfiguration_create(uint8_t k, uint8_t n, uint8_t c, uint8_t *n_cycle)
{
PrrtCodingConfiguration *cc = calloc(1, sizeof(PrrtCodingConfiguration));
check_mem(cc);
cc->k = k;
cc->n = n;
cc->r = cc->n - cc->k;
cc->c = c;
if(n_cycle != NULL) {
cc->n_cycle = (uint8_t*) realloc(cc->n_cycle, cc->c * sizeof(int8_t));
memcpy(cc->n_cycle, n_cycle, cc->c * sizeof(int8_t));
}
return cpar;
return cc;
error:
PERROR("Memory issue.%s","");
return NULL;
}
bool PrrtCodingParams_update(PrrtCodingParams *cpar, uint8_t k, uint8_t n, uint8_t c, uint8_t *n_cycle) {
cpar->k = k;
cpar->n = n;
cpar->r = cpar->n - cpar->k;
cpar->c = c;
if(cpar->n_cycle != NULL) {
free(cpar->n_cycle);
}
cpar->n_cycle = n_cycle;
PrrtCoder_get_coder(&cpar->coder, n, k);
return true;
PrrtCodingConfiguration *PrrtCodingConfiguration_copy(PrrtCodingConfiguration *codingConfiguration) {
return PrrtCodingConfiguration_create(codingConfiguration->k, codingConfiguration->n, codingConfiguration->c, codingConfiguration->n_cycle);
}
PrrtCodingParams* PrrtCodingParams_copy(PrrtCodingParams *cpar) {
PrrtCodingParams *result = PrrtCodingParams_create();
check(pthread_mutex_lock(&cpar->lock) == EXIT_SUCCESS, "Lock failed.");
result->k = cpar->k;
result->n = cpar->n;
result->r = cpar->r;
result->c = cpar->c;
result->n_cycle = (uint8_t*) realloc(result->n_cycle, result->c * sizeof(int8_t));
memcpy(result->n_cycle, cpar->n_cycle, result->c * sizeof(int8_t));
// PrrtCoder_get_coder(&result->coder, result->n, result->k); // TODO
check(pthread_mutex_unlock(&cpar->lock) == EXIT_SUCCESS, "Unlock failed");
return result;
error:
PERROR("Could not copy%s", "");
return NULL;
}
bool PrrtCodingParams_destroy(PrrtCodingParams * cpar) {
pthread_mutex_destroy(&cpar->lock);
PrrtCoder_destroy(cpar->coder);
if(cpar->n_cycle != NULL) {
free(cpar->n_cycle);
bool PrrtCodingConfiguration_destroy(PrrtCodingConfiguration *codingConfiguration) {
if(codingConfiguration->n_cycle != NULL) {
free(codingConfiguration->n_cycle);
}
free(cpar);
free(codingConfiguration);
return true;
}
......@@ -4,23 +4,17 @@
#include <pthread.h>
#include <stdint.h>
#include <stdbool.h>
#include "vdmcode/block_code.h"
typedef struct prrtCodingParams {
pthread_mutex_t lock;
typedef struct prrtCodingConfiguration {
uint8_t k;
uint8_t r;
uint8_t n;
uint8_t c;
uint8_t* n_cycle;
} PrrtCodingConfiguration;
PrrtCoder* coder;
} PrrtCodingParams;
PrrtCodingParams * PrrtCodingParams_create(void);
PrrtCodingParams * PrrtCodingParams_copy(PrrtCodingParams *cpar);
bool PrrtCodingParams_update(PrrtCodingParams * cpar, uint8_t k, uint8_t n, uint8_t c, uint8_t *n_cycle);
bool PrrtCodingParams_destroy(PrrtCodingParams * cpar);
PrrtCodingConfiguration *PrrtCodingConfiguration_create(uint8_t k, uint8_t n, uint8_t c, uint8_t *n_cycle);
PrrtCodingConfiguration *PrrtCodingConfiguration_copy(PrrtCodingConfiguration *codingConfiguration);
bool PrrtCodingConfiguration_destroy(PrrtCodingConfiguration *codingConfiguration);
#endif //PRRT_CODING_PARAMS_H
/*
* pp.h
*
* This file contains some useful preprocessor macros.
*
* Warning: This file is auto-generated. Do not edit.
*/
#ifndef __PP_H__
#define __PP_H__ 1
/*
* PP__cmn_* macros
*
* PP common macros
*/
#define PP__cmn_id(...) __VA_ARGS__
#define PP__cmn_call(m,...) m(__VA_ARGS__)
/*
* PP__arg_* macros
*
* PP macros that operate on argument lists.
*/
#define PP_arg_count(...) PP__arg_cnt(__VA_ARGS__)
#define PP__arg_cnt(...) PP__arg_cnt_2(__VA_ARGS__,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
#define PP__arg_cnt_2(_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9,_a10,_a11,_a12,_a13,_a14,_a15,_a16,_a17,_a18,_a19,_a20,_a21,_a22,_a23,_a24,_a25,_a26,_a27,_a28,_a29,_a30,_a31,_a32,_a33,_a34,_a35,_a36,_a37,_a38,_a39,_a40,_a41,_a42,_a43,_a44,_a45,_a46,_a47,_a48,_a49,_a50,_a51,_a52,_a53,_a54,_a55,_a56,_a57,_a58,_a59,_a60,_a61,_a62,_a63,_a64,_a65,_a66,_a67,_a68,_a69,_a70,_a71,_a72,_a73,_a74,_a75,_a76,_a77,_a78,_a79,_a80,_a81,_a82,_a83,_a84,_a85,_a86,_a87,_a88,_a89,_a90,_a91,_a92,_a93,_a94,_a95,_a96,_a97,_a98,_a99,_a100,_a101,_a102,_a103,_a104,_a105,_a106,_a107,_a108,_a109,_a110,_a111,_a112,_a113,_a114,_a115,_a116,_a117,_a118,_a119,_a120,_a121,_a122,_a123,_a124,_a125,_a126,_a127,_a128,_x,...) _x
/*
* argument list map-reduce macros
*/
#define PP__mapreduce_1(reduce,eol,map,a) eol(map(a))
#define PP__mapreduce_2(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_1(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_3(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_2(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_4(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_3(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_5(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_4(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_6(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_5(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_7(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_6(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_8(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_7(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_9(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_8(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_10(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_9(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_11(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_10(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_12(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_11(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_13(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_12(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_14(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_13(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_15(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_14(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_16(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_15(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_17(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_16(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_18(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_17(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_19(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_18(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_20(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_19(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_21(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_20(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_22(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_21(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_23(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_22(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_24(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_23(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_25(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_24(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_26(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_25(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_27(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_26(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_28(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_27(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_29(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_28(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_30(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_29(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_31(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_30(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_32(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_31(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_33(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_32(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_34(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_33(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_35(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_34(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_36(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_35(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_37(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_36(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_38(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_37(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_39(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_38(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_40(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_39(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_41(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_40(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_42(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_41(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_43(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_42(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_44(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_43(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_45(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_44(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_46(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_45(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_47(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_46(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_48(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_47(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_49(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_48(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_50(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_49(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_51(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_50(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_52(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_51(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_53(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_52(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_54(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_53(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_55(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_54(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_56(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_55(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_57(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_56(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_58(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_57(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_59(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_58(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_60(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_59(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_61(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_60(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_62(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_61(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_63(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_62(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_64(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_63(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_65(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_64(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_66(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_65(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_67(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_66(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_68(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_67(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_69(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_68(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_70(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_69(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_71(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_70(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_72(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_71(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_73(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_72(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_74(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_73(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_75(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_74(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_76(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_75(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_77(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_76(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_78(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_77(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_79(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_78(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_80(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_79(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_81(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_80(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_82(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_81(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_83(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_82(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_84(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_83(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_85(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_84(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_86(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_85(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_87(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_86(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_88(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_87(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_89(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_88(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_90(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_89(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_91(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_90(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_92(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_91(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_93(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_92(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_94(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_93(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_95(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_94(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_96(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_95(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_97(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_96(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_98(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_97(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_99(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_98(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_100(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_99(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_101(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_100(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_102(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_101(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_103(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_102(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_104(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_103(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_105(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_104(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_106(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_105(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_107(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_106(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_108(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_107(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_109(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_108(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_110(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_109(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_111(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_110(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_112(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_111(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_113(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_112(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_114(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_113(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_115(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_114(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_116(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_115(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_117(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_116(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_118(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_117(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_119(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_118(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_120(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_119(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_121(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_120(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_122(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_121(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_123(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_122(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_124(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_123(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_125(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_124(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_126(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_125(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_127(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_126(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce_128(reduce,eol,map,head,...) reduce(map(head),PP__mapreduce_127(reduce,eol,map,__VA_ARGS__))
#define PP__mapreduce(reduce,eol,map,...) PP__mapreduce__i(PP__arg_cnt(__VA_ARGS__),reduce,eol,map,__VA_ARGS__)
#define PP__mapreduce__i(n,reduce,eol,map,...) PP__mapreduce__ii(n,reduce,eol,map,__VA_ARGS__)
#define PP__mapreduce__ii(n,reduce,eol,map,...) PP__mapreduce_##n(reduce,eol,map,__VA_ARGS__)
/*
* foreach loop
*/
#define PP_foreach(join,map,...) PP__mapreduce(join,PP__cmn_id,map,__VA_ARGS__)
/*
* common join and map operations
*/
#define PP_join_space(a,b) a b
#define PP_join_comma(a,b) a,b
#define PP_join_plus(a,b) a+b
#define PP_join_minus(a,b) a-b
#define PP_join_mul(a,b) a*b
#define PP_join_or(a,b) a|b
#define PP_join_and(a,b) a&b
#define PP_join_lor(a,b) a||b
#define PP_join_land(a,b) a&&b
#define PP_join_xor(a,b) a^b
#define PP_join_glue(a,b) PP__join_glue(a,b)