← Back to davo.co
summaryrefslogtreecommitdiffstats
path: root/life.h
blob: d5f7eec69646984b6b7fdfe7894f5a0f33d2bdb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "c23-fallback.h"
#include <ctype.h>
#ifndef __STDC_NO_THREADS__
# include <threads.h>
#else
# error This needs C11 threads, aborting.
#endif
#include <stdatomic.h>


enum { life_maxit = 1ull << 23, };

typedef struct life life;
struct life {
  mtx_t mtx;    //< Mutex that protects Mv
  cnd_t draw;   //< cnd that controls drawing
  cnd_t acco;   //< cnd that controls accounting
  cnd_t upda;   //< cnd that controls updating

  void*restrict Mv;            //< bool M[n0][n1];
  bool (*visited)[life_maxit]; //< Hashing constellations

  // A bunch of parameters that are not subject to change
  size_t n0;    //< Number of rows
  size_t n1;    //< Number of columns
  size_t off0;  //< Start row
  size_t len0;  //< Number of rows to be handled
  size_t off1;  //< Start column
  size_t len1;  //< Number of columns to be handled
  void* restrict Bv;  //< Unsigned char B[len0][len1];


  // Parameters that are updated but that are protected by the mutex
  size_t iteration;   //< Current iteration
  size_t accounted;   //< Last accounted iteration
  size_t drawn;       //< Last drawn iteration
  size_t last;        //< Last iteration with new state
  size_t birth9;      //< Number of birth9 calls

  // Parameters that will dynamically be changed by
  // different threads
  _Atomic(size_t) constellations; //< Constellations visited
  _Atomic(size_t) x0;             //< Cursor position, row
  _Atomic(size_t) x1;             //< Cursor position, column
  _Atomic(size_t) frames;         //< FPS for display
  _Atomic(bool)   finished;       //< This game is finished.
};

inline
void life_advance(life* L, signed t0, signed t1) {
  if (t0) {
    size_t n = L->n0-2;
    L->x0 = ((L->x0-1)+n+t0)%n + 1;
  }
  if (t1) {
    size_t n = L->n1-2;
    L->x1 = ((L->x1-1)+n+t1)%n + 1;
  }
}

int life_wait(cnd_t*, mtx_t*);
void life_sleep(double s);

void life_birth9(life*);
size_t life_update(life*restrict L);
void life_count(life*restrict L);
void life_draw(life*);
void life_draw4(life*);
void life_account(life*);
life* life_init(life*, size_t _n, size_t _m, bool[_n][_m]);
void life_destroy(life* L);
void life_torus(life*);

#define LIFE_INITIALIZER                        \
{                                               \
    .visited = 0,                               \
    .birth9 = 1,                                \
    .x0 = 1,                                    \
    .x1 = 1,                                    \
    .frames = 20,                               \
    .finished = false,                          \
    .constellations = 1,                        \
}