patterncMinor
Robust scene manager
Viewed 0 times
managerscenerobust
Problem
I made a simple scene manager in C99. I tried to make it readable, reusable and reliable. I would be grateful if you would help me to improve it. I want to use it for my upcoming OpenGL game. I think that code is sufficiently self-documenting for you to skip the comments.
The headers
scene_manager.h
scene.h
```
// Defines interface used by scene manager (SM) to communicate with its scenes
#ifndef SCENE_H
#define SCENE_H
#include
#define POP_REQUEST (-1)
// Sends a critical error signal which results in immediate SM termination and
// stderr output if error is not equal to 0 OR description is not equal to NULL
void send_critical_error_signal(int error, const char *description);
// Invalid pointers cause undefined behavior - most likely a segmentation fault
typedef struct Scene
{
// It initializes the scene
// On success, returns a pointer to its private data
// If the scene has no private data, it can return a dummy string literal
// On failure, returns a NULL pointer
// If the INITIAL scene fails to initialize, so does the scene manager
// If a NON-INITIAL scene fails to initialize, the scene manager attempts
// t
The headers
scene_manager.h
// Defines client interface of Scene Manager
#ifndef SCENE_MANAGER_H
#define SCENE_MANAGER_H
#include "scene.h"
// Initialization and termination functions will not fail or yield undefined
// behaviour if called multiple times or in the wrong order. Other functions
// are safe to be called at all times, too. Scenes are the weakest component
// Initializes scene manager. Warning: scenes are not deep copied!
bool initialize_scene_manager(int n_scenes, Scene *scenes, int initial_id);
// Executes the top scene on the scene stack
bool execute_top_scene(void);
// Terminates the scene manager.
void terminate_scene_manager(void);
// Returns whether the scene stack is empty
bool scene_stack_is_empty(void);
// Returns whether the scene stack is not empty
bool scene_stack_is_not_empty(void);
#endif // SCENE_MANAGER_Hscene.h
```
// Defines interface used by scene manager (SM) to communicate with its scenes
#ifndef SCENE_H
#define SCENE_H
#include
#define POP_REQUEST (-1)
// Sends a critical error signal which results in immediate SM termination and
// stderr output if error is not equal to 0 OR description is not equal to NULL
void send_critical_error_signal(int error, const char *description);
// Invalid pointers cause undefined behavior - most likely a segmentation fault
typedef struct Scene
{
// It initializes the scene
// On success, returns a pointer to its private data
// If the scene has no private data, it can return a dummy string literal
// On failure, returns a NULL pointer
// If the INITIAL scene fails to initialize, so does the scene manager
// If a NON-INITIAL scene fails to initialize, the scene manager attempts
// t
Solution
Small review
Pedantic:
[Edit] Sample merge
Since the calling code essentially needs to keep track of the present size, pass then both in by address and let the pointer and size variables get updated together in this function.
When calling code is shrinking, no strong need to check the return value.
safe_dealloc() and safer_realloc() could be rolled into one. safer_realloc(0) would benefit clear size==0 functionality.Pedantic:
size_t new_size = old_size + sizeof(*sm_stack.stack); lacks overflow protection.[Edit] Sample merge
Since the calling code essentially needs to keep track of the present size, pass then both in by address and let the pointer and size variables get updated together in this function.
bool safer_realloc(void **p, size_t *current_size, size_t new_size) {
assert(p != NULL);
assert(Current_size != NULL);
if (new_size == 0) {
free(*p);
*p = NULL;
*current_size = 0;
return true; // OK;
}
void *tmp = realloc(*p, new_size);
if (tmp == NULL) {
// no change to *p or *current_size
return false; // !OK
}
*p = tmp;
*current_size = new_size;
return true; // OK;
}When calling code is shrinking, no strong need to check the return value.
Code Snippets
bool safer_realloc(void **p, size_t *current_size, size_t new_size) {
assert(p != NULL);
assert(Current_size != NULL);
if (new_size == 0) {
free(*p);
*p = NULL;
*current_size = 0;
return true; // OK;
}
void *tmp = realloc(*p, new_size);
if (tmp == NULL) {
// no change to *p or *current_size
return false; // !OK
}
*p = tmp;
*current_size = new_size;
return true; // OK;
}Context
StackExchange Code Review Q#118565, answer score: 2
Revisions (0)
No revisions yet.