Just a second...

Session locks

Session locks are a way to ensure that only one session at a time can access a particular resource. For example, you can use a session lock to ensure that only one session is allowed to update a certain topic.

Session locks are a mechanism managed by the Diffusion™ server to coordinate access to shared resources among multiple sessions.

A session can acquire a lock, identified by a lock name (chosen by you to suit your application). Once a session acquires a lock, no other session can acquire the same lock.

Acquiring a lock does not automatically change anything else about a session. Locks are not linked to topics or permissions, except through your application's logic. It is up to you to design a suitable locking scheme and ensure your application implements it. For example, if you want to implement exclusive updating of a topic using a session lock, you must make sure that each session always acquires the lock and uses a lock constraint created from the lock when updating the topic.

By default, a lock is released when the session owning it closes. Alternatively, when acquiring a lock, a session can specify that the lock will be released if connection to the server is lost. This is done using a scope parameter.

A session can also explicitly release a lock.

.NET
/**
 * Copyright © 2021 Push Technology Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using PushTechnology.ClientInterface.Client.Callbacks;
using PushTechnology.ClientInterface.Client.Factories;
using PushTechnology.ClientInterface.Client.Features;
using PushTechnology.ClientInterface.Client.Features.Topics;
using PushTechnology.ClientInterface.Client.Session;
using PushTechnology.ClientInterface.Client.Topics;
using PushTechnology.ClientInterface.Client.Topics.Details;
using static System.Console;

namespace PushTechnology.ClientInterface.Example
{
    /// <summary>
    /// Client implementation that demonstrates session locks.
    /// </summary>
    public sealed class SessionLocks
    {
        private ISession session1, session2;
        private ISessionLock sessionLock1, sessionLock2;

        private static string LOCK_NAME = "lockA";

        public SessionLocks(string serverUrl)
        {
            session1 = Diffusion.Sessions.Principal("control").Password("password")
                .CertificateValidation((cert, chain, errors) => CertificateValidationResult.ACCEPT)
                .Open(serverUrl);

            session2 = Diffusion.Sessions.Principal("control").Password("password")
                .CertificateValidation((cert, chain, errors) => CertificateValidationResult.ACCEPT)
                .Open(serverUrl);

            WriteLine("Sessions 1 and 2 have been created.");

            AcquireLockSession1();
        }

        private async void AcquireLockSession1()
        {
            try
            {
                WriteLine("Requesting lock 1...");

                sessionLock1 = await session1.LockAsync(LOCK_NAME, SessionLockScope.UNLOCK_ON_CONNECTION_LOSS);

                WriteLine("Lock 1 has been acquired.");

                AcquireLockSession2();

                Thread.Sleep(1000);

                ReleaseLock1();
            }
            catch (Exception ex)
            {
                WriteLine($"Failed to get lock 1 : {ex}.");
                session1.Close();
                session2.Close();
            }
        }

        private async void AcquireLockSession2()
        {
            try
            {
                WriteLine("Requesting lock 2...");

                sessionLock2 = await session2.LockAsync(LOCK_NAME, SessionLockScope.UNLOCK_ON_CONNECTION_LOSS);

                WriteLine("Lock 2 has been acquired.");

                Thread.Sleep(1000);

                ReleaseLock2();
            }
            catch (Exception ex)
            {
                WriteLine($"Failed to get lock 2 : {ex}.");
                session1.Close();
                session2.Close();
            }
        }

        private async void ReleaseLock1()
        {
            try
            {
                WriteLine("Requesting lock 1 release...");

                await sessionLock1.UnlockAsync();

                WriteLine("Lock 1 has been released.");
            }
            catch (Exception ex)
            {
                WriteLine($"Failed to release lock 1 : {ex}.");
                session1.Close();
                session2.Close();
            }
        }

        private async void ReleaseLock2()
        {
            try
            {
                WriteLine("Requesting lock 2 release...");

                await sessionLock2.UnlockAsync();

                WriteLine("Lock 2 has been released.");
            }
            catch (Exception ex)
            {
                WriteLine($"Failed to release lock 2 : {ex}.");
            }
            finally
            {
                session1.Close();
                session2.Close();
            }
        }
    }
}

Acquiring a lock

Required permissions: acquire_lock

Session locks are established on demand. There is no separate operation to create or destroy a named lock.

If a session attempts to acquire a lock that is not assigned, the server assigns it immediately to the session.

If a session attempts to acquire a lock that is already assigned, the server will record that the session is waiting to acquire it. When a lock is released and multiple sessions are waiting to acquire it, the server will arbitrarily assign it to one of the waiting sessions.

A session can request a lock with these parameters:
Lock name
A name for the lock.
Lock scope (optional)

The scope of the lock.

By default, the scope is UNLOCK_ON_SESSION_LOSS, meaning that the lock will be released when the session is closed.

If the scope is set to UNLOCK_ON_CONNECTION_LOSS, the lock will be released when the session loses its current connection to the server.