flyweightbyid ~main
Flyweight template based on explicitly named ids compatible with betterC
To use this package, run the following command in your project's root directory:
						Manual usage
						
						Put the following dependency into your project's dependences section:
					
flyweightbyid
A -betterC compatible Flyweight template based on explicitly named ids for D.
It is available as a DUB package and may be used directly as a Meson subproject or wrap.
Maintains two thread local or global arrays, one for identified objects, so that only one instance for each ID is loaded at a time, and another for reference counts or boolean loaded flags. Uses automatic reference counting via copy constructor/postblit and destructor by default, but has an option for manually unloading.
Loading and unloading of instances is fully customizable by passing the right callables to template.
As a special case, one may supply a single id to Flyweight and achieve a Singleton pattern.
Usage examples
import flyweightbyid;
// Flyweight for instances of `Image*`, loaded by `loadImage` and unloaded by `unloadImage`
// IDs and getter names are taken from `imageFileNames` slice
alias ImageFlyweight = Flyweight!(
    Image*,
    loadImage,
    unloadImage,
    imageFileNames,
    /+, FlyweightOptions.none /+ (the default) +/ +/
);
// Some file names that should be loaded only once
enum imageFileNames = [
    "img1.png",
    "subdir/img2.png",
];
// Image struct, with a pointer to the data, dimensions, member functions, etc...
struct Image {
    void draw() const
    {
        // ...
    }
    // ...
    ~this()
    {
        import std.stdio : writeln;
        writeln("bye bye");
    }
}
// Function that loads an Image from file
Image* loadImage(uint id)
{
    auto filename = imageFileNames[id];
    Image* img = new Image;
    // ...
    return img;
}
// Function to unload the images
void unloadImage(ref Image* img)
{
    // ...
    destroy(img);
}
void example()
{
    // Flyweight identified by `ID.img1_png` is constructed by calling `loadImage(0)`
    // Notice how invalid identifier characters are replaced by underscores
    ImageFlyweight image1 = ImageFlyweight.get(ImageFlyweight.ID.img1_png);
    assert(ImageFlyweight.isLoaded(ImageFlyweight.ID.img1_png));
    // `img1_png` is an alias for getting the "img1.png" instance,
    // `subdir_img2_png` for "subdir/img2.png" and so on
    auto also_image1 = ImageFlyweight.img1_png;
    // `also_image1` contains the same instance as `image1`, as it is already loaded
    assert(also_image1 is image1);
    {
        // `ID.subdir_img2_png` is constructed by `loadImage(1)`
        ImageFlyweight image2 = ImageFlyweight.subdir_img2_png;
        // ImageFlyweight instance is a proxy (by means of `alias this`)
        // for the loaded `Image*` instance, so member functions, fields and
        // others work like expected
        image2.draw();
        // If `FlyweightOptions.noReferenceCount` is NOT passed to template (default),
        // references are automatically counted and content is unloaded if reference
        // count reaches 0. Pass them by value for automatic reference counting
        ImageFlyweight also_image2 = image2;
        assert(ImageFlyweight.isLoaded(ImageFlyweight.ID.subdir_img2_png));
        // subdir_img2_png gets unloaded
    }
    assert(!ImageFlyweight.isLoaded(ImageFlyweight.ID.subdir_img2_png));
    // It is possible to manually unload one or all instances, be careful to not access them afterwards!
    ImageFlyweight.unload(ImageFlyweight.ID.img1_png);
    ImageFlyweight.unloadAll();
    // It is safe to call unload more than once, so when `image1` and `also_image1`
    // are destroyed, nothing happens
    assert(!ImageFlyweight.isLoaded(ImageFlyweight.ID.img1_png));
    assert(!ImageFlyweight.isLoaded(ImageFlyweight.ID.subdir_img2_png));
}
import flyweightbyid;
// Config singleton, using global storage and not reference counted
alias ConfigSingleton = Flyweight!(
    Config*,
    loadConfig,
    unloadConfig,
    "instance",
    FlyweightOptions.gshared | FlyweightOptions.noReferenceCount
);
// Configuration structure
struct Config
{
    // ...
}
Config* loadConfig(uint)
{
    return new Config;
}
void unloadConfig(ref Config* c)
{
    destroy(c);
}
void example2()
{
    assert(!ConfigSingleton.isLoaded(ConfigSingleton.ID.instance));
    {
        // Get Config instance
        auto config = ConfigSingleton.instance;
        auto also_config = ConfigSingleton.get(ConfigSingleton.ID.instance);
        assert(also_config is config);
        assert(ConfigSingleton.isLoaded(ConfigSingleton.ID.instance));
    }
    // ConfigSingleton is not reference counted, so it is still loaded
    assert(ConfigSingleton.isLoaded(ConfigSingleton.ID.instance));
    ConfigSingleton.unloadAll();
    assert(!ConfigSingleton.isLoaded(ConfigSingleton.ID.instance));
}
- ~main released 4 years ago
 - gilzoide/flyweightbyid
 - public license
 
- Authors:
 - Dependencies:
 - none
 - Versions:
 - 
						
Show all 4 versions0.2.1 2021-Jan-25 0.2.0 2021-Jan-23 0.1.0 2020-Dec-24 ~main 2021-Jan-25  - Download Stats:
 - 
						
- 
								
0 downloads today
 - 
								
0 downloads this week
 - 
								
0 downloads this month
 - 
								
0 downloads total
 
 - 
								
 - Score:
 - 0.4
 - Short URL:
 - flyweightbyid.dub.pm