Çözüldü singleton.h

  • Konuyu açan Konuyu açan TheAdmin33
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 8
  • Gösterim Gösterim 231
Bu konu çözüme ulaştırılmıştır. Çözüm için konuya yazılan tüm yorumları okumayı unutmayın. Eğer konudaki yorumlar sorununuzu çözmediyse yeni bir konu açabilirsiniz.
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.

TheAdmin33

Ah, bu şarkıların gözü kör olsun
Geliştirici
Yardımsever Üye
Usta Üye
Editör
Mesaj
1.328
Çözümler
75
Beğeni
5.059
Puan
2.859
Ticaret Puanı
0
singleton.h dosyası tam olarak ne işe yarıyor ve en azından basit düzeyde de olsa geliştirilme yapılmalımı?


singleton.h:
Genişlet Daralt Kopyala
#ifndef __INC_SINGLETON_H__
#define __INC_SINGLETON_H__

#include <cassert>
#include <memory>

template <typename T>
class singleton
{
    public:
        static std::unique_ptr<T> ms_singleton;

        singleton()
        {
            assert(!ms_singleton);
            ms_singleton.reset(static_cast<T*>(this));
        }

        virtual ~singleton()
        {
            assert(ms_singleton);
            ms_singleton.reset();
        }

        static T& instance()
        {
            assert(ms_singleton);
            return *ms_singleton;
        }

        static T& Instance()
        {
            return instance();
        }

        static T* instance_ptr()
        {
            return ms_singleton.get();
        }
};

template <typename T> std::unique_ptr<T> singleton<T>::ms_singleton = nullptr;

#endif
 
Çözüm
Bir sistemin bel kemiğidir. Bir sınıftan bir tane oluşturulup, pek çok yerden ortak kullanımı sağlar.
Mesela aşağıda şöyle göstereyim;
C++:
Genişlet Daralt Kopyala
class TestClass
{
    public:
        int x = 0;
};
Kullanım örneği:
C++:
Genişlet Daralt Kopyala
TestClass a;     // sınıf nesnesi oluştur
a.x = 5;        // içindeki x'i 5 yap.

TestClass b;    // sınıf nesnesi oluştur (Tekrar! Yani x2 olmuş oldu. Bu +CPU kullanımı demektir.)
b.x = 10;        // içindeki x'i 5 yap.

Singleton için örnek:
C++:
Genişlet Daralt Kopyala
class TestClass : public CSingleton<TestClass>
{
    public:
        int x = 0;
};

Kullanım örneği:
C++:
Genişlet Daralt Kopyala
// Aşağıdaki her bir satırı farklı farklı yerlerde kullandığını düşün.
TestClass::Instance().x = 5;
TestClass::Instance().x = 6;
TestClass::Instance().x = 7...
Bir sistemin bel kemiğidir. Bir sınıftan bir tane oluşturulup, pek çok yerden ortak kullanımı sağlar.
Mesela aşağıda şöyle göstereyim;
C++:
Genişlet Daralt Kopyala
class TestClass
{
    public:
        int x = 0;
};
Kullanım örneği:
C++:
Genişlet Daralt Kopyala
TestClass a;     // sınıf nesnesi oluştur
a.x = 5;        // içindeki x'i 5 yap.

TestClass b;    // sınıf nesnesi oluştur (Tekrar! Yani x2 olmuş oldu. Bu +CPU kullanımı demektir.)
b.x = 10;        // içindeki x'i 5 yap.

Singleton için örnek:
C++:
Genişlet Daralt Kopyala
class TestClass : public CSingleton<TestClass>
{
    public:
        int x = 0;
};

Kullanım örneği:
C++:
Genişlet Daralt Kopyala
// Aşağıdaki her bir satırı farklı farklı yerlerde kullandığını düşün.
TestClass::Instance().x = 5;
TestClass::Instance().x = 6;
TestClass::Instance().x = 7;
TestClass::Instance().x = 8;
TestClass::Instance().x = 9;
TestClass::Instance().x = 10;

