pthread функционируют от класса

Вы правы, degree игнорирует веса независимо от ignore.eval. Это видно в самой первой строке degree, где мы имеем

dat <- as.edgelist.sna(dat)

, в то время как as.edgelist.sna имеет параметр attrname:

attrname - если x является сетевой объект, (необязательный) атрибут края, который будет использоваться для получения значений границ.

Так что degree на самом деле даже не пытается использовать какие-либо веса. Чтобы исправить это, мы можем переопределить эту функцию, добавив возможность использовать веса, как в

myDegree <- function (dat, g = 1, nodes = NULL, gmode = "digraph", diag = FALSE, 
          tmaxdev = FALSE, cmode = "freeman", rescale = FALSE, ignore.eval = FALSE, attrname = NULL) 
{
  dat <- as.edgelist.sna(dat, attrname = attrname)
  if (is.list(dat)) 
    return(sapply(dat[g], degree, g = 1, nodes = nodes, gmode = gmode, 
                  diag = diag, tmaxdev = tmaxdev, cmode = cmode, rescale = rescale))
  n <- attr(dat, "n")
  if (gmode == "graph") 
    cmode <- "indegree"
  if (tmaxdev) {
    if (gmode == "digraph") 
      deg <- switch(cmode, indegree = (n - 1) * (n - 1 + 
                                                   diag), outdegree = (n - 1) * (n - 1 + diag), 
                    freeman = (n - 1) * (2 * (n - 1) - 2 + diag))
    else deg <- switch(cmode, indegree = (n - 1) * (n - 2 + 
                                                      diag), outdegree = (n - 1) * (n - 2 + diag), freeman = (n - 
                                                                                                                1) * (2 * (n - 1) - 2 + diag))
  }
  else {
    m <- NROW(dat)
    cm <- switch(cmode, indegree = 0, outdegree = 1, freeman = 2)
    if (!(cmode %in% c("indegree", "outdegree", "freeman"))) 
      stop("Unknown cmode in degree.\n")
    deg <- .C("degree_R", as.double(dat), as.integer(m), 
              as.integer(cm), as.integer(diag), as.integer(ignore.eval), 
              deg = as.double(rep(0, n)), PACKAGE = "sna", NAOK = TRUE)$deg
    if (rescale) 
      deg <- deg/sum(deg)
    if (!is.null(nodes)) 
      deg <- deg[nodes]
  }
  deg
}

Это затем дает

(degree_unweighted <- myDegree(network_statnet, gmode = "graph", ignore.eval = TRUE))
# [1] 2 3 3 1 1
(degree_weighted <- myDegree(network_statnet, gmode = "graph", ignore.eval = FALSE, attrname = "weight"))
# [1] 3 4 4 1 2

Я боюсь, что вам понадобится такая же настройка для других функций, таких как betweenness.

77
задан Willi Mentzel 27 September 2015 в 18:58
поделиться

5 ответов

Вы не можете сделать это так, как написали, потому что функции-члены класса C ++ имеют переданный скрытый параметр this . pthread_create () не знает, какое значение this использовать, поэтому, если вы попытаетесь обойти компилятор, приведя метод к указателю функции соответствующего типа, вы получите ошибку сегметрации. Вы должны использовать статический метод класса (у которого нет параметра this ) или обычную обычную функцию для загрузки класса:

class C
{
public:
    void *hello(void)
    {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }

    static void *hello_helper(void *context)
    {
        return ((C *)context)->hello();
    }
};
...
C c;
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, &c);
142
ответ дан 24 November 2019 в 10:46
поделиться

Это - немного старый вопрос, но очень распространенная проблема, с которой многие сталкиваются. Следующее является простым и изящным способом обработать это при помощи станд.:: поток

#include <iostream>
#include <utility>
#include <thread>
#include <chrono>

class foo
{
    public:
        void bar(int j)
        {
            n = j;
            for (int i = 0; i < 5; ++i) {
                std::cout << "Child thread executing\n";
                ++n;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        }
        int n = 0;
};

int main()
{
    int n = 5;
    foo f;
    std::thread class_thread(&foo::bar, &f, n); // t5 runs foo::bar() on object f
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    std::cout << "Main Thread running as usual";
    class_thread.join();
    std::cout << "Final value of foo::n is " << f.n << '\n';
}

Выше кода также заботится о передающем аргументе функции потока.

Относятся станд.:: поток документ для получения дополнительной информации.

0
ответ дан 24 November 2019 в 10:46
поделиться

Мой любимый способ обработки потока - это инкапсулировать его внутри объекта C ++. Вот пример:

class MyThreadClass
{
public:
   MyThreadClass() {/* empty */}
   virtual ~MyThreadClass() {/* empty */}

   /** Returns true if the thread was successfully started, false if there was an error starting the thread */
   bool StartInternalThread()
   {
      return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
   }

   /** Will not return until the internal thread has exited. */
   void WaitForInternalThreadToExit()
   {
      (void) pthread_join(_thread, NULL);
   }

protected:
   /** Implement this method in your subclass with the code you want your thread to run. */
   virtual void InternalThreadEntry() = 0;

private:
   static void * InternalThreadEntryFunc(void * This) {((MyThreadClass *)This)->InternalThreadEntry(); return NULL;}

   pthread_t _thread;
};

Чтобы использовать его, вы должны просто создать подкласс MyThreadClass с методом InternalThreadEntry (), реализованным, чтобы содержать цикл событий вашего потока. Вам нужно будет вызвать WaitForInternalThreadToExit () для объекта потока перед удалением объекта потока, конечно (и иметь некоторый механизм, чтобы убедиться, что поток действительно завершается, иначе WaitForInternalThreadToExit () никогда не вернется)

79
ответ дан 24 November 2019 в 10:46
поделиться

Вам нужно будет предоставить pthread_create функцию, которая соответствует сигнатуре, которую он ищет. То, что вы передаете, не будет работать.

Вы можете реализовать любую статическую функцию, которая вам нравится, и она может ссылаться на экземпляр c и выполнять то, что вы хотите, в потоке. pthread_create предназначен для приема не только указателя функции, но и указателя на «контекст». В этом случае вы просто передаете ему указатель на экземпляр c .

Например:

static void* execute_print(void* ctx) {
    c* cptr = (c*)ctx;
    cptr->print();
    return NULL;
}


void func() {

    ...

    pthread_create(&t1, NULL, execute_print, &c[0]);

    ...
}
8
ответ дан 24 November 2019 в 10:46
поделиться

Я предполагаю, что это из-за того, что C ++ немного искажает его, потому что вы отправляете ему указатель C ++, а не указатель функции C. Очевидно, есть разница . Попробуйте выполнить

(void)(*p)(void) = ((void) *(void)) &c[0].print; //(check my syntax on that cast)

, а затем отправить p.

Я проделал то же, что и вы, с функцией-членом, но я сделал это в классе, который ее использовал, и с помощью статической функции , что, я думаю, имело значение.

-1
ответ дан 24 November 2019 в 10:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: