2017-05-26 04:48:44 +08:00
/*
* IRandom . h
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013 - 2018 Apple Inc . and the FoundationDB project authors
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* http : //www.apache.org/licenses/LICENSE-2.0
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
# ifndef FLOW_IRANDOM_H
# define FLOW_IRANDOM_H
# pragma once
2018-10-20 01:30:13 +08:00
# include "flow/Platform.h"
2017-05-26 04:48:44 +08:00
# include <stdint.h>
# if (defined(__APPLE__))
# include <ext/hash_map>
# else
# include <unordered_map>
# endif
class UID {
uint64_t part [ 2 ] ;
public :
UID ( ) { part [ 0 ] = part [ 1 ] = 0 ; }
UID ( uint64_t a , uint64_t b ) { part [ 0 ] = a ; part [ 1 ] = b ; }
std : : string toString ( ) const ;
std : : string shortString ( ) const ;
bool isValid ( ) const { return part [ 0 ] | | part [ 1 ] ; }
bool operator = = ( const UID & r ) const { return part [ 0 ] = = r . part [ 0 ] & & part [ 1 ] = = r . part [ 1 ] ; }
bool operator ! = ( const UID & r ) const { return part [ 0 ] ! = r . part [ 0 ] | | part [ 1 ] ! = r . part [ 1 ] ; }
bool operator < ( const UID & r ) const { return part [ 0 ] < r . part [ 0 ] | | ( part [ 0 ] = = r . part [ 0 ] & & part [ 1 ] < r . part [ 1 ] ) ; }
uint64_t hash ( ) const { return first ( ) ; }
uint64_t first ( ) const { return part [ 0 ] ; }
uint64_t second ( ) const { return part [ 1 ] ; }
static UID fromString ( std : : string const & ) ;
template < class Ar >
void serialize_unversioned ( Ar & ar ) { // Changing this serialization format will affect key definitions, so can't simply be versioned!
2018-12-29 02:49:26 +08:00
serializer ( ar , part [ 0 ] , part [ 1 ] ) ;
2017-05-26 04:48:44 +08:00
}
} ;
template < class Ar > void load ( Ar & ar , UID & uid ) { uid . serialize_unversioned ( ar ) ; }
template < class Ar > void save ( Ar & ar , UID const & uid ) { const_cast < UID & > ( uid ) . serialize_unversioned ( ar ) ; }
namespace std {
template < >
class hash < UID > : public unary_function < UID , size_t > {
public :
size_t operator ( ) ( UID const & u ) const { return u . hash ( ) ; }
} ;
}
class IRandom {
public :
virtual double random01 ( ) = 0 ;
virtual int randomInt ( int min , int maxPlusOne ) = 0 ;
virtual int64_t randomInt64 ( int64_t min , int64_t maxPlusOne ) = 0 ;
virtual uint32_t randomUInt32 ( ) = 0 ;
virtual UID randomUniqueID ( ) = 0 ;
virtual char randomAlphaNumeric ( ) = 0 ;
virtual std : : string randomAlphaNumeric ( int length ) = 0 ;
virtual uint64_t peek ( ) const = 0 ; // returns something that is probably different for different random states. Deterministic (and idempotent) for a deterministic generator.
// The following functions have fixed implementations for now:
template < class C >
decltype ( ( fake < const C > ( ) [ 0 ] ) ) randomChoice ( const C & c ) { return c [ randomInt ( 0 , ( int ) c . size ( ) ) ] ; }
template < class C >
void randomShuffle ( C & container ) {
int s = ( int ) container . size ( ) ;
2018-08-02 09:09:54 +08:00
for ( int i = 0 ; i < s ; i + + ) {
int j = randomInt ( i , s ) ;
if ( i ! = j ) {
std : : swap ( container [ i ] , container [ j ] ) ;
}
}
2017-05-26 04:48:44 +08:00
}
bool coinflip ( ) { return ( this - > random01 ( ) < 0.5 ) ; }
} ;
extern IRandom * g_random ;
extern IRandom * g_nondeterministic_random ;
extern IRandom * g_debug_random ;
extern FILE * randLog ;
# endif