// Ancak hepsi tek nesne üzerinden işlem yapar.
// Önceki örnekteki gibi her erişim için farklı bellek tahsisi gerçekleşmez.

Örneğin PythonApplication.h içindeki sınıfı singleton'a dönüştürürsen mesela ortalık 56ya gidecektir büyük ihtimalle. Bu biraz da kullanım amacına ve senaryoya göre değişen bir faktör. Bu örnekte de; PythonApplication.h ve .cpp, her exe için ayrı ayrı oluşturulması gereken sınıflar olduğu için singleton değildir mesela.

Ek olarak; mesela oyundaki oyun ayarları / sistem ayarları kısmını ele alalım.
Bu ayarların barındırıldığı CPythonSystem sınıfı singleton türündedir. Aksi halde sen her bir ayarı değiştirdiğinde arkaplanda tekrar tekrar bellek tahsis edilecektir. Çünkü her bir ayara tıklamanda CPythonSystem sınıfını yeni bir nesne olarak oluşturacak.. Umarım anlatabilmişimdir.


İyileştirme konusuna gelince de bu çok geniş kapsamlı bir konu ama böyle şablon tasarımlarında yapılacak tek tük şeyler vardır elbet. Verdiğin örnekteki gibi unique_ptr kullanmak gibi iyileştirmeler uygulanabilir. Bence buradaki iyileştirmeden daha çok, singleton olan veya olmayan sınıflar ile üretilen nesnelerin yönetimi çok önemli. Bunların takibini iyi yapmak gerek asıl.
 
Çözüm
teşekkürler anladım. geliştirme konusunda da yapay zekaya danıştım bir çok yapay zeka denedim nerdeyse hepsi benzer kodu verip bunu kullan dedi kafamda biraz karıştı.

singleton.h:
Genişlet Daralt Kopyala
#ifndef __INC_SINGLETON_H__
#define __INC_SINGLETON_H__

#include <memory>
#include <mutex>
#include <cassert>

template <typename T>
class singleton
{
    protected:
        singleton() = default;
        virtual ~singleton() = default;

    public:
        singleton(const singleton&) = delete;
        singleton& operator=(const singleton&) = delete;
        singleton(singleton&&) = delete;
        singleton& operator=(singleton&&) = delete;

        static T& instance()
        {
            std::call_once(initFlag, []()
            {
                ms_singleton.reset(new T());
            });
            assert(ms_singleton);
            return *ms_singleton;
        }

        static T* instance_ptr()
        {
            std::call_once(initFlag, []()
            {
                ms_singleton.reset(new T());
            });
            return ms_singleton.get();
        }

private:
    static std::unique_ptr<T> ms_singleton;
    static std::once_flag initFlag;
};

template <typename T> std::unique_ptr<T> singleton<T>::ms_singleton = nullptr;

template <typename T> std::once_flag singleton<T>::initFlag;

#endif

Benchmark:
Genişlet Daralt Kopyala
#include <iostream>
#include <chrono>
#include <thread>
#include <vector>
#include "singleton.h" // Buraya kendi singleton dosyanı ekle

class MyClass : public singleton<MyClass> {
    friend class singleton<MyClass>; // Erişim izni
private:
    MyClass() {
        std::cout << "MyClass constructor\n";
    }
public:
    void do_something() const {
        // Küçük işlem
        volatile int x = 0;
        for (int i = 0; i < 100; ++i) x += i;
    }
};

void benchmark_singleton(int iterations) {
    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < iterations; ++i) {
        MyClass::instance().do_something();
    }

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration<double, std::micro>(end - start);

    std::cout << "[Thread " << std::this_thread::get_id() << "] "
              << "Total time: " << duration.count() << " µs\n";
}

