(no subject)
A little bit of a delay in releasing the canvas server. I wanted to include an example of using it for running John Conway's Game of Life. That meant adding a few more functions and getting shared memory access working properly. That all works properly, and the Game of Life works really well. On a 500x500 pixel canvas it runs about 30 generations per second. Not bad! (This is not awk. It's a short C program that uses the canvas server for display.)
There are a couple more things I need to make demos for, and then I'll finish the documentation and release it. I know I keep saying I'll release it and then put it off, but I want it to be as useful as possible.
Here's just a few seconds of it, to give you an idea of how fast it runs, and below that, the C program.
I've uploaded it to YouTube (it might take a little time before it becomes available).
https://youtube.com/shorts/mbF7khhrmIQ?feature=share
Here is the C code I used:
There are a couple more things I need to make demos for, and then I'll finish the documentation and release it. I know I keep saying I'll release it and then put it off, but I want it to be as useful as possible.
Here's just a few seconds of it, to give you an idea of how fast it runs, and below that, the C program.
I've uploaded it to YouTube (it might take a little time before it becomes available).
https://youtube.com/shorts/mbF7khhrmIQ?feature=share
Here is the C code I used:
// gol.c - Game of Life using shared memory #define _GNU_SOURCE #include
[Error: Irreparable invalid markup ('<stdio.h>') in entry. Owner must fix manually. Raw contents below.]
A little bit of a delay in releasing the canvas server. I wanted to include an example of using it for running John Conway's Game of Life. That meant adding a few more functions and getting shared memory access working properly. That all works properly, and the Game of Life works really well. On a 500x500 pixel canvas it runs about 30 generations per second. Not bad! (This is not awk. It's a short C program that uses the canvas server for display.)
There are a couple more things I need to make demos for, and then I'll finish the documentation and release it. I know I keep saying I'll release it and then put it off, but I want it to be as useful as possible.
Here's just a few seconds of it, to give you an idea of how fast it runs, and below that, the C program.
I've uploaded it to YouTube (it might take a little time before it becomes available).
https://youtube.com/shorts/mbF7khhrmIQ?feature=share
Here is the C code I used:
<pre>// gol.c - Game of Life using shared memory
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include "pixel_protocol.h"
int main(int argc, char **argv) {
int w = argc > 1 ? atoi(argv[1]) : 80;
int h = argc > 2 ? atoi(argv[2]) : 60;
int generations = argc > 3 ? atoi(argv[3]) : 100;
// Open shared memory
int fd = shm_open(PIXEL_SHM_NAME, O_RDWR, 0666);
if (fd < 0) {
perror("shm_open - is canvas_server running?");
return 1;
}
size_t size = sizeof(shm_canvas_t) + w * h * 4;
shm_canvas_t *shm = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (shm == MAP_FAILED) {
perror("mmap");
close(fd);
return 1;
}
// Verify dimensions match
if (shm->width != w || shm->height != h) {
fprintf(stderr, "Error: canvas size is %dx%d, expected %dx%d\n",
shm->width, shm->height, w, h);
munmap(shm, size);
close(fd);
return 1;
}
uint8_t *grid = malloc(w * h);
uint8_t *next = malloc(w * h);
if (!grid || !next) {
perror("malloc");
return 1;
}
// Random initialization
srand(time(NULL));
for (int i = 0; i < w * h; i++) {
grid[i] = rand() > RAND_MAX * 0.25;
((uint32_t*)shm->pixels)[i] = grid[i] ? 0xFFFFFFFF : 0xFF000000;
}
shm->seq++;
printf("Generation 0: random init\n");
// Evolve
for (int gen = 1; gen <= generations; gen++) {
// Compute next generation
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int neighbors = 0;
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
if (dx == 0 && dy == 0) continue;
int nx = (x + dx + w) % w;
int ny = (y + dy + h) % h;
neighbors += grid[ny * w + nx];
}
}
int alive = grid[y * w + x];
next[y * w + x] = (alive && neighbors >= 2 && neighbors <= 3) ||
(!alive && neighbors == 3);
}
}
// Update display
int changed = 0;
for (int i = 0; i < w * h; i++) {
if (grid[i] != next[i]) {
grid[i] = next[i];
((uint32_t*)shm->pixels)[i] = grid[i] ? 0xFFFFFFFF : 0xFF000000;
changed = 1;
}
}
if (changed) {
shm->seq++;
printf("Gen: %d \r", gen);
fflush(stdout);
} else {
printf("Generation %d: stable\n", gen);
break; // Stop if no changes
}
//usleep(50000); // 50ms per generation
}
munmap(shm, size);
close(fd);
free(grid);
free(next);
return 0;
}
</pre>
There are a couple more things I need to make demos for, and then I'll finish the documentation and release it. I know I keep saying I'll release it and then put it off, but I want it to be as useful as possible.
Here's just a few seconds of it, to give you an idea of how fast it runs, and below that, the C program.
I've uploaded it to YouTube (it might take a little time before it becomes available).
https://youtube.com/shorts/mbF7khhrmIQ?feature=share
Here is the C code I used:
<pre>// gol.c - Game of Life using shared memory
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include "pixel_protocol.h"
int main(int argc, char **argv) {
int w = argc > 1 ? atoi(argv[1]) : 80;
int h = argc > 2 ? atoi(argv[2]) : 60;
int generations = argc > 3 ? atoi(argv[3]) : 100;
// Open shared memory
int fd = shm_open(PIXEL_SHM_NAME, O_RDWR, 0666);
if (fd < 0) {
perror("shm_open - is canvas_server running?");
return 1;
}
size_t size = sizeof(shm_canvas_t) + w * h * 4;
shm_canvas_t *shm = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (shm == MAP_FAILED) {
perror("mmap");
close(fd);
return 1;
}
// Verify dimensions match
if (shm->width != w || shm->height != h) {
fprintf(stderr, "Error: canvas size is %dx%d, expected %dx%d\n",
shm->width, shm->height, w, h);
munmap(shm, size);
close(fd);
return 1;
}
uint8_t *grid = malloc(w * h);
uint8_t *next = malloc(w * h);
if (!grid || !next) {
perror("malloc");
return 1;
}
// Random initialization
srand(time(NULL));
for (int i = 0; i < w * h; i++) {
grid[i] = rand() > RAND_MAX * 0.25;
((uint32_t*)shm->pixels)[i] = grid[i] ? 0xFFFFFFFF : 0xFF000000;
}
shm->seq++;
printf("Generation 0: random init\n");
// Evolve
for (int gen = 1; gen <= generations; gen++) {
// Compute next generation
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int neighbors = 0;
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
if (dx == 0 && dy == 0) continue;
int nx = (x + dx + w) % w;
int ny = (y + dy + h) % h;
neighbors += grid[ny * w + nx];
}
}
int alive = grid[y * w + x];
next[y * w + x] = (alive && neighbors >= 2 && neighbors <= 3) ||
(!alive && neighbors == 3);
}
}
// Update display
int changed = 0;
for (int i = 0; i < w * h; i++) {
if (grid[i] != next[i]) {
grid[i] = next[i];
((uint32_t*)shm->pixels)[i] = grid[i] ? 0xFFFFFFFF : 0xFF000000;
changed = 1;
}
}
if (changed) {
shm->seq++;
printf("Gen: %d \r", gen);
fflush(stdout);
} else {
printf("Generation %d: stable\n", gen);
break; // Stop if no changes
}
//usleep(50000); // 50ms per generation
}
munmap(shm, size);
close(fd);
free(grid);
free(next);
return 0;
}
</pre>