No subject


Fri Aug 27 17:10:57 UTC 2010


Modified:
    trunk/PCSC/src/simclist.c

Modified: trunk/PCSC/src/simclist.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/simclist.c?rev=5420&op=diff
==============================================================================
--- trunk/PCSC/src/simclist.c (original)
+++ trunk/PCSC/src/simclist.c Fri Nov 26 12:55:54 2010
@@ -19,12 +19,11 @@
  * SimCList library. See http://mij.oltrelinux.com/devel/simclist
  */
 
-/* SimCList implementation, version 1.4.4rc4 */
+/* SimCList implementation, version 1.5 */
 
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>      /* for setting errno */
-#include <inttypes.h>   /* (u)int*_t */
 #include <sys/types.h>
 #include <sys/uio.h>    /* for READ_ERRCHECK() and write() */
 #include <fcntl.h>      /* for open() etc */
@@ -37,11 +36,21 @@
 #include <stdint.h>
 
 
-/* use rand() in place of srand()? */
-#ifndef _BSD_SOURCE
-#   define random       rand
-#   define srandom      srand
+/* work around lack of inttypes.h support in broken Microsoft Visual Studio compilers */
+#if !defined(WIN32) || !defined(_MSC_VER)
+#   include <inttypes.h>   /* (u)int*_t */
+#else
+#   include <basetsd.h>
+typedef UINT8   uint8_t;
+typedef UINT16  uint16_t;
+typedef ULONG32 uint32_t;
+typedef UINT64  uint64_t;
+typedef INT8    int8_t;
+typedef INT16   int16_t;
+typedef LONG32  int32_t;
+typedef INT64   int64_t;
 #endif
+ 
 
 
 #ifndef SIMCLIST_NO_DUMPRESTORE
@@ -181,12 +190,54 @@
                                                     }                                                   \
                                                 } while (0);
 
+/*
+ * Random Number Generator
+ * 
+ * The user is expected to seed the RNG (ie call srand()) if 
+ * SIMCLIST_SYSTEM_RNG is defined.
+ *
+ * Otherwise, a self-contained RNG based on LCG is used; see
+ * http://en.wikipedia.org/wiki/Linear_congruential_generator .
+ *
+ * Facts pro local RNG:
+ * 1. no need for the user to call srand() on his own
+ * 2. very fast, possibly faster than OS
+ * 3. avoid interference with user's RNG
+ *
+ * Facts pro system RNG:
+ * 1. may be more accurate (irrelevant for SimCList randno purposes)
+ * 2. why reinvent the wheel
+ *
+ * Default to local RNG for user's ease of use.
+ */
+
+#ifdef SIMCLIST_SYSTEM_RNG
+/* keep track whether we initialized already (non-0) or not (0) */
+static unsigned random_seed = 0;
+
+/* use local RNG */
+static inline void seed_random() {
+    if (random_seed == 0)
+        random_seed = (unsigned)getpid() ^ (unsigned)time(NULL);
+}
+
+static inline long get_random() {
+    random_seed = (1664525 * random_seed + 1013904223);
+    return random_seed;
+}
+
+#else
+/* use OS's random generator */
+#   define  seed_random()
+#   define  get_random()        (rand())
+#endif
+
 
 /* list initialization */
 int list_init(list_t *restrict l) {
     if (l == NULL) return -1;
 
-    srandom((unsigned long)time(NULL));
+    seed_random();
 
     l->numels = 0;
 
@@ -360,10 +411,7 @@
     /* accept 1 slot overflow for fetching head and tail sentinels */
     if (posstart < -1 || posstart > (int)l->numels) return NULL;
 
-    if (0 == l->numels)
-        x = 0;
-    else
-        x = (float)(posstart+1) / l->numels;
+    x = (float)(posstart+1) / l->numels;
     if (x <= 0.25) {
         /* first quarter: get to posstart from head */
         for (i = -1, ptr = l->head_sentinel; i < posstart; ptr = ptr->next, i++);
@@ -393,10 +441,7 @@
     tmp->data = NULL;   /* save data from list_drop_elem() free() */
     list_drop_elem(l, tmp, pos);
     l->numels--;
-
-    if (0 == l->numels)
-        l->mid = NULL;
-
+    
     assert(list_repOk(l));
 
     return data;
@@ -479,8 +524,6 @@
 
     l->numels--;
 
-    if (0 == l->numels)
-        l->mid = NULL;
 
     assert(list_repOk(l));
 
@@ -762,7 +805,7 @@
     /* base of iteration: one element list */
     if (! (last > first)) return;
 
-    pivotid = (random() % (last - first + 1));
+    pivotid = (get_random() % (last - first + 1));
     /* pivotid = (last - first + 1) / 2; */
 
     /* find pivot */
@@ -1038,7 +1081,7 @@
     header.timestamp = (int64_t)timeofday.tv_sec * 1000000 + (int64_t)timeofday.tv_usec;
     header.timestamp = hton64(header.timestamp);
 
-    header.rndterm = htonl((int32_t)random());
+    header.rndterm = htonl((int32_t)get_random());
 
     /* total list size is postprocessed afterwards */
 
@@ -1302,9 +1345,11 @@
 static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos) {
     if (tmp == NULL) return -1;
 
-    /* fix mid pointer */
+    /* fix mid pointer. This is wrt the PRE situation */
     if (l->numels % 2) {    /* now odd */
-        if (pos >= l->numels/2) l->mid = l->mid->prev;
+        /* sort out the base case by hand */
+        if (l->numels == 1) l->mid = NULL;
+        else if (pos >= l->numels/2) l->mid = l->mid->prev;
     } else {                /* now even */
         if (pos < l->numels/2) l->mid = l->mid->next;
     }




More information about the Pcsclite-cvs-commit mailing list