6

I have some output from a (C++) application that stores a tickcount value in a type that wraps to zero at 233. (8,589,934,592) (Don't have the code)

I need to write my own output in the same way. I retrieve the tickcount from a C lib through JNA, but if I store it in an int it wraps to -231 (-2,147,483,648) after ~25 days' tickcount and if I store it in a long it just keeps going past 233.

How can I store (or write) the value in Java in such a way that it wraps (to zero) at 233?

(Preferably a JRE7- & JRE8- on Win32- & Win64- & Linux-compatible solution)

To get the tickcount I use the following:

import com.sun.jna.*;
public interface Kernel32 extends Library {
    Kernel32 INSTANCE = (Kernel32) Native.loadLibrary((Platform.isWindows() ? "kernel32" : "c"), Kernel32.class);

    /**
     * Retrieves the number of milliseconds that have elapsed since the system was started.
     *
     * @return number of milliseconds that have elapsed since the system was started.
     * @see http://msdn2.microsoft.com/en-us/library/ms724408.aspx
     */
    Long GetTickCount();
}

public interface Clib extends Library {
    Clib INSTANCE = (Clib) Native.loadLibrary((Platform.isWindows() ? "kernel32" : "c"), Clib.class);

    /**
     * Retrieves the number of milliseconds that have elapsed since the system was started.
     *
     * @return number of milliseconds that have elapsed since the system was started.
     */
    Long clock();
}

// And later
Number n = (Platform.isWindows() ? Kernel32.INSTANCE.GetTickCount() : Clib.INSTANCE.clock()).toString());
Boann
  • 48,794
  • 16
  • 117
  • 146
Alex
  • 631
  • 1
  • 8
  • 33

2 Answers2

8

You can store the value in a long, then truncate the value to 33 bits (wrapping 233 around to 0) by doing:

n &= (1L << 33) - 1;

This is exactly the same as:

n &= 0x1_ffff_ffffL;

which is also the same as:

n &= 8_589_934_591L;
Boann
  • 48,794
  • 16
  • 117
  • 146
  • this will still eventually overflow – ControlAltDel Aug 06 '15 at 17:57
  • @ControlAltDel not if he does this after every increment. – RealSkeptic Aug 06 '15 at 18:01
  • @ControlAltDel It's supposed to overflow. Isn't that the point? – Boann Aug 06 '15 at 18:03
  • 1
    @RealSkeptic You don't need to do it after every increment. It will fix up the result to be the same as a true 33-bit int regardless of how much you added to it in the mean time. – Boann Aug 06 '15 at 18:06
  • 1
    I thought he meant overflowing in a different way (that is, if you did it once, and never again, it would overflow), otherwise it overflows just as it should. – RealSkeptic Aug 06 '15 at 18:07
  • I like @ControlAltDel's modulo solution for simplicity, any performance difference? – Alex Aug 07 '15 at 07:43
  • 1
    @AlexMan In general bit manipulation like this is much faster than modulo if you're counting every CPU cycle. But in practice you'll only notice the difference if doing billions of these operations, and for a constant divisor like this, the JVM might well be able to optimize the modulo and turn it into bit manipulation, so it could be just as fast. By the way there is a subtle behavior difference between the two techniques if the long value is ever negative, then the result of the modulo will also be negative, whereas the bit manipulation result will always be unsigned. – Boann Aug 07 '15 at 09:25
5

Simplest solution: You can do it in Java using a long, like

long count;

public void tick() {
  count++;
  count %= 8589934592L;
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80