private void SaveFile(FileContentWithHash fileContentWithHash)
        {
            // Extracting a task completion source to notify the producer that the operation is complete/fail
            bool tcsFound = m_saveCompletionTasks.TryRemove(fileContentWithHash, out var tcs);

            Contract.Assert(tcsFound, "Can't find a task completion source.");

            try
            {
                // We only add the file content if it is not already there (with same path and hash)
                m_fileCombiner.GetOrAddFile(fileContentWithHash.Content.Content, fileContentWithHash.Hash, fileContentWithHash.PathToFile, fileContentWithHash.Content.Length);
                tcs.TrySetResult(null);
            }
            catch (Exception e)
            {
                tcs.TrySetException(e);
            }
        }
        /// <summary>
        /// Stores a serialized AST for future retrieval
        /// </summary>
        public async Task SaveAstAsync(AbsolutePath path, ByteContent content)
        {
            var rootPath = path.ToString(m_pathTable);
            var hash     = await m_engine.GetFileContentHashAsync(rootPath);

            var pathToAst = Path.Combine(rootPath, AstFilenameFragment);

            var fileWithContent = new FileContentWithHash(content, hash, pathToAst);

            // Need to store a task completion source to be able to await for the save operation to finish
            var tcs = TaskSourceSlim.Create <object>();

            m_saveCompletionTasks[fileWithContent] = tcs;
            m_filesToSaveQueue.Post(fileWithContent);

            await tcs.Task;

            // Now we can remove the item from the dictionary.
            m_saveCompletionTasks.TryRemove(fileWithContent, out var _);
        }
        /// <summary>
        /// Stores a public facade content for future retrieval
        /// </summary>
        public async Task SavePublicFacadeAsync(AbsolutePath path, FileContent publicFacade)
        {
            Contract.Requires(publicFacade.IsValid);

            var rootPath = path.ToString(m_pathTable);
            var hash     = await m_engine.GetFileContentHashAsync(rootPath);

            var pathToPublicFacade = Path.Combine(rootPath, PublicFacadeFilenameFragment);
            var content            = Encoding.UTF8.GetBytes(publicFacade.Content);

            var fileWithContent = new FileContentWithHash(ByteContent.Create(content, content.Length), hash, pathToPublicFacade);

            // Need to store a task completion source to be able to await for the save operation to finish
            var tcs = TaskSourceSlim.Create <object>();

            m_saveCompletionTasks[fileWithContent] = tcs;
            m_filesToSaveQueue.Post(fileWithContent);

            await tcs.Task;
        }