0

To give a bit of context, I have n threads receiving ints. These are coming in cycles (let's say we have a uint16, so after 65535 the next received number will be zero again). There is no known mapping from the respective number to the thread it will be received from, like even numbers are received from thread 1 and odd numbers from thread 2 as a simple example. Some threads can also receive more numbers than others (which is actually the reason why the blocking is neccessary) There can be "jumps", meaning the numbers are not received in a strict ascending order. After a number x is received, the next number, be it in the same or another thread, need not be x+1 but can also be less than x or greater than x+1. We can make assumptions about the size of these jumps though (upper bound is N/2 for N being the largest number possible).

To allow the following subsystem to process the numbers correctly we need to make sure they don't drift apart too far when received. The following example should do the trick:

struct thread_status {
    bool block;
    uint16_t last;
}

void *thread_worker(void *data)
{
    struct thread_status *staus = (struct thread_status*)data;

    while (1) {
        if (status->block) {
            if (status->last <= MIN(array_of_lasts_from_all_threads))
                status->block = false;
            else
                continue;
        }

        status->last = receive_next();

        if (status->last >= MIN(array_of_lasts_from_all_threads) + ALLOWED_DIFF)
            status->block = true;
    }
}

Now the actual question is, how would I implement the MIN function? Instead of always comparing to the array of last values, I could also save the minimum last value and just compare to it. Then I need to implement the comparison operator though.

Another example to be more precicse: If I only have ints from 0 to 15 and 3 threads.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | |X|X| | |0| | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Here, X are the last read values from the other threads and 0 os the currently read value. MIN and comparison are easy here. However in this case

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|X|0| | | | | | | | | | | | | |X|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

the minimum value should be 15 and not zero.

flowit
  • 1,382
  • 1
  • 10
  • 36
  • What **EXACTLY** do you mean by *There is no known mapping from the respective number to the thread it will be received from* How do you receive numbers "from" a thread? Also, what does *the numbers are not received in a strict ascending order.* mean? The specifics in both cases are critical to any reliable solution. And FWIW, given the requirement to compare results across threads, more than one thread might not work as well as a single thread. – Andrew Henle Feb 11 '18 at 17:56
  • 1
    Are these two situations possible? `-----X-0X------` and `----0-XX------` – Sergey Kalinichenko Feb 11 '18 at 17:56
  • So.. like sequence numbers in networks, yes? – Martin James Feb 11 '18 at 18:17
  • Andrew: See the editet question for examples. dasblinkenlight: Yes. Martin: Exactly. But unfortunately I only have the numbers to work with, no additional information like for example in TCP. – flowit Feb 11 '18 at 19:31

1 Answers1

0

I think you might be asking the wrong question, but it's difficult to explain why. Let's answer the simple question first, and see if it helps you figure out how to implement (or avoid implementing) a MIN function.

If your array boundaries really do lie on a uint16_t boundary, you can find the distance between your 0 read and a given X index with simple subtraction. (Play around with this example a bit to see why.)

uint16_t recent = 1;
uint16_t previous = 65535;
uint16_t foo = (uint16_t)(recent - previous);
printf("%hu\n", foo);

You might think the result would be a uint16_t, but because of the casting rules in C it's probably going to be an int on your platform, thus the explicit cast above. If 0 is after X, this number will be relatively small; if it's the other way around, the number will be close to UINT16_MAX. If you cast to int16_t instead, on most modern platforms you should get a positive or negative number representing both ordering and distance.

If the array boundaries don't lie on a size boundary, you can use modulo arithmetic to "wrap" the subtraction back into a sane region before casting to a signed type.

Shobi
  • 10,374
  • 6
  • 46
  • 82
Jeff Hiner
  • 39
  • 1
  • 2
  • So basically what you are saying is that I should calculate the distance to all other values and block if one of those exceeds the maximum allowed difference? Yeah I guess this would be much easier to realize. – flowit Feb 11 '18 at 19:41