int main() {
    const int iterations_per_thread = 1000000;
    const int thread_count = 4;

    std::cout << "Benchmark starting...\n";

    // Çoklu thread test
    std::vector<std::thread> threads;
    for (int i = 0; i < thread_count; ++i) {
        threads.emplace_back(benchmark_singleton, iterations_per_thread);
    }

    for (auto& t : threads) {
        t.join();
    }

    std::cout << "Benchmark complete.\n";
    return 0;
}
 
teşekkürler anladım. geliştirme konusunda da yapay zekaya danıştım bir çok yapay zeka denedim nerdeyse hepsi benzer kodu verip bunu kullan dedi kafamda biraz karıştı.

singleton.h:
Genişlet Daralt Kopyala
#ifndef __INC_SINGLETON_H__
#define __INC_SINGLETON_H__

#include <memory>
#include <mutex>
#include <cassert>

template <typename T>
class singleton
{
    protected:
        singleton() = default;
        virtual ~singleton() = default;

    public:
        singleton(const singleton&) = delete;
        singleton& operator=(const singleton&) = delete;
        singleton(singleton&&) = delete;
        singleton& operator=(singleton&&) = delete;

        static T& instance()
        {
            std::call_once(initFlag, []()
            {
                ms_singleton.reset(new T());
            });
            assert(ms_singleton);
            return *ms_singleton;
        }

        static T* instance_ptr()
        {
            std::call_once(initFlag, []()
            {
                ms_singleton.reset(new T());
            });
            return ms_singleton.get();
        }

private:
    static std::unique_ptr<T> ms_singleton;
    static std::once_flag initFlag;
};

template <typename T> std::unique_ptr<T> singleton<T>::ms_singleton = nullptr;

template <typename T> std::once_flag singleton<T>::initFlag;

#endif

Benchmark:
Genişlet Daralt Kopyala
#include <iostream>
#include <chrono>
#include <thread>
#include <vector>
#include "singleton.h" // Buraya kendi singleton dosyanı ekle

class MyClass : public singleton<MyClass> {
    friend class singleton<MyClass>; // Erişim izni
private:
    MyClass() {
        std::cout << "MyClass constructor\n";
    }
public:
    void do_something() const {
        // Küçük işlem
        volatile int x = 0;
        for (int i = 0; i < 100; ++i) x += i;
    }
};

void benchmark_singleton(int iterations) {
    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < iterations; ++i) {
        MyClass::instance().do_something();
    }

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration<double, std::micro>(end - start);

    std::cout << "[Thread " << std::this_thread::get_id() << "] "
              << "Total time: " << duration.count() << " µs\n";
}

int main() {
    const int iterations_per_thread = 1000000;
    const int thread_count = 4;

    std::cout << "Benchmark starting...\n";

    // Çoklu thread test
    std::vector<std::thread> threads;
    for (int i = 0; i < thread_count; ++i) {
        threads.emplace_back(benchmark_singleton, iterations_per_thread);
    }

    for (auto& t : threads) {
        t.join();
    }

    std::cout << "Benchmark complete.\n";
    return 0;
}
Yapay zekalar C++ standartlarına göre tavsiyeler verip iyileştirmeler uyguluyor. Ancak senin projenin işleyişini, nerede neyi nasıl kullandığını bilmiyor. Dolayısıyla doğrudan copy paste yapmakla böyle önemli alanlarda değişiklik yapılmaması gerek. Kısa vadede olmasa bile uzun vadede ciddi sorunlara neden olabilir. Kısacası bu gibi alanlarda değişiklik yaparken tüm projeyi elden geçirmek ve kontrol etmek, nihayetinde de sağlam testler yapmak gerekir. Çünkü sınıflar sadece .h dosyalarındaki tanımlardan ibaret değil. Bir sınıf singleton olsun ya da olmasın pek çok yerde farklı farklı senaryolarda kullanılabiliyor.

