Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DictionaryStore.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Linq;
7 
8 namespace SiliconStudio.Core.IO
9 {
10  /// <summary>
11  /// A Key->Value store that will be incrementally saved on the HDD.
12  /// Thread-safe and process-safe.
13  /// </summary>
14  /// <typeparam name="TKey">The type of the key.</typeparam>
15  /// <typeparam name="TValue">The type of the value.</typeparam>
16  public class DictionaryStore<TKey, TValue> : Store<KeyValuePair<TKey, TValue>>
17  {
18  protected readonly Dictionary<TKey, TValue> loadedIdMap = new Dictionary<TKey, TValue>();
19  protected readonly Dictionary<TKey, UnsavedIdMapEntry> unsavedIdMap = new Dictionary<TKey, UnsavedIdMapEntry>();
20 
21  public DictionaryStore(Stream stream) : base(stream)
22  {
23  }
24 
25  /// <summary>
26  /// Gets the values stored including unsaved.
27  /// </summary>
28  /// <returns>Values stored including unsaved.</returns>
29  public KeyValuePair<TKey, TValue>[] GetValues()
30  {
31  lock (lockObject)
32  {
33  var result = new KeyValuePair<TKey, TValue>[loadedIdMap.Count + unsavedIdMap.Count];
34  int i = 0;
35  foreach (var value in loadedIdMap)
36  {
37  result[i++] = value;
38  }
39  foreach (var item in unsavedIdMap)
40  {
41  result[i++] = new KeyValuePair<TKey, TValue>(item.Key, item.Value.Value);
42  }
43 
44  return result;
45  }
46  }
47 
48  /// <summary>
49  /// Gets or sets the item with the specified key.
50  /// </summary>
51  /// <value>
52  /// The item to get or set.
53  /// </value>
54  /// <param name="key">The key of the item to get or set.</param>
55  /// <returns></returns>
56  /// <exception cref="System.Collections.Generic.KeyNotFoundException"></exception>
57  public bool Contains(TKey key)
58  {
59  TValue value;
60  return TryGetValue(key, out value);
61  }
62 
63  /// <summary>
64  /// Gets or sets the item with the specified key.
65  /// </summary>
66  /// <value>
67  /// The item to get or set.
68  /// </value>
69  /// <param name="key">The key of the item to get or set.</param>
70  /// <returns></returns>
71  /// <exception cref="System.Collections.Generic.KeyNotFoundException"></exception>
72  public TValue this[TKey key]
73  {
74  get
75  {
76  TValue value;
77  if (!TryGetValue(key, out value))
78  throw new KeyNotFoundException();
79  return value;
80  }
81  set
82  {
83  AddValue(new KeyValuePair<TKey, TValue>(key, value));
84  }
85  }
86 
87  /// <summary>
88  /// Tries to get the value from its key.
89  /// </summary>
90  /// <param name="key">The key.</param>
91  /// <param name="value">The value.</param>
92  /// <returns></returns>
93  public bool TryGetValue(TKey key, out TValue value)
94  {
95  lock (lockObject)
96  {
97  UnsavedIdMapEntry unsavedIdMapEntry;
98  if (unsavedIdMap.TryGetValue(key, out unsavedIdMapEntry))
99  {
100  value = unsavedIdMapEntry.Value;
101  return true;
102  }
103 
104  return loadedIdMap.TryGetValue(key, out value);
105  }
106  }
107 
108  public IEnumerable<KeyValuePair<TKey, TValue>> SearchValues(Func<KeyValuePair<TKey, TValue>, bool> predicate)
109  {
110  lock (lockObject)
111  {
112  var result = new Dictionary<TKey, TValue>(loadedIdMap.Count + unsavedIdMap.Count);
113 
114  foreach (var item in loadedIdMap)
115  {
116  if (predicate(new KeyValuePair<TKey, TValue>(item.Key, item.Value)))
117  {
118  result[item.Key] = item.Value;
119  }
120  }
121 
122  foreach (var item in unsavedIdMap)
123  {
124  if (predicate(new KeyValuePair<TKey, TValue>(item.Key, item.Value.Value)))
125  {
126  result[item.Key] = item.Value.Value;
127  }
128  }
129 
130  return result;
131  }
132  }
133 
134  protected override void AddUnsaved(KeyValuePair<TKey, TValue> item, int currentTransaction)
135  {
136  var unsavedIdMapEntry = new UnsavedIdMapEntry { Value = item.Value, Transaction = currentTransaction };
137  unsavedIdMap[item.Key] = unsavedIdMapEntry;
138  }
139 
140  protected override void RemoveUnsaved(KeyValuePair<TKey, TValue> item, int currentTransaction)
141  {
142  UnsavedIdMapEntry entry;
143  if (unsavedIdMap.TryGetValue(item.Key, out entry))
144  {
145  if (entry.Transaction == currentTransaction)
146  {
147  unsavedIdMap.Remove(item.Key);
148  }
149  }
150  }
151 
152  protected override void AddLoaded(KeyValuePair<TKey, TValue> item)
153  {
154  loadedIdMap[item.Key] = item.Value;
155  }
156 
157  protected override IEnumerable<KeyValuePair<TKey, TValue>> GetPendingItems(int currentTransaction)
158  {
159  var transactionIds = new List<KeyValuePair<TKey, TValue>>();
160 
161  foreach (var unsavedIdMapEntry in unsavedIdMap.Where(x => x.Value.Transaction == currentTransaction))
162  {
163  transactionIds.Add(new KeyValuePair<TKey, TValue>(unsavedIdMapEntry.Key, unsavedIdMapEntry.Value.Value));
164  }
165 
166  return transactionIds.ToArray();
167  }
168 
169  protected override void ResetInternal()
170  {
171  loadedIdMap.Clear();
172  unsavedIdMap.Clear();
173  }
174 
175  protected struct UnsavedIdMapEntry
176  {
177  public int Transaction;
178  public TValue Value;
179  }
180  }
181 }
KeyValuePair< TKey, TValue >[] GetValues()
Gets the values stored including unsaved.
override IEnumerable< KeyValuePair< TKey, TValue > > GetPendingItems(int currentTransaction)
Gets the list of pending items for a given transaction index.
bool TryGetValue(TKey key, out TValue value)
Tries to get the value from its key.
override void AddLoaded(KeyValuePair< TKey, TValue > item)
TValue Value
bool Contains(TKey key)
Gets or sets the item with the specified key.
IEnumerable< KeyValuePair< TKey, TValue > > SearchValues(Func< KeyValuePair< TKey, TValue >, bool > predicate)
override void RemoveUnsaved(KeyValuePair< TKey, TValue > item, int currentTransaction)
override void AddUnsaved(KeyValuePair< TKey, TValue > item, int currentTransaction)
int Transaction
override void ResetInternal()
Resets the store to an empty state, to be implemented by subclasses if necessary. ...