/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
* 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.Concurrent;
using System.Threading;
namespace Tizen.Applications
{
///
/// Provides a synchronization context for the Tizen application model.
///
/// 3
public class TizenSynchronizationContext : SynchronizationContext
{
private readonly Interop.Glib.GSourceFunc _wrapperHandler;
private readonly Object _transactionLock = new Object();
private readonly ConcurrentDictionary _handlerMap = new ConcurrentDictionary();
private int _transactionId = 0;
///
/// Initializes a new instance of the TizenSynchronizationContext class.
///
/// 3
public TizenSynchronizationContext()
{
_wrapperHandler = new Interop.Glib.GSourceFunc(Handler);
}
///
/// Initilizes a new TizenSynchronizationContext and install into the current thread.
///
///
/// It is equivalent.
///
/// SetSynchronizationContext(new TizenSynchronizationContext());
///
///
/// 3
public static void Initialize()
{
SetSynchronizationContext(new TizenSynchronizationContext());
}
///
/// Dispatches an asynchronous message to a Tizen main loop.
///
/// The SendOrPostCallback delegate to call.
/// The object passed to the delegate.
///
/// The post method starts an asynchronous request to post a message.
/// 3
public override void Post(SendOrPostCallback d, object state)
{
Post(() =>
{
d(state);
});
}
///
/// Dispatches a synchronous message to a Tizen main loop.
///
/// The SendOrPostCallback delegate to call.
/// The object passed to the delegate.
///
/// The send method starts a synchronous request to send a message.
/// 3
public override void Send(SendOrPostCallback d, object state)
{
var mre = new ManualResetEvent(false);
Exception err = null;
Post(() =>
{
try
{
d(state);
}
catch (Exception ex)
{
err = ex;
}
finally
{
mre.Set();
}
});
mre.WaitOne();
if (err != null)
{
throw err;
}
}
private void Post(Action action)
{
int id = 0;
lock (_transactionLock)
{
id = _transactionId++;
}
_handlerMap.TryAdd(id, action);
Interop.Glib.IdleAdd(_wrapperHandler, (IntPtr)id);
}
private bool Handler(IntPtr userData)
{
int key = (int)userData;
if (_handlerMap.ContainsKey(key))
{
Action action;
_handlerMap.TryRemove(key, out action);
action?.Invoke();
}
return false;
}
}
}