Metin2 yapısal olarak zaten çoğunlukla eski c++ standartlarını kullanıyor(c++11 ve öncesi).
Ve bunun gibi tek tük yerlerde C++11 sonrası sürümlerin standartlarını uygulayınca bu sefer diğer yerlerdeki eski sürüm yapılar bozuluyor veya patlıyor. Biraz fazla dikkat gerektiren bir durum.
 
Yapay zekalar C++ standartlarına göre tavsiyeler verip iyileştirmeler uyguluyor. Ancak senin projenin işleyişini, nerede neyi nasıl kullandığını bilmiyor. Dolayısıyla doğrudan copy paste yapmakla böyle önemli alanlarda değişiklik yapılmaması gerek. Kısa vadede olmasa bile uzun vadede ciddi sorunlara neden olabilir. Kısacası bu gibi alanlarda değişiklik yaparken tüm projeyi elden geçirmek ve kontrol etmek, nihayetinde de sağlam testler yapmak gerekir. Çünkü sınıflar sadece .h dosyalarındaki tanımlardan ibaret değil. Bir sınıf singleton olsun ya da olmasın pek çok yerde farklı farklı senaryolarda kullanılabiliyor.

Metin2 yapısal olarak zaten çoğunlukla eski c++ standartlarını kullanıyor(c++11 ve öncesi).
Ve bunun gibi tek tük yerlerde C++11 sonrası sürümlerin standartlarını uygulayınca bu sefer diğer yerlerdeki eski sürüm yapılar bozuluyor veya patlıyor. Biraz fazla dikkat gerektiren bir durum.
Özelliklede yapay zekaların yazdığı şeyler sizin verdiğiniz promptun ne kadar detaylı olduğuyla alakalı. Mesela siz "char.h dosyasında 124. satırda hata alıyorum" dediğinizde yapay zeka sadece o hatayı çözmek için kodu değiştirir ancak sizin genel yapınızı bilmediğinden yazdıklarının %60'ı tamamen halüsilasyon olarak yazar. Genel hitap etmez sadece o dosya içerisinde bir şeyler değiştirir. Bu sebeple yapay zekalara iş yaptırırken öncesinde projenizi tanıtmanız ve yapısını çok detaylı şekilde anlatmanız gerekir.

Özellikle sevgili adminim sizin dediğiniz gibi Metin2 eski bir oyun olduğu için normalde yapay zekaya yaptıracağınız işlere göre 3-4 kat daha zordur. Çünkü yapay zeka hep yeniye göre yazmaya çalışıyor ancak sizin sisteminizde (örneğin quest sistemlerinde) eski yapılar çalıştığından çok fazla hataya sebebiyet verir.
 
Martysama 5.8 p23 sürümündeki tasarım desenini kullanabilirsin. Modern standartlara uygun, ayrıca metin2 projesinde multi thread ile işimiz yok thread kullanman sadece performans kaybına neden olur.

C++:
Genişlet Daralt Kopyala
#ifndef __INC_SINGLETON_H__
#define __INC_SINGLETON_H__
#pragma once

#include <cassert>

#if !defined(WIN32) && !defined(__forceinline)
#define __forceinline __attribute__((always_inline))
#endif

template <typename T> class CSingleton
{
    static inline T * ms_singleton = nullptr;

public:
    CSingleton()
    {
        assert(!ms_singleton);
        ms_singleton = static_cast<T*>(this);
    }

    virtual ~CSingleton()
    {
        assert(ms_singleton);
        ms_singleton = nullptr;
    }

    __forceinline static T & Instance()
    {
        assert(ms_singleton);
        return (*ms_singleton);
    }

    __forceinline static T * InstancePtr()
    {
        return (ms_singleton);
    }

    __forceinline static T & instance()
    {
        assert(ms_singleton);
        return (*ms_singleton);
    }

    __forceinline static T * instance_ptr()
    {
        return (ms_singleton);
    }

    // prevent manager 0x0 by deleting copy/assignment operators
    CSingleton(const CSingleton&) = delete;
    CSingleton& operator=(const CSingleton&) = delete;
    CSingleton(CSingleton&&) = delete;
    CSingleton& operator=(CSingleton&&) = delete;
};

template <typename T>
using singleton = CSingleton<T>;

#endif
//martysama0134's 8e0aa8057d3f54320e391131a48866b4
 
Son düzenleme:
bu şekilde düzenledim herhalde yeterli olur;

singleton.h:
Genişlet Daralt Kopyala
#ifndef __INC_SINGLETON_H__
#define __INC_SINGLETON_H__

#include <cassert>
#include <memory>

template <typename T>
class singleton
{
    public:
        static std::unique_ptr<T> ms_singleton;

        singleton()
        {
            assert(!ms_singleton);
            ms_singleton.reset(static_cast<T*>(this));
        }

        virtual ~singleton()
        {
            assert(ms_singleton);
            ms_singleton.reset();
        }

        singleton(const singleton&) = delete;
        singleton& operator=(const singleton&) = delete;

        singleton(singleton&&) = delete;
        singleton& operator=(singleton&&) = delete;

        static T& instance()
        {
            assert(ms_singleton);
            return *ms_singleton;
        }

        static T& Instance()
        {
            return instance();
        }

        static T* instance_ptr()
        {
            return ms_singleton.get();
        }
};

template <typename T> std::unique_ptr<T> singleton<T>::ms_singleton = nullptr;

#endif
 
bu şekilde düzenledim herhalde yeterli olur;

singleton.h:
Genişlet Daralt Kopyala
#ifndef __INC_SINGLETON_H__
#define __INC_SINGLETON_H__

#include <cassert>
#include <memory>

template <typename T>
class singleton
{
    public:
        static std::unique_ptr<T> ms_singleton;

        singleton()
        {
            assert(!ms_singleton);
            ms_singleton.reset(static_cast<T*>(this));
        }

        virtual ~singleton()
        {
            assert(ms_singleton);
            ms_singleton.reset();
        }

        singleton(const singleton&) = delete;
        singleton& operator=(const singleton&) = delete;

        singleton(singleton&&) = delete;
        singleton& operator=(singleton&&) = delete;

        static T& instance()
        {
            assert(ms_singleton);
            return *ms_singleton;
        }

        static T& Instance()
        {
            return instance();
        }

        static T* instance_ptr()
        {
            return ms_singleton.get();
        }
};

template <typename T> std::unique_ptr<T> singleton<T>::ms_singleton = nullptr;

#endif
CHARACTER_MANAGER global instance oluşturuyor hocam. stack'te olan nesneyi unique_ptr ile yönetmemen gerekiyor. double free hatası v.s oluşturur.
 
CHARACTER_MANAGER global instance oluşturuyor hocam. stack'te olan nesneyi unique_ptr ile yönetmemen gerekiyor. double free hatası v.s oluşturur.
galiba öyle çok kurcalamaya gerek yok, bu kadarı yeterli olur mu?

singleton.h:
Genişlet Daralt Kopyala
#ifndef __INC_SINGLETON_H__
#define __INC_SINGLETON_H__

#include <cassert>

template <typename T> class singleton
{
    protected:
        static T* ms_singleton;

    public:
        singleton()
        {
            assert(!ms_singleton);
            ms_singleton = static_cast<T*>(this);
        }

        virtual ~singleton()
        {
            assert(ms_singleton);
            ms_singleton = nullptr;
        }

        static T& instance()
        {
            assert(ms_singleton);
            return *ms_singleton;
        }

        static T& Instance()
        {
            return instance();
        }

        static T* instance_ptr()
        {
            return ms_singleton;
        }

        singleton(const singleton&) = delete;
        singleton& operator=(const singleton&) = delete;

        singleton(singleton&&) = delete;
        singleton& operator=(singleton&&) = delete;
};

template <typename T> T* singleton <T>::ms_singleton = nullptr;

#endif
 
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.
Geri
Üst