/* * 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; } } }