view datagear/DataGears.cs @ 26:45ff08d59fda

update CGM
author riono <e165729@ie.u-ryukyu.ac.jp>
date Tue, 12 Jan 2021 21:23:23 +0900
parents 3aaa77e12493
children efb06874a34e
line wrap: on
line source

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Christie_net.annotation;
using Christie_net.datagear.command;
using Christie_net.datagear.dg;

namespace Christie_net.datagear {
public class DataGears {
    protected SortedDictionary<string, BlockingCollection<DataGear<object>>> dataGears =
        new SortedDictionary<string, BlockingCollection<DataGear<object>>>();

    private readonly object syncObject = new object();

    /// <summary>
    /// 新しいdataGearの追加
    /// </summary>
    /// <param name="key"></param>
    /// <param name="dg"></param>
    public void Put(string key, DataGear<object> dg) {
        lock (syncObject) {
            if (dataGears.ContainsKey(key)) {
                dataGears[key].TryAdd(dg);
            } else {
                var queue = new BlockingCollection<DataGear<object>>();
                queue.TryAdd(dg);
                dataGears.Add(key, queue);
            }
        }
    }

    /// <summary>
    /// DataGeraの取得と削除
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public object Take(string key) {
        lock (syncObject) {
            object data = null;
            // Queueからの取得は参照渡し
            DataGear<object> dataGear;
            if (dataGears[key].TryTake(out dataGear)) {
                data = dataGear.GetData();
            }

            // DataGeraを削除取り出ししたのでkeyも削除
            if (dataGears[key].IsCompleted) {
                dataGears[key].Dispose();
                dataGears.Remove(key);
            }
            return data;
        }
    }

    /// <summary>
    /// DataGeraを削除せずに取得
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public object Peek(string key) {
        lock (syncObject) {
            object data = null;
            DataGear<object> dataGear;
            // BlockingCollectionではpeekできないので、中のConcurrentQueueを取り出して操作
            ConcurrentQueue<DataGear<object>> queue = new ConcurrentQueue<DataGear<object>>(dataGears[key]);
            if (queue.TryPeek(out dataGear)) {
                data = dataGear.GetData();
            }
            return data;
        }
    }

    /// <summary>
    /// commandによりDataの取得
    /// </summary>
    /// <param name="cm"></param>
    /// <returns></returns>
    public object GetData(Command cm) {
        lock (syncObject) {
            CommandType type = cm.type;
            if (type == CommandType.TAKE || type == CommandType.REMOTETAKE) {
                return Take(cm.key);
            } else if (type == CommandType.PEEK || type == CommandType.REMOTEPEEK){
                return Peek(cm.key);
            }
            return null;
        }
    }

    /// <summary>
    /// Dataを挿入する
    /// </summary>
    /// <param name="cm"></param>
    public void SetData(Command cm) {
        lock (syncObject) {
            Put(cm.key, cm.dg);
        }
    }

    /// <summary>
    /// 既にkeyが含まれているか返す
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public bool ContainsKey(string key) {
        lock (syncObject) {
            return dataGears.ContainsKey(key);
        }
    }
}
}