views:

69

answers:

2

I have ported the code inside java.util.Random class in objectivec. I want to have an identical random number generator so that it synchs with the server app running on java. Now is this a safe porting and if not is there a way to mimic AtomicLong as it is found in java? Please see my code below.

static long long multiplier = 0x5DEECE66DL;
static long addend = 0xBL;
static long long mask = (0x1000000000000001L << 48) - 1;


-(void) initWithSeed:(long long) seed1 {
    [self setRandomSeed: 0L];// = new AtomicLong(0L);
    [self setSeed: seed1];
}

-(int) next:(int)bits {
    long long oldseed, nextseed;
    long long seed1 = [self.randomSeed longLongValue]; //AtomicLong
    //do {
        oldseed = seed1;
        nextseed = (oldseed * multiplier + addend) & mask;
    //} while (!seed.compareAndSet(oldseed, nextseed));
    [self setRandomSeed: [NSNumber numberWithLongLong:nextseed]];

    ///int ret = (int)(nextseed >>> (48 - bits));
    int ret = (unsigned int)(nextseed >> (48 - bits));
    return ret;
}
-(void) setSeed:(long long) seed1 {
    seed1 = (seed1 ^ multiplier) & mask;
    [self setRandomSeed: [NSNumber numberWithLongLong:seed1]];
}
+1  A: 

If you search for atomic manipulation, then there are the OSAtomic collection of functions. These functions allow various operation on 32 and 64 bits integer.

Laurent Etiemble
+1  A: 

If your objective is to make the generation of these numbers thread safe, the answer is it doesn't work as currently written. If two threads enter the next: method at the same time, they may both get the same value of the seed and both return the same value.

What I would do is forget about wrapping the number in a NSNumber object and just put the code in next: and setSeed: in @synchronised blocks

// randomSeed is a long long ivar 

-(void) setSeed:(long long) seed1 
{
    @synchronized(self)
    {
        randomSeed = (seed1 ^ multiplier) & mask;
    }
}

-(int) next:(int)bits 
{
    int ret;
    @synchronized(self)
    {
        long long oldseed, nextseed;
        long long seed1 = randomSeed;
        //do {
                 oldseed = seed1;
                 nextseed = (oldseed * multiplier + addend) & mask;
        //} while (!seed.compareAndSet(oldseed, nextseed)); /* you won't need to do this atomically */
        randomSeed = nextSeed;
        ///ret = (int)(nextseed >>> (48 - bits));
        ret = (unsigned int)(nextseed >> (48 - bits));
    }

    return ret;
}

I can't comment on whether your algorithm is right or not.

However, your init method needs to call [super init] like so:

-(id) init
{
    self = [super init];
    if (self != nil)
    {
        // init stuff
    }
    return self;
}
JeremyP