Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# lock in generic function

I have such a class:

public static class CacheManager
{
    static object lockObject = new object();

    static MemcachedClient CacheObject
    {
        get
        {
            if (!MemcachedClient.Exists(Settings.Default
                .CacheInstanceName))
            {
                MemcachedClient.Setup(Settings.Default
                    .CacheInstanceName,
                        new string[] {Settings.Default
                            .CacheHostAddress});
            }
            //
            //
            return MemcachedClient.GetInstance(Settings
                .Default.CacheInstanceName);
        }
    }

    public static List<TData> Get<TData>(string key, Func<List<int>> getListCallback,
        Func<int, TData> getItemCallback) where TData : class
    {
        var result = new List<TData>();
        //
        //
        var list = CacheObject.Get(key);
        if (list == null)
        {
            lock (lockObject)
            {
                list = CacheObject.Get(key);
                if (list == null)
                {
                    list = getListCallback();
                    CacheObject.Set(key, list);
                    //
                    //
                    foreach (var id in (List<int>)list)
                    {
                        var item = getItemCallback(id);
                        result.Add(item);
                        CacheObject.Set(string.Concat(key, id), item);
                    }
                }
            }
        }
        else
        {
            foreach (var id in (List<int>)list)
            {
                var itemKey = string.Concat(key, id);
                //
                //
                var item = CacheObject.Get(itemKey);
                if (item == null)
                {
                    lock (lockObject)
                    {
                        item = CacheObject.Get(itemKey);
                        if (item == null)
                        {
                            item = getItemCallback(id);
                            CacheObject.Set(itemKey, item);
                        }
                    }
                }
                //
                //
                result.Add((TData)item);
            }
        }
        //
        //
        return (List<TData>)result;
    }

    public static void Remove(string key)
    {
        CacheObject.Delete(key);
    }
}

it is used in classes-repositories:

public class NewsRepository : BaseRepository, IRepository
{

    public List<News> FindAll()
    {
        return CacheManager.Get<News>(key,
            () => clientEntities.News.OrderByDescending(n => n.DateCreated).Select(n => n.NewsId).ToList(),
            (id) => clientEntities.News.Single(n => n.NewsId == id));
    }
}
public class PagesRepository : BaseRepository
{
    public List<Page> FindAll()
    {

        return CacheManager.Get<Page>(key,
            () => clientEntities.Pages.OrderBy(p => p.PageId).Select(p => p.PageId).ToList(),
            (id) => clientEntities.Pages.Single(p => p.PageId == id));
    }
}

my question is: for example NewsRepository didn't find news in cache and got the lock and began to load data but at this moment PagesRepository didn't find pages in cache. will PagesRepository's CacheManager be locked by NewsRepository or (I think so) NewsRepository's CacheManager is another static class and its internal locks do not touch PagesRepository's CacheManager?

like image 655
donRumatta Avatar asked Dec 07 '11 07:12

donRumatta


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


2 Answers

A static field of a non-generic type (that is itself not nested in a generic type etc) exists only once, so all the locks will conflict.

If (comments) your aim is to make the lock per-type (from the generic method), then perhaps the best way to do that is:

public static class CacheManager {
    static class TypeLock<T> {
        public static readonly object SyncLock = new object();
    }
    ...
    void SomeGenericMethod<TData>(args) {
       ...
       lock(TypeLock<TData>.SyncLock) {
          ...
       }
       ...
    }
}

Here, SyncLock exists once (and only once) per T, so per TData. This allows you to keep your existing API (where CacheManager is non-generic).

like image 68
Marc Gravell Avatar answered Sep 28 '22 11:09

Marc Gravell


Both will use the same reference to lockObject, and therefore the same lock.

like image 35
Kevin Gosse Avatar answered Sep 28 '22 09:09

Kevin Gosse