Multithreading add-on

Description

BGDatabase itself is not thread-safe, it's meant to be called from main thread only (from MonoBehaviour scripts). Multi-threading addon creates environment, which can be accessed from multiple threads safely.

Alternative methods

Option # 1 : Using database in read-only mode

You can access database in read-only mode using this plugin

Option # 2 : Use database data to spawn thread safe objects

Another alternative method to use BGDatabase data in multithreaded environment (for example, with Unity ECS). Use data from BGDatabase and create Unity ECS entities. Merge changes back to database on save if needed.

  1. Make sure you call database only from main thread (e.g. from MonoBehaviour classes)
  2. Create Unity ECS entities out of database data
  3. If you need some of these Unity ECS entities to be persistent, (e.g. they need to be saved/loaded), store them back to database the moment they need to be persisted, e.g, when the game needs to be saved. Run saving/loading on main thread.
  4. If you need to call database from multithreaded environment, use BGMainThreadRunner.RunOnMainThread(Action action). This will add action to the jobs list to be run on main thread. Make sure you call at sparingly, at some relatively rare condition, otherwise it can become a bottleneck.

What can I do with multi-threading addon?

  1. You can choose which tables you want to be accessible for multi-threading operations.
  2. You can merge changes back to main database either manually or auto (on saving). Otherwise, changes are not synchronized. Merging changes back is pretty expensive operation.
  3. MT addon has its own code generator and API very similar to single-threaded API.
  4. Not all BGDatabase fields are available for multithreaded access. Read more about which fields are available below in What I need to know before using MT Addon? section. You can also see which fields are not supported in merge settings under "Merge" tab
  5. There are 2 types of transactions: lightweight, lock-free readonly transactions and very heavy write transactions. If you need to update data very often, consider using Alternative method instead (described above).

How multi-threading addon works?

What I need to know before using MT Addon?

  1. Fast read / slow(expensive) update. If you need to update often, this solution is not good
  2. Lists fields, hashtable, Unity assets fields and fields, which reference objects (not structs) are not supported.
  3. All entities are structs, not classes. If result can be null, BGMTEntity? is used
  4. Entities are only marked as deleted inside transaction, the actual removal takes place at the end of transaction
  5. Write transactions can be executed asynchronously, so do not expect changes take effect right after the method call. If you need some code to be run after transaction finish, use (Action callback) as second parameter to BGRepo.M.Write method

Usage examples

We tried our best to make multithreaded API very similar to single-threaded one. Also, we provide code generation for MT addon. Start working with multithreading environment by creating read-only or write transactions.


        //start read-only transaction (option 1)
        BGMTRepo mtRepo = BGRepo.M.RepoReadOnly;

	    //start read-only transaction (option 2)
	    BGRepo.M.Read(mtRepo =>
        {
            //access data from mtRepo here
        });

	    //start write transaction (the only option)
	    BGRepo.M.Write(mtRepo =>
        {
            // you can read and change data here.
			// This transaction can be run asynchronously (on separate thread),
			// so do not expect changes take effect right after the method call
        });

BGMTRepo has very similar methods to ones single-threaded API has. For example, to iterate through "Items" table rows, which have "damage" column value more than 10:


        BGRepo.M.Read(mtRepo =>
        {
            mtRepo["Items"].ForEachEntity(entity =>
            {
                print("Weapon: " + entity.Name);
            }, entity => entity.Get<int>("damage") > 10);
        });

And just like with single-threaded API, Code generation greatly simplify access to database by removing all boilerplate code


		BGRepo.M.Read(mtRepo =>
		{
			Items.ForEachEntity(mtRepo, item =>
			{
				print("Weapon: " + item.name);
			}, item => item.damage > 10);
		});

Parameters

Parameter name Description
Multithreaded updates By default, all update transaction are run on single thread one-by-one. Toggle this parameter on if you want to enable multithreaded updates. Note, multithreaded updates make 'lost updates' possible. Learn more about Lost updates here
Meta list List of tables to include in multithreaded environment
Merge on save Should the changes from multithreaded environment be auto-merged back to main database before saving the game with SaveLoad add-on
Merge Settings Merge settings to use for merging changes back to main database. The same merge settings you use for Export/Import or Saving/Loading. Learn more about merge